CTF will need this distinction in that it handles functions differently, using
data in the ELF symbol table.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Only seen in some C++ inline expansion cases. Will appear as "(null)" in the
rendered source code.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Because we already use ctf__load in libctf.c, rename the others to
disambiguate, and also as there are the __load_dir and __load_files
it looks more consistent.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So after the next patch, when dwarf_loader will use this new core
functionality, it recognizes:
908 typedef int __m64 __attribute__ ((__vector_size__ (8))); size: 8
909 int array __attribute__ ((__vector_size__ (8))); size: 8
910 int array __attribute__ ((__vector_size__ (4))); size: 4
911 short int array __attribute__ ((__vector_size__ (2))); size: 2
912 char array __attribute__ ((__vector_size__ (1))); size: 1
The above output was obtained using pdwtags.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Nasty trick, but works and should be properly documented in the sources
and here:
If struct namespace.shared_tags is 1, we actually are reusing the list
of enumerators in another namespace, so we shouldn't delete them, for
that list_for_each_tag now means more for each _unshared_ tag, so that
cu__delete doesn't visits it, double freeing enumerator tags.
type__for_each_enumerator knows that and only for enums we'll set this
->shared_tags bit to 1, so we should be safe...
Disgusting? send me a patch, but without increasing memory or processing
footprints, please ;-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
CTF doesn't have support for multiple array dimensions, so it flattens
the arrays.
This caused a large number of false positives in ctfdwdiff, so introduce
this conf_fprintf option, use it in pahole and ctfdwdiff.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For a file with just DWARF info:
$ pahole -F ctf build/pahole
$
But if we ask that it also try dwarf:
$ pahole -F ctf,dwarf build/pahole | head -2
struct _IO_FILE {
int _flags; /* 0 4 */
$
Useful when testing the new CTF support in these tools, as we'll be able to,
from the DWARF info in objects, generate the CTF equivalent and add to the same
object, then run pahole -A -F ctf, pahole -A -F dwarf and compare the outputs.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that the user can specify what is the order it wants for decodind, as
we can have several debugging formats encoded in different ELF sections.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
I have to normalize this so that we don't have this special case, but
since we can have enum bitfields....
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Will later be used when generating the CTF info, be it in a separate
file, be it on a new ELF section inserted into this filename.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
To shorten the name and to reflect the fact that we're no longer
"finding" a type, but merely accessing an array with a bounds check in
this function.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Needed for reencoding DWARF bitfields, where we need to create a new
enum that has a bitfield_size bits size.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This will help us in the next csets when we need to know both the full
size of the base_type used in an bitfield _and_ the size in bits of the
bitfield member.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Because we will need the "bit_offset" and "bit_size" names when converting the
representation of offset and size everywhere to be in bits, not bytes.
At the same time we will keep bitfield_size and bitfield_offset when we convert
from DWARF to CTF and will calculate them when loading CTF, so that the
conversion of the algorithms in dwarves_reorganize, that have all sorts of
subtle issues, can be left for later.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
It makes no sense to try to lookup the abstract_origin (a Dwarf_Off)
after we recode the types just after load.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Amazing how many crept up over time, should have set the
execute bit of .git/hooks/pre-commit already, duh.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Out of cu__find_struct_by_name so that we can do a string__find
once and lookup the string id on multiple cus.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Also introducing cus__load, that load just one file.
The new cus__load_files routine now iterates thru the provided array
calling cus__load for each, and that in turn will try first dwarf__load,
and if that fail, i.e. if no DWARF info is found, call ctf__load.
This now allows loading DWARF _and_ CTF files at the same time. This
will be useful in the future when we, from DWARF generate CTF and at the
same time do a codiff, comparing the freshly generated CTF file with the
DWARF it came from.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Not used anymore now that cus__loadfl is sanitized. Now we can even
remove the fl (historically comes from libdwfl, when we used to pass an
argp, argh!).
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that, when not needing the DWARF info, the apps can tell that at load
time, and then the dwarf loader can just free all the dwarf_tags
allocated, reducing memory usage.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
To visit all parms, lexblocks, namespaces, i.e. not just the top level
tags listed in cu->tags.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
To take advantage of cache effects and to avoid calling cu__find_holes
more than once on the same struct.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
parameter__type was needed because the abstract_origin resolution was
done later, now it is at dwarf recode time, and for debugging formats
that don't have this crap, never. So it now can use the same idiom as
other tags: foo->tag.type.
parameter__name still exists because the tools still want a string
returned, but for some what they want is indeed the string_t, so that
when looking for a particular string it can be done as an string__find
for the key + integer comparision instead of doing a costlier strcmp.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Had to be a big sweeping change, but the regression tests shows just
improvements :-)
Now we stop using an id in struct tag, only storing the type, that now
uses 16 bits only, as CTF does.
Each format loader has to go on adding the types to the core, that
figures out if it is a tag that can be on the tag->type field
(tag__is_tag_type).
Formats that already have the types separated and in sequence, such as
CTF, just ask the core to insert in the types_table directly with its
original ID.
For DWARF, we ask the core to put it on the table, in sequence, and return the
index, that is then stashed with the DWARF specific info (original id, type,
decl_line, etc) and hashed by the original id. Later we recode everything,
looking up via the original type, getting the small_id to put on the tag->type.
The underlying debugging info not needed by the core is stashed in tag->priv,
and the DWARF loader now just allocates sizeof(struct dwarf_tag) at the end of
the core tag and points it there, and makes that info available thru
cu->orig_info. In the future we can ask, when loading a cu, that this info be
trown away, so that we reduce the memory footprint for big multi-cu files such
as the Linux kernel.
There is also a routine to ask for inserting a NULL, as we still have
bugs in the CTF decoding and thus some entries are being lost, to avoid
using an undefined pointer when traversing the types_table the ctf
loader puts a NULL there via cu__table_nullify_type_entry() and then
cu__for_each_type skips those.
There is some more cleanups for leftovers that I avoided cleaning to
reduce this changeset.
And also while doing this I saw that enums can appear without any
enumerators and that an array with DW_TAG_GNU_vector is actually a
different tag, encoded this way till we get to DWARF4 ;-)
So now we don't have to lookup on a hash table looking for DWARF
offsets, we can do the more sensible thing of just indexing the
types_tags array.
Now to do some cleanups and try to get the per cu encoder done. Then
order all the cus per number of type entries, pick the one with more,
then go on merging/recoding the types of the others and putting the
parent linkage in place.
Just to show the extent of the changes:
$ codiff /tmp/libdwarves.so.1.0.0 build/libdwarves.so.1.0.0
/home/acme/git/pahole/dwarves.c:
struct cu | -4048
struct tag | -32
struct ptr_to_member_type | -32
struct namespace | -32
struct type | -32
struct class | -32
struct base_type | -32
struct array_type | -32
struct class_member | -32
struct lexblock | -32
struct ftype | -32
struct function | -64
struct parameter | -32
struct variable | -32
struct inline_expansion | -32
struct label | -32
struct enumerator | -32
17 structs changed
tag__follow_typedef | +3
tag__fprintf_decl_info | +25
array_type__fprintf | +6
type__name | -126
type__find_first_biggest_size_base_type_member | -3
typedef__fprintf | +16
imported_declaration__fprintf | +6
imported_module__fprintf | +3
cu__new | +26
cu__delete | +26
hashtags__hash | -65
hash_64 | -124
hlist_add_head | -78
hashtags__find | -157
cu__hash | -80
cu__add_tag | +20
tag__prefix | -3
cu__find_tag_by_id | -2
cu__find_type_by_id | -3
cu__find_first_typedef_of_type | +38
cu__find_base_type_by_name | +68
cu__find_base_type_by_name_and_size | +72
cu__find_struct_by_name | +59
cus__find_struct_by_name | +8
cus__find_tag_by_id | +5
cus__find_cu_by_name | -6
lexblock__find_tag_by_id | -173
cu__find_variable_by_id | -197
list__find_tag_by_id | -308
cu__find_parameter_by_id | -60
tag__ptr_name | +6
tag__name | +15
variable__type | +13
variable__name | +7
class_member__size | +6
parameter__name | -119
tag__parameter | -14
parameter__type | -143
type__fprintf | -29
union__fprintf | +6
class__add_vtable_entry | -9
type__add_member | -6
type__clone_members | -3
enumeration__add | -6
function__name | -156
ftype__has_parm_of_type | -39
class__find_holes | -27
class__has_hole_ge | -3
type__nr_members_of_type | +3
lexblock__account_inline_expansions | +3
cu__account_inline_expansions | -18
ftype__fprintf_parms | +46
function__tag_fprintf | +24
lexblock__fprintf | -6
ftype__fprintf | +3
function__fprintf_stats | -18
function__size | -6
class__vtable_fprintf | -11
class__fprintf | -21
tag__fprintf | -35
60 functions changed, 513 bytes added, 2054 bytes removed, diff: -1541
/home/acme/git/pahole/ctf_loader.c:
struct ctf_short_type | +0
14 structs changed
type__init | -14
type__new | -9
class__new | -12
create_new_base_type | -7
create_new_base_type_float | -7
create_new_array | -8
create_new_subroutine_type | -9
create_full_members | -18
create_short_members | -18
create_new_class | +1
create_new_union | +1
create_new_enumeration | -19
create_new_forward_decl | -2
create_new_typedef | +3
create_new_tag | -5
load_types | +16
class__fixup_ctf_bitfields | -3
17 functions changed, 21 bytes added, 131 bytes removed, diff: -110
/home/acme/git/pahole/dwarf_loader.c:
17 structs changed
zalloc | -56
tag__init | +3
array_type__new | +20
type__init | -24
class_member__new | +46
inline_expansion__new | +12
class__new | +81
lexblock__init | +19
function__new | +43
die__create_new_array | +20
die__create_new_parameter | +4
die__create_new_label | +4
die__create_new_subroutine_type | +113
die__create_new_enumeration | -21
die__process_class | +79
die__process_namespace | +76
die__create_new_inline_expansion | +4
die__process_function | +147
__die__process_tag | +34
die__process_unit | +56
die__process | +90
21 functions changed, 851 bytes added, 101 bytes removed, diff: +750
/home/acme/git/pahole/dwarves.c:
struct ptr_table | +16
struct cu_orig_info | +32
2 structs changed
tag__decl_line | +68
tag__decl_file | +70
tag__orig_id | +71
ptr_table__init | +46
ptr_table__exit | +37
ptr_table__add | +183
ptr_table__add_with_id | +165
ptr_table__entry | +64
cu__table_add_tag | +171
cu__table_nullify_type_entry | +38
10 functions changed, 913 bytes added, diff: +913
/home/acme/git/pahole/ctf_loader.c:
2 structs changed
tag__alloc | +52
1 function changed, 52 bytes added, diff: +52
/home/acme/git/pahole/dwarf_loader.c:
struct dwarf_tag | +48
struct dwarf_cu | +4104
4 structs changed
dwarf_cu__init | +83
hashtags__hash | +61
hash_64 | +124
hlist_add_head | +78
hashtags__find | +161
cu__hash | +95
tag__is_tag_type | +171
tag__is_type | +85
tag__is_union | +28
tag__is_struct | +57
tag__is_typedef | +28
tag__is_enumeration | +28
dwarf_cu__find_tag_by_id | +56
dwarf_cu__find_type_by_id | +63
tag__alloc | +114
__tag__print_type_not_found | +108
namespace__recode_dwarf_types | +346
tag__namespace | +14
tag__has_namespace | +86
tag__is_namespace | +28
type__recode_dwarf_specification | +182
tag__type | +14
__tag__print_abstract_origin_not_found | +105
ftype__recode_dwarf_types | +322
tag__ftype | +14
tag__parameter | +14
lexblock__recode_dwarf_types | +736
tag__lexblock | +14
tag__label | +14
tag__recode_dwarf_type | +766
tag__ptr_to_member_type | +14
cu__recode_dwarf_types_table | +88
cu__recode_dwarf_types | +48
dwarf_tag__decl_file | +77
strings__ptr | +33
dwarf_tag__decl_line | +59
dwarf_tag__orig_id | +59
dwarf_tag__orig_type | +59
38 functions changed, 4432 bytes added, diff: +4432
build/libdwarves.so.1.0.0:
147 functions changed, 6782 bytes added, 2286 bytes removed, diff: +4496
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that we can then decide in what hashtable we will add it, and this
also paves the way for a type array that will help us in reducing the
size of struct tag by removing the id field.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Needed for CTF, where we can have many base types with name "unsigned",
but with different bit sizes, to implement bitfields.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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>