Commit 0201c575 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov
Browse files

libbpf: Ensure ELF symbols table is found before further ELF processing



libbpf ELF parsing logic might need symbols available before ELF parsing is
completed, so we need to make sure that symbols table section is found in
a separate pass before all the subsequent sections are processed.

Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20200903203542.15944-2-andriin@fb.com
parent 83cf5c68
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -2720,14 +2720,38 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
	Elf *elf = obj->efile.elf;
	Elf_Data *btf_ext_data = NULL;
	Elf_Data *btf_data = NULL;
	Elf_Scn *scn = NULL;
	int idx = 0, err = 0;

	while ((scn = elf_nextscn(elf, scn)) != NULL) {
	const char *name;
		GElf_Shdr sh;
	Elf_Data *data;
	Elf_Scn *scn;
	GElf_Shdr sh;

	/* a bunch of ELF parsing functionality depends on processing symbols,
	 * so do the first pass and find the symbol table
	 */
	scn = NULL;
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		if (elf_sec_hdr(obj, scn, &sh))
			return -LIBBPF_ERRNO__FORMAT;

		if (sh.sh_type == SHT_SYMTAB) {
			if (obj->efile.symbols) {
				pr_warn("elf: multiple symbol tables in %s\n", obj->path);
				return -LIBBPF_ERRNO__FORMAT;
			}

			data = elf_sec_data(obj, scn);
			if (!data)
				return -LIBBPF_ERRNO__FORMAT;

			obj->efile.symbols = data;
			obj->efile.symbols_shndx = elf_ndxscn(scn);
			obj->efile.strtabidx = sh.sh_link;
		}
	}

	scn = NULL;
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		idx++;

		if (elf_sec_hdr(obj, scn, &sh))
@@ -2766,13 +2790,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
		} else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
			btf_ext_data = data;
		} else if (sh.sh_type == SHT_SYMTAB) {
			if (obj->efile.symbols) {
				pr_warn("elf: multiple symbol tables in %s\n", obj->path);
				return -LIBBPF_ERRNO__FORMAT;
			}
			obj->efile.symbols = data;
			obj->efile.symbols_shndx = idx;
			obj->efile.strtabidx = sh.sh_link;
			/* already processed during the first pass above */
		} else if (sh.sh_type == SHT_PROGBITS && data->d_size > 0) {
			if (sh.sh_flags & SHF_EXECINSTR) {
				if (strcmp(name, ".text") == 0)