| 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 | }
 | 
|---|