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