btf_encoder: Use address size based on ELF's class

We can't assume the address size is always size of unsigned long, we
have to use directly the ELF's address size.

Change the 'addrs' array to __u64 and convert 32 bit address values when
copying from ELF section.

Committer notes:

Jiri tested this by:

<quote>
So to test this I built 32bit vmlinux and used 64bit pahole
to generate BTF data on both vmlinux and modules, which I
thought was valid use case.
</>

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Hao Luo <haoluo@google.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2020-12-03 23:06:24 +01:00 committed by Arnaldo Carvalho de Melo
parent aff60970d1
commit 06ca639505
1 changed files with 17 additions and 7 deletions

View File

@ -93,8 +93,8 @@ static int collect_function(struct btf_elf *btfe, GElf_Sym *sym)
static int addrs_cmp(const void *_a, const void *_b)
{
const unsigned long *a = _a;
const unsigned long *b = _b;
const __u64 *a = _a;
const __u64 *b = _b;
if (*a == *b)
return 0;
@ -102,9 +102,10 @@ static int addrs_cmp(const void *_a, const void *_b)
}
static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
unsigned long **paddrs, unsigned long *pcount)
__u64 **paddrs, __u64 *pcount)
{
unsigned long *addrs, count, offset;
__u64 *addrs, count, offset;
unsigned int addr_size, i;
Elf_Data *data;
GElf_Shdr shdr;
Elf_Scn *sec;
@ -128,8 +129,11 @@ static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
return -1;
}
/* Get address size from processed file's ELF class. */
addr_size = gelf_getclass(btfe->elf) == ELFCLASS32 ? 4 : 8;
offset = fl->mcount_start - shdr.sh_addr;
count = (fl->mcount_stop - fl->mcount_start) / 8;
count = (fl->mcount_stop - fl->mcount_start) / addr_size;
data = elf_getdata(sec, 0);
if (!data) {
@ -144,7 +148,13 @@ static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
return -1;
}
memcpy(addrs, data->d_buf + offset, count * sizeof(addrs[0]));
if (addr_size == sizeof(__u64)) {
memcpy(addrs, data->d_buf + offset, count * addr_size);
} else {
for (i = 0; i < count; i++)
addrs[i] = (__u64) *((__u32 *) (data->d_buf + offset + i * addr_size));
}
*paddrs = addrs;
*pcount = count;
return 0;
@ -152,7 +162,7 @@ static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
static int setup_functions(struct btf_elf *btfe, struct funcs_layout *fl)
{
unsigned long *addrs, count, i;
__u64 *addrs, count, i;
int functions_valid = 0;
/*