xref: /titanic_44/usr/src/tools/ctf/dwarf/common/dwarf_macro.c (revision f05d7fc81533be643136e12ce92516d1d4292921)
1 /*
2 
3   Copyright (C) 2000, 2002 Silicon Graphics, Inc.  All Rights Reserved.
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of version 2.1 of the GNU Lesser General Public License
7   as published by the Free Software Foundation.
8 
9   This program is distributed in the hope that it would be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13   Further, this software is distributed without any warranty that it is
14   free of the rightful claim of any third person regarding infringement
15   or the like.  Any license provided herein, whether implied or
16   otherwise, applies only to this software file.  Patent licenses, if
17   any, provided herein do not apply to combinations of this program with
18   other software, or any other product whatsoever.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program; if not, write the Free Software
22   Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
23   USA.
24 
25   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
26   Mountain View, CA 94043, or:
27 
28   http://www.sgi.com
29 
30   For further information regarding this notice, see:
31 
32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
33 
34 */
35 
36 
37 
38 #include "config.h"
39 #include "dwarf_incl.h"
40 #include <stdio.h>
41 #include <limits.h>
42 #include "dwarf_macro.h"
43 
44 
45 #define LEFTPAREN '('
46 #define RIGHTPAREN ')'
47 #define SPACE ' '
48 
49 /*
50 	Given the dwarf macro string, return a pointer to
51 	the value.  Returns pointer to 0 byte at end of string
52 	if no value found (meaning the value is the empty string).
53 
54 	Only understands well-formed dwarf macinfo strings.
55 */
56 char *
57 dwarf_find_macro_value_start(char *str)
58 {
59     char *lcp;
60     int funclike = 0;
61 
62     for (lcp = str; *lcp; ++lcp) {
63 	switch (*lcp) {
64 	case LEFTPAREN:
65 	    funclike = 1;
66 	    break;
67 	case RIGHTPAREN:
68 	    /* lcp+1 must be a space, and following char is the value */
69 	    return lcp + 2;
70 	case SPACE:
71 	    /* we allow extraneous spaces inside macro parameter **
72 	       list, just in case... This is not really needed. */
73 	    if (!funclike) {
74 		return lcp + 1;
75 	    }
76 	    break;
77 	}
78     }
79     /* never found value: returns pointer to the 0 byte at end of
80        string */
81     return lcp;
82 
83 }
84 
85 
86 /*
87    Try to keep fileindex correct in every Macro_Details
88    record by tracking file starts and ends.
89    Uses high water mark: space reused, not freed.
90    Presumption is that this makes sense for most uses.
91    STARTERMAX is set so that the array need not be expanded for
92    most files: it is the initial include file depth.
93 */
94 static Dwarf_Signed *st_base;
95 static long max;
96 static long next_to_use;
97 static int was_fault = 0;
98 
99 #define STARTERMAX 10
100 static void
101 _dwarf_reset_index_stack(void)
102 {
103     next_to_use = 0;
104     was_fault = 0;
105 }
106 static int
107 _dwarf_mac_push_index(Dwarf_Debug dbg, Dwarf_Signed indx)
108 {
109     Dwarf_Signed *newbase;
110 
111     if (next_to_use >= max) {
112 	long new_size;
113 
114 	if (max == 0) {
115 	    max = STARTERMAX;
116 	}
117 	new_size = max * 2;
118 	newbase =
119 	    _dwarf_get_alloc(dbg, DW_DLA_STRING,
120 			     new_size * sizeof(Dwarf_Signed));
121 	if (newbase == 0) {
122 	    /* just leave the old array in place */
123 	    was_fault = 1;
124 	    return DW_DLV_ERROR;
125 	}
126 	memcpy(newbase, st_base, next_to_use * sizeof(Dwarf_Signed));
127 	dwarf_dealloc(dbg, st_base, DW_DLA_STRING);
128 	st_base = newbase;
129 	max = new_size;
130     }
131     st_base[next_to_use] = indx;
132     ++next_to_use;
133     return DW_DLV_OK;
134 }
135 static Dwarf_Signed
136 _dwarf_mac_pop_index(void)
137 {
138     if (was_fault) {
139 	return -1;
140     }
141     if (next_to_use > 0) {
142 	next_to_use--;
143 	return (*(st_base + next_to_use));
144     }
145     return -1;
146 }
147 
148 /* starting at macro_offset in .debug_macinfo,
149 	if maximum_count is 0, treat as if it is infinite.
150 	get macro data up thru
151 	maximum_count entries or the end of a compilation
152 	unit's entries (whichever comes first).
153 */
154 
155 int
156 dwarf_get_macro_details(Dwarf_Debug dbg,
157 			Dwarf_Off macro_offset,
158 			Dwarf_Unsigned maximum_count,
159 			Dwarf_Signed * entry_count,
160 			Dwarf_Macro_Details ** details,
161 			Dwarf_Error * error)
162 {
163     Dwarf_Small *macro_base;
164     Dwarf_Small *pnext;
165     Dwarf_Unsigned endloc;
166     unsigned char uc;
167     unsigned long depth;
168 
169     int res;
170 
171     /* count space used by strings */
172     unsigned long str_space = 0;
173     int done = 0;
174     unsigned long space_needed;
175     unsigned long string_offset;
176     Dwarf_Small *return_data;
177     Dwarf_Small *pdata;
178     unsigned long final_count = 0;
179     Dwarf_Signed fileindex = -1;
180     Dwarf_Small *latest_str_loc;
181 
182     unsigned long count;
183     unsigned long max_count = (unsigned long) maximum_count;
184 
185     _dwarf_reset_index_stack();
186     if (dbg == NULL) {
187 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
188 	return (DW_DLV_ERROR);
189     }
190 
191     res =
192        _dwarf_load_section(dbg,
193 		           dbg->de_debug_macinfo_index,
194 			   &dbg->de_debug_macinfo,
195 			   error);
196     if (res != DW_DLV_OK) {
197 	return res;
198     }
199 
200     macro_base = dbg->de_debug_macinfo;
201     if (macro_base == NULL) {
202 	return (DW_DLV_NO_ENTRY);
203     }
204     if (macro_offset >= dbg->de_debug_macinfo_size) {
205 	return (DW_DLV_NO_ENTRY);
206     }
207 
208     pnext = macro_base + macro_offset;
209     if (maximum_count == 0) {
210 	max_count = ULONG_MAX;
211     }
212 
213 
214     /* how many entries and how much space will they take? */
215 
216     endloc = (pnext - macro_base);
217     if (endloc >= dbg->de_debug_macinfo_size) {
218 	if (endloc == dbg->de_debug_macinfo_size) {
219 	    /* normal: found last entry */
220 	    return DW_DLV_NO_ENTRY;
221 	}
222 	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
223 	return (DW_DLV_ERROR);
224     }
225     for (count = 0; !done && count < max_count; ++count) {
226 	unsigned long slen;
227 	Dwarf_Word len;
228 
229 	uc = *pnext;
230 	++pnext;		/* get past the type code */
231 	switch (uc) {
232 	case DW_MACINFO_define:
233 	case DW_MACINFO_undef:
234 	    /* line, string */
235 	case DW_MACINFO_vendor_ext:
236 	    /* number, string */
237 	    (void) _dwarf_decode_u_leb128(pnext, &len);
238 
239 	    pnext += len;
240 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
241 		_dwarf_error(dbg, error,
242 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
243 		return (DW_DLV_ERROR);
244 	    }
245 	    slen = strlen((char *) pnext) + 1;
246 	    pnext += slen;
247 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
248 		_dwarf_error(dbg, error,
249 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
250 		return (DW_DLV_ERROR);
251 	    }
252 	    str_space += slen;
253 	    break;
254 	case DW_MACINFO_start_file:
255 	    /* line, file index */
256 	    (void) _dwarf_decode_u_leb128(pnext, &len);
257 	    pnext += len;
258 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
259 		_dwarf_error(dbg, error,
260 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
261 		return (DW_DLV_ERROR);
262 	    }
263 	    (void) _dwarf_decode_u_leb128(pnext, &len);
264 	    pnext += len;
265 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
266 		_dwarf_error(dbg, error,
267 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
268 		return (DW_DLV_ERROR);
269 	    }
270 	    ++depth;
271 	    break;
272 
273 	case DW_MACINFO_end_file:
274 	    if (--depth == 0) {
275 		done = 1;
276 	    }
277 	    break;		/* no string or number here */
278 	case 0:
279 	    /* end of cu's entries */
280 	    done = 1;
281 	    break;
282 	default:
283 	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
284 	    return (DW_DLV_ERROR);
285 	    /* bogus macinfo! */
286 	}
287 
288 	endloc = (pnext - macro_base);
289 	if (endloc == dbg->de_debug_macinfo_size) {
290 	    done = 1;
291 	} else if (endloc > dbg->de_debug_macinfo_size) {
292 	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
293 	    return (DW_DLV_ERROR);
294 	}
295     }
296     if (count == 0) {
297 	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR);
298 	return (DW_DLV_ERROR);
299     }
300 
301     /* we have 'count' array entries to allocate and str_space bytes of
302        string space to provide for. */
303 
304     string_offset = count * sizeof(Dwarf_Macro_Details);
305 
306     /* extra 2 not really needed */
307     space_needed = string_offset + str_space + 2;
308     return_data = pdata =
309 	_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
310     latest_str_loc = pdata + string_offset;
311     if (pdata == 0) {
312 	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
313 	return (DW_DLV_ERROR);
314     }
315     pnext = macro_base + macro_offset;
316 
317     done = 0;
318 
319     for (final_count = 0; !done && final_count < count; ++final_count) {
320 	unsigned long slen;
321 	Dwarf_Word len;
322 	Dwarf_Unsigned v1;
323 	Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
324 							     final_count
325 							     *
326 							     sizeof
327 							     (Dwarf_Macro_Details));
328 
329 	endloc = (pnext - macro_base);
330 	if (endloc > dbg->de_debug_macinfo_size) {
331 	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
332 	    return (DW_DLV_ERROR);
333 	}
334 	uc = *pnext;
335 	pdmd->dmd_offset = (pnext - macro_base);
336 	pdmd->dmd_type = uc;
337 	pdmd->dmd_fileindex = fileindex;
338 	pdmd->dmd_lineno = 0;
339 	pdmd->dmd_macro = 0;
340 	++pnext;		/* get past the type code */
341 	switch (uc) {
342 	case DW_MACINFO_define:
343 	case DW_MACINFO_undef:
344 	    /* line, string */
345 	case DW_MACINFO_vendor_ext:
346 	    /* number, string */
347 	    v1 = _dwarf_decode_u_leb128(pnext, &len);
348 	    pdmd->dmd_lineno = v1;
349 
350 	    pnext += len;
351 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
352 		_dwarf_error(dbg, error,
353 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
354 		return (DW_DLV_ERROR);
355 	    }
356 	    slen = strlen((char *) pnext) + 1;
357 	    strcpy((char *) latest_str_loc, (char *) pnext);
358 	    pdmd->dmd_macro = (char *) latest_str_loc;
359 	    latest_str_loc += slen;
360 	    pnext += slen;
361 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
362 		_dwarf_error(dbg, error,
363 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
364 		return (DW_DLV_ERROR);
365 	    }
366 	    str_space += slen;
367 	    break;
368 	case DW_MACINFO_start_file:
369 	    /* line, file index */
370 	    v1 = _dwarf_decode_u_leb128(pnext, &len);
371 	    pdmd->dmd_lineno = v1;
372 	    pnext += len;
373 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
374 		_dwarf_error(dbg, error,
375 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
376 		return (DW_DLV_ERROR);
377 	    }
378 	    v1 = _dwarf_decode_u_leb128(pnext, &len);
379 	    pdmd->dmd_fileindex = v1;
380 	    (void) _dwarf_mac_push_index(dbg, fileindex);
381 	    /* we ignore the error, we just let fileindex ** be -1 when
382 	       we pop this one */
383 	    fileindex = v1;
384 	    pnext += len;
385 	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
386 		_dwarf_error(dbg, error,
387 			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
388 		return (DW_DLV_ERROR);
389 	    }
390 	    break;
391 
392 	case DW_MACINFO_end_file:
393 	    fileindex = _dwarf_mac_pop_index();
394 	    break;		/* no string or number here */
395 	case 0:
396 	    /* end of cu's entries */
397 	    done = 1;
398 	    break;
399 	default:
400 	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
401 	    return (DW_DLV_ERROR);
402 	    /* bogus macinfo! */
403 	}
404     }
405     *entry_count = count;
406     *details = (Dwarf_Macro_Details *) return_data;
407 
408     return DW_DLV_OK;
409 }
410