1 /*
2 Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
3 Portions Copyright (C) 2007-2019 David Anderson. All Rights Reserved.
4 Portions Copyright 2012 SN Systems Ltd. All rights reserved.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of version 2.1 of the GNU Lesser General Public License
8 as published by the Free Software Foundation.
9
10 This program is distributed in the hope that it would be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 Further, this software is distributed without any warranty that it is
15 free of the rightful claim of any third person regarding infringement
16 or the like. Any license provided herein, whether implied or
17 otherwise, applies only to this software file. Patent licenses, if
18 any, provided herein do not apply to combinations of this program with
19 other software, or any other product whatsoever.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this program; if not, write the Free Software
23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24 USA.
25
26 */
27
28 #include "config.h"
29 #include <stdio.h>
30 #include <limits.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif /* HAVE_STDLIB_H */
34 #include "dwarf_incl.h"
35 #include "dwarf_alloc.h"
36 #include "dwarf_error.h"
37 #include "dwarf_util.h"
38 #include "dwarf_macro.h"
39
40
41 #define LEFTPAREN '('
42 #define RIGHTPAREN ')'
43 #define SPACE ' '
44
45 /* Given the dwarf macro string, return a pointer to
46 the value. Returns pointer to 0 byte at end of string
47 if no value found (meaning the value is the empty string).
48
49 Only understands well-formed dwarf macinfo strings.
50 */
51 char *
dwarf_find_macro_value_start(char * str)52 dwarf_find_macro_value_start(char *str)
53 {
54 char *lcp;
55 int funclike = 0;
56
57 for (lcp = str; *lcp; ++lcp) {
58 switch (*lcp) {
59 case LEFTPAREN:
60 funclike = 1;
61 break;
62 case RIGHTPAREN:
63 /* lcp+1 must be a space, and following char is the value */
64 return lcp + 2;
65 case SPACE:
66 /* We allow extraneous spaces inside macro parameter **
67 list, just in case... This is not really needed. */
68 if (!funclike) {
69 return lcp + 1;
70 }
71 break;
72 }
73 }
74 /* Never found value: returns pointer to the 0 byte at end of
75 string. */
76 return lcp;
77
78 }
79
80
81 /*
82 Try to keep fileindex correct in every Macro_Details
83 record by tracking file starts and ends.
84 Uses high water mark: space reused, not freed.
85 Presumption is that this makes sense for most uses.
86 STARTERMAX is set so that the array need not be expanded for
87 most files: it is the initial include file depth.
88 */
89 struct macro_stack_s {
90 Dwarf_Signed *st_base;
91 long st_max;
92 long st_next_to_use;
93 int st_was_fault;
94 };
95
96 static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms);
97 static void
free_macro_stack(Dwarf_Debug dbg,struct macro_stack_s * ms)98 free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms)
99 {
100 dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING);
101 _dwarf_reset_index_macro_stack(ms);
102 }
103
104 #define STARTERMAX 10
105 static void
_dwarf_reset_index_macro_stack(struct macro_stack_s * ms)106 _dwarf_reset_index_macro_stack(struct macro_stack_s *ms)
107 {
108 ms->st_base = 0;
109 ms->st_max = 0;
110 ms->st_next_to_use = 0;
111 ms->st_was_fault = 0;
112 }
113 static int
_dwarf_macro_stack_push_index(Dwarf_Debug dbg,Dwarf_Signed indx,struct macro_stack_s * ms)114 _dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx,
115 struct macro_stack_s *ms)
116 {
117
118 if (!ms->st_max || ms->st_next_to_use >= ms->st_max) {
119 long new_size = ms->st_max;
120 Dwarf_Signed *newbase = 0;
121
122 if (!new_size) {
123 new_size = STARTERMAX;
124 }
125 new_size = new_size * 2;
126 newbase =
127 (Dwarf_Signed *)_dwarf_get_alloc(dbg, DW_DLA_STRING,
128 new_size * sizeof(Dwarf_Signed));
129 if (!newbase) {
130 /* just leave the old array in place */
131 ms->st_was_fault = 1;
132 return DW_DLV_ERROR;
133 }
134 if (ms->st_base) {
135 memcpy(newbase, ms->st_base,
136 ms->st_next_to_use * sizeof(Dwarf_Signed));
137 dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING);
138 }
139 ms->st_base = newbase;
140 ms->st_max = new_size;
141 }
142 ms->st_base[ms->st_next_to_use] = indx;
143 ++ms->st_next_to_use;
144 return DW_DLV_OK;
145 }
146
147 static Dwarf_Signed
_dwarf_macro_stack_pop_index(struct macro_stack_s * ms)148 _dwarf_macro_stack_pop_index(struct macro_stack_s *ms)
149 {
150 if (ms->st_was_fault) {
151 return -1;
152 }
153 if (ms->st_next_to_use > 0) {
154 ms->st_next_to_use--;
155 return (ms->st_base[ms->st_next_to_use]);
156 } else {
157 ms->st_was_fault = 1;
158 }
159 return -1;
160 }
161
162 /* Starting at macro_offset in .debug_macinfo,
163 if maximum_count is 0, treat as if it is infinite.
164 get macro data up thru
165 maximum_count entries or the end of a compilation
166 unit's entries (whichever comes first).
167
168 .debug_macinfo never appears in a .dwp Package File.
169 So offset adjustment for such is not needed.
170 */
171
172 int
dwarf_get_macro_details(Dwarf_Debug dbg,Dwarf_Off macro_offset,Dwarf_Unsigned maximum_count,Dwarf_Signed * entry_count,Dwarf_Macro_Details ** details,Dwarf_Error * error)173 dwarf_get_macro_details(Dwarf_Debug dbg,
174 Dwarf_Off macro_offset,
175 Dwarf_Unsigned maximum_count,
176 Dwarf_Signed * entry_count,
177 Dwarf_Macro_Details ** details,
178 Dwarf_Error * error)
179 {
180 Dwarf_Small *macro_base = 0;
181 Dwarf_Small *macro_end = 0;
182 Dwarf_Small *pnext = 0;
183 Dwarf_Unsigned endloc = 0;
184 unsigned char uc = 0;
185 unsigned long depth = 0;
186 /* By section 6.3.2 Dwarf3 draft 8/9,
187 the base file should appear as
188 DW_MACINFO_start_file. See
189 http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html
190 on "[Bug debug/20253] New: [3.4/4.0 regression]:
191 Macro debug info broken due to lexer change" for how
192 gcc is broken in some versions. We no longer use
193 depth as a stopping point, it's not needed as a
194 stopping point anyway. */
195 int res = 0;
196 /* count space used by strings */
197 unsigned long str_space = 0;
198 int done = 0;
199 unsigned long space_needed = 0;
200 unsigned long string_offset = 0;
201 Dwarf_Small *return_data = 0;
202 Dwarf_Small *pdata = 0;
203 unsigned long final_count = 0;
204 Dwarf_Signed fileindex = -1;
205 Dwarf_Small *latest_str_loc = 0;
206 struct macro_stack_s msdata;
207
208 unsigned long count = 0;
209 unsigned long max_count = (unsigned long) maximum_count;
210
211 _dwarf_reset_index_macro_stack(&msdata);
212 if (dbg == NULL) {
213 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
214 free_macro_stack(dbg,&msdata);
215 return (DW_DLV_ERROR);
216 }
217
218 res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error);
219 if (res != DW_DLV_OK) {
220 free_macro_stack(dbg,&msdata);
221 return res;
222 }
223 if (!dbg->de_debug_abbrev.dss_size) {
224 free_macro_stack(dbg,&msdata);
225 return (DW_DLV_NO_ENTRY);
226 }
227
228 macro_base = dbg->de_debug_macinfo.dss_data;
229 if (macro_base == NULL) {
230 free_macro_stack(dbg,&msdata);
231 return (DW_DLV_NO_ENTRY);
232 }
233 if (macro_offset >= dbg->de_debug_macinfo.dss_size) {
234 free_macro_stack(dbg,&msdata);
235 return (DW_DLV_NO_ENTRY);
236 }
237 macro_end = macro_base + dbg->de_debug_macinfo.dss_size;
238 /* FIXME debugfission is NOT handled here. */
239
240 pnext = macro_base + macro_offset;
241 if (maximum_count == 0) {
242 max_count = ULONG_MAX;
243 }
244
245
246 /* how many entries and how much space will they take? */
247
248 endloc = (pnext - macro_base);
249 if (endloc >= dbg->de_debug_macinfo.dss_size) {
250 if (endloc == dbg->de_debug_macinfo.dss_size) {
251 /* normal: found last entry */
252 free_macro_stack(dbg,&msdata);
253 return DW_DLV_NO_ENTRY;
254 }
255 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
256 free_macro_stack(dbg,&msdata);
257 return (DW_DLV_ERROR);
258 }
259 for (count = 0; !done && count < max_count; ++count) {
260 unsigned long slen = 0;
261
262 /* Set but not used */
263 UNUSEDARG Dwarf_Unsigned utemp = 0;
264
265 uc = *pnext;
266 ++pnext; /* get past the type code */
267 switch (uc) {
268 case DW_MACINFO_define:
269 case DW_MACINFO_undef:
270 /* line, string */
271 case DW_MACINFO_vendor_ext:
272 /* number, string */
273 DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
274 macro_end);
275 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
276 dbg->de_debug_macinfo.dss_size) {
277 free_macro_stack(dbg,&msdata);
278 _dwarf_error(dbg, error,
279 DW_DLE_DEBUG_MACRO_INCONSISTENT);
280 return (DW_DLV_ERROR);
281 }
282 res = _dwarf_check_string_valid(dbg,
283 macro_base,pnext,macro_end,
284 DW_DLE_MACINFO_STRING_BAD,error);
285 if (res != DW_DLV_OK) {
286 return res;
287 }
288 slen = strlen((char *) pnext) + 1;
289 pnext += slen;
290 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
291 dbg->de_debug_macinfo.dss_size) {
292 free_macro_stack(dbg,&msdata);
293 _dwarf_error(dbg, error,
294 DW_DLE_DEBUG_MACRO_INCONSISTENT);
295 return (DW_DLV_ERROR);
296 }
297 str_space += slen;
298 break;
299 case DW_MACINFO_start_file:
300 /* line, file index */
301 DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
302 macro_end);
303 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
304 dbg->de_debug_macinfo.dss_size) {
305 free_macro_stack(dbg,&msdata);
306 _dwarf_error(dbg, error,
307 DW_DLE_DEBUG_MACRO_INCONSISTENT);
308 return (DW_DLV_ERROR);
309 }
310 DECODE_LEB128_UWORD_CK(pnext,utemp,dbg,error,
311 macro_end);
312 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
313 dbg->de_debug_macinfo.dss_size) {
314 free_macro_stack(dbg,&msdata);
315 _dwarf_error(dbg, error,
316 DW_DLE_DEBUG_MACRO_INCONSISTENT);
317 return (DW_DLV_ERROR);
318 }
319 ++depth;
320 break;
321
322 case DW_MACINFO_end_file:
323 if (--depth == 0) {
324 /* done = 1; no, do not stop here, at least one gcc had
325 the wrong depth settings in the gcc 3.4 timeframe. */
326 }
327 /* no string or number here */
328 break;
329 case 0:
330 /* end of cu's entries */
331 done = 1;
332 break;
333 default:
334 free_macro_stack(dbg,&msdata);
335 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
336 return (DW_DLV_ERROR);
337 /* bogus macinfo! */
338 }
339
340 endloc = (pnext - macro_base);
341 if (endloc == dbg->de_debug_macinfo.dss_size) {
342 done = 1;
343 } else if (endloc > dbg->de_debug_macinfo.dss_size) {
344 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
345 free_macro_stack(dbg,&msdata);
346 return (DW_DLV_ERROR);
347 }
348 }
349 /* ASSERT: The above loop will never let us get here
350 with count < 1. No need to test for a zero count.
351
352 We have 'count' array entries to allocate and
353 str_space bytes of string space to provide for. */
354
355 string_offset = count * sizeof(Dwarf_Macro_Details);
356
357 /* extra 2 not really needed */
358 space_needed = string_offset + str_space + 2;
359 return_data = pdata =
360 (Dwarf_Small *)_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
361 latest_str_loc = pdata + string_offset;
362 if (pdata == 0) {
363 free_macro_stack(dbg,&msdata);
364 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
365 return (DW_DLV_ERROR);
366 }
367 pnext = macro_base + macro_offset;
368
369 done = 0;
370
371 /* A series ends with a type code of 0. */
372
373 for (final_count = 0; !done && final_count < count; ++final_count) {
374 unsigned long slen = 0;
375 Dwarf_Unsigned v1 = 0;
376 Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
377 (final_count * sizeof (Dwarf_Macro_Details)));
378
379 endloc = (pnext - macro_base);
380 if (endloc > dbg->de_debug_macinfo.dss_size) {
381 free_macro_stack(dbg,&msdata);
382 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
383 return (DW_DLV_ERROR);
384 }
385 uc = *pnext;
386 pdmd->dmd_offset = (pnext - macro_base);
387 pdmd->dmd_type = uc;
388 pdmd->dmd_fileindex = fileindex;
389 pdmd->dmd_lineno = 0;
390 pdmd->dmd_macro = 0;
391 ++pnext; /* get past the type code */
392 switch (uc) {
393 case DW_MACINFO_define:
394 case DW_MACINFO_undef:
395 /* line, string */
396 case DW_MACINFO_vendor_ext:
397 /* number, string */
398 DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
399 macro_end);
400 pdmd->dmd_lineno = v1;
401
402 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
403 dbg->de_debug_macinfo.dss_size) {
404 free_macro_stack(dbg,&msdata);
405 dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
406 _dwarf_error(dbg, error,
407 DW_DLE_DEBUG_MACRO_INCONSISTENT);
408 return (DW_DLV_ERROR);
409 }
410 res = _dwarf_check_string_valid(dbg,
411 macro_base,pnext,macro_end,
412 DW_DLE_MACINFO_STRING_BAD,error);
413 if (res != DW_DLV_OK) {
414 return res;
415 }
416 slen = strlen((char *) pnext) + 1;
417 strcpy((char *) latest_str_loc, (char *) pnext);
418 pdmd->dmd_macro = (char *) latest_str_loc;
419 latest_str_loc += slen;
420 pnext += slen;
421 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
422 dbg->de_debug_macinfo.dss_size) {
423 free_macro_stack(dbg,&msdata);
424 dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
425 _dwarf_error(dbg, error,
426 DW_DLE_DEBUG_MACRO_INCONSISTENT);
427 return (DW_DLV_ERROR);
428 }
429 break;
430 case DW_MACINFO_start_file:
431 /* Line, file index */
432 DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
433 macro_end);
434 pdmd->dmd_lineno = v1;
435 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
436 dbg->de_debug_macinfo.dss_size) {
437 free_macro_stack(dbg,&msdata);
438 dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
439 _dwarf_error(dbg, error,
440 DW_DLE_DEBUG_MACRO_INCONSISTENT);
441 return (DW_DLV_ERROR);
442 }
443 DECODE_LEB128_UWORD_CK(pnext,v1,dbg,error,
444 macro_end);
445 pdmd->dmd_fileindex = v1;
446 (void) _dwarf_macro_stack_push_index(dbg, fileindex,
447 &msdata);
448 /* We ignore the error, we just let fileindex ** be -1 when
449 we pop this one. */
450 fileindex = v1;
451 if (((Dwarf_Unsigned)(pnext - macro_base)) >=
452 dbg->de_debug_macinfo.dss_size) {
453 free_macro_stack(dbg,&msdata);
454 dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
455 _dwarf_error(dbg, error,
456 DW_DLE_DEBUG_MACRO_INCONSISTENT);
457 return (DW_DLV_ERROR);
458 }
459 break;
460
461 case DW_MACINFO_end_file:
462 fileindex = _dwarf_macro_stack_pop_index(&msdata);
463 break; /* no string or number here */
464 case 0:
465 /* Type code of 0 means the end of cu's entries. */
466 done = 1;
467 break;
468 default:
469 /* Bogus macinfo! */
470 dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
471 free_macro_stack(dbg,&msdata);
472 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
473 return (DW_DLV_ERROR);
474 }
475 }
476 *entry_count = count;
477 *details = (Dwarf_Macro_Details *) return_data;
478 free_macro_stack(dbg,&msdata);
479 return DW_DLV_OK;
480 }
481