This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[build] Use elfdump, readelf in make_sunver.pl


The use of nm in contrib/make_sunver.pl has caused problems without end,
both due to the different and sometimes hard to parse output formats of
GNU nm and Sun nm, and lately due to the inability to reliably detect
and ignore hidden symbols in the symbol table:

While trying to use CVS gas and gld in a Solaris 11 bootstrap, it could
happen that global hidden symbols in libgcj.so input objects were turned
global with default visibility and thus cause link failures later.
While Sun nm can show hidden symbols in its default (without -P)
output format, GNU nm can not.

So I've finally chosed to bite the bullet and move away from nm here:
I'd like to avoid requiring users to install GNU binutils if possible,
so I'm using elfdump -s in the native case.  For the cross case, I chose
to use readelf -s instead since the objdump -t output is useless for
automatic consumption.

The patch below implements this.  It allowed the bootstrap with CVS gas
and gld to complete successfully, and I've bootstrapped on Solaris 8 to
11 on SPARC and x86, both with Sun as and gas to make sure nothing
broke.  Than, I've compared the old version maps generated using nm
output and the new ones and found them to be identical with the
exception of the two libgcj ones where many hidden symbols are now
correctly omitted.  Finally, I've disabled the use of elfdump and
verified that readelf produced identical output.

This should hopefully put an end to all the problems and fragility
Solaris bootstraps have suffered from make_sunver.pl.

Installed.

	Rainer



2010-11-13  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	* make_sunver.pl: Use elfdump -s to extract symbols if possible,
	readelf -s otherwise.

diff -r e93a180fd196 contrib/make_sunver.pl
--- a/contrib/make_sunver.pl	Mon Nov 15 12:59:41 2010 +0100
+++ b/contrib/make_sunver.pl	Fri Nov 19 15:33:21 2010 +0100
@@ -12,8 +12,7 @@
 # A comment with the original pattern and its type is left in the output
 # file to make it easy to understand the matches.
 #
-# It expects a 'nm' with the POSIX '-P' option, but everyone has one of
-# those, right?
+# It uses elfdump when present (native), GNU readelf otherwise.
 # It depends on the GNU version of c++filt, since it must understand the
 # GNU mangling style.
 
@@ -46,35 +45,104 @@
     }
 }
 
-# The nm command to use.
-my $nm = $ENV{'NM_FOR_TARGET'} || "nm";
+# We need to detect and ignore hidden symbols.  Solaris nm can only detect
+# this in the harder to parse default output format, and GNU nm not at all,
+# so use elfdump -s in the native case and GNU readelf -s otherwise.
+# GNU objdump -t cannot be used since it produces a variable number of
+# columns.
 
-# Process each symbol.
-open NM,$nm.' -P '.(join ' ',@OBJECTS).'|' or die $!;
-while (<NM>) {
-    my $i;
-    chomp;
+# The path to elfdump.
+my $elfdump = "/usr/ccs/bin/elfdump";
 
-    # nm prints out stuff at the start, ignore it.
-    next if (/^$/);
-    next if (/:$/);
-    # Ignore entries without symbol name.  Sun nm emits those for local, .bss
-    # or scratch register (SPARC only) symbols for example.
-    next if (/^ /);
-    # Ignore undefined and local symbols.
-    next if (/^[^ ]+[ \t]+[Ua-z][ \t]+/);
-    # Ignore objects without symbol table.  Message goes to stdout with Sun
-    # nm, while GNU nm emits the corresponding message to stderr.
-    next if (/.* - No symbol table data/);
+if (-f $elfdump) {
+    open ELFDUMP,$elfdump.' -s '.(join ' ',@OBJECTS).'|' or die $!;
+    my $skip_arsym = 0;
 
-    # $sym is the name of the symbol.
-    die "unknown nm output $_" if (! /^([^ ]+)[ \t]+[A-Z][ \t]+/);
-    my $sym = $1;
+    while (<ELFDUMP>) {
+	chomp;
 
-    # Remember symbol.
-    $sym_hash{$sym}++;
+	# Ignore empty lines.
+	if (/^$/) {
+	    # End of archive symbol table, stop skipping.
+	    $skip_arsym = 0 if $skip_arsym;
+	    next;
+	}
+
+	# Keep skipping until end of archive symbol table.
+	next if ($skip_arsym);
+
+	# Ignore object name header for individual objects and archives.
+	next if (/:$/);
+
+	# Ignore table header lines.
+	next if (/^Symbol Table Section:/);
+	next if (/index.*value.*size/);
+
+	# Start of archive symbol table: start skipping.
+	if (/^Symbol Table: \(archive/) {
+	    $skip_arsym = 1;
+	    next;
+	}
+
+	# Split table.
+	(undef, undef, undef, undef, $bind, $oth, undef, $shndx, $name) = split;
+
+	# Error out for unknown input.
+	die "unknown input line:\n$_" unless defined($bind);
+
+	# Ignore local symbols.
+	next if ($bind eq "LOCL");
+	# Ignore hidden symbols.
+	next if ($oth eq "H");
+	# Ignore undefined symbols.
+	next if ($shndx eq "UNDEF");
+	# Error out for unhandled cases.
+	if ($bind !~ /^(GLOB|WEAK)/ or $oth ne "D") {
+	    die "unhandled symbol:\n$_";
+	}
+
+	# Remember symbol.
+	$sym_hash{$name}++;
+    }
+    close ELFDUMP or die "$elfdump error";
+} else {
+    open READELF, 'readelf -s -W '.(join ' ',@OBJECTS).'|' or die $!;
+    # Process each symbol.
+    while (<READELF>) {
+	chomp;
+
+	# Ignore empty lines.
+	next if (/^$/);
+
+	# Ignore object name header.
+	next if (/^File: .*$/);
+
+	# Ignore table header lines.
+	next if (/^Symbol table.*contains.*:/);
+	next if (/Num:.*Value.*Size/);
+
+	# Split table.
+	(undef, undef, undef, undef, $bind, $vis, $ndx, $name) = split;
+
+	# Error out for unknown input.
+	die "unknown input line:\n$_" unless defined($bind);
+
+	# Ignore local symbols.
+	next if ($bind eq "LOCAL");
+	# Ignore hidden symbols.
+	next if ($vis eq "HIDDEN");
+	# Ignore undefined symbols.
+	next if ($ndx eq "UND");
+	# Error out for unhandled cases.
+	if ($bind !~ /^(GLOBAL|WEAK)/ or $vis ne "DEFAULT") {
+	    die "unhandled symbol:\n$_";
+	}
+
+	# Remember symbol.
+	$sym_hash{$name}++;
+    }
+    close READELF or die "readelf error";
 }
-close NM or die "nm error";
 
 ##########
 # The various types of glob patterns.


-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]