diff options
-rw-r--r-- | rts/Linker.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index b9c8fd001a..8f57873ad0 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -211,9 +211,7 @@ static int ocAllocateSymbolExtras_ELF ( ObjectCode* oc ); static int ocVerifyImage_PEi386 ( ObjectCode* oc ); static int ocGetNames_PEi386 ( ObjectCode* oc ); static int ocResolve_PEi386 ( ObjectCode* oc ); -#if !defined(x86_64_HOST_ARCH) static int ocRunInit_PEi386 ( ObjectCode* oc ); -#endif static void *lookupSymbolInDLLs ( unsigned char *lbl ); static void zapTrailingAtSign ( unsigned char *sym ); static char *allocateImageAndTrampolines ( @@ -2875,10 +2873,7 @@ resolveObjs( void ) #if defined(OBJFORMAT_ELF) r = ocRunInit_ELF ( oc ); #elif defined(OBJFORMAT_PEi386) -#if !defined(x86_64_HOST_ARCH) - /* It does not work on x86_64 yet. #8698. */ r = ocRunInit_PEi386 ( oc ); -#endif #elif defined(OBJFORMAT_MACHO) r = ocRunInit_MachO ( oc ); #else @@ -3608,9 +3603,10 @@ cstring_from_section_name (UChar* name, UChar* strtab) /* Just compares the short names (first 8 chars) */ static COFF_section * -findPEi386SectionCalled ( ObjectCode* oc, UChar* name ) +findPEi386SectionCalled ( ObjectCode* oc, UChar* name, UChar* strtab ) { int i; + rtsBool long_name = rtsFalse; COFF_header* hdr = (COFF_header*)(oc->image); COFF_section* sectab @@ -3618,6 +3614,14 @@ findPEi386SectionCalled ( ObjectCode* oc, UChar* name ) ((UChar*)(oc->image)) + sizeof_COFF_header + hdr->SizeOfOptionalHeader ); + // String is longer than 8 bytes, swap in the proper + // (NULL-terminated) version, and make a note that this + // is a long name. + if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) { + UInt32 strtab_offset = * (UInt32*)(name+4); + name = ((UChar*)strtab) + strtab_offset; + long_name = rtsTrue; + } for (i = 0; i < hdr->NumberOfSections; i++) { UChar* n1; UChar* n2; @@ -3626,10 +3630,28 @@ findPEi386SectionCalled ( ObjectCode* oc, UChar* name ) myindex ( sizeof_COFF_section, sectab, i ); n1 = (UChar*) &(section_i->Name); n2 = name; - if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] && - n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] && - n1[6]==n2[6] && n1[7]==n2[7]) - return section_i; + // Long section names are prefixed with a slash, see + // also cstring_from_section_name + if (n1[0] == '/' && long_name) { + // Long name check + // We don't really want to make an assumption that the string + // table indexes are the same, so we'll do a proper check. + int n1_strtab_offset = strtol((char*)n1+1,NULL,10); + n1 = (UChar*) (((char*)strtab) + n1_strtab_offset); + if (0==strcmp((const char*)n1, (const char*)n2)) { + return section_i; + } + } else if (n1[0] != '/' && !long_name) { + // Short name check + if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] && + n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] && + n1[6]==n2[6] && n1[7]==n2[7]) { + return section_i; + } + } else { + // guaranteed to mismatch, because we never attempt to link + // in an executable where the section name may be truncated + } } return NULL; @@ -4235,14 +4257,6 @@ ocResolve_PEi386 ( ObjectCode* oc ) continue; } -#if defined(x86_64_HOST_ARCH) - /* It does not work on x86_64 yet. #8698. */ - if (0 == strcmp(".ctors", (char*)secname)) { - stgFree(secname); - continue; - } -#endif - stgFree(secname); if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) { @@ -4304,9 +4318,11 @@ ocResolve_PEi386 ( ObjectCode* oc ) if (sym->StorageClass == MYIMAGE_SYM_CLASS_STATIC) { COFF_section* section_sym - = findPEi386SectionCalled ( oc, sym->Name ); + = findPEi386SectionCalled ( oc, sym->Name, strtab ); if (!section_sym) { - errorBelch("%" PATH_FMT ": can't find section `%s' in %s", oc->fileName, sym->Name, secname); + errorBelch("%" PATH_FMT ": can't find section named: ", oc->fileName); + printName(sym->Name, strtab); + errorBelch(" in %s", secname); return 0; } S = ((size_t)(oc->image)) @@ -4414,8 +4430,6 @@ ocResolve_PEi386 ( ObjectCode* oc ) return 1; } -/* It does not work on x86_64 yet. #8698. */ -#if !defined(x86_64_HOST_ARCH) static int ocRunInit_PEi386 ( ObjectCode *oc ) { @@ -4458,7 +4472,6 @@ ocRunInit_PEi386 ( ObjectCode *oc ) freeProgEnvv(envc, envv); return 1; } -#endif #endif /* defined(OBJFORMAT_PEi386) */ |