mirror of
https://github.com/netdata/libbpf.git
synced 2026-04-03 15:19:07 +08:00
libbpf: Introduce elf_find_func_offset_from_file() function
This change splits the elf_find_func_offset() function in two: elf_find_func_offset(), which now accepts an already opened Elf object instead of a path to a file that is to be opened, as well as elf_find_func_offset_from_file(), which opens a binary based on a path and then invokes elf_find_func_offset() on the Elf object. Having this split in responsibilities will allow us to call elf_find_func_offset() from other code paths on Elf objects that did not necessarily come from a file on disk. Signed-off-by: Daniel Müller <deso@posteo.net> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20230301212308.1839139-3-deso@posteo.net
This commit is contained in:
committed by
Andrii Nakryiko
parent
9ca6f946cd
commit
47eb62005a
57
src/libbpf.c
57
src/libbpf.c
@@ -10530,32 +10530,19 @@ static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find offset of function name in object specified by path. "name" matches
|
/* Find offset of function name in the provided ELF object. "binary_path" is
|
||||||
* symbol name or name@@LIB for library functions.
|
* the path to the ELF binary represented by "elf", and only used for error
|
||||||
|
* reporting matters. "name" matches symbol name or name@@LIB for library
|
||||||
|
* functions.
|
||||||
*/
|
*/
|
||||||
static long elf_find_func_offset(const char *binary_path, const char *name)
|
static long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
|
||||||
{
|
{
|
||||||
int fd, i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
|
int i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
|
||||||
bool is_shared_lib, is_name_qualified;
|
bool is_shared_lib, is_name_qualified;
|
||||||
char errmsg[STRERR_BUFSIZE];
|
|
||||||
long ret = -ENOENT;
|
long ret = -ENOENT;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
GElf_Ehdr ehdr;
|
GElf_Ehdr ehdr;
|
||||||
Elf *elf;
|
|
||||||
|
|
||||||
fd = open(binary_path, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_warn("failed to open %s: %s\n", binary_path,
|
|
||||||
libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
|
||||||
if (!elf) {
|
|
||||||
pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
|
|
||||||
close(fd);
|
|
||||||
return -LIBBPF_ERRNO__FORMAT;
|
|
||||||
}
|
|
||||||
if (!gelf_getehdr(elf, &ehdr)) {
|
if (!gelf_getehdr(elf, &ehdr)) {
|
||||||
pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1));
|
pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1));
|
||||||
ret = -LIBBPF_ERRNO__FORMAT;
|
ret = -LIBBPF_ERRNO__FORMAT;
|
||||||
@@ -10568,7 +10555,7 @@ static long elf_find_func_offset(const char *binary_path, const char *name)
|
|||||||
/* Does name specify "@@LIB"? */
|
/* Does name specify "@@LIB"? */
|
||||||
is_name_qualified = strstr(name, "@@") != NULL;
|
is_name_qualified = strstr(name, "@@") != NULL;
|
||||||
|
|
||||||
/* Search SHT_DYNSYM, SHT_SYMTAB for symbol. This search order is used because if
|
/* Search SHT_DYNSYM, SHT_SYMTAB for symbol. This search order is used because if
|
||||||
* a binary is stripped, it may only have SHT_DYNSYM, and a fully-statically
|
* a binary is stripped, it may only have SHT_DYNSYM, and a fully-statically
|
||||||
* linked binary may not have SHT_DYMSYM, so absence of a section should not be
|
* linked binary may not have SHT_DYMSYM, so absence of a section should not be
|
||||||
* reported as a warning/error.
|
* reported as a warning/error.
|
||||||
@@ -10681,6 +10668,34 @@ static long elf_find_func_offset(const char *binary_path, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find offset of function name in ELF object specified by path. "name" matches
|
||||||
|
* symbol name or name@@LIB for library functions.
|
||||||
|
*/
|
||||||
|
static long elf_find_func_offset_from_file(const char *binary_path, const char *name)
|
||||||
|
{
|
||||||
|
char errmsg[STRERR_BUFSIZE];
|
||||||
|
long ret = -ENOENT;
|
||||||
|
Elf *elf;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(binary_path, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_warn("failed to open %s: %s\n", binary_path,
|
||||||
|
libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
||||||
|
if (!elf) {
|
||||||
|
pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
|
||||||
|
close(fd);
|
||||||
|
return -LIBBPF_ERRNO__FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = elf_find_func_offset(elf, binary_path, name);
|
||||||
elf_end(elf);
|
elf_end(elf);
|
||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -10804,7 +10819,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
|
|||||||
if (func_name) {
|
if (func_name) {
|
||||||
long sym_off;
|
long sym_off;
|
||||||
|
|
||||||
sym_off = elf_find_func_offset(binary_path, func_name);
|
sym_off = elf_find_func_offset_from_file(binary_path, func_name);
|
||||||
if (sym_off < 0)
|
if (sym_off < 0)
|
||||||
return libbpf_err_ptr(sym_off);
|
return libbpf_err_ptr(sym_off);
|
||||||
func_offset += sym_off;
|
func_offset += sym_off;
|
||||||
|
|||||||
Reference in New Issue
Block a user