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