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 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; }
/* 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; }
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; }