[commit: ghc] master: Fix #8698 by properly handling long section names and reenabling .ctors handling (40ce203)
git at git.haskell.org
git at git.haskell.org
Wed Feb 5 03:28:24 UTC 2014
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/40ce20357fb6266471a53cec7de0a810a3070f36/ghc
>---------------------------------------------------------------
commit 40ce20357fb6266471a53cec7de0a810a3070f36
Author: Edward Z. Yang <ezyang at cs.stanford.edu>
Date: Tue Feb 4 15:59:55 2014 -0800
Fix #8698 by properly handling long section names and reenabling .ctors handling
Our old function for searching for sections could only deal
with section names that were eight bytes or shorter; this
patch adds support for long section names.
Signed-off-by: Edward Z. Yang <ezyang at cs.stanford.edu>
>---------------------------------------------------------------
40ce20357fb6266471a53cec7de0a810a3070f36
rts/Linker.c | 59 +++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 36 insertions(+), 23 deletions(-)
diff --git a/rts/Linker.c b/rts/Linker.c
index b9c8fd0..8f57873 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) */
More information about the ghc-commits
mailing list