xref: /titanic_44/usr/src/tools/ctf/dwarf/common/dwarf_arange.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 
39 #include "config.h"
40 #include "dwarf_incl.h"
41 #include <stdio.h>
42 #include "dwarf_arange.h"
43 
44 
45 /*
46     This function returns the count of the number of
47     aranges in the .debug_aranges section.  It sets
48     aranges to point to a block of Dwarf_Arange's
49     describing the arange's.  It returns DW_DLV_ERROR
50     on error.
51 
52     Must be identical in most aspects to
53 	dwarf_get_aranges_addr_offsets!
54 */
55 int
56 dwarf_get_aranges(Dwarf_Debug dbg,
57 		  Dwarf_Arange ** aranges,
58 		  Dwarf_Signed * returned_count, Dwarf_Error * error)
59 {
60     /* Sweeps the .debug_aranges section. */
61     Dwarf_Small *arange_ptr;
62 
63     /*
64        Start of arange header.  Used for rounding offset of arange_ptr
65        to twice the tuple size.  Libdwarf requirement. */
66     Dwarf_Small *header_ptr;
67 
68 
69     /* Version of .debug_aranges header. */
70     Dwarf_Half version;
71 
72     /* Offset of current set of aranges into .debug_info. */
73     Dwarf_Off info_offset;
74 
75     /* Size in bytes of addresses in target. */
76     Dwarf_Small address_size;
77 
78     /* Size in bytes of segment offsets in target. */
79     Dwarf_Small segment_size;
80 
81     Dwarf_Small remainder;
82 
83     /* Count of total number of aranges. */
84     Dwarf_Unsigned arange_count = 0;
85 
86     /* Start address of arange. */
87     Dwarf_Addr range_address;
88 
89     /* Length of arange. */
90     Dwarf_Unsigned range_length;
91 
92     Dwarf_Arange arange, *arange_block;
93 
94     Dwarf_Unsigned i;
95 
96     /* Used to chain Dwarf_Aranges structs. */
97     Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
98 
99     int res;
100 
101     /* ***** BEGIN CODE ***** */
102 
103     if (dbg == NULL) {
104 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
105 	return (DW_DLV_ERROR);
106     }
107 
108     res =
109         _dwarf_load_section(dbg,
110 			    dbg->de_debug_aranges_index,
111 			    &dbg->de_debug_aranges,
112 			    error);
113     if (res != DW_DLV_OK) {
114         return res;
115     }
116 
117     arange_ptr = dbg->de_debug_aranges;
118     do {
119         /* Length of current set of aranges. */
120         Dwarf_Unsigned length;
121 	Dwarf_Small *arange_ptr_past_end = 0;
122 
123 	int local_length_size;
124 	/*REFERENCED*/ /* Not used in this instance of the macro */
125 	int local_extension_size;
126 
127 	header_ptr = arange_ptr;
128 
129 	/* READ_AREA_LENGTH updates arange_ptr for consumed bytes */
130 	READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
131 			 arange_ptr, local_length_size,
132 			 local_extension_size);
133 	arange_ptr_past_end = arange_ptr + length;
134 
135 
136 	READ_UNALIGNED(dbg, version, Dwarf_Half,
137 		       arange_ptr, sizeof(Dwarf_Half));
138 	arange_ptr += sizeof(Dwarf_Half);
139 	length = length - sizeof(Dwarf_Half);
140 	if (version != CURRENT_VERSION_STAMP) {
141 	    _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
142 	    return (DW_DLV_ERROR);
143 	}
144 
145 	READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
146 		       arange_ptr, local_length_size);
147 	arange_ptr += local_length_size;
148 	length = length - local_length_size;
149 	if (info_offset >= dbg->de_debug_info_size) {
150 	    _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
151 	    return (DW_DLV_ERROR);
152 	}
153 
154 	address_size = *(Dwarf_Small *) arange_ptr;
155 	if (address_size != dbg->de_pointer_size) {
156 	    /* Internal error of some kind */
157 	    _dwarf_error(dbg, error, DW_DLE_BADBITC);
158 	    return (DW_DLV_ERROR);
159 	}
160 	arange_ptr = arange_ptr + sizeof(Dwarf_Small);
161 	length = length - sizeof(Dwarf_Small);
162 
163 	segment_size = *(Dwarf_Small *) arange_ptr;
164 	arange_ptr = arange_ptr + sizeof(Dwarf_Small);
165 	length = length - sizeof(Dwarf_Small);
166 	if (segment_size != 0) {
167 	    _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
168 	    return (DW_DLV_ERROR);
169 	}
170 
171 	/* Round arange_ptr offset to next multiple of address_size. */
172 	remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
173 	    (2 * address_size);
174 	if (remainder != 0) {
175 	    arange_ptr = arange_ptr + (2 * address_size) - remainder;
176 	    length = length - ((2 * address_size) - remainder);
177 	}
178 
179 	do {
180 	    READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
181 			   arange_ptr, address_size);
182 	    arange_ptr += address_size;
183 	    length = length - address_size;
184 
185 	    READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
186 			   arange_ptr, address_size);
187 	    arange_ptr += address_size;
188 	    length = length - address_size;
189 
190 	    if (range_address != 0 || range_length != 0) {
191 
192 		arange = (Dwarf_Arange)
193 		    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
194 		if (arange == NULL) {
195 		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
196 		    return (DW_DLV_ERROR);
197 		}
198 
199 		arange->ar_address = range_address;
200 		arange->ar_length = range_length;
201 		arange->ar_info_offset = info_offset;
202 		arange->ar_dbg = dbg;
203 		arange_count++;
204 
205 		curr_chain = (Dwarf_Chain)
206 		    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
207 		if (curr_chain == NULL) {
208 		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
209 		    return (DW_DLV_ERROR);
210 		}
211 
212 		curr_chain->ch_item = arange;
213 		if (head_chain == NULL)
214 		    head_chain = prev_chain = curr_chain;
215 		else {
216 		    prev_chain->ch_next = curr_chain;
217 		    prev_chain = curr_chain;
218 		}
219 	    }
220 	} while (range_address != 0 || range_length != 0);
221 
222 	/* A compiler could emit some padding bytes here.
223 	   dwarf2/3 (dwarf3 draft8 sec 7.20) does not clearly make
224 	   extra padding bytes illegal. */
225 	if(arange_ptr_past_end < arange_ptr) {
226 	    _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
227 	    return (DW_DLV_ERROR);
228 	}
229 	/* For most compilers, arange_ptr == arange_ptr_past_end
230 	   at this point. But not if there were padding bytes */
231 	arange_ptr = arange_ptr_past_end;
232 
233     } while (arange_ptr <
234 	     dbg->de_debug_aranges + dbg->de_debug_aranges_size);
235 
236     if (arange_ptr !=
237 	dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
238 	_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
239 	return (DW_DLV_ERROR);
240     }
241 
242     arange_block = (Dwarf_Arange *)
243 	_dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
244     if (arange_block == NULL) {
245 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
246 	return (DW_DLV_ERROR);
247     }
248 
249     curr_chain = head_chain;
250     for (i = 0; i < arange_count; i++) {
251 	*(arange_block + i) = curr_chain->ch_item;
252 	prev_chain = curr_chain;
253 	curr_chain = curr_chain->ch_next;
254 	dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
255     }
256 
257     *aranges = arange_block;
258     *returned_count = (arange_count);
259     return DW_DLV_OK;
260 }
261 
262 /*
263     This function returns DW_DLV_OK if it succeeds
264     and DW_DLV_ERR or DW_DLV_OK otherwise.
265     count is set to the number of addresses in the
266     .debug_aranges section.
267     For each address, the corresponding element in
268     an array is set to the address itself(aranges) and
269     the section offset (offsets).
270     Must be identical in most aspects to
271 	dwarf_get_aranges!
272 */
273 int
274 _dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
275 				Dwarf_Addr ** addrs,
276 				Dwarf_Off ** offsets,
277 				Dwarf_Signed * count,
278 				Dwarf_Error * error)
279 {
280     /* Sweeps the .debug_aranges section. */
281     Dwarf_Small *arange_ptr;
282     Dwarf_Small *arange_start_ptr;
283 
284     /*
285        Start of arange header.  Used for rounding offset of arange_ptr
286        to twice the tuple size.  Libdwarf requirement. */
287     Dwarf_Small *header_ptr;
288 
289     /* Length of current set of aranges. */
290     Dwarf_Unsigned length;
291 
292     /* Version of .debug_aranges header. */
293     Dwarf_Half version;
294 
295     /* Offset of current set of aranges into .debug_info. */
296     Dwarf_Off info_offset;
297 
298     /* Size in bytes of addresses in target. */
299     Dwarf_Small address_size;
300 
301     /* Size in bytes of segment offsets in target. */
302     Dwarf_Small segment_size;
303 
304     Dwarf_Small remainder;
305 
306     /* Count of total number of aranges. */
307     Dwarf_Unsigned arange_count = 0;
308 
309     /* Start address of arange. */
310     Dwarf_Addr range_address;
311 
312     /* Length of arange. */
313     Dwarf_Unsigned range_length;
314 
315     Dwarf_Arange arange;
316 
317     Dwarf_Unsigned i;
318 
319     /* Used to chain Dwarf_Aranges structs. */
320     Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
321 
322     Dwarf_Addr *arange_addrs;
323     Dwarf_Off *arange_offsets;
324 
325     int res;
326 
327     /* ***** BEGIN CODE ***** */
328 
329     if (error != NULL)
330 	*error = NULL;
331 
332     if (dbg == NULL) {
333 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
334 	return (DW_DLV_ERROR);
335     }
336 
337     res =
338         _dwarf_load_section(dbg,
339 			    dbg->de_debug_aranges_index,
340 			    &dbg->de_debug_aranges,
341 			    error);
342     if (res != DW_DLV_OK) {
343         return res;
344     }
345 
346     arange_ptr = dbg->de_debug_aranges;
347     do {
348 	int local_length_size;
349 	/*REFERENCED*/ /* not used in this instance of the macro */
350 	int local_extension_size;
351 
352 	header_ptr = arange_ptr;
353 
354 
355 	/* READ_AREA_LENGTH updates arange_ptr for consumed bytes */
356 	READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
357 			 arange_ptr, local_length_size,
358 			 local_extension_size);
359 
360 
361 	READ_UNALIGNED(dbg, version, Dwarf_Half,
362 		       arange_ptr, sizeof(Dwarf_Half));
363 	arange_ptr += sizeof(Dwarf_Half);
364 	length = length - sizeof(Dwarf_Half);
365 	if (version != CURRENT_VERSION_STAMP) {
366 	    _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
367 	    return (DW_DLV_ERROR);
368 	}
369 
370 	READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
371 		       arange_ptr, local_length_size);
372 	arange_ptr += local_length_size;
373 	length = length - local_length_size;
374 	if (info_offset >= dbg->de_debug_info_size) {
375 	    _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
376 	    return (DW_DLV_ERROR);
377 	}
378 
379 	address_size = *(Dwarf_Small *) arange_ptr;
380 	arange_ptr = arange_ptr + sizeof(Dwarf_Small);
381 	length = length - sizeof(Dwarf_Small);
382 
383 	segment_size = *(Dwarf_Small *) arange_ptr;
384 	arange_ptr = arange_ptr + sizeof(Dwarf_Small);
385 	length = length - sizeof(Dwarf_Small);
386 	if (segment_size != 0) {
387 	    _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
388 	    return (DW_DLV_ERROR);
389 	}
390 
391 	/* Round arange_ptr offset to next multiple of address_size. */
392 	remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
393 	    (2 * address_size);
394 	if (remainder != 0) {
395 	    arange_ptr = arange_ptr + (2 * address_size) - remainder;
396 	    length = length - ((2 * address_size) - remainder);
397 	}
398 
399 	do {
400 	    arange_start_ptr = arange_ptr;
401 	    READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
402 			   arange_ptr, dbg->de_pointer_size);
403 	    arange_ptr += dbg->de_pointer_size;
404 	    length = length - dbg->de_pointer_size;
405 
406 	    READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
407 			   arange_ptr, local_length_size);
408 	    arange_ptr += local_length_size;
409 	    length = length - local_length_size;
410 
411 	    if (range_address != 0 || range_length != 0) {
412 
413 		arange = (Dwarf_Arange)
414 		    _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
415 		if (arange == NULL) {
416 		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
417 		    return (DW_DLV_ERROR);
418 		}
419 
420 		arange->ar_address = range_address;
421 		arange->ar_length = range_length;
422 		arange->ar_info_offset =
423 		    arange_start_ptr - dbg->de_debug_aranges;
424 		arange->ar_dbg = dbg;
425 		arange_count++;
426 
427 		curr_chain = (Dwarf_Chain)
428 		    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
429 		if (curr_chain == NULL) {
430 		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
431 		    return (DW_DLV_ERROR);
432 		}
433 
434 		curr_chain->ch_item = arange;
435 		if (head_chain == NULL)
436 		    head_chain = prev_chain = curr_chain;
437 		else {
438 		    prev_chain->ch_next = curr_chain;
439 		    prev_chain = curr_chain;
440 		}
441 	    }
442 	} while (range_address != 0 || range_length != 0);
443 
444 	if (length != 0) {
445 	    _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
446 	    return (DW_DLV_ERROR);
447 	}
448 
449     } while (arange_ptr <
450 	     dbg->de_debug_aranges + dbg->de_debug_aranges_size);
451 
452     if (arange_ptr !=
453 	dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
454 	_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
455 	return (DW_DLV_ERROR);
456     }
457 
458     arange_addrs = (Dwarf_Addr *)
459 	_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
460     if (arange_addrs == NULL) {
461 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
462 	return (DW_DLV_ERROR);
463     }
464     arange_offsets = (Dwarf_Off *)
465 	_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
466     if (arange_offsets == NULL) {
467 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
468 	return (DW_DLV_ERROR);
469     }
470 
471     curr_chain = head_chain;
472     for (i = 0; i < arange_count; i++) {
473 	Dwarf_Arange ar = curr_chain->ch_item;
474 
475 	arange_addrs[i] = ar->ar_address;
476 	arange_offsets[i] = ar->ar_info_offset;
477 	prev_chain = curr_chain;
478 	curr_chain = curr_chain->ch_next;
479 	dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
480 	dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
481     }
482     *count = arange_count;
483     *offsets = arange_offsets;
484     *addrs = arange_addrs;
485     return (DW_DLV_OK);
486 }
487 
488 
489 /*
490     This function takes a pointer to a block
491     of Dwarf_Arange's, and a count of the
492     length of the block.  It checks if the
493     given address is within the range of an
494     address range in the block.  If yes, it
495     returns the appropriate Dwarf_Arange.
496     Otherwise, it returns DW_DLV_ERROR.
497 */
498 int
499 dwarf_get_arange(Dwarf_Arange * aranges,
500 		 Dwarf_Unsigned arange_count,
501 		 Dwarf_Addr address,
502 		 Dwarf_Arange * returned_arange, Dwarf_Error * error)
503 {
504     Dwarf_Arange curr_arange;
505     Dwarf_Unsigned i;
506 
507     if (aranges == NULL) {
508 	_dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
509 	return (DW_DLV_ERROR);
510     }
511 
512     for (i = 0; i < arange_count; i++) {
513 	curr_arange = *(aranges + i);
514 	if (address >= curr_arange->ar_address &&
515 	    address <
516 	    curr_arange->ar_address + curr_arange->ar_length) {
517 	    *returned_arange = curr_arange;
518 	    return (DW_DLV_OK);
519 	}
520     }
521 
522     return (DW_DLV_NO_ENTRY);
523 }
524 
525 
526 /*
527     This function takes an Dwarf_Arange,
528     and returns the offset of the first
529     die in the compilation-unit that the
530     arange belongs to.  Returns DW_DLV_ERROR
531     on error.
532 */
533 int
534 dwarf_get_cu_die_offset(Dwarf_Arange arange,
535 			Dwarf_Off * returned_offset,
536 			Dwarf_Error * error)
537 {
538     Dwarf_Debug dbg;
539     Dwarf_Off offset;
540 
541     if (arange == NULL) {
542 	_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
543 	return (DW_DLV_ERROR);
544     }
545 
546 
547     dbg = arange->ar_dbg;
548 
549 
550     offset = arange->ar_info_offset;
551     if(!dbg->de_debug_info) {
552         int res = _dwarf_load_debug_info(dbg,error);
553         if(res != DW_DLV_OK) {
554 	    return res;
555         }
556     }
557 
558     *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset);
559     return DW_DLV_OK;
560 }
561 
562 /*
563     This function takes an Dwarf_Arange,
564     and returns the offset of the CU header
565     in the compilation-unit that the
566     arange belongs to.  Returns DW_DLV_ERROR
567     on error.
568 */
569 int
570 dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
571 				  Dwarf_Off * cu_header_offset_returned,
572 				  Dwarf_Error * error)
573 {
574     if (arange == NULL) {
575 	_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
576 	return (DW_DLV_ERROR);
577     }
578 
579     *cu_header_offset_returned = arange->ar_info_offset;
580     return DW_DLV_OK;
581 }
582 
583 
584 
585 /*
586     This function takes a Dwarf_Arange, and returns
587     true if it is not NULL.  It also stores the start
588     address of the range in *start, the length of the
589     range in *length, and the offset of the first die
590     in the compilation-unit in *cu_die_offset.  It
591     returns false on error.
592 */
593 int
594 dwarf_get_arange_info(Dwarf_Arange arange,
595 		      Dwarf_Addr * start,
596 		      Dwarf_Unsigned * length,
597 		      Dwarf_Off * cu_die_offset, Dwarf_Error * error)
598 {
599     if (arange == NULL) {
600 	_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
601 	return (DW_DLV_ERROR);
602     }
603 
604     if (start != NULL)
605 	*start = arange->ar_address;
606     if (length != NULL)
607 	*length = arange->ar_length;
608     if (cu_die_offset != NULL) {
609 	Dwarf_Debug dbg = arange->ar_dbg;
610 	Dwarf_Off offset = arange->ar_info_offset;
611 
612 	if(!dbg->de_debug_info) {
613 	   int res = _dwarf_load_debug_info(dbg,error);
614            if(res != DW_DLV_OK) {
615                return res;
616            }
617         }
618 
619 	*cu_die_offset =
620 	    offset + _dwarf_length_of_cu_header(dbg, offset);
621     }
622     return (DW_DLV_OK);
623 }
624