45 # |
46 # |
46 # main |
47 # main |
47 # |
48 # |
48 sub main() |
49 sub main() |
49 { |
50 { |
50 my $file; |
51 my $symbolfile = $rombuild; |
51 my $mapfile; |
52 $symbolfile =~ s/\.log$/\.symbol/i; |
52 my $mapfile2; |
53 my @cmdres = `rombuild -loginput=$rombuild`; |
53 my $text; |
54 print "@cmdres\n"; |
54 my $data; |
|
55 my $bss; |
|
56 my $textsize; |
|
57 my $datasize; |
|
58 my $bsssize; |
|
59 my $totaldatasize; |
|
60 my $totalsize; |
|
61 |
55 |
62 open (ROM, "<$rombuild") |
56 if(($maksym ne "") && ($maksym ne $symbolfile)) |
63 or die "ERROR: Can't open rombuild log file \"$rombuild\"\n"; |
57 { |
64 if ($maksym ne "") { |
58 copy($symbolfile, $maksym); |
65 open (SYM, ">$maksym") |
59 unlink $symbolfile; |
66 or die "ERROR: Can't open output file \"$maksym\"\n"; |
|
67 print "Creating $maksym...\n"; |
|
68 } |
60 } |
69 |
|
70 while (<ROM>) { |
|
71 # Start of ROM |
|
72 if (/^Creating Rom image (\S*)/) { |
|
73 if ($maksym eq "") { |
|
74 # For backwards compatibility, replace trailing .img with .symbol |
|
75 # if no trailing .img, just append .symbol anyway |
|
76 $maksym = $1; |
|
77 $maksym =~ s/(\.img)?$/.symbol/i; |
|
78 close SYM; |
|
79 open (SYM, ">$maksym") |
|
80 or die "ERROR: Can't open output file \"$maksym\"\n"; |
|
81 print "\nCreating $maksym...\n"; |
|
82 } |
|
83 next; |
|
84 } |
|
85 # end of ROM |
|
86 if (/^Writing Rom image/) { |
|
87 close SYM; |
|
88 $maksym = ""; |
|
89 next; |
|
90 } |
|
91 # Data file |
|
92 if (/^Reading resource (.*) to rom linear address (.*)/) { |
|
93 $file = $1; |
|
94 my $data = hex($2); |
|
95 $file =~ /([^\\]+)$/; |
|
96 printf SYM "\nFrom $file\n\n%08x 0000 $1\n", $data; |
|
97 } |
|
98 # Executable file |
|
99 elsif (/^Processing file (.*)/) { |
|
100 $file = $1; |
|
101 $text = 0; |
|
102 $data = 0; |
|
103 $bss = 0; |
|
104 $textsize = 0; |
|
105 $datasize = 0; |
|
106 $bsssize = 0; |
|
107 $totaldatasize = 0; |
|
108 |
|
109 # Work out final addresses of sections |
|
110 while (defined($_=<ROM>) && !/^$/) { |
|
111 if (/^Size:\s+(\w+)/) { |
|
112 $totalsize = hex($1); |
|
113 } elsif (/^Code start addr:\s+(\w+)/) { |
|
114 $text = hex($1); |
|
115 } elsif (/^Data start addr:\s+(\w+)/) { |
|
116 $data = hex($1); |
|
117 } elsif (/^DataBssLinearBase:\s+(\w+)/) { |
|
118 $bss = hex($1); |
|
119 } elsif (/^Text size:\s+(\w+)/) { |
|
120 $textsize = hex($1); |
|
121 } elsif (/^Data size:\s+(\w+)/) { |
|
122 $datasize = hex($1); |
|
123 } elsif (/^Bsssize:\s+(\w+)/) { |
|
124 $bsssize = hex($1); |
|
125 } elsif (/^Total data size:\s+(\w+)/) { |
|
126 $totaldatasize = hex($1); |
|
127 } |
|
128 } |
|
129 |
|
130 # Sanity check - text section can't be zero |
|
131 die "ERROR: Can't find rombuild info for \"$file\"\n" |
|
132 if (!$text); |
|
133 |
|
134 print SYM "\nFrom $file\n\n"; |
|
135 |
|
136 # Look in map file for symbols in .text and relocate them |
|
137 $mapfile2 = $file.".map"; |
|
138 $mapfile = $file; |
|
139 $mapfile =~ s/\.\w+$/\.map/; |
|
140 if (!(open (MAP, "$mapfile2") || open (MAP, "$mapfile"))) { |
|
141 print "$file\nWarning: Can't open \"$mapfile2\" or \"$mapfile\"\n"; |
|
142 $file =~ /([^\\]+)$/; |
|
143 printf SYM "%08x %04x $1\n", $text, $totalsize; |
|
144 } else { |
|
145 local $/ = undef; |
|
146 my (@maplines) = split(/\n/, <MAP>); |
|
147 close MAP; |
|
148 # See if we're dealing with the RVCT output |
|
149 if ($maplines[0] =~ /^ARM Linker/) { |
|
150 print "$file\n"; |
|
151 |
|
152 my %syms; |
|
153 my @hasharray; |
|
154 # Starts from begining of map file. |
|
155 while (@maplines) { |
|
156 $_ = shift @maplines; |
|
157 if (/Global Symbols/) { |
|
158 last; |
|
159 } elsif (!/(ARM Code|Thumb Code)/) { |
|
160 next; |
|
161 } |
|
162 # name address type size section |
|
163 if (/^\s*(.+)\s*(0x\S+)\s+(ARM Code|Thumb Code)\s+[^\d]*(\d+)\s+(.*)$/) { |
|
164 # Check for static methods in local symbols section. |
|
165 my $sym = $1; |
|
166 my $addr = hex($2); |
|
167 my $size = sprintf("%04x",$4); |
|
168 my $section = $5; |
|
169 $size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/); |
|
170 if(exists($syms{$addr})) { |
|
171 push @{ $syms{$addr} }, "$size $sym $section"; |
|
172 } |
|
173 elsif ($addr > 0){ |
|
174 @hasharray = "$size $sym $section"; |
|
175 $syms{$addr} = [@hasharray]; |
|
176 } |
|
177 } |
|
178 } |
|
179 |
|
180 foreach (@maplines) { |
|
181 # name address ignore size section |
|
182 if (/^\s*(.+)\s*(0x\S+)\s+[^\d]*(\d+)\s+(.*)$/) { |
|
183 my $sym = $1; |
|
184 my $addr = hex($2); |
|
185 my $size = sprintf("%04x",$3); |
|
186 my $section = $4; |
|
187 $size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/); |
|
188 if(exists($syms{$addr})) { |
|
189 push @{ $syms{$addr} }, "$size $sym $section"; |
|
190 } |
|
191 elsif ($addr > 0) { |
|
192 @hasharray = "$size $sym $section"; |
|
193 $syms{$addr} = [@hasharray]; |
|
194 } |
|
195 } |
|
196 } # end of foreach |
|
197 |
|
198 # .text gets linked at 0x00008000 |
|
199 # .data gets linked at 0x00400000 |
|
200 my $srctext = hex(8000); |
|
201 my $srcdata = hex(400000); |
|
202 my $j; |
|
203 # Write symbols in address order |
|
204 my @addrs = sort CompareAddrs keys %syms; |
|
205 for ($i = 0; $i < @addrs ; $i++) { |
|
206 my $thisaddr = $addrs[$i]; |
|
207 my $romaddr = 0; |
|
208 # see if its in the text segment |
|
209 if ($thisaddr >= $srctext && $thisaddr <= ($srctext+$textsize)) { |
|
210 $romaddr = $thisaddr-$srctext+$text; |
|
211 } elsif ( $data && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$datasize))) { |
|
212 # its in the data segment |
|
213 # is it from .data or .bss |
|
214 |
|
215 # confusingly (?) $bss is the right value to use here |
|
216 # since we're interested in where the data gets copied to |
|
217 # in RAM rather than where it sits in ROM |
|
218 $romaddr = $thisaddr-$srcdata+$bss; |
|
219 } elsif ( $bss && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$totaldatasize))) { |
|
220 # its BSS |
|
221 $romaddr = $thisaddr-$srcdata+$bss; |
|
222 } else { |
|
223 my $errsym = $syms{$thisaddr}[0]; |
|
224 my $erraddr = sprintf("%08x", $thisaddr); |
|
225 print "WARNING: Symbol $errsym @ $erraddr not in text or data segments\n"; |
|
226 print "WARNING: The map file for binary $file is out-of-sync with the binary itself\n\n"; |
|
227 next; |
|
228 } |
|
229 |
|
230 printf SYM "%08x %s\n", $romaddr, $_ for @{$syms{$addrs[$i]}}; |
|
231 } # end of for. |
|
232 # See if we're dealing with the GCC output |
|
233 } elsif ($maplines[0] =~ /^Archive member included/) { |
|
234 |
|
235 my $imgtext; |
|
236 my $textlen; |
|
237 my %syms; |
|
238 my $stubhex=1; |
|
239 |
|
240 # Find text section |
|
241 while (@maplines) { |
|
242 $_ = shift @maplines; |
|
243 last if /^\.text\s+/; |
|
244 } |
|
245 |
|
246 /^\.text\s+(\w+)\s+(\w+)/ |
|
247 or die "ERROR: Can't get .text section info for \"$file\"\n"; |
|
248 |
|
249 $imgtext=hex($1); |
|
250 $textlen=hex($2); |
|
251 |
|
252 print "$file\n"; |
|
253 |
|
254 # Slurp symbols 'til the end of the text section |
|
255 foreach (@maplines) { |
|
256 |
|
257 # blank line marks the end of the text section |
|
258 last if (/^$/); |
|
259 |
|
260 # .text <addr> <len> <library(member)> |
|
261 # .text$something |
|
262 # <addr> <len> <library(member)> |
|
263 # <addr> <len> LONG 0x0 |
|
264 |
|
265 if (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io) { |
|
266 my $address = hex($2); |
|
267 my $length = hex($3); |
|
268 my $libraryfile = $4; |
|
269 next if ($libraryfile =~ /^LONG 0x/); |
|
270 $syms{$address+$length} = ' '; # impossible symbol as end marker |
|
271 |
|
272 # EUSER.LIB(ds01423.o) |
|
273 # EUSER.LIB(C:/TEMP/d1000s_01423.o) |
|
274 if ($libraryfile =~ /.*lib\(.*d\d*s_?\d{5}.o\)$/io) { |
|
275 $stubhex=$address; |
|
276 } |
|
277 next; |
|
278 } |
|
279 |
|
280 # <addr> <symbol name possibly including spaces> |
|
281 if (/^\s+(\w+)\s\s+([a-zA-Z_].+)/o) { |
|
282 my $addr = hex($1); |
|
283 my $symbol = $2; |
|
284 $symbol = "stub $symbol" if ($addr == $stubhex); |
|
285 $syms{$addr} = $symbol; |
|
286 next; |
|
287 } |
|
288 } |
|
289 |
|
290 # Write symbols in address order |
|
291 @addrs = sort CompareAddrs keys %syms; |
|
292 for ($i = 0; $i < @addrs - 1; $i++) { |
|
293 my $symbol = $syms{$addrs[$i]}; |
|
294 next if ($symbol eq ' '); |
|
295 printf SYM "%08x %04x %s\n", |
|
296 $addrs[$i]-$imgtext+$text, $addrs[$i+1]-$addrs[$i], $symbol; |
|
297 } |
|
298 # last address assumed to be imgtext+lentext |
|
299 |
|
300 close MAP; |
|
301 } |
|
302 # Must be x86 output |
|
303 else { |
|
304 while (@maplines) { |
|
305 $_ = shift @maplines; |
|
306 last if /^ Address/; |
|
307 } |
|
308 shift @maplines; |
|
309 |
|
310 my ($lastname, $lastaddr); |
|
311 while (@maplines) { |
|
312 $_ = shift @maplines; |
|
313 last unless /^ 0001:(\w+)\s+(\S+)/; |
|
314 my ($addr, $name) = (hex $1, $2); |
|
315 if ($lastname) { |
|
316 my $size = $addr - $lastaddr; |
|
317 printf SYM "%08x %04x %s\n", $lastaddr + $text, $size, $lastname; |
|
318 } |
|
319 ($lastname, $lastaddr) = ($name, $addr); |
|
320 } |
|
321 printf SYM "%08x %04x %s\n", $lastaddr + $text, 0, $lastname if $lastname; |
|
322 } |
|
323 |
|
324 } |
|
325 } |
|
326 } |
|
327 close SYM; |
|
328 close ROM; |
|
329 } |
61 } |
330 |
62 |
331 # |
63 # |
332 # args - get command line args |
64 # args - get command line args |
333 # |
65 # |