Subject: | Problems with unnamed unions, enums and function pointers. |
Using Parse::Readelf::Debug::Info version 0.09, unnamed unions and enums
that are declared in a typedef do not get processed properly, and show
as size of zero when using 'structure_layout.pl'.
Same issue for function and function pointer typedefs.
Similar problem with forward definitions.
The following should demonstrate it.
// Test input for Parse::Readelf::Debug::Info.
// Build with: gcc -g structure_layout_test.c -o structure_layout_test
// Test with: perl structure_layout.pl structure_layout_test 2>&1 |less
typedef union
{
long int field1;
} union1;
typedef union union2
{
long int field2;
} union2;
typedef enum
{
ev1 = 1
} enum1;
typedef enum enum2
{
ev2 = 2
} enum2;
struct strut3; // Forward reference.
typedef struct struct3 *struct3p;
typedef struct
{
long int field3;
} struct3;
typedef char char_func(int *int_ptr);
typedef char_func *char_func_ptr;
int main(int argc, char *argv[])
{
static union1 u1 = {0};
static union2 u2 = {0};
static struct3 s3 = {0};
static struct3p sp3;
static enum1 e1;
static enum2 e2;
static char_func_ptr fp;
return 0;
}
#if 0
// With Parse::Readelf::Debug::Info version 0.09, unnamed unions and
enums
// that are declared in a typedef do not get processed properly, and
show
// as size of zero. Same for function and function pointer typedefs.
// Similar problem with forward definitions.
Use of uninitialized value in pattern match (m//) at Parse/Readelf/
Debug/Info.pm line 995.
Use of uninitialized value in pattern match (m//) at Parse/Readelf/
Debug/Info.pm line 995.
Use of uninitialized value in pattern match (m//) at Parse/Readelf/
Debug/Info.pm line 995.
Use of uninitialized value in pattern match (m//) at Parse/Readelf/
Debug/Info.pm line 995.
Use of uninitialized value in pattern match (m//) at Parse/Readelf/
Debug/Info.pm line 995.
O STRUCTURE TYPE (SIZE) SOURCE LOCATION
0 char_func (0) structure_layout_test.c:32
0 char_func_ptr char_func* (0) structure_layout_test.c:33
0 e1 enum1 (0) structure_layout_test.c:41
0 enum1 (0) structure_layout_test.c:18
0 e2 enum2 (4) structure_layout_test.c:42
0 enum2 enum2 (4) structure_layout_test.c:23
0 enum2 (4) structure_layout_test.c:21
0 enum1 (0) structure_layout_test.c:18
0 enum2 (4) structure_layout_test.c:21
0 enum2 enum2 (4) structure_layout_test.c:23
0 enum2 (4) structure_layout_test.c:21
0 field3 long int (4) structure_layout_test.c:29
0 fp char_func_ptr (4) structure_layout_test.c:43
0 char_func_ptr char_func* (0) structure_layout_test.c:33
0 s3 struct3 (4) structure_layout_test.c:39
0 struct3 (4) structure_layout_test.c:30
0 field3 long int (4) structure_layout_test.c:29
0 sp3 struct3p (4) structure_layout_test.c:40
0 struct3p struct3* (0) structure_layout_test.c:26
0 struct3 (4) structure_layout_test.c:30
0 field3 long int (4) structure_layout_test.c:29
0 struct3p struct3* (0) structure_layout_test.c:26
0 u1 union1 (0) structure_layout_test.c:37
0 union1 (0) structure_layout_test.c:8
0 u2 union2 (4) structure_layout_test.c:38
0 union2 union2 (4) structure_layout_test.c:13
0 union2 (4) structure_layout_test.c:11
0 union1 (0) structure_layout_test.c:8
0 union2 (4) structure_layout_test.c:11
0 union2 union2 (4) structure_layout_test.c:13
0 union2 (4) structure_layout_test.c:11
After the following Parse::Readelf::Debug::Info patches:
*** ./Parse/Readelf/Debug/Info.pm-orig 2011-03-21
17:07:10.962334008 -0700
--- ./Parse/Readelf/Debug/Info.pm 2011-03-22 06:43:05.506263049 -0700
***************
*** 50,55 ****
--- 50,61 ----
use Carp;
our $VERSION = '0.09';
+ ## JLB Added patches to handle some issues with unnamed unions and
enums
+ ## that are declared in a typedef that do not get processed properly,
+ ## and show as size of zero with:
+ ## http://cpansearch.perl.org/src/DORNER/Parse-Readelf-0.05/Examples/
structure_layout.pl
+ ## Same for function and function pointer typedefs. Similar problem
with
+ ## function pointers, and forward definitions.
use Parse::Readelf::Debug::Line;
***************
*** 398,404 ****
our @re_ignored_attributes =
( undef, undef,
! qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_(?:artificial|(?:entry|high|
low)_pc|macro_info|ranges|sibling|stmt_list|location\s*:\s*0x))i );
our @tag_needs_attributes =
(
--- 404,412 ----
our @re_ignored_attributes =
( undef, undef,
! ## JLB Ignore more attributes: prototyped, lower_bound,
upper_bound
! ## qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_(?:artificial|(?:entry|high|
low)_pc|macro_info|ranges|sibling|stmt_list|location\s*:\s*0x))i );
! qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_(?:artificial|prototyped|
lower_bound|upper_bound|(?:entry|high|low)_pc|macro_info|ranges|sibling|
stmt_lis
t|location\s*:\s*0x))i );
our @tag_needs_attributes =
(
***************
*** 411,428 ****
DW_TAG_const_type => [ qw(type) ],
DW_TAG_compile_unit => [ qw(name) ],
DW_TAG_enumerator => [ qw(name) ],
! DW_TAG_enumeration_type => [ qw(name byte_size) ],
DW_TAG_formal_parameter => [ qw(name type) ],
DW_TAG_member => [ qw(name type member_location) ],
! DW_TAG_pointer_type => [ qw(byte_size) ],
DW_TAG_ptr_to_member_type => [ qw(containing_type) ],
DW_TAG_reference_type => [ qw(type byte_size) ],
DW_TAG_structure_type => [],
DW_TAG_subrange_type => [ qw(upper_bound) ],
DW_TAG_typedef => [ qw(name type) ],
! DW_TAG_union_type => [ qw(name byte_size) ],
DW_TAG_variable => [ qw(name type) ],
! DW_TAG_volatile_type => [ qw(type) ]
}
);
--- 419,444 ----
DW_TAG_const_type => [ qw(type) ],
DW_TAG_compile_unit => [ qw(name) ],
DW_TAG_enumerator => [ qw(name) ],
! ## JLB Handle unnamed enums in typedefs.
! ## DW_TAG_enumeration_type => [ qw(name byte_size) ],
! DW_TAG_enumeration_type => [],
DW_TAG_formal_parameter => [ qw(name type) ],
DW_TAG_member => [ qw(name type member_location) ],
! ## JLB Handle function pointer typedefs.
! ##DW_TAG_pointer_type => [ qw(byte_size) ],
! DW_TAG_pointer_type => [],
DW_TAG_ptr_to_member_type => [ qw(containing_type) ],
DW_TAG_reference_type => [ qw(type byte_size) ],
DW_TAG_structure_type => [],
DW_TAG_subrange_type => [ qw(upper_bound) ],
DW_TAG_typedef => [ qw(name type) ],
! ## JLB Handle unnamed unions in typedefs.
! ## DW_TAG_union_type => [ qw(name byte_size) ],
! DW_TAG_union_type => [],
DW_TAG_variable => [ qw(name type) ],
! DW_TAG_volatile_type => [ qw(type) ],
! ## JLB Handle function pointer typedefs.
! DW_TAG_subroutine_type => [],
}
);
it is now somewhat better, although forward references not handled.
O STRUCTURE TYPE (SIZE) SOURCE LOCATION
0 char_func (1) structure_layout_test.c:32
0 char_func_ptr char_func* (1) structure_layout_test.c:33
0 e1 enum1 (4) structure_layout_test.c:41
0 enum1 (4) structure_layout_test.c:18
0 (4) structure_layout_test.c:16
0 e2 enum2 (4) structure_layout_test.c:42
0 enum2 enum2 (4) structure_layout_test.c:23
0 enum2 (4) structure_layout_test.c:21
0 enum1 (4) structure_layout_test.c:18
0 (4) structure_layout_test.c:16
0 enum2 (4) structure_layout_test.c:21
0 enum2 enum2 (4) structure_layout_test.c:23
0 enum2 (4) structure_layout_test.c:21
0 field3 long int (4) structure_layout_test.c:29
0 fp char_func_ptr (4) structure_layout_test.c:43
0 char_func_ptr char_func* (1) structure_layout_test.c:33
0 s3 struct3 (4) structure_layout_test.c:39
0 struct3 (4) structure_layout_test.c:30
0 field3 long int (4) structure_layout_test.c:29
0 sp3 struct3p (4) structure_layout_test.c:40
0 struct3p struct3* (0) structure_layout_test.c:26
0 struct3 (4) structure_layout_test.c:30
0 field3 long int (4) structure_layout_test.c:29
0 struct3p struct3* (0) structure_layout_test.c:26
0 u1 union1 (4) structure_layout_test.c:37
0 union1 (4) structure_layout_test.c:8
0 (4) structure_layout_test.c:8
0 u2 union2 (4) structure_layout_test.c:38
0 union2 union2 (4) structure_layout_test.c:13
0 union2 (4) structure_layout_test.c:11
0 union1 (4) structure_layout_test.c:8
0 (4) structure_layout_test.c:8
0 union2 (4) structure_layout_test.c:11
0 union2 union2 (4) structure_layout_test.c:13
0 union2 (4) structure_layout_test.c:11
#endif