| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | |
|---|
| 6 | # This script is called from ./make_symlist.sh@filter_objdump_syms |
|---|
| 7 | # |
|---|
| 8 | # For help on filtered format see .man objdump under '--syms' |
|---|
| 9 | |
|---|
| 10 | my $show_converted = 1; # 1=result, 0=leftover(debug) |
|---|
| 11 | my $ENDIE = "\n "; # print error location, but in new line |
|---|
| 12 | |
|---|
| 13 | sub list_symbol($$$) { |
|---|
| 14 | my ($state, $type, $symbol) = @_; |
|---|
| 15 | # $state: 'ref' = refer symbol |
|---|
| 16 | # 'def' = define symbol |
|---|
| 17 | # $type: 'sub' = subroutine |
|---|
| 18 | # 'var' = variable |
|---|
| 19 | # 'unk' = unknown ('ref' is always unknown) |
|---|
| 20 | # $symbol: prototype or variable name |
|---|
| 21 | # |
|---|
| 22 | # see also ./make_symlist.sh@SYMLIST_FORMAT |
|---|
| 23 | |
|---|
| 24 | if ($symbol =~ /;/) { |
|---|
| 25 | die "unexpected ';' contained in demangled symbol '$symbol'".$ENDIE; |
|---|
| 26 | } |
|---|
| 27 | if ($state eq 'def') { |
|---|
| 28 | if ($type ne 'sub' and $type ne 'var') { |
|---|
| 29 | die "unexpected type='$type' when defining symbol '$symbol'".$ENDIE; |
|---|
| 30 | } |
|---|
| 31 | } |
|---|
| 32 | if ($show_converted==1) { |
|---|
| 33 | print $state.';'.$type.';'.$symbol."\n"; |
|---|
| 34 | } |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | my $reg_objdump_symbol_linestart = qr/^([0-9a-f]+)\s([a-zA-Z !]{7})\s/o; |
|---|
| 38 | my $reg_symrest_lineend_elf = qr/^([^\s]+)\s([0-9a-f]+)\s+(.*)$/o; |
|---|
| 39 | my $reg_symrest_lineend_osx = qr/^([^\s]+)\s(.*)$/o; |
|---|
| 40 | my $reg_file_header = qr/^([^:]+):\s+(.*)$/o; |
|---|
| 41 | |
|---|
| 42 | my %symbol_seen = (); |
|---|
| 43 | |
|---|
| 44 | sub main() { |
|---|
| 45 | my $style = undef; |
|---|
| 46 | |
|---|
| 47 | LINE: while (defined ($_=<STDIN>)) { |
|---|
| 48 | # if ($_ =~ $reg_objdump_elf_line) { |
|---|
| 49 | if ($_ =~ $reg_objdump_symbol_linestart) { |
|---|
| 50 | my ($addr, $flags, $rest) = ($1, $2, $'); |
|---|
| 51 | my ($section, $symbol) = (undef, undef); |
|---|
| 52 | |
|---|
| 53 | my $thisStyle = undef; |
|---|
| 54 | if ($rest =~ $reg_symrest_lineend_elf) { |
|---|
| 55 | ($section, $symbol) = ($1, $3); |
|---|
| 56 | $thisStyle = 'ELF'; |
|---|
| 57 | } |
|---|
| 58 | elsif ($rest =~ $reg_symrest_lineend_osx) { |
|---|
| 59 | ($section, $symbol) = ($1, $2); |
|---|
| 60 | if ($symbol =~ /^\.hidden\s/o) { $symbol = $'; } |
|---|
| 61 | $thisStyle = 'MACHO'; |
|---|
| 62 | } |
|---|
| 63 | else { |
|---|
| 64 | die "unexpected rest='$rest' in line: $_".$ENDIE; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | if (defined $style) { |
|---|
| 68 | if ($thisStyle ne $style) { |
|---|
| 69 | die "objdump style change detected: $style -> $thisStyle (parser is broken)".$ENDIE; |
|---|
| 70 | } |
|---|
| 71 | } |
|---|
| 72 | else { |
|---|
| 73 | $style = $thisStyle; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | # exclude useless symbols: |
|---|
| 77 | if ($symbol =~ /^non-virtual thunk to /o) { |
|---|
| 78 | next LINE; |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | if ($section eq '*UND*') { |
|---|
| 82 | if ($symbol =~ /;/) { die "unexpected ';' contained in demangled symbol '$symbol'".$ENDIE; } |
|---|
| 83 | list_symbol('ref', 'unk', $symbol); # references are stored with unknown type here |
|---|
| 84 | } |
|---|
| 85 | else { |
|---|
| 86 | my $scope = substr($flags, 0, 1); # l=local, g=global, u=unique-global(gnu), !=broken, ' '=no-scope |
|---|
| 87 | if ($scope =~ /[ug]/o) { |
|---|
| 88 | my $type = substr($flags, 6, 1); # 'F'=function, 'f'=file, 'o'=object, ' '=normal |
|---|
| 89 | |
|---|
| 90 | if ($type eq 'F') { # function |
|---|
| 91 | my $suppress = 0; |
|---|
| 92 | if (exists $symbol_seen{$symbol}) { |
|---|
| 93 | # duplicated symbol - accept only for ctors and dtors. no idea why these are duplicated. |
|---|
| 94 | if ($symbol =~ /\(/o) { |
|---|
| 95 | my ($name, $params) = ($`, $&.$'); |
|---|
| 96 | my @namepart = split /::/, $name; |
|---|
| 97 | my $parts = scalar(@namepart); |
|---|
| 98 | if ($parts>=2) { |
|---|
| 99 | my ($class, $method) = @namepart[$parts-2, $parts-1]; |
|---|
| 100 | if (($class eq $method) or ($method eq '~'.$class)) { $suppress = 1; } |
|---|
| 101 | else { print STDERR "Warning: not ctor/dtor: class='$class' method='$method'\n"; } |
|---|
| 102 | } |
|---|
| 103 | else { print STDERR "Warning: non-class function\n"; } |
|---|
| 104 | } |
|---|
| 105 | else { print STDERR "Warning: function w/o parenthesis\n"; } |
|---|
| 106 | if ($suppress==0) { die "detected duplicated symbol '$symbol'".$ENDIE; } |
|---|
| 107 | } |
|---|
| 108 | else { $symbol_seen{$symbol} = 1; } |
|---|
| 109 | if ($suppress==0) { list_symbol('def', 'sub', $symbol); } |
|---|
| 110 | } |
|---|
| 111 | elsif ($type =~ /[O]/o) { |
|---|
| 112 | if (($scope eq 'g') and (($section eq '.data') or ($section eq '.bss'))) { |
|---|
| 113 | list_symbol('def', 'var', $symbol); |
|---|
| 114 | } |
|---|
| 115 | } |
|---|
| 116 | elsif (($scope eq 'g') and (($section eq '.data') or ($section eq '.bss'))) { |
|---|
| 117 | # silently accept some symbols occurring in dynamic libraries |
|---|
| 118 | # (only occur in libCORE, libARBDB and libWINDOW; but neighter in libglAW nor in libglpng_arb) |
|---|
| 119 | } |
|---|
| 120 | else { |
|---|
| 121 | if ($show_converted==0) { print $_; } |
|---|
| 122 | else { |
|---|
| 123 | die "unexpected line: $_".$ENDIE; |
|---|
| 124 | # If this fails, set show_converted=0 => prints non-converted lines. |
|---|
| 125 | # Decide whether to suppress or convert.. |
|---|
| 126 | } |
|---|
| 127 | } |
|---|
| 128 | } |
|---|
| 129 | } |
|---|
| 130 | } |
|---|
| 131 | else { |
|---|
| 132 | chomp; |
|---|
| 133 | if (/./o) { |
|---|
| 134 | if ($_ =~ $reg_file_header) { |
|---|
| 135 | # print "matched reg_file_header: $_\n"; |
|---|
| 136 | ; |
|---|
| 137 | } |
|---|
| 138 | elsif (/:$/o) { |
|---|
| 139 | my $b4 = $`; |
|---|
| 140 | if (($b4 eq 'SYMBOL TABLE') or |
|---|
| 141 | ($b4 =~ /^In\sarchive\s.*$/o)) { |
|---|
| 142 | ; |
|---|
| 143 | } |
|---|
| 144 | else { |
|---|
| 145 | die "can't parse line '$_'".$ENDIE; |
|---|
| 146 | } |
|---|
| 147 | } |
|---|
| 148 | else { |
|---|
| 149 | die "can't parse line '$_'".$ENDIE; |
|---|
| 150 | # may be caused by non-ELF-object. |
|---|
| 151 | } |
|---|
| 152 | } |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | eval { main(); }; |
|---|
| 158 | if ($@) { die "filter_objdump_syms.pl: Error: $@\n"; } |
|---|