1 /*
2 Copyright (c) 2020, David Anderson
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with
6 or without modification, are permitted provided that the
7 following conditions are met:
8
9 Redistributions of source code must retain the above
10 copyright notice, this list of conditions and the following
11 disclaimer.
12
13 Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials
16 provided with the distribution.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "config.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif /* HAVE_STDLIB_H */
39 #include "dwarf_incl.h"
40 #include "dwarf_alloc.h"
41 #include "dwarf_error.h"
42 #include "dwarf_util.h"
43 #include "dwarfstring.h"
44 #include "dwarf_loc.h"
45
46 #define SIZEOFT8 1
47 #define SIZEOFT16 2
48 #define SIZEOFT32 4
49 #define SIZEOFT64 8
50 #define TRUE 1
51 #define FALSE 0
52
53
54 /* Used in case of error reading the
55 loclists headers (not referring to Dwarf_Loc_Head_c
56 here), to clean up. */
57 static void
free_loclists_chain(Dwarf_Debug dbg,Dwarf_Chain head)58 free_loclists_chain(Dwarf_Debug dbg, Dwarf_Chain head)
59 {
60 Dwarf_Chain cur = head;
61 Dwarf_Chain next = 0;
62
63 if(!head) {
64 return;
65 }
66 for( ;cur; cur = next) {
67 next = cur->ch_next;
68 if (cur->ch_item) {
69 free(cur->ch_item);
70 cur->ch_item = 0;
71 dwarf_dealloc(dbg,cur,DW_DLA_CHAIN);
72 }
73 }
74 }
75
76 static int
counted_loc_descr(Dwarf_Debug dbg,Dwarf_Small * data,Dwarf_Small * enddata,Dwarf_Unsigned offset,Dwarf_Unsigned * loc_ops_overall_size,Dwarf_Unsigned * loc_ops_count_len,Dwarf_Unsigned * loc_ops_len,Dwarf_Small ** opsdata,Dwarf_Unsigned * opsoffset,Dwarf_Error * err)77 counted_loc_descr(Dwarf_Debug dbg,
78 Dwarf_Small *data,
79 Dwarf_Small *enddata,
80 Dwarf_Unsigned offset,
81 Dwarf_Unsigned *loc_ops_overall_size,
82 Dwarf_Unsigned *loc_ops_count_len,
83 Dwarf_Unsigned *loc_ops_len,
84 Dwarf_Small **opsdata,
85 Dwarf_Unsigned *opsoffset,
86 Dwarf_Error * err)
87 {
88 Dwarf_Unsigned ops_len = 0;
89 Dwarf_Unsigned leblen = 0;
90 DECODE_LEB128_UWORD_LEN_CK(data,ops_len,leblen,
91 dbg,err,enddata);
92 *loc_ops_count_len = leblen;
93 *loc_ops_overall_size = ops_len+leblen;
94 *loc_ops_len = ops_len;
95 *opsdata = data;
96 *opsoffset = offset +leblen;
97 return DW_DLV_OK;
98 }
99
100 static int
read_single_lle_entry(Dwarf_Debug dbg,Dwarf_Small * data,Dwarf_Unsigned dataoffset,Dwarf_Small * enddata,unsigned address_size,unsigned * bytes_count_out,unsigned * entry_kind,Dwarf_Unsigned * entry_operand1,Dwarf_Unsigned * entry_operand2,Dwarf_Unsigned * opsblocksize,Dwarf_Unsigned * opsoffset,Dwarf_Small ** ops,Dwarf_Error * err)101 read_single_lle_entry(Dwarf_Debug dbg,
102 Dwarf_Small *data,
103 Dwarf_Unsigned dataoffset,
104 Dwarf_Small *enddata,
105 unsigned address_size,
106 unsigned *bytes_count_out,
107 unsigned *entry_kind,
108 Dwarf_Unsigned *entry_operand1,
109 Dwarf_Unsigned *entry_operand2,
110 Dwarf_Unsigned *opsblocksize, /* Just the expr data */
111 Dwarf_Unsigned *opsoffset, /* Just the expr ops data */
112 Dwarf_Small **ops, /* pointer to expr ops ops */
113 Dwarf_Error* err)
114 {
115 Dwarf_Unsigned count = 0;
116 unsigned int leblen = 0;
117 unsigned int code = 0;
118 Dwarf_Unsigned val1 = 0;
119 Dwarf_Unsigned val2 = 0;
120 Dwarf_Unsigned loc_ops_overall_size = 0;
121 Dwarf_Unsigned loc_ops_count_len = 0;
122 Dwarf_Unsigned loc_ops_len = 0;
123 Dwarf_Small *lopsdata = 0;
124 Dwarf_Unsigned lopsoffset = 0;
125
126 /* Some of these have a Counted Location Description
127 in them. */
128 code = *data;
129 ++data;
130 ++count;
131 switch(code) {
132 case DW_LLE_end_of_list: break;
133 case DW_LLE_base_addressx:{
134 DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen,
135 dbg,err,enddata);
136 count += leblen;
137 }
138 break;
139 case DW_LLE_startx_endx:
140 case DW_LLE_startx_length:
141 case DW_LLE_offset_pair: {
142 int res = 0;
143
144 DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen,
145 dbg,err,enddata);
146 count += leblen;
147 DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen,
148 dbg,err,enddata);
149 count += leblen;
150 res = counted_loc_descr(dbg,data,enddata,
151 dataoffset,
152 &loc_ops_overall_size,
153 &loc_ops_count_len,
154 &loc_ops_len,
155 &lopsdata,
156 &lopsoffset,
157 err);
158 if (res != DW_DLV_OK) {
159 return res;
160 }
161 count += loc_ops_overall_size;
162 data += loc_ops_overall_size;
163
164 }
165 break;
166 case DW_LLE_default_location: {
167 int res = 0;
168
169 res = counted_loc_descr(dbg,data,enddata,
170 dataoffset,
171 &loc_ops_overall_size,
172 &loc_ops_count_len,
173 &loc_ops_len,
174 &lopsdata,
175 &lopsoffset,
176 err);
177 if (res != DW_DLV_OK) {
178 return res;
179 }
180 data += loc_ops_overall_size;
181 count += loc_ops_overall_size;
182 }
183 break;
184 case DW_LLE_base_address: {
185 READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
186 data,address_size,err,enddata);
187 data += address_size;
188 count += address_size;
189 }
190 break;
191 case DW_LLE_start_end: {
192 int res = 0;
193
194 READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
195 data,address_size,err,enddata);
196 data += address_size;
197 count += address_size;
198 READ_UNALIGNED_CK(dbg,val2, Dwarf_Unsigned,
199 data,address_size,err,enddata);
200 data += address_size;
201 count += address_size;
202 res = counted_loc_descr(dbg,data,enddata,
203 dataoffset,
204 &loc_ops_overall_size,
205 &loc_ops_count_len,
206 &loc_ops_len,
207 &lopsdata,
208 &lopsoffset,
209 err);
210 if (res != DW_DLV_OK) {
211 return res;
212 }
213 count += loc_ops_overall_size;
214 data += loc_ops_overall_size;
215 }
216 break;
217 case DW_LLE_start_length: {
218 int res = 0;
219
220 READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
221 data,address_size,err,enddata);
222 data += address_size;
223 count += address_size;
224 DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen,
225 dbg,err,enddata);
226 count += leblen;
227 res = counted_loc_descr(dbg,data,enddata,
228 dataoffset,
229 &loc_ops_overall_size,
230 &loc_ops_count_len,
231 &loc_ops_len,
232 &lopsdata,
233 &lopsoffset,
234 err);
235 if (res != DW_DLV_OK) {
236 return res;
237 }
238 count += loc_ops_overall_size;
239 data += loc_ops_overall_size;
240 }
241 break;
242 default: {
243 dwarfstring m;
244
245 dwarfstring_constructor(&m);
246 dwarfstring_append_printf_u(&m,
247 "DW_DLE_LOCLISTS_ERROR: "
248 "The loclists entry at .debug_loclists"
249 " offset 0x%x" ,dataoffset);
250 dwarfstring_append_printf_u(&m,
251 " has code 0x%x which is unknown",code);
252 _dwarf_error_string(dbg,err,DW_DLE_LOCLISTS_ERROR,
253 dwarfstring_string(&m));
254 dwarfstring_destructor(&m);
255 return DW_DLV_ERROR;
256 }
257 break;
258 }
259 *bytes_count_out = count;
260 *entry_kind = code;
261 *entry_operand1 = val1;
262 *entry_operand2 = val2;
263 *opsblocksize = loc_ops_len;
264 *opsoffset = lopsoffset;
265 *ops = lopsdata;
266 return DW_DLV_OK;
267 }
268
269 /* Reads the header. Determines the
270 various offsets, including offset
271 of the next header. Does no memory
272 allocations here. */
273 static int
internal_read_header(Dwarf_Debug dbg,Dwarf_Unsigned contextnum,Dwarf_Unsigned sectionlength,Dwarf_Small * data,Dwarf_Small * end_data,Dwarf_Unsigned offset,Dwarf_Loclists_Context buildhere,Dwarf_Unsigned * next_offset,Dwarf_Error * error)274 internal_read_header(Dwarf_Debug dbg,
275 Dwarf_Unsigned contextnum,
276 Dwarf_Unsigned sectionlength,
277 Dwarf_Small *data,
278 Dwarf_Small *end_data,
279 Dwarf_Unsigned offset,
280 Dwarf_Loclists_Context buildhere,
281 Dwarf_Unsigned *next_offset,
282 Dwarf_Error *error)
283 {
284 Dwarf_Small *startdata = data;
285 Dwarf_Unsigned arealen = 0;
286 int length_size = 0;
287 int exten_size = 0;
288 Dwarf_Unsigned version = 0;
289 unsigned address_size = 0;
290 unsigned segment_selector_size= 0;
291 Dwarf_Unsigned offset_entry_count = 0;
292 Dwarf_Unsigned localoff = 0;
293 Dwarf_Unsigned lists_len = 0;
294
295 READ_AREA_LENGTH_CK(dbg,arealen,Dwarf_Unsigned,
296 data,length_size,exten_size,
297 error,
298 sectionlength,end_data);
299 if (arealen > sectionlength) {
300 dwarfstring m;
301 dwarfstring_constructor(&m);
302 dwarfstring_append_printf_u(&m,
303 "DW_DLE_SECTION_SIZE_ERROR: A .debug_loclists "
304 "area size of 0x%x ",arealen);
305 dwarfstring_append_printf_u(&m,
306 "at offset 0x%x ",offset);
307 dwarfstring_append_printf_u(&m,
308 "is larger than the entire section size of "
309 "0x%x. Corrupt DWARF.",sectionlength);
310 _dwarf_error_string(dbg,error,DW_DLE_SECTION_SIZE_ERROR,
311 dwarfstring_string(&m));
312 dwarfstring_destructor(&m);
313 return DW_DLV_ERROR;
314 }
315
316 buildhere->lc_length = arealen +length_size+exten_size;
317 buildhere->lc_dbg = dbg;
318 buildhere->lc_index = contextnum;
319 buildhere->lc_header_offset = offset;
320 buildhere->lc_offset_size = length_size;
321 buildhere->lc_extension_size = exten_size;
322 READ_UNALIGNED_CK(dbg,version,Dwarf_Unsigned,data,
323 SIZEOFT16,error,end_data);
324 if (version != DW_CU_VERSION5) {
325 dwarfstring m;
326 dwarfstring_constructor(&m);
327 dwarfstring_append_printf_u(&m,
328 "DW_DLE_VERSION_STAMP_ERROR: The version should be 5 "
329 "but we find %u instead.",version);
330 _dwarf_error_string(dbg,error,DW_DLE_VERSION_STAMP_ERROR,
331 dwarfstring_string(&m));
332 dwarfstring_destructor(&m);
333 return DW_DLV_ERROR;
334 }
335 buildhere->lc_version = version;
336 data += SIZEOFT16;
337
338 READ_UNALIGNED_CK(dbg,address_size,unsigned,data,
339 SIZEOFT8,error,end_data);
340 if (version != DW_CU_VERSION5) {
341 dwarfstring m;
342 dwarfstring_constructor(&m);
343 dwarfstring_append_printf_u(&m,
344 "DW_DLE_VERSION_STAMP_ERROR: The version should be 5 "
345 "but we find %u instead.",version);
346 _dwarf_error_string(dbg,error,DW_DLE_VERSION_STAMP_ERROR,
347 dwarfstring_string(&m));
348 dwarfstring_destructor(&m);
349 return DW_DLV_ERROR;
350 }
351 if (address_size != 4 && address_size != 8 &&
352 address_size != 2) {
353 dwarfstring m;
354 dwarfstring_constructor(&m);
355 dwarfstring_append_printf_u(&m,
356 " DW_DLE_ADDRESS_SIZE_ERROR: The address size "
357 "of %u is not supported.",address_size);
358 _dwarf_error_string(dbg,error,DW_DLE_ADDRESS_SIZE_ERROR,
359 dwarfstring_string(&m));
360 dwarfstring_destructor(&m);
361 return DW_DLV_ERROR;
362 }
363 buildhere->lc_address_size = address_size;
364 data++;
365
366 READ_UNALIGNED_CK(dbg,segment_selector_size,unsigned,data,
367 SIZEOFT8,error,end_data);
368 buildhere->lc_segment_selector_size = segment_selector_size;
369 data++;
370
371 READ_UNALIGNED_CK(dbg,offset_entry_count,Dwarf_Unsigned,data,
372 SIZEOFT32,error,end_data);
373 buildhere->lc_offset_entry_count = offset_entry_count;
374 data += SIZEOFT32;
375 if (offset_entry_count ){
376 buildhere->lc_offsets_array = data;
377 }
378 localoff = data - startdata;
379 lists_len = address_size *offset_entry_count;
380
381 data += lists_len;
382
383 buildhere->lc_offsets_off_in_sect = offset+localoff;
384 buildhere->lc_first_loclist_offset = offset+localoff+
385 lists_len;
386 buildhere->lc_loclists_header = startdata;
387 buildhere->lc_endaddr = startdata +buildhere->lc_length;
388 buildhere->lc_past_last_loclist_offset =
389 buildhere->lc_header_offset +buildhere->lc_length;
390 *next_offset = buildhere->lc_past_last_loclist_offset;
391 return DW_DLV_OK;
392 }
393
394
395 /* We return a pointer to an array of contexts
396 (not context pointers through *cxt if
397 we succeed and are returning DW_DLV_OK.
398 We never return DW_DLV_NO_ENTRY here. */
399 static int
internal_load_loclists_contexts(Dwarf_Debug dbg,Dwarf_Loclists_Context ** cxt,Dwarf_Unsigned * count,Dwarf_Error * error)400 internal_load_loclists_contexts(Dwarf_Debug dbg,
401 Dwarf_Loclists_Context **cxt,
402 Dwarf_Unsigned *count,
403 Dwarf_Error *error)
404 {
405 Dwarf_Unsigned offset = 0;
406 Dwarf_Unsigned nextoffset = 0;
407 Dwarf_Small * data = dbg->de_debug_loclists.dss_data;
408 Dwarf_Unsigned section_size = dbg->de_debug_loclists.dss_size;
409 Dwarf_Small * startdata = data;
410 Dwarf_Small * end_data = data +section_size;
411 Dwarf_Chain curr_chain = 0;
412 Dwarf_Chain prev_chain = 0;
413 Dwarf_Chain head_chain = 0;
414 int res = 0;
415 Dwarf_Unsigned chainlength = 0;
416 Dwarf_Loclists_Context *fullarray = 0;
417 Dwarf_Unsigned i = 0;
418
419 for( ; data < end_data ; ) {
420 Dwarf_Loclists_Context newcontext = 0;
421
422 /* sizeof the context struct, not sizeof a pointer */
423 newcontext = malloc(sizeof(*newcontext));
424 if (!newcontext) {
425 free_loclists_chain(dbg,head_chain);
426 _dwarf_error_string(dbg,error,
427 DW_DLE_ALLOC_FAIL,
428 "DW_DLE_ALLOC_FAIL: Allocation of "
429 "Loclists_Context failed");
430 return DW_DLV_ERROR;
431 }
432 memset(newcontext,0,sizeof(*newcontext));
433 res = internal_read_header(dbg,chainlength,
434 section_size,
435 data,end_data,offset,
436 newcontext,&nextoffset,error);
437 if (res == DW_DLV_ERROR) {
438 free(newcontext);
439 free_loclists_chain(dbg,head_chain);
440 }
441 curr_chain = (Dwarf_Chain)
442 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
443 if (curr_chain == NULL) {
444 free_loclists_chain(dbg,head_chain);
445 _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
446 "DW_DLE_ALLOC_FAIL: allocating Loclists_Context"
447 " chain entry");
448 return DW_DLV_ERROR;
449 }
450 curr_chain->ch_item = newcontext;
451 ++chainlength;
452 if (head_chain == NULL) {
453 head_chain = prev_chain = curr_chain;
454 } else {
455 prev_chain->ch_next = curr_chain;
456 prev_chain = curr_chain;
457 }
458 data = startdata+nextoffset;
459 offset = nextoffset;
460 }
461 fullarray= (Dwarf_Loclists_Context *)malloc(
462 chainlength *sizeof(Dwarf_Loclists_Context /*pointer*/));
463 if (!fullarray) {
464 free_loclists_chain(dbg,head_chain);
465 _dwarf_error_string(dbg,error,
466 DW_DLE_ALLOC_FAIL,"Allocation of "
467 "Loclists_Context pointer array failed");
468 return DW_DLV_ERROR;
469 }
470 curr_chain = head_chain;
471 for( i = 0; i < chainlength; ++i) {
472 fullarray[i] = (Dwarf_Loclists_Context)curr_chain->ch_item;
473 curr_chain->ch_item = 0;
474 prev_chain = curr_chain;
475 curr_chain = curr_chain->ch_next;
476 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
477 }
478 /* ASSERT: the chain is entirely dealloc'd
479 and the array of pointers points to
480 individually malloc'd Dwarf_Loclists_Context_s */
481 *cxt = fullarray;
482 *count = chainlength;
483 return DW_DLV_OK;
484 }
485
486
487
488 /* Used by dwarfdump to print raw loclists data.
489 Loads all the .debug_loclists[.dwo] headers and
490 returns DW_DLV_NO_ENTRY if the section
491 is missing or empty.
492 Intended to be done quite early and
493 done exactly once.
494 Harmless to do more than once.
495 With DW_DLV_OK it returns the number of
496 loclists headers in the section through
497 loclists_count. */
dwarf_load_loclists(Dwarf_Debug dbg,Dwarf_Unsigned * loclists_count,Dwarf_Error * error)498 int dwarf_load_loclists(
499 Dwarf_Debug dbg,
500 Dwarf_Unsigned *loclists_count,
501 Dwarf_Error *error)
502 {
503 int res = DW_DLV_ERROR;
504 Dwarf_Loclists_Context *cxt = 0;
505 Dwarf_Unsigned count = 0;
506
507 if (dbg->de_loclists_context) {
508 if (loclists_count) {
509 *loclists_count = dbg->de_loclists_context_count;
510 }
511 }
512 if (!dbg->de_debug_loclists.dss_size) {
513 /* nothing there. */
514 return DW_DLV_NO_ENTRY;
515 }
516 if (!dbg->de_debug_loclists.dss_data) {
517 res = _dwarf_load_section(dbg, &dbg->de_debug_loclists,
518 error);
519 if (res != DW_DLV_OK) {
520 return res;
521 }
522 }
523 res = internal_load_loclists_contexts(dbg,&cxt,&count,error);
524 if (res == DW_DLV_ERROR) {
525 return res;
526 }
527 dbg->de_loclists_context = cxt;
528 dbg->de_loclists_context_count = count;
529 if (loclists_count) {
530 *loclists_count = count;
531 }
532 return DW_DLV_OK;
533 }
534
535 /* Frees the memory in use in all loclists contexts.
536 Done by dwarf_finish() */
537 void
_dwarf_dealloc_loclists_context(Dwarf_Debug dbg)538 _dwarf_dealloc_loclists_context(Dwarf_Debug dbg)
539 {
540 Dwarf_Unsigned i = 0;
541 Dwarf_Loclists_Context * loccon = 0;
542
543 if (!dbg->de_loclists_context) {
544 return;
545 }
546 loccon = dbg->de_loclists_context;
547 for( ; i < dbg->de_loclists_context_count; ++i,++loccon) {
548 Dwarf_Loclists_Context con = *loccon;
549 con->lc_offsets_array = 0;
550 con->lc_offset_entry_count = 0;
551 free(con);
552 }
553 free(dbg->de_loclists_context);
554 dbg->de_loclists_context = 0;
555 dbg->de_loclists_context_count = 0;
556 }
557
558 /* Used by dwarfdump to print raw loclists data. */
559 int
dwarf_get_loclist_offset_index_value(Dwarf_Debug dbg,Dwarf_Unsigned context_index,Dwarf_Unsigned offsetentry_index,Dwarf_Unsigned * offset_value_out,Dwarf_Unsigned * global_offset_value_out,Dwarf_Error * error)560 dwarf_get_loclist_offset_index_value(
561 Dwarf_Debug dbg,
562 Dwarf_Unsigned context_index,
563 Dwarf_Unsigned offsetentry_index,
564 Dwarf_Unsigned * offset_value_out,
565 Dwarf_Unsigned * global_offset_value_out,
566 Dwarf_Error *error)
567 {
568 Dwarf_Loclists_Context con = 0;
569 unsigned offset_len = 0;
570 Dwarf_Small *offsetptr = 0;
571 Dwarf_Unsigned targetoffset = 0;
572
573 if (!dbg->de_loclists_context_count) {
574 return DW_DLV_NO_ENTRY;
575 }
576 if (context_index >= dbg->de_loclists_context_count) {
577 return DW_DLV_NO_ENTRY;
578 }
579 con = dbg->de_loclists_context[context_index];
580
581 if (offsetentry_index >= con->lc_offset_entry_count) {
582 return DW_DLV_NO_ENTRY;
583 }
584 offset_len = con->lc_offset_size;
585 offsetptr = con->lc_offsets_array +
586 (offsetentry_index*offset_len);
587 READ_UNALIGNED_CK(dbg,targetoffset,Dwarf_Unsigned,
588 offsetptr,
589 offset_len,error,con->lc_endaddr);
590 if (offset_value_out) {
591 *offset_value_out = targetoffset;
592 }
593 if (global_offset_value_out) {
594 *global_offset_value_out = targetoffset +
595 con->lc_offsets_off_in_sect;
596 }
597 return DW_DLV_OK;
598 }
599
600 /* Used by dwarfdump to print basic data from the
601 data generated to look at a specific loclist
602 as returned by dwarf_loclists_index_get_rle_head()
603 or dwarf_loclists_offset_get_rle_head. */
dwarf_get_loclist_head_basics(Dwarf_Loc_Head_c head,Dwarf_Small * lkind,Dwarf_Unsigned * lle_count,Dwarf_Unsigned * lle_version,Dwarf_Unsigned * loclists_index_returned,Dwarf_Unsigned * bytes_total_in_lle,Dwarf_Half * offset_size,Dwarf_Half * address_size,Dwarf_Half * segment_selector_size,Dwarf_Unsigned * overall_offset_of_this_context,Dwarf_Unsigned * total_length_of_this_context,Dwarf_Unsigned * offset_table_offset,Dwarf_Unsigned * offset_table_entrycount,Dwarf_Bool * loclists_base_present,Dwarf_Unsigned * loclists_base,Dwarf_Bool * loclists_base_address_present,Dwarf_Unsigned * loclists_base_address,Dwarf_Bool * loclists_debug_addr_base_present,Dwarf_Unsigned * loclists_debug_addr_base,Dwarf_Unsigned * loclists_offset_lle_set,UNUSEDARG Dwarf_Error * error)604 int dwarf_get_loclist_head_basics(
605 Dwarf_Loc_Head_c head,
606 Dwarf_Small * lkind,
607 Dwarf_Unsigned * lle_count,
608 Dwarf_Unsigned * lle_version,
609 Dwarf_Unsigned * loclists_index_returned,
610 Dwarf_Unsigned * bytes_total_in_lle,
611 Dwarf_Half * offset_size,
612 Dwarf_Half * address_size,
613 Dwarf_Half * segment_selector_size,
614 Dwarf_Unsigned * overall_offset_of_this_context,
615 Dwarf_Unsigned * total_length_of_this_context,
616 Dwarf_Unsigned * offset_table_offset,
617 Dwarf_Unsigned * offset_table_entrycount,
618 Dwarf_Bool * loclists_base_present,
619 Dwarf_Unsigned * loclists_base,
620 Dwarf_Bool * loclists_base_address_present,
621 Dwarf_Unsigned * loclists_base_address,
622 Dwarf_Bool * loclists_debug_addr_base_present,
623 Dwarf_Unsigned * loclists_debug_addr_base,
624 Dwarf_Unsigned * loclists_offset_lle_set,
625 UNUSEDARG Dwarf_Error *error)
626 {
627 Dwarf_Loclists_Context loccontext = 0;
628 *lkind = head->ll_kind;
629 *lle_count = head->ll_locdesc_count;
630 *lle_version = head->ll_cuversion;
631 *loclists_index_returned = head->ll_index;
632 *bytes_total_in_lle = head->ll_bytes_total;
633 *offset_size = head->ll_offset_size;
634 *address_size = head->ll_address_size;
635 *segment_selector_size = head->ll_segment_selector_size;
636 /* If a dwarf_expression, no ll_loccontext */
637 loccontext = head->ll_localcontext;
638 if (loccontext) {
639 *overall_offset_of_this_context =
640 loccontext->lc_header_offset;
641 *total_length_of_this_context = loccontext->lc_length;
642 *offset_table_offset = loccontext->lc_offsets_off_in_sect;
643 *offset_table_entrycount = loccontext->lc_offset_entry_count;
644 }
645 *loclists_base_present = head->ll_at_loclists_base_present;
646 *loclists_base= head->ll_at_loclists_base;
647
648 *loclists_base_address_present = head->ll_cu_base_address_present;
649 *loclists_base_address= head->ll_cu_base_address;
650
651 *loclists_debug_addr_base_present = head->ll_cu_addr_base_present;
652 *loclists_debug_addr_base = head->ll_cu_addr_base;
653 *loclists_offset_lle_set = head->ll_llearea_offset;
654 return DW_DLV_OK;
655 }
656
657 /* Used by dwarfdump to print raw loclists data.
658 Enables printing of details about the Range List Table
659 Headers, one header per call. Index starting at 0.
660 Returns DW_DLV_NO_ENTRY if index is too high for the table.
661 A .debug_loclists section may contain any number
662 of Range List Table Headers with their details. */
dwarf_get_loclist_context_basics(Dwarf_Debug dbg,Dwarf_Unsigned context_index,Dwarf_Unsigned * header_offset,Dwarf_Small * offset_size,Dwarf_Small * extension_size,unsigned * version,Dwarf_Small * address_size,Dwarf_Small * segment_selector_size,Dwarf_Unsigned * offset_entry_count,Dwarf_Unsigned * offset_of_offset_array,Dwarf_Unsigned * offset_of_first_loclistentry,Dwarf_Unsigned * offset_past_last_loclistentry,UNUSEDARG Dwarf_Error * error)663 int dwarf_get_loclist_context_basics(
664 Dwarf_Debug dbg,
665 Dwarf_Unsigned context_index,
666 Dwarf_Unsigned * header_offset,
667 Dwarf_Small * offset_size,
668 Dwarf_Small * extension_size,
669 unsigned * version, /* 5 */
670 Dwarf_Small * address_size,
671 Dwarf_Small * segment_selector_size,
672 Dwarf_Unsigned * offset_entry_count,
673 Dwarf_Unsigned * offset_of_offset_array,
674 Dwarf_Unsigned * offset_of_first_loclistentry,
675 Dwarf_Unsigned * offset_past_last_loclistentry,
676 UNUSEDARG Dwarf_Error *error)
677 {
678 Dwarf_Loclists_Context con = 0;
679 if (!dbg->de_loclists_context_count) {
680 return DW_DLV_NO_ENTRY;
681 }
682 if (context_index >= dbg->de_loclists_context_count) {
683 return DW_DLV_NO_ENTRY;
684 }
685 con = dbg->de_loclists_context[context_index];
686
687 if (header_offset) {
688 *header_offset = con->lc_header_offset;
689 }
690 if (offset_size) {
691 *offset_size = con->lc_offset_size;
692 }
693 if (offset_size) {
694 *extension_size = con->lc_extension_size;
695 }
696 if (version) {
697 *version = con->lc_version;
698 }
699 if (address_size) {
700 *address_size = con->lc_address_size;
701 }
702 if (segment_selector_size) {
703 *segment_selector_size = con->lc_segment_selector_size;
704 }
705 if (offset_entry_count) {
706 *offset_entry_count = con->lc_offset_entry_count;
707 }
708 if (offset_of_offset_array) {
709 *offset_of_offset_array = con->lc_offsets_off_in_sect;
710 }
711 if (offset_of_first_loclistentry) {
712 *offset_of_first_loclistentry = con->lc_first_loclist_offset;
713 }
714 if (offset_past_last_loclistentry) {
715 *offset_past_last_loclistentry =
716 con->lc_past_last_loclist_offset;
717 }
718 return DW_DLV_OK;
719 }
720
721 /* Used by dwarfdump to print raw loclists data.
722 entry offset is offset_of_first_loclistentry.
723 Stop when the returned *next_entry_offset
724 is == offset_past_last_loclistentry (from
725 dwarf_get_loclist_context_plus).
726 This only makes sense within those loclists
727 This retrieves raw detail from the section,
728 no base values or anything are added.
729 So this returns raw individual entries
730 for a single loclist header, meaning a
731 a single Dwarf_Loclists_Context. */
dwarf_get_loclist_lle(Dwarf_Debug dbg,Dwarf_Unsigned contextnumber,Dwarf_Unsigned entry_offset,Dwarf_Unsigned endoffset,unsigned * entrylen,unsigned * entry_kind,Dwarf_Unsigned * entry_operand1,Dwarf_Unsigned * entry_operand2,Dwarf_Unsigned * expr_ops_blocksize,Dwarf_Unsigned * expr_ops_offset,Dwarf_Small ** expr_opsdata,Dwarf_Error * err)732 int dwarf_get_loclist_lle(
733 Dwarf_Debug dbg,
734 Dwarf_Unsigned contextnumber,
735 Dwarf_Unsigned entry_offset,
736 Dwarf_Unsigned endoffset,
737 unsigned *entrylen,
738 unsigned *entry_kind,
739 Dwarf_Unsigned *entry_operand1,
740 Dwarf_Unsigned *entry_operand2,
741 Dwarf_Unsigned *expr_ops_blocksize,
742 Dwarf_Unsigned *expr_ops_offset,
743 Dwarf_Small **expr_opsdata,
744 Dwarf_Error *err)
745 {
746 Dwarf_Loclists_Context con = 0;
747 Dwarf_Small *data = 0;
748 Dwarf_Small *enddata = 0;
749 int res = 0;
750 unsigned address_size = 0;
751
752
753 if (!dbg->de_loclists_context_count) {
754 return DW_DLV_NO_ENTRY;
755 }
756 data = dbg->de_debug_loclists.dss_data +
757 entry_offset;
758 enddata = dbg->de_debug_loclists.dss_data +
759 endoffset;
760 if (contextnumber >= dbg->de_loclists_context_count) {
761 return DW_DLV_NO_ENTRY;
762 }
763 con = dbg->de_loclists_context[contextnumber];
764 address_size = con->lc_address_size;
765 res = read_single_lle_entry(dbg,
766 data,entry_offset,enddata,
767 address_size, entrylen,
768 entry_kind, entry_operand1, entry_operand2,
769 expr_ops_blocksize,
770 expr_ops_offset,
771 expr_opsdata,
772 err);
773 return res;
774 }
775
776
777 static int
_dwarf_which_loclists_context(Dwarf_Debug dbg,Dwarf_CU_Context ctx,Dwarf_Unsigned loclist_offset,Dwarf_Unsigned * index,Dwarf_Error * error)778 _dwarf_which_loclists_context(Dwarf_Debug dbg,
779 Dwarf_CU_Context ctx,
780 Dwarf_Unsigned loclist_offset,
781 Dwarf_Unsigned *index,
782 Dwarf_Error *error)
783 {
784 Dwarf_Unsigned count = 0;
785 Dwarf_Loclists_Context *array = 0;
786 Dwarf_Unsigned i = 0;
787 Dwarf_Loclists_Context rcx = 0;
788 Dwarf_Unsigned rcxoff = 0;
789 Dwarf_Unsigned rcxend = 0;
790
791 array = dbg->de_loclists_context;
792 count = dbg->de_loclists_context_count;
793 if (!array) {
794 return DW_DLV_NO_ENTRY;
795 }
796 rcx = array[i];
797 rcxoff = rcx->lc_header_offset;
798 rcxend = rcxoff + rcx->lc_length;
799 if (!ctx->cc_loclists_base_present) {
800 /* We look at the location of each loclist context
801 to find one with the offset the DIE gave us. */
802 for ( i = 0 ; i < count; ++i) {
803 rcx = array[i];
804 rcxoff = rcx->lc_header_offset;
805 rcxend = rcxoff +
806 rcx->lc_length;
807 rcxend = rcxoff +
808 rcx->lc_length;
809 if (loclist_offset < rcxoff){
810 continue;
811 }
812 if (loclist_offset < rcxend ){
813 *index = i;
814 return DW_DLV_OK;
815 }
816 }
817 {
818 dwarfstring m;
819
820 dwarfstring_constructor(&m);
821 dwarfstring_append_printf_u(&m,
822 "DW_DLE_LOCLISTS_ERROR: loclist ran off end "
823 " finding target offset of"
824 " 0x%" DW_PR_XZEROS DW_PR_DUx ,loclist_offset);
825 dwarfstring_append(&m,
826 " Not found anywhere in .debug_loclists "
827 "data. Corrupted data?");
828 _dwarf_error_string(dbg,error,
829 DW_DLE_LOCLISTS_ERROR,
830 dwarfstring_string(&m));
831 dwarfstring_destructor(&m);
832 return DW_DLV_ERROR;
833 }
834 } else {
835 /* We have a DW_AT_loclists_base (lc_loclists_base),
836 let's use it. */
837 Dwarf_Unsigned lookfor = 0;;
838
839 lookfor = ctx->cc_loclists_base;
840 for ( i = 0 ; i < count; ++i) {
841 dwarfstring m;
842
843 rcx = array[i];
844 if (rcx->lc_offsets_off_in_sect == lookfor){
845 *index = i;
846 return DW_DLV_OK;
847 }
848 if (rcx->lc_offsets_off_in_sect < lookfor){
849 continue;
850 }
851
852 dwarfstring_constructor(&m);
853 dwarfstring_append_printf_u(&m,
854 "DW_DLE_LOCLISTS_ERROR: loclists base of "
855 " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor);
856 dwarfstring_append_printf_u(&m,
857 " was not found though we are now at base "
858 " 0x%" DW_PR_XZEROS DW_PR_DUx ,
859 rcx->lc_offsets_off_in_sect);
860 _dwarf_error_string(dbg,error,
861 DW_DLE_LOCLISTS_ERROR,
862 dwarfstring_string(&m));
863 dwarfstring_destructor(&m);
864 return DW_DLV_ERROR;
865 }
866 {
867 dwarfstring m;
868
869 dwarfstring_constructor(&m);
870 dwarfstring_append_printf_u(&m,
871 "DW_DLE_LOCLISTS_ERROR: loclist base of "
872 " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor);
873 dwarfstring_append(&m,
874 " was not found anywhere in .debug_loclists "
875 "data. Corrupted data?");
876 _dwarf_error_string(dbg,error,
877 DW_DLE_LOCLISTS_ERROR,
878 dwarfstring_string(&m));
879 dwarfstring_destructor(&m);
880 return DW_DLV_ERROR;
881 }
882 }
883 return DW_DLV_ERROR;
884 }
885 #if 0
886 int
887 dwarf_dealloc_loclists_head(Dwarf_Loc_Head_c h)
888 {
889 Dwarf_Debug dbg = h->ll_dbg;
890
891 dwarf_dealloc(dbg,h,DW_DLA_LOCLISTS_HEAD);
892 return DW_DLV_OK;
893 }
894 #endif
895
896 /* Caller will eventually free as appropriate. */
897 static int
alloc_rle_and_append_to_list(Dwarf_Debug dbg,Dwarf_Loc_Head_c rctx,Dwarf_Locdesc_c * e_out,Dwarf_Error * error)898 alloc_rle_and_append_to_list(Dwarf_Debug dbg,
899 Dwarf_Loc_Head_c rctx,
900 Dwarf_Locdesc_c *e_out,
901 Dwarf_Error *error)
902 {
903 Dwarf_Locdesc_c e = 0;
904
905 e = malloc(sizeof(struct Dwarf_Locdesc_c_s));
906 if (!e) {
907 _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
908 "DW_DLE_ALLOC_FAIL: Out of memory in "
909 "building list of loclists entries on a DIE.");
910 return DW_DLV_ERROR;
911 }
912 memset(e,0,sizeof(struct Dwarf_Locdesc_c_s));
913 if (rctx->ll_first) {
914 rctx->ll_last->ld_next = e;
915 rctx->ll_last = e;
916 } else {
917 rctx->ll_first = e;
918 rctx->ll_last = e;
919 }
920 rctx->ll_locdesc_count++;
921 *e_out = e;
922 return DW_DLV_OK;
923 }
924
925 /* Read the group of loclists entries, and
926 finally build an array of Dwarf_Locdesc_c
927 records. Attach to rctx here.
928 Since on error the caller will destruct the rctx
929 and we ensure to attach allocations there
930 the caller will destruct the allocations here
931 in case we return DW_DLV_ERROR*/
932 static int
build_array_of_lle(Dwarf_Debug dbg,Dwarf_Loc_Head_c rctx,Dwarf_Error * error)933 build_array_of_lle(Dwarf_Debug dbg,
934 Dwarf_Loc_Head_c rctx,
935 Dwarf_Error *error)
936 {
937 int res = 0;
938 Dwarf_Small *data = rctx->ll_llepointer;
939 Dwarf_Unsigned dataoffset = rctx->ll_llearea_offset;
940 Dwarf_Small *enddata = rctx->ll_end_data_area;
941 unsigned int offset_size = rctx->ll_offset_size;
942 unsigned int address_size = rctx->ll_address_size;
943 Dwarf_Unsigned bytescounttotal= 0;
944 Dwarf_Unsigned latestbaseaddr = 0;
945 unsigned int foundbaseaddr = FALSE;
946 int done = FALSE;
947 Dwarf_Unsigned locdesc_index = 0;
948 Dwarf_Unsigned i = 0;
949
950 if (rctx->ll_cu_base_address_present) {
951 /* The CU DIE had DW_AT_low_pc
952 and it is a base address. */
953 latestbaseaddr = rctx->ll_cu_base_address;
954 foundbaseaddr = TRUE;
955 }
956 for( ; !done ;++locdesc_index ) {
957 unsigned entrylen = 0;
958 unsigned code = 0;
959 Dwarf_Unsigned val1 = 0;
960 Dwarf_Unsigned val2 = 0;
961 Dwarf_Addr addr1= 0;
962 Dwarf_Addr addr2 = 0;
963 Dwarf_Locdesc_c e = 0;
964 Dwarf_Unsigned opsblocksize = 0;
965 Dwarf_Unsigned opsoffset = 0;
966 Dwarf_Small *ops = 0;
967 Dwarf_Block_c eops;
968
969 memset(&eops,0,sizeof(eops));
970 res = read_single_lle_entry(dbg,
971 data,dataoffset, enddata,
972 address_size,&entrylen,
973 &code,&val1, &val2,
974 &opsblocksize,&opsoffset,&ops,
975 error);
976 if (res != DW_DLV_OK) {
977 return res;
978 }
979 res = alloc_rle_and_append_to_list(dbg,rctx,&e,error);
980 if (res != DW_DLV_OK) {
981 return res;
982 }
983 eops.bl_len =opsblocksize;
984 eops.bl_data = ops;
985 eops.bl_kind = rctx->ll_kind;
986 eops.bl_section_offset = opsoffset;
987 eops.bl_locdesc_offset = dataoffset;
988 e->ld_kind = rctx->ll_kind;
989 e->ld_lle_value = code,
990 e->ld_entrylen = entrylen;
991 e->ld_rawlow = val1;
992 e->ld_rawhigh = val2;
993 e->ld_opsblock = eops;
994 bytescounttotal += entrylen;
995 data += entrylen;
996 if (code == DW_LLE_end_of_list) {
997 done = TRUE;
998 break;
999 }
1000 /* Here we create the cooked values from
1001 the raw values and other data. */
1002 switch(code) {
1003 case DW_LLE_base_addressx:
1004 foundbaseaddr = TRUE;
1005 res = _dwarf_extract_address_from_debug_addr(
1006 dbg,rctx->ll_context,val1,
1007 &addr1,error);
1008 if (res != DW_DLV_OK) {
1009 return res;
1010 }
1011 e->ld_lopc = addr1;
1012 latestbaseaddr = addr1;
1013 break;
1014 case DW_LLE_startx_endx:
1015 res = _dwarf_extract_address_from_debug_addr(
1016 dbg,rctx->ll_context,val1,
1017 &addr1,error);
1018 if (res != DW_DLV_OK) {
1019 return res;
1020 }
1021 res = _dwarf_extract_address_from_debug_addr(
1022 dbg,rctx->ll_context,val2,
1023 &addr2,error);
1024 if (res != DW_DLV_OK) {
1025 return res;
1026 }
1027 e->ld_lopc = addr1;
1028 e->ld_highpc = addr2;
1029 break;
1030 case DW_LLE_startx_length:
1031 res = _dwarf_extract_address_from_debug_addr(
1032 dbg,rctx->ll_context,val1,
1033 &addr1,error);
1034 if (res != DW_DLV_OK) {
1035 return res;
1036 }
1037 e->ld_lopc = addr1;
1038 e->ld_highpc = val2+addr1;
1039 break;
1040 case DW_LLE_offset_pair:
1041 if(foundbaseaddr) {
1042 e->ld_lopc = val1+latestbaseaddr;
1043 e->ld_highpc = val2+latestbaseaddr;
1044 } else {
1045 e->ld_lopc = val1+rctx->ll_cu_base_address;
1046 e->ld_highpc = val2+rctx->ll_cu_base_address;
1047 }
1048 break;
1049 case DW_LLE_base_address:
1050 foundbaseaddr = TRUE;
1051 latestbaseaddr = val1;
1052 e->ld_lopc = val1;
1053 break;
1054 case DW_LLE_start_end:
1055 e->ld_lopc = val1;
1056 e->ld_highpc = val2;
1057 break;
1058 case DW_LLE_start_length:
1059 e->ld_lopc = val1;
1060 e->ld_highpc = val2+val1;
1061 break;
1062 default: {
1063 dwarfstring m;
1064
1065 dwarfstring_constructor(&m);
1066 dwarfstring_append_printf_u(&m,
1067 " DW_DLE_LOCLISTS_ERROR: "
1068 " The .debug_loclists "
1069 " loclist code 0x%x is unknown, "
1070 " DWARF5 is corrupted.",code);
1071 _dwarf_error_string(dbg, error,
1072 DW_DLE_LOCLISTS_ERROR,
1073 dwarfstring_string(&m));
1074 dwarfstring_destructor(&m);
1075 return DW_DLV_ERROR;
1076 }
1077 }
1078 }
1079 if (rctx->ll_locdesc_count > 0) {
1080 Dwarf_Locdesc_c array = 0;
1081 Dwarf_Locdesc_c cur = 0;
1082 Dwarf_Locdesc_c prev = 0;
1083
1084 /* array of structs. */
1085 array = (Dwarf_Locdesc_c)_dwarf_get_alloc(dbg,
1086 DW_DLA_LOCDESC_C, rctx->ll_locdesc_count);
1087 if (!array) {
1088 _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
1089 "DW_DLE_ALLOC_FAIL: Out of memory in "
1090 "copying list of locdescs into array ");
1091 return DW_DLV_ERROR;
1092 }
1093 rctx->ll_locdesc = array;
1094 cur = rctx->ll_first;
1095 for (i = 0 ; i < rctx->ll_locdesc_count; ++i) {
1096 prev = cur;
1097 array[i] = *cur;
1098 cur = cur->ld_next;
1099 free(prev);
1100 }
1101 rctx->ll_first = 0;
1102 rctx->ll_last = 0;
1103 }
1104 for (i = 0; i < rctx->ll_locdesc_count; ++i) {
1105 Dwarf_Locdesc_c ldc = rctx->ll_locdesc + i;
1106
1107 res = _dwarf_fill_in_locdesc_op_c(dbg,
1108 i,
1109 rctx,
1110 &ldc->ld_opsblock,
1111 address_size, offset_size,
1112 rctx->ll_cuversion,
1113 ldc->ld_lopc, ldc->ld_highpc,
1114 ldc->ld_lle_value,
1115 error);
1116 if (res != DW_DLV_OK) {
1117 return res;
1118 }
1119 }
1120 rctx->ll_bytes_total = bytescounttotal;
1121 return DW_DLV_OK;
1122 }
1123
1124 /* Build a head with all the relevent Entries
1125 attached, all the locdescs and for each such,
1126 all its expression operators.
1127 */
1128 int
_dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg,Dwarf_Attribute attr,Dwarf_Loc_Head_c llhead,Dwarf_Error * error)1129 _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg,
1130 Dwarf_Attribute attr,
1131 Dwarf_Loc_Head_c llhead,
1132 Dwarf_Error *error)
1133 {
1134 int res = 0;
1135 Dwarf_Unsigned loclists_contextnum = 0;
1136 Dwarf_Small *table_base = 0;
1137 Dwarf_Small *table_entry = 0;
1138 Dwarf_Small *enddata = 0;
1139 Dwarf_Loclists_Context *array = 0;
1140 Dwarf_Loclists_Context rctx = 0;
1141 Dwarf_Unsigned entrycount = 0;
1142 unsigned offsetsize = 0;
1143 Dwarf_Unsigned lle_global_offset = 0;
1144 Dwarf_CU_Context ctx = 0;
1145 Dwarf_Unsigned offset_in_loclists = 0;
1146 Dwarf_Bool is_loclistx = FALSE;
1147 int theform = llhead->ll_attrform;
1148 Dwarf_Unsigned attr_val = 0;
1149
1150 ctx = attr->ar_cu_context;
1151 array = dbg->de_loclists_context;
1152 if ( theform == DW_FORM_sec_offset) {
1153 /* DW_FORM_sec_offset is not formudata , often
1154 seen in in DW5 DW_AT_location etc */
1155 res = dwarf_global_formref(attr, &attr_val,error);
1156 if (res != DW_DLV_OK) {
1157 return res;
1158 }
1159 offset_in_loclists = attr_val;
1160 } else {
1161 if (theform == DW_FORM_loclistx) {
1162 is_loclistx = TRUE;
1163 }
1164 res = dwarf_formudata(attr,&attr_val,error);
1165 if (res != DW_DLV_OK) {
1166 return res;
1167 }
1168 /* the context cc_loclists_base gives the offset
1169 of the array. of offsets (if cc_loclists_base_present) */
1170 offset_in_loclists = attr_val;
1171 if (is_loclistx) {
1172 if (ctx->cc_loclists_base_present) {
1173 offset_in_loclists = ctx->cc_loclists_base;
1174 } else {
1175 /* FIXME: check in tied file for a cc_loclists_base */
1176 dwarfstring m;
1177
1178 dwarfstring_constructor(&m);
1179 dwarfstring_append_printf_u(&m,
1180 "DW_DLE_LOCLISTS_ERROR: loclists table index of"
1181 " %u" ,attr_val);
1182 dwarfstring_append(&m,
1183 " is unusable unless it is in a tied file."
1184 " libdwarf is incomplete. FIXME");
1185 _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR,
1186 dwarfstring_string(&m));
1187 dwarfstring_destructor(&m);
1188 return DW_DLV_ERROR;
1189 }
1190 } else {
1191 offset_in_loclists = attr_val;
1192 }
1193 }
1194 res = _dwarf_which_loclists_context(dbg,ctx,
1195 offset_in_loclists,
1196 &loclists_contextnum,error);
1197 if (res != DW_DLV_OK) {
1198 return res;
1199 }
1200 rctx = array[loclists_contextnum];
1201 table_base = rctx->lc_offsets_array;
1202 entrycount = rctx->lc_offset_entry_count;
1203 offsetsize = rctx->lc_offset_size;
1204 enddata = rctx->lc_endaddr;
1205
1206 if (is_loclistx && attr_val >= entrycount) {
1207 dwarfstring m;
1208
1209 dwarfstring_constructor(&m);
1210 dwarfstring_append_printf_u(&m,
1211 "DW_DLE_LOCLISTS_ERROR: loclists table index of"
1212 " %u" ,attr_val);
1213 dwarfstring_append_printf_u(&m,
1214 " too large for table of %u "
1215 "entries.",entrycount);
1216 _dwarf_error_string(dbg,error,
1217 DW_DLE_LOCLISTS_ERROR,
1218 dwarfstring_string(&m));
1219 dwarfstring_destructor(&m);
1220 return DW_DLV_ERROR;
1221 }
1222 llhead->ll_localcontext = rctx;
1223 llhead->ll_index = loclists_contextnum;
1224 llhead->ll_cuversion = rctx->lc_version;
1225 llhead->ll_offset_size = offsetsize;
1226 llhead->ll_address_size = rctx->lc_address_size;
1227 llhead->ll_segment_selector_size =
1228 rctx->lc_segment_selector_size;
1229
1230 if (is_loclistx) {
1231 Dwarf_Unsigned table_entryval = 0;
1232
1233 table_entry = attr_val*offsetsize + table_base;
1234 /* No malloc here yet so no leak if the macro returns
1235 DW_DLV_ERROR */
1236 READ_UNALIGNED_CK(dbg,table_entryval, Dwarf_Unsigned,
1237 table_entry,offsetsize,error,enddata);
1238 lle_global_offset = rctx->lc_offsets_off_in_sect +
1239 table_entryval;
1240 } else {
1241 lle_global_offset = attr_val;
1242 }
1243
1244 llhead->ll_llepointer = rctx->lc_offsets_array +
1245 rctx->lc_offset_entry_count*offsetsize;
1246 llhead->ll_end_data_area = enddata;
1247
1248 llhead->ll_llearea_offset = lle_global_offset;
1249 llhead->ll_llepointer = lle_global_offset +
1250 dbg->de_debug_loclists.dss_data;
1251
1252 res = build_array_of_lle(dbg,llhead,error);
1253 if (res != DW_DLV_OK) {
1254 dwarf_dealloc(dbg,llhead,DW_DLA_LOCLISTS_HEAD);
1255 return res;
1256 }
1257 return DW_DLV_OK;
1258 }
1259
1260
1261 int
dwarf_get_loclists_entry_fields(Dwarf_Loc_Head_c head,Dwarf_Unsigned entrynum,unsigned * entrylen,unsigned * code,Dwarf_Unsigned * raw1,Dwarf_Unsigned * raw2,Dwarf_Unsigned * cooked1,Dwarf_Unsigned * cooked2,UNUSEDARG Dwarf_Error * err)1262 dwarf_get_loclists_entry_fields(
1263 Dwarf_Loc_Head_c head,
1264 Dwarf_Unsigned entrynum,
1265 unsigned *entrylen,
1266 unsigned *code,
1267 Dwarf_Unsigned *raw1,
1268 Dwarf_Unsigned *raw2,
1269 Dwarf_Unsigned *cooked1,
1270 Dwarf_Unsigned *cooked2,
1271 /* FIXME not right for loclists or their loc exprs */
1272 UNUSEDARG Dwarf_Error *err)
1273 {
1274 Dwarf_Locdesc_c e = 0;
1275
1276 if (entrynum >= head->ll_locdesc_count) {
1277 return DW_DLV_NO_ENTRY;
1278 }
1279 e = head->ll_locdesc + entrynum;
1280 *entrylen = e->ld_entrylen;
1281 *code = e->ld_lle_value;
1282 *raw1 = e->ld_rawlow;
1283 *raw2 = e->ld_rawhigh;
1284 *cooked1 = e->ld_lopc;
1285 *cooked2 = e->ld_highpc;
1286 return DW_DLV_OK;
1287 }
1288
1289 /* Deals with both fully and partially build head */
1290 void
_dwarf_free_loclists_head(Dwarf_Loc_Head_c head)1291 _dwarf_free_loclists_head(Dwarf_Loc_Head_c head)
1292 {
1293 Dwarf_Debug dbg = head->ll_dbg;
1294
1295 if (head->ll_first) {
1296 /* partially built head. */
1297 /* ASSERT: ll_loclists is NULL */
1298 Dwarf_Locdesc_c cur = head->ll_first;
1299 Dwarf_Locdesc_c next = 0;
1300
1301 for ( ; cur ; cur = next) {
1302 next = cur->ld_next;
1303 free(cur);
1304 }
1305 head->ll_first = 0;
1306 head->ll_last = 0;
1307 head->ll_locdesc_count = 0;
1308 } else {
1309 Dwarf_Locdesc_c desc = head->ll_locdesc;
1310 /* ASSERT: ll_first and ll_last are NULL */
1311 /* fully built head. */
1312 Dwarf_Unsigned listlen = head->ll_locdesc_count;
1313 Dwarf_Unsigned i = 0;
1314 for ( ; i < listlen; ++i) {
1315 Dwarf_Loc_Expr_Op loc = desc[i].ld_s;
1316 if(loc) {
1317 dwarf_dealloc(dbg,loc,DW_DLA_LOC_BLOCK_C);
1318 }
1319 }
1320 dwarf_dealloc(dbg,head->ll_locdesc,DW_DLA_LOCDESC_C);
1321 head->ll_locdesc = 0;
1322 head->ll_locdesc_count = 0;
1323 }
1324 }
1325
1326 void
_dwarf_loclists_head_destructor(void * head)1327 _dwarf_loclists_head_destructor(void *head)
1328 {
1329 Dwarf_Loc_Head_c h = head;
1330
1331 _dwarf_free_loclists_head(h);
1332 }
1333