object_t *symbol_name (object_t * lst) { DOC ("Return symbol name as string."); REQ (lst, 1, c_sym ("symbol-name")); if (!SYMBOLP (CAR (lst))) THROW (wrong_type, UPREF (CAR (lst))); return c_strs (xstrdup (SYMNAME (CAR (lst)))); }
status_t get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength, int32 *_type, void **_location) { int32 count = 0, j; uint32 i; image_t *image; rld_lock(); // get the image from those who have been already initialized image = find_loaded_image_by_id(imageID, false); if (image == NULL) { rld_unlock(); return B_BAD_IMAGE_ID; } // iterate through all the hash buckets until we've found the one for (i = 0; i < HASHTABSIZE(image); i++) { for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { elf_sym *symbol = &image->syms[j]; if (count == num) { const char* symbolName = SYMNAME(image, symbol); strlcpy(nameBuffer, symbolName, *_nameLength); *_nameLength = strlen(symbolName); void* location = (void*)(symbol->st_value + image->regions[0].delta); int32 type; if (symbol->Type() == STT_FUNC) type = B_SYMBOL_TYPE_TEXT; else if (symbol->Type() == STT_OBJECT) type = B_SYMBOL_TYPE_DATA; else type = B_SYMBOL_TYPE_ANY; // TODO: check with the return types of that BeOS function patch_defined_symbol(image, symbolName, &location, &type); if (_type != NULL) *_type = type; if (_location != NULL) *_location = location; goto out; } count++; } } out: rld_unlock(); if (num != count) return B_BAD_INDEX; return B_OK; }
static void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym) { dprintf("symbol at %p, in image %p\n", sym, image); dprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym)); dprintf(" st_value 0x%x\n", sym->st_value); dprintf(" st_size %d\n", sym->st_size); dprintf(" st_info 0x%x\n", sym->st_info); dprintf(" st_other 0x%x\n", sym->st_other); dprintf(" st_shndx %d\n", sym->st_shndx); }
static struct Elf32_Sym *elf_find_symbol(struct elf_image_info *image, const char *name) { unsigned int hash; unsigned int i; if(!image->dynamic_ptr) return NULL; hash = elf_hash(name) % HASHTABSIZE(image); // dprintf("elf_find_symbol: hash %d on '%s'\n", hash, name); for(i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { if(!strcmp(SYMNAME(image, &image->syms[i]), name)) { return &image->syms[i]; } } return NULL; }
// 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 int 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) { struct Elf32_Sym *sym2; char new_symname[512]; switch(sym->st_shndx) { case SHN_UNDEF: // patch the symbol name strlcpy(new_symname, sym_prepend, sizeof(new_symname)); strlcat(new_symname, SYMNAME(image, sym), sizeof(new_symname)); // it's undefined, must be outside this image, try the other image sym2 = elf_find_symbol(shared_image, new_symname); if(!sym2) { dprintf("elf_resolve_symbol: could not resolve symbol '%s'\n", new_symname); return ERR_ELF_RESOLVING_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); return ERR_ELF_RESOLVING_SYMBOL; } if(ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { dprintf("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname); return ERR_ELF_RESOLVING_SYMBOL; } *sym_addr = sym2->st_value + shared_image->regions[0].delta; return NO_ERROR; case SHN_ABS: *sym_addr = sym->st_value; return NO_ERROR; case SHN_COMMON: // XXX finish this dprintf("elf_resolve_symbol: COMMON symbol, finish me!\n"); return ERR_NOT_IMPLEMENTED; default: // standard symbol *sym_addr = sym->st_value + image->regions[0].delta; return NO_ERROR; } }
/* handles single-byte characters, implicit length */ ptr S_intern(const unsigned char *s) { iptr n = strlen((const char *)s); iptr hc = hash(s, n); iptr idx = hc % S_G.oblist_length; ptr sym; bucket *b; tc_mutex_acquire() b = S_G.oblist[idx]; while (b != NULL) { sym = b->sym; if (!GENSYMP(sym)) { ptr str = SYMNAME(sym); if (Sstring_length(str) == n) { iptr i; for (i = 0; ; i += 1) { if (i == n) { tc_mutex_release() return sym; } if (Sstring_ref(str, i) != s[i]) break; } }
int arch_elf_relocate_rel(struct elf_image_info *image, struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) #endif { addr_t S; addr_t A; addr_t P; addr_t finalAddress; addr_t *resolveAddress; int i; S = A = P = 0; for (i = 0; i * (int)sizeof(struct Elf32_Rel) < relLength; i++) { TRACE(("looking at rel type %s, offset 0x%lx\n", kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset)); // calc S switch (ELF32_R_TYPE(rel[i].r_info)) { case R_ARM_JMP_SLOT: case R_ARM_GLOB_DAT: case R_ARM_ABS32: { struct Elf32_Sym *symbol; status_t status; symbol = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); #ifdef _BOOT_MODE status = boot_elf_resolve_symbol(image, symbol, &S); #else status = elf_resolve_symbol(image, symbol, resolveImage, &S); #endif if (status < B_OK) { #ifndef _BOOT_MODE TRACE(("failed relocating %s\n", SYMNAME(image, symbol))); #endif //IRA return status; return B_OK; } #ifndef _BOOT_MODE TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, symbol))); #endif } } // calc A switch (ELF32_R_TYPE(rel[i].r_info)) { case R_ARM_ABS32: case R_ARM_RELATIVE: A = *(addr_t *)(image->text_region.delta + rel[i].r_offset); TRACE(("A %p\n", (void *)A)); break; } switch (ELF32_R_TYPE(rel[i].r_info)) { case R_ARM_NONE: continue; case R_ARM_RELATIVE: // B + A; finalAddress = image->text_region.delta + A; break; case R_ARM_JMP_SLOT: case R_ARM_GLOB_DAT: finalAddress = S; break; case R_ARM_ABS32: finalAddress = S + A; break; default: dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); return B_BAD_DATA; } resolveAddress = (addr_t *)(image->text_region.delta + rel[i].r_offset); #ifndef _BOOT_MODE if (!is_in_image(image, (addr_t)resolveAddress)) { dprintf("arch_elf_relocate_rel: invalid offset %#lx\n", rel[i].r_offset); return B_BAD_ADDRESS; } #endif *resolveAddress = finalAddress; TRACE(("-> offset %#lx = %#lx\n", (image->text_region.delta + rel[i].r_offset), finalAddress)); } return B_NO_ERROR; }
/* Take an address to symbol. Taken from the OpenBeOS version of the newos kernel. */ int elf_reverse_lookup_symbol(addr_t address, addr_t *base_address, char *text, int len) { struct elf_image_info **ptr; struct elf_image_info *image; struct Elf32_Sym *sym; struct elf_image_info *found_image; struct Elf32_Sym *found_sym; long found_delta; unsigned int i,j; int rv; PRINT(("looking up %p\n",(void *)address)); mutex_lock(&image_lock); found_sym = 0; found_image = 0; found_delta = 0x7fffffff; for(ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) { image = *ptr; PRINT((" image %p, base = %p, size = %p\n", image, (void *)image->regions[0].start, (void *)image->regions[0].size)); if ((address < image->regions[0].start) || (address >= (image->regions[0].start + image->regions[0].size))) continue; PRINT((" searching...\n")); found_image = image; for (i = 0; i < HASHTABSIZE(image); i++) { for(j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { long d; sym = &image->syms[j]; PRINT((" %p looking at %s, type = %d, bind = %d, addr = %p\n",sym,SYMNAME(image, sym),ELF32_ST_TYPE(sym->st_info),ELF32_ST_BIND(sym->st_info),(void *)sym->st_value)); PRINT((" symbol: %lx (%x + %lx)\n", sym->st_value + image->regions[0].delta, sym->st_value, image->regions[0].delta)); if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC) continue; d = (long)address - (long)(sym->st_value + image->regions[0].delta); if ((d >= 0) && (d < found_delta)) { found_delta = d; found_sym = sym; } } } break; } if (found_sym == 0) { PRINT(("symbol not found!\n")); strlcpy(text, "symbol not found", len); rv = ERR_NOT_FOUND; } else { PRINT(("symbol at %p, in image %p\n", found_sym, found_image)); PRINT(("name index %d, '%s'\n", found_sym->st_name, SYMNAME(found_image, found_sym))); PRINT(("addr = %#lx, offset = %#lx\n",(found_sym->st_value + found_image->regions[0].delta),found_delta)); // XXX should honor len here // sprintf(text, "<%#lx:%s + %#lx> %s", (found_sym->st_value + found_image->regions[0].delta), SYMNAME(found_image, found_sym), found_delta, found_image->name); strncpy(text, SYMNAME(found_image, found_sym), len); text[len-1] = 0; *base_address = found_sym->st_value + found_image->regions[0].delta; rv = 0; } mutex_unlock(&image_lock); return rv; }
static status_t relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel, size_t relLength, SymbolLookupCache* cache) { for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) { int type = ELF64_R_TYPE(rel[i].r_info); int symIndex = ELF64_R_SYM(rel[i].r_info); Elf64_Addr symAddr = 0; image_t* symbolImage = NULL; // Resolve the symbol, if any. if (symIndex != 0) { Elf64_Sym* sym = SYMBOL(image, symIndex); status_t status = resolve_symbol(rootImage, image, sym, cache, &symAddr, &symbolImage); if (status != B_OK) { TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n", SYMNAME(image, sym), status)); printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n", SYMNAME(image, sym), status); return status; } } // Address of the relocation. Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset; // Calculate the relocation value. Elf64_Addr relocValue; switch(type) { case R_X86_64_NONE: continue; case R_X86_64_64: case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: relocValue = symAddr + rel[i].r_addend; break; case R_X86_64_PC32: relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; break; case R_X86_64_RELATIVE: relocValue = image->regions[0].delta + rel[i].r_addend; break; case R_X86_64_DTPMOD64: relocValue = symbolImage == NULL ? image->dso_tls_id : symbolImage->dso_tls_id; break; case R_X86_64_DTPOFF32: case R_X86_64_DTPOFF64: relocValue = symAddr; break; default: TRACE(("unhandled relocation type %d\n", type)); return B_BAD_DATA; } *(Elf64_Addr *)relocAddr = relocValue; } return B_OK; }
int arch_elf_relocate_rel(struct elf_image_info *image, struct elf_image_info *resolveImage, Elf32_Rel *rel, int relLength) #endif { elf_addr S; uint32 A; uint32 P; uint32 finalAddress; uint32 *resolveAddress; int i; S = A = P = 0; for (i = 0; i * (int)sizeof(Elf32_Rel) < relLength; i++) { TRACE(("looking at rel type %s, offset 0x%lx\n", kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset)); // calc S switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_32: case R_386_PC32: case R_386_GLOB_DAT: case R_386_JMP_SLOT: case R_386_GOTOFF: { Elf32_Sym *symbol; status_t status; symbol = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); #ifdef _BOOT_MODE status = boot_elf_resolve_symbol(image, symbol, &S); #else status = elf_resolve_symbol(image, symbol, resolveImage, &S); #endif if (status < B_OK) return status; TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, symbol))); } } // calc A switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_32: case R_386_PC32: case R_386_GOT32: case R_386_PLT32: case R_386_RELATIVE: case R_386_GOTOFF: case R_386_GOTPC: A = *(uint32 *)(image->text_region.delta + rel[i].r_offset); TRACE(("A %p\n", (void *)A)); break; } // calc P switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_PC32: case R_386_GOT32: case R_386_PLT32: case R_386_GOTPC: P = image->text_region.delta + rel[i].r_offset; TRACE(("P %p\n", (void *)P)); break; } switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_NONE: continue; case R_386_32: finalAddress = S + A; break; case R_386_PC32: finalAddress = S + A - P; break; case R_386_RELATIVE: // B + A; finalAddress = image->text_region.delta + A; break; case R_386_JMP_SLOT: case R_386_GLOB_DAT: finalAddress = S; break; default: dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); return B_BAD_DATA; } resolveAddress = (uint32 *)(image->text_region.delta + rel[i].r_offset); #ifndef _BOOT_MODE if (!is_in_image(image, (addr_t)resolveAddress)) { dprintf("arch_elf_relocate_rel: invalid offset %#lx\n", rel[i].r_offset); return B_BAD_ADDRESS; } #endif *resolveAddress = finalAddress; TRACE(("-> offset %#lx (%#lx) = %#lx\n", (image->text_region.delta + rel[i].r_offset), rel[i].r_offset, finalAddress)); } return B_NO_ERROR; }
static int relocate_rela(image_t *rootImage, image_t *image, Elf32_Rela *rel, int rel_len, SymbolLookupCache* cache) { int i; addr_t S; addr_t final_val; # define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset)) //# define A (*(P)) #define A ((addr_t)rel[i].r_addend) # define B (image->regions[0].delta) for (i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) { unsigned type = ELF32_R_TYPE(rel[i].r_info); switch (type) { case R_68K_32: case R_68K_16: case R_68K_8: case R_68K_PC32: case R_68K_PC16: case R_68K_PC8: case R_68K_GLOB_DAT: case R_68K_JMP_SLOT: { Elf32_Sym *sym; status_t status; sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); status = resolve_symbol(rootImage, image, sym, cache, &S); if (status < B_OK) { TRACE(("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status)); printf("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status); return status; } } } switch (type) { case R_68K_NONE: continue; case R_68K_32: write_32(P, S + A); break; case R_68K_16: if (write_16_check(P, S + A)) break; TRACE(("R_68K_16 overflow\n")); return B_BAD_DATA; case R_68K_8: if (write_8_check(P, S + A)) break; TRACE(("R_68K_8 overflow\n")); return B_BAD_DATA; case R_68K_PC32: write_32(P, (S + A - (addr_t)P)); break; #if 0 case R_68K_PC16: if (write_16_check(P, (S + A - P))) break; TRACE(("R_68K_PC16 overflow\n")); return B_BAD_DATA; case R_68K_PC8: if (write_8(P, (S + A - P))) break; TRACE(("R_68K_PC8 overflow\n")); return B_BAD_DATA; case R_68K_GOT32: REQUIRE_GOT; write_32(P, (G + A - P)); break; case R_68K_GOT16: REQUIRE_GOT; if (write_16_check(P, (G + A - P))) break; TRACE(("R_68K_GOT16 overflow\n")); return B_BAD_DATA; case R_68K_GOT8: REQUIRE_GOT; if (write_8_check(P, (G + A - P))) break; TRACE(("R_68K_GOT8 overflow\n")); return B_BAD_DATA; case R_68K_GOT32O: REQUIRE_GOT; write_32(P, (G + A)); break; case R_68K_GOT16O: REQUIRE_GOT; if (write_16_check(P, (G + A))) break; TRACE(("R_68K_GOT16 overflow\n")); return B_BAD_DATA; case R_68K_GOT8O: REQUIRE_GOT; if (write_8_check(P, (G + A))) break; TRACE(("R_68K_GOT8 overflow\n")); return B_BAD_DATA; case R_68K_PLT32: REQUIRE_PLT; write_32(P, (L + A - P)); break; case R_68K_PLT16: REQUIRE_PLT; if (write_16_check(P, (L + A - P))) break; TRACE(("R_68K_PLT16 overflow\n")); return B_BAD_DATA; case R_68K_PLT8: REQUIRE_PLT; if (write_8_check(P, (L + A - P))) break; TRACE(("R_68K_PLT8 overflow\n")); return B_BAD_DATA; case R_68K_PLT32O: REQUIRE_PLT; write_32(P, (L + A)); break; case R_68K_PLT16O: REQUIRE_PLT; if (write_16_check(P, (L + A))) break; TRACE(("R_68K_PLT16O overflow\n")); return B_BAD_DATA; case R_68K_PLT8O: REQUIRE_PLT; if (write_8_check(P, (L + A))) break; TRACE(("R_68K_PLT8O overflow\n")); return B_BAD_DATA; case R_386_GOT32: final_val = G + A; break; case R_386_PLT32: final_val = L + A - (addr_t)P; break; #endif case R_68K_COPY: /* what ? */ continue; case R_68K_GLOB_DAT: write_32(P, S/* + A*/); break; case R_68K_JMP_SLOT: //XXX ? write_32(P, (G + A)); write_32(P, S); break; #if 0 case R_386_JMP_SLOT: write_32(P, S); break; #endif case R_68K_RELATIVE: write_32(P, B + A); break; #if 0 case R_386_GOTOFF: final_val = S + A - GOT; break; case R_386_GOTPC: final_val = GOT + A - P; break; #endif default: TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info))); return B_NOT_ALLOWED; } *P = final_val; } # undef P # undef A # undef B return B_NO_ERROR; }
static int relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel, int rel_len, SymbolLookupCache* cache) { int i; addr_t S; addr_t final_val; # define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset)) # define A (*(P)) # define B (image->regions[0].delta) for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) { unsigned type = ELF32_R_TYPE(rel[i].r_info); switch (type) { case R_386_32: case R_386_PC32: case R_386_GLOB_DAT: case R_386_JMP_SLOT: case R_386_GOTOFF: { struct Elf32_Sym *sym; status_t status; sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); status = resolve_symbol(rootImage, image, sym, cache, &S); if (status < B_OK) { TRACE(("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status)); printf("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status); return status; } } } switch (type) { case R_386_NONE: continue; case R_386_32: final_val = S + A; break; case R_386_PC32: final_val = S + A - (addr_t)P; break; #if 0 case R_386_GOT32: final_val = G + A; break; case R_386_PLT32: final_val = L + A - (addr_t)P; break; #endif case R_386_COPY: /* what ? */ continue; case R_386_GLOB_DAT: final_val = S; break; case R_386_JMP_SLOT: final_val = S; break; case R_386_RELATIVE: final_val = B + A; break; #if 0 case R_386_GOTOFF: final_val = S + A - GOT; break; case R_386_GOTPC: final_val = GOT + A - P; break; #endif default: TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info))); return B_NOT_ALLOWED; } *P = final_val; } # undef P # undef A # undef B return B_NO_ERROR; }
status_t get_nearest_symbol_at_address(void* address, image_id* _imageID, char** _imagePath, char** _symbolName, int32* _type, void** _location) { rld_lock(); image_t* image = find_loaded_image_by_address((addr_t)address); if (image == NULL) { rld_unlock(); return B_BAD_VALUE; } elf_sym* foundSymbol = NULL; addr_t foundLocation = (addr_t)NULL; bool found = false; for (uint32 i = 0; i < HASHTABSIZE(image) && !found; i++) { for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { elf_sym *symbol = &image->syms[j]; addr_t location = symbol->st_value + image->regions[0].delta; if (location <= (addr_t)address && location >= foundLocation) { foundSymbol = symbol; foundLocation = location; // jump out if we have an exact match if (foundLocation == (addr_t)address) { found = true; break; } } } } if (_imageID != NULL) *_imageID = image->id; if (_imagePath != NULL) *_imagePath = image->path; if (foundSymbol != NULL) { *_symbolName = SYMNAME(image, foundSymbol); if (_type != NULL) { if (foundSymbol->Type() == STT_FUNC) *_type = B_SYMBOL_TYPE_TEXT; else if (foundSymbol->Type() == STT_OBJECT) *_type = B_SYMBOL_TYPE_DATA; else *_type = B_SYMBOL_TYPE_ANY; // TODO: check with the return types of that BeOS function } if (_location != NULL) *_location = (void*)foundLocation; } else { *_symbolName = NULL; if (_location != NULL) *_location = NULL; } rld_unlock(); return B_OK; }
char *boot, *proto, *dev; #if 0 #ifdef __ELF__ #define SYMNAME(a) a #else #define SYMNAME(a) __CONCAT("_",a) #endif #else /* XXX: Hack in libc nlist works with both formats */ #define SYMNAME(a) __CONCAT("_",a) #endif struct nlist nl[] = { #define X_BLOCKTABLE 0 { {SYMNAME("block_table")} }, #define X_BLOCKCOUNT 1 { {SYMNAME("block_count")} }, #define X_BLOCKSIZE 2 { {SYMNAME("block_size")} }, { {NULL} } }; daddr_t *block_table; /* block number array in prototype image */ int32_t *block_count_p; /* size of this array */ int32_t *block_size_p; /* filesystem block size */ int32_t max_block_count; char *loadprotoblocks __P((char *, size_t *)); int loadblocknums __P((char *, int)); static void devread __P((int, void *, daddr_t, size_t, char *)); static void usage __P((void));