Now we just pass a NULL terminated array of filenames, since we got rid
of that ugly -e insertion hack.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This is still ugly, as the processing of argp was done on the loader so
that we can use the libdwfl argp processing, doing the tool argp
processing as a child. But then when we find out that there is no DWARF
info we fall back to another debugging format, with CTF being the only
other one supported as of now.
I used this scheme as when developing the CTF decoder and using pahole
on a binary with both CTF and DWARF info I would like to get the CTF
processed first.
So we still need some good refactoring here to get this sorted out in a
way that the user can specify the order of decoding, and perhaps even
ask for decoding _both_ and comparing if the results are the same, i.e.
if the (potentially subset of) information decoded from the first (that
may have less information: CTF) is the same as decoded from the second
(DWARF, more verbose).
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
And make the dwarves use it, so that we can remove duplicate strings in
a multi-CU file (vmlinux anyone?) and have it ready for insertion in a
compressed DWARF format with just the types, or better, CTF or some new
compressed debugging info format.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Basically a wrapper for ftype__fprintf(&function__proto, ...) for the
cases we want the prototype rendered to a buffer, not to a file.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Thanks to Dennis Lubert for bringing this to my attention, now tons of BRAIN
FART ALERTs are gone.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
By inlining them in the output when possible, that way we get context on where
the problem is, etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For correctly created and completely parsed debugging information the type will
always be found, but as we still need to parse more tags and expecting
debugging information to be always correctly built is not sane... sprinkle some
asserts.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This is trying to get CTF friendly, where bitfields are not stored in the
equivalent to the DW_TAG_member dwarf TAG, but on "base types" with bit sizes
different than the real in the DWARF sense, base types (char, long, etc).
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
In libdwarves.so well continue using DW_TAG_ entries and types for now, but its
becoming non-DWARF specific as will be demonstrated with the introduction of
ctf_loader.c in the upcoming csets.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
memdup() is only referenced from dwarves.c. This patch defines them
static. Further symbol hiding can be accomplished via GCC attributes:
Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Almost halves the time spent on processing a x86_64 vmlinux. Good, we
have features, now lets have performance ;-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
It will return NULL, this will be useful for codiff to use /dev/null as one of
the files being compared. And if you look for something in NULL, you better
get NULL, seems like a useful convention, huh?
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
What a mouthful ;-) To be used in finding the most aligned member in a non-packed
type, i.e. one that originally wasn't __attribute__((packed)).
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
That is not present in stable distros, where people trying the dwarves, for
now, should just disable build id support in this awkward way till I find out
how to do it properly using cmake.
Or you can get so annoyed to the point of submitting a patch to fix this ;-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This was found on an old openbsd kernel image that Leonardo Chiquito built
enabling DWARF instead of the default, STABS debugging format 8)
Just this struct has this characteristic:
struct ricoh_is410_window_data {
struct scsi_window_data window_data; /* 0 48 */
u_int8_t res1; /* 48 1 */
u_int8_t res2; /* 49 1 */
/* Bitfield combined with previous fields */
u_int mrif:1; /* 48:15 4 */
u_int filtering:3; /* 48:12 4 */
u_int gamma_id:4; /* 48: 8 4 */
/* size: 52, cachelines: 1 */
/* bit_padding: 24 bits */
/* last cacheline: 52 bytes */
};
Now there are no BRAIN FART ALERT!s when paholing openbsd, yay!
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Lots of BRAIN FART ALERT!s removed!
There is still a problem in class__find_holes where we don't catch bitfields
that are combined with previous fields where the byte offset for the bitfield
is the same as the previous field. This happens when the compiler combines a
bitfield with real byte size > 1 just after a one or two bytes field that is at
an alignment boundary.
Will fix later.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Make class__find_holes understand that when a byte offset goes backward it is
because the compiler is "combining" small bitfields with previous fields, and
using from the end of the combined bitfield + small fields. This made your
head hurt, huh? One example:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
/* XXX 4 bytes hole, try to pack */
char * bus_name; /* 16 8 */
u8 uses_dma; /* 24 1 */
u8 otg_port; /* 25 1 */
/* Bitfield combined with previous fields */
unsigned int is_b_host:1; /* 24:15 4 */
unsigned int b_hnp_enable:1; /* 24:14 4 */
/* XXX 14 bits hole, try to pack */
int devnum_next; /* 28 4 */
struct usb_devmap devmap; /* 32 16 */
<SNIP>
};
See? is_b_host:1 .. b_hnp_enable:1 makes a bitfield of just two bits.
The programmer decided to make this a 'unsigned int' bitfield, so taking 4 bytes.
And placed this "4" bytes bitfield just after two fields of one byte.
The compiler put the "4" bytes bitfield "in the same place" as the "uses_dma"
field, but its really not clobbering it neither "otg_port", as it allocates it
from (offset 24 + sizeof(unsigned int) - 1), backwards.
So at the end there is a, now correctly calculated, 14 bits hole, and that
matches the bit offset used for the last field, that is "14", as offsets for
bits and bytes starts at zero, all is explained now.
One last thing is that since we actually have 14 bits we in fact have a one
byte hole + a 6 bits hole, but that should be clear (haha) for those looking
for holes :-)
Nah, just run pahole reorganize on this beast and you'll have (for the complete
structure, with the <SNIP> part back in:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
unsigned char is_b_host:1; /* 12:247 1 */
unsigned char b_hnp_enable:1; /* 12:246 1 */
/* XXX 6 bits hole, try to pack */
u8 otg_port; /* 13 1 */
u8 uses_dma; /* 14 1 */
/* XXX 1 byte hole, try to pack */
char * bus_name; /* 16 8 */
int bandwidth_isoc_reqs; /* 24 4 */
int devnum_next; /* 28 4 */
struct usb_devmap devmap; /* 32 16 */
struct usb_device * root_hub; /* 48 8 */
struct list_head bus_list; /* 56 16 */
/* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
int bandwidth_allocated; /* 72 4 */
int bandwidth_int_reqs; /* 76 4 */
struct dentry * usbfs_dentry; /* 80 8 */
struct class_device * class_dev; /* 88 8 */
struct mon_bus * mon_bus; /* 96 8 */
int monitored; /* 104 4 */
/* size: 112, cachelines: 2 */
/* sum members: 107, holes: 1, sum holes: 1 */
/* bit holes: 1, sum bit holes: 6 bits */
/* padding: 4 */
/* last cacheline: 48 bytes */
}; /* saved 8 bytes! */
And we save 8 bytes and reduce the previous complexity. Hey, but look at those
bit offsets at is_b_host and b_hnp_enable... damn, exposing the bit offsets I
just exposed another bug, that is: the reorganization code is not fixing up the
bit offsets, one more for the TODO list, nah, just compile it and pass the
results back to the dwarves and we get:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
unsigned char is_b_host:1; /* 12: 7 1 */
unsigned char b_hnp_enable:1; /* 12: 6 1 */
/* XXX 6 bits hole, try to pack */
u8 otg_port; /* 13 1 */
u8 uses_dma; /* 14 1 */
/* XXX 1 byte hole, try to pack */
char * bus_name; /* 16 8 */
int bandwidth_isoc_reqs; /* 24 4 */
int devnum_next; /* 28 4 */
struct usb_devmap devmap; /* 32 16 */
struct usb_device * root_hub; /* 48 8 */
struct list_head bus_list; /* 56 16 */
/* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
int bandwidth_allocated; /* 72 4 */
int bandwidth_int_reqs; /* 76 4 */
struct dentry * usbfs_dentry; /* 80 8 */
struct class_device * class_dev; /* 88 8 */
struct mon_bus * mon_bus; /* 96 8 */
int monitored; /* 104 4 */
/* size: 112, cachelines: 2 */
/* sum members: 107, holes: 1, sum holes: 1 */
/* bit holes: 1, sum bit holes: 6 bits */
/* padding: 4 */
/* last cacheline: 48 bytes */
};
See? this time gcc fixed up things for us and even agreed on the reorganization
the dwarves did! 8-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Helps understanding how bitfields really work, and after all it is just
confusing, not wrong.
See this one:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
/* XXX 4 bytes hole, try to pack */
char * bus_name; /* 16 8 */
u8 uses_dma; /* 24 1 */
u8 otg_port; /* 25 1 */
/* WARNING: DWARF offset=24, real offset=26 */
unsigned int is_b_host:1; /* 24:15 4 */
unsigned int b_hnp_enable:1; /* 24:14 4 */
/* XXX 30 bits hole, try to pack */
int devnum_next; /* 28 4 */
<SNIP>
};
So the bitfield _really_ is at offset 24 and the "WARNING:" above is just
pahole not understanding how it works, i.e. it starts at 24 and since the
bitfield has a 'unsigned int' as its base type it goes from 24 to 27, the
offsets start at the end, i.e. from byte 27 back to byte 27, but as only two
bits are used, it puts bit padding at the end, at bit offset 0, that is the
last bit in byte 27 and uses the first bits of byte 26 at bit offset 14 and 15.
Now to make libdwarves finally understand this convention.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This struct, from the linux kernel:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
char * bus_name; /* 16 8 */
u8 uses_dma; /* 24 1 */
u8 otg_port; /* 25 1 */
unsigned int is_b_host:1; /* 24 4 */
unsigned int b_hnp_enable:1; /* 24 4 */
int devnum_next; /* 28 4 */
struct usb_devmap devmap; /* 32 16 */
struct usb_device * root_hub; /* 48 8 */
struct list_head bus_list; /* 56 16 */
int bandwidth_allocated; /* 72 4 */
int bandwidth_int_reqs; /* 76 4 */
int bandwidth_isoc_reqs; /* 80 4 */
struct dentry * usbfs_dentry; /* 88 8 */
struct class_device * class_dev; /* 96 8 */
struct mon_bus * mon_bus; /* 104 8 */
int monitored; /* 112 4 */
};
Generates seemingly wrong DWARF when compiled with GCC:
struct usb_bus {
struct device * controller; /* 0 8 */
int busnum; /* 8 4 */
/* XXX 4 bytes hole, try to pack */
char * bus_name; /* 16 8 */
u8 uses_dma; /* 24 1 */
u8 otg_port; /* 25 1 */
/* WARNING: DWARF offset=24, real offset=26 */
unsigned int is_b_host:1; /* 24 4 */
unsigned int b_hnp_enable:1; /* 24 4 */
/* XXX 30 bits hole, try to pack */
int devnum_next; /* 28 4 */
struct usb_devmap devmap; /* 32 16 */
struct usb_device * root_hub; /* 48 8 */
struct list_head bus_list; /* 56 16 */
/* --- cacheline 1 boundary (64 bytes) was 10 bytes ago --- */
int bandwidth_allocated; /* 72 4 */
int bandwidth_int_reqs; /* 76 4 */
int bandwidth_isoc_reqs; /* 80 4 */
/* XXX 4 bytes hole, try to pack */
struct dentry * usbfs_dentry; /* 88 8 */
struct class_device * class_dev; /* 96 8 */
struct mon_bus * mon_bus; /* 104 8 */
int monitored; /* 112 4 */
/* size: 120, cachelines: 2 */
/* sum members: 110, holes: 2, sum holes: 8 */
/* bit holes: 1, sum bit holes: 30 bits */
/* padding: 4 */
/* last cacheline: 56 bytes */
/* BRAIN FART ALERT! 120 != 110 + 8(holes), diff = 2 */
};
Look at the offset for the first entry in the bitfield (is_b_host), the
compiler said in the DWARF info that it was at offset 25, when in fact it is at
offset 26 as can be seen when looking at the generated assembly code.
This previously was confusing libdwarves, as it uses subtracts the last offset
from the current offset to see what was the size the compiler really allocated
to then check if it is equal to the size of the previous entry, so as to detect
alignment holes.
The offsets are uint32_t, so cast both to int64_t when doing the calculation,
the existing code already deals with negative numbers that result in this
patologic case.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
In ctracer we can find a function that receives as one of its arguments a
pointer to the target class and also a pointer to an alias or pointer class,
so we have to check if the function was already added to one of these lists:
class methods list
class aliases list
class pointer list
To avoid corrupting one of them by trying to add the function to multiple
lists.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
When we are looking for members of some type in all CUs it may be that in
some CU we don't have the full type, but just a declaration.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The latest elfutils-libelf headers won't compile without _LARGEFILE64_SOURCE
(that is implied by _GNU_SOURCE).
Some .c files don't have a #define _GNU_SOURCE line. Instead of adding the line
to all .c files, define it globally on CMakeLists.txt.
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Will just print the vtable as a comment on classes with vtables.
But we have to support multiple vtables when multiple inheritance exists.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that we can also look for offset expressions other than DW_AT_data_member_location.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Another C++ specific case:
- class TypeTemplate ByName(const string &, size_t);
+ class TypeTemplate ByName(const string &, size_t); /* linkage=_ZN4ROOT6Reflex12TypeTemplate6ByNameERKSsj */
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
More C++ support. Now we print "virtual" before DW_TAG_subprogram DW_TAG_member
tags that have a DW_AT_virtuality attribute of and DW_VIRTUALITY_pure_virtual or
DW_VIRTUALITY_virtual and " = 0" after the DW_VIRTUALITY_pure_virtual ones.
vtables are next.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
class__fprintf_cacheline_boundary should only be called if
conf_suppress_comments is not set.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
And use it when expandind pointer types (using --expand_pointer).
This has to be done because the offset comments make no sense when expanding a
pointer.
Will be used as well in pahole --quiet.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that we can expand pointer types, useful for ABI signature checking. And to
fully browse a type, when using --expand_types is also of interest.
I have yet to disable printing the offsets when expanding pointers, where the
information is not useful at all, for now just ignore it, it gets back to a
sane state in the next field, after the pointer type expansion.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
For now it just suppresses the struct statistics at the end of the output, but
will also suppress the comments about holes.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
To indicate wheter the semicolon should be supressed. Useful for
prototype/function emission, etc.
Also move the struct stats to be inside its body, to simplify tag__fprintf,
that now looks at conf.no_semicolon after calling the tag type specific
__fprintf method.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that tools can specify if they are interested in printing just the members
that use space in the class layout (DW_TAG_inheritance, DW_TAG_member) and not
things like constructors, private type definitions, etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So far we only handle DW_OP_plus_uconst, the simplest of them all, but now
'public virtual' base classes are appearing in these tools radar, so, to make
it clear that we don't support it spit a warning message to stderr and return
UINT64_MAX so that in the report it is clearly seen. C++ support still needs
more work, simple as that :)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that we traverse just the data members, mostly in the reorganize code, where
we can't care less where is that the compiler put the base classes in the
layout since we can't influence how the compiler does this, it has only to
respect the layout we specify for the data members.
Well, it may well be the case that the order of the ancestor classes in the
class declaration can influence this, but I haven't checked.
Yes, another C++ism :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
This is simplified by introducing list__find_tag_by_id. I guess in the end the
right thing is to use a hashtable to find the ids. Trying to have specialized
find_foo_by_id functions instead of having just one that traverses _all_ the
tags is becoming less of a performance advantage as struct class now has
namespaces, i.e. functions can be inside structs and to find abstract_origin,
specification, etc references we have to traverse most of the tree anyway...
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Heck, anonymous structs are nothing new, things like:
typedef struct {
int bar;
} baz;
Are ugly, but valid. So if ->name is NULL and ->specification is 0, its an
anonymous struct, don't go looking for dwarf offset 0, that is "void", not
something a DW_AT_specification is supposed to point to 8)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
tag__type_not_found was incorrectly being used for cases where we were
searching things like abstract_origin and specification, not tag->type, so add
this variant, make tag__type_not_found use id and fix the callers.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Basic support, as according to the DWARF3 standard there are other cases that
we don't support yet, such as "using ::foo" with an alias, i.e. in the
namespace that is importing the imported declaration is aliased to some other
name.
But for the test cases, common case, its enough.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
The "using namespace" line in:
namespace __gnu_debug {
using namespace __gnu_debug_def;
};
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Now we see the "private:\n" etc, everytime the accessibility is changed from
one member to the next.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Helper to check if the tag has accessibility info, returning one of
"protected", "private", "public" or NULL if there is no accessibility info.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Will be used in the following csets, where we'll print the accessibility
info in C++ classes.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
The offsets doesn't make sense, /me lazy right now to look at untangling the
expressions in the DW_AT_data_member_location.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
C++ uses this, and to cache the result of the lookup at type__name time we need
to pass the cu to class__name and type__name. Big fallout because of that :-\
But now the output is mucho embelished by the humongous strings representing
C++ templates.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Using it in the --dwarf_offset/-O new pahole command line option, useful in
debugging. Prints the tag in the dwarf offset supplied.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
In class__fprintf, at least this can help till we get proper DW_TAG_inheritance
layout printing, that is right now blocked by lack of knowledge about
DW_AT_data_member_location DWARF expression parsing for non const expressions.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that in DW_TAG_inheritance we can should "virtual", "virtual public", etc.
This has yet to be supported for normal class members, constructors, etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Use pdwtags, that prints all the tags, pahole has to be changed to traverse
namespaces looking for structs.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Go down the rabbit hole baby, oops, the namespace hole that is. Now we find
types inside namespaces. Off to implement namespace__fprintf so that we can see
more brunnetes and blondes out of the DWARF encoding 8)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
For now its just the direct ancestor of struct type. But it will exists by
itself, to represent the DW_TAG_namespace DWARF tag, that is how the C++
'namespace' (and other languages too, heck, I'd love to get my hands on a
binary with DWARF info built from, say, ADA source code, objectiveC... COBOL!
:-P).
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
This is in preparation for the introduction of struct namespace, that will be
struct type ancestor.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Such as types within types and class methods. This greatly improves support for
C++. Next improvements will be supporting DW_TAG_namespace and properly
supporting DW_TAG_inheritance.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Will be useful to show that the intent is to traverse just the DW_TAG_member
entries in the type list. Right now there are both DW_TAG_inheritance and
DW_TAG_member entries in the ->members type list. But there will be many more
tags, like enumerations, classes, etc, that are defined inside classes, a C++
feature. This will also help with DW_TAG_namespace support.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
First user is pahole, that now has a --contains CLASS_NAME option, that will
show which classes contains CLASS_NAME, i.e.:
struct foo {
struct bar baz;
int i;
};
on an object file called with '--contains bar' will produce:
foo
if --verbose is used it will tell the number of CLASS_NAME members, so, in the
above example:
foo:1
Next thing will be a --recursive flag, that will show all the structs that
contains CLASS_NAME and the ones that contains the ones which contains and...
:-)
Useful to evaluate the impact that increasing or decreasing the size of some
important struct will have on the whole project that uses the struct.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
By default, pahole will display the offsets of the inner struct members from
the top level struct. If the user wants to focus on some inner structs, just
call the tool with the -r option to use relative offset instead of the base
offset.
Signed-off-by: Eugene Teo <eteo@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that we can go on adding more config knobs without requiring adding new
parameters to lots of functions.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
1. if the first member is a bitfield, we have to have set current_bitfield_size to 0
prior to entering the loop.
2. If sizeof(last member) == 0, don't try to move it
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Confusing huh? Think about ____cacheline_aligned_in_smp, and you'll get the
idea, look at this patch inline comment to understand the issue.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
E.g. in struct net_device when moving sysfs_groups[3] to after reg_state,
sizeof(sisfs_groups[3]) is 24 and the hole found after some reorganizing after
reg_state is 80 bytes, so align it just after reg_state, not 8 bytes after it.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Now there is a cus__loadfl function that receives the tool argp tables and uses
libdwfl to process the DWARF info, with this RELA objects such as .o and .ko
files in a Linux kernel build are supported, and all the other goodies that
come from using libdwfl, such as separate debuginfo files, etc come as a bonus.
Now to convert the tools, pahole being the first, that already works well using
cus__loadfl().
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
[acme@filo examples]$ pahole -a mpg_audio_frame_t
/* <14f> /home/acme/git/pahole/examples/mpg_audio_frame_t.c:4 */
typedef struct {
uint16_t frame_sync; /* 0 2 */
uint8_t layer; /* 2 1 */
/* WARNING: DWARF offset=0, real offset=3 */
uint32_t mpeg25_bit:1; /* 0 4 */
uint32_t lsf_bit:1; /* 0 4 */
uint32_t bitrate_idx:4; /* 0 4 */
<SNIP>
So gcc combined a uint16_t + a uint8_t + the first entries in the uint32_t
bitfield that could fit in the 8 bits after the first two fields but haven't
updated the size of the bitfield (4) and wrote 0 as the offset, warn about such
inconsistencies.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
So that we print the boundary after the last member in a bitfield.
Spotted by Matthew Wilcox.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
[acme@mica pahole]$ pahole lala
pahole: Permission denied
[acme@mica pahole]$ pahole foo
pahole: No such file or directory
[acme@mica pahole]$ pahole ctracer.c
pahole: couldn't load DWARF info from ctracer.c
[acme@mica pahole]$
Thanks to Matthew Wilcox for noticing how lame it was :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
[acme@filo pahole]$ cat examples/expand_typedefs.c
<SNIP>
typedef struct {
int a, b, c;
} inner;
static struct outer {
int q, b;
inner m;
} foo;
<SNIP>
[acme@filo pahole]$ pahole --expand_types examples/expand_typedefs
/* <158> /home/acme/git/pahole/examples/expand_typedefs.c:7 */
struct outer {
int q; /* 0 4 */
int b; /* 4 4 */
/* typedef inner */ struct {
int a; /* 0 4 */
int b; /* 4 4 */
int c; /* 8 4 */
} m; /* 8 12 */
}; /* size: 20, cachelines: 1 */
/* last cacheline: 20 bytes */
/* definitions: 1 */
[acme@filo pahole]$
For now it does all typedef expansions, which in at least the base types may be
a bit too much, e.g. u32 -> unsigned long int, lets see if somebody complains,
perhaps even myself 8) If that is the case we can add yet another command line
option to specify that such base type expansions should be filtered out, making
the expand_types parameter be flag mask, not just a boolean as it is today.
To see a more complete output look at:
http://oops.ghostprotocols.net:81/acme/dwarves/vmlinux-pahole-expand_types-typedef_unfolding.txt
Suggested by Jeff Muizelaar.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that we get rid of all the buffer limits, if we need to format into strings
we can use string streams, like we're doing now in just one case, tag__name for
DW_TAG_subroutine_type, that is bogus as it is, as we need to have the name of
the type inside the type declaration (void (*type_name)(parameters)) and not
after (void (*)(parameters) type_name)), but leave this for an upcoming cset.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
And use it in a new tool, pglobal, that shows global variables and functions.
Signed-off-by: Davi Arnaut <davi@haxent.com.br>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that in tools like ctracer we can print to a file, most of the tools just
pass stdout, keeping the previous behaviour.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Will be used in ctracer to create a struct subset with just the types for which
we have "collectors", i.e. functions that reduce complex types to base types
that will be put in the mini-struct, that will be as tightly packed as it can
be.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Using export CFLAGS="-Wall -Wfatal-errors -Wformat=2 -Wsequence-point -Wextra
-Wno-parentheses -g", suggested by Davi Arnault, amazing how cruft piles up
when one is not looking ;)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Some are just typedefs, others are inside structs and in some cases its
useful to see the statistics for them, so add two new cmd line options:
-a, --anon_include include anonymous classes\
-A, --nested_anon_include include nested (inside other structs) anonymous classes
Commiter note: I've reworked several aspects of the patch, but mostly to
give better names for the new find_first_typedef_of_type function, adding
a clarifying comment and introducing --nested_anon_include so that we
can select just the typedef'ed anonymous structs.
Signed-off-by: Davi Arnaut <davi@haxent.com.br>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Previously it was being added to the CU tag list.
This also fixes a problem in cu__find_parameter_by_id where the second test in
the loop was actually outside the loop due to lack of {}.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Better, to match the readelf (binutils) and eu-readelf (elfutils) tools,
that on multi CU blobs is the way to go.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
That was preventing the correct printing of anonymous struct typedefs.
Signed-off-by: Davi Arnaut <davi@haxent.com.br>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Recheck if the typedef was emitted as part of the emission of its target, as
there are cases, like wait_queue_t in the Linux kernel, that is against struct
__wait_queue, that has a wait_queue_func_t member, a function typedef that has
as one of its parameters a... wait_queue_t, that will thus be emitted before
the function typedef, making a no go to redefine the typedef after struct
__wait_queue.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
And it even shrinks the lib a bit :-)
[acme@filo pahole]$ codiff build/libdwarves.so.before build/libdwarves.so
/home/acme/git/pahole/dwarves.c:
cus__emit_tag_definitions | -68
1 function changed, 68 bytes removed
[acme@filo pahole]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Now the functions that call cus__emit_enumeration_definitions should call
tag__print_decl_info, so that if it is a typedef we can just print "typedef ",
then call the enum printing routines.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
I.e. things like
typedef struct foo bar;
will emit the definition for struct foo before emitting the above line.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Where the 'if' should be just one of of the cases in the 'switch', and guess
what:
This:
diff --git a/dwarves.c b/dwarves.c
index c0ae7c8..34f29a1 100644
--- a/dwarves.c
+++ b/dwarves.c
@@ -2580,10 +2580,10 @@ static int cus__emit_typedef_definitions
}
type = cu__find_tag_by_id(cu, tdef->type);
- if (type->tag == DW_TAG_typedef)
- cus__emit_typedef_definitions(self, cu, type);
-
switch (type->tag) {
+ case DW_TAG_typedef:
+ cus__emit_typedef_definitions(self, cu, type);
+ break;
case DW_TAG_pointer_type:
ptr_type = cu__find_tag_by_id(cu, type->type);
if (ptr_type->tag != DW_TAG_subroutine_type)
Results in this:
[acme@newtoy pahole]$ codiff -V build/libdwarves.so.orig build/libdwarves.so
/home/acme/pahole/dwarves.c:
cus__emit_typedef_definitions | -18 # 466 -> 448
1 function changed, 18 bytes removed
[acme@newtoy pahole]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
tag__print on a DW_TAG_subprogram tag prints just the function prototype,
without the ending ";\", so if a user wants to print the whole function its
just a matter of calling tag__print + lexblock__(tag__function(tag), cu,
indent).
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This should not happen, but right now happens as we don't support all the C++
tags, so some types are not being collected when inside DW_TAG_namespace dies.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
And since there are no external users now, just unexport it, ditto
for tag__print_decl_info.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Its up to its callers, that will be moot soon as tag__print will call
function__print and as it already prints the decl info it'll be just a matter
of making all the function__print callers call tag__print instead and then
function__print will be unexported.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>