libbpf.c (8097e460cabd9973e424e0f93bc1ad44cebf6466) | libbpf.c (5c742725045ae9c15b7ae2041d1fbd1f2180ab86) |
---|---|
1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 3/* 4 * Common eBPF ELF object loading operations. 5 * 6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 8 * Copyright (C) 2015 Huawei Inc. --- 10990 unchanged lines hidden (view full) --- 10999 return pfd; 11000 11001err_clean_legacy: 11002 /* Clear the newly added legacy uprobe_event */ 11003 remove_uprobe_event_legacy(probe_name, retprobe); 11004 return err; 11005} 11006 | 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 3/* 4 * Common eBPF ELF object loading operations. 5 * 6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 7 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 8 * Copyright (C) 2015 Huawei Inc. --- 10990 unchanged lines hidden (view full) --- 10999 return pfd; 11000 11001err_clean_legacy: 11002 /* Clear the newly added legacy uprobe_event */ 11003 remove_uprobe_event_legacy(probe_name, retprobe); 11004 return err; 11005} 11006 |
11007/* Return next ELF section of sh_type after scn, or first of that type if scn is NULL. */ 11008static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn) 11009{ 11010 while ((scn = elf_nextscn(elf, scn)) != NULL) { 11011 GElf_Shdr sh; 11012 11013 if (!gelf_getshdr(scn, &sh)) 11014 continue; 11015 if (sh.sh_type == sh_type) 11016 return scn; 11017 } 11018 return NULL; 11019} 11020 11021/* Find offset of function name in the provided ELF object. "binary_path" is 11022 * the path to the ELF binary represented by "elf", and only used for error 11023 * reporting matters. "name" matches symbol name or name@@LIB for library 11024 * functions. 11025 */ 11026static long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name) 11027{ 11028 int i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB }; 11029 bool is_shared_lib, is_name_qualified; 11030 long ret = -ENOENT; 11031 size_t name_len; 11032 GElf_Ehdr ehdr; 11033 11034 if (!gelf_getehdr(elf, &ehdr)) { 11035 pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1)); 11036 ret = -LIBBPF_ERRNO__FORMAT; 11037 goto out; 11038 } 11039 /* for shared lib case, we do not need to calculate relative offset */ 11040 is_shared_lib = ehdr.e_type == ET_DYN; 11041 11042 name_len = strlen(name); 11043 /* Does name specify "@@LIB"? */ 11044 is_name_qualified = strstr(name, "@@") != NULL; 11045 11046 /* Search SHT_DYNSYM, SHT_SYMTAB for symbol. This search order is used because if 11047 * a binary is stripped, it may only have SHT_DYNSYM, and a fully-statically 11048 * linked binary may not have SHT_DYMSYM, so absence of a section should not be 11049 * reported as a warning/error. 11050 */ 11051 for (i = 0; i < ARRAY_SIZE(sh_types); i++) { 11052 size_t nr_syms, strtabidx, idx; 11053 Elf_Data *symbols = NULL; 11054 Elf_Scn *scn = NULL; 11055 int last_bind = -1; 11056 const char *sname; 11057 GElf_Shdr sh; 11058 11059 scn = elf_find_next_scn_by_type(elf, sh_types[i], NULL); 11060 if (!scn) { 11061 pr_debug("elf: failed to find symbol table ELF sections in '%s'\n", 11062 binary_path); 11063 continue; 11064 } 11065 if (!gelf_getshdr(scn, &sh)) 11066 continue; 11067 strtabidx = sh.sh_link; 11068 symbols = elf_getdata(scn, 0); 11069 if (!symbols) { 11070 pr_warn("elf: failed to get symbols for symtab section in '%s': %s\n", 11071 binary_path, elf_errmsg(-1)); 11072 ret = -LIBBPF_ERRNO__FORMAT; 11073 goto out; 11074 } 11075 nr_syms = symbols->d_size / sh.sh_entsize; 11076 11077 for (idx = 0; idx < nr_syms; idx++) { 11078 int curr_bind; 11079 GElf_Sym sym; 11080 Elf_Scn *sym_scn; 11081 GElf_Shdr sym_sh; 11082 11083 if (!gelf_getsym(symbols, idx, &sym)) 11084 continue; 11085 11086 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) 11087 continue; 11088 11089 sname = elf_strptr(elf, strtabidx, sym.st_name); 11090 if (!sname) 11091 continue; 11092 11093 curr_bind = GELF_ST_BIND(sym.st_info); 11094 11095 /* User can specify func, func@@LIB or func@@LIB_VERSION. */ 11096 if (strncmp(sname, name, name_len) != 0) 11097 continue; 11098 /* ...but we don't want a search for "foo" to match 'foo2" also, so any 11099 * additional characters in sname should be of the form "@@LIB". 11100 */ 11101 if (!is_name_qualified && sname[name_len] != '\0' && sname[name_len] != '@') 11102 continue; 11103 11104 if (ret >= 0) { 11105 /* handle multiple matches */ 11106 if (last_bind != STB_WEAK && curr_bind != STB_WEAK) { 11107 /* Only accept one non-weak bind. */ 11108 pr_warn("elf: ambiguous match for '%s', '%s' in '%s'\n", 11109 sname, name, binary_path); 11110 ret = -LIBBPF_ERRNO__FORMAT; 11111 goto out; 11112 } else if (curr_bind == STB_WEAK) { 11113 /* already have a non-weak bind, and 11114 * this is a weak bind, so ignore. 11115 */ 11116 continue; 11117 } 11118 } 11119 11120 /* Transform symbol's virtual address (absolute for 11121 * binaries and relative for shared libs) into file 11122 * offset, which is what kernel is expecting for 11123 * uprobe/uretprobe attachment. 11124 * See Documentation/trace/uprobetracer.rst for more 11125 * details. 11126 * This is done by looking up symbol's containing 11127 * section's header and using it's virtual address 11128 * (sh_addr) and corresponding file offset (sh_offset) 11129 * to transform sym.st_value (virtual address) into 11130 * desired final file offset. 11131 */ 11132 sym_scn = elf_getscn(elf, sym.st_shndx); 11133 if (!sym_scn) 11134 continue; 11135 if (!gelf_getshdr(sym_scn, &sym_sh)) 11136 continue; 11137 11138 ret = sym.st_value - sym_sh.sh_addr + sym_sh.sh_offset; 11139 last_bind = curr_bind; 11140 } 11141 if (ret > 0) 11142 break; 11143 } 11144 11145 if (ret > 0) { 11146 pr_debug("elf: symbol address match for '%s' in '%s': 0x%lx\n", name, binary_path, 11147 ret); 11148 } else { 11149 if (ret == 0) { 11150 pr_warn("elf: '%s' is 0 in symtab for '%s': %s\n", name, binary_path, 11151 is_shared_lib ? "should not be 0 in a shared library" : 11152 "try using shared library path instead"); 11153 ret = -ENOENT; 11154 } else { 11155 pr_warn("elf: failed to find symbol '%s' in '%s'\n", name, binary_path); 11156 } 11157 } 11158out: 11159 return ret; 11160} 11161 11162/* Find offset of function name in ELF object specified by path. "name" matches 11163 * symbol name or name@@LIB for library functions. 11164 */ 11165static long elf_find_func_offset_from_file(const char *binary_path, const char *name) 11166{ 11167 char errmsg[STRERR_BUFSIZE]; 11168 long ret = -ENOENT; 11169 Elf *elf; 11170 int fd; 11171 11172 fd = open(binary_path, O_RDONLY | O_CLOEXEC); 11173 if (fd < 0) { 11174 ret = -errno; 11175 pr_warn("failed to open %s: %s\n", binary_path, 11176 libbpf_strerror_r(ret, errmsg, sizeof(errmsg))); 11177 return ret; 11178 } 11179 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 11180 if (!elf) { 11181 pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1)); 11182 close(fd); 11183 return -LIBBPF_ERRNO__FORMAT; 11184 } 11185 11186 ret = elf_find_func_offset(elf, binary_path, name); 11187 elf_end(elf); 11188 close(fd); 11189 return ret; 11190} 11191 | |
11192/* Find offset of function name in archive specified by path. Currently 11193 * supported are .zip files that do not compress their contents, as used on 11194 * Android in the form of APKs, for example. "file_name" is the name of the ELF 11195 * file inside the archive. "func_name" matches symbol name or name@@LIB for 11196 * library functions. 11197 * 11198 * An overview of the APK format specifically provided here: 11199 * https://en.wikipedia.org/w/index.php?title=Apk_(file_format)&oldid=1139099120#Package_contents --- 1996 unchanged lines hidden --- | 11007/* Find offset of function name in archive specified by path. Currently 11008 * supported are .zip files that do not compress their contents, as used on 11009 * Android in the form of APKs, for example. "file_name" is the name of the ELF 11010 * file inside the archive. "func_name" matches symbol name or name@@LIB for 11011 * library functions. 11012 * 11013 * An overview of the APK format specifically provided here: 11014 * https://en.wikipedia.org/w/index.php?title=Apk_(file_format)&oldid=1139099120#Package_contents --- 1996 unchanged lines hidden --- |