forked from jmrosinski/GPTL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hex2name.pl
executable file
·238 lines (213 loc) · 6.17 KB
/
hex2name.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/perl
# jr-resolve.pl - convert timing lib output addresses to names
# hacked from cyg-profile script found on web.
use strict;
use warnings;
no warnings 'portable';
use diagnostics;
use English;
my (%symtab); # symbol table derived from executable
my ($binfile); # executable
my ($timingout); # timer file (normally timing.[0-9]*)
my ($demangle); # whether to demangle the symbols
my ($arg); # cmd-line arg
my ($PRTHRESH) = 1000000; # This needs to match what is in the GPTL lib
our ($max_sym) = 0;
$OUTPUT_AUTOFLUSH = 1;
&help() if ($#ARGV < 1 || $#ARGV > 2);
while ($arg = shift (@ARGV)) {
if ($arg eq "-demangle") {
$demangle = 1;
} elsif ( ! defined ($binfile)) {
$binfile = $arg;
} else {
$timingout = $arg;
}
}
&help() if ($binfile =~ /--help/);
&help() if (!defined ($binfile));
&help() if (!defined ($timingout));
&main();
# ==== Subs
sub help()
{
printf ("Usage: $0 [-demangle] executable timing_file\n");
exit;
}
sub main()
{
my ($offset); # offset into a.out (to match timing output)
my ($type); # symbol type
my ($function); # name of function in symtab
my ($nsym) = 0; # number of symbols
my ($nfunc) = 0; # number of functions
my ($sym); # symbol
my ($begofline);
my ($off1);
my ($spaftsym);
my ($ncalls);
my ($restofline);
my ($numsp); # number of spaces before rest of line
my ($spaces); # text containing spaces before rest of line
my ($thread) = -1; # thread number (init to -1
my ($doparse) = 0; # logical flag: true indicates between "Statas for thread..."
# and "Number of calls..."
my ($indent);
my (@max_chars); # longest symbol name + indentation (per thread)
my ($statsforthread) = 0; # Inside region "Stats for thread ..."
my ($sortedbytimer) = 0; # Inside region "Same stats sorted by ..."
my ($countnexttochild) = 0; # Inside region "Count next to child ..."
if ($demangle) {
open (NM, "nm $binfile | c++filt | ") or die ("Unable to run 'nm $binfile | c++filt': $!\n");
} else {
open (NM, "nm $binfile |") or die ("Unable to run 'nm $binfile': $!\n");
}
printf ("Loading symbols from $binfile ... ");
while (<NM>) {
$nsym++;
next if (!/^([0-9A-F]+) (.) (.+)$/i);
$offset = hex($1);
$type = $2;
$function = $3;
next if ($type !~ /[tT]/);
$nfunc++;
$symtab{$offset} = $function;
}
printf("OK\nSeen %d symbols, stored %d function offsets\n", $nsym, $nfunc);
close(NM);
@max_chars = &get_max_chars ("$timingout");
open (TEXT, "<$timingout") or die ("Unable to open '$timingout': $!\n");
while (<TEXT>) {
# 3 types of input line will need parsing
if (/^Stats for thread /) { # beginning of main region
$statsforthread = 1;
$sortedbytimer = 0;
$countnexttochild = 0;
++$thread;
print $_;
next;
} elsif (/^(Thd) (Called.*)$/) { # Sorted by timer
$statsforthread = 0;
$sortedbytimer = 1;
$countnexttochild = 0;
$spaces = " " x $max_sym;
printf ("%s%s%s\n", $1, $spaces, $2);
next;
} elsif (/^Count next to child /) { # Parent-child stats
$statsforthread = 0;
$sortedbytimer = 0;
$countnexttochild = 1;
print $_;
next;
} elsif ( ! $statsforthread && ! $sortedbytimer && ! $countnexttochild) { # header--just print
print $_;
next;
}
if ($statsforthread) {
if (/^ *(Called Recurse.*)$/) { # heading
$numsp = $max_chars[$thread];
$spaces = " " x $numsp;
printf ("%s %s\n", $spaces, $1);
} elsif (/(^\*? *)([[:xdigit:]]+)( +)([0-9.Ee+]+)(.*)$/) { # hex entry
$begofline = $1;
$off1 = hex($2);
$ncalls = $4;
$restofline = $5;
if (defined ($symtab{$off1})) {
$sym = $symtab{$off1};
} else {
$sym = "???";
}
$numsp = $max_chars[$thread] - length ($begofline) - length ($sym);
$spaces = " " x $numsp;
printf ("%s%s%s %9s %s\n", $begofline, $sym, $spaces, $ncalls, $restofline);
} elsif (/(^\*? *)(\w+)( +)([0-9.Ee+]+)(.*)$/) { # standard entry
$begofline = $1;
$sym = $2;
$ncalls = $4;
$restofline = $5;
$numsp = $max_chars[$thread] - length ($begofline) - length ($sym);
$spaces = " " x $numsp;
printf ("%s%s%s %9s %s\n", $begofline, $sym, $spaces, $ncalls, $restofline);
} else { # unknown: just print it
print $_;
}
} elsif ($sortedbytimer) {
if (/^([0-9][0-9][0-9] )([[:xdigit:]]+)( +)(.*)$/ ||
/^(SUM )([[:xdigit:]]+)( +)(.*)$/) {
$off1 = hex($2);
if (defined ($symtab{$off1})) {
$sym = $symtab{$off1};
} else {
$sym = "???";
}
$numsp = length($3) + $max_sym - length ($sym) - 1;
$spaces = " " x $numsp;
printf ("%s%s%s%s\n", $1, $sym, $spaces, $4);
} else {
print $_;
}
} elsif ($countnexttochild) {
if (/(^ *)([0-9.Ee+]+)( +)([[:xdigit:]]+)( *)$/) {
#
# Hex entry in multiple parent region
#
$ncalls = $2;
$indent = $3;
$off1 = hex($4);
if (defined ($symtab{$off1})) {
$sym = $symtab{$off1};
} else {
$sym = "???";
}
$restofline = $5;
printf ("%8s%s%s%s\n", $ncalls, $indent, $sym, $restofline);
} else { # unknown: just print it
print $_;
next;
}
}
}
close (TEXT);
printf("done\n");
}
sub get_max_chars ()
{
my ($file) = $_[0];
my ($thread) = -1;
my ($tmp);
my ($sym);
my ($off1);
my ($doparse) = 0;
my ($lensym);
my (@max_chars);
our ($max_sym) = 0;
open (TEXT, "<$file") or die ("Unable to open '$file': $!\n");
while (<TEXT>) {
# Parse the line if it's a hex number followed by a number
if (/Stats for thread /) {
$doparse = 1;
++$thread;
$max_chars[$thread] = 0;
} elsif (/^Total calls /) {
$doparse = 0;
} elsif ($doparse && /(^\*? *)([[:xdigit:]]+)/) {
$off1 = hex($2);
if (defined ($symtab{$off1})) {
$sym = $symtab{$off1};
} else {
$sym = "???";
}
$lensym = length ($sym);
$tmp = length ($1) + $lensym;
if ($tmp > $max_chars[$thread]) {
$max_chars[$thread] = $tmp;
}
if ($lensym > $max_sym) {
$max_sym = $lensym;
}
}
}
close (TEXT);
return @max_chars;
}