Skip to content

Commit

Permalink
Fix ELF ABI and endianness checks for powerpc64
Browse files Browse the repository at this point in the history
Earlier, it was assumed that ELF ABI v2 is used only on
little-endian powerpc64 environments but it seems this
ABI can be used independently of endianness.

It is expected that any C preprocessor that conforms to
the ELF ABI v2 specification must predefine the _CALL_ELF
macro and set its value to 2.

Instead of looking at __BYTE_ORDER__ to determine whether
to use the Local Entry Point (LEP) of symbols, one should
look at the _CALL_ELF macro instead as this is ABI-related.

Similarly, _CALL_ELF should be used only for determining
the ABI version and not the endianness.

Reported-by: Naveen N. Rao <[email protected]>
Fixes: bbd4180 ("Fix uprobes on powerpc64")
Fixes: 1086952 ("clang: Add support to build eBPF for user specified ARCH")
Acked-by: Naveen N. Rao <[email protected]>
Signed-off-by: Sandipan Das <[email protected]>
  • Loading branch information
sandip4n authored and yonghong-song committed Apr 23, 2020
1 parent ceb458d commit d2e8ea4
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 18 deletions.
20 changes: 10 additions & 10 deletions src/cc/bcc_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,16 +257,8 @@ static int list_in_scn(Elf *e, Elf_Scn *section, size_t stridx, size_t symsize,
continue;

#ifdef __powerpc64__
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
if (opddata && sym.st_shndx == opdidx) {
size_t offset = sym.st_value - opdshdr.sh_addr;
/* Find the function descriptor */
uint64_t *descr = opddata->d_buf + offset;
/* Read the actual entry point address from the descriptor */
sym.st_value = *descr;
}
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
if (option->use_symbol_type & (1 << STT_PPC64LE_SYM_LEP)) {
#if defined(_CALL_ELF) && _CALL_ELF == 2
if (option->use_symbol_type & (1 << STT_PPC64_ELFV2_SYM_LEP)) {
/*
* The PowerPC 64-bit ELF v2 ABI says that the 3 most significant bits
* in the st_other field of the symbol table specifies the number of
Expand All @@ -287,6 +279,14 @@ static int list_in_scn(Elf *e, Elf_Scn *section, size_t stridx, size_t symsize,
case 6: sym.st_value += 64; break;
}
}
#else
if (opddata && sym.st_shndx == opdidx) {
size_t offset = sym.st_value - opdshdr.sh_addr;
/* Find the function descriptor */
uint64_t *descr = opddata->d_buf + offset;
/* Read the actual entry point address from the descriptor */
sym.st_value = *descr;
}
#endif
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/cc/bcc_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -712,8 +712,8 @@ int bcc_resolve_symname(const char *module, const char *symname,
.use_debug_file = 1,
.check_debug_file_crc = 1,
.lazy_symbolize = 1,
#if defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
.use_symbol_type = BCC_SYM_ALL_TYPES | (1 << STT_PPC64LE_SYM_LEP),
#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
.use_symbol_type = BCC_SYM_ALL_TYPES | (1 << STT_PPC64_ELFV2_SYM_LEP),
#else
.use_symbol_type = BCC_SYM_ALL_TYPES,
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/cc/bcc_syms.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ struct mod_info;
#define STT_GNU_IFUNC 10
#endif

#if defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
// Indicate if the Local Entry Point (LEP) should be used as a symbol's
// start address
#define STT_PPC64LE_SYM_LEP 31
#define STT_PPC64_ELFV2_SYM_LEP 31
#endif

static const uint32_t BCC_SYM_ALL_TYPES = 65535;
Expand Down
4 changes: 2 additions & 2 deletions src/cc/frontends/clang/arch_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static void *run_arch_callback(arch_callback_t fn)
/* If ARCH is not set, detect from local arch clang is running on */
if (!archenv) {
#if defined(__powerpc64__)
#if defined(_CALL_ELF) && _CALL_ELF == 2
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return fn(BCC_ARCH_PPC_LE);
#else
return fn(BCC_ARCH_PPC);
Expand All @@ -50,7 +50,7 @@ static void *run_arch_callback(arch_callback_t fn)

/* Otherwise read it from ARCH */
if (!strcmp(archenv, "powerpc")) {
#if defined(_CALL_ELF) && _CALL_ELF == 2
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return fn(BCC_ARCH_PPC_LE);
#else
return fn(BCC_ARCH_PPC);
Expand Down
4 changes: 2 additions & 2 deletions tests/cc/test_c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ TEST_CASE("resolve symbol addresses for a given PID", "[c_api]") {
.use_debug_file = 1,
.check_debug_file_crc = 1,
.lazy_symbolize = 1,
#if defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
.use_symbol_type = BCC_SYM_ALL_TYPES | (1 << STT_PPC64LE_SYM_LEP),
#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
.use_symbol_type = BCC_SYM_ALL_TYPES | (1 << STT_PPC64_ELFV2_SYM_LEP),
#else
.use_symbol_type = BCC_SYM_ALL_TYPES,
#endif
Expand Down

0 comments on commit d2e8ea4

Please sign in to comment.