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
|
#!/usr/bin/perl -w
#
# A simple script used to build relocation information needed
# to move critical low-level code to continuous physical
# memory
#
# (C) 1999 Samuel Rydh <samuel@ibrium.se>
#
#use POSIX;
if( $#ARGV < 1 ) {
print "Usage: symextract objectfile source [source...]\n";
exit 1;
}
$bad = 0;
#print `cat warning.txt`;
$output = `objdump -r $ARGV[0]` or die "Script failed";
######################################################################
# extract action symbol declarations from the specified source files
######################################################################
# find the symbols to export from the files specified on the cmdline
$basecode = `gcc -I./include -I./sinclude -E -DACTION_SYM_GREPPING @ARGV 2> /dev/null`
or die "preprocessing failed";
@ASYMS = $basecode =~ /ACTION_SYM_START, *(\w*) *, *(\w*) *,ACTION_SYM_END.*/g;
# find exported global symbols
@GSYMS = $basecode =~ /GLOBAL_SYM_START, *(\w*) *,GLOBAL_SYM_END.*/g;
# make sure no action symbols are defined twice (a programming error)
for( $j=0 ; $j <= $#ASYMS ; $j+=2 ) {
for( $i=$j+2 ; $i <= $#ASYMS ; $i+=2 ) {
if( $ASYMS[$j] eq $ASYMS[$i] ) {
print STDERR "*** Error: Action symbol '".
$ASYMS[$j]."' declared twice! ***\n";
$bad++;
}
}
}
# make sure no symbols are exported which are not declared
@esyms = `nm $ARGV[0]` =~ / T (.*)/g;
for( $j=0 ; $j <= $#esyms ; $j++ ) {
$match = 0;
for( $i=0; $i <= $#GSYMS; $i++ ) {
if( $GSYMS[$i] eq $esyms[$j] ) {
$match = 1;
}
}
if( !$match ) {
$bad++;
print STDERR "*** Error: Symbol `".$esyms[$j].
"` is not explicitely exported ***\n";
}
}
######################################################################
# eliminate external symbols (absolutely addressed) from the
# reloctable list (and detect relative addressing of external
# symbols - we can't use such since the 24bit limit will cause problem)
######################################################################
@ext_syms = (`nm -g -u $ARGV[0]` or die "nm failed") =~ /(\w*)\n/g;
foreach( @ext_syms ) {
if( $output =~ /.*PPC_REL.*$_[+\n\-0-9 ].*/ ) {
print STDERR "*** Error: External symbol '".$_.
"' is referenced relatively ***\n";
$bad++;
}
$output =~ s/.*PPC_ADDR.*$_[+\n\-0-9 ].*//g;
$output =~ s/.*PPC_REL.*$_[+\n\-0-9 ].*//g;
}
# At this point only local symbols are in $output.
######################################################################
# Print the relocation table
######################################################################
# Find all local labels and the corresponding offset (in the .text segment)
@lsyms = (`nm -n $ARGV[0]` or die "nm failed") =~ /(.*) [tT] (.*)/g;
# Put the local symbols in an arrary (ADDR_MODE, sym_name, offset)
@E = $output =~ /([0-9,a-f,A-FxX]*) *(\w*_PPC_\w*) *(\w*)([xX+\-0-9,a-f,A-F]*)\n/g;
print "\nstatic reloc_table_t reloc_table[] = {\n";
for($i=0; $i<=$#E; $i+=4 ) {
$match = 0;
# remove leading '+' in the offset (hex doesn't like it)
#$orgoffs = $E[$i+3];
$E[$i+3] =~ s/\+//;
# Action symbols have top priority
$addr = hex($E[$i]);
$name = $E[$i+2];
$type = $E[$i+1];
$action = 0;
$offs1 = 0;
$offs2 = hex( $E[$i+3] );
$skip = 0;
for( $k=0; $k <= $#ASYMS; $k+=2 ){
if( $ASYMS[$k] eq $name ) {
$match = 1;
$action = $ASYMS[$k+1];
}
}
# Find "normal" local symbols
for( $k=1; !$match && $k<=$#lsyms; $k+=2 ) {
if( $lsyms[$k] eq $name ) {
$match = 1;
$offs1 = hex( $lsyms[$k-1]);
# local relative symbols can be skipped - these will work properly anyway
if( $type =~ /PPC_REL/ ) {
$skip = 1;
}
}
}
if( !$match ) {
# This is typically a unhandled local symbol in the data section...
$bad++;
print STDERR "*** Error: Could not obtain the address of the symbol ".$name.
" in the .text section\n";
}
# We have a good entry, print it!
if( !$skip && $match ) {
printf " { 0x%04x, ", $addr;
print $action.", ";
printf "%-16s", sprintf "%s,", $type;
printf " 0x%04x ", $offs1;
if( $offs2 != 0 ) {
printf "+ 0x%-8x ", $offs2;
} else {
print " ";
}
print "}, \t /* ".$name." */\n"
}
}
print " { 0, -1, 0, 0 } /* End marker */ \n};\n";
$bad && print STDERR "*** There were errors (perhaps in ".$ARGV[0].") ***\n";
exit $bad
|