xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_loclists.c (revision a92282e44f968185a6bba094d1e5fece2da819cf)
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
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
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
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
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
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. */
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
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
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. */
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.  */
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.  */
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
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
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
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
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
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
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
1327 _dwarf_loclists_head_destructor(void *head)
1328 {
1329     Dwarf_Loc_Head_c h = head;
1330 
1331     _dwarf_free_loclists_head(h);
1332 }
1333