#!/usr/bin/perl -w # gensymbols : Generates a symbol table based on the output of elfgrep_fixup # Copyright (C) 2002 Dion Mendel # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # gensymbols generates a symbol table for all object files determined # from the output of elfgrep and elfgrep_fixup. # # Sample usage: # % for i in obj/*.o ; do # elfgrep -t $i the-binary # done | elfgrep_fixup > object_files # % gensymbols object_files > symbols use Getopt::Long "GetOptions"; use FileHandle; use strict 'vars'; use vars '$VERSION', '$Verbose', '$NM'; # full path to nm program $NM = "/usr/bin/nm"; $VERSION = "1.0"; # version of this program $Verbose = 1; &parse_command_line_for_options(); &usage if (scalar @ARGV != 1); my $filename = $ARGV[0]; # read data and sort into symbol table my %symbols = &read_data($filename); my $fh = STDOUT; &display_output($fh, \%symbols); exit 0; ############################### Output Functions ############################## # ----------------------------------------------------------------------------- # Displays the results of this program. # Params: $fh - file handle to display output to. # \%symbols - symbols table to display # Returns: none sub display_output($\%) { my ($fh, $ref_symbols) = @_; my ($key); print $fh <<"_HERE"; # # -- This is an automatically generated file. -- # # This file contains symbol table entries related to a specific binary file. # _HERE for $key (sort keys %$ref_symbols) { printf $fh ("0x%08x %s\n", $key, $ref_symbols->{$key}); } printf $fh ("\n# Add manual symbol table entries below this line\n"); printf $fh ("# ----------------------------------------------------\n"); } ############################# Read Data Functions ############################# # ----------------------------------------------------------------------------- # Reads data regarding matching object files and examines each object file for # symbols. All symbols found are returned. # Params: $filename - filename containing data to read or '-' for stdin # Returns: symbols as a hashtable (key - offset, value - name) sub read_data($) { my ($filename) = @_; my ($fh, $line, $nmline, $name, $base_offset, $offset, $type, $total_offset); my (@output, %syms, %symbols); # open file, or just use stdin if filename is '-' if ($filename eq "-") { $fh = STDIN; } else { $fh = new FileHandle(); open $fh, "< $filename" or die "could not open file `$filename': $!"; } # key is offset, value is {type, name} %syms = (); # for each line while ($line = <$fh>) { next if $line =~ /^$/; # skip empty lines next if $line =~ /^#/; # skip comment lines if ($line =~ /(.*) - match at (0x.*) \((0x.*) bytes\)/) { # get object file details $name = $1; $base_offset = oct($2); # call $NM for the symbol table for this object file @output = `$NM $name`; foreach $nmline (@output) { # extract symbol details from nm output $offset = '0x'.substr($nmline, 0, 8); $type = substr($nmline, 9, 1); ($name = substr($nmline, 11)) =~ s/\s+$//; # only add symbol table entries of these types if (($type eq "W") or ($type eq "T")) { # calculate total offset for this symbol $total_offset = oct($offset) + $base_offset; if ((not exists($syms{$total_offset})) or ($syms{$total_offset}->{type} eq "W")) { # store symbol $syms{$total_offset} = {type => $type, name => $name}; } } } } else { die "bad input `$line'"; } } # create new symbols hash (key: offset, value: name) %symbols = (); foreach $offset (keys %syms) { $name = $syms{$offset}->{name}; $symbols{$offset} = $name; } # close file handle unless reading from stdin close $fh unless ($filename eq "-"); return %symbols; } ############################### Usage Functions ############################### # ----------------------------------------------------------------------------- # Parses the command line for any specified options. Sets the appropriate # option flags if options are specified. Prints usage info if invalid options # are given. # Returns: nothing sub parse_command_line_for_options() { my ($want_quiet) = 0; my ($want_version) = 0; my ($want_help) = 0; &GetOptions("q|quiet" => \$want_quiet, "V|version" => \$want_version, "h|help" => \$want_help, ); if ($want_version) { print "$0 $VERSION\n"; exit 0; } if ($want_help) { &usage(); } $Verbose = !$want_quiet; } # ----------------------------------------------------------------------------- # Prints a nice usage message to stdout, and then exits. sub usage() { print <<"_END"; $0 v${VERSION} A program to process the output elfgrep_fixup and generate a symbol table from the matches object files. Usage: $0 [options] [file_name] filename is the name of the file containing data to process, or - for stdin Options: -V, --version outputs version information and exits -h, --help displays this help and exits _END exit 1; }