Use bfd_alloc memory for read_debugging_info storage
[binutils-gdb.git] / binutils / rddbg.c
1 /* rddbg.c -- Read debugging information into a generic form.
2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@cygnus.com>.
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 bool read_section_stabs_debugging_info
35 (bfd *, asymbol **, long, void *, bool *);
36 static bool read_symbol_stabs_debugging_info
37 (bfd *, asymbol **, long, void *, bool *);
38 static void save_stab (int, int, bfd_vma, const char *);
39 static void stab_context (void);
40 static void free_saved_stabs (void);
41
42 /* Read debugging information from a BFD. Returns a generic debugging
43 pointer. */
44
45 void *
46 read_debugging_info (bfd *abfd, asymbol **syms, long symcount,
47 bool no_messages)
48 {
49 void *dhandle;
50 bool found;
51
52 dhandle = debug_init (abfd);
53 if (dhandle == NULL)
54 return NULL;
55
56 if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
57 &found))
58 goto err_exit;
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 goto err_exit;
65 }
66
67 /* Try reading the COFF symbols if we didn't find any stabs in COFF
68 sections. */
69 if (! found
70 && bfd_get_flavour (abfd) == bfd_target_coff_flavour
71 && symcount > 0)
72 {
73 if (! parse_coff (abfd, syms, symcount, dhandle))
74 goto err_exit;
75 found = true;
76 }
77
78 if (! found)
79 {
80 if (! no_messages)
81 non_fatal (_("%s: no recognized debugging information"),
82 bfd_get_filename (abfd));
83 err_exit:
84 return NULL;
85 }
86
87 return dhandle;
88 }
89
90 /* Read stabs in sections debugging information from a BFD. */
91
92 static bool
93 read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
94 void *dhandle, bool *pfound)
95 {
96 static struct
97 {
98 const char *secname;
99 const char *strsecname;
100 }
101 names[] =
102 {
103 { ".stab", ".stabstr" },
104 { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" },
105 { "$GDB_SYMBOLS$", "$GDB_STRINGS$" }
106 };
107 unsigned int i;
108 void *shandle;
109 bool ret = false;
110
111 *pfound = false;
112 shandle = NULL;
113
114 for (i = 0; i < sizeof names / sizeof names[0]; i++)
115 {
116 asection *sec, *strsec;
117
118 sec = bfd_get_section_by_name (abfd, names[i].secname);
119 strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
120 if (sec != NULL
121 && (bfd_section_flags (sec) & SEC_HAS_CONTENTS) != 0
122 && bfd_section_size (sec) >= 12
123 && strsec != NULL
124 && (bfd_section_flags (strsec) & SEC_HAS_CONTENTS) != 0)
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 if (!bfd_malloc_and_get_section (abfd, sec, &stabs))
132 {
133 fprintf (stderr, "%s: %s: %s\n",
134 bfd_get_filename (abfd), names[i].secname,
135 bfd_errmsg (bfd_get_error ()));
136 goto out;
137 }
138
139 if (!bfd_malloc_and_get_section (abfd, strsec, &strings))
140 {
141 fprintf (stderr, "%s: %s: %s\n",
142 bfd_get_filename (abfd), names[i].strsecname,
143 bfd_errmsg (bfd_get_error ()));
144 free (stabs);
145 goto out;
146 }
147 /* Zero terminate the strings table, just in case. */
148 strsize = bfd_section_size (strsec);
149 if (strsize != 0)
150 strings [strsize - 1] = 0;
151 if (shandle == NULL)
152 {
153 shandle = start_stab (dhandle, abfd, true, syms, symcount);
154 if (shandle == NULL)
155 {
156 free (strings);
157 free (stabs);
158 goto out;
159 }
160 }
161
162 *pfound = true;
163
164 stroff = 0;
165 next_stroff = 0;
166 stabsize = bfd_section_size (sec);
167 /* PR 17512: file: 078-60391-0.001:0.1. */
168 for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12)
169 {
170 unsigned int strx;
171 int type;
172 int other ATTRIBUTE_UNUSED;
173 int desc;
174 bfd_vma value;
175
176 /* This code presumes 32 bit values. */
177
178 strx = bfd_get_32 (abfd, stab);
179 type = bfd_get_8 (abfd, stab + 4);
180 other = bfd_get_8 (abfd, stab + 5);
181 desc = bfd_get_16 (abfd, stab + 6);
182 value = bfd_get_32 (abfd, stab + 8);
183
184 if (type == 0)
185 {
186 /* Special type 0 stabs indicate the offset to the
187 next string table. */
188 stroff = next_stroff;
189 next_stroff += value;
190 }
191 else
192 {
193 size_t len;
194 char *f, *s;
195
196 if (stroff + strx >= strsize)
197 {
198 fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"),
199 bfd_get_filename (abfd), names[i].secname,
200 (long) (stab - stabs) / 12, strx, type);
201 continue;
202 }
203
204 s = (char *) strings + stroff + strx;
205 f = NULL;
206
207 /* PR 17512: file: 002-87578-0.001:0.1.
208 It is possible to craft a file where, without the 'strlen (s) > 0',
209 an attempt to read the byte before 'strings' would occur. */
210 while ((len = strlen (s)) > 0
211 && s[len - 1] == '\\'
212 && stab + 16 <= stabs + stabsize)
213 {
214 char *p;
215
216 stab += 12;
217 p = s + len - 1;
218 *p = '\0';
219 strx = stroff + bfd_get_32 (abfd, stab);
220 if (strx >= strsize)
221 {
222 fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"),
223 bfd_get_filename (abfd), names[i].secname,
224 (long) (stab - stabs) / 12);
225 break;
226 }
227
228 s = concat (s, (char *) strings + strx,
229 (const char *) NULL);
230
231 /* We have to restore the backslash, because, if
232 the linker is hashing stabs strings, we may
233 see the same string more than once. */
234 *p = '\\';
235
236 free (f);
237 f = s;
238 }
239
240 save_stab (type, desc, value, s);
241
242 if (!parse_stab (dhandle, shandle, type, desc, value, s))
243 {
244 stab_context ();
245 free_saved_stabs ();
246 free (f);
247 free (stabs);
248 free (strings);
249 goto out;
250 }
251
252 free (f);
253 }
254 }
255
256 free_saved_stabs ();
257 free (stabs);
258 free (strings);
259 }
260 }
261 ret = true;
262
263 out:
264 if (shandle != NULL)
265 {
266 if (! finish_stab (dhandle, shandle, ret))
267 return false;
268 }
269
270 return ret;
271 }
272
273 /* Read stabs in the symbol table. */
274
275 static bool
276 read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
277 void *dhandle, bool *pfound)
278 {
279 void *shandle;
280 asymbol **ps, **symend;
281
282 shandle = NULL;
283 symend = syms + symcount;
284 for (ps = syms; ps < symend; ps++)
285 {
286 symbol_info i;
287
288 bfd_get_symbol_info (abfd, *ps, &i);
289
290 if (i.type == '-')
291 {
292 const char *s;
293 char *f;
294
295 if (shandle == NULL)
296 {
297 shandle = start_stab (dhandle, abfd, false, syms, symcount);
298 if (shandle == NULL)
299 return false;
300 }
301
302 *pfound = true;
303
304 s = i.name;
305 if (s == NULL || strlen (s) < 1)
306 break;
307 f = NULL;
308
309 while (strlen (s) > 0
310 && s[strlen (s) - 1] == '\\'
311 && ps + 1 < symend)
312 {
313 char *sc, *n;
314
315 ++ps;
316 sc = xstrdup (s);
317 sc[strlen (sc) - 1] = '\0';
318 n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
319 free (sc);
320 free (f);
321 f = n;
322 s = n;
323 }
324
325 save_stab (i.stab_type, i.stab_desc, i.value, s);
326
327 if (!parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
328 i.value, s))
329 {
330 stab_context ();
331 free (f);
332 break;
333 }
334
335 free (f);
336 }
337 }
338 bool ret = ps >= symend;
339
340 free_saved_stabs ();
341
342 if (shandle != NULL)
343 {
344 if (! finish_stab (dhandle, shandle, ret))
345 return false;
346 }
347
348 return ret;
349 }
350 \f
351 /* Record stabs strings, so that we can give some context for errors. */
352
353 #define SAVE_STABS_COUNT (16)
354
355 struct saved_stab
356 {
357 int type;
358 int desc;
359 bfd_vma value;
360 char *string;
361 };
362
363 static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
364 static int saved_stabs_index;
365
366 /* Save a stabs string. */
367
368 static void
369 save_stab (int type, int desc, bfd_vma value, const char *string)
370 {
371 free (saved_stabs[saved_stabs_index].string);
372 saved_stabs[saved_stabs_index].type = type;
373 saved_stabs[saved_stabs_index].desc = desc;
374 saved_stabs[saved_stabs_index].value = value;
375 saved_stabs[saved_stabs_index].string = xstrdup (string);
376 saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
377 }
378
379 /* Provide context for an error. */
380
381 static void
382 stab_context (void)
383 {
384 int i;
385
386 fprintf (stderr, _("Last stabs entries before error:\n"));
387 fprintf (stderr, "n_type n_desc n_value string\n");
388
389 i = saved_stabs_index;
390 do
391 {
392 struct saved_stab *stabp;
393
394 stabp = saved_stabs + i;
395 if (stabp->string != NULL)
396 {
397 const char *s;
398
399 s = bfd_get_stab_name (stabp->type);
400 if (s != NULL)
401 fprintf (stderr, "%-6s", s);
402 else if (stabp->type == 0)
403 fprintf (stderr, "HdrSym");
404 else
405 fprintf (stderr, "%-6d", stabp->type);
406 fprintf (stderr, " %-6d ", stabp->desc);
407 fprintf (stderr, "%08" PRIx64, (uint64_t) stabp->value);
408 if (stabp->type != 0)
409 fprintf (stderr, " %s", stabp->string);
410 fprintf (stderr, "\n");
411 }
412 i = (i + 1) % SAVE_STABS_COUNT;
413 }
414 while (i != saved_stabs_index);
415 }
416
417 /* Free the saved stab strings. */
418
419 static void
420 free_saved_stabs (void)
421 {
422 int i;
423
424 for (i = 0; i < SAVE_STABS_COUNT; i++)
425 {
426 free (saved_stabs[i].string);
427 saved_stabs[i].string = NULL;
428 }
429
430 saved_stabs_index = 0;
431 }