| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # -*- coding: utf-8 -*- | 
| 2 |  |  |  |  |  |  | # Copyright (C) 2012-2015 Rocky Bernstein <rocky@cpan.org> | 
| 3 | 12 |  |  | 12 |  | 84 | use strict; use warnings; use utf8; | 
|  | 12 |  |  | 12 |  | 30 |  | 
|  | 12 |  |  | 12 |  | 296 |  | 
|  | 12 |  |  |  |  | 60 |  | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 308 |  | 
|  | 12 |  |  |  |  | 59 |  | 
|  | 12 |  |  |  |  | 28 |  | 
|  | 12 |  |  |  |  | 102 |  | 
| 4 | 12 |  |  | 12 |  | 272 | use rlib '../../..'; | 
|  | 12 |  |  |  |  | 29 |  | 
|  | 12 |  |  |  |  | 61 |  | 
| 5 | 12 |  |  | 12 |  | 3714 | use Devel::Trepan::DB::LineCache; # for map_file | 
|  | 12 |  |  |  |  | 28 |  | 
|  | 12 |  |  |  |  | 2410 |  | 
| 6 | 12 |  |  | 12 |  | 88 | use Devel::Trepan::Complete; | 
|  | 12 |  |  |  |  | 29 |  | 
|  | 12 |  |  |  |  | 1217 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | package Devel::Trepan::Processor; | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 12 |  |  | 12 |  | 98 | use vars qw(@EXPORT @ISA); | 
|  | 12 |  |  |  |  | 30 |  | 
|  | 12 |  |  |  |  | 783 |  | 
| 11 |  |  |  |  |  |  | @EXPORT    = qw( adjust_frame ); | 
| 12 |  |  |  |  |  |  | @ISA = qw(Exporter); | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 12 |  |  | 12 |  | 83 | use English qw( -no_match_vars ); | 
|  | 12 |  |  |  |  | 29 |  | 
|  | 12 |  |  |  |  | 69 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | sub adjust_frame($$$) | 
| 17 |  |  |  |  |  |  | { | 
| 18 | 0 |  |  | 0 | 0 | 0 | my ($self, $frame_num, $absolute_pos) = @_; | 
| 19 | 0 |  |  |  |  | 0 | my $frame; | 
| 20 | 0 |  |  |  |  | 0 | ($frame, $frame_num) = $self->get_frame($frame_num, $absolute_pos); | 
| 21 | 0 | 0 |  |  |  | 0 | if ($frame) { | 
| 22 | 0 |  |  |  |  | 0 | $self->{frame} = $frame; | 
| 23 | 0 |  |  |  |  | 0 | $self->{frame_index} = $frame_num; | 
| 24 | 0 | 0 |  |  |  | 0 | unless ($self->{settings}{traceprint}) { | 
| 25 |  |  |  |  |  |  | my $opts = { | 
| 26 |  |  |  |  |  |  | basename    => $self->{settings}{basename}, | 
| 27 |  |  |  |  |  |  | current_pos => $frame_num, | 
| 28 |  |  |  |  |  |  | maxwidth    => $self->{settings}{maxwidth}, | 
| 29 |  |  |  |  |  |  | displayop   => $self->{settings}{displayop}, | 
| 30 | 0 |  |  |  |  | 0 | }; | 
| 31 | 0 |  |  |  |  | 0 | $self->print_stack_trace_from_to($frame_num, $frame_num, $self->{frames}, $opts); | 
| 32 | 0 |  |  |  |  | 0 | $self->print_location ; | 
| 33 |  |  |  |  |  |  | } | 
| 34 | 0 |  |  |  |  | 0 | $self->{list_line} = $self->line(); | 
| 35 | 0 |  |  |  |  | 0 | $self->{list_filename} = $self->filename(); | 
| 36 | 0 |  |  |  |  | 0 | $self->{frame}; | 
| 37 |  |  |  |  |  |  | } else { | 
| 38 |  |  |  |  |  |  | undef | 
| 39 | 0 |  |  |  |  | 0 | } | 
| 40 |  |  |  |  |  |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | sub frame_low_high($;$) | 
| 43 |  |  |  |  |  |  | { | 
| 44 | 0 |  |  | 0 | 0 | 0 | my ($self, $direction) = @_; | 
| 45 | 0 | 0 |  |  |  | 0 | $direction = 1 unless defined $direction; | 
| 46 | 0 |  |  |  |  | 0 | my $stack_size = $self->{stack_size}; | 
| 47 | 0 |  |  |  |  | 0 | my ($low, $high) = (-$stack_size, $stack_size-1); | 
| 48 | 0 | 0 |  |  |  | 0 | ($low, $high) = ($high, $low) if ($direction < 0); | 
| 49 | 0 |  |  |  |  | 0 | return ($low, $high); | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | sub frame_setup($$) | 
| 53 |  |  |  |  |  |  | { | 
| 54 | 1 |  |  | 1 | 0 | 28 | my ($self, $frame_aref) = @_; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 1 | 50 |  |  |  | 5 | if (defined $frame_aref) { | 
| 57 | 1 |  |  |  |  | 3 | $self->{frames} = $frame_aref; | 
| 58 | 1 |  |  |  |  | 2 | $self->{stack_size}    = $#{$self->{frames}}+1; | 
|  | 1 |  |  |  |  | 5 |  | 
| 59 |  |  |  |  |  |  | } else { | 
| 60 |  |  |  |  |  |  | ### FIXME: look go over this code. | 
| 61 |  |  |  |  |  |  | # $stack_size contains the stack ignoring frames | 
| 62 |  |  |  |  |  |  | # of this debugger. | 
| 63 | 0 |  |  |  |  | 0 | my $stack_size = $DB::stack_depth; | 
| 64 | 0 |  |  |  |  | 0 | my @frames = $self->{dbgr}->tbacktrace(0); | 
| 65 | 0 | 0 |  |  |  | 0 | @frames = splice(@frames, 2) if $self->{dbgr}{caught_signal}; | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 0 | 0 |  |  |  | 0 | if ($self->{event} eq 'post-mortem') { | 
| 68 | 0 |  |  |  |  | 0 | $stack_size = 0; | 
| 69 | 0 |  |  |  |  | 0 | for my $frame (@frames) { | 
| 70 | 0 | 0 | 0 |  |  | 0 | next unless defined($frame) && exists($frame->{file}); | 
| 71 | 0 |  |  |  |  | 0 | $stack_size ++; | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  | } else { | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | # Figure out how many frames this debugger put in. | 
| 76 | 0 |  |  |  |  | 0 | my $debugger_frames_to_skip=0; | 
| 77 | 0 |  |  |  |  | 0 | while (my ($pkg, $file, $line, $fn) = | 
| 78 |  |  |  |  |  |  | caller($debugger_frames_to_skip++)) { | 
| 79 | 0 | 0 | 0 |  |  | 0 | last if 'DB::DB' eq $fn or ('DB' eq $pkg && 'DB' eq $fn); | 
|  |  |  | 0 |  |  |  |  | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | # Dynamic debugging might not have set $DB::stack_depth | 
| 83 |  |  |  |  |  |  | # correctly. So we'll doublecheck it here. | 
| 84 |  |  |  |  |  |  | # $stack_size_with_debugger contains the stack depth | 
| 85 |  |  |  |  |  |  | # *including* frames added by this debugger. | 
| 86 | 0 |  |  |  |  | 0 | my $stack_size_with_debugger = $debugger_frames_to_skip; | 
| 87 | 0 |  |  |  |  | 0 | $stack_size_with_debugger++ while defined caller($stack_size_with_debugger); | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | # Adjust for the fact that caller starts at 0; | 
| 90 | 0 |  |  |  |  | 0 | $stack_size_with_debugger++; | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 0 |  |  |  |  | 0 | my $computed_stack_depth = | 
| 93 |  |  |  |  |  |  | $stack_size_with_debugger - $debugger_frames_to_skip; | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | # printf("+++ debugger_frames_to_skip: %d, stack_size_with_debugger %d\n", | 
| 96 |  |  |  |  |  |  | # 	   $debugger_frames_to_skip, $stack_size_with_debugger); | 
| 97 |  |  |  |  |  |  | # printf("+++ computed_stack_depth: %d DB::stack_depth\n", $computed_stack_depth, $DB::stack_depth); | 
| 98 |  |  |  |  |  |  | # use Carp qw(cluck); cluck('testing'); | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 0 | 0 | 0 |  |  | 0 | if ((!defined $DB::stack_depth | 
|  |  |  | 0 |  |  |  |  | 
| 101 |  |  |  |  |  |  | or $DB::stack_depth < $computed_stack_depth) | 
| 102 |  |  |  |  |  |  | and !$self->{gave_stack_trunc_warning}) { | 
| 103 | 0 |  |  |  |  | 0 | $self->errmsg( | 
| 104 |  |  |  |  |  |  | "Call stack depth recorded in DB module is short. We've adjusted it."); | 
| 105 | 0 |  |  |  |  | 0 | $self->{gave_stack_trunc_warning} = 1; | 
| 106 |  |  |  |  |  |  | } | 
| 107 | 0 |  |  |  |  | 0 | $stack_size = $computed_stack_depth; | 
| 108 | 0 | 0 |  |  |  | 0 | $stack_size++ if $self->{event} eq 'call'; | 
| 109 |  |  |  |  |  |  | } | 
| 110 | 0 |  |  |  |  | 0 | $self->{frames} = \@frames; | 
| 111 | 0 |  |  |  |  | 0 | $self->{stack_size}    = $stack_size; | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 1 |  |  |  |  | 3 | $self->{frame_index}   = 0; | 
| 115 | 1 |  |  |  |  | 4 | $self->{hide_level}    = 0; | 
| 116 | 1 |  |  |  |  | 4 | $self->{frame}         = $self->{frames}[0]; | 
| 117 | 1 |  |  |  |  | 8 | $self->{list_line}     = $self->line(); | 
| 118 | 1 |  |  |  |  | 7 | $self->{list_filename} = $self->filename(); | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | sub filename($) | 
| 122 |  |  |  |  |  |  | { | 
| 123 | 1 |  |  | 1 | 0 | 2 | my $self = shift; | 
| 124 | 1 |  |  |  |  | 4 | my $filename = $self->{frame}{file}; | 
| 125 | 1 | 50 |  |  |  | 7 | if (filename_is_eval($filename)) { | 
| 126 | 0 |  |  |  |  | 0 | return $filename; | 
| 127 |  |  |  |  |  |  | } else { | 
| 128 | 1 |  |  |  |  | 11 | return map_file($filename); | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | sub funcname($) | 
| 133 |  |  |  |  |  |  | { | 
| 134 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 135 | 0 |  |  |  |  | 0 | $self->{frame}{fn}; | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | sub get_frame($$$) | 
| 139 |  |  |  |  |  |  | { | 
| 140 | 0 |  |  | 0 | 0 | 0 | my ($self, $frame_num, $absolute_pos) = @_; | 
| 141 | 0 |  |  |  |  | 0 | my $stack_size = $self->{stack_size}; | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 0 | 0 |  |  |  | 0 | if ($absolute_pos) { | 
| 144 | 0 | 0 |  |  |  | 0 | $frame_num += $stack_size if $frame_num < 0; | 
| 145 |  |  |  |  |  |  | } else { | 
| 146 | 0 |  |  |  |  | 0 | $frame_num += $self->{frame_index}; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 | 0 | 0 |  |  |  | 0 | if ($frame_num < 0) { | 
|  |  | 0 |  |  |  |  |  | 
| 150 | 0 |  |  |  |  | 0 | $self->errmsg('Adjusting would put us beyond the newest frame.'); | 
| 151 | 0 |  |  |  |  | 0 | return (undef, undef); | 
| 152 |  |  |  |  |  |  | } elsif ($frame_num >= $stack_size) { | 
| 153 | 0 |  |  |  |  | 0 | $self->errmsg('Adjusting would put us beyond the oldest frame.'); | 
| 154 | 0 |  |  |  |  | 0 | return (undef, undef); | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 0 |  |  |  |  | 0 | my $frames = $self->{frames}; | 
| 158 | 0 | 0 |  |  |  | 0 | unless ($frames->[$frame_num]) { | 
| 159 | 0 |  |  |  |  | 0 | my @new_frames = $self->{dbgr}->tbacktrace(0); | 
| 160 | 0 |  |  |  |  | 0 | $self->{frames}[$frame_num] = $new_frames[$frame_num]; | 
| 161 |  |  |  |  |  |  | } | 
| 162 | 0 |  |  |  |  | 0 | $self->{frame} = $frames->[$frame_num]; | 
| 163 | 0 |  |  |  |  | 0 | return ($self->{frame}, $frame_num); | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | sub line($) | 
| 167 |  |  |  |  |  |  | { | 
| 168 | 1 |  |  | 1 | 0 | 3 | my $self = shift; | 
| 169 | 1 |  |  |  |  | 3 | $self->{frame}{line}; | 
| 170 |  |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | sub print_stack_entry() | 
| 173 |  |  |  |  |  |  | { | 
| 174 | 0 |  |  | 0 | 0 |  | die "This should have been implemented somewhere else" | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | sub print_stack_trace_from_to($$$$$) | 
| 178 |  |  |  |  |  |  | { | 
| 179 | 0 |  |  | 0 | 0 |  | die "This should have been implemented somewhere else" | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | # Print `count' frame entries | 
| 183 |  |  |  |  |  |  | sub print_stack_trace($$$) | 
| 184 |  |  |  |  |  |  | { | 
| 185 | 0 |  |  | 0 | 0 |  | die "This should have been implemented somewhere else" | 
| 186 |  |  |  |  |  |  | } | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | 1; |