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 ---