| 1 | #!/usr/bin/perl -w | 
|---|
| 2 |  | 
|---|
| 3 | # A script to get around some shortcomings in elf2e32, namely: | 
|---|
| 4 | # - Returning 0 even when there are errors. | 
|---|
| 5 | # - Excluding symbols from the dso file even when they are present in the ELF file. | 
|---|
| 6 | # - Including symbols in the the dso file even when they are not present in the ELF file. | 
|---|
| 7 | # - Overwriting the old dso file even when there are no changes (increases build time). | 
|---|
| 8 |  | 
|---|
| 9 | use File::Copy; | 
|---|
| 10 |  | 
|---|
| 11 | my @args = (); | 
|---|
| 12 | my @definput; | 
|---|
| 13 | my @defoutput; | 
|---|
| 14 | my @dso; | 
|---|
| 15 | my @tmpdso; | 
|---|
| 16 | foreach (@ARGV) { | 
|---|
| 17 | if (/^--definput/o) { | 
|---|
| 18 | @definput = split('=', $_); | 
|---|
| 19 | } elsif (/^--defoutput/o) { | 
|---|
| 20 | @defoutput = split('=', $_); | 
|---|
| 21 | } elsif (/^--dso/o) { | 
|---|
| 22 | @dso = split('=', $_); | 
|---|
| 23 | } elsif (/^--tmpdso/o) { | 
|---|
| 24 | @tmpdso = split('=', $_); | 
|---|
| 25 | $tmpdso[0] = "--dso"; | 
|---|
| 26 | } else { | 
|---|
| 27 | push(@args, $_); | 
|---|
| 28 | } | 
|---|
| 29 | } | 
|---|
| 30 |  | 
|---|
| 31 | @definput = () if (!@definput || ! -e $definput[1]); | 
|---|
| 32 |  | 
|---|
| 33 | if (@dso && !@tmpdso || !@dso && @tmpdso) { | 
|---|
| 34 | print("--dso and --tmpdso must be used together.\n"); | 
|---|
| 35 | exit 1; | 
|---|
| 36 | } | 
|---|
| 37 |  | 
|---|
| 38 | my $buildingLibrary = (@defoutput && @dso) ? 1 : 0; | 
|---|
| 39 |  | 
|---|
| 40 | my $fixupFile = ""; | 
|---|
| 41 | my $runCount = 0; | 
|---|
| 42 | my $returnCode = 0; | 
|---|
| 43 |  | 
|---|
| 44 | while (1) { | 
|---|
| 45 | if (++$runCount > 2) { | 
|---|
| 46 | print("Internal error in $0, link succeeded, but exports may be wrong.\n"); | 
|---|
| 47 | last; | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | my $elf2e32Pipe; | 
|---|
| 51 | my $elf2e32Cmd = "elf2e32 @args" | 
|---|
| 52 | . " " . join("=", @definput) | 
|---|
| 53 | . " " . join("=", @defoutput) | 
|---|
| 54 | . " " . join("=", @tmpdso); | 
|---|
| 55 | open($elf2e32Pipe, "$elf2e32Cmd 2>&1 |") or die ("Could not run elf2e32"); | 
|---|
| 56 |  | 
|---|
| 57 | my %fixupSymbols; | 
|---|
| 58 | my $foundBrokenSymbols = 0; | 
|---|
| 59 | my $errors = 0; | 
|---|
| 60 | while (<$elf2e32Pipe>) { | 
|---|
| 61 | print; | 
|---|
| 62 | if (/Error:/io) { | 
|---|
| 63 | $errors = 1; | 
|---|
| 64 | } elsif (/symbol ([a-z0-9_]+) absent in the DEF file, but present in the ELF file/io) { | 
|---|
| 65 | $fixupSymbols{$1} = 1; | 
|---|
| 66 | $foundBrokenSymbols = 1; | 
|---|
| 67 | } elsif (/[0-9]+ Frozen Export\(s\) missing from the ELF file/io) { | 
|---|
| 68 | $foundBrokenSymbols = 1; | 
|---|
| 69 | } | 
|---|
| 70 | } | 
|---|
| 71 | close($elf2e32Pipe); | 
|---|
| 72 |  | 
|---|
| 73 | if ($errors) { | 
|---|
| 74 | $returnCode = 1; | 
|---|
| 75 | last; | 
|---|
| 76 | } | 
|---|
| 77 |  | 
|---|
| 78 | if ($buildingLibrary) { | 
|---|
| 79 | my $tmpDefFile; | 
|---|
| 80 | my $defFile; | 
|---|
| 81 | open($defFile, "< $defoutput[1]") or die("Could not open $defoutput[1]"); | 
|---|
| 82 | open($tmpDefFile, "> $defoutput[1].tmp") or die("Could not open $defoutput[1].tmp"); | 
|---|
| 83 | $fixupFile = "$defoutput[1].tmp"; | 
|---|
| 84 | while (<$defFile>) { | 
|---|
| 85 | s/\r//; | 
|---|
| 86 | s/\n//; | 
|---|
| 87 | next if (/; NEW:/); | 
|---|
| 88 | if (/([a-z0-9_]+) @/i) { | 
|---|
| 89 | if (exists($fixupSymbols{$1})) { | 
|---|
| 90 | s/ ABSENT//; | 
|---|
| 91 | } elsif (s/; MISSING://) { | 
|---|
| 92 | s/$/ ABSENT/; | 
|---|
| 93 | } | 
|---|
| 94 | } | 
|---|
| 95 | print($tmpDefFile "$_\n"); | 
|---|
| 96 | } | 
|---|
| 97 | close($defFile); | 
|---|
| 98 | close($tmpDefFile); | 
|---|
| 99 |  | 
|---|
| 100 | $definput[1] = "$defoutput[1].tmp"; | 
|---|
| 101 |  | 
|---|
| 102 | if (!$foundBrokenSymbols || $errors) { | 
|---|
| 103 | last; | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | print("Rerunning elf2e32 due to DEF file / ELF file mismatch\n"); | 
|---|
| 107 | } else { | 
|---|
| 108 | last; | 
|---|
| 109 | } | 
|---|
| 110 | }; | 
|---|
| 111 |  | 
|---|
| 112 | if ($fixupFile) { | 
|---|
| 113 | unlink($defoutput[1]); | 
|---|
| 114 | move($fixupFile, $defoutput[1]); | 
|---|
| 115 | } | 
|---|
| 116 |  | 
|---|
| 117 | exit $returnCode if ($returnCode != 0); | 
|---|
| 118 |  | 
|---|
| 119 | if ($buildingLibrary) { | 
|---|
| 120 | my $differenceFound = 0; | 
|---|
| 121 |  | 
|---|
| 122 | if (-e $dso[1]) { | 
|---|
| 123 | my $dsoFile; | 
|---|
| 124 | my $tmpdsoFile; | 
|---|
| 125 | my $dsoBuf; | 
|---|
| 126 | my $tmpdsoBuf; | 
|---|
| 127 | open($dsoFile, "< $dso[1]") or die("Could not open $dso[1]"); | 
|---|
| 128 | open($tmpdsoFile, "< $tmpdso[1]") or die("Could not open $tmpdso[1]"); | 
|---|
| 129 | binmode($dsoFile); | 
|---|
| 130 | binmode($tmpdsoFile); | 
|---|
| 131 | while(read($dsoFile, $dsoBuf, 4096) && read($tmpdsoFile, $tmpdsoBuf, 4096)) { | 
|---|
| 132 | if ($dsoBuf ne $tmpdsoBuf) { | 
|---|
| 133 | $differenceFound = 1; | 
|---|
| 134 | } | 
|---|
| 135 | } | 
|---|
| 136 | close($tmpdsoFile); | 
|---|
| 137 | close($dsoFile); | 
|---|
| 138 | } else { | 
|---|
| 139 | $differenceFound = 1; | 
|---|
| 140 | } | 
|---|
| 141 |  | 
|---|
| 142 | if ($differenceFound) { | 
|---|
| 143 | copy($tmpdso[1], $dso[1]); | 
|---|
| 144 | } | 
|---|
| 145 | } | 
|---|