Some fixes...
* read_config_file.c: initialise pt stack argument to stop warning
* summary.c: make show_summary() obey -C for demangaling function names
diff --git a/elf.c b/elf.c
index 1d37eb9..4f543d7 100644
--- a/elf.c
+++ b/elf.c
@@ -16,322 +16,320 @@
#include "elf.h"
#include "debug.h"
-static void do_init_elf (struct ltelf *lte, const char *filename);
-static void do_close_elf (struct ltelf *lte);
-static void add_library_symbol (GElf_Addr addr, const char *name,
- struct library_symbol **library_symbolspp);
-static int in_load_libraries (const char *name, struct ltelf *lte);
+static void do_init_elf(struct ltelf *lte, const char *filename);
+static void do_close_elf(struct ltelf *lte);
+static void add_library_symbol(GElf_Addr addr, const char *name,
+ struct library_symbol **library_symbolspp);
+static int in_load_libraries(const char *name, struct ltelf *lte);
-static void
-do_init_elf (struct ltelf *lte, const char *filename)
+static void do_init_elf(struct ltelf *lte, const char *filename)
{
- int i;
- GElf_Addr relplt_addr = 0;
- size_t relplt_size = 0;
+ int i;
+ GElf_Addr relplt_addr = 0;
+ size_t relplt_size = 0;
- debug (1, "Reading ELF from %s...", filename);
+ debug(1, "Reading ELF from %s...", filename);
- memset (lte, 0, sizeof (*lte));
- lte->fd = open (filename, O_RDONLY);
- if (lte->fd == -1)
- error (EXIT_FAILURE, errno, "Can't open \"%s\"", filename);
+ memset(lte, 0, sizeof(*lte));
+ lte->fd = open(filename, O_RDONLY);
+ if (lte->fd == -1)
+ error(EXIT_FAILURE, errno, "Can't open \"%s\"", filename);
#ifdef HAVE_ELF_C_READ_MMAP
- lte->elf = elf_begin (lte->fd, ELF_C_READ_MMAP, NULL);
+ lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
#else
- lte->elf = elf_begin (lte->fd, ELF_C_READ, NULL);
+ lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
#endif
- if (lte->elf == NULL || elf_kind (lte->elf) != ELF_K_ELF)
- error (EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
+ if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF)
+ error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
- if (gelf_getehdr (lte->elf, <e->ehdr) == NULL)
- error (EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"", filename);
+ if (gelf_getehdr(lte->elf, <e->ehdr) == NULL)
+ error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"",
+ filename);
- if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
- error (EXIT_FAILURE, 0, "\"%s\" is not an ELF executable nor shared library",
- filename);
+ if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
+ error(EXIT_FAILURE, 0,
+ "\"%s\" is not an ELF executable nor shared library",
+ filename);
- if (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
- || (lte->ehdr.e_machine != LT_ELF_MACHINE
+ if (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
+ || (lte->ehdr.e_machine != LT_ELF_MACHINE
#ifdef LT_ELF_MACHINE2
- && lte->ehdr.e_machine != LT_ELF_MACHINE2
+ && lte->ehdr.e_machine != LT_ELF_MACHINE2
#endif
#ifdef LT_ELF_MACHINE3
- && lte->ehdr.e_machine != LT_ELF_MACHINE3
+ && lte->ehdr.e_machine != LT_ELF_MACHINE3
#endif
- ))
- error (EXIT_FAILURE, 0, "\"%s\" is ELF from incompatible architecture",
- filename);
+ ))
+ error(EXIT_FAILURE, 0,
+ "\"%s\" is ELF from incompatible architecture", filename);
- for (i = 1; i < lte->ehdr.e_shnum; ++i)
- {
- Elf_Scn *scn;
- GElf_Shdr shdr;
- const char *name;
+ for (i = 1; i < lte->ehdr.e_shnum; ++i) {
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ const char *name;
- scn = elf_getscn (lte->elf, i);
- if (scn == NULL || gelf_getshdr (scn, &shdr) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get section header from \"%s\"",
- filename);
+ scn = elf_getscn(lte->elf, i);
+ if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get section header from \"%s\"",
+ filename);
- name = elf_strptr (lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
- if (name == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get section header from \"%s\"",
- filename);
+ name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
+ if (name == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get section header from \"%s\"",
+ filename);
- if (shdr.sh_type == SHT_DYNSYM)
- {
- Elf_Data *data;
+ if (shdr.sh_type == SHT_DYNSYM) {
+ Elf_Data *data;
- lte->dynsym = elf_getdata (scn, NULL);
- lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
- if (lte->dynsym == NULL || elf_getdata (scn, lte->dynsym) != NULL)
- error (EXIT_FAILURE, 0, "Couldn't get .dynsym data from \"%s\"",
- filename);
+ lte->dynsym = elf_getdata(scn, NULL);
+ lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
+ if (lte->dynsym == NULL
+ || elf_getdata(scn, lte->dynsym) != NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .dynsym data from \"%s\"",
+ filename);
- scn = elf_getscn (lte->elf, shdr.sh_link);
- if (scn == NULL || gelf_getshdr (scn, &shdr) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get section header from \"%s\"",
- filename);
+ scn = elf_getscn(lte->elf, shdr.sh_link);
+ if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get section header from \"%s\"",
+ filename);
- data = elf_getdata (scn, NULL);
- if (data == NULL || elf_getdata (scn, data) != NULL
- || shdr.sh_size != data->d_size || data->d_off)
- error (EXIT_FAILURE, 0, "Couldn't get .dynstr data from \"%s\"",
- filename);
+ data = elf_getdata(scn, NULL);
+ if (data == NULL || elf_getdata(scn, data) != NULL
+ || shdr.sh_size != data->d_size || data->d_off)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .dynstr data from \"%s\"",
+ filename);
- lte->dynstr = data->d_buf;
- }
- else if (shdr.sh_type == SHT_DYNAMIC)
- {
- Elf_Data *data;
- size_t j;
+ lte->dynstr = data->d_buf;
+ } else if (shdr.sh_type == SHT_DYNAMIC) {
+ Elf_Data *data;
+ size_t j;
- data = elf_getdata (scn, NULL);
- if (data == NULL || elf_getdata (scn, data) != NULL)
- error (EXIT_FAILURE, 0, "Couldn't get .dynamic data from \"%s\"",
- filename);
+ data = elf_getdata(scn, NULL);
+ if (data == NULL || elf_getdata(scn, data) != NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .dynamic data from \"%s\"",
+ filename);
- for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j)
- {
- GElf_Dyn dyn;
+ for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
+ GElf_Dyn dyn;
- if (gelf_getdyn (data, j, &dyn) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get .dynamic data from \"%s\"",
- filename);
+ if (gelf_getdyn(data, j, &dyn) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .dynamic data from \"%s\"",
+ filename);
- if (dyn.d_tag == DT_JMPREL)
- relplt_addr = dyn.d_un.d_ptr;
- else if (dyn.d_tag == DT_PLTRELSZ)
- relplt_size = dyn.d_un.d_val;
- }
- }
- else if (shdr.sh_type == SHT_HASH)
- {
- Elf_Data *data;
- size_t j;
+ if (dyn.d_tag == DT_JMPREL)
+ relplt_addr = dyn.d_un.d_ptr;
+ else if (dyn.d_tag == DT_PLTRELSZ)
+ relplt_size = dyn.d_un.d_val;
+ }
+ } else if (shdr.sh_type == SHT_HASH) {
+ Elf_Data *data;
+ size_t j;
- data = elf_getdata (scn, NULL);
- if (data == NULL || elf_getdata (scn, data) != NULL
- || data->d_off || data->d_size != shdr.sh_size)
- error (EXIT_FAILURE, 0, "Couldn't get .hash data from \"%s\"",
- filename);
+ data = elf_getdata(scn, NULL);
+ if (data == NULL || elf_getdata(scn, data) != NULL
+ || data->d_off || data->d_size != shdr.sh_size)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .hash data from \"%s\"",
+ filename);
- if (shdr.sh_entsize == 4)
- {
- /* Standard conforming ELF. */
- if (data->d_type != ELF_T_WORD)
- error (EXIT_FAILURE, 0, "Couldn't get .hash data from \"%s\"",
- filename);
- lte->hash = (Elf32_Word *) data->d_buf;
- }
- else if (shdr.sh_entsize == 8)
- {
- /* Alpha or s390x. */
- Elf32_Word *dst, *src;
- size_t hash_count = data->d_size / 8;
+ if (shdr.sh_entsize == 4) {
+ /* Standard conforming ELF. */
+ if (data->d_type != ELF_T_WORD)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .hash data from \"%s\"",
+ filename);
+ lte->hash = (Elf32_Word *) data->d_buf;
+ } else if (shdr.sh_entsize == 8) {
+ /* Alpha or s390x. */
+ Elf32_Word *dst, *src;
+ size_t hash_count = data->d_size / 8;
- lte->hash = (Elf32_Word *)
- malloc (hash_count * sizeof (Elf32_Word));
- if (lte->hash == NULL)
- error (EXIT_FAILURE, 0, "Couldn't convert .hash section from \"%s\"",
- filename);
- lte->hash_malloced = 1;
- dst = lte->hash;
- src = (Elf32_Word *) data->d_buf;
- if ((data->d_type == ELF_T_WORD && __BYTE_ORDER == __BIG_ENDIAN)
- || (data->d_type == ELF_T_XWORD
- && lte->ehdr.e_ident[EI_DATA] == ELFDATA2MSB))
- ++src;
- for (j = 0; j < hash_count; ++j, src += 2)
- *dst++ = *src;
- }
- else
- error (EXIT_FAILURE, 0, "Unknown .hash sh_entsize in \"%s\"",
- filename);
- }
- else if ((shdr.sh_type == SHT_PROGBITS || shdr.sh_type == SHT_NOBITS)
- && strcmp (name, ".plt") == 0)
- lte->plt_addr = shdr.sh_addr;
- }
-
- if (lte->dynsym == NULL || lte->dynstr == NULL)
- error (EXIT_FAILURE, 0, "Couldn't find .dynsym or .dynstr in \"%s\"",
- filename);
-
- if (!relplt_addr || !lte->plt_addr)
- {
- debug (1, "%s has no PLT relocations", filename);
- lte->relplt = NULL;
- lte->relplt_count = 0;
- }
- else
- {
- for (i = 1; i < lte->ehdr.e_shnum; ++i)
- {
- Elf_Scn *scn;
- GElf_Shdr shdr;
-
- scn = elf_getscn (lte->elf, i);
- if (scn == NULL || gelf_getshdr (scn, &shdr) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get section header from \"%s\"",
- filename);
- if (shdr.sh_addr == relplt_addr && shdr.sh_size == relplt_size)
- {
- lte->relplt = elf_getdata (scn, NULL);
- lte->relplt_count = shdr.sh_size / shdr.sh_entsize;
- if (lte->relplt == NULL
- || elf_getdata (scn, lte->relplt) != NULL)
- error (EXIT_FAILURE, 0, "Couldn't get .rel*.plt data from \"%s\"",
- filename);
- break;
- }
+ lte->hash = (Elf32_Word *)
+ malloc(hash_count * sizeof(Elf32_Word));
+ if (lte->hash == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't convert .hash section from \"%s\"",
+ filename);
+ lte->hash_malloced = 1;
+ dst = lte->hash;
+ src = (Elf32_Word *) data->d_buf;
+ if ((data->d_type == ELF_T_WORD
+ && __BYTE_ORDER == __BIG_ENDIAN)
+ || (data->d_type == ELF_T_XWORD
+ && lte->ehdr.e_ident[EI_DATA] ==
+ ELFDATA2MSB))
+ ++src;
+ for (j = 0; j < hash_count; ++j, src += 2)
+ *dst++ = *src;
+ } else
+ error(EXIT_FAILURE, 0,
+ "Unknown .hash sh_entsize in \"%s\"",
+ filename);
+ } else
+ if ((shdr.sh_type == SHT_PROGBITS
+ || shdr.sh_type == SHT_NOBITS)
+ && strcmp(name, ".plt") == 0)
+ lte->plt_addr = shdr.sh_addr;
}
- if (i == lte->ehdr.e_shnum)
- error (EXIT_FAILURE, 0, "Couldn't find .rel*.plt section in \"%s\"",
- filename);
+ if (lte->dynsym == NULL || lte->dynstr == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
- debug (1, "%s %zd PLT relocations", filename, lte->relplt_count);
- }
+ if (!relplt_addr || !lte->plt_addr) {
+ debug(1, "%s has no PLT relocations", filename);
+ lte->relplt = NULL;
+ lte->relplt_count = 0;
+ } else {
+ for (i = 1; i < lte->ehdr.e_shnum; ++i) {
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+
+ scn = elf_getscn(lte->elf, i);
+ if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get section header from \"%s\"",
+ filename);
+ if (shdr.sh_addr == relplt_addr
+ && shdr.sh_size == relplt_size) {
+ lte->relplt = elf_getdata(scn, NULL);
+ lte->relplt_count =
+ shdr.sh_size / shdr.sh_entsize;
+ if (lte->relplt == NULL
+ || elf_getdata(scn, lte->relplt) != NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get .rel*.plt data from \"%s\"",
+ filename);
+ break;
+ }
+ }
+
+ if (i == lte->ehdr.e_shnum)
+ error(EXIT_FAILURE, 0,
+ "Couldn't find .rel*.plt section in \"%s\"",
+ filename);
+
+ debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
+ }
+}
+
+static void do_close_elf(struct ltelf *lte)
+{
+ if (lte->hash_malloced)
+ free((char *)lte->hash);
+ elf_end(lte->elf);
+ close(lte->fd);
}
static void
-do_close_elf (struct ltelf *lte)
+add_library_symbol(GElf_Addr addr, const char *name,
+ struct library_symbol **library_symbolspp)
{
- if (lte->hash_malloced)
- free ((char *) lte->hash);
- elf_end (lte->elf);
- close (lte->fd);
+ struct library_symbol *s;
+ s = malloc(sizeof(struct library_symbol) + strlen(name) + 1);
+ if (s == NULL)
+ error(EXIT_FAILURE, errno, "add_library_symbol failed");
+
+ s->next = *library_symbolspp;
+ s->enter_addr = (void *)(uintptr_t) addr;
+ s->name = (char *)(s + 1);
+ strcpy(s->name, name);
+ *library_symbolspp = s;
+
+ debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name);
}
-static void
-add_library_symbol (GElf_Addr addr, const char *name,
- struct library_symbol **library_symbolspp)
+static int in_load_libraries(const char *name, struct ltelf *lte)
{
- struct library_symbol *s;
- s = malloc (sizeof (struct library_symbol) + strlen (name) + 1);
- if (s == NULL)
- error (EXIT_FAILURE, errno, "add_library_symbol failed");
+ size_t i;
+ unsigned long hash;
- s->next = *library_symbolspp;
- s->enter_addr = (void *) (uintptr_t) addr;
- s->name = (char *) (s + 1);
- strcpy (s->name, name);
- *library_symbolspp = s;
+ if (!library_num)
+ return 1;
- debug (2, "addr: %p, symbol: \"%s\"", (void *) (uintptr_t) addr, name);
+ hash = elf_hash(name);
+ for (i = 1; i <= library_num; ++i) {
+ Elf32_Word nbuckets, symndx;
+ Elf32_Word *buckets, *chain;
+
+ if (lte[i].hash == NULL)
+ continue;
+
+ nbuckets = lte[i].hash[0];
+ buckets = <e[i].hash[2];
+ chain = <e[i].hash[2 + nbuckets];
+ for (symndx = buckets[hash % nbuckets];
+ symndx != STN_UNDEF; symndx = chain[symndx]) {
+ GElf_Sym sym;
+
+ if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get symbol from .dynsym");
+
+ if (sym.st_value != 0
+ && sym.st_shndx != SHN_UNDEF
+ && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
+ return 1;
+ }
+ }
+ return 0;
}
-static int
-in_load_libraries (const char *name, struct ltelf *lte)
+struct library_symbol *read_elf(const char *filename)
{
- size_t i;
- unsigned long hash;
+ struct library_symbol *library_symbols = NULL;
+ struct ltelf lte[MAX_LIBRARY + 1];
+ size_t i;
- if (!library_num)
- return 1;
+ elf_version(EV_CURRENT);
- hash = elf_hash (name);
- for (i = 1; i <= library_num; ++i)
- {
- Elf32_Word nbuckets, symndx;
- Elf32_Word *buckets, *chain;
+ do_init_elf(lte, filename);
+ for (i = 0; i < library_num; ++i)
+ do_init_elf(<e[i + 1], library[i]);
- if (lte[i].hash == NULL)
- continue;
+ for (i = 0; i < lte->relplt_count; ++i) {
+ GElf_Rel rel;
+ GElf_Rela rela;
+ GElf_Sym sym;
+ GElf_Addr addr;
+ void *ret;
+ const char *name;
- nbuckets = lte[i].hash[0];
- buckets = <e[i].hash[2];
- chain = <e[i].hash[2 + nbuckets];
- for (symndx = buckets[hash % nbuckets];
- symndx != STN_UNDEF;
- symndx = chain[symndx])
- {
- GElf_Sym sym;
+ if (lte->relplt->d_type == ELF_T_REL) {
+ ret = gelf_getrel(lte->relplt, i, &rel);
+ rela.r_offset = rel.r_offset;
+ rela.r_info = rel.r_info;
+ rela.r_addend = 0;
+ } else
+ ret = gelf_getrela(lte->relplt, i, &rela);
- if (gelf_getsym (lte[i].dynsym, symndx, &sym) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get symbol from .dynsym");
+ if (ret == NULL
+ || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
+ || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
+ &sym) == NULL)
+ error(EXIT_FAILURE, 0,
+ "Couldn't get relocation from \"%s\"", filename);
- if (sym.st_value != 0
- && sym.st_shndx != SHN_UNDEF
- && strcmp (name, lte[i].dynstr + sym.st_name) == 0)
- return 1;
+ name = lte->dynstr + sym.st_name;
+ if (in_load_libraries(name, lte)) {
+ addr = arch_plt_sym_val(lte, i, &rela);
+ if (addr != 0)
+ add_library_symbol(addr, name,
+ &library_symbols);
+ }
}
- }
- return 0;
-}
-struct library_symbol *
-read_elf (const char *filename)
-{
- struct library_symbol *library_symbols = NULL;
- struct ltelf lte[MAX_LIBRARY + 1];
- size_t i;
+ for (i = 0; i < library_num + 1; ++i)
+ do_close_elf(<e[i]);
- elf_version (EV_CURRENT);
-
- do_init_elf (lte, filename);
- for (i = 0; i < library_num; ++i)
- do_init_elf (<e[i + 1], library[i]);
-
- for (i = 0; i < lte->relplt_count; ++i)
- {
- GElf_Rel rel;
- GElf_Rela rela;
- GElf_Sym sym;
- GElf_Addr addr;
- void *ret;
- const char *name;
-
- if (lte->relplt->d_type == ELF_T_REL)
- {
- ret = gelf_getrel (lte->relplt, i, &rel);
- rela.r_offset = rel.r_offset;
- rela.r_info = rel.r_info;
- rela.r_addend = 0;
- }
- else
- ret = gelf_getrela (lte->relplt, i, &rela);
-
- if (ret == NULL
- || ELF64_R_SYM (rela.r_info) >= lte->dynsym_count
- || gelf_getsym (lte->dynsym, ELF64_R_SYM (rela.r_info), &sym) == NULL)
- error (EXIT_FAILURE, 0, "Couldn't get relocation from \"%s\"",
- filename);
-
- name = lte->dynstr + sym.st_name;
- if (in_load_libraries (name, lte))
- {
- addr = arch_plt_sym_val (lte, i, &rela);
- if (addr != 0)
- add_library_symbol (addr, name, &library_symbols);
- }
- }
-
- for (i = 0; i < library_num + 1; ++i)
- do_close_elf (<e[i]);
-
- return library_symbols;
+ return library_symbols;
}