2 # Copyright (C) 2004-2007, Parrot Foundation.
7 tools/dev/nm.pl - Display symbol table information
11 % perl tools/dev/nm.pl [options] file
13 To list all the symbols in Parrot:
15 % perl tools/dev/nm.pl parrot
19 Portable frontend for C<nm(1)>; by default lists all the code and data
20 symbols in the object or archive files.
22 =head2 Command-Line Options
24 The following options can be used to limit the symbols:
32 List the code/text symbols.
38 List the data symbols.
44 List the initialised data symbols.
50 List the uninitialised data symbols.
56 List the constant (read-only) data symbols.
58 Not all platforms support this, a warning will be given if not. You can
59 try GNU C<nm> if you want this feature.
65 List the undefined symbols.
71 List the defined symbols.
77 List the file(name) symbols.
81 If more than one of all the above options are given, they are C<AND>ed.
82 They can also be negated with a "no", for example C<--noconst>.
90 Prepend the object name before the symbol name.
94 Append the short BSD-style type to the symbol name.
96 B - uninitialised data symbol
97 D - initialised data symbol
99 R - read-only data symbol
103 Uppercase indicates that the symbol is global; lowercase indicates that
116 Append a long type (e.g. "global_const_init_data" versus "R") to the
125 Show the version number.
129 All the options can be shortened to their unique prefixes, and one
130 leading dash ("-") can be used instead of two ("--").
139 use vars
qw($VERSION);
143 $VERSION = sprintf "%d.%d", q$Revision$ =~ /(\d+)/g; # jhi@iki.fi;
145 my $ME = basename($0);
146 my $RCS_DATE = q$Date$;
150 my $nm_try = qx(nm -V 2>&1);
152 my $nm_ro; # can tell apart read-only (const) data sections
155 $Code, $Data, $Init, $Uninit, $Const, $Mutable,
156 $Global, $Local, $Undef, $Def, $File, $ObjectName,
157 $Type, $BSD, $Long, $Help, $Version
161 print "$ME: $VERSION ( $RCS_DATE)\n";
166 $ME: Usage: $ME [options] [ foo.o ... | bar.a | other_library_format ]
167 Portable frontend for nm(1); by default lists all the code and data symbols
168 in the object or archive files. The options can be used to limit the symbols:
169 --code|-c code/text symbols (Tt)
170 --data|-d data symbols (Dd, Bb)
171 --init|-i initialised data symbols (Dd)
172 --uninit|-u uninitialised data symbols (Bb)
173 --local|-l local symbols (tdbruf)
174 --global|-g global symbols (TDBRUF)
175 --const|-C const (read-only) data symbols (Rr) [1]
176 --undef|-U undefined symbols (Uu)
177 --def|-D defined symbols (not Uu)
178 --file|-f file(name) symbols (Ff)
179 If more than one of all the above options are given, they are ANDed.
180 They can also be negated with a "no", for example --noconst.
181 [1] Not all platforms support this, a warning will be given if not.
182 You can try GNU nm if you want this feature.
183 --objectname|-o prepend the object name before the symbol name
184 --t append the short BSD-style type (in parentheses above)
185 --type=bsd|-B same as --t
186 --type=long|-L append a long type (e.g. "global_const_init_data" versus "R")
187 --help|-h show this help
188 --version|-v show version
189 All the options can be shortened to their unique prefixes,
190 and one leading dash ("-") can be used instead of two ("--").
194 if ( $^O eq 'solaris' && $nm_try =~ /Solaris/ ) {
197 elsif ( $^O eq 'hpux' && $nm_try =~ /linker command|HP-UX/ ) {
200 elsif ( $^O eq 'aix' && $nm_try =~ /illegal option/ ) {
203 elsif ( $^O eq 'irix' && $nm_try =~ /C Development Set/ ) {
207 elsif ( $^O eq 'dec_osf' && $nm_try =~ /Alpha/ ) { # aka Tru64 aka DEC OSF/1
211 elsif ( $^O eq 'darwin' && $nm_try =~ /invalid argument/ ) {
214 elsif ( $nm_try =~ /GNU nm/ ) {
221 # Hope for BSD-style nm output.
224 Getopt::Long::Configure("bundling");
231 'uninit|u!' => \$Uninit,
232 'const|C!' => \$Const,
233 'global|g!' => \$Global,
234 'local|l!' => \$Local,
235 'undef|U!' => \$Undef,
238 'objectname|o' => \$ObjectName,
244 'version|v' => \$Version,
252 if ( $Const && !$nm_ro ) {
253 warn "$ME: the native nm cannot tell apart const data sections\n";
272 my ( $a, $b, $sa, $sb ) = @_;
273 if ( defined $a && defined $b && $a == $b ) {
274 warn "$ME: both --$sa and --$sb used\n";
278 warn_if_both( $Code, $Data, 'code', 'data' );
279 warn_if_both( $Global, $Local, 'global', 'local' );
280 warn_if_both( $Init, $Uninit, 'init', 'uninit' );
281 warn_if_both( $Def, $Undef, 'def', 'undef' );
283 $Undef ||= !$Def if defined $Def && !defined $Undef;
286 @Type{qw(bsd long)} = ();
289 || ( defined $Type && $Type eq '1' ); # So they used --t.
290 $Type = 'long' if $Long;
291 die "$ME: --type=$Type unknown\n"
292 if defined $Type && $Type ne '' && !exists $Type{$Type};
294 my $TypeLong = defined $Type && $Type eq 'long';
298 warn "$ME: No such file: $f\n";
301 if ( open( my $NM, '<', "$nm_cmd $nm_opt $f |" ) ) {
303 $o = $f if $f =~ /\.o$/;
307 if ( m/^(.+\.o):$/ || m/\[(.+\.o)\]:$/ || m/\((.+\.o)\):$/ ) {
310 elsif (/ ([A-Za-z]) \.?(\w+)$/) {
312 # Especially text symbols are sometimes prefixed by a ".".
313 my ( $type, $name ) = ( $1, $2 );
315 # The following are assumed to work Everywhere.
316 my $absolute = ( $type =~ /^[Aa]$/ ) ?
1 : 0;
317 my $uninit = ( $type =~ /^[BbCc]$/ ) ?
1 : 0;
318 my $init = ( $type =~ /^[DdGg]$/ ) ?
1 : 0;
319 my $file = ( $type =~ /^[Ff]$/ ) ?
1 : 0;
320 my $small = ( $type =~ /^[Gg]$/ ) ?
1 : 0;
321 my $code = ( $type =~ /^[Tt]$/ ) ?
1 : 0;
322 my $undef = ( $type =~ /^[Uu]$/ ) ?
1 : 0;
325 my $local = $type eq lc $type ?
1 : 0;
328 if ( ( $^O
eq 'irix' || $^O
eq 'dec_osf' )
329 && $type =~ /^[BbSs]$/ )
331 if ( $type =~ /^[Ss]$/ ) {
337 if ( $^O
eq 'irix' && $type =~ /^[Rr]$/ ) {
341 if ( $^O
eq 'dec_osf' ) {
342 if ( $type eq 'E' ) {
345 elsif ( $type =~ /^[RrQq]$/ ) {
350 if ( $^O
eq 'darwin' ) {
354 if ( $type =~ /^[Rr]$/ ) {
358 elsif ( $type =~ /^[Ss]$/ ) {
363 if ( $type =~ /^[ABCDFGQRSTU]$/i ) {
364 unless ( $undef || $code || $other || $absolute ) {
365 if ( $init && $uninit ) {
366 warn "$.:$_: both init and uninit?\n";
368 elsif ( !$init && !$uninit ) {
369 warn "$.:$_: neither init and uninit?\n";
373 my $data = ( $uninit || $init ) && !$code;
374 my $global = !$local;
378 my ( $show, $Got, $got ) = @_;
379 if ( defined $Got ) {
380 if ( $Got == $got ) {
388 want_show
( \
$show, $Code, $code ) if $show;
389 want_show
( \
$show, $Data, $data ) if $show;
390 want_show
( \
$show, $Init, $init ) if $show;
391 want_show
( \
$show, $Uninit, $uninit ) if $show;
392 want_show
( \
$show, $Const, $const ) if $show;
393 want_show
( \
$show, $Global, $global ) if $show;
394 want_show
( \
$show, $Local, $local ) if $show;
395 want_show
( \
$show, $Undef, $undef ) if $show;
396 want_show
( \
$show, $File, $file ) if $show;
399 $show = $ObjectName ?
"$o\t$name" : $name;
400 if ( defined $Type ) {
404 $symbol = $TypeLong ?
"code" : "T";
408 $symbol = $TypeLong ?
"const_init" : "R";
411 $symbol = $TypeLong ?
"init" : "D";
414 $symbol = $TypeLong ?
"uninit" : "B";
417 $symbol = $TypeLong ?
"unknown" : "D?";
419 $symbol .= "_data" if $TypeLong;
422 $symbol = $TypeLong ?
"undef" : "U";
425 $symbol = $TypeLong ?
"unknown" : "?";
428 $show .= $global ?
"global_$symbol" : "local_$symbol";
431 $show .= $global ?
$symbol : lc $symbol;
441 warn "$ME: '$nm_cmd $nm_opt $f' failed: $!\n";
449 Author: Jarkko Hietaniemi.
455 # cperl-indent-level: 4
458 # vim: expandtab shiftwidth=4: