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>
Thus emitting definitions/forward declarations for the types of function
pointers, not just for the return type of the function pointer.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This way cus__emit_typedef_definitions first looks for definitions in the
typedef that will be emitted, emits those definitions, then prints the typedef.
With this it'll be possible to make tag__print to print typedefs, when we know
that the definitions it needs were already previously emitted/printed.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
So that we can continue and see what was the problem, investigate using readelf
-wi and proceed to fix it, normally its just references to not yet supported
tags, so far the ones I know are not supported are DW_TAG_reference_type &
DW_TAG_namespace, i.e. tags not present in the C language, only on C++ and
other object oriented routines with such concepts.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>