Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:GA
ltrace
ltrace-ppc64le_git7.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ltrace-ppc64le_git7.patch of Package ltrace
--- ltrace-elf.c.ori +++ ltrace-elf.c @@ -599,6 +599,24 @@ mark_chain_latent(struct library_symbol *libsym) } } +static void +filter_symbol_chain(struct filter *filter, + struct library_symbol **libsymp, struct library *lib) +{ + assert(libsymp != NULL); + struct library_symbol **ptr = libsymp; + while (*ptr != NULL) { + if (filter_matches_symbol(filter, (*ptr)->name, lib)) { + ptr = &(*ptr)->next; + } else { + struct library_symbol *sym = *ptr; + *ptr = (*ptr)->next; + library_symbol_destroy(sym); + free(sym); + } + } +} + static int populate_plt(struct Process *proc, const char *filename, struct ltelf *lte, struct library *lib, @@ -614,30 +632,36 @@ populate_plt(struct Process *proc, const char *filename, char const *name = lte->dynstr + sym.st_name; - /* If the symbol wasn't matched, reject it, unless we - * need to keep latent PLT breakpoints for tracing - * exports. */ int matched = filter_matches_symbol(options.plt_filter, name, lib); - if (!matched && !latent_plts) - continue; struct library_symbol *libsym = NULL; switch (arch_elf_add_plt_entry(proc, lte, name, &rela, i, &libsym)) { + case plt_fail: + return -1; + case plt_default: + /* Add default entry to the beginning of LIBSYM. */ if (default_elf_add_plt_entry(proc, lte, name, &rela, i, &libsym) < 0) - /* fall-through */ - case plt_fail: return -1; /* fall-through */ case plt_ok: + /* If we didn't match the PLT entry up there, + * filter the chain to only include the + * matching symbols (but include all if we are + * adding latent symbols). This is to allow + * arch_elf_add_plt_entry to override the PLT + * symbol's name. */ + if (!matched && !latent_plts) + filter_symbol_chain(options.plt_filter, + &libsym, lib); if (libsym != NULL) { /* If we are adding those symbols just * for tracing exports, mark them all * latent. */ - if (!matched) + if (!matched && latent_plts) mark_chain_latent(libsym); library_add_symbol(lib, libsym); } @@ -717,7 +741,6 @@ populate_this_symtab(struct Process *proc, const char *filename, continue; } - /* XXX support IFUNC as well. */ if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_value == 0 || sym.st_shndx == STN_UNDEF) --- sysdeps/linux-gnu/trace.c.ori +++ sysdeps/linux-gnu/trace.c @@ -24,25 +24,28 @@ #include "config.h" #include <asm/unistd.h> -#include <sys/types.h> -#include <sys/wait.h> #include <assert.h> #include <errno.h> +#include <gelf.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #ifdef HAVE_LIBSELINUX # include <selinux/selinux.h> #endif -#include "linux-gnu/trace.h" #include "linux-gnu/trace-defs.h" +#include "linux-gnu/trace.h" #include "backend.h" #include "breakpoint.h" #include "debug.h" #include "events.h" +#include "ltrace-elf.h" #include "options.h" #include "proc.h" #include "ptrace.h" @@ -1208,3 +1211,61 @@ umovebytes(struct Process *proc, void *addr, void *laddr, size_t len) return bytes_read; } + +struct irelative_name_data_t { + GElf_Addr addr; + const char *found_name; +}; + +static enum callback_status +irelative_name_cb(GElf_Sym *symbol, const char *name, void *d) +{ + struct irelative_name_data_t *data = d; + + if (symbol->st_value == data->addr) { + bool is_ifunc = false; +#ifdef STT_GNU_IFUNC + is_ifunc = GELF_ST_TYPE(symbol->st_info) == STT_GNU_IFUNC; +#endif + data->found_name = name; + + /* Keep looking, unless we found the actual IFUNC + * symbol. What we matched may have been a symbol + * denoting the resolver function, which would have + * the same address. */ + return CBS_STOP_IF(is_ifunc); + } + + return CBS_CONT; +} + +enum plt_status +linux_elf_add_plt_entry_irelative(struct Process *proc, struct ltelf *lte, + GElf_Rela *rela, size_t ndx, + struct library_symbol **ret) + +{ + struct irelative_name_data_t data = { rela->r_addend, NULL }; + if (rela->r_addend != 0 + && elf_each_symbol(lte, 0, + irelative_name_cb, &data).status < 0) + return -1; + + const char *name; + if (data.found_name != NULL) { + name = data.found_name; + } else { +#define NAME "IREL." + /* NAME\0 + 0x + digits. */ + char *tmp_name = alloca(sizeof NAME + 2 + 16); + sprintf(tmp_name, NAME "%#" PRIx64, + (uint64_t)rela->r_addend); + name = tmp_name; +#undef NAME + } + + if (default_elf_add_plt_entry(proc, lte, name, rela, ndx, ret) < 0) + return plt_fail; + + return plt_ok; +} --- sysdeps/linux-gnu/trace.h.ori +++ sysdeps/linux-gnu/trace.h @@ -118,4 +118,22 @@ int process_install_stopping_handler void linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self); void linux_ptrace_disable_and_continue(struct process_stopping_handler *self); +/* When main binary needs to call an IFUNC function defined in the + * binary itself, a PLT entry is set up so that dynamic linker can get + * involved and resolve the symbol. But unlike other PLT relocation, + * this one can't rely on symbol table being available. So it doesn't + * reference the symbol by its name, but by its address, and + * correspondingly, has another type. When arch backend wishes to + * support these IRELATIVE relocations, it should override + * arch_elf_add_plt_entry and dispatch to this function for IRELATIVE + * relocations. + * + * This function behaves as arch_elf_add_plt_entry, except that it + * doesn't take name for a parameter, but instead looks up the name in + * symbol tables in LTE. */ +enum plt_status linux_elf_add_plt_entry_irelative(struct Process *proc, + struct ltelf *lte, + GElf_Rela *rela, size_t ndx, + struct library_symbol **ret); + #endif /* _LTRACE_LINUX_TRACE_H_ */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor