Skip to content

Commit afffec6

Browse files
captain5050namhyung
authored andcommitted
perf dso: Add support for reading the e_machine type for a dso
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> Reviewed-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Arnaldo Carvalho de Melo <acme@kernel.org> Link: https://lore.kernel.org/r/20250319050741.269828-7-irogers@google.com Signed-off-by: Namhyung Kim <namhyung@kernel.org>
1 parent 5c2938f commit afffec6

3 files changed

Lines changed: 92 additions & 27 deletions

File tree

tools/perf/util/dso.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,68 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
11941194
return data_read_write_offset(dso, machine, offset, data, size, true);
11951195
}
11961196

1197+
uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
1198+
{
1199+
uint16_t e_machine = EM_NONE;
1200+
int fd;
1201+
1202+
switch (dso__binary_type(dso)) {
1203+
case DSO_BINARY_TYPE__KALLSYMS:
1204+
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1205+
case DSO_BINARY_TYPE__VMLINUX:
1206+
case DSO_BINARY_TYPE__GUEST_VMLINUX:
1207+
case DSO_BINARY_TYPE__GUEST_KMODULE:
1208+
case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
1209+
case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1210+
case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
1211+
case DSO_BINARY_TYPE__KCORE:
1212+
case DSO_BINARY_TYPE__GUEST_KCORE:
1213+
case DSO_BINARY_TYPE__BPF_PROG_INFO:
1214+
case DSO_BINARY_TYPE__BPF_IMAGE:
1215+
case DSO_BINARY_TYPE__OOL:
1216+
case DSO_BINARY_TYPE__JAVA_JIT:
1217+
return EM_HOST;
1218+
case DSO_BINARY_TYPE__DEBUGLINK:
1219+
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1220+
case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
1221+
case DSO_BINARY_TYPE__GNU_DEBUGDATA:
1222+
case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
1223+
case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
1224+
case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
1225+
case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
1226+
case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
1227+
case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
1228+
break;
1229+
case DSO_BINARY_TYPE__NOT_FOUND:
1230+
default:
1231+
return EM_NONE;
1232+
}
1233+
1234+
mutex_lock(dso__data_open_lock());
1235+
1236+
/*
1237+
* dso__data(dso)->fd might be closed if other thread opened another
1238+
* file (dso) due to open file limit (RLIMIT_NOFILE).
1239+
*/
1240+
try_to_open_dso(dso, machine);
1241+
fd = dso__data(dso)->fd;
1242+
if (fd >= 0) {
1243+
_Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
1244+
_Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
1245+
if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
1246+
unsigned char eidata;
1247+
1248+
if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
1249+
dso__swap_init(dso, eidata);
1250+
}
1251+
if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
1252+
pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
1253+
e_machine = DSO__SWAP(dso, uint16_t, e_machine);
1254+
}
1255+
mutex_unlock(dso__data_open_lock());
1256+
return e_machine;
1257+
}
1258+
11971259
/**
11981260
* dso__data_read_addr - Read data from dso address
11991261
* @dso: dso object
@@ -1549,6 +1611,33 @@ void dso__put(struct dso *dso)
15491611
RC_CHK_PUT(dso);
15501612
}
15511613

1614+
int dso__swap_init(struct dso *dso, unsigned char eidata)
1615+
{
1616+
static unsigned int const endian = 1;
1617+
1618+
dso__set_needs_swap(dso, DSO_SWAP__NO);
1619+
1620+
switch (eidata) {
1621+
case ELFDATA2LSB:
1622+
/* We are big endian, DSO is little endian. */
1623+
if (*(unsigned char const *)&endian != 1)
1624+
dso__set_needs_swap(dso, DSO_SWAP__YES);
1625+
break;
1626+
1627+
case ELFDATA2MSB:
1628+
/* We are little endian, DSO is big endian. */
1629+
if (*(unsigned char const *)&endian != 0)
1630+
dso__set_needs_swap(dso, DSO_SWAP__YES);
1631+
break;
1632+
1633+
default:
1634+
pr_err("unrecognized DSO data encoding %d\n", eidata);
1635+
return -EINVAL;
1636+
}
1637+
1638+
return 0;
1639+
}
1640+
15521641
void dso__set_build_id(struct dso *dso, struct build_id *bid)
15531642
{
15541643
RC_CHK_ACCESS(dso)->bid = *bid;

tools/perf/util/dso.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ bool dso__sorted_by_name(const struct dso *dso);
737737
void dso__set_sorted_by_name(struct dso *dso);
738738
void dso__sort_by_name(struct dso *dso);
739739

740+
int dso__swap_init(struct dso *dso, unsigned char eidata);
741+
740742
void dso__set_build_id(struct dso *dso, struct build_id *bid);
741743
bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
742744
void dso__read_running_kernel_build_id(struct dso *dso,
@@ -826,6 +828,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
826828
off_t dso__data_size(struct dso *dso, struct machine *machine);
827829
ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
828830
u64 offset, u8 *data, ssize_t size);
831+
uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
829832
ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
830833
struct machine *machine, u64 addr,
831834
u8 *data, ssize_t size);

tools/perf/util/symbol-elf.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,33 +1174,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
11741174

11751175
#endif
11761176

1177-
static int dso__swap_init(struct dso *dso, unsigned char eidata)
1178-
{
1179-
static unsigned int const endian = 1;
1180-
1181-
dso__set_needs_swap(dso, DSO_SWAP__NO);
1182-
1183-
switch (eidata) {
1184-
case ELFDATA2LSB:
1185-
/* We are big endian, DSO is little endian. */
1186-
if (*(unsigned char const *)&endian != 1)
1187-
dso__set_needs_swap(dso, DSO_SWAP__YES);
1188-
break;
1189-
1190-
case ELFDATA2MSB:
1191-
/* We are little endian, DSO is big endian. */
1192-
if (*(unsigned char const *)&endian != 0)
1193-
dso__set_needs_swap(dso, DSO_SWAP__YES);
1194-
break;
1195-
1196-
default:
1197-
pr_err("unrecognized DSO data encoding %d\n", eidata);
1198-
return -EINVAL;
1199-
}
1200-
1201-
return 0;
1202-
}
1203-
12041177
bool symsrc__possibly_runtime(struct symsrc *ss)
12051178
{
12061179
return ss->dynsym || ss->opdsec;

0 commit comments

Comments
 (0)