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