Message ID | 20250308003209.234114-7-irogers@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | perf: Support multiple system call tables in the build | expand |
Context | Check | Description |
---|---|---|
bjorn/pre-ci_am | fail | Failed to apply series |
On Fri, Mar 07, 2025 at 04:32:04PM -0800, Ian Rogers wrote: > For ELF file dsos read the e_machine from the ELF header. For kernel > types assume the e_machine matches the perf tool. In other cases > return EM_NONE. > > When reading from the ELF header use DSO__SWAP that may need > dso->needs_swap initializing. Factor out dso__swap_init to allow this. > > Signed-off-by: Ian Rogers <irogers@google.com> > --- > tools/perf/util/dso.c | 88 ++++++++++++++++++++++++++++++++++++ > tools/perf/util/dso.h | 3 ++ > tools/perf/util/symbol-elf.c | 27 ----------- > 3 files changed, 91 insertions(+), 27 deletions(-) This one, due to this having already been merged: commit b10f74308e1305275e69ddde711ec817cc69e306 (perf-tools-next/perf-tools-next) Author: Stephen Brennan <stephen.s.brennan@oracle.com> Date: Fri Mar 7 15:22:03 2025 -0800 perf symbol: Support .gnu_debugdata for symbols Needs this so that we read the e_machine from the ELF file: diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 8188ba4d432cd5ac..8d2d8bb22e077bea 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1203,6 +1203,7 @@ uint16_t dso__e_machine(struct dso *dso, struct machine *machine) case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: + case DSO_BINARY_TYPE__GNU_DEBUGDATA: break; case DSO_BINARY_TYPE__NOT_FOUND: default: --- Continuing the review and test. - Arnaldo > diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c > index 5c6e85fdae0d..00fec1bc32bc 100644 > --- a/tools/perf/util/dso.c > +++ b/tools/perf/util/dso.c > @@ -1170,6 +1170,67 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, > return data_read_write_offset(dso, machine, offset, data, size, true); > } > > +uint16_t dso__e_machine(struct dso *dso, struct machine *machine) > +{ > + uint16_t e_machine = EM_NONE; > + int fd; > + > + switch (dso__binary_type(dso)) { > + case DSO_BINARY_TYPE__KALLSYMS: > + case DSO_BINARY_TYPE__GUEST_KALLSYMS: > + case DSO_BINARY_TYPE__VMLINUX: > + case DSO_BINARY_TYPE__GUEST_VMLINUX: > + case DSO_BINARY_TYPE__GUEST_KMODULE: > + case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: > + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: > + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: > + case DSO_BINARY_TYPE__KCORE: > + case DSO_BINARY_TYPE__GUEST_KCORE: > + case DSO_BINARY_TYPE__BPF_PROG_INFO: > + case DSO_BINARY_TYPE__BPF_IMAGE: > + case DSO_BINARY_TYPE__OOL: > + case DSO_BINARY_TYPE__JAVA_JIT: > + return EM_HOST; > + case DSO_BINARY_TYPE__DEBUGLINK: > + case DSO_BINARY_TYPE__BUILD_ID_CACHE: > + case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: > + case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: > + case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: > + case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: > + case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: > + case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: > + case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: > + break; > + case DSO_BINARY_TYPE__NOT_FOUND: > + default: > + return EM_NONE; > + } > + > + pthread_mutex_lock(&dso__data_open_lock); > + > + /* > + * dso__data(dso)->fd might be closed if other thread opened another > + * file (dso) due to open file limit (RLIMIT_NOFILE). > + */ > + try_to_open_dso(dso, machine); > + fd = dso__data(dso)->fd; > + if (fd >= 0) { > + _Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset"); > + _Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset"); > + if (dso__needs_swap(dso) == DSO_SWAP__UNSET) { > + unsigned char eidata; > + > + if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata)) > + dso__swap_init(dso, eidata); > + } > + if (dso__needs_swap(dso) != DSO_SWAP__UNSET && > + pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine)) > + e_machine = DSO__SWAP(dso, uint16_t, e_machine); > + } > + pthread_mutex_unlock(&dso__data_open_lock); > + return e_machine; > +} > + > /** > * dso__data_read_addr - Read data from dso address > * @dso: dso object > @@ -1525,6 +1586,33 @@ void dso__put(struct dso *dso) > RC_CHK_PUT(dso); > } > > +int dso__swap_init(struct dso *dso, unsigned char eidata) > +{ > + static unsigned int const endian = 1; > + > + dso__set_needs_swap(dso, DSO_SWAP__NO); > + > + switch (eidata) { > + case ELFDATA2LSB: > + /* We are big endian, DSO is little endian. */ > + if (*(unsigned char const *)&endian != 1) > + dso__set_needs_swap(dso, DSO_SWAP__YES); > + break; > + > + case ELFDATA2MSB: > + /* We are little endian, DSO is big endian. */ > + if (*(unsigned char const *)&endian != 0) > + dso__set_needs_swap(dso, DSO_SWAP__YES); > + break; > + > + default: > + pr_err("unrecognized DSO data encoding %d\n", eidata); > + return -EINVAL; > + } > + > + return 0; > +} > + > void dso__set_build_id(struct dso *dso, struct build_id *bid) > { > RC_CHK_ACCESS(dso)->bid = *bid; > diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h > index 4aa8c3d36566..38d9e3eac501 100644 > --- a/tools/perf/util/dso.h > +++ b/tools/perf/util/dso.h > @@ -730,6 +730,8 @@ bool dso__sorted_by_name(const struct dso *dso); > void dso__set_sorted_by_name(struct dso *dso); > void dso__sort_by_name(struct dso *dso); > > +int dso__swap_init(struct dso *dso, unsigned char eidata); > + > void dso__set_build_id(struct dso *dso, struct build_id *bid); > bool dso__build_id_equal(const struct dso *dso, struct build_id *bid); > void dso__read_running_kernel_build_id(struct dso *dso, > @@ -818,6 +820,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine); > off_t dso__data_size(struct dso *dso, struct machine *machine); > ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, > u64 offset, u8 *data, ssize_t size); > +uint16_t dso__e_machine(struct dso *dso, struct machine *machine); > ssize_t dso__data_read_addr(struct dso *dso, struct map *map, > struct machine *machine, u64 addr, > u8 *data, ssize_t size); > diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c > index 66fd1249660a..71df13a5722a 100644 > --- a/tools/perf/util/symbol-elf.c > +++ b/tools/perf/util/symbol-elf.c > @@ -1173,33 +1173,6 @@ int filename__read_debuglink(const char *filename, char *debuglink, > > #endif > > -static int dso__swap_init(struct dso *dso, unsigned char eidata) > -{ > - static unsigned int const endian = 1; > - > - dso__set_needs_swap(dso, DSO_SWAP__NO); > - > - switch (eidata) { > - case ELFDATA2LSB: > - /* We are big endian, DSO is little endian. */ > - if (*(unsigned char const *)&endian != 1) > - dso__set_needs_swap(dso, DSO_SWAP__YES); > - break; > - > - case ELFDATA2MSB: > - /* We are little endian, DSO is big endian. */ > - if (*(unsigned char const *)&endian != 0) > - dso__set_needs_swap(dso, DSO_SWAP__YES); > - break; > - > - default: > - pr_err("unrecognized DSO data encoding %d\n", eidata); > - return -EINVAL; > - } > - > - return 0; > -} > - > bool symsrc__possibly_runtime(struct symsrc *ss) > { > return ss->dynsym || ss->opdsec; > -- > 2.49.0.rc0.332.g42c0ae87b1-goog >
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 5c6e85fdae0d..00fec1bc32bc 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1170,6 +1170,67 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, return data_read_write_offset(dso, machine, offset, data, size, true); } +uint16_t dso__e_machine(struct dso *dso, struct machine *machine) +{ + uint16_t e_machine = EM_NONE; + int fd; + + switch (dso__binary_type(dso)) { + case DSO_BINARY_TYPE__KALLSYMS: + case DSO_BINARY_TYPE__GUEST_KALLSYMS: + case DSO_BINARY_TYPE__VMLINUX: + case DSO_BINARY_TYPE__GUEST_VMLINUX: + case DSO_BINARY_TYPE__GUEST_KMODULE: + case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: + case DSO_BINARY_TYPE__KCORE: + case DSO_BINARY_TYPE__GUEST_KCORE: + case DSO_BINARY_TYPE__BPF_PROG_INFO: + case DSO_BINARY_TYPE__BPF_IMAGE: + case DSO_BINARY_TYPE__OOL: + case DSO_BINARY_TYPE__JAVA_JIT: + return EM_HOST; + case DSO_BINARY_TYPE__DEBUGLINK: + case DSO_BINARY_TYPE__BUILD_ID_CACHE: + case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: + case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: + case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: + case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: + case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: + case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: + case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: + break; + case DSO_BINARY_TYPE__NOT_FOUND: + default: + return EM_NONE; + } + + pthread_mutex_lock(&dso__data_open_lock); + + /* + * dso__data(dso)->fd might be closed if other thread opened another + * file (dso) due to open file limit (RLIMIT_NOFILE). + */ + try_to_open_dso(dso, machine); + fd = dso__data(dso)->fd; + if (fd >= 0) { + _Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset"); + _Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset"); + if (dso__needs_swap(dso) == DSO_SWAP__UNSET) { + unsigned char eidata; + + if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata)) + dso__swap_init(dso, eidata); + } + if (dso__needs_swap(dso) != DSO_SWAP__UNSET && + pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine)) + e_machine = DSO__SWAP(dso, uint16_t, e_machine); + } + pthread_mutex_unlock(&dso__data_open_lock); + return e_machine; +} + /** * dso__data_read_addr - Read data from dso address * @dso: dso object @@ -1525,6 +1586,33 @@ void dso__put(struct dso *dso) RC_CHK_PUT(dso); } +int dso__swap_init(struct dso *dso, unsigned char eidata) +{ + static unsigned int const endian = 1; + + dso__set_needs_swap(dso, DSO_SWAP__NO); + + switch (eidata) { + case ELFDATA2LSB: + /* We are big endian, DSO is little endian. */ + if (*(unsigned char const *)&endian != 1) + dso__set_needs_swap(dso, DSO_SWAP__YES); + break; + + case ELFDATA2MSB: + /* We are little endian, DSO is big endian. */ + if (*(unsigned char const *)&endian != 0) + dso__set_needs_swap(dso, DSO_SWAP__YES); + break; + + default: + pr_err("unrecognized DSO data encoding %d\n", eidata); + return -EINVAL; + } + + return 0; +} + void dso__set_build_id(struct dso *dso, struct build_id *bid) { RC_CHK_ACCESS(dso)->bid = *bid; diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 4aa8c3d36566..38d9e3eac501 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -730,6 +730,8 @@ bool dso__sorted_by_name(const struct dso *dso); void dso__set_sorted_by_name(struct dso *dso); void dso__sort_by_name(struct dso *dso); +int dso__swap_init(struct dso *dso, unsigned char eidata); + void dso__set_build_id(struct dso *dso, struct build_id *bid); bool dso__build_id_equal(const struct dso *dso, struct build_id *bid); void dso__read_running_kernel_build_id(struct dso *dso, @@ -818,6 +820,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine); off_t dso__data_size(struct dso *dso, struct machine *machine); ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size); +uint16_t dso__e_machine(struct dso *dso, struct machine *machine); ssize_t dso__data_read_addr(struct dso *dso, struct map *map, struct machine *machine, u64 addr, u8 *data, ssize_t size); diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 66fd1249660a..71df13a5722a 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1173,33 +1173,6 @@ int filename__read_debuglink(const char *filename, char *debuglink, #endif -static int dso__swap_init(struct dso *dso, unsigned char eidata) -{ - static unsigned int const endian = 1; - - dso__set_needs_swap(dso, DSO_SWAP__NO); - - switch (eidata) { - case ELFDATA2LSB: - /* We are big endian, DSO is little endian. */ - if (*(unsigned char const *)&endian != 1) - dso__set_needs_swap(dso, DSO_SWAP__YES); - break; - - case ELFDATA2MSB: - /* We are little endian, DSO is big endian. */ - if (*(unsigned char const *)&endian != 0) - dso__set_needs_swap(dso, DSO_SWAP__YES); - break; - - default: - pr_err("unrecognized DSO data encoding %d\n", eidata); - return -EINVAL; - } - - return 0; -} - bool symsrc__possibly_runtime(struct symsrc *ss) { return ss->dynsym || ss->opdsec;
For ELF file dsos read the e_machine from the ELF header. For kernel types assume the e_machine matches the perf tool. In other cases return EM_NONE. When reading from the ELF header use DSO__SWAP that may need dso->needs_swap initializing. Factor out dso__swap_init to allow this. Signed-off-by: Ian Rogers <irogers@google.com> --- tools/perf/util/dso.c | 88 ++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 3 ++ tools/perf/util/symbol-elf.c | 27 ----------- 3 files changed, 91 insertions(+), 27 deletions(-)