summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
7bf9669)
PEi386/COFF: handle relocation overflows, i.e., if a section is
marked with the flag (MY)IMAGE_SCN_LNK_NRELOC_OVFL, then
the first entry in the relocation table holds the 32-bit
relocation count rather than 16-bit number in the section header.
Apparently, a version of the MS PE spec exists that spells this
out, but haven't been able to locate it (perhaps people on the
'inside' could try to locate an up-to-date version...?) winnt.h
is clear enough about it though (as is the GNU libbfd sources).
This is the Right Way to compute the relocation count, but
unfortunately libbfd / GNU ld is generating bogus output
when the reloc field overflows (causing objdump/nm etc. to
crash when trying to read the generated output!) Looking into it.
Once this has been cleared up/fixed, the splitting up of HSstd.o
(and HSwin32.o) should be a thing of the past. I've taken the
liberty of disabling the suspiciously-large-reloc-section test
already.
/* -----------------------------------------------------------------------------
/* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.78 2002/01/23 11:29:12 sewardj Exp $
+ * $Id: Linker.c,v 1.79 2002/01/29 02:41:21 sof Exp $
*
* (c) The GHC Team, 2000, 2001
*
*
* (c) The GHC Team, 2000, 2001
*
/* From PE spec doc, section 4.1 */
#define MYIMAGE_SCN_CNT_CODE 0x00000020
#define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
/* From PE spec doc, section 4.1 */
#define MYIMAGE_SCN_CNT_CODE 0x00000020
#define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define MYIMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
/* From PE spec doc, section 5.2.1 */
#define MYIMAGE_REL_I386_DIR32 0x0006
/* From PE spec doc, section 5.2.1 */
#define MYIMAGE_REL_I386_DIR32 0x0006
static int
ocVerifyImage_PEi386 ( ObjectCode* oc )
{
static int
ocVerifyImage_PEi386 ( ObjectCode* oc )
{
+ int i;
+ UInt32 j, noRelocs;
COFF_header* hdr;
COFF_section* sectab;
COFF_symbol* symtab;
COFF_header* hdr;
COFF_section* sectab;
COFF_symbol* symtab;
there are more than 64k relocations, despite claims to the
contrary. Hence this test. */
/* fprintf(stderr, "strtab size %d\n", * (UInt32*)strtab); */
there are more than 64k relocations, despite claims to the
contrary. Hence this test. */
/* fprintf(stderr, "strtab size %d\n", * (UInt32*)strtab); */
- if (* (UInt32*)strtab > 600000) {
+#if 0
+ if ( (*(UInt32*)strtab) > 600000 ) {
/* Note that 600k has no special significance other than being
big enough to handle the almost-2MB-sized lumps that
constitute HSwin32*.o. */
belch("PEi386 object has suspiciously large string table; > 64k relocs?");
return 0;
}
/* Note that 600k has no special significance other than being
big enough to handle the almost-2MB-sized lumps that
constitute HSwin32*.o. */
belch("PEi386 object has suspiciously large string table; > 64k relocs?");
return 0;
}
/* No further verification after this point; only debug printing. */
i = 0;
/* No further verification after this point; only debug printing. */
i = 0;
reltab = (COFF_reloc*) (
((UChar*)(oc->image)) + sectab_i->PointerToRelocations
);
reltab = (COFF_reloc*) (
((UChar*)(oc->image)) + sectab_i->PointerToRelocations
);
+
+ if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
+ /* If the relocation field (a short) has overflowed, the
+ * real count can be found in the first reloc entry.
+ * The PE spec (Rev 6.0) doesn't really cover this,
+ * but as always header files provide the final word on
+ * details like this (cf. WinNT.h).
+ */
+ COFF_reloc* rel = (COFF_reloc*)
+ myindex ( sizeof_COFF_reloc, reltab, 0 );
+ noRelocs = rel->VirtualAddress;
+ j = 1;
+ } else {
+ noRelocs = sectab_i->NumberOfRelocations;
+ j = 0;
+ }
- for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
+ for (; j < noRelocs; j++) {
COFF_symbol* sym;
COFF_reloc* rel = (COFF_reloc*)
myindex ( sizeof_COFF_reloc, reltab, j );
COFF_symbol* sym;
COFF_reloc* rel = (COFF_reloc*)
myindex ( sizeof_COFF_reloc, reltab, j );
rel->VirtualAddress );
sym = (COFF_symbol*)
myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
rel->VirtualAddress );
sym = (COFF_symbol*)
myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
+ /* Hmm..mysterious looking offset - what's it for? SOF */
printName ( sym->Name, strtab -10 );
fprintf ( stderr, "'\n" );
}
printName ( sym->Name, strtab -10 );
fprintf ( stderr, "'\n" );
}
/* fprintf(stderr, "BSS section at 0x%x\n", addr); */
}
/* fprintf(stderr, "BSS section at 0x%x\n", addr); */
}
sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab );
sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab );
- /* fprintf(stderr,"addSymbol %p `%s'\n", addr,sname); */
+ /* fprintf(stderr,"addSymbol %p `%s \n", addr,sname); */
IF_DEBUG(linker, belch("addSymbol %p `%s'\n", addr,sname);)
ASSERT(i >= 0 && i < oc->n_symbols);
/* cstring_from_COFF_symbol_name always succeeds. */
IF_DEBUG(linker, belch("addSymbol %p `%s'\n", addr,sname);)
ASSERT(i >= 0 && i < oc->n_symbols);
/* cstring_from_COFF_symbol_name always succeeds. */
+ int i;
+ UInt32 j, noRelocs;
/* ToDo: should be variable-sized? But is at least safe in the
sense of buffer-overrun-proof. */
/* ToDo: should be variable-sized? But is at least safe in the
sense of buffer-overrun-proof. */
|| 0 == strcmp(".stabstr", sectab_i->Name))
continue;
|| 0 == strcmp(".stabstr", sectab_i->Name))
continue;
- for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
+ if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
+ /* If the relocation field (a short) has overflowed, the
+ * real count can be found in the first reloc entry.
+ * The PE spec (Feb 99 version) doesn't really cover this,
+ * but as always header files provide the final word on
+ * details like this (cf. WinNT.h).
+ */
+ COFF_reloc* rel = (COFF_reloc*)
+ myindex ( sizeof_COFF_reloc, reltab, 0 );
+ noRelocs = rel->VirtualAddress;
+ fprintf(stderr, "Overflown relocs: %u\n", noRelocs);
+ j = 1;
+ } else {
+ noRelocs = sectab_i->NumberOfRelocations;
+ j = 0;
+ }
+
+
+ for (; j < noRelocs; j++) {
COFF_symbol* sym;
COFF_reloc* reltab_j
= (COFF_reloc*)
COFF_symbol* sym;
COFF_reloc* reltab_j
= (COFF_reloc*)