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