Elementary support for -x
- this is applied across libraries. Syntax for the -x option is the same
as for -e
- this fails on symbol aliases. E.g. there are several symbols named like
strlen in libc: strlen, __GI_strlen, and perhaps others. This needs to
be taken into account, and symbol aliases shouldn't be enabled if
they were added under a different name already
diff --git a/ltrace-elf.c b/ltrace-elf.c
index 5d01581..69f3075 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -297,7 +297,7 @@
lte->symtab_count = shdr.sh_size / shdr.sh_entsize;
if ((lte->symtab == NULL
|| elf_getdata(scn, lte->symtab) != NULL)
- && opt_x != NULL)
+ && options.static_filter != NULL)
error(EXIT_FAILURE, 0,
"Couldn't get .symtab data from \"%s\"",
filename);
@@ -507,11 +507,74 @@
return 0;
}
+static int
+populate_this_symtab(struct Process *proc, const char *filename,
+ struct ltelf *lte, struct library *lib,
+ Elf_Data *symtab, const char *strtab, size_t size)
+{
+ size_t lib_len = strlen(lib->soname);
+ size_t i;
+ for (i = 0; i < size; ++i) {
+ GElf_Sym sym;
+ if (gelf_getsym(lte->symtab, i, &sym) == NULL) {
+ fail:
+ error(0, errno, "couldn't get symbol #%zd from %s: %s",
+ i, filename, elf_errmsg(-1));
+ continue;
+ }
+
+ if (sym.st_value == 0)
+ continue;
+
+ const char *name = strtab + sym.st_name;
+ if (!filter_matches_symbol(options.static_filter, name, lib))
+ continue;
+ fprintf(stderr, "%s@%s matches\n", name, lib->soname);
+
+ char *full_name = malloc(strlen(name) + 1 + lib_len + 1);
+ if (full_name == NULL)
+ goto fail;
+ sprintf(full_name, "%s@%s", name, lib->soname);
+
+ target_address_t addr
+ = (target_address_t)(sym.st_value + lte->bias);
+ target_address_t naddr;
+ if (arch_translate_address(proc, addr, &naddr) < 0) {
+ error(0, errno, "couldn't translate address of %s@%s",
+ name, lib->soname);
+ continue;
+ }
+ if (addr != naddr)
+ naddr += lte->bias;
+
+ struct library_symbol *libsym = malloc(sizeof(*libsym));
+ if (libsym == NULL)
+ goto fail;
+
+ library_symbol_init(libsym, naddr, full_name, 1, LS_TOPLT_NONE);
+ library_add_symbol(lib, libsym);
+ }
+ return 0;
+}
+
+static int
+populate_symtab(struct Process *proc, const char *filename,
+ struct ltelf *lte, struct library *lib)
+{
+ if (lte->symtab != NULL && lte->strtab != NULL)
+ return populate_this_symtab(proc, filename, lte, lib,
+ lte->symtab, lte->strtab,
+ lte->symtab_count);
+ else
+ return populate_this_symtab(proc, filename, lte, lib,
+ lte->dynsym, lte->dynstr,
+ lte->dynsym_count);
+}
+
int
ltelf_read_library(struct library *lib, struct Process *proc,
const char *filename, GElf_Addr bias)
{
- // XXX we leak LTE contents
struct ltelf lte = {};
if (do_init_elf(<e, filename, bias) < 0)
return -1;
@@ -553,6 +616,10 @@
&& populate_plt(proc, filename, <e, lib) < 0)
goto fail;
+ if (filter_matches_library(options.static_filter, lib)
+ && populate_symtab(proc, filename, <e, lib) < 0)
+ goto fail;
+
done:
do_close_elf(<e);
return status;