coff: Handle massive relocations

The backport of

4db724fdd7
359b63f897
01102ee8e6
2672af7379

so coff output target to be able to handle
massive relocations.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
This commit is contained in:
Cyrill Gorcunov 2010-11-20 14:18:23 +03:00
parent 3cb0e8c052
commit cb9a459560
2 changed files with 44 additions and 3 deletions

View file

@ -837,6 +837,25 @@ static int coff_directives(enum directives directive, char *value, int pass)
}
}
/* handle relocations storm, valid for win32/64 only */
static inline void coff_adjust_relocs(struct Section *s)
{
if (s->nrelocs < IMAGE_SCN_MAX_RELOC)
return;
#ifdef OF_COFF
else
{
if (ofmt == &of_coff)
nasm_error(ERR_FATAL,
"Too many relocations (%d) for section `%s'",
s->nrelocs, s->name);
}
#endif
s->flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
s->nrelocs++;
}
static void coff_write(void)
{
int32_t pos, sympos, vsize;
@ -860,13 +879,15 @@ static void coff_write(void)
}
/*
* Work out how big the file will get. Calculate the start of
* the `real' symbols at the same time.
* Work out how big the file will get.
* Calculate the start of the `real' symbols at the same time.
* Check for massive relocations.
*/
pos = 0x14 + 0x28 * nsects;
initsym = 3; /* two for the file, one absolute */
for (i = 0; i < nsects; i++) {
if (sects[i]->data) {
coff_adjust_relocs(sects[i]);
sects[i]->pos = pos;
pos += sects[i]->len;
sects[i]->relpos = pos;
@ -939,7 +960,18 @@ static void coff_section_header(char *name, int32_t vsize,
fwriteint32_t(datapos, ofile);
fwriteint32_t(relpos, ofile);
fwriteint32_t(0L, ofile); /* no line numbers - we don't do 'em */
fwriteint16_t(nrelocs, ofile);
/*
* a special case -- if there are too many relocs
* we have to put IMAGE_SCN_MAX_RELOC here and write
* the real relocs number into VirtualAddress of first
* relocation
*/
if (flags & IMAGE_SCN_LNK_NRELOC_OVFL)
fwriteint16_t(IMAGE_SCN_MAX_RELOC, ofile);
else
fwriteint16_t(nrelocs, ofile);
fwriteint16_t(0, ofile); /* again, no line numbers */
fwriteint32_t(flags, ofile);
}
@ -948,6 +980,13 @@ static void coff_write_relocs(struct Section *s)
{
struct Reloc *r;
/* a real number of relocations if needed */
if (s->flags & IMAGE_SCN_LNK_NRELOC_OVFL) {
fwriteint32_t(s->nrelocs, ofile);
fwriteint32_t(0, ofile);
fwriteint16_t(0, ofile);
}
for (r = s->head; r; r = r->next) {
fwriteint32_t(r->address, ofile);
fwriteint32_t(r->symbol + (r->symbase == REAL_SYMBOLS ? initsym :

View file

@ -137,6 +137,8 @@
#define IMAGE_SCN_LNK_REMOVE 0x00000800
#define IMAGE_SCN_LNK_COMDAT 0x00001000
#define IMAGE_SCN_MAX_RELOC 0xffff
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000