X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FLinker.c;h=1f958cb96b247da173317b423c3f1e995f550b69;hb=ad75daecbeadf59809c4309d8ee35282513d3e59;hp=13ba8351e1951106cdecdf038ae06e353567dde5;hpb=265be40ffb10e9c1713479bb2b89a4bfa699c3a6;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 13ba835..1f958cb 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -1,12 +1,13 @@ /* ----------------------------------------------------------------------------- - * $Id: Linker.c,v 1.45 2001/06/25 09:44:10 rrt Exp $ + * $Id: Linker.c,v 1.62 2001/08/31 14:32:03 sewardj Exp $ * - * (c) The GHC Team, 2000 + * (c) The GHC Team, 2000, 2001 * * RTS Object Linker * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" #include "RtsFlags.h" #include "HsFFI.h" @@ -80,7 +81,30 @@ typedef struct _RtsSymbolVal { #else #define RTS_POSIX_ONLY_SYMBOLS + +/* These are statically linked from the mingw libraries into the ghc + executable, so we have to employ this hack. */ #define RTS_MINGW_ONLY_SYMBOLS \ + SymX(memset) \ + SymX(inet_ntoa) \ + SymX(inet_addr) \ + SymX(htonl) \ + SymX(recvfrom) \ + SymX(listen) \ + SymX(bind) \ + SymX(shutdown) \ + SymX(connect) \ + SymX(htons) \ + SymX(ntohs) \ + SymX(getservbyname) \ + SymX(getservbyport) \ + SymX(getprotobynumber) \ + SymX(getprotobyname) \ + SymX(gethostbyname) \ + SymX(gethostbyaddr) \ + SymX(gethostname) \ + SymX(strcpy) \ + SymX(strncpy) \ SymX(abort) \ Sym(_alloca) \ Sym(isxdigit) \ @@ -93,23 +117,10 @@ typedef struct _RtsSymbolVal { Sym(iscntrl) \ Sym(isalpha) \ Sym(isalnum) \ - SymX(memset) \ - SymX(strncpy) \ - SymX(strcpy) \ SymX(strcmp) \ - SymX(strerror) \ - Sym(mktime) \ - Sym(gmtime) \ - Sym(strftime) \ - Sym(localtime) \ - SymX(getenv) \ - SymX(rename) \ - Sym(opendir) \ - Sym(readdir) \ - Sym(closedir) \ - Sym(PrelHandle_stderr_closure) \ - Sym(Main_main_closure) \ - Sym(__init_Main) \ + SymX(memmove) \ + SymX(realloc) \ + SymX(malloc) \ SymX(pow) \ SymX(tanh) \ SymX(cosh) \ @@ -123,46 +134,29 @@ typedef struct _RtsSymbolVal { SymX(exp) \ SymX(log) \ SymX(sqrt) \ - SymX(Sleep) \ - SymX(system) \ - SymX(memchr) \ SymX(memcpy) \ - SymX(memmove) \ - SymX(fprintf) \ - Sym(_imp___iob) \ - Sym(_imp___tzname) \ + Sym(mktime) \ Sym(_imp___timezone) \ - Sym(__udivdi3) \ - SymX(GetProcessTimes) \ - SymX(GetCurrentProcess) \ - SymX(read) \ - SymX(write) \ - SymX(open) \ - SymX(close) \ - SymX(send) \ - SymX(recv) \ - SymX(malloc) \ + Sym(_imp___tzname) \ + Sym(localtime) \ + Sym(gmtime) \ + SymX(getenv) \ SymX(free) \ - SymX(realloc) \ - SymX(fstat) \ - SymX(stat) \ - Sym(ftime) \ - SymX(isatty) \ - SymX(lseek) \ - SymX(access) \ - Sym(setmode) \ - SymX(chmod) \ - SymX(chdir) \ - SymX(getcwd) \ - SymX(unlink) \ - SymX(rmdir) \ - SymX(mkdir) \ - SymX(CreateProcessA) \ - SymX(WaitForSingleObject) \ - SymX(GetExitCodeProcess) \ + SymX(rename) \ + Sym(opendir) \ + Sym(readdir) \ + Sym(closedir) \ + SymX(GetCurrentProcess) \ + SymX(GetProcessTimes) \ SymX(CloseHandle) \ - SymX(_errno) \ - SymX(closesocket) + SymX(GetExitCodeProcess) \ + SymX(WaitForSingleObject) \ + SymX(CreateProcessA) \ + Sym(__divdi3) \ + Sym(__udivdi3) \ + Sym(__moddi3) \ + Sym(__umoddi3) \ + SymX(_errno) #endif @@ -244,6 +238,7 @@ typedef struct _RtsSymbolVal { SymX(newArrayzh_fast) \ SymX(unsafeThawArrayzh_fast) \ SymX(newByteArrayzh_fast) \ + SymX(newPinnedByteArrayzh_fast) \ SymX(newMutVarzh_fast) \ SymX(quotRemIntegerzh_fast) \ SymX(quotIntegerzh_fast) \ @@ -279,6 +274,8 @@ typedef struct _RtsSymbolVal { SymX(__gmpz_get_ui) \ SymX(prog_argv) \ SymX(prog_argc) \ + SymX(getProgArgv) \ + SymX(setProgArgv) \ SymX(resetNonBlockingFd) \ SymX(performGC) \ SymX(getStablePtr) \ @@ -342,41 +339,6 @@ typedef struct _RtsSymbolVal { #define RTS_LONG_LONG_SYMS /* nothing */ #else #define RTS_LONG_LONG_SYMS \ - SymX(stg_gtWord64) \ - SymX(stg_geWord64) \ - SymX(stg_eqWord64) \ - SymX(stg_neWord64) \ - SymX(stg_ltWord64) \ - SymX(stg_leWord64) \ - SymX(stg_gtInt64) \ - SymX(stg_geInt64) \ - SymX(stg_eqInt64) \ - SymX(stg_neInt64) \ - SymX(stg_ltInt64) \ - SymX(stg_leInt64) \ - SymX(stg_remWord64) \ - SymX(stg_quotWord64) \ - SymX(stg_remInt64) \ - SymX(stg_quotInt64) \ - SymX(stg_negateInt64) \ - SymX(stg_plusInt64) \ - SymX(stg_minusInt64) \ - SymX(stg_timesInt64) \ - SymX(stg_and64) \ - SymX(stg_or64) \ - SymX(stg_xor64) \ - SymX(stg_not64) \ - SymX(stg_shiftL64) \ - SymX(stg_shiftRL64) \ - SymX(stg_iShiftL64) \ - SymX(stg_iShiftRL64) \ - SymX(stg_iShiftRA64) \ - SymX(stg_intToInt64) \ - SymX(stg_int64ToInt) \ - SymX(stg_int64ToWord64) \ - SymX(stg_wordToWord64) \ - SymX(stg_word64ToWord) \ - SymX(stg_word64ToInt64) \ SymX(int64ToIntegerzh_fast) \ SymX(word64ToIntegerzh_fast) #endif /* SUPPORT_LONG_LONGS */ @@ -449,6 +411,7 @@ initLinker( void ) typedef struct _OpenedDLL { + char* name; struct _OpenedDLL* next; HINSTANCE instance; } @@ -461,7 +424,7 @@ static OpenedDLL* opened_dlls = NULL; char* -addDLL ( char* path, char* dll_name ) +addDLL ( __attribute((unused)) char* path, char* dll_name ) { # if defined(OBJFORMAT_ELF) void *hdl; @@ -485,33 +448,25 @@ addDLL ( char* path, char* dll_name ) } else { return NULL; } - ASSERT(0); /*NOTREACHED*/ + /*NOTREACHED*/ + # elif defined(OBJFORMAT_PEi386) /* Add this DLL to the list of DLLs in which to search for symbols. - The first time through, also add the executable to the list, - since we need to search that too. The path argument is ignored. */ + The path argument is ignored. */ char* buf; OpenedDLL* o_dll; HINSTANCE instance; - /* fprintf(stderr, "addDLL %s\n", dll_name ); */ - -#if 0 - /* Later ... can't figure out why this doesn't work. So retain the - RTS_MINGW_ONLY_SYMBOLS hack for the time being. */ - if (opened_dlls == NULL) { - /* First time through ... */ - instance = GetModuleHandle(NULL); - if (instance == NULL) - return "addDLL: can't get handle to the executable"; - o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL-init" ); - o_dll->instance = instance; - o_dll->next = opened_dlls; - opened_dlls = o_dll; + + /* fprintf(stderr, "\naddDLL; path=`%s', dll_name = `%s'\n", path, dll_name); */ + + /* See if we've already got it, and ignore if so. */ + for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) { + if (0 == strcmp(o_dll->name, dll_name)) + return NULL; } -#endif - buf = stgMallocBytes(strlen(dll_name) + 10, "addDll"); + buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL"); sprintf(buf, "%s.DLL", dll_name); instance = LoadLibrary(buf); free(buf); @@ -521,6 +476,8 @@ addDLL ( char* path, char* dll_name ) } o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" ); + o_dll->name = stgMallocBytes(1+strlen(dll_name), "addDLL"); + strcpy(o_dll->name, dll_name); o_dll->instance = instance; o_dll->next = opened_dlls; opened_dlls = o_dll; @@ -548,10 +505,23 @@ lookupSymbol( char *lbl ) OpenedDLL* o_dll; void* sym; for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) { + /* fprintf(stderr, "look in %s for %s\n", o_dll->name, lbl); */ + if (lbl[0] == '_') { + /* HACK: if the name has an initial underscore, try stripping + it off & look that up first. I've yet to verify whether there's + a Rule that governs whether an initial '_' *should always* be + stripped off when mapping from import lib name to the DLL name. + */ + sym = GetProcAddress(o_dll->instance, (lbl+1)); + if (sym != NULL) return sym; + } sym = GetProcAddress(o_dll->instance, lbl); if (sym != NULL) return sym; } return NULL; +# else + ASSERT(2+2 == 5); + return NULL; # endif } else { return val; @@ -619,6 +589,7 @@ loadObj( char *path ) oc->symbols = NULL; oc->sections = NULL; oc->lochash = allocStrHashTable(); + oc->proddables = NULL; /* chain it onto the list of objects */ oc->next = objects; @@ -739,6 +710,39 @@ unloadObj( char *path ) return 0; } +/* ----------------------------------------------------------------------------- + * Sanity checking. For each ObjectCode, maintain a list of address ranges + * which may be prodded during relocation, and abort if we try and write + * outside any of these. + */ +static void addProddableBlock ( ObjectCode* oc, void* start, int size ) +{ + ProddableBlock* pb + = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock"); + /* fprintf(stderr, "aPB %p %p %d\n", oc, start, size); */ + ASSERT(size > 0); + pb->start = start; + pb->size = size; + pb->next = oc->proddables; + oc->proddables = pb; +} + +static void checkProddableBlock ( ObjectCode* oc, void* addr ) +{ + ProddableBlock* pb; + for (pb = oc->proddables; pb != NULL; pb = pb->next) { + char* s = (char*)(pb->start); + char* e = s + pb->size - 1; + char* a = (char*)addr; + /* Assumes that the biggest fixup involves a 4-byte write. This + probably needs to be changed to 8 (ie, +7) on 64-bit + plats. */ + if (a >= s && (a+3) <= e) return; + } + barf("checkProddableBlock: invalid fixup in runtime linker"); +} + + /* -------------------------------------------------------------------------- * PEi386 specifics (Win32 targets) * ------------------------------------------------------------------------*/ @@ -977,7 +981,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc ) COFF_section* sectab; COFF_symbol* symtab; UChar* strtab; - fprintf(stderr, "\nLOADING %s\n", oc->fileName); + /* fprintf(stderr, "\nLOADING %s\n", oc->fileName); */ hdr = (COFF_header*)(oc->image); sectab = (COFF_section*) ( ((UChar*)(oc->image)) @@ -1066,13 +1070,15 @@ ocVerifyImage_PEi386 ( ObjectCode* oc ) " data sz %d\n" " data off %d\n" " num rel %d\n" - " off rel %d\n", + " off rel %d\n" + " ptr raw 0x%x\n", sectab_i->VirtualSize, sectab_i->VirtualAddress, sectab_i->SizeOfRawData, sectab_i->PointerToRawData, sectab_i->NumberOfRelocations, - sectab_i->PointerToRelocations + sectab_i->PointerToRelocations, + sectab_i->PointerToRawData ); reltab = (COFF_reloc*) ( ((UChar*)(oc->image)) + sectab_i->PointerToRelocations @@ -1091,9 +1097,9 @@ ocVerifyImage_PEi386 ( ObjectCode* oc ) printName ( sym->Name, strtab -10 ); fprintf ( stderr, "'\n" ); } + fprintf ( stderr, "\n" ); } - fprintf ( stderr, "\n" ); fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab ); fprintf ( stderr, "---START of string table---\n"); @@ -1120,12 +1126,12 @@ ocVerifyImage_PEi386 ( ObjectCode* oc ) fprintf ( stderr, "'\n" " value 0x%x\n" - " sec# %d\n" + " 1+sec# %d\n" " type 0x%x\n" " sclass 0x%x\n" " nAux %d\n", symtab_i->Value, - (Int32)(symtab_i->SectionNumber) - 1, + (Int32)(symtab_i->SectionNumber), (UInt32)symtab_i->Type, (UInt32)symtab_i->StorageClass, (UInt32)symtab_i->NumberOfAuxSymbols @@ -1164,6 +1170,25 @@ ocGetNames_PEi386 ( ObjectCode* oc ) + hdr->PointerToSymbolTable + hdr->NumberOfSymbols * sizeof_COFF_symbol; + /* Allocate space for any (local, anonymous) .bss sections. */ + + for (i = 0; i < hdr->NumberOfSections; i++) { + UChar* zspace; + COFF_section* sectab_i + = (COFF_section*) + myindex ( sizeof_COFF_section, sectab, i ); + if (0 != strcmp(sectab_i->Name, ".bss")) continue; + if (sectab_i->VirtualSize == 0) continue; + /* This is a non-empty .bss section. Allocate zeroed space for + it, and set its PointerToRawData field such that oc->image + + PointerToRawData == addr_of_zeroed_space. */ + zspace = stgCallocBytes(1, sectab_i->VirtualSize, + "ocGetNames_PEi386(anonymous bss)"); + sectab_i->PointerToRawData = ((UChar*)zspace) - ((UChar*)(oc->image)); + addProddableBlock(oc, zspace, sectab_i->VirtualSize); + /* fprintf(stderr, "BSS section at 0x%x\n", zspace); */ + } + /* Copy exported symbols into the ObjectCode. */ oc->n_symbols = hdr->NumberOfSymbols; @@ -1180,33 +1205,66 @@ ocGetNames_PEi386 ( ObjectCode* oc ) symtab_i = (COFF_symbol*) myindex ( sizeof_COFF_symbol, symtab, i ); - if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL && - symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) { + addr = NULL; + if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL + && symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) { /* This symbol is global and defined, viz, exported */ - COFF_section* sectabent; - - /* cstring_from_COFF_symbol_name always succeeds. */ - sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab ); - /* for MYIMAGE_SYMCLASS_EXTERNAL && !MYIMAGE_SYM_UNDEFINED, the address of the symbol is: address of relevant section + offset in section */ - sectabent = (COFF_section*) - myindex ( sizeof_COFF_section, - sectab, - symtab_i->SectionNumber-1 ); + COFF_section* sectabent + = (COFF_section*) myindex ( sizeof_COFF_section, + sectab, + symtab_i->SectionNumber-1 ); addr = ((UChar*)(oc->image)) + (sectabent->PointerToRawData + symtab_i->Value); + } + else + if (symtab_i->SectionNumber == MYIMAGE_SYM_UNDEFINED + && symtab_i->Value > 0) { + /* This symbol isn't in any section at all, ie, global bss. + Allocate zeroed space for it. */ + addr = stgCallocBytes(1, symtab_i->Value, + "ocGetNames_PEi386(non-anonymous bss)"); + addProddableBlock(oc, addr, symtab_i->Value); + } + + if (addr != NULL) { + sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab ); /* 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. */ oc->symbols[i] = sname; insertStrHashTable(symhash, sname, addr); + } else { +# if 0 + fprintf ( stderr, + "IGNORING symbol %d\n" + " name `", + i + ); + printName ( symtab_i->Name, strtab ); + fprintf ( stderr, + "'\n" + " value 0x%x\n" + " 1+sec# %d\n" + " type 0x%x\n" + " sclass 0x%x\n" + " nAux %d\n", + symtab_i->Value, + (Int32)(symtab_i->SectionNumber), + (UInt32)symtab_i->Type, + (UInt32)symtab_i->StorageClass, + (UInt32)symtab_i->NumberOfAuxSymbols + ); +# endif } + i += symtab_i->NumberOfAuxSymbols; i++; } @@ -1228,7 +1286,7 @@ ocGetNames_PEi386 ( ObjectCode* oc ) myindex ( sizeof_COFF_section, sectab, i ); IF_DEBUG(linker, belch("section name = %s\n", sectab_i->Name )); -#if 0 +# if 0 /* I'm sure this is the Right Way to do it. However, the alternative of testing the sectab_i->Name field seems to work ok with Cygwin. @@ -1236,9 +1294,10 @@ ocGetNames_PEi386 ( ObjectCode* oc ) if (sectab_i->Characteristics & MYIMAGE_SCN_CNT_CODE || sectab_i->Characteristics & MYIMAGE_SCN_CNT_INITIALIZED_DATA) kind = SECTIONKIND_CODE_OR_RODATA; -#endif +# endif - if (0==strcmp(".text",sectab_i->Name)) + if (0==strcmp(".text",sectab_i->Name) || + 0==strcmp(".rodata",sectab_i->Name)) kind = SECTIONKIND_CODE_OR_RODATA; if (0==strcmp(".data",sectab_i->Name) || 0==strcmp(".bss",sectab_i->Name)) @@ -1254,9 +1313,12 @@ ocGetNames_PEi386 ( ObjectCode* oc ) return 0; } - oc->sections[i].start = start; - oc->sections[i].end = end; - oc->sections[i].kind = kind; + if (end >= start) { + oc->sections[i].start = start; + oc->sections[i].end = end; + oc->sections[i].kind = kind; + addProddableBlock(oc, start, end - start + 1); + } } return 1; @@ -1336,8 +1398,7 @@ ocResolve_PEi386 ( ObjectCode* oc ) COFF_section* section_sym = findPEi386SectionCalled ( oc, sym->Name ); if (!section_sym) { - fprintf ( stderr, "bad section = `%s'\n", sym->Name ); - barf("Can't find abovementioned PEi386 section"); + belch("%s: can't find section `%s'", oc->fileName, sym->Name); return 0; } S = ((UInt32)(oc->image)) @@ -1350,12 +1411,11 @@ ocResolve_PEi386 ( ObjectCode* oc ) if ((void*)S == NULL) (void*)S = lookupSymbol( symbol ); if (S == 0) { - belch("ocResolve_PEi386: %s: unknown symbol `%s'", - oc->fileName, symbol); + belch("%s: unknown symbol `%s'", oc->fileName, symbol); return 0; } } - + checkProddableBlock(oc, pP); switch (reltab_j->Type) { case MYIMAGE_REL_I386_DIR32: *pP = A + S; @@ -1376,17 +1436,15 @@ ocResolve_PEi386 ( ObjectCode* oc ) *pP = S - ((UInt32)pP) - 4; break; default: - fprintf(stderr, - "unhandled PEi386 relocation type %d\n", - reltab_j->Type); - barf("unhandled PEi386 relocation type"); + belch("%s: unhandled PEi386 relocation type %d", + oc->fileName, reltab_j->Type); return 0; } } } - /* fprintf(stderr, "completed %s\n", oc->fileName); */ + IF_DEBUG(linker, belch("completed %s", oc->fileName)); return 1; } @@ -1404,7 +1462,12 @@ ocResolve_PEi386 ( ObjectCode* oc ) #if defined(sparc_TARGET_ARCH) # define ELF_TARGET_SPARC /* Used inside */ +#elif defined(i386_TARGET_ARCH) +# define ELF_TARGET_386 /* Used inside */ #endif +/* There is a similar case for IA64 in the Solaris2 headers if this + * ever becomes relevant. + */ #include @@ -1443,13 +1506,13 @@ ocVerifyImage_ELF ( ObjectCode* oc ) ehdr->e_ident[EI_MAG1] != ELFMAG1 || ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) { - belch("ocVerifyImage_ELF: not an ELF header"); + belch("%s: not an ELF header", oc->fileName); return 0; } IF_DEBUG(linker,belch( "Is an ELF header" )); if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) { - belch("ocVerifyImage_ELF: not 32 bit ELF" ); + belch("%s: not 32 bit ELF", oc->fileName); return 0; } @@ -1461,12 +1524,12 @@ ocVerifyImage_ELF ( ObjectCode* oc ) if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { IF_DEBUG(linker,belch( "Is big-endian" )); } else { - belch("ocVerifyImage_ELF: unknown endiannness"); + belch("%s: unknown endiannness", oc->fileName); return 0; } if (ehdr->e_type != ET_REL) { - belch("ocVerifyImage_ELF: not a relocatable object (.o) file"); + belch("%s: not a relocatable object (.o) file", oc->fileName); return 0; } IF_DEBUG(linker, belch( "Is a relocatable object (.o) file" )); @@ -1476,7 +1539,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) case EM_386: IF_DEBUG(linker,belch( "x86" )); break; case EM_SPARC: IF_DEBUG(linker,belch( "sparc" )); break; default: IF_DEBUG(linker,belch( "unknown" )); - belch("ocVerifyImage_ELF: unknown architecture"); + belch("%s: unknown architecture", oc->fileName); return 0; } @@ -1489,7 +1552,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff); if (ehdr->e_shstrndx == SHN_UNDEF) { - belch("ocVerifyImage_ELF: no section header string table"); + belch("%s: no section header string table", oc->fileName); return 0; } else { IF_DEBUG(linker,belch( "Section header string table is section %d", @@ -1530,7 +1593,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) } } if (nstrtab != 1) { - belch("ocVerifyImage_ELF: no string tables, or too many"); + belch("%s: no string tables, or too many", oc->fileName); return 0; } @@ -1547,7 +1610,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) shdr[i].sh_size % sizeof(Elf32_Sym) )); if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) { - belch("ocVerifyImage_ELF: non-integral number of symbol table entries"); + belch("%s: non-integral number of symbol table entries", oc->fileName); return 0; } for (j = 0; j < nent; j++) { @@ -1582,7 +1645,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) } if (nsymtabs == 0) { - belch("ocVerifyImage_ELF: didn't find any symbol tables"); + belch("%s: didn't find any symbol tables", oc->fileName); return 0; } @@ -1605,7 +1668,7 @@ ocGetNames_ELF ( ObjectCode* oc ) ASSERT(symhash != NULL); if (!strtab) { - belch("ocGetNames_ELF: no strtab"); + belch("%s: no strtab", oc->fileName); return 0; } @@ -1619,18 +1682,38 @@ ocGetNames_ELF ( ObjectCode* oc ) /* make a section entry for relevant sections */ SectionKind kind = SECTIONKIND_OTHER; if (!strcmp(".data",sh_strtab+shdr[i].sh_name) || - !strcmp(".data1",sh_strtab+shdr[i].sh_name)) + !strcmp(".data1",sh_strtab+shdr[i].sh_name) || + !strcmp(".bss",sh_strtab+shdr[i].sh_name)) kind = SECTIONKIND_RWDATA; if (!strcmp(".text",sh_strtab+shdr[i].sh_name) || !strcmp(".rodata",sh_strtab+shdr[i].sh_name) || !strcmp(".rodata1",sh_strtab+shdr[i].sh_name)) kind = SECTIONKIND_CODE_OR_RODATA; + if (!strcmp(".bss",sh_strtab+shdr[i].sh_name) && shdr[i].sh_size > 0) { + /* This is a non-empty .bss section. Allocate zeroed space for + it, and set its .sh_offset field such that + ehdrC + .sh_offset == addr_of_zeroed_space. */ + char* zspace = stgCallocBytes(1, shdr[i].sh_size, + "ocGetNames_ELF(anonymous bss)"); + shdr[i].sh_offset = ((char*)zspace) - ((char*)ehdrC); + /* We don't prod BSS sections, hence the following isn't + necessary: + addProddableBlock(oc, zspace, shdr[i].sh_size); + */ + /* + fprintf(stderr, "BSS section at 0x%x, size %d\n", + zspace, shdr[i].sh_size); + */ + } + /* fill in the section info */ oc->sections[i].start = ehdrC + shdr[i].sh_offset; oc->sections[i].end = ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1; oc->sections[i].kind = kind; - + if (kind != SECTIONKIND_OTHER && shdr[i].sh_size > 0) + addProddableBlock(oc, ehdrC + shdr[i].sh_offset, shdr[i].sh_size); + if (shdr[i].sh_type != SHT_SYMTAB) continue; /* copy stuff into this module's object symbol table */ @@ -1655,11 +1738,20 @@ ocGetNames_ELF ( ObjectCode* oc ) ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE ) - ) { - char* nm = strtab + stab[j].st_name; - char* ad = ehdrC - + shdr[ stab[j].st_shndx ].sh_offset - + stab[j].st_value; + ) { + char* nm; + char* ad; + int secno = stab[j].st_shndx; + /* Section 0 is the undefined section, hence > and not >=. */ + ASSERT(secno > 0 && secno < ehdr->e_shnum); + nm = strtab + stab[j].st_name; + /* + if (shdr[secno].sh_type == SHT_NOBITS) { + fprintf(stderr, "bss symbol, size %d off %d name %s\n", + stab[j].st_size, stab[j].st_value, nm); + } + */ + ad = ehdrC + shdr[ secno ].sh_offset + stab[j].st_value; ASSERT(nm != NULL); ASSERT(ad != NULL); oc->symbols[j] = nm; @@ -1696,9 +1788,10 @@ ocGetNames_ELF ( ObjectCode* oc ) /* Do ELF relocations which lack an explicit addend. All x86-linux relocations appear to be of this form. */ -static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC, - Elf32_Shdr* shdr, int shnum, - Elf32_Sym* stab, char* strtab ) +static int +do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC, + Elf32_Shdr* shdr, int shnum, + Elf32_Sym* stab, char* strtab ) { int j; char *symbol; @@ -1741,22 +1834,22 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC, (void*)S = lookupSymbol( symbol ); } if (!S) { - barf("do_Elf32_Rel_relocations: %s: unknown symbol `%s'", - oc->fileName, symbol); + belch("%s: unknown symbol `%s'", oc->fileName, symbol); + return 0; } IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S )); } IF_DEBUG(linker,belch( "Reloc: P = %p S = %p A = %p", (void*)P, (void*)S, (void*)A )); + checkProddableBlock ( oc, pP ); switch (ELF32_R_TYPE(info)) { # ifdef i386_TARGET_ARCH case R_386_32: *pP = S + A; break; case R_386_PC32: *pP = S + A - P; break; # endif default: - fprintf(stderr, "unhandled ELF relocation(Rel) type %d\n", - ELF32_R_TYPE(info)); - barf("do_Elf32_Rel_relocations: unhandled ELF relocation type"); + belch("%s: unhandled ELF relocation(Rel) type %d\n", + oc->fileName, ELF32_R_TYPE(info)); return 0; } @@ -1767,9 +1860,10 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC, /* Do ELF relocations for which explicit addends are supplied. sparc-solaris relocations appear to be of this form. */ -static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, - Elf32_Shdr* shdr, int shnum, - Elf32_Sym* stab, char* strtab ) +static int +do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, + Elf32_Shdr* shdr, int shnum, + Elf32_Sym* stab, char* strtab ) { int j; char *symbol; @@ -1818,8 +1912,8 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, (void*)S = lookupSymbol( symbol ); } if (!S) { - barf("do_Elf32_Rela_relocations: %s: unknown symbol `%s'", - oc->fileName, symbol); + belch("%s: unknown symbol `%s'", oc->fileName, symbol); + return 0; /* S = 0x11223344; fprintf ( stderr, "S %p A %p S+A %p S+A-P %p\n",S,A,S+A,S+A-P); @@ -1829,6 +1923,7 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, } IF_DEBUG(linker,fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n", (void*)P, (void*)S, (void*)A )); + checkProddableBlock ( oc, P ); switch (ELF32_R_TYPE(info)) { # if defined(sparc_TARGET_ARCH) case R_SPARC_WDISP30: @@ -1852,15 +1947,25 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, w1 |= w2; *pP = w1; break; + /* According to the Sun documentation: + R_SPARC_UA32 + This relocation type resembles R_SPARC_32, except it refers to an + unaligned word. That is, the word to be relocated must be treated + as four separate bytes with arbitrary alignment, not as a word + aligned according to the architecture requirements. + + (JRS: which means that freeloading on the R_SPARC_32 case + is probably wrong, but hey ...) + */ + case R_SPARC_UA32: case R_SPARC_32: w2 = (Elf32_Word)(S + A); *pP = w2; break; # endif default: - fprintf(stderr, "unhandled ELF relocation(RelA) type %d\n", - ELF32_R_TYPE(info)); - barf("do_Elf32_Rela_relocations: unhandled ELF relocation type"); + belch("%s: unhandled ELF relocation(RelA) type %d\n", + oc->fileName, ELF32_R_TYPE(info)); return 0; } @@ -1886,7 +1991,7 @@ ocResolve_ELF ( ObjectCode* oc ) strtab = findElfSection ( ehdrC, SHT_STRTAB ); if (stab == NULL || strtab == NULL) { - belch("ocResolve_ELF: can't find string or symbol table"); + belch("%s: can't find string or symbol table", oc->fileName); return 0; }