aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-08-07 07:38:50 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-08-07 16:35:32 -0400
commit0131c4ec794a7409eafff0c79105309540aaca4d (patch)
tree2e75956f1d28c5177ef52efdf9c4a8957a8e819a /tools
parentd380b34830cc76461feab012f0bc52b01e65087c (diff)
perf tools: Make it possible to read object code from kernel modules
The new "object code reading" test shows that it is not possible to read object code from kernel modules. That is because the mappings do not map to the dsos. This patch fixes that. This involves identifying and flagging relocatable (ELF type ET_REL) files (e.g. kernel modules) for symbol adjustment and updating map__rip_2objdump() accordingly. The kmodule parameter of dso__load_sym() is taken into use and the module map altered to map to the dso. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1375875537-4509-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/dso.c1
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/map.c14
-rw-r--r--tools/perf/util/symbol-elf.c25
-rw-r--r--tools/perf/util/symbol.c11
5 files changed, 43 insertions, 9 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 121583dbf34b..1955804e82ff 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -419,6 +419,7 @@ struct dso *dso__new(const char *name)
419 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 419 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
420 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; 420 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
421 dso->loaded = 0; 421 dso->loaded = 0;
422 dso->rel = 0;
422 dso->sorted_by_name = 0; 423 dso->sorted_by_name = 0;
423 dso->has_build_id = 0; 424 dso->has_build_id = 0;
424 dso->kernel = DSO_TYPE_USER; 425 dso->kernel = DSO_TYPE_USER;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 02aadaf45c63..735a83751b19 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -85,6 +85,7 @@ struct dso {
85 u8 lname_alloc:1; 85 u8 lname_alloc:1;
86 u8 sorted_by_name; 86 u8 sorted_by_name;
87 u8 loaded; 87 u8 loaded;
88 u8 rel;
88 u8 build_id[BUILD_ID_SIZE]; 89 u8 build_id[BUILD_ID_SIZE];
89 const char *short_name; 90 const char *short_name;
90 char *long_name; 91 char *long_name;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 5f662a3a0163..4d599febfb0b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -248,14 +248,18 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
248 248
249/* 249/*
250 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 250 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
251 * map->dso->adjust_symbols==1 for ET_EXEC-like cases. 251 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
252 * relative to section start.
252 */ 253 */
253u64 map__rip_2objdump(struct map *map, u64 rip) 254u64 map__rip_2objdump(struct map *map, u64 rip)
254{ 255{
255 u64 addr = map->dso->adjust_symbols ? 256 if (!map->dso->adjust_symbols)
256 map->unmap_ip(map, rip) : /* RIP -> IP */ 257 return rip;
257 rip; 258
258 return addr; 259 if (map->dso->rel)
260 return rip - map->pgoff;
261
262 return map->unmap_ip(map, rip);
259} 263}
260 264
261void map_groups__init(struct map_groups *mg) 265void map_groups__init(struct map_groups *mg)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index ed6f443a3e10..3eaa7b486e2e 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -599,11 +599,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
599 if (dso->kernel == DSO_TYPE_USER) { 599 if (dso->kernel == DSO_TYPE_USER) {
600 GElf_Shdr shdr; 600 GElf_Shdr shdr;
601 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 601 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
602 ehdr.e_type == ET_REL ||
602 elf_section_by_name(elf, &ehdr, &shdr, 603 elf_section_by_name(elf, &ehdr, &shdr,
603 ".gnu.prelink_undo", 604 ".gnu.prelink_undo",
604 NULL) != NULL); 605 NULL) != NULL);
605 } else { 606 } else {
606 ss->adjust_symbols = ehdr.e_type == ET_EXEC; 607 ss->adjust_symbols = ehdr.e_type == ET_EXEC ||
608 ehdr.e_type == ET_REL;
607 } 609 }
608 610
609 ss->name = strdup(name); 611 ss->name = strdup(name);
@@ -676,6 +678,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
676 bool remap_kernel = false, adjust_kernel_syms = false; 678 bool remap_kernel = false, adjust_kernel_syms = false;
677 679
678 dso->symtab_type = syms_ss->type; 680 dso->symtab_type = syms_ss->type;
681 dso->rel = syms_ss->ehdr.e_type == ET_REL;
682
683 /*
684 * Modules may already have symbols from kallsyms, but those symbols
685 * have the wrong values for the dso maps, so remove them.
686 */
687 if (kmodule && syms_ss->symtab)
688 symbols__delete(&dso->symbols[map->type]);
679 689
680 if (!syms_ss->symtab) { 690 if (!syms_ss->symtab) {
681 syms_ss->symtab = syms_ss->dynsym; 691 syms_ss->symtab = syms_ss->dynsym;
@@ -828,11 +838,24 @@ int dso__load_sym(struct dso *dso, struct map *map,
828 map_groups__insert(kmap->kmaps, map); 838 map_groups__insert(kmap->kmaps, map);
829 } 839 }
830 840
841 /*
842 * The initial module mapping is based on
843 * /proc/modules mapped to offset zero.
844 * Overwrite it to map to the module dso.
845 */
846 if (remap_kernel && kmodule) {
847 remap_kernel = false;
848 map->pgoff = shdr.sh_offset;
849 }
850
831 curr_map = map; 851 curr_map = map;
832 curr_dso = dso; 852 curr_dso = dso;
833 goto new_symbol; 853 goto new_symbol;
834 } 854 }
835 855
856 if (!kmap)
857 goto new_symbol;
858
836 snprintf(dso_name, sizeof(dso_name), 859 snprintf(dso_name, sizeof(dso_name),
837 "%s%s", dso->short_name, section_name); 860 "%s%s", dso->short_name, section_name);
838 861
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 04300dd5221f..b9056a8c1620 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -854,10 +854,15 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
854 if (!runtime_ss && syms_ss) 854 if (!runtime_ss && syms_ss)
855 runtime_ss = syms_ss; 855 runtime_ss = syms_ss;
856 856
857 if (syms_ss) 857 if (syms_ss) {
858 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); 858 int km;
859 else 859
860 km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
861 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
862 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
863 } else {
860 ret = -1; 864 ret = -1;
865 }
861 866
862 if (ret > 0) { 867 if (ret > 0) {
863 int nr_plt; 868 int nr_plt;