Rev 5217 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5217 | serge | 1 | /* rddbg.c -- Read debugging information into a generic form. |
6324 | serge | 2 | Copyright (C) 1995-2015 Free Software Foundation, Inc. |
5217 | serge | 3 | Written by Ian Lance Taylor |
4 | |||
5 | This file is part of GNU Binutils. |
||
6 | |||
7 | This program is free software; you can redistribute it and/or modify |
||
8 | it under the terms of the GNU General Public License as published by |
||
9 | the Free Software Foundation; either version 3 of the License, or |
||
10 | (at your option) any later version. |
||
11 | |||
12 | This program is distributed in the hope that it will be useful, |
||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | GNU General Public License for more details. |
||
16 | |||
17 | You should have received a copy of the GNU General Public License |
||
18 | along with this program; if not, write to the Free Software |
||
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
||
20 | 02110-1301, USA. */ |
||
21 | |||
22 | |||
23 | /* This file reads debugging information into a generic form. This |
||
24 | file knows how to dig the debugging information out of an object |
||
25 | file. */ |
||
26 | |||
27 | #include "sysdep.h" |
||
28 | #include "bfd.h" |
||
29 | #include "libiberty.h" |
||
30 | #include "bucomm.h" |
||
31 | #include "debug.h" |
||
32 | #include "budbg.h" |
||
33 | |||
34 | static bfd_boolean read_section_stabs_debugging_info |
||
35 | (bfd *, asymbol **, long, void *, bfd_boolean *); |
||
36 | static bfd_boolean read_symbol_stabs_debugging_info |
||
37 | (bfd *, asymbol **, long, void *, bfd_boolean *); |
||
38 | static bfd_boolean read_ieee_debugging_info (bfd *, void *, bfd_boolean *); |
||
39 | static void save_stab (int, int, bfd_vma, const char *); |
||
40 | static void stab_context (void); |
||
41 | static void free_saved_stabs (void); |
||
42 | |||
43 | /* Read debugging information from a BFD. Returns a generic debugging |
||
44 | pointer. */ |
||
45 | |||
46 | void * |
||
47 | read_debugging_info (bfd *abfd, asymbol **syms, long symcount, bfd_boolean no_messages) |
||
48 | { |
||
49 | void *dhandle; |
||
50 | bfd_boolean found; |
||
51 | |||
52 | dhandle = debug_init (); |
||
53 | if (dhandle == NULL) |
||
54 | return NULL; |
||
55 | |||
56 | if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, |
||
57 | &found)) |
||
58 | return NULL; |
||
59 | |||
60 | if (bfd_get_flavour (abfd) == bfd_target_aout_flavour) |
||
61 | { |
||
62 | if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, |
||
63 | &found)) |
||
64 | return NULL; |
||
65 | } |
||
66 | |||
67 | if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour) |
||
68 | { |
||
69 | if (! read_ieee_debugging_info (abfd, dhandle, &found)) |
||
70 | return NULL; |
||
71 | } |
||
72 | |||
73 | /* Try reading the COFF symbols if we didn't find any stabs in COFF |
||
74 | sections. */ |
||
75 | if (! found |
||
76 | && bfd_get_flavour (abfd) == bfd_target_coff_flavour |
||
77 | && symcount > 0) |
||
78 | { |
||
79 | if (! parse_coff (abfd, syms, symcount, dhandle)) |
||
80 | return NULL; |
||
81 | found = TRUE; |
||
82 | } |
||
83 | |||
84 | if (! found) |
||
85 | { |
||
86 | if (! no_messages) |
||
87 | non_fatal (_("%s: no recognized debugging information"), |
||
88 | bfd_get_filename (abfd)); |
||
89 | return NULL; |
||
90 | } |
||
91 | |||
92 | return dhandle; |
||
93 | } |
||
94 | |||
95 | /* Read stabs in sections debugging information from a BFD. */ |
||
96 | |||
97 | static bfd_boolean |
||
98 | read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, |
||
99 | void *dhandle, bfd_boolean *pfound) |
||
100 | { |
||
101 | static struct |
||
102 | { |
||
103 | const char *secname; |
||
104 | const char *strsecname; |
||
105 | } |
||
106 | names[] = |
||
107 | { |
||
108 | { ".stab", ".stabstr" }, |
||
109 | { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" }, |
||
110 | { "$GDB_SYMBOLS$", "$GDB_STRINGS$" } |
||
111 | }; |
||
112 | unsigned int i; |
||
113 | void *shandle; |
||
114 | |||
115 | *pfound = FALSE; |
||
116 | shandle = NULL; |
||
117 | |||
118 | for (i = 0; i < sizeof names / sizeof names[0]; i++) |
||
119 | { |
||
120 | asection *sec, *strsec; |
||
121 | |||
122 | sec = bfd_get_section_by_name (abfd, names[i].secname); |
||
123 | strsec = bfd_get_section_by_name (abfd, names[i].strsecname); |
||
124 | if (sec != NULL && strsec != NULL) |
||
125 | { |
||
126 | bfd_size_type stabsize, strsize; |
||
127 | bfd_byte *stabs, *strings; |
||
128 | bfd_byte *stab; |
||
129 | bfd_size_type stroff, next_stroff; |
||
130 | |||
131 | stabsize = bfd_section_size (abfd, sec); |
||
132 | stabs = (bfd_byte *) xmalloc (stabsize); |
||
133 | if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) |
||
134 | { |
||
135 | fprintf (stderr, "%s: %s: %s\n", |
||
136 | bfd_get_filename (abfd), names[i].secname, |
||
137 | bfd_errmsg (bfd_get_error ())); |
||
138 | return FALSE; |
||
139 | } |
||
140 | |||
141 | strsize = bfd_section_size (abfd, strsec); |
||
6324 | serge | 142 | strings = (bfd_byte *) xmalloc (strsize + 1); |
5217 | serge | 143 | if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) |
144 | { |
||
145 | fprintf (stderr, "%s: %s: %s\n", |
||
146 | bfd_get_filename (abfd), names[i].strsecname, |
||
147 | bfd_errmsg (bfd_get_error ())); |
||
148 | return FALSE; |
||
149 | } |
||
6324 | serge | 150 | /* Zero terminate the strings table, just in case. */ |
151 | strings [strsize] = 0; |
||
5217 | serge | 152 | if (shandle == NULL) |
153 | { |
||
154 | shandle = start_stab (dhandle, abfd, TRUE, syms, symcount); |
||
155 | if (shandle == NULL) |
||
156 | return FALSE; |
||
157 | } |
||
158 | |||
159 | *pfound = TRUE; |
||
160 | |||
161 | stroff = 0; |
||
162 | next_stroff = 0; |
||
6324 | serge | 163 | /* PR 17512: file: 078-60391-0.001:0.1. */ |
164 | for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12) |
||
5217 | serge | 165 | { |
166 | unsigned int strx; |
||
167 | int type; |
||
168 | int other ATTRIBUTE_UNUSED; |
||
169 | int desc; |
||
170 | bfd_vma value; |
||
171 | |||
172 | /* This code presumes 32 bit values. */ |
||
173 | |||
174 | strx = bfd_get_32 (abfd, stab); |
||
175 | type = bfd_get_8 (abfd, stab + 4); |
||
176 | other = bfd_get_8 (abfd, stab + 5); |
||
177 | desc = bfd_get_16 (abfd, stab + 6); |
||
178 | value = bfd_get_32 (abfd, stab + 8); |
||
179 | |||
180 | if (type == 0) |
||
181 | { |
||
182 | /* Special type 0 stabs indicate the offset to the |
||
183 | next string table. */ |
||
184 | stroff = next_stroff; |
||
185 | next_stroff += value; |
||
186 | } |
||
187 | else |
||
188 | { |
||
6324 | serge | 189 | size_t len; |
5217 | serge | 190 | char *f, *s; |
191 | |||
6324 | serge | 192 | if (stroff + strx >= strsize) |
5217 | serge | 193 | { |
6324 | serge | 194 | fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"), |
5217 | serge | 195 | bfd_get_filename (abfd), names[i].secname, |
196 | (long) (stab - stabs) / 12, strx, type); |
||
197 | continue; |
||
198 | } |
||
199 | |||
200 | s = (char *) strings + stroff + strx; |
||
6324 | serge | 201 | f = NULL; |
5217 | serge | 202 | |
6324 | serge | 203 | /* PR 17512: file: 002-87578-0.001:0.1. |
204 | It is possible to craft a file where, without the 'strlen (s) > 0', |
||
205 | an attempt to read the byte before 'strings' would occur. */ |
||
206 | while ((len = strlen (s)) > 0 |
||
207 | && s[len - 1] == '\\' |
||
5217 | serge | 208 | && stab + 12 < stabs + stabsize) |
209 | { |
||
210 | char *p; |
||
211 | |||
212 | stab += 12; |
||
6324 | serge | 213 | p = s + len - 1; |
5217 | serge | 214 | *p = '\0'; |
6324 | serge | 215 | strx = stroff + bfd_get_32 (abfd, stab); |
216 | if (strx >= strsize) |
||
217 | { |
||
218 | fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"), |
||
219 | bfd_get_filename (abfd), names[i].secname, |
||
220 | (long) (stab - stabs) / 12); |
||
221 | break; |
||
222 | } |
||
223 | else |
||
224 | s = concat (s, (char *) strings + strx, |
||
5217 | serge | 225 | (const char *) NULL); |
226 | |||
227 | /* We have to restore the backslash, because, if |
||
228 | the linker is hashing stabs strings, we may |
||
229 | see the same string more than once. */ |
||
230 | *p = '\\'; |
||
231 | |||
232 | if (f != NULL) |
||
233 | free (f); |
||
234 | f = s; |
||
235 | } |
||
236 | |||
237 | save_stab (type, desc, value, s); |
||
238 | |||
239 | if (! parse_stab (dhandle, shandle, type, desc, value, s)) |
||
240 | { |
||
241 | stab_context (); |
||
242 | free_saved_stabs (); |
||
243 | return FALSE; |
||
244 | } |
||
245 | |||
246 | /* Don't free f, since I think the stabs code |
||
247 | expects strings to hang around. This should be |
||
248 | straightened out. FIXME. */ |
||
249 | } |
||
250 | } |
||
251 | |||
252 | free_saved_stabs (); |
||
253 | free (stabs); |
||
254 | |||
255 | /* Don't free strings, since I think the stabs code expects |
||
256 | the strings to hang around. This should be straightened |
||
257 | out. FIXME. */ |
||
258 | } |
||
259 | } |
||
260 | |||
261 | if (shandle != NULL) |
||
262 | { |
||
263 | if (! finish_stab (dhandle, shandle)) |
||
264 | return FALSE; |
||
265 | } |
||
266 | |||
267 | return TRUE; |
||
268 | } |
||
269 | |||
270 | /* Read stabs in the symbol table. */ |
||
271 | |||
272 | static bfd_boolean |
||
273 | read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, |
||
274 | void *dhandle, bfd_boolean *pfound) |
||
275 | { |
||
276 | void *shandle; |
||
277 | asymbol **ps, **symend; |
||
278 | |||
279 | shandle = NULL; |
||
280 | symend = syms + symcount; |
||
281 | for (ps = syms; ps < symend; ps++) |
||
282 | { |
||
283 | symbol_info i; |
||
284 | |||
285 | bfd_get_symbol_info (abfd, *ps, &i); |
||
286 | |||
287 | if (i.type == '-') |
||
288 | { |
||
289 | const char *s; |
||
290 | char *f; |
||
291 | |||
292 | if (shandle == NULL) |
||
293 | { |
||
294 | shandle = start_stab (dhandle, abfd, FALSE, syms, symcount); |
||
295 | if (shandle == NULL) |
||
296 | return FALSE; |
||
297 | } |
||
298 | |||
299 | *pfound = TRUE; |
||
300 | |||
301 | s = i.name; |
||
302 | f = NULL; |
||
303 | while (s[strlen (s) - 1] == '\\' |
||
304 | && ps + 1 < symend) |
||
305 | { |
||
306 | char *sc, *n; |
||
307 | |||
308 | ++ps; |
||
309 | sc = xstrdup (s); |
||
310 | sc[strlen (sc) - 1] = '\0'; |
||
311 | n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL); |
||
312 | free (sc); |
||
313 | if (f != NULL) |
||
314 | free (f); |
||
315 | f = n; |
||
316 | s = n; |
||
317 | } |
||
318 | |||
319 | save_stab (i.stab_type, i.stab_desc, i.value, s); |
||
320 | |||
321 | if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc, |
||
322 | i.value, s)) |
||
323 | { |
||
324 | stab_context (); |
||
325 | free_saved_stabs (); |
||
326 | return FALSE; |
||
327 | } |
||
328 | |||
329 | /* Don't free f, since I think the stabs code expects |
||
330 | strings to hang around. This should be straightened out. |
||
331 | FIXME. */ |
||
332 | } |
||
333 | } |
||
334 | |||
335 | free_saved_stabs (); |
||
336 | |||
337 | if (shandle != NULL) |
||
338 | { |
||
339 | if (! finish_stab (dhandle, shandle)) |
||
340 | return FALSE; |
||
341 | } |
||
342 | |||
343 | return TRUE; |
||
344 | } |
||
345 | |||
346 | /* Read IEEE debugging information. */ |
||
347 | |||
348 | static bfd_boolean |
||
349 | read_ieee_debugging_info (bfd *abfd, void *dhandle, bfd_boolean *pfound) |
||
350 | { |
||
351 | asection *dsec; |
||
352 | bfd_size_type size; |
||
353 | bfd_byte *contents; |
||
354 | |||
355 | /* The BFD backend puts the debugging information into a section |
||
356 | named .debug. */ |
||
357 | |||
358 | dsec = bfd_get_section_by_name (abfd, ".debug"); |
||
359 | if (dsec == NULL) |
||
360 | return TRUE; |
||
361 | |||
362 | size = bfd_section_size (abfd, dsec); |
||
363 | contents = (bfd_byte *) xmalloc (size); |
||
364 | if (! bfd_get_section_contents (abfd, dsec, contents, 0, size)) |
||
365 | return FALSE; |
||
366 | |||
367 | if (! parse_ieee (dhandle, abfd, contents, size)) |
||
368 | return FALSE; |
||
369 | |||
370 | free (contents); |
||
371 | |||
372 | *pfound = TRUE; |
||
373 | |||
374 | return TRUE; |
||
375 | } |
||
376 | |||
377 | /* Record stabs strings, so that we can give some context for errors. */ |
||
378 | |||
379 | #define SAVE_STABS_COUNT (16) |
||
380 | |||
381 | struct saved_stab |
||
382 | { |
||
383 | int type; |
||
384 | int desc; |
||
385 | bfd_vma value; |
||
386 | char *string; |
||
387 | }; |
||
388 | |||
389 | static struct saved_stab saved_stabs[SAVE_STABS_COUNT]; |
||
390 | static int saved_stabs_index; |
||
391 | |||
392 | /* Save a stabs string. */ |
||
393 | |||
394 | static void |
||
395 | save_stab (int type, int desc, bfd_vma value, const char *string) |
||
396 | { |
||
397 | if (saved_stabs[saved_stabs_index].string != NULL) |
||
398 | free (saved_stabs[saved_stabs_index].string); |
||
399 | saved_stabs[saved_stabs_index].type = type; |
||
400 | saved_stabs[saved_stabs_index].desc = desc; |
||
401 | saved_stabs[saved_stabs_index].value = value; |
||
402 | saved_stabs[saved_stabs_index].string = xstrdup (string); |
||
403 | saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT; |
||
404 | } |
||
405 | |||
406 | /* Provide context for an error. */ |
||
407 | |||
408 | static void |
||
409 | stab_context (void) |
||
410 | { |
||
411 | int i; |
||
412 | |||
413 | fprintf (stderr, _("Last stabs entries before error:\n")); |
||
414 | fprintf (stderr, "n_type n_desc n_value string\n"); |
||
415 | |||
416 | i = saved_stabs_index; |
||
417 | do |
||
418 | { |
||
419 | struct saved_stab *stabp; |
||
420 | |||
421 | stabp = saved_stabs + i; |
||
422 | if (stabp->string != NULL) |
||
423 | { |
||
424 | const char *s; |
||
425 | |||
426 | s = bfd_get_stab_name (stabp->type); |
||
427 | if (s != NULL) |
||
428 | fprintf (stderr, "%-6s", s); |
||
429 | else if (stabp->type == 0) |
||
430 | fprintf (stderr, "HdrSym"); |
||
431 | else |
||
432 | fprintf (stderr, "%-6d", stabp->type); |
||
433 | fprintf (stderr, " %-6d ", stabp->desc); |
||
434 | fprintf_vma (stderr, stabp->value); |
||
435 | if (stabp->type != 0) |
||
436 | fprintf (stderr, " %s", stabp->string); |
||
437 | fprintf (stderr, "\n"); |
||
438 | } |
||
439 | i = (i + 1) % SAVE_STABS_COUNT; |
||
440 | } |
||
441 | while (i != saved_stabs_index); |
||
442 | } |
||
443 | |||
444 | /* Free the saved stab strings. */ |
||
445 | |||
446 | static void |
||
447 | free_saved_stabs (void) |
||
448 | { |
||
449 | int i; |
||
450 | |||
451 | for (i = 0; i < SAVE_STABS_COUNT; i++) |
||
452 | { |
||
453 | if (saved_stabs[i].string != NULL) |
||
454 | { |
||
455 | free (saved_stabs[i].string); |
||
456 | saved_stabs[i].string = NULL; |
||
457 | } |
||
458 | } |
||
459 | |||
460 | saved_stabs_index = 0; |
||
461 | }>>>>=>> |