File Coverage

blib/lib/Parse/StackTrace/Type/GDB/Frame.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Parse::StackTrace::Type::GDB::Frame;
2 1     1   2057 use Moose;
  0            
  0            
3             use Parse::StackTrace::Exceptions;
4             use Data::Dumper;
5              
6             extends 'Parse::StackTrace::Frame';
7              
8             has 'memory_location' => (is => 'ro', isa => 'Str');
9             has 'lib_tag' => (is => 'ro', isa => 'Str');
10             has 'library' => (is => 'ro', isa => 'Str');
11              
12             # This describes a valid function name.
13             our $FUNCTION = qr/(?:[^\@]+?(?:\(.*\))?)|\S+/;
14              
15             our $FRAME_REGEX = qr/
16             ^\# (\d+) # 1 level
17             \s+ (?:(0x[A-Fa-f0-9]+)\s+in\s+)? # 2 location
18             ($FUNCTION) # 3 function
19             (?:\@+([\w\.]+))? # 4 libtag
20             \s+ \(([^\)]*)\) # 5 args
21             \s* (?:from\s(\S+))? # 6 library
22             \s* (?:at\s+([^:]+) # 7 file
23             : (\d+))? # 8 line
24             /x;
25              
26             # This is a strange frame format we get occasionally without a function.
27             our $FUNCTIONLESS_FRAME = qr/^#(\d+)\s+(0x[A-Fa-f0-9]+)\s+in\s+\(\)$/;
28              
29             # Sometimes people try to parse traces that don't contain parentheses for
30             # the arguments, which are actually the key part of the regex above.
31             # (Without them, some of the craziness doesn't work.) So for these
32             # particular frames, we just grab what we can (the function, memory_loc, etc.)
33             our $PARENLESS_FRAME = qr/^#(\d+)\s+(0x[A-Fa-f0-9]+)\s+in\s+($FUNCTION)$/;
34              
35             sub parse {
36             my ($class, %params) = @_;
37             my $lines = $params{'lines'};
38             my $debug = $params{'debug'};
39            
40             my $text = join(' ', @$lines);
41              
42             my %parsed;
43             if ($text =~ $FRAME_REGEX) {
44             %parsed = (number => $1, memory_location => $2,
45             function => $3, lib_tag => $4, args => $5,
46             library => $6, file => $7, line => $8);
47             }
48             elsif ($text =~ $FUNCTIONLESS_FRAME) {
49             %parsed = (number => $1, memory_location => $2, function => '??');
50             }
51             elsif ($text =~ $PARENLESS_FRAME) {
52             %parsed = (number => $1, memory_location => $2, function => $3);
53             }
54             elsif ($text =~ /^#(\d+)\s+(<signal handler called>)/) {
55             %parsed = (number => $1, function => $2, is_crash => 1);
56             }
57            
58             if (!%parsed) {
59             Parse::StackTrace::Exception::NotAFrame->throw(
60             "Not a valid GDB stack frame: " . join("\n", @$lines)
61             );
62             }
63            
64             foreach my $key (keys %parsed) {
65             delete $parsed{$key} if !defined $parsed{$key};
66             }
67             print STDERR "Parsed As: " . Dumper(\%parsed) if $debug;
68             return $class->new(%parsed);
69             }
70              
71             __PACKAGE__->meta->make_immutable;
72              
73             1;
74              
75             __END__
76              
77             =head1 NAME
78              
79             Parse::StackTrace::Type::GDB::Frame - A GDB stack frame
80              
81             =head1 DESCRIPTION
82              
83             This is an implementation of L<Parse::StackTrace::Frame> for GDB.
84              
85             Note that GDB frames never have a value for the C<code> accessor, but
86             they B<might> have values for all the other accessors.
87              
88             For frames where the function is unknown, the function will be C<??>
89             (because that's what GDB prints out in that case).
90              
91             =head1 METHODS
92              
93             In addition to the methods available from L<Parse::StackTrace::Frame>,
94             GDB frames possibly have additional information. All of these
95             are C<undef> if they are not available for this Frame.
96              
97             =head2 C<memory_location>
98              
99             Almost all frames contain a hexidecimal memory address where that
100             frame resides. This is that address, as a string starting with C<0x>
101              
102             =head2 C<lib_tag>
103              
104             Some stack frames have a piece of text like C<@GLIBC_2.3.2> after the
105             function name. This is the C<GLIBC_2.3.2> part of that.
106              
107             =head2 C<library>
108              
109             Some stack frames contain the filesystem path to the dynamic library
110             that the binary code of this function lives in. This is a string
111             representing that filesystem path.