dwarves/libbtf.h

70 lines
1.9 KiB
C
Raw Normal View History

/*
SPDX-License-Identifier: GPL-2.0-only
Copyright (C) 2019 Facebook
*/
#ifndef _LIBBTF_H
#define _LIBBTF_H
#include "gobuffer.h"
btf: Fix bitfield encoding The btf bitfield encoding is broken. For the following example: -bash-4.2$ cat t.c struct t { int a:2; int b:1; int :3; int c:1; int d; char e:1; char f:1; int g; }; void test(struct t *t) { return; } -bash-4.2$ clang -S -g -emit-llvm t.c The output for bpf "little and big" endian results with pahole dwarf2btf conversion: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=30 b type_id=6 bits_offset=29 c type_id=6 bits_offset=25 d type_id=3 bits_offset=32 e type_id=7 bits_offset=71 f type_id=7 bits_offset=70 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=3 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) The BTF struct member bits_offset counts bits from the beginning of the containing entity regardless of endianness, similar to what DW_AT_bit_offset from DWARF4 does. Such counting is equivalent to the big endian conversion in the above. But the little endian conversion is not correct since dwarf generates DW_AT_bit_offset based on actual bit position in the little endian architecture. For example, for the above struct member "a", the dwarf would generate DW_AT_bit_offset=30 for little endian, and DW_AT_bit_offset=0 for big endian. This patch fixed the little endian structure member bits_offset problem with proper calculation based on dwarf attributes. With the fix, we get: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=2 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=2 bits_offset=96 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [4] PTR (anon) type_id=1 [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=3 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ For both little endian and big endian, we have correct and same bits_offset for struct members. We could fix pos->bit_offset, but pos->bit_offset will be inconsistent to pos->bitfield_offset in the meaning and pos->bitfield_offset is used to print out pahole data structure: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ /bin/pahole t.o struct t { int a:2; /* 0:30 4 */ int b:1; /* 0:29 4 */ int c:1; /* 0:25 4 */ ..... So this patch just made the change in btf specific routines. Signed-off-by: Yonghong Song <yhs@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-09-13 18:19:40 +02:00
#include <stdbool.h>
#include <stdint.h>
struct btf {
union {
struct btf_header *hdr;
void *data;
};
void *priv;
Elf *elf;
GElf_Ehdr ehdr;
struct gobuffer types;
struct gobuffer *strings;
char *filename;
size_t size;
int swapped;
int in_fd;
uint8_t wordsize;
btf: Fix bitfield encoding The btf bitfield encoding is broken. For the following example: -bash-4.2$ cat t.c struct t { int a:2; int b:1; int :3; int c:1; int d; char e:1; char f:1; int g; }; void test(struct t *t) { return; } -bash-4.2$ clang -S -g -emit-llvm t.c The output for bpf "little and big" endian results with pahole dwarf2btf conversion: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=30 b type_id=6 bits_offset=29 c type_id=6 bits_offset=25 d type_id=3 bits_offset=32 e type_id=7 bits_offset=71 f type_id=7 bits_offset=70 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=3 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) The BTF struct member bits_offset counts bits from the beginning of the containing entity regardless of endianness, similar to what DW_AT_bit_offset from DWARF4 does. Such counting is equivalent to the big endian conversion in the above. But the little endian conversion is not correct since dwarf generates DW_AT_bit_offset based on actual bit position in the little endian architecture. For example, for the above struct member "a", the dwarf would generate DW_AT_bit_offset=30 for little endian, and DW_AT_bit_offset=0 for big endian. This patch fixed the little endian structure member bits_offset problem with proper calculation based on dwarf attributes. With the fix, we get: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=2 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=2 bits_offset=96 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [4] PTR (anon) type_id=1 [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ pahole -JV t.o [1] PTR (anon) type_id=2 [2] STRUCT t size=16 vlen=7 a type_id=5 bits_offset=0 b type_id=6 bits_offset=2 c type_id=6 bits_offset=6 d type_id=3 bits_offset=32 e type_id=7 bits_offset=64 f type_id=7 bits_offset=65 g type_id=3 bits_offset=96 [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none) [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none) [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none) -bash-4.2$ For both little endian and big endian, we have correct and same bits_offset for struct members. We could fix pos->bit_offset, but pos->bit_offset will be inconsistent to pos->bitfield_offset in the meaning and pos->bitfield_offset is used to print out pahole data structure: -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll -bash-4.2$ /bin/pahole t.o struct t { int a:2; /* 0:30 4 */ int b:1; /* 0:29 4 */ int c:1; /* 0:25 4 */ ..... So this patch just made the change in btf specific routines. Signed-off-by: Yonghong Song <yhs@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-09-13 18:19:40 +02:00
bool is_big_endian;
uint32_t type_index;
};
extern uint8_t btf_verbose;
#define btf_verbose_log(fmt, ...) { if (btf_verbose) printf(fmt, __VA_ARGS__); }
struct base_type;
btf: add func_proto support Two new btf kinds, BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO, have been added in kernel since https://patchwork.ozlabs.org/cover/1000176/ to support better func introspection. Currently, for a DW_TAG_subroutine_type dwarf type, a simple "void *" is generated instead of real subroutine type. This patch teaches pahole to generate BTF_KIND_FUNC_PROTO properly. After this patch, pahole should have complete type coverage for C frontend with types a bpf program cares. For example, $ cat t1.c typedef int __int32; struct t1 { int a1; int (*f1)(char p1, __int32 p2); } g1; $ cat t2.c typedef int __int32; struct t2 { int a2; int (*f2)(char q1, __int32 q2, ...); int (*f3)(); } g2; int main() { return 0; } $ gcc -O2 -o t1 -g t1.c t2.c $ pahole -JV t1 File t1: [1] TYPEDEF __int32 type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] STRUCT t1 kind_flag=0 size=16 vlen=2 a1 type_id=2 bits_offset=0 f1 type_id=6 bits_offset=64 [4] FUNC_PROTO (anon) return=2 args=(5 (anon), 1 (anon)) [5] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [6] PTR (anon) type_id=4 [7] TYPEDEF __int32 type_id=8 [8] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [9] STRUCT t2 kind_flag=0 size=24 vlen=3 a2 type_id=8 bits_offset=0 f2 type_id=12 bits_offset=64 f3 type_id=14 bits_offset=128 [10] FUNC_PROTO (anon) return=8 args=(11 (anon), 7 (anon), vararg) [11] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [12] PTR (anon) type_id=10 [13] FUNC_PROTO (anon) return=8 args=(vararg) [14] PTR (anon) type_id=13 $ In the above example, type [4], [10] and [13] represent the func_proto types. BTF_KIND_FUNC, which represents a real subprogram, is not generated in this patch and will be considered later. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-12-18 23:09:42 +01:00
struct ftype;
struct btf *btf__new(const char *filename, Elf *elf);
void btf__free(struct btf *btf);
int32_t btf__add_base_type(struct btf *btf, const struct base_type *bt);
int32_t btf__add_ref_type(struct btf *btf, uint16_t kind, uint32_t type,
btf: fix struct/union/fwd types with kind_flag This patch fixed two issues with BTF. One is related to struct/union bitfield encoding and the other is related to forward type. Issue #1 and solution: ====================== Current btf encoding of bitfield follows what pahole generates. For each bitfield, pahole will duplicate the type chain and put the bitfield size at the final int or enum type. Since the BTF enum type cannot encode bit size, commit b18354f64cc2 ("btf: Generate correct struct bitfield member types") workarounds the issue by generating an int type whenever the enum bit size is not 32. The above workaround is not ideal as we lost original type in BTF. Another undesiable fact is the type duplication as the pahole duplicates the type chain. To fix this issue, this patch implemented a compatible change for BTF struct type encoding: . the bit 31 of type->info, previously reserved, now is used to indicate whether bitfield_size is encoded in btf_member or not. . if bit 31 of struct_type->info is set, btf_member->offset will encode like: bit 0 - 23: bit offset bit 24 - 31: bitfield size if bit 31 is not set, the old behavior is preserved: bit 0 - 31: bit offset So if the struct contains a bit field, the maximum bit offset will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum bitfield size will be 255 which is enough for today as maximum bitfield in compiler can be 128 where int128 type is supported. A new global, no_bitfield_type_recode, is introduced and which will be set to true if BTF encoding is enabled. This global will prevent pahole duplicating the bitfield types to avoid type duplication in BTF. Issue #2 and solution: ====================== Current forward type in BTF does not specify whether the original type is struct or union. This will not work for type pretty print and BTF-to-header-file conversion as struct/union must be specified. To fix this issue, similar to issue #1, type->info bit 31 is used. If the bit is set, it is union type. Otherwise, it is a struct type. Examples: ========= -bash-4.4$ cat t.c struct s; union u; typedef int ___int; enum A { A1, A2, A3 }; struct t { int a[5]; ___int b:4; volatile enum A c:4; struct s *p1; union u *p2; } g; -bash-4.4$ gcc -c -O2 -g t.c Without this patch: $ pahole -JV t.o [1] TYPEDEF ___int type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] ENUM A size=4 vlen=3 A1 val=0 A2 val=1 A3 val=2 [4] STRUCT t size=40 vlen=5 a type_id=5 bits_offset=0 b type_id=13 bits_offset=160 c type_id=15 bits_offset=164 p1 type_id=9 bits_offset=192 p2 type_id=11 bits_offset=256 [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5 [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none) [7] VOLATILE (anon) type_id=3 [8] FWD s type_id=0 [9] PTR (anon) type_id=8 [10] FWD u type_id=0 [11] PTR (anon) type_id=10 [12] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none) [13] TYPEDEF ___int type_id=12 [14] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED [15] VOLATILE (anon) type_id=14 With this patch: $ pahole -JV t.o File t.o: [1] TYPEDEF ___int type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] ENUM A size=4 vlen=3 A1 val=0 A2 val=1 A3 val=2 [4] STRUCT t kind_flag=1 size=40 vlen=5 a type_id=5 bitfield_size=0 bits_offset=0 b type_id=1 bitfield_size=4 bits_offset=160 c type_id=7 bitfield_size=4 bits_offset=164 p1 type_id=9 bitfield_size=0 bits_offset=192 p2 type_id=11 bitfield_size=0 bits_offset=256 [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5 [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none) [7] VOLATILE (anon) type_id=3 [8] FWD s struct [9] PTR (anon) type_id=8 [10] FWD u union [11] PTR (anon) type_id=10 The fix removed the type duplication, preserved the enum type for the bitfield, and have correct struct/union information for the forward type. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-12-18 23:09:41 +01:00
uint32_t name, bool kind_flag);
int btf__add_member(struct btf *btf, uint32_t name, uint32_t type, bool kind_flag,
uint32_t bitfield_size, uint32_t bit_offset);
int32_t btf__add_struct(struct btf *btf, uint8_t kind, uint32_t name,
btf: fix struct/union/fwd types with kind_flag This patch fixed two issues with BTF. One is related to struct/union bitfield encoding and the other is related to forward type. Issue #1 and solution: ====================== Current btf encoding of bitfield follows what pahole generates. For each bitfield, pahole will duplicate the type chain and put the bitfield size at the final int or enum type. Since the BTF enum type cannot encode bit size, commit b18354f64cc2 ("btf: Generate correct struct bitfield member types") workarounds the issue by generating an int type whenever the enum bit size is not 32. The above workaround is not ideal as we lost original type in BTF. Another undesiable fact is the type duplication as the pahole duplicates the type chain. To fix this issue, this patch implemented a compatible change for BTF struct type encoding: . the bit 31 of type->info, previously reserved, now is used to indicate whether bitfield_size is encoded in btf_member or not. . if bit 31 of struct_type->info is set, btf_member->offset will encode like: bit 0 - 23: bit offset bit 24 - 31: bitfield size if bit 31 is not set, the old behavior is preserved: bit 0 - 31: bit offset So if the struct contains a bit field, the maximum bit offset will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum bitfield size will be 255 which is enough for today as maximum bitfield in compiler can be 128 where int128 type is supported. A new global, no_bitfield_type_recode, is introduced and which will be set to true if BTF encoding is enabled. This global will prevent pahole duplicating the bitfield types to avoid type duplication in BTF. Issue #2 and solution: ====================== Current forward type in BTF does not specify whether the original type is struct or union. This will not work for type pretty print and BTF-to-header-file conversion as struct/union must be specified. To fix this issue, similar to issue #1, type->info bit 31 is used. If the bit is set, it is union type. Otherwise, it is a struct type. Examples: ========= -bash-4.4$ cat t.c struct s; union u; typedef int ___int; enum A { A1, A2, A3 }; struct t { int a[5]; ___int b:4; volatile enum A c:4; struct s *p1; union u *p2; } g; -bash-4.4$ gcc -c -O2 -g t.c Without this patch: $ pahole -JV t.o [1] TYPEDEF ___int type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] ENUM A size=4 vlen=3 A1 val=0 A2 val=1 A3 val=2 [4] STRUCT t size=40 vlen=5 a type_id=5 bits_offset=0 b type_id=13 bits_offset=160 c type_id=15 bits_offset=164 p1 type_id=9 bits_offset=192 p2 type_id=11 bits_offset=256 [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5 [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none) [7] VOLATILE (anon) type_id=3 [8] FWD s type_id=0 [9] PTR (anon) type_id=8 [10] FWD u type_id=0 [11] PTR (anon) type_id=10 [12] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none) [13] TYPEDEF ___int type_id=12 [14] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED [15] VOLATILE (anon) type_id=14 With this patch: $ pahole -JV t.o File t.o: [1] TYPEDEF ___int type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] ENUM A size=4 vlen=3 A1 val=0 A2 val=1 A3 val=2 [4] STRUCT t kind_flag=1 size=40 vlen=5 a type_id=5 bitfield_size=0 bits_offset=0 b type_id=1 bitfield_size=4 bits_offset=160 c type_id=7 bitfield_size=4 bits_offset=164 p1 type_id=9 bitfield_size=0 bits_offset=192 p2 type_id=11 bitfield_size=0 bits_offset=256 [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5 [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none) [7] VOLATILE (anon) type_id=3 [8] FWD s struct [9] PTR (anon) type_id=8 [10] FWD u union [11] PTR (anon) type_id=10 The fix removed the type duplication, preserved the enum type for the bitfield, and have correct struct/union information for the forward type. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-12-18 23:09:41 +01:00
bool kind_flag, uint32_t size, uint16_t nr_members);
int32_t btf__add_array(struct btf *btf, uint32_t type, uint32_t index_type,
uint32_t nelems);
int32_t btf__add_enum(struct btf *btf, uint32_t name, uint32_t size,
uint16_t nr_entries);
int btf__add_enum_val(struct btf *btf, uint32_t name, int32_t value);
btf: add func_proto support Two new btf kinds, BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO, have been added in kernel since https://patchwork.ozlabs.org/cover/1000176/ to support better func introspection. Currently, for a DW_TAG_subroutine_type dwarf type, a simple "void *" is generated instead of real subroutine type. This patch teaches pahole to generate BTF_KIND_FUNC_PROTO properly. After this patch, pahole should have complete type coverage for C frontend with types a bpf program cares. For example, $ cat t1.c typedef int __int32; struct t1 { int a1; int (*f1)(char p1, __int32 p2); } g1; $ cat t2.c typedef int __int32; struct t2 { int a2; int (*f2)(char q1, __int32 q2, ...); int (*f3)(); } g2; int main() { return 0; } $ gcc -O2 -o t1 -g t1.c t2.c $ pahole -JV t1 File t1: [1] TYPEDEF __int32 type_id=2 [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [3] STRUCT t1 kind_flag=0 size=16 vlen=2 a1 type_id=2 bits_offset=0 f1 type_id=6 bits_offset=64 [4] FUNC_PROTO (anon) return=2 args=(5 (anon), 1 (anon)) [5] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [6] PTR (anon) type_id=4 [7] TYPEDEF __int32 type_id=8 [8] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED [9] STRUCT t2 kind_flag=0 size=24 vlen=3 a2 type_id=8 bits_offset=0 f2 type_id=12 bits_offset=64 f3 type_id=14 bits_offset=128 [10] FUNC_PROTO (anon) return=8 args=(11 (anon), 7 (anon), vararg) [11] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none) [12] PTR (anon) type_id=10 [13] FUNC_PROTO (anon) return=8 args=(vararg) [14] PTR (anon) type_id=13 $ In the above example, type [4], [10] and [13] represent the func_proto types. BTF_KIND_FUNC, which represents a real subprogram, is not generated in this patch and will be considered later. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-12-18 23:09:42 +01:00
int32_t btf__add_func_proto(struct btf *btf, struct ftype *ftype,
uint32_t type_id_off);
void btf__set_strings(struct btf *btf, struct gobuffer *strings);
int btf__encode(struct btf *btf, uint8_t flags);
btf_loader: Introduce a loader for the BTF format Show 'struct list_head' from DWARF info: $ pahole -C list_head ~/git/build/v4.20-rc5+/net/ipv4/tcp.o struct list_head { struct list_head * next; /* 0 8 */ struct list_head * prev; /* 8 8 */ /* size: 16, cachelines: 1, members: 2 */ /* last cacheline: 16 bytes */ }; Try to show it from BTF, on a file without it: $ pahole -F btf -C list_head ~/git/build/v4.20-rc5+/net/ipv4/tcp.o pahole: /home/acme/git/build/v4.20-rc5+/net/ipv4/tcp.o: No debugging information found Encode BTF from the DWARF info: $ pahole -J ~/git/build/v4.20-rc5+/net/ipv4/tcp.o Check that it is there: $ readelf -SW ~/git/build/v4.20-rc5+/net/ipv4/tcp.o | grep BTF readelf: /home/acme/git/build/v4.20-rc5+/net/ipv4/tcp.o: Warning: possibly corrupt ELF header - it has a non-zero program header offset, but no program headers [136] .BTF PROGBITS 0000000000000000 101d0e 042edf 00 0 0 1 Now try again printing 'struct list_head' from the BTF info just encoded: $ pahole -F btf -C list_head ~/git/build/v4.20-rc5+/net/ipv4/tcp.o 2> /dev/null struct list_head { struct list_head * next; /* 0 8 */ struct list_head * prev; /* 8 8 */ /* size: 16, cachelines: 1, members: 2 */ /* last cacheline: 16 bytes */ }; $ There is the bitfields case that BTF desn't have the bit_size info for bitfield members that makes the output from dwarf to be different than the one from BTF: $ pahole -F btf -C sk_buff ~/git/build/v4.20-rc5+/net/ipv4/tcp.o > /tmp/sk_buff.btf $ pahole -F dwarf -C sk_buff ~/git/build/v4.20-rc5+/net/ipv4/tcp.o > /tmp/sk_buff.dwarf $ diff -u /tmp/sk_buff.dwarf /tmp/sk_buff.btf --- /tmp/sk_buff.dwarf 2018-12-20 14:50:51.428653046 -0300 +++ /tmp/sk_buff.btf 2018-12-20 14:50:46.302601516 -0300 @@ -38,45 +38,45 @@ __u16 hdr_len; /* 138 2 */ __u16 queue_mapping; /* 140 2 */ __u8 __cloned_offset[0]; /* 142 0 */ - __u8 cloned:1; /* 142: 7 1 */ - __u8 nohdr:1; /* 142: 6 1 */ - __u8 fclone:2; /* 142: 4 1 */ - __u8 peeked:1; /* 142: 3 1 */ - __u8 head_frag:1; /* 142: 2 1 */ - __u8 xmit_more:1; /* 142: 1 1 */ - __u8 pfmemalloc:1; /* 142: 0 1 */ + __u8 cloned; /* 142 1 */ + __u8 nohdr; /* 142 1 */ + __u8 fclone; /* 142 1 */ + __u8 peeked; /* 142 1 */ + __u8 head_frag; /* 142 1 */ + __u8 xmit_more; /* 142 1 */ + __u8 pfmemalloc; /* 142 1 */ /* XXX 1 byte hole, try to pack */ __u32 headers_start[0]; /* 144 0 */ __u8 __pkt_type_offset[0]; /* 144 0 */ - __u8 pkt_type:3; /* 144: 5 1 */ - __u8 ignore_df:1; /* 144: 4 1 */ - __u8 nf_trace:1; /* 144: 3 1 */ - __u8 ip_summed:2; /* 144: 1 1 */ - __u8 ooo_okay:1; /* 144: 0 1 */ - __u8 l4_hash:1; /* 145: 7 1 */ - __u8 sw_hash:1; /* 145: 6 1 */ - __u8 wifi_acked_valid:1; /* 145: 5 1 */ - __u8 wifi_acked:1; /* 145: 4 1 */ - __u8 no_fcs:1; /* 145: 3 1 */ - __u8 encapsulation:1; /* 145: 2 1 */ - __u8 encap_hdr_csum:1; /* 145: 1 1 */ - __u8 csum_valid:1; /* 145: 0 1 */ - __u8 csum_complete_sw:1; /* 146: 7 1 */ - __u8 csum_level:2; /* 146: 5 1 */ - __u8 csum_not_inet:1; /* 146: 4 1 */ - __u8 dst_pending_confirm:1; /* 146: 3 1 */ - __u8 ndisc_nodetype:2; /* 146: 1 1 */ - __u8 ipvs_property:1; /* 146: 0 1 */ - __u8 inner_protocol_type:1; /* 147: 7 1 */ - __u8 remcsum_offload:1; /* 147: 6 1 */ - __u8 offload_fwd_mark:1; /* 147: 5 1 */ - __u8 offload_mr_fwd_mark:1; /* 147: 4 1 */ - __u8 tc_skip_classify:1; /* 147: 3 1 */ - __u8 tc_at_ingress:1; /* 147: 2 1 */ - __u8 tc_redirected:1; /* 147: 1 1 */ - __u8 tc_from_ingress:1; /* 147: 0 1 */ + __u8 pkt_type; /* 144 1 */ + __u8 ignore_df; /* 144 1 */ + __u8 nf_trace; /* 144 1 */ + __u8 ip_summed; /* 144 1 */ + __u8 ooo_okay; /* 144 1 */ + __u8 l4_hash; /* 145 1 */ + __u8 sw_hash; /* 145 1 */ + __u8 wifi_acked_valid; /* 145 1 */ + __u8 wifi_acked; /* 145 1 */ + __u8 no_fcs; /* 145 1 */ + __u8 encapsulation; /* 145 1 */ + __u8 encap_hdr_csum; /* 145 1 */ + __u8 csum_valid; /* 145 1 */ + __u8 csum_complete_sw; /* 146 1 */ + __u8 csum_level; /* 146 1 */ + __u8 csum_not_inet; /* 146 1 */ + __u8 dst_pending_confirm; /* 146 1 */ + __u8 ndisc_nodetype; /* 146 1 */ + __u8 ipvs_property; /* 146 1 */ + __u8 inner_protocol_type; /* 147 1 */ + __u8 remcsum_offload; /* 147 1 */ + __u8 offload_fwd_mark; /* 147 1 */ + __u8 offload_mr_fwd_mark; /* 147 1 */ + __u8 tc_skip_classify; /* 147 1 */ + __u8 tc_at_ingress; /* 147 1 */ + __u8 tc_redirected; /* 147 1 */ + __u8 tc_from_ingress; /* 147 1 */ __u16 tc_index; /* 148 2 */ /* XXX 2 bytes hole, try to pack */ $ Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-12-03 19:44:16 +01:00
char *btf__string(struct btf *btf, uint32_t ref);
int btf__load(struct btf *btf);
uint32_t btf__get32(struct btf *btf, uint32_t *p);
void *btf__get_buffer(struct btf *btf);
size_t btf__get_size(struct btf *btf);
#endif /* _LIBBTF_H */