This is DWARF specific, we don't have in CTF, AFAIK, info about where a
variable is put, i.e. in a register? in the stack? etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
We'll use location in the DWARF sense, i.e. location lists, etc, i.e.
where is this variable? In a register? The stack? etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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>
That wasn't going into the tarballs generated when releasing new
versions.
Reported-by: Michal Schmidt <mschmidt@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Run 'perf ftrace' to show *btf* functions called to load, validate and
put in place data structures with the .BTF ELF section contents.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Updated elfutils to 0.173, using the fedora 28 packages and, as noted in
https://github.com/cilium/cilium/pull/5106/files ["bpf, doc: further
improvements on the BTF related section #5106"] there is no need to pass
the '-mattr=dwarfris' to llc to have DWARF sections correctly parsed by
tools like pahole.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This allows processing DW_TAG_partial_unit sections, which gets us from
no tags processed in files contained such tags to at least showing the
tags present in those sections.
Further work is required to support DW_TAG_compile_unit sections using
DW_TAG_imported_unit to import those DW_TAG_partial_unit sections, which
will be done by basically readding the contents of the
DW_TAG_partial_unit sections to the DW_TAG_compile_unit sections
importing them and then recoding as if all the tags in the partial units
were in the compile units.
This will make sure we have a contiguous series of types used in a
compile unit so that the converting routines to CTF and BTF can work
just as before.
On a fedora 27 system:
Before:
$ pahole /usr/lib/debug/usr/lib64/libgtk-3.so.0.2200.19.debug
die__process: DW_TAG_compile_unit or DW_TAG_type_unit expected got partial_unit!
$
After:
$ pahole /usr/lib/debug/usr/lib64/libgtk-3.so.0.2200.19.debug
struct _GTimeVal {
glong tv_sec; /* 0 8 */
glong tv_usec; /* 8 8 */
/* size: 16, cachelines: 1, members: 2 */
/* last cacheline: 16 bytes */
};
struct _GError {
GQuark domain; /* 0 4 */
gint code; /* 4 4 */
gchar * message; /* 8 8 */
/* size: 16, cachelines: 1, members: 3 */
/* last cacheline: 16 bytes */
};
struct _GCond {
gpointer p; /* 0 8 */
guint i[2]; /* 8 8 */
/* size: 16, cachelines: 1, members: 2 */
/* last cacheline: 16 bytes */
};
<SNIP some more structs found in DW_TAG_partial unit sections...>
struct _GSourceFuncs {
gboolean (*prepare)(GSource *, gint *); /* 0 8 */
gboolean (*check)(GSource *); /* 8 8 */
gboolean (*dispatch)(GSource *, GSourceFunc, gpointer); /* 16 8 */
void (*finalize)(GSource *); /* 24 8 */
GSourceFunc closure_callback; /* 32 8 */
GSourceDummyMarshal closure_marshal; /* 40 8 */
/* size: 48, cachelines: 1, members: 6 */
/* last cacheline: 48 bytes */
};
struct _GThreadFunctions {
GMutex * (*mutex_new)(void); /* 0 8 */
void (*mutex_lock)(GMutex *); /* 8 8 */
gboolean (*mutex_trylock)(GMutex *)tag__recode_dwarf_type: couldn't find 0x74 type for 0x7fc (typedef)!
tag__recode_dwarf_type: couldn't find 0x7e type for 0x829 (pointer_type)!
tag__recode_dwarf_type: couldn't find 0x829 type for 0x844 (variable)!
tag__recode_dwarf_type: couldn't find 0x7e type for 0x850 (variable)!
tag__recode_dwarf_type: couldn't find 0x22 type for 0x85b (variable)!
tag__recode_dwarf_type: couldn't find 0x22 type for 0x866 (variable)!
tag__recode_dwarf_type: couldn't find 0x22 type for 0x871 (variable)!
namespace__recode_dwarf_types: couldn't find 0x7fc type for 0x8a4 (member)!
tag__recode_dwarf_type: couldn't find 0xfa type for 0x8e8 (volatile_type)!
namespace__recode_dwarf_types: couldn't find 0x8b2 type for 0x90d (member)!
tag__recode_dwarf_type: couldn't find 0x1b type for 0x941 (typedef)!
<SNIP>
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This patch introduces BPF Type Format (BTF).
BTF (BPF Type Format) is the meta data format which describes
the data types of BPF program/map. Hence, it basically focus
on the C programming language which the modern BPF is primary
using. The first use case is to provide a generic pretty print
capability for a BPF map.
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
To help with using just that object file, avoiding processing big files
such as vmlinux, e.g.:
$ pahole -I vmlinux
<SNIP>
/* Used at: /home/acme/git/perf/init/main.c */
/* <1f4a5> /home/acme/git/perf/arch/x86/include/asm/orc_types.h:85 */
struct orc_entry {
s16 sp_offset; /* 0 2 */
s16 bp_offset; /* 2 2 */
unsigned int sp_reg:4; /* 4:28 4 */
unsigned int bp_reg:4; /* 4:24 4 */
unsigned int type:2; /* 4:22 4 */
/* size: 6, cachelines: 1, members: 5 */
/* padding: 65534 */
/* bit_padding: 22 bits */
/* last cacheline: 6 bytes */
/* BRAIN FART ALERT! 6 != 8 + 0(holes), diff = -2 */
};
<SNIP>
So I noticed that BFA, need to work on it, to make the testing process
faster, better not process vmlinux.o, instead, do:
$ pahole -C orc_entry ${kernel_build_dir}/init/main.o
Much faster, as main.o is much smaller than the vmlinux file.
Now to fix the processing of 'struct orc_entry'.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
If we processed at least one file we should return 0 to mean success.
Fixes: 02a456f5f5 ("pahole: Search and use running kernel vmlinux when no file is passed")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Seems like a nice shortcut for kernel hackers, and one that makes sure
the right vmlinux file is used, as it reads the running kernel build id
from /sys/kernel/notes and then searches the well known path for vmlinux
files:
vmlinux
/boot/vmlinux
/boot/vmlinux-4.14.0+
/usr/lib/debug/boot/vmlinux-`uname -r`
/lib/modules/`uname -r`/build/vmlinux
/usr/lib/debug/lib/modules/`uname -r`/vmlinux
/usr/lib/debug/boot/vmlinux-`uname -r`.debug
To find one with a matching build id (.notes ELF section, then
nhdr->n_type == NT_GNU_BUILD_ID), just like the Linux kernel 'perf
tools', where this code comes from, with some minor modifications to
cope with not having symbol_conf, symfs, etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Flavio needed this and found it only after some head scratching, add it.
Someone could help here by looking at other missing entries in the man
page, getting it in synch with 'pahole --help' ;-)
Reported-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The ghostprotocols.net domain is busted for a while, point to the
more permanent OLS proceedings pdf hosted at kernel.org.
Reported-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Take 'struct task_struct' in the Linux kernel, these fields:
/* --- cacheline 2 boundary (128 bytes) --- */
struct sched_entity se; /* 128 448 */
/* XXX last struct has 24 bytes of padding */
/* --- cacheline 9 boundary (576 bytes) --- */
struct sched_rt_entity rt; /* 576 48 */
The sched_entity struct has 24 bytes of padding, and that info would
only appear when printing 'struct task_struct' if class__find_holes()
had previously been run on 'struct sched_entity' which wasn't always the
case, make sure that happens.
This results in this extra stat being printed for 'struct task_struct':
/* paddings: 4, sum paddings: 38 */
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
A diff for 'pahole -EC task_struct vmlinux' should clarify what this fixes:
[acme@jouet linux]$ diff -u /tmp/before.c /tmp/after.c | head -30
--- /tmp/before.c 2016-06-29 17:00:38.082647281 -0300
+++ /tmp/a.c 2016-06-29 17:03:36.913124779 -0300
@@ -43,8 +43,8 @@
struct list_head * prev; /* 176 8 */
} group_node; /* 168 16 */
unsigned int on_rq; /* 184 4 */
+ /* --- cacheline 3 boundary (192 bytes) --- */
/* typedef u64 */ long long unsigned int exec_start; /* 192 8 */
- /* --- cacheline 1 boundary (64 bytes) was 4 bytes ago --- */
/* typedef u64 */ long long unsigned int sum_exec_runtime; /* 200 8 */
/* typedef u64 */ long long unsigned int vruntime; /* 208 8 */
/* typedef u64 */ long long unsigned int prev_sum_exec_runtime; /* 216 8 */
@@ -53,40 +53,40 @@
/* typedef u64 */ long long unsigned int wait_start; /* 232 8 */
/* typedef u64 */ long long unsigned int wait_max; /* 240 8 */
/* typedef u64 */ long long unsigned int wait_count; /* 248 8 */
+ /* --- cacheline 4 boundary (256 bytes) --- */
/* typedef u64 */ long long unsigned int wait_sum; /* 256 8 */
/* typedef u64 */ long long unsigned int iowait_count; /* 264 8 */
/* typedef u64 */ long long unsigned int iowait_sum; /* 272 8 */
/* typedef u64 */ long long unsigned int sleep_start; /* 280 8 */
/* typedef u64 */ long long unsigned int sleep_max; /* 288 8 */
- /* --- cacheline 1 boundary (64 bytes) --- */
/* typedef s64 */ long long int sum_sleep_runtime; /* 296 8 */
/* typedef u64 */ long long unsigned int block_start; /* 304 8 */
/* typedef u64 */ long long unsigned int block_max; /* 312 8 */
+ /* --- cacheline 5 boundary (320 bytes) --- */
/* typedef u64 */ long long unsigned int exec_max; /* 320 8 */
/* typedef u64 */ long long unsigned int slice_max; /* 328 8 */
/* typedef u64 */ long long unsigned int nr_migrations_cold; /* 336 8 */
[acme@jouet linux]$
I.e. the boundary detection was being reset at each expanded struct, do the math globally,
using the member offset, that was already done globally and correctly.
Reported-and-Tested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
That conf_fprintf can be elided as it is always NULL for the root call,
i.e. only when expanding types is that it will be called recursively.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
We need to get it under some ifdefs to avoid breaking the build in
distros where these tags are not defined.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This causes a segfault:
at /home/teuf/freesoftware/pahole/dwarf_loader.c:141
at /home/teuf/freesoftware/pahole/dwarf_loader.c:170
cu=0x66bc70) at /home/teuf/freesoftware/pahole/dwarf_loader.c:1535
at /home/teuf/freesoftware/pahole/dwarf_loader.c:1552
fn=0x7ffff79cd160 <__FUNCTION__.8133> "die__process_class")
at /home/teuf/freesoftware/pahole/dwarf_loader.c:1593
at /home/teuf/freesoftware/pahole/dwarf_loader.c:1288
We're not supposed to hash those unsupported tags, so just check for it and
avoid hashing.
Reported-by: Christophe Fergeau <cfergeau@redhat.com>
Cc: Dodji Seketeli <dodji@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Still need to check what to fprintf for this, but at least have it in
the type lists so that we can find it.
Reported-by: Christophe Fergeau <cfergeau@redhat.com>
Cc: Dodji Seketeli <dodji@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
No tool in this suite has any use for that, so just leave the comments
and pointers to the documentation for these tags and stop bothering the
user.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Need to read more on http://www.artima.com/cppsource/rvalue.html, but
handling it mostly like DW_TAG_typedef so that at least references to it
are resolved, we can get its byte size, etc.
FIXME: look at the vtable parameters, some are resolving to "(null)".
Reported-by: Benjamin Kosnik <bkoz@redhat.com>
Reported-by: Mark Wieelard <mjw@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=962571
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
$ cat foo
cat: foo: No such file or directory
Before:
$ pahole foo
pahole: No debugging information found
After:
$ pahole foo
pahole: foo: No such file or directory
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Before it would print no message, only update its exit status, now:
$ cat foo
cat: foo: No such file or directory
$ pdwtags foo
pdwtags: foo: No such file or directory
$ pdwtags /dev/null
ctf__new: cannot get elf header.
pdwtags: /dev/null: Invalid argument
$
Reported-by: Eric Blake <eblake@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=949034
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Silly bug, it was trying to return a negative index stating what file
had problems in the provided array, but if the first had problems it was
return -0, duh, fix it by returning the first as 1, etc.
With this, calling 'pdwtags non-existent-file' would return no errors
via $?.
Next csets will provide proper error messages, using what is in errno
and this index to tell what file has problems.
Reported-by: Eric Blake <eblake@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=949034
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
To deal with unrepresentable constant logarithms we end up causing a
build error, provide the declaration so that the compiler shut up.
Taken, as the other related code, from the Linux kernel sources.
For reference, the warning:
[ 40%] Building C object CMakeFiles/dwarves_reorganize.dir/dwarves_reorganize.o
/home/acme/git/pahole/dwarves_reorganize.c: In function ‘class__demote_bitfields’:
/home/acme/git/pahole/dwarves_reorganize.c:536:168: warning: implicit declaration of function ‘____ilog2_NaN’ [-Wimplicit-function-declaration]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The current release is v1.10, but CMakeLists.txt had just v1.9, fix it.
Reported-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
In class_member__dwarf_recode_bitfield, making it more robust, as
now we're in the process of supporting DW_TAG_partial_unit, where
some types seem to be in some ther unit and thus not being found
at the moment.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
It just about having a location expression that is referenced by other
tags to save space, since we don't have use for loc exprs so far, just
ignore it instead of spamming the user with "tag not supported"
warnings.
First seen on binaries generated by gcc 4.9
Reported-by: Diego Elio Pettenò <flameeyes@flameeyes.eu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
DW_TAG_mutable_type was a mistake in an early DWARFv3 draft and was
removed in the final version.
http://dwarfstd.org/ShowIssue.php?issue=050223.1
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
obstack_alloc was used in __tag__alloc to allocate tag object. As the
result some fields of the tag object are not initialized.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>