Skip to content

Commit

Permalink
elf: Detect if Elf is PIE
Browse files Browse the repository at this point in the history
It is not sufficient to determine whether Elf is ET_DYN or not to be a
dynamic library in bcc_elf_is_shared_obj() function, because the executable
Elf of the PIE type is also ET_DYN.

For example, on Fedora 41, /usr/bin/bash is PIE:

    $ readelf -h /usr/bin/bash
    ELF Header:
      ...
      Type:                     DYN (Position-Independent Executable file)
      ...

bcc_elf_is_shared_obj() should not return 'true' for /usr/bin/bash.

This commit add function bcc_elf_is_pie() and export it in bcc_elf.h.

At the same time, fix test py_test_usdt3.

Signed-off-by: Rong Tao <[email protected]>
Signed-off-by: Jiang Guirong <[email protected]>
  • Loading branch information
Rtoax authored and yonghong-song committed Nov 4, 2024
1 parent d36ab45 commit 0b5be9b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 3 deletions.
42 changes: 41 additions & 1 deletion src/cc/bcc_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,12 +1013,52 @@ int bcc_elf_get_type(const char *path) {
return hdr.e_type;
}

int bcc_elf_is_pie(const char *path) {
int i, j, res;
struct bcc_elf_file elf_file;

if (bcc_elf_file_open(path, &elf_file) < 0)
return false;

Elf *elf = elf_file.elf;
size_t shdrnum;

elf_getshdrnum(elf, &shdrnum);
res = false;

for (i = 0; i < shdrnum; i++) {
Elf_Scn *scn = elf_getscn(elf, i);
Elf64_Shdr *shdr = elf64_getshdr(scn);
Elf_Data *data = elf_getdata(scn, NULL);

if (shdr->sh_type != SHT_DYNAMIC)
continue;

Elf64_Dyn *dyns = data->d_buf;
for (j = 0; j * shdr->sh_entsize < shdr->sh_size; j++) {
Elf64_Dyn *dyn = &dyns[j];
if (dyn->d_tag == DT_FLAGS_1) {
if (dyn->d_un.d_val & DF_1_PIE) {
res = true;
goto done;
}
}
}
}

done:
bcc_elf_file_close(&elf_file);
return res;
}

int bcc_elf_is_exe(const char *path) {
return (bcc_elf_get_type(path) != -1) && (access(path, X_OK) == 0);
}

int bcc_elf_is_shared_obj(const char *path) {
return bcc_elf_get_type(path) == ET_DYN;
int is_dyn = bcc_elf_get_type(path) == ET_DYN;
int is_pie = bcc_elf_is_pie(path);
return is_dyn ? (is_pie ? false : true) : false;
}

int bcc_elf_is_vdso(const char *name) {
Expand Down
1 change: 1 addition & 0 deletions src/cc/bcc_elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ int bcc_elf_get_text_scn_info(const char *path, uint64_t *addr,
uint64_t *offset);

int bcc_elf_get_type(const char *path);
int bcc_elf_is_pie(const char *path);
int bcc_elf_is_shared_obj(const char *path);
int bcc_elf_is_exe(const char *path);
int bcc_elf_is_vdso(const char *name);
Expand Down
2 changes: 1 addition & 1 deletion src/cc/usdt/usdt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ bool Probe::in_shared_object(const std::string &bin_path) {

bool Probe::resolve_global_address(uint64_t *global, const std::string &bin_path,
const uint64_t addr) {
if (in_shared_object(bin_path)) {
if (in_shared_object(bin_path) || bcc_elf_is_pie(bin_path.c_str())) {
return (pid_ &&
!bcc_resolve_global_addr(*pid_, bin_path.c_str(), addr, mod_match_inode_only_, global));
}
Expand Down
3 changes: 2 additions & 1 deletion src/cc/usdt/usdt_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ bool Argument::get_global_address(uint64_t *address, const std::string &binpath,
.resolve_name(binpath.c_str(), deref_ident_->c_str(), address);
}

if (!bcc_elf_is_shared_obj(binpath.c_str())) {
if (!bcc_elf_is_shared_obj(binpath.c_str()) ||
bcc_elf_is_pie(binpath.c_str())) {
struct bcc_symbol sym;
if (bcc_resolve_symname(binpath.c_str(), deref_ident_->c_str(), 0x0, -1, nullptr, &sym) == 0) {
*address = sym.offset;
Expand Down

0 comments on commit 0b5be9b

Please sign in to comment.