summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ia64/libuwx/src/uwx_symbols.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ia64/libuwx/src/uwx_symbols.c')
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_symbols.c850
1 files changed, 0 insertions, 850 deletions
diff --git a/sys/contrib/ia64/libuwx/src/uwx_symbols.c b/sys/contrib/ia64/libuwx/src/uwx_symbols.c
deleted file mode 100644
index b91c2db..0000000
--- a/sys/contrib/ia64/libuwx/src/uwx_symbols.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
-Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifdef USE_CLEAN_NAMESPACE
-#define fopen _fopen
-#define fseek _fseek
-#define fread _fread
-#define fclose _fclose
-#endif /* USE_CLEAN_NAMESPACE */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <elf.h>
-
-#include "uwx.h"
-#include "uwx_env.h"
-
-#ifdef USE_CLEAN_NAMESPACE
-/*
- * Moved the defines above the include of stdio.h,
- * so we don't need these unless that causes problems
- * and we have to move them back down here.
- * #define fopen _fopen
- * #define fseek _fseek
- * #define fread _fread
- * #define fclose _fclose
- * extern FILE *_fopen(const char *, const char *);
- * extern int _fseek(FILE *, long int, int);
- * extern size_t _fread(void *, size_t, size_t, FILE *);
- * extern int _fclose(FILE *);
- */
-#endif /* USE_CLEAN_NAMESPACE */
-
-struct uwx_symbol_cache {
- char *module_name;
- int nsyms;
- uint64_t *sym_values;
- char **sym_names;
- char *strings;
-};
-
-
-int uwx_read_func_symbols(
- struct uwx_env *env,
- struct uwx_symbol_cache *cache,
- char *module_name);
-
-
-int uwx_find_symbol(
- struct uwx_env *env,
- struct uwx_symbol_cache **symbol_cache_p,
- char *module_name,
- uint64_t relip,
- char **func_name_p,
- uint64_t *offset_p)
-{
- int status;
- int i;
- uint64_t offset;
- uint64_t best_offset;
- char *best_name;
- struct symbol *sym;
- struct uwx_symbol_cache *cache = NULL;
-
- /* Allocate a symbol cache on first call */
- if (symbol_cache_p != NULL)
- cache = *symbol_cache_p;
- if (cache == NULL) {
- cache = (struct uwx_symbol_cache *)
- (*env->allocate_cb)(sizeof(struct uwx_symbol_cache));
- if (cache == NULL)
- return UWX_ERR_NOMEM;
- cache->module_name = NULL;
- cache->nsyms = 0;
- cache->sym_values = NULL;
- cache->sym_names = NULL;
- cache->strings = NULL;
- if (symbol_cache_p != NULL)
- *symbol_cache_p = cache;
- }
-
- /* Read function symbols from the object file */
- status = uwx_read_func_symbols(env, cache, module_name);
- if (status != UWX_OK)
- return status;
-
- /* Search for best match */
- best_offset = ~(uint64_t)0;
- best_name = NULL;
- for (i = 0; i < cache->nsyms; i++) {
- if (cache->sym_values[i] == relip) {
- *func_name_p = cache->sym_names[i];
- *offset_p = 0;
- if (symbol_cache_p == NULL)
- uwx_release_symbol_cache(env, cache);
- return UWX_OK;
- }
- if (relip > cache->sym_values[i]) {
- offset = relip - cache->sym_values[i];
- if (offset < best_offset) {
- best_offset = offset;
- best_name = cache->sym_names[i];
- }
- }
- }
- if (best_name == NULL)
- return UWX_ERR_NOSYM;
-
- if (symbol_cache_p == NULL)
- uwx_release_symbol_cache(env, cache);
-
- *func_name_p = best_name;
- *offset_p = best_offset;
- return UWX_OK;
-}
-
-
-void uwx_release_symbol_cache(
- struct uwx_env *env,
- struct uwx_symbol_cache *symbol_cache)
-{
- if (symbol_cache->module_name != NULL)
- (*env->free_cb)(symbol_cache->module_name);
- if (symbol_cache->sym_values != NULL)
- (*env->free_cb)(symbol_cache->sym_values);
- if (symbol_cache->sym_names != NULL)
- (*env->free_cb)(symbol_cache->sym_names);
- if (symbol_cache->strings != NULL)
- (*env->free_cb)(symbol_cache->strings);
- (*env->free_cb)(symbol_cache);
-}
-
-
-#define ELF_ERR_NOMEM UWX_ERR_NOMEM /* Out of memory */
-#define ELF_ERR_OPEN UWX_ERR_NOSYM /* Can't open file */
-
-#define ELF_ERR_NOHEADER UWX_ERR_NOSYM /* Can't read ELF header */
-#define ELF_ERR_NOTELF UWX_ERR_NOSYM /* Not an ELF file */
-#define ELF_ERR_HEADER_SIZE UWX_ERR_NOSYM /* Invalid e_ehsize */
-#define ELF_ERR_INVALID_CLASS UWX_ERR_NOSYM /* Invalid EI_CLASS */
-#define ELF_ERR_INVALID_DATA UWX_ERR_NOSYM /* Invalid EI_DATA */
-
-#define ELF_ERR_READ_SECTHDR UWX_ERR_NOSYM /* Can't read section headers */
-#define ELF_ERR_SECTHDR_SIZE UWX_ERR_NOSYM /* Invalid e_shentsize */
-
-#define ELF_ERR_READ_PROGHDR UWX_ERR_NOSYM /* Can't read program headers */
-#define ELF_ERR_PROGHDR_SIZE UWX_ERR_NOSYM /* Invalid e_phentsize */
-
-#define ELF_ERR_READ_SECTION UWX_ERR_NOSYM /* Can't read section contents */
-
-#define ELF_ERR_READ_SYMTAB UWX_ERR_NOSYM /* Can't read symbol table */
-#define ELF_ERR_SYMTAB_SIZE UWX_ERR_NOSYM /* Invalid sh_entsize for symtab */
-
-
-struct elf_file {
- uint64_t phoff;
- uint64_t shoff;
- uint64_t text_base;
- uint64_t text_end;
- alloc_cb allocate_cb;
- free_cb free_cb;
- const char *filename;
- FILE *fd;
- struct elf_section *sections;
- struct elf_symbol *symbols;
- char *symbol_strings;
- int native_data;
- int source_class;
- int source_data;
- int ehsize;
- int phentsize;
- int phnum;
- int shentsize;
- int shnum;
- int nsyms;
-};
-
-struct elf_section {
- uint64_t flags;
- uint64_t addr;
- uint64_t offset;
- uint64_t size;
- uint64_t entsize;
- char *contents;
- struct elf_symbol *symbols;
- int type;
- int link;
- int info;
- int nelems;
-};
-
-struct elf_symbol {
- uint64_t value;
- char *namep;
- int name;
- int type;
- int shndx;
-};
-
-
-static void elf_swap_bytes(char *buf, char *template)
-{
- int i;
- int sz;
- char temp[16];
-
- while (sz = *template++) {
- if (sz > 16)
- exit(1);
- for (i = 0; i < sz; i++)
- temp[i] = buf[i];
- for (i = 0; i < sz; i++)
- buf[i] = temp[sz-i-1];
- buf += sz;
- }
-}
-
-
-static int elf_read_section(struct elf_file *ef, int shndx)
-{
- struct elf_section *sect;
-
- if (shndx < 0 || shndx > ef->shnum)
- return 0;
-
- sect = &ef->sections[shndx];
-
- /* Return if section has already been read */
- if (sect->contents != NULL)
- return 0;
-
- sect->contents = (*ef->allocate_cb)(sect->size);
- if (sect->contents == NULL)
- return ELF_ERR_NOMEM;
-
- fseek(ef->fd, (long)sect->offset, SEEK_SET);
- if (fread(sect->contents, 1, sect->size, ef->fd) != sect->size)
- return ELF_ERR_READ_SECTION;
-
- return 0;
-}
-
-
-static char template_elf32_sym[] = {4, 4, 4, 1, 1, 2, 0};
-static char template_elf64_sym[] = {4, 1, 1, 2, 8, 8, 0};
-
-static int elf_read_symtab_section(struct elf_file *ef, int shndx)
-{
- int i;
- int nsyms;
- long size;
- union {
- Elf32_Sym sym32;
- Elf64_Sym sym64;
- } sym;
- struct elf_section *sect;
- struct elf_symbol *syms;
- struct elf_symbol *symp;
- char *strtab;
-
- sect = &ef->sections[shndx];
-
- /* Return if section has already been read */
- if (sect->symbols != NULL)
- return 0;
-
- if (ef->source_class == ELFCLASS32) {
- if (sect->entsize != sizeof(sym.sym32))
- return ELF_ERR_SYMTAB_SIZE;
- }
- else {
- if (sect->entsize != sizeof(sym.sym64))
- return ELF_ERR_SYMTAB_SIZE;
- }
-
- nsyms = sect->nelems;
- syms = (struct elf_symbol *)
- (*ef->allocate_cb)(sizeof(struct elf_symbol) * nsyms);
- if (syms == NULL)
- return ELF_ERR_NOMEM;
-
- /* Read the symbol table */
- fseek(ef->fd, (long)sect->offset, SEEK_SET);
- for (i = 0; i < nsyms; i++) {
-
- symp = &syms[i];
-
- /* Read the next symbol table entry */
- if (fread((char *)&sym, sect->entsize, 1, ef->fd) != 1) {
- (*ef->free_cb)(syms);
- return ELF_ERR_READ_SYMTAB;
- }
-
- /* Get fields from appropriate structure */
- if (ef->source_class == ELFCLASS32) {
- /* Swap bytes if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&sym, template_elf32_sym);
- symp->name = sym.sym32.st_name;
- symp->type = sym.sym32.st_info & 0x0f;
- symp->shndx = sym.sym32.st_shndx;
- symp->value = sym.sym32.st_value;
- }
- else {
- /* Swap bytes if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&sym, template_elf64_sym);
- symp->name = sym.sym64.st_name;
- symp->type = sym.sym64.st_info & 0x0f;
- symp->shndx = sym.sym64.st_shndx;
- symp->value = sym.sym64.st_value;
- }
- symp->namep = NULL;
-
- }
-
- /* Read the symbol string table and convert section names */
- /* from string table offsets to pointers */
- if (sect->link > 0 && sect->link < ef->shnum) {
- if (elf_read_section(ef, sect->link) == 0) {
- strtab = ef->sections[sect->link].contents;
- for (i = 0; i < nsyms; i++) {
- symp = &syms[i];
- symp->namep = strtab + symp->name;
- }
- ef->symbol_strings = strtab;
- ef->sections[sect->link].contents = NULL;
- }
- }
-
- sect->symbols = syms;
- return 0;
-}
-
-
-static char template_elf32_phdr[] = {4, 4, 4, 4, 4, 4, 4, 4, 0};
-static char template_elf64_phdr[] = {4, 4, 8, 8, 8, 8, 8, 8, 0};
-
-static int elf_read_prog_hdrs(struct elf_file *ef)
-{
- int i;
- union {
- Elf32_Phdr hdr32;
- Elf64_Phdr hdr64;
- } header;
- uint64_t vaddr;
- uint64_t memsz;
- uint64_t unwind_base;
- int type;
-
- if (ef->phnum == 0)
- return 0;
-
- if (ef->source_class == ELFCLASS32) {
- if (ef->phentsize != sizeof(header.hdr32))
- return ELF_ERR_PROGHDR_SIZE;
- }
- else {
- if (ef->phentsize != sizeof(header.hdr64))
- return ELF_ERR_PROGHDR_SIZE;
- }
-
- /* Look for the PT_IA_64_UNWIND segment */
- /* (That will help us identify the text segment) */
-
- fseek(ef->fd, (long)ef->phoff, SEEK_SET);
- for (i = 0; i < ef->phnum; i++) {
-
- /* Read the next program header */
- if (fread((char *)&header, ef->phentsize, 1, ef->fd) != 1)
- return ELF_ERR_READ_PROGHDR;
-
- /* Get fields from appropriate structure */
- if (ef->source_class == ELFCLASS32) {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf32_phdr);
- type = header.hdr32.p_type;
- vaddr = header.hdr32.p_vaddr;
- }
- else {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf64_phdr);
- type = header.hdr64.p_type;
- vaddr = header.hdr64.p_vaddr;
- }
-
- if (type == PT_IA_64_UNWIND) {
- unwind_base = vaddr;
- break;
- }
-
- }
-
- /* Now look for the PT_LOAD segment that includes the unwind segment */
-
- fseek(ef->fd, (long)ef->phoff, SEEK_SET);
- for (i = 0; i < ef->phnum; i++) {
-
- /* Read the next program header */
- if (fread((char *)&header, ef->phentsize, 1, ef->fd) != 1)
- return ELF_ERR_READ_PROGHDR;
-
- /* Get fields from appropriate structure */
- if (ef->source_class == ELFCLASS32) {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf32_phdr);
- type = header.hdr32.p_type;
- vaddr = header.hdr32.p_vaddr;
- memsz = header.hdr32.p_memsz;
- }
- else {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf64_phdr);
- type = header.hdr64.p_type;
- vaddr = header.hdr64.p_vaddr;
- memsz = header.hdr64.p_memsz;
- }
-
- if (type == PT_LOAD &&
- vaddr <= unwind_base && unwind_base < vaddr + memsz) {
- ef->text_base = vaddr;
- ef->text_end = vaddr + memsz;
- break;
- }
-
- }
-
- return 0;
-}
-
-
-static char template_elf32_shdr[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0};
-static char template_elf64_shdr[] = {4, 4, 8, 8, 8, 8, 4, 4, 8, 8, 0};
-
-static int elf_read_sect_hdrs(struct elf_file *ef)
-{
- int i;
- long size;
- int err;
- union {
- Elf32_Shdr hdr32;
- Elf64_Shdr hdr64;
- } header;
- struct elf_section *sect;
- char *shstrtab;
-
- if (ef->source_class == ELFCLASS32) {
- if (ef->shentsize != sizeof(header.hdr32))
- return ELF_ERR_SECTHDR_SIZE;
- }
- else {
- if (ef->shentsize != sizeof(header.hdr64))
- return ELF_ERR_SECTHDR_SIZE;
- }
-
- fseek(ef->fd, (long)ef->shoff, SEEK_SET);
- ef->sections = (struct elf_section *)
- (*ef->allocate_cb)(sizeof(struct elf_section) * ef->shnum);
- if (ef->sections == NULL)
- return ELF_ERR_NOMEM;
-
- /* Read the section header table */
- for (i = 0; i < ef->shnum; i++) {
-
- sect = &ef->sections[i];
-
- /* Read the next section header */
- if (fread((char *)&header, ef->shentsize, 1, ef->fd) != 1) {
- (*ef->free_cb)(ef->sections);
- return ELF_ERR_READ_SECTHDR;
- }
-
- /* Get fields from appropriate structure */
- if (ef->source_class == ELFCLASS32) {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf32_shdr);
- sect->type = header.hdr32.sh_type;
- sect->flags = header.hdr32.sh_flags;
- sect->addr = header.hdr32.sh_addr;
- sect->offset = header.hdr32.sh_offset;
- sect->size = header.hdr32.sh_size;
- sect->link = header.hdr32.sh_link;
- sect->info = header.hdr32.sh_info;
- sect->entsize = header.hdr32.sh_entsize;
- }
- else {
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header, template_elf64_shdr);
- sect->type = header.hdr64.sh_type;
- sect->flags = header.hdr64.sh_flags;
- sect->addr = header.hdr64.sh_addr;
- sect->offset = header.hdr64.sh_offset;
- sect->size = header.hdr64.sh_size;
- sect->link = header.hdr64.sh_link;
- sect->info = header.hdr64.sh_info;
- sect->entsize = header.hdr64.sh_entsize;
- }
- sect->contents = NULL;
- sect->symbols = NULL;
- if (sect->entsize > 0)
- sect->nelems = sect->size / sect->entsize;
-
- }
-
- return 0;
-}
-
-
-static char template_elf32_ehdr[] = {2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 0};
-static char template_elf64_ehdr[] = {2, 2, 4, 8, 8, 8, 4, 2, 2, 2, 2, 2, 2, 0};
-
-static int elf_read_header(struct elf_file *ef)
-{
- union {
- char ident[EI_NIDENT];
- Elf32_Ehdr hdr32;
- Elf64_Ehdr hdr64;
- } header;
-
- /* Read the ELF header */
- fseek(ef->fd, 0L, SEEK_SET);
- if (fread((char *)header.ident, EI_NIDENT, 1, ef->fd) != 1) {
- return ELF_ERR_NOHEADER;
- }
-
- /* Verify that this is an ELF file */
- if (header.ident[EI_MAG0] != ELFMAG0 ||
- header.ident[EI_MAG1] != ELFMAG1 ||
- header.ident[EI_MAG2] != ELFMAG2 ||
- header.ident[EI_MAG3] != ELFMAG3) {
- return ELF_ERR_NOTELF;
- }
-
- /* Get header fields from the byte array e_ident */
- /* (These are independent of EI_CLASS and EI_DATA) */
- ef->source_class = header.ident[EI_CLASS];
- ef->source_data = header.ident[EI_DATA];
-
- /* Verify EI_CLASS and EI_DATA */
- if (header.ident[EI_CLASS] != ELFCLASS32 &&
- header.ident[EI_CLASS] != ELFCLASS64) {
- return ELF_ERR_INVALID_CLASS;
- }
- if (header.ident[EI_DATA] != ELFDATA2LSB &&
- header.ident[EI_DATA] != ELFDATA2MSB) {
- return ELF_ERR_INVALID_DATA;
- }
-
- /* Get remaining header fields from appropriate structure */
- if (ef->source_class == ELFCLASS32) {
- if (fread((char *)&header.hdr32 + EI_NIDENT,
- sizeof(header.hdr32) - EI_NIDENT, 1, ef->fd) != 1)
- return ELF_ERR_NOHEADER;
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header + EI_NIDENT, template_elf32_ehdr);
- ef->phoff = header.hdr32.e_phoff;
- ef->shoff = header.hdr32.e_shoff;
- ef->ehsize = header.hdr32.e_ehsize;
- ef->phentsize = header.hdr32.e_phentsize;
- ef->phnum = header.hdr32.e_phnum;
- ef->shentsize = header.hdr32.e_shentsize;
- ef->shnum = header.hdr32.e_shnum;
- if (ef->ehsize != sizeof(header.hdr32)) {
- return ELF_ERR_HEADER_SIZE;
- }
- }
- else {
- if (fread((char *)&header.hdr64 + EI_NIDENT,
- sizeof(header.hdr64) - EI_NIDENT, 1, ef->fd) != 1)
- return ELF_ERR_NOHEADER;
- /* Swap bytes in header fields if necessary */
- if (ef->source_data != ef->native_data)
- elf_swap_bytes((char *)&header + EI_NIDENT, template_elf64_ehdr);
- ef->phoff = header.hdr64.e_phoff;
- ef->shoff = header.hdr64.e_shoff;
- ef->ehsize = header.hdr64.e_ehsize;
- ef->phentsize = header.hdr64.e_phentsize;
- ef->phnum = header.hdr64.e_phnum;
- ef->shentsize = header.hdr64.e_shentsize;
- ef->shnum = header.hdr64.e_shnum;
- if (ef->ehsize != sizeof(header.hdr64)) {
- return ELF_ERR_HEADER_SIZE;
- }
- }
-
- return 0;
-}
-
-
-static struct elf_file *elf_new(struct uwx_env *env)
-{
- int native_be;
- char *p;
- struct elf_file *ef;
-
- ef = (struct elf_file *)(*env->allocate_cb)(sizeof(struct elf_file));
- if (ef == NULL)
- return NULL;
-
- /* Determine the native byte order */
- p = (char *)&native_be;
- native_be = 1; /* Assume big-endian */
- *p = 0; /* Sets be == 0 only if little-endian */
-
- ef->allocate_cb = env->allocate_cb;
- ef->free_cb = env->free_cb;
- ef->filename = NULL;
- ef->native_data = (native_be ? ELFDATA2MSB : ELFDATA2LSB);
- ef->fd = NULL;
- ef->source_class = 0;
- ef->source_data = 0;
- ef->phoff = 0;
- ef->shoff = 0;
- ef->text_base = 0;
- ef->text_end = 0;
- ef->ehsize = 0;
- ef->phentsize = 0;
- ef->phnum = 0;
- ef->shentsize = 0;
- ef->shnum = 0;
- ef->sections = NULL;
- ef->symbols = NULL;
- ef->symbol_strings = NULL;
- ef->nsyms = 0;
- return ef;
-}
-
-
-static int elf_open(struct elf_file *ef, const char *filename)
-{
- int err;
-
- ef->filename = filename;
-
- ef->fd = fopen(filename, "r");
- if (ef->fd == NULL)
- return ELF_ERR_OPEN;
-
- if ((err = elf_read_header(ef)) != 0)
- return err;
-
- if ((err = elf_read_sect_hdrs(ef)) != 0)
- return err;
-
- if ((err = elf_read_prog_hdrs(ef)) != 0)
- return err;
-
- return 0;
-}
-
-
-static void elf_free_sections(struct elf_file *ef)
-{
- int i;
- struct elf_section *sect;
-
- for (i = 0; i < ef->shnum; i++) {
- sect = &ef->sections[i];
- if (sect->contents != NULL)
- (*ef->free_cb)(sect->contents);
- if ((sect->type == SHT_SYMTAB || sect->type == SHT_DYNSYM)
- && sect->symbols != NULL)
- (*ef->free_cb)(sect->symbols);
- }
- (*ef->free_cb)(ef->sections);
-}
-
-
-static void elf_close(struct elf_file *ef)
-{
- if (ef->fd != NULL) {
- fclose(ef->fd);
- ef->fd = NULL;
- }
-}
-
-
-static void elf_free(struct elf_file *ef)
-{
- elf_close(ef);
- if (ef->sections != NULL)
- elf_free_sections(ef);
- (*ef->free_cb)(ef);
-}
-
-
-static int elf_read_symbols(struct elf_file *ef)
-{
- int i;
- int err;
- struct elf_section *sect;
-
- for (i = 1; i < ef->shnum; i++) {
- sect = &ef->sections[i];
- if (sect->type == SHT_SYMTAB) {
- if (elf_read_symtab_section(ef, i) == 0) {
- ef->symbols = sect->symbols;
- ef->nsyms = sect->nelems;
-#ifdef DEBUG_SYMBOLS
- printf("Read %d symbols from SHT_SYMTAB section\n", ef->nsyms);
-#endif /* DEBUG_SYMBOLS */
- return 0;
- }
- }
- }
- for (i = 1; i < ef->shnum; i++) {
- sect = &ef->sections[i];
- if (sect->type == SHT_DYNSYM) {
- if (elf_read_symtab_section(ef, i) == 0) {
- ef->symbols = sect->symbols;
- ef->nsyms = sect->nelems;
-#ifdef DEBUG_SYMBOLS
- printf("Read %d symbols from SHT_DYNSYM section\n", ef->nsyms);
-#endif /* DEBUG_SYMBOLS */
- return 0;
- }
- }
- }
- return UWX_ERR_NOSYM;
-}
-
-
-#define SYM_IS_DEFINED(sym) \
- ((sym)->shndx != SHN_UNDEF)
-
-#define SYM_IS_IN_TEXT_SEGMENT(value) \
- ((value) >= ef->text_base && (value) < ef->text_end)
-
-#define SYM_HAS_INTERESTING_TYPE(type) ( \
- (type) == STT_FUNC || \
- (type) == STT_OBJECT || \
- (type) == STT_HP_STUB \
- )
-
-#define SYM_IS_INTERESTING(sym) ( \
- SYM_IS_DEFINED(sym) && \
- SYM_IS_IN_TEXT_SEGMENT((sym)->value) && \
- SYM_HAS_INTERESTING_TYPE((sym)->type) \
- )
-
-int uwx_read_func_symbols(
- struct uwx_env *env,
- struct uwx_symbol_cache *cache,
- char *module_name)
-{
- int i, j;
- int status;
- struct elf_file *ef;
- struct elf_symbol *sym;
- int nfuncsyms;
- char **names;
- uint64_t *values;
-
- if (module_name != NULL &&
- cache->module_name != NULL &&
- strcmp(module_name, cache->module_name) == 0)
- return UWX_OK;
-
- if (cache->sym_names != NULL)
- (*env->free_cb)(cache->sym_names);
- if (cache->sym_values != NULL)
- (*env->free_cb)(cache->sym_values);
- if (cache->strings != NULL)
- (*env->free_cb)(cache->strings);
-
- ef = elf_new(env);
- if (ef == NULL)
- return UWX_ERR_NOMEM;
- status = elf_open(ef, module_name);
- if (status != 0)
- return UWX_ERR_NOSYM;
- status = elf_read_symbols(ef);
- if (status != 0)
- return UWX_ERR_NOSYM;
-
- nfuncsyms = 0;
- for (i = 0; i < ef->nsyms; i++) {
- sym = &ef->symbols[i];
- if (SYM_IS_INTERESTING(sym))
- nfuncsyms++;
- }
-
- names = (char **)(*env->allocate_cb)(nfuncsyms * sizeof(char *));
- if (names == NULL)
- return UWX_ERR_NOMEM;
- values = (uint64_t *)(*env->allocate_cb)(nfuncsyms * sizeof(uint64_t));
- if (values == NULL)
- return UWX_ERR_NOMEM;
-
- j = 0;
- for (i = 0; i < ef->nsyms; i++) {
- sym = &ef->symbols[i];
- if (SYM_IS_INTERESTING(sym)) {
- if (j >= nfuncsyms) /* should not happen! */
- break;
- names[j] = sym->namep;
- values[j] = sym->value - ef->text_base;
- j++;
- }
- }
-
- cache->module_name = (char *)(*env->allocate_cb)(strlen(module_name)+1);
- if (cache->module_name != NULL) {
- strcpy(cache->module_name, module_name);
- cache->nsyms = nfuncsyms;
- cache->sym_names = names;
- cache->sym_values = values;
- cache->strings = ef->symbol_strings;
- ef->symbol_strings = NULL;
- }
-
- elf_close(ef);
- elf_free(ef);
-
-#ifdef DEBUG_SYMBOLS
- printf("Cached %d interesting symbols\n", nfuncsyms);
-#endif /* DEBUG_SYMBOLS */
-
- return UWX_OK;
-}
OpenPOWER on IntegriCloud