From 4063db92d046d7a878f659e13b07be5f732ee0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 6 Jan 2008 14:54:57 +0000 Subject: [PATCH] * elf_resolve_symbol() no longer copies the symbol name if symbolPrepend is NULL (it's not used anywhere yet, anyway). * Fixed warning when compiling with tracing turned on. * Some cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23267 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/elf.cpp | 141 +++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 62 deletions(-) diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index fe7ee6af03..9f2c198bf6 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -62,8 +62,7 @@ static mutex sImageLoadMutex; // serializes loading/unloading add-ons static bool sInitialized = false; -/** calculates hash for an image using its ID */ - +/*! Calculates hash for an image using its ID */ static uint32 image_hash(void *_image, const void *_key, uint32 range) { @@ -77,8 +76,7 @@ image_hash(void *_image, const void *_key, uint32 range) } -/** compares an image to a given ID */ - +/*! Compares an image to a given ID */ static int image_compare(void *_image, const void *_key) { @@ -117,8 +115,7 @@ register_elf_image(struct elf_image_info *image) } -/** Note, you must lock the image mutex when you call this function. */ - +/*! Note, you must lock the image mutex when you call this function. */ static struct elf_image_info * find_image_at_address(addr_t address) { @@ -481,28 +478,34 @@ elf_parse_dynamic_section(struct elf_image_info *image) neededOffset = d[i].d_un.d_ptr + image->text_region.delta; break; case DT_HASH: - image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->text_region.delta); + image->symhash = (uint32 *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_STRTAB: - image->strtab = (char *)(d[i].d_un.d_ptr + image->text_region.delta); + image->strtab = (char *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_SYMTAB: - image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->text_region.delta); + image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_REL: - image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta); + image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_RELSZ: image->rel_len = d[i].d_un.d_val; break; case DT_RELA: - image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->text_region.delta); + image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_RELASZ: image->rela_len = d[i].d_un.d_val; break; case DT_JMPREL: - image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta); + image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_PLTRELSZ: image->pltrel_len = d[i].d_un.d_val; @@ -520,7 +523,7 @@ elf_parse_dynamic_section(struct elf_image_info *image) if (!image->symhash || !image->syms || !image->strtab) return B_ERROR; - TRACE(("needed_offset = %d\n", neededOffset)); + TRACE(("needed_offset = %ld\n", neededOffset)); if (neededOffset >= 0) image->needed = STRING(image, neededOffset); @@ -529,64 +532,74 @@ elf_parse_dynamic_section(struct elf_image_info *image) } -/** this function first tries to see if the first image and it's already resolved symbol is okay, otherwise - * it tries to link against the shared_image - * XXX gross hack and needs to be done better - */ - +/*! Resolves the \a symbol by linking against \a sharedImage if necessary. + Returns the resolved symbol's address in \a _symbolAddress. + TODO: eventually get rid of "symbolPrepend" +*/ status_t -elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, - struct elf_image_info *shared_image, const char *sym_prepend, addr_t *sym_addr) +elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, + struct elf_image_info *sharedImage, const char *symbolPrepend, + addr_t *_symbolAddress) { - struct Elf32_Sym *sym2; - char new_symname[512]; - - switch (sym->st_shndx) { + switch (symbol->st_shndx) { case SHN_UNDEF: + { + struct Elf32_Sym *newSymbol; + char newNameBuffer[368]; + char *newName; + // patch the symbol name - strlcpy(new_symname, sym_prepend, sizeof(new_symname)); - strlcat(new_symname, SYMNAME(image, sym), sizeof(new_symname)); + if (symbolPrepend) { + newName = newNameBuffer; + strlcpy(newName, symbolPrepend, sizeof(newName)); + strlcat(newName, SYMNAME(image, symbol), sizeof(newName)); + } else + newName = SYMNAME(image, symbol); // it's undefined, must be outside this image, try the other image - sym2 = elf_find_symbol(shared_image, new_symname); - if (!sym2) { + newSymbol = elf_find_symbol(sharedImage, newName); + if (newSymbol == NULL) { dprintf("\"%s\": could not resolve symbol '%s'\n", - image->name, new_symname); + image->name, newName); return B_MISSING_SYMBOL; } // make sure they're the same type - if (ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) { - dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", new_symname); + if (ELF32_ST_TYPE(symbol->st_info) + != ELF32_ST_TYPE(newSymbol->st_info)) { + dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", newName); return B_MISSING_SYMBOL; } - if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { - TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname)); + if (ELF32_ST_BIND(newSymbol->st_info) != STB_GLOBAL + && ELF32_ST_BIND(newSymbol->st_info) != STB_WEAK) { + TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n", newName)); return B_MISSING_SYMBOL; } - *sym_addr = sym2->st_value + shared_image->text_region.delta; - return B_NO_ERROR; + *_symbolAddress = newSymbol->st_value + + sharedImage->text_region.delta; + return B_OK; + } case SHN_ABS: - *sym_addr = sym->st_value; - return B_NO_ERROR; + *_symbolAddress = symbol->st_value; + return B_OK; case SHN_COMMON: // ToDo: finish this TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n")); return B_ERROR; + default: // standard symbol - *sym_addr = sym->st_value + image->text_region.delta; - return B_NO_ERROR; + *_symbolAddress = symbol->st_value + image->text_region.delta; + return B_OK; } } -/** Until we have shared library support, just links against the kernel */ - +/*! Until we have shared library support, just links against the kernel */ static int -elf_relocate(struct elf_image_info *image, const char *sym_prepend) +elf_relocate(struct elf_image_info *image, const char *symbolPrepend) { int status = B_NO_ERROR; @@ -594,26 +607,33 @@ elf_relocate(struct elf_image_info *image, const char *sym_prepend) // deal with the rels first if (image->rel) { - TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel))); + TRACE(("total %i relocs\n", + image->rel_len / (int)sizeof(struct Elf32_Rel))); - status = arch_elf_relocate_rel(image, sym_prepend, sKernelImage, image->rel, image->rel_len); + status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage, + image->rel, image->rel_len); if (status < B_OK) return status; } if (image->pltrel) { - TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel))); + TRACE(("total %i plt-relocs\n", + image->pltrel_len / (int)sizeof(struct Elf32_Rel))); - if (image->pltrel_type == DT_REL) - status = arch_elf_relocate_rel(image, sym_prepend, sKernelImage, image->pltrel, image->pltrel_len); - else - status = arch_elf_relocate_rela(image, sym_prepend, sKernelImage, (struct Elf32_Rela *)image->pltrel, image->pltrel_len); + if (image->pltrel_type == DT_REL) { + status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage, + image->pltrel, image->pltrel_len); + } else { + status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage, + (struct Elf32_Rela *)image->pltrel, image->pltrel_len); + } if (status < B_OK) return status; } if (image->rela) { - status = arch_elf_relocate_rela(image, sym_prepend, sKernelImage, image->rela, image->rela_len); + status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage, + image->rela, image->rela_len); if (status < B_OK) return status; } @@ -809,7 +829,7 @@ insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel) goto error1; if (!kernel) { - status = elf_relocate(image, ""); + status = elf_relocate(image, NULL); if (status < B_OK) goto error1; } else @@ -841,8 +861,7 @@ error1: } -// #pragma mark - -// public kernel API +// #pragma mark - public kernel API status_t @@ -881,15 +900,13 @@ done: } -// #pragma mark - -// kernel private API +// #pragma mark - kernel private API -/** Looks up a symbol by address in all images loaded in kernel space. - * Note, if you need to call this function outside a debugger, make - * sure you fix locking and the way it returns its information, first! - */ - +/*! Looks up a symbol by address in all images loaded in kernel space. + Note, if you need to call this function outside a debugger, make + sure you fix locking and the way it returns its information, first! +*/ status_t elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) @@ -1322,7 +1339,7 @@ load_kernel_add_on(const char *path) char regionName[B_OS_NAME_LENGTH]; elf_region *region; - TRACE(("looking at program header %d\n", i)); + TRACE(("looking at program header %ld\n", i)); switch (programHeaders[i].p_type) { case PT_LOAD: @@ -1410,7 +1427,7 @@ load_kernel_add_on(const char *path) if (status < B_OK) goto error5; - status = elf_relocate(image, ""); + status = elf_relocate(image, NULL); if (status < B_OK) goto error5;