3 # (eu-unstrip -n --core=`echo ./core.*`; echo; gdb -nx -ex "set debug-file-directory /_N" -ex "core-file `echo ./core.*`" -ex bt -ex q) 2>/dev/null | retrace
8 delete @ENV{qw(PATH BASH_ENV)};
9 my $hex=qr/[[:xdigit:]]/;
10 my $tmp="/tmp/retrace.$$";
17 system $cmd and die "$cmd: $!";
25 open F,$fname or die $fname;
26 my $F=do { local $/; <F>; };
27 defined $F or die $fname;
28 close F or die $fname;
34 my($fname,$content)=@_;
37 open F,">$fname" or die $fname;
38 print F $content or die $fname;
39 close F or die $fname;
50 set architecture i386:x86-64
54 sub buildid_to_filename($)
58 $hash=~/^($hex{2})($hex{38})$/o or die;
59 local $_=readfile "readlink -f /usr/lib/debug/.build-id/$1/$2 |";
64 sub filename_to_text_off($)
68 my $headers=readfile "eu-readelf --section-headers $filename |";
71 # [Nr] Name Type Addr Off Size ES Flags Lk Inf Al
73 # [12] .text PROGBITS 000000000001e6a0 0001e6a0 000fe2b4 0 AX 0 0 16
74 $headers=~/^\[ *\d+\] \.text +PROGBITS +$hex+ +($hex+) /mo or die "No .text Addr found:\n".$headers;
78 sub cmd_add_symbol_file($$)
80 my($base0x,$buildid_hash)=@_;
82 my $buildid_filename=buildid_to_filename $buildid_hash;
83 if (!-r $buildid_filename) {
84 print "$buildid_hash Missing: $buildid_filename\n";
87 print "$buildid_hash $buildid_filename\n";
89 my $text_addr=filename_to_text_off $buildid_filename;
92 add-symbol-file $buildid_filename $base0x+0x$text_addr
96 sub cmd_add_address0x($)
100 # addr2line/eu-addr2line do not print symbols with no .debug_line.
102 echo =S=$address0x\\n
104 echo =E=$address0x\\n
106 # __nanosleep_nocancel + 7 in section .text of /lib64/libc-2.10.1.so
116 sub eu_unstrip_n_read($)
122 # 0x36b5a00000+0x36e000 ec8dd400904ddfcac8b1c343263a790f977159dc@0x36b5a00280 /lib64/libc-2.10.1.so /usr/lib/debug/lib64/libc-2.10.1.so.debug on
125 my($base0x,$buildid_hash)=(/^(0x$hex+)[+]0x$hex+ +($hex+)\Q@\E0x$hex+/) or die "Invalid eu-unstrip -n line: $_";
126 cmd_add_symbol_file $base0x,$buildid_hash;
135 # #0 0x00000036b5aa3f70 in ?? ()
136 if (!/^(#\d+ +(0x$hex+) in )\Q?? ()\E\s*$/) {
140 my($prefix,$address0x)=($1,$2);
141 cmd_add_address0x $address0x;
142 push @r,[$_,$prefix,$address0x];
147 spawn "renice 20 -p $$ 2>/dev/null";
150 eu_unstrip_n_read \*STDIN;
151 my @output=gdb_bt_read;
154 writefile $tmp,$gdbcmd;
156 my $gdbout=readfile "TERM=dumb gdb -nx -batch -x $tmp </dev/null |";
158 print "### retrace begin\n";
165 my($origline,$prefix,$address0x)=@$_;
166 # __nanosleep_nocancel + 7 in section .text of /lib64/libc-2.10.1.so
167 if ($gdbout!~/\n=S=$address0x\n(.*?\n)=E=$address0x\n/) {
168 # This should not happen for addresses not found, they would have valid
169 # marked output just with unsuccessful result from GDB.
170 print "### retrace fail: $origline";
174 print $prefix.$gdbline;
178 print "### retrace finish\n";