diff --git a/src/cc/bcc_elf.c b/src/cc/bcc_elf.c index bf853fee0e87..521ee9777e96 100644 --- a/src/cc/bcc_elf.c +++ b/src/cc/bcc_elf.c @@ -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) { diff --git a/src/cc/bcc_elf.h b/src/cc/bcc_elf.h index c9c614085c7e..ba1805682ff3 100644 --- a/src/cc/bcc_elf.h +++ b/src/cc/bcc_elf.h @@ -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); diff --git a/src/cc/usdt/usdt.cc b/src/cc/usdt/usdt.cc index a6213653ec6e..f36bf75ee9a8 100644 --- a/src/cc/usdt/usdt.cc +++ b/src/cc/usdt/usdt.cc @@ -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)); } diff --git a/src/cc/usdt/usdt_args.cc b/src/cc/usdt/usdt_args.cc index 5433334dcc9e..db65df591e64 100644 --- a/src/cc/usdt/usdt_args.cc +++ b/src/cc/usdt/usdt_args.cc @@ -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;