/src/libdwarf/src/lib/libdwarf/dwarf_rnglists.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
35 | | #include <stdlib.h> /* free() malloc() */ |
36 | | #include <stdio.h> /* printf */ |
37 | | #include <string.h> /* memset() */ |
38 | | |
39 | | #if defined(_WIN32) && defined(HAVE_STDAFX_H) |
40 | | #include "stdafx.h" |
41 | | #endif /* HAVE_STDAFX_H */ |
42 | | |
43 | | #include "dwarf.h" |
44 | | #include "libdwarf.h" |
45 | | #include "libdwarf_private.h" |
46 | | #include "dwarf_base_types.h" |
47 | | #include "dwarf_opaque.h" |
48 | | #include "dwarf_alloc.h" |
49 | | #include "dwarf_error.h" |
50 | | #include "dwarf_util.h" |
51 | | #include "dwarf_string.h" |
52 | | #include "dwarf_rnglists.h" |
53 | | |
54 | | #define SIZEOFT8 1 |
55 | 6.63k | #define SIZEOFT16 2 |
56 | 9.48k | #define SIZEOFT32 4 |
57 | | #define SIZEOFT64 8 |
58 | | |
59 | | #if 0 |
60 | | static void |
61 | | dump_bytes(const char *msg,Dwarf_Small * start, long len) |
62 | | { |
63 | | Dwarf_Small *end = start + len; |
64 | | Dwarf_Small *cur = start; |
65 | | printf("%s (0x%lx) ",msg,(unsigned long)start); |
66 | | for (; cur < end; cur++) { |
67 | | printf("%02x", *cur); |
68 | | } |
69 | | printf("\n"); |
70 | | } |
71 | | #endif /*0*/ |
72 | | #if 0 |
73 | | static void |
74 | | dump_rh(const char *msg, |
75 | | int line, |
76 | | struct Dwarf_Rnglists_Head_s *head) |
77 | | { |
78 | | printf("Rnglists_Head: %s line %d\n", |
79 | | msg,line); |
80 | | printf(" count of entries: " |
81 | | DW_PR_DUu |
82 | | " (0x%" DW_PR_DUx ")\n", |
83 | | head->rh_count,head->rh_count); |
84 | | printf(" rh_rnglists : %p\n",(void *)) head->rh_rnglists); |
85 | | if (head->rh_first) { |
86 | | printf(" rh_first : %" DW_PR_DUu "\n", head->rh_first); |
87 | | if (head->rh_last) { |
88 | | printf(" rh_last : %" DW_PR_DUu "\n",head->rh_last); |
89 | | } |
90 | | printf(" rh_bytes total : %" DW_PR_DUu |
91 | | " (0x%" DW_PR_DUx ")\n",head->rh_bytes_total, |
92 | | head->rh_bytes_total); |
93 | | printf(" CU Context : %p",(void *)head->rh_context); |
94 | | printf(" Rnglists Context: %p",(void *)head->rh_localcontext); |
95 | | } |
96 | | #endif |
97 | | |
98 | | /* Used in case of error reading the |
99 | | rnglists headers (not referring to Dwarf_Rnglists_Head |
100 | | here), to clean up. */ |
101 | | static void |
102 | | free_rnglists_chain(Dwarf_Debug dbg, Dwarf_Chain head) |
103 | 2.51k | { |
104 | 2.51k | Dwarf_Chain cur = head; |
105 | 2.51k | Dwarf_Chain next = 0; |
106 | | |
107 | 2.51k | if (!head) { |
108 | 2.25k | return; |
109 | 2.25k | } |
110 | 1.89k | for ( ;cur; cur = next) { |
111 | 1.63k | next = cur->ch_next; |
112 | 1.63k | if (cur->ch_item) { |
113 | 1.63k | free(cur->ch_item); |
114 | 1.63k | cur->ch_item = 0; |
115 | 1.63k | dwarf_dealloc(dbg,cur,DW_DLA_CHAIN); |
116 | 1.63k | } |
117 | 1.63k | } |
118 | 264 | } |
119 | | |
120 | | static int |
121 | | read_single_rle_entry(Dwarf_Debug dbg, |
122 | | Dwarf_Small *data, |
123 | | Dwarf_Unsigned dataoffset, |
124 | | Dwarf_Small *enddata, |
125 | | unsigned address_size, |
126 | | unsigned *bytes_count_out, |
127 | | unsigned *entry_kind, |
128 | | Dwarf_Unsigned *entry_operand1, |
129 | | Dwarf_Unsigned *entry_operand2, |
130 | | Dwarf_Error* error) |
131 | 4.86k | { |
132 | 4.86k | Dwarf_Unsigned count = 0; |
133 | 4.86k | unsigned leblen = 0; |
134 | 4.86k | unsigned code = 0; |
135 | 4.86k | Dwarf_Unsigned val1 = 0; |
136 | 4.86k | Dwarf_Unsigned val2 = 0; |
137 | | |
138 | 4.86k | code = *data; |
139 | 4.86k | ++data; |
140 | 4.86k | ++count; |
141 | 4.86k | switch(code) { |
142 | 2.21k | case DW_RLE_end_of_list: break; |
143 | 824 | case DW_RLE_base_addressx:{ |
144 | 824 | DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen, |
145 | 824 | dbg,error,enddata); |
146 | 823 | count += leblen; |
147 | 823 | } |
148 | 0 | break; |
149 | 408 | case DW_RLE_startx_endx: |
150 | 655 | case DW_RLE_startx_length: |
151 | 996 | case DW_RLE_offset_pair: { |
152 | 996 | DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen, |
153 | 996 | dbg,error,enddata); |
154 | 988 | count += leblen; |
155 | 988 | DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen, |
156 | 988 | dbg,error,enddata); |
157 | 979 | count += leblen; |
158 | 979 | } |
159 | 0 | break; |
160 | 277 | case DW_RLE_base_address: { |
161 | 277 | READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned, |
162 | 277 | data,address_size,error,enddata); |
163 | 274 | data += address_size; |
164 | 274 | count += address_size; |
165 | 274 | } |
166 | 0 | break; |
167 | 229 | case DW_RLE_start_end: { |
168 | 229 | READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned, |
169 | 229 | data,address_size,error,enddata); |
170 | 225 | data += address_size; |
171 | 225 | count += address_size; |
172 | 225 | READ_UNALIGNED_CK(dbg,val2, Dwarf_Unsigned, |
173 | 225 | data,address_size,error,enddata); |
174 | 221 | data += address_size; |
175 | 221 | count += address_size; |
176 | 221 | } |
177 | 0 | break; |
178 | 273 | case DW_RLE_start_length: { |
179 | 273 | READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned, |
180 | 273 | data,address_size,error,enddata); |
181 | 269 | data += address_size; |
182 | 269 | count += address_size; |
183 | 269 | DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen, |
184 | 269 | dbg,error,enddata); |
185 | 266 | count += leblen; |
186 | 266 | } |
187 | 0 | break; |
188 | 53 | default: { |
189 | 53 | dwarfstring m; |
190 | | |
191 | 53 | dwarfstring_constructor(&m); |
192 | 53 | dwarfstring_append_printf_u(&m, |
193 | 53 | "DW_DLE_RNGLISTS_ERROR: " |
194 | 53 | "The rangelists entry at .debug_rnglists" |
195 | 53 | " offset 0x%x" ,dataoffset); |
196 | 53 | dwarfstring_append_printf_u(&m, |
197 | 53 | " has code 0x%x which is unknown",code); |
198 | 53 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
199 | 53 | dwarfstring_string(&m)); |
200 | 53 | dwarfstring_destructor(&m); |
201 | 53 | return DW_DLV_ERROR; |
202 | 269 | } |
203 | 0 | break; |
204 | 4.86k | } |
205 | 4.77k | *bytes_count_out = count; |
206 | 4.77k | *entry_kind = code; |
207 | 4.77k | *entry_operand1 = val1; |
208 | 4.77k | *entry_operand2 = val2; |
209 | 4.77k | return DW_DLV_OK; |
210 | 4.86k | } |
211 | | |
212 | | /* Reads the header. Determines the |
213 | | various offsets, including offset |
214 | | of the next header. Does no memory |
215 | | allocations here. */ |
216 | | int |
217 | | _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, |
218 | | Dwarf_Unsigned contextnum, |
219 | | Dwarf_Unsigned sectionlength, |
220 | | Dwarf_Small *data, |
221 | | Dwarf_Small *end_data, |
222 | | Dwarf_Unsigned offset, |
223 | | Dwarf_Rnglists_Context buildhere, |
224 | | Dwarf_Unsigned *next_offset, |
225 | | Dwarf_Error *error) |
226 | 5.40k | { |
227 | 5.40k | Dwarf_Small *startdata = data; |
228 | 5.40k | Dwarf_Unsigned arealen = 0; |
229 | 5.40k | int offset_size = 0; |
230 | 5.40k | int exten_size = 0; |
231 | 5.40k | Dwarf_Unsigned version = 0; |
232 | 5.40k | unsigned address_size = 0; |
233 | 5.40k | unsigned segment_selector_size= 0; |
234 | 5.40k | Dwarf_Unsigned offset_entry_count = 0; |
235 | 5.40k | Dwarf_Unsigned localoff = 0; |
236 | 5.40k | Dwarf_Unsigned lists_len = 0; |
237 | 5.40k | Dwarf_Unsigned secsize_dbg = 0; |
238 | | |
239 | 5.40k | secsize_dbg = dbg->de_debug_rnglists.dss_size; |
240 | | /* Sanity checks */ |
241 | 5.40k | if (sectionlength > secsize_dbg) { |
242 | 0 | dwarfstring m; |
243 | 0 | dwarfstring_constructor(&m); |
244 | 0 | dwarfstring_append_printf_u(&m, |
245 | 0 | "DW_DLE_RNGLISTS_ERROR: " |
246 | 0 | " section_length argument (%lu) mismatch vs.", |
247 | 0 | sectionlength); |
248 | 0 | dwarfstring_append_printf_u(&m, |
249 | 0 | ".debug_rnglists" |
250 | 0 | " section length",secsize_dbg); |
251 | 0 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
252 | 0 | dwarfstring_string(&m)); |
253 | 0 | dwarfstring_destructor(&m); |
254 | 0 | return DW_DLV_ERROR; |
255 | 0 | } |
256 | 5.40k | if (sectionlength > secsize_dbg) { |
257 | 0 | dwarfstring m; |
258 | 0 | dwarfstring_constructor(&m); |
259 | 0 | dwarfstring_append(&m, |
260 | 0 | "DW_DLE_RNGLISTS_ERROR: " |
261 | 0 | " section_length argument mismatch vs. .debug_rnglists" |
262 | 0 | " section length including header."); |
263 | 0 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
264 | 0 | dwarfstring_string(&m)); |
265 | 0 | dwarfstring_destructor(&m); |
266 | 0 | return DW_DLV_ERROR; |
267 | 0 | } |
268 | 5.40k | buildhere->rc_startaddr = data; |
269 | 5.40k | READ_AREA_LENGTH_CK(dbg,arealen,Dwarf_Unsigned, |
270 | 5.40k | data,offset_size,exten_size, |
271 | 5.40k | error, |
272 | 5.40k | sectionlength,end_data); |
273 | 3.73k | if (arealen > sectionlength || |
274 | 3.73k | (arealen+offset_size+exten_size) > sectionlength) { |
275 | 30 | dwarfstring m; |
276 | 30 | dwarfstring_constructor(&m); |
277 | 30 | dwarfstring_append_printf_u(&m, |
278 | 30 | "DW_DLE_RNGLISTS_ERROR: A .debug_rnglists " |
279 | 30 | "area size of 0x%x ",arealen); |
280 | 30 | dwarfstring_append_printf_u(&m, |
281 | 30 | "at offset 0x%x ",offset); |
282 | 30 | dwarfstring_append_printf_u(&m, |
283 | 30 | "is larger than the entire section size of " |
284 | 30 | "0x%x. Corrupt DWARF.",sectionlength); |
285 | 30 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
286 | 30 | dwarfstring_string(&m)); |
287 | 30 | dwarfstring_destructor(&m); |
288 | 30 | return DW_DLV_ERROR; |
289 | 30 | } |
290 | | |
291 | 3.70k | localoff = offset_size+exten_size; |
292 | 3.70k | buildhere->rc_length = arealen + localoff; |
293 | 3.70k | buildhere->rc_dbg = dbg; |
294 | 3.70k | buildhere->rc_index = contextnum; |
295 | 3.70k | buildhere->rc_header_offset = offset; |
296 | 3.70k | buildhere->rc_offset_size = offset_size; |
297 | 3.70k | buildhere->rc_extension_size = exten_size; |
298 | 3.70k | buildhere->rc_magic = RNGLISTS_MAGIC; |
299 | 3.70k | READ_UNALIGNED_CK(dbg,version,Dwarf_Unsigned,data, |
300 | 3.70k | SIZEOFT16,error,end_data); |
301 | 3.68k | if (version != DW_CU_VERSION5) { |
302 | 366 | dwarfstring m; |
303 | 366 | dwarfstring_constructor(&m); |
304 | 366 | dwarfstring_append_printf_u(&m, |
305 | 366 | "DW_DLE_RNGLISTS_ERROR: The version should be 5 " |
306 | 366 | "but we find %u instead.",version); |
307 | 366 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
308 | 366 | dwarfstring_string(&m)); |
309 | 366 | dwarfstring_destructor(&m); |
310 | 366 | return DW_DLV_ERROR; |
311 | 366 | } |
312 | 3.31k | buildhere->rc_version = version; |
313 | 3.31k | data += SIZEOFT16; |
314 | 3.31k | localoff += SIZEOFT16; |
315 | | |
316 | 3.31k | READ_UNALIGNED_CK(dbg,address_size,unsigned,data, |
317 | 3.31k | SIZEOFT8,error,end_data); |
318 | 3.31k | if (address_size != 4 && address_size != 8 && |
319 | 3.31k | address_size != 2) { |
320 | 99 | dwarfstring m; |
321 | 99 | dwarfstring_constructor(&m); |
322 | 99 | dwarfstring_append_printf_u(&m, |
323 | 99 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists " |
324 | 99 | "The address size " |
325 | 99 | "of %u is not supported.",address_size); |
326 | 99 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
327 | 99 | dwarfstring_string(&m)); |
328 | 99 | dwarfstring_destructor(&m); |
329 | 99 | return DW_DLV_ERROR; |
330 | 99 | } |
331 | 3.21k | buildhere->rc_address_size = address_size; |
332 | 3.21k | localoff++; |
333 | 3.21k | data++; |
334 | | |
335 | 3.21k | READ_UNALIGNED_CK(dbg,segment_selector_size,unsigned,data, |
336 | 3.21k | SIZEOFT8,error,end_data); |
337 | 3.20k | buildhere->rc_segment_selector_size = segment_selector_size; |
338 | 3.20k | data++; |
339 | 3.20k | localoff++; |
340 | 3.20k | if (segment_selector_size) { |
341 | 37 | dwarfstring m; |
342 | 37 | dwarfstring_constructor(&m); |
343 | 37 | dwarfstring_append_printf_u(&m, |
344 | 37 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" |
345 | 37 | " The segment selector size " |
346 | 37 | "of %u is not supported.",address_size); |
347 | 37 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
348 | 37 | dwarfstring_string(&m)); |
349 | 37 | dwarfstring_destructor(&m); |
350 | 37 | return DW_DLV_ERROR; |
351 | 37 | } |
352 | 3.16k | if ((offset+localoff+SIZEOFT32) > secsize_dbg) { |
353 | 12 | dwarfstring m; |
354 | 12 | dwarfstring_constructor(&m); |
355 | 12 | dwarfstring_append_printf_u(&m, |
356 | 12 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" |
357 | 12 | " Header runs off the end of the section " |
358 | 12 | " with offset %u",offset+localoff+SIZEOFT32); |
359 | 12 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
360 | 12 | dwarfstring_string(&m)); |
361 | 12 | dwarfstring_destructor(&m); |
362 | 12 | return DW_DLV_ERROR; |
363 | 12 | } |
364 | | |
365 | 3.15k | READ_UNALIGNED_CK(dbg,offset_entry_count,Dwarf_Unsigned,data, |
366 | 3.15k | SIZEOFT32,error,end_data); |
367 | 3.15k | buildhere->rc_offset_entry_count = offset_entry_count; |
368 | 3.15k | data += SIZEOFT32; |
369 | 3.15k | localoff+= SIZEOFT32; |
370 | 3.15k | if (offset_entry_count ){ |
371 | 1.47k | buildhere->rc_offsets_array = data; |
372 | 1.47k | } |
373 | | |
374 | 3.15k | lists_len = offset_size *offset_entry_count; |
375 | 3.15k | if (offset_entry_count >= secsize_dbg || |
376 | 3.15k | lists_len >= secsize_dbg) { |
377 | 170 | dwarfstring m; |
378 | 170 | dwarfstring_constructor(&m); |
379 | 170 | dwarfstring_append_printf_u(&m, |
380 | 170 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" |
381 | 170 | " offset entry count" |
382 | 170 | " of %u is clearly impossible. Corrupt data", |
383 | 170 | offset_entry_count); |
384 | 170 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
385 | 170 | dwarfstring_string(&m)); |
386 | 170 | dwarfstring_destructor(&m); |
387 | 170 | return DW_DLV_ERROR; |
388 | 170 | } |
389 | 2.98k | data += lists_len; |
390 | 2.98k | buildhere->rc_offsets_off_in_sect = offset+localoff; |
391 | 2.98k | localoff += lists_len; |
392 | 2.98k | if (localoff > buildhere->rc_length) { |
393 | 81 | dwarfstring m; |
394 | 81 | dwarfstring_constructor(&m); |
395 | 81 | dwarfstring_append_printf_u(&m, |
396 | 81 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" |
397 | 81 | " length of rnglists header too large at" |
398 | 81 | " of %u is clearly impossible. Corrupt data", |
399 | 81 | localoff); |
400 | 81 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
401 | 81 | dwarfstring_string(&m)); |
402 | 81 | dwarfstring_destructor(&m); |
403 | 81 | return DW_DLV_ERROR; |
404 | 81 | } |
405 | 2.90k | buildhere->rc_first_rnglist_offset = offset+localoff; |
406 | 2.90k | buildhere->rc_rnglists_header = startdata; |
407 | 2.90k | buildhere->rc_endaddr = startdata +buildhere->rc_length; |
408 | 2.90k | if (buildhere->rc_endaddr > end_data) { |
409 | 19 | dwarfstring m; |
410 | 19 | dwarfstring_constructor(&m); |
411 | 19 | dwarfstring_append_printf_u(&m, |
412 | 19 | " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" |
413 | 19 | " length of rnglists header (%u) " |
414 | 19 | "runs off end of section. Corrupt data", |
415 | 19 | buildhere->rc_length); |
416 | 19 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
417 | 19 | dwarfstring_string(&m)); |
418 | 19 | dwarfstring_destructor(&m); |
419 | 19 | return DW_DLV_ERROR; |
420 | 19 | } |
421 | 2.88k | buildhere->rc_past_last_rnglist_offset = |
422 | 2.88k | buildhere->rc_header_offset +buildhere->rc_length; |
423 | 2.88k | *next_offset = buildhere->rc_past_last_rnglist_offset; |
424 | 2.88k | return DW_DLV_OK; |
425 | 2.90k | } |
426 | | |
427 | | /* We return a pointer to an array of contexts |
428 | | (not context pointers) through *cxt if |
429 | | we succeed and are returning DW_DLV_OK. |
430 | | We never return DW_DLV_NO_ENTRY here. */ |
431 | | static int |
432 | | internal_load_rnglists_contexts(Dwarf_Debug dbg, |
433 | | Dwarf_Rnglists_Context **cxt, |
434 | | Dwarf_Unsigned *count, |
435 | | Dwarf_Error *error) |
436 | 2.65k | { |
437 | 2.65k | Dwarf_Unsigned offset = 0; |
438 | 2.65k | Dwarf_Unsigned nextoffset = 0; |
439 | 2.65k | Dwarf_Small * data = dbg->de_debug_rnglists.dss_data; |
440 | 2.65k | Dwarf_Unsigned section_size = dbg->de_debug_rnglists.dss_size; |
441 | 2.65k | Dwarf_Small * startdata = data; |
442 | 2.65k | Dwarf_Small * end_data = data +section_size; |
443 | 2.65k | Dwarf_Chain curr_chain = 0; |
444 | 2.65k | Dwarf_Chain head_chain = 0; |
445 | 2.65k | Dwarf_Chain *plast = &head_chain; |
446 | 2.65k | int res = 0; |
447 | 2.65k | Dwarf_Unsigned chainlength = 0; |
448 | 2.65k | Dwarf_Rnglists_Context *fullarray = 0; |
449 | 2.65k | Dwarf_Unsigned i = 0; |
450 | | |
451 | 5.53k | for (i = 0 ; data < end_data ; ++i,data = startdata+nextoffset) { |
452 | 5.40k | Dwarf_Rnglists_Context newcontext = 0; |
453 | | |
454 | | /* sizeof the context struct, not sizeof a pointer */ |
455 | 5.40k | newcontext = malloc(sizeof(*newcontext)); |
456 | 5.40k | if (!newcontext) { |
457 | 0 | free_rnglists_chain(dbg,head_chain); |
458 | 0 | _dwarf_error_string(dbg,error, |
459 | 0 | DW_DLE_ALLOC_FAIL, |
460 | 0 | "DW_DLE_ALLOC_FAIL: Allocation of " |
461 | 0 | "Rnglists_Context failed"); |
462 | 0 | return DW_DLV_ERROR; |
463 | 0 | } |
464 | 5.40k | memset(newcontext,0,sizeof(*newcontext)); |
465 | 5.40k | newcontext->rc_magic = RNGLISTS_MAGIC; |
466 | 5.40k | res = _dwarf_internal_read_rnglists_header(dbg, |
467 | 5.40k | chainlength, |
468 | 5.40k | section_size, |
469 | 5.40k | data,end_data,offset, |
470 | 5.40k | newcontext,&nextoffset,error); |
471 | 5.40k | if (res == DW_DLV_ERROR) { |
472 | 2.51k | free(newcontext); |
473 | 2.51k | newcontext = 0; |
474 | 2.51k | free_rnglists_chain(dbg,head_chain); |
475 | 2.51k | return res; |
476 | 2.51k | } |
477 | 2.88k | newcontext->rc_magic = RNGLISTS_MAGIC; |
478 | 2.88k | curr_chain = (Dwarf_Chain) |
479 | 2.88k | _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); |
480 | 2.88k | if (curr_chain == NULL) { |
481 | 0 | _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, |
482 | 0 | "DW_DLE_ALLOC_FAIL: allocating Rnglists_Context" |
483 | 0 | " chain entry"); |
484 | 0 | free(newcontext); |
485 | 0 | newcontext = 0; |
486 | 0 | free_rnglists_chain(dbg,head_chain); |
487 | 0 | return DW_DLV_ERROR; |
488 | 0 | } |
489 | 2.88k | curr_chain->ch_item = newcontext; |
490 | 2.88k | ++chainlength; |
491 | 2.88k | (*plast) = curr_chain; |
492 | 2.88k | plast = &(curr_chain->ch_next); |
493 | 2.88k | offset = nextoffset; |
494 | 2.88k | newcontext = 0; |
495 | 2.88k | } |
496 | 134 | fullarray= (Dwarf_Rnglists_Context *)malloc( |
497 | 134 | chainlength *sizeof(Dwarf_Rnglists_Context /*pointer*/)); |
498 | 134 | if (!fullarray) { |
499 | 0 | free_rnglists_chain(dbg,head_chain); |
500 | 0 | _dwarf_error_string(dbg,error, |
501 | 0 | DW_DLE_ALLOC_FAIL,"Allocation of " |
502 | 0 | "Rnglists_Context pointer array failed"); |
503 | 0 | return DW_DLV_ERROR; |
504 | 0 | } |
505 | 134 | curr_chain = head_chain; |
506 | 1.38k | for (i = 0; i < chainlength; ++i) { |
507 | 1.25k | Dwarf_Chain prev = 0; |
508 | 1.25k | Dwarf_Rnglists_Context c = |
509 | 1.25k | (Dwarf_Rnglists_Context)curr_chain->ch_item; |
510 | 1.25k | fullarray[i] = c; |
511 | 1.25k | curr_chain->ch_item = 0; |
512 | 1.25k | prev = curr_chain; |
513 | 1.25k | curr_chain = curr_chain->ch_next; |
514 | 1.25k | dwarf_dealloc(dbg, prev, DW_DLA_CHAIN); |
515 | 1.25k | } |
516 | | /* ASSERT: the chain is entirely alloc'd |
517 | | and the array of pointers points to |
518 | | individually malloc'd Dwarf_Rnglists_Context_s */ |
519 | 134 | *cxt = fullarray; |
520 | 134 | *count = chainlength; |
521 | 134 | return DW_DLV_OK; |
522 | 134 | } |
523 | | |
524 | | /* Used by dwarfdump to print raw rnglists data. |
525 | | Loads all the .debug_rnglists[.dwo] headers and |
526 | | returns DW_DLV_NO_ENTRY if the section |
527 | | is missing or empty. |
528 | | Intended to be done quite early and |
529 | | done exactly once. |
530 | | Harmless to do more than once. |
531 | | With DW_DLV_OK it returns the number of |
532 | | rnglists headers in the section through |
533 | | rnglists_count. */ |
534 | | int dwarf_load_rnglists( |
535 | | Dwarf_Debug dbg, |
536 | | Dwarf_Unsigned *rnglists_count, |
537 | | Dwarf_Error *error) |
538 | 18.5k | { |
539 | 18.5k | int res = DW_DLV_ERROR; |
540 | 18.5k | Dwarf_Rnglists_Context *cxt = 0; |
541 | 18.5k | Dwarf_Unsigned count = 0; |
542 | | |
543 | 18.5k | CHECK_DBG(dbg,error,"dwarf_load_rnglists"); |
544 | 11.4k | if (dbg->de_rnglists_context) { |
545 | 0 | if (rnglists_count) { |
546 | 0 | *rnglists_count = dbg->de_rnglists_context_count; |
547 | 0 | } |
548 | 0 | return DW_DLV_OK; |
549 | 0 | } |
550 | 11.4k | if (!dbg->de_debug_rnglists.dss_size) { |
551 | | /* nothing there. */ |
552 | 8.18k | return DW_DLV_NO_ENTRY; |
553 | 8.18k | } |
554 | 3.27k | if (!dbg->de_debug_rnglists.dss_data) { |
555 | 3.27k | res = _dwarf_load_section(dbg, &dbg->de_debug_rnglists, |
556 | 3.27k | error); |
557 | 3.27k | if (res != DW_DLV_OK) { |
558 | 621 | return res; |
559 | 621 | } |
560 | 3.27k | } |
561 | 2.65k | res = internal_load_rnglists_contexts(dbg,&cxt,&count,error); |
562 | 2.65k | if (res == DW_DLV_ERROR) { |
563 | 2.51k | return res; |
564 | 2.51k | } |
565 | 134 | dbg->de_rnglists_context = cxt; |
566 | 134 | dbg->de_rnglists_context_count = count; |
567 | 134 | if (rnglists_count) { |
568 | 110 | *rnglists_count = count; |
569 | 110 | } |
570 | 134 | return DW_DLV_OK; |
571 | 2.65k | } |
572 | | |
573 | | /* Frees the memory in use in all rnglists contexts. |
574 | | Done by dwarf_finish() */ |
575 | | void |
576 | | _dwarf_dealloc_rnglists_context(Dwarf_Debug dbg) |
577 | 143k | { |
578 | 143k | Dwarf_Unsigned i = 0; |
579 | 143k | Dwarf_Rnglists_Context * rngcon = 0; |
580 | | |
581 | 143k | if (IS_INVALID_DBG(dbg)) { |
582 | 0 | return; |
583 | 0 | } |
584 | 143k | if (!dbg->de_rnglists_context) { |
585 | 143k | return; |
586 | 143k | } |
587 | 134 | rngcon = dbg->de_rnglists_context; |
588 | 1.38k | for ( ; i < dbg->de_rnglists_context_count; ++i) { |
589 | 1.25k | Dwarf_Rnglists_Context con = rngcon[i]; |
590 | 1.25k | con->rc_offsets_array = 0; |
591 | 1.25k | con->rc_magic = 0; |
592 | 1.25k | con->rc_offset_entry_count = 0; |
593 | 1.25k | free(con); |
594 | 1.25k | rngcon[i] = 0; |
595 | 1.25k | } |
596 | 134 | free(dbg->de_rnglists_context); |
597 | 134 | dbg->de_rnglists_context = 0; |
598 | 134 | dbg->de_rnglists_context_count = 0; |
599 | 134 | } |
600 | | |
601 | | /* Used by dwarfdump to print raw rnglists data. */ |
602 | | int |
603 | | dwarf_get_rnglist_offset_index_value( |
604 | | Dwarf_Debug dbg, |
605 | | Dwarf_Unsigned context_index, |
606 | | Dwarf_Unsigned offsetentry_index, |
607 | | Dwarf_Unsigned * offset_value_out, |
608 | | Dwarf_Unsigned * global_offset_value_out, |
609 | | Dwarf_Error *error) |
610 | 3.61k | { |
611 | 3.61k | Dwarf_Rnglists_Context con = 0; |
612 | 3.61k | unsigned offset_len = 0; |
613 | 3.61k | Dwarf_Small *offsetptr = 0; |
614 | 3.61k | Dwarf_Unsigned targetoffset = 0; |
615 | 3.61k | Dwarf_Unsigned localoffset = 0; |
616 | | |
617 | 3.61k | CHECK_DBG(dbg,error,"dwarf_get_rnglist_offset_index_value()"); |
618 | 3.61k | if (!dbg->de_rnglists_context) { |
619 | 0 | return DW_DLV_NO_ENTRY; |
620 | 0 | } |
621 | | |
622 | 3.61k | if (!dbg->de_rnglists_context_count) { |
623 | 0 | return DW_DLV_NO_ENTRY; |
624 | 0 | } |
625 | 3.61k | if (context_index >= dbg->de_rnglists_context_count) { |
626 | 0 | return DW_DLV_NO_ENTRY; |
627 | 0 | } |
628 | 3.61k | con = dbg->de_rnglists_context[context_index]; |
629 | 3.61k | if (con->rc_magic != RNGLISTS_MAGIC) { |
630 | 0 | _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, |
631 | 0 | "DW_DLE_DBG_NULL " |
632 | 0 | "rnglists context magic wrong " |
633 | 0 | "not RNGLISTS_MAGIC"); |
634 | 0 | return DW_DLV_ERROR; |
635 | 0 | } |
636 | 3.61k | if (offsetentry_index >= con->rc_offset_entry_count) { |
637 | 0 | return DW_DLV_NO_ENTRY; |
638 | 0 | } |
639 | 3.61k | offset_len = con->rc_offset_size; |
640 | 3.61k | localoffset = offsetentry_index*offset_len; |
641 | 3.61k | offsetptr = con->rc_offsets_array + localoffset; |
642 | 3.61k | if ((con->rc_offsets_off_in_sect +localoffset + |
643 | 3.61k | offset_len) > |
644 | 3.61k | con->rc_past_last_rnglist_offset) { |
645 | 0 | dwarfstring m; |
646 | |
|
647 | 0 | dwarfstring_constructor(&m); |
648 | 0 | dwarfstring_append_printf_u(&m, |
649 | 0 | "DW_DLE_RNGLISTS_ERROR " |
650 | 0 | "dwarf_get_rnglist_offset_index_value() " |
651 | 0 | " Offset for index %u is too large. ", |
652 | 0 | offsetentry_index); |
653 | 0 | _dwarf_error_string(dbg, error,DW_DLE_RNGLISTS_ERROR, |
654 | 0 | dwarfstring_string(&m)); |
655 | 0 | dwarfstring_destructor(&m); |
656 | 0 | return DW_DLV_ERROR; |
657 | |
|
658 | 0 | } |
659 | 3.61k | READ_UNALIGNED_CK(dbg,targetoffset,Dwarf_Unsigned, |
660 | 3.61k | offsetptr, |
661 | 3.61k | offset_len,error,con->rc_endaddr); |
662 | 3.61k | if (offset_value_out) { |
663 | 3.61k | *offset_value_out = targetoffset; |
664 | 3.61k | } |
665 | 3.61k | if (global_offset_value_out) { |
666 | 3.61k | *global_offset_value_out = targetoffset + |
667 | 3.61k | con->rc_offsets_off_in_sect; |
668 | 3.61k | } |
669 | 3.61k | return DW_DLV_OK; |
670 | 3.61k | } |
671 | | |
672 | | /* Used by dwarfdump to print basic data from the |
673 | | data generated to look at a specific rangelist |
674 | | as returned by dwarf_rnglists_index_get_rle_head() |
675 | | or dwarf_rnglists_offset_get_rle_head. */ |
676 | | int dwarf_get_rnglist_head_basics( |
677 | | Dwarf_Rnglists_Head head, |
678 | | Dwarf_Unsigned * rle_count, |
679 | | Dwarf_Unsigned * rle_version, |
680 | | Dwarf_Unsigned * rnglists_index_returned, |
681 | | Dwarf_Unsigned * bytes_total_in_rle, |
682 | | Dwarf_Half * offset_size, |
683 | | Dwarf_Half * address_size, |
684 | | Dwarf_Half * segment_selector_size, |
685 | | Dwarf_Unsigned * overall_offset_of_this_context, |
686 | | Dwarf_Unsigned * total_length_of_this_context, |
687 | | Dwarf_Unsigned * offset_table_offset, |
688 | | Dwarf_Unsigned * offset_table_entrycount, |
689 | | Dwarf_Bool * rnglists_base_present, |
690 | | Dwarf_Unsigned * rnglists_base, |
691 | | Dwarf_Bool * rnglists_base_address_present, |
692 | | Dwarf_Unsigned * rnglists_base_address, |
693 | | Dwarf_Bool * rnglists_debug_addr_base_present, |
694 | | Dwarf_Unsigned * rnglists_debug_addr_base, |
695 | | Dwarf_Error *error) |
696 | 0 | { |
697 | 0 | Dwarf_Rnglists_Context rngcontext = 0; |
698 | |
|
699 | 0 | if (!head || (!head->rh_dbg) || |
700 | 0 | head->rh_magic != RNGLISTS_MAGIC) { |
701 | 0 | _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, |
702 | 0 | "DW_DLE_DBG_NULL " |
703 | 0 | "NULL or invalid Dwarf_Rnglists_Head " |
704 | 0 | "argument passed to " |
705 | 0 | "dwarf_get_rnglist_head_basics()"); |
706 | 0 | return DW_DLV_ERROR; |
707 | 0 | } |
708 | 0 | *rle_count = head->rh_count; |
709 | 0 | *rle_version = head->rh_version; |
710 | 0 | *rnglists_index_returned = head->rh_index; |
711 | 0 | *bytes_total_in_rle = head->rh_bytes_total; |
712 | 0 | *offset_size = head->rh_offset_size; |
713 | 0 | *address_size = head->rh_address_size; |
714 | 0 | *segment_selector_size = head->rh_segment_selector_size; |
715 | 0 | rngcontext = head->rh_localcontext; |
716 | 0 | if (rngcontext) { |
717 | 0 | *overall_offset_of_this_context = |
718 | 0 | rngcontext->rc_header_offset; |
719 | 0 | *total_length_of_this_context = rngcontext->rc_length; |
720 | 0 | *offset_table_offset = rngcontext->rc_offsets_off_in_sect; |
721 | 0 | *offset_table_entrycount = rngcontext->rc_offset_entry_count; |
722 | 0 | } |
723 | 0 | *rnglists_base_present = head->rh_at_rnglists_base_present; |
724 | 0 | *rnglists_base= head->rh_at_rnglists_base; |
725 | |
|
726 | 0 | *rnglists_base_address_present = head->rh_cu_base_address_present; |
727 | 0 | *rnglists_base_address= head->rh_cu_base_address; |
728 | |
|
729 | 0 | *rnglists_debug_addr_base_present = head->rh_cu_addr_base_present; |
730 | 0 | *rnglists_debug_addr_base = head->rh_cu_addr_base; |
731 | 0 | return DW_DLV_OK; |
732 | 0 | } |
733 | | |
734 | | /* Used by dwarfdump to print raw rnglists data. |
735 | | Enables printing of details about the Range List Table |
736 | | Headers, one header per call. Index starting at 0. |
737 | | Returns DW_DLV_NO_ENTRY if index is too high for the table. |
738 | | A .debug_rnglists section may contain any number |
739 | | of Range List Table Headers with their details. */ |
740 | | int dwarf_get_rnglist_context_basics( |
741 | | Dwarf_Debug dbg, |
742 | | Dwarf_Unsigned context_index, |
743 | | Dwarf_Unsigned * header_offset, |
744 | | Dwarf_Small * offset_size, |
745 | | Dwarf_Small * extension_size, |
746 | | unsigned * version, /* 5 */ |
747 | | Dwarf_Small * address_size, |
748 | | Dwarf_Small * segment_selector_size, |
749 | | Dwarf_Unsigned * offset_entry_count, |
750 | | Dwarf_Unsigned * offset_of_offset_array, |
751 | | Dwarf_Unsigned * offset_of_first_rangeentry, |
752 | | Dwarf_Unsigned * offset_past_last_rangeentry, |
753 | | Dwarf_Error *error) |
754 | 709 | { |
755 | 709 | Dwarf_Rnglists_Context con = 0; |
756 | | |
757 | 709 | CHECK_DBG(dbg,error,"dwarf_get_rnglist_context_basics()"); |
758 | 709 | if (!dbg->de_rnglists_context_count) { |
759 | 0 | return DW_DLV_NO_ENTRY; |
760 | 0 | } |
761 | 709 | if (context_index >= dbg->de_rnglists_context_count) { |
762 | 0 | return DW_DLV_NO_ENTRY; |
763 | 0 | } |
764 | 709 | con = dbg->de_rnglists_context[context_index]; |
765 | 709 | if (con->rc_magic != RNGLISTS_MAGIC) { |
766 | 0 | _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, |
767 | 0 | "DW_DLE_DBG_NULL " |
768 | 0 | "rnglists context " |
769 | 0 | "not RNGLISTS_MAGIC " |
770 | 0 | "in dwarf_get_rnglist_context_basics()"); |
771 | 0 | return DW_DLV_ERROR; |
772 | 0 | } |
773 | 709 | if (header_offset) { |
774 | 709 | *header_offset = con->rc_header_offset; |
775 | 709 | } |
776 | 709 | if (offset_size) { |
777 | 709 | *offset_size = con->rc_offset_size; |
778 | 709 | } |
779 | 709 | if (extension_size) { |
780 | 709 | *extension_size = con->rc_extension_size; |
781 | 709 | } |
782 | 709 | if (version) { |
783 | 709 | *version = con->rc_version; |
784 | 709 | } |
785 | 709 | if (address_size) { |
786 | 709 | *address_size = con->rc_address_size; |
787 | 709 | } |
788 | 709 | if (segment_selector_size) { |
789 | 709 | *segment_selector_size = con->rc_segment_selector_size; |
790 | 709 | } |
791 | 709 | if (offset_entry_count) { |
792 | 709 | *offset_entry_count = con->rc_offset_entry_count; |
793 | 709 | } |
794 | 709 | if (offset_of_offset_array) { |
795 | 709 | *offset_of_offset_array = con->rc_offsets_off_in_sect; |
796 | 709 | } |
797 | 709 | if (offset_of_first_rangeentry) { |
798 | 709 | *offset_of_first_rangeentry = con->rc_first_rnglist_offset; |
799 | 709 | } |
800 | 709 | if (offset_past_last_rangeentry) { |
801 | 709 | *offset_past_last_rangeentry = |
802 | 709 | con->rc_past_last_rnglist_offset; |
803 | 709 | } |
804 | 709 | return DW_DLV_OK; |
805 | 709 | } |
806 | | |
807 | | /* Used by dwarfdump to print raw rnglists data. |
808 | | entry offset is offset_of_first_rangeentry. |
809 | | Stop when the returned *next_entry_offset |
810 | | is == offset_past_last_rangentry (from |
811 | | dwarf_get_rnglist_context_plus). |
812 | | This only makes sense within those ranges. |
813 | | This retrieves raw detail from the section, |
814 | | no base values or anything are added. |
815 | | So this returns raw individual entries |
816 | | for a single rnglist header, meaning a |
817 | | a single Dwarf_Rnglists_Context. */ |
818 | | int dwarf_get_rnglist_rle( |
819 | | Dwarf_Debug dbg, |
820 | | Dwarf_Unsigned contextnumber, |
821 | | Dwarf_Unsigned entry_offset, |
822 | | Dwarf_Unsigned endoffset, |
823 | | unsigned *entrylen, |
824 | | unsigned *entry_kind, |
825 | | Dwarf_Unsigned *entry_operand1, |
826 | | Dwarf_Unsigned *entry_operand2, |
827 | | Dwarf_Error *error) |
828 | 4.86k | { |
829 | 4.86k | Dwarf_Rnglists_Context con = 0; |
830 | 4.86k | Dwarf_Small *data = 0; |
831 | 4.86k | Dwarf_Small *enddata = 0; |
832 | 4.86k | int res = 0; |
833 | 4.86k | unsigned address_size = 0; |
834 | 4.86k | Dwarf_Unsigned secsize = 0; |
835 | | |
836 | 4.86k | CHECK_DBG(dbg,error,"dwarf_get_rnglist_rle()"); |
837 | 4.86k | secsize = dbg->de_debug_rnglists.dss_size; |
838 | 4.86k | if (!dbg->de_rnglists_context_count) { |
839 | 0 | return DW_DLV_NO_ENTRY; |
840 | 0 | } |
841 | 4.86k | if (!dbg->de_rnglists_context_count) { |
842 | 0 | return DW_DLV_NO_ENTRY; |
843 | 0 | } |
844 | 4.86k | if (contextnumber >= dbg->de_rnglists_context_count) { |
845 | 0 | return DW_DLV_NO_ENTRY; |
846 | 0 | } |
847 | 4.86k | if (entry_offset >= secsize) { |
848 | 0 | return DW_DLV_NO_ENTRY; |
849 | 0 | } |
850 | 4.86k | if (endoffset > secsize) { |
851 | 0 | _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR, |
852 | 0 | " DW_DLE_RNGLISTS_ERROR " |
853 | 0 | "The end offset to " |
854 | 0 | "dwarf_get_rnglist_rle() is " |
855 | 0 | "too large for the section"); |
856 | 0 | return DW_DLV_ERROR; |
857 | 0 | } |
858 | 4.86k | if (endoffset <= entry_offset) { |
859 | 0 | _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR, |
860 | 0 | " DW_DLE_RNGLISTS_ERROR " |
861 | 0 | "The end offset to " |
862 | 0 | "dwarf_get_rnglist_rle() is smaller than " |
863 | 0 | "the entry offset! Corrupt data"); |
864 | 0 | return DW_DLV_ERROR; |
865 | 0 | } |
866 | 4.86k | if ((entry_offset +1) > endoffset) { |
867 | | /* The read_single_rle_entry call will need |
868 | | at least 1 byte as it reads at least one |
869 | | ULEB */ |
870 | 0 | dwarfstring m; |
871 | 0 | dwarfstring_constructor(&m); |
872 | 0 | dwarfstring_append_printf_u(&m, |
873 | 0 | " DW_DLE_RNGLISTS_ERROR " |
874 | 0 | "The entry offset+1 (%lu) " |
875 | 0 | "dwarf_get_rnglist_rle() is too close to the" |
876 | 0 | " end",entry_offset+1); |
877 | 0 | dwarfstring_append_printf_u(&m, |
878 | 0 | " of the offset of the end of the entry (%lu)" |
879 | 0 | " Apparently corrupt Dwarf",endoffset); |
880 | 0 | _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR, |
881 | 0 | dwarfstring_string(&m)); |
882 | 0 | dwarfstring_destructor(&m); |
883 | 0 | return DW_DLV_ERROR; |
884 | 0 | } |
885 | 4.86k | data = dbg->de_debug_rnglists.dss_data + |
886 | 4.86k | entry_offset; |
887 | 4.86k | enddata = dbg->de_debug_rnglists.dss_data + |
888 | 4.86k | endoffset; |
889 | | |
890 | 4.86k | con = dbg->de_rnglists_context[contextnumber]; |
891 | 4.86k | address_size = con->rc_address_size; |
892 | 4.86k | res = read_single_rle_entry(dbg, |
893 | 4.86k | data,entry_offset,enddata, |
894 | 4.86k | address_size,entrylen, |
895 | 4.86k | entry_kind, entry_operand1, entry_operand2, |
896 | 4.86k | error); |
897 | 4.86k | return res; |
898 | 4.86k | } |
899 | | |
900 | | static int |
901 | | _dwarf_which_rnglists_context(Dwarf_Debug dbg, |
902 | | Dwarf_CU_Context ctx, |
903 | | Dwarf_Unsigned rnglist_offset, |
904 | | Dwarf_Unsigned *index, |
905 | | Dwarf_Error *error) |
906 | 0 | { |
907 | 0 | Dwarf_Unsigned count; |
908 | 0 | Dwarf_Rnglists_Context *array; |
909 | 0 | Dwarf_Unsigned i = 0; |
910 | |
|
911 | 0 | array = dbg->de_rnglists_context; |
912 | 0 | count = dbg->de_rnglists_context_count; |
913 | | /* Using the slow way, a simple linear search. */ |
914 | 0 | if (!ctx->cc_rnglists_base_present) { |
915 | | /* We look at the location of each rnglist context |
916 | | to find one with the offset the DIE gave us. */ |
917 | 0 | for ( i = 0 ; i < count; ++i) { |
918 | 0 | Dwarf_Rnglists_Context rcx = array[i]; |
919 | 0 | Dwarf_Unsigned rcxoff = rcx->rc_header_offset; |
920 | 0 | Dwarf_Unsigned rcxend = rcxoff + |
921 | 0 | rcx->rc_length; |
922 | |
|
923 | 0 | if (rnglist_offset < rcxoff){ |
924 | 0 | continue; |
925 | 0 | } |
926 | 0 | if (rnglist_offset < rcxend ){ |
927 | 0 | *index = i; |
928 | 0 | return DW_DLV_OK; |
929 | 0 | } |
930 | 0 | } |
931 | 0 | { |
932 | 0 | dwarfstring m; |
933 | |
|
934 | 0 | dwarfstring_constructor(&m); |
935 | 0 | dwarfstring_append_printf_u(&m, |
936 | 0 | "DW_DLE_RNGLISTS_ERROR: rnglist ran off end " |
937 | 0 | " finding target offset of" |
938 | 0 | " 0x%" DW_PR_XZEROS DW_PR_DUx ,rnglist_offset); |
939 | 0 | dwarfstring_append(&m, |
940 | 0 | " Not found anywhere in .debug_rnglists " |
941 | 0 | "data. Corrupted data?"); |
942 | 0 | _dwarf_error_string(dbg,error, |
943 | 0 | DW_DLE_RNGLISTS_ERROR, |
944 | 0 | dwarfstring_string(&m)); |
945 | 0 | dwarfstring_destructor(&m); |
946 | 0 | return DW_DLV_ERROR; |
947 | 0 | } |
948 | 0 | } else { |
949 | | /* We have a DW_AT_rnglists_base (cc_rangelists_base), |
950 | | let's use it. */ |
951 | 0 | Dwarf_Unsigned lookfor = 0;; |
952 | |
|
953 | 0 | lookfor = ctx->cc_rnglists_base; |
954 | 0 | for ( i = 0 ; i < count; ++i) { |
955 | 0 | dwarfstring m; |
956 | |
|
957 | 0 | Dwarf_Rnglists_Context rcx = array[i]; |
958 | 0 | if (rcx->rc_offsets_off_in_sect == lookfor){ |
959 | 0 | *index = i; |
960 | 0 | return DW_DLV_OK; |
961 | 0 | } |
962 | 0 | if (rcx->rc_offsets_off_in_sect < lookfor){ |
963 | 0 | continue; |
964 | 0 | } |
965 | | |
966 | 0 | dwarfstring_constructor(&m); |
967 | 0 | dwarfstring_append_printf_u(&m, |
968 | 0 | "DW_DLE_RNGLISTS_ERROR: rnglists base of " |
969 | 0 | " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); |
970 | 0 | dwarfstring_append_printf_u(&m, |
971 | 0 | " was not found though we are now at base " |
972 | 0 | " 0x%" DW_PR_XZEROS DW_PR_DUx , |
973 | 0 | rcx->rc_offsets_off_in_sect); |
974 | 0 | _dwarf_error_string(dbg,error, |
975 | 0 | DW_DLE_RNGLISTS_ERROR, |
976 | 0 | dwarfstring_string(&m)); |
977 | 0 | dwarfstring_destructor(&m); |
978 | 0 | return DW_DLV_ERROR; |
979 | 0 | } |
980 | 0 | { |
981 | 0 | dwarfstring m; |
982 | |
|
983 | 0 | dwarfstring_constructor(&m); |
984 | 0 | dwarfstring_append_printf_u(&m, |
985 | 0 | "DW_DLE_RNGLISTS_ERROR: rnglist base of " |
986 | 0 | " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); |
987 | 0 | dwarfstring_append(&m, |
988 | 0 | " was not found anywhere in .debug_rnglists " |
989 | 0 | "data. Corrupted data?"); |
990 | 0 | _dwarf_error_string(dbg,error, |
991 | 0 | DW_DLE_RNGLISTS_ERROR, |
992 | 0 | dwarfstring_string(&m)); |
993 | 0 | dwarfstring_destructor(&m); |
994 | 0 | return DW_DLV_ERROR; |
995 | 0 | } |
996 | 0 | } |
997 | | /* ASSERT: This line cannot be reached. */ |
998 | 0 | } |
999 | | |
1000 | | void |
1001 | | dwarf_dealloc_rnglists_head(Dwarf_Rnglists_Head h) |
1002 | 0 | { |
1003 | 0 | Dwarf_Debug dbg = 0; |
1004 | |
|
1005 | 0 | if (!h || !h->rh_dbg || h->rh_magic != RNGLISTS_MAGIC) { |
1006 | 0 | return; |
1007 | 0 | } |
1008 | 0 | dbg = h->rh_dbg; |
1009 | 0 | h->rh_magic = 0; |
1010 | 0 | dwarf_dealloc(dbg,h,DW_DLA_RNGLISTS_HEAD); |
1011 | 0 | return; |
1012 | 0 | } |
1013 | | |
1014 | | /* Caller will eventually free as appropriate. */ |
1015 | | static int |
1016 | | alloc_rle_and_append_to_list(Dwarf_Debug dbg, |
1017 | | Dwarf_Rnglists_Head rctx, |
1018 | | Dwarf_Rnglists_Entry *e_out, |
1019 | | Dwarf_Error *error) |
1020 | 0 | { |
1021 | 0 | Dwarf_Rnglists_Entry e = 0; |
1022 | |
|
1023 | 0 | e = malloc(sizeof(struct Dwarf_Rnglists_Entry_s)); |
1024 | 0 | if (!e) { |
1025 | 0 | _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, |
1026 | 0 | "DW_DLE_ALLOC_FAIL: Out of memory in " |
1027 | 0 | "building list of rnglists entries on a DIE."); |
1028 | 0 | return DW_DLV_ERROR; |
1029 | 0 | } |
1030 | 0 | memset(e,0,sizeof(struct Dwarf_Rnglists_Entry_s)); |
1031 | 0 | if (rctx->rh_first) { |
1032 | 0 | rctx->rh_last->rle_next = e; |
1033 | 0 | rctx->rh_last = e; |
1034 | 0 | } else { |
1035 | 0 | rctx->rh_first = e; |
1036 | 0 | rctx->rh_last = e; |
1037 | 0 | } |
1038 | 0 | rctx->rh_count++; |
1039 | 0 | *e_out = e; |
1040 | 0 | return DW_DLV_OK; |
1041 | 0 | } |
1042 | | |
1043 | | /* Read the group of rangelists entries, and |
1044 | | finally build an array of Dwarf_Rnglists_Entry |
1045 | | records. Attach to rctx here. |
1046 | | Since on error the caller will destruct the rctx |
1047 | | and we ensure to attach allocations there |
1048 | | the caller will destruct the allocations here |
1049 | | in case we return DW_DLV_ERROR*/ |
1050 | | static int |
1051 | | build_array_of_rle(Dwarf_Debug dbg, |
1052 | | Dwarf_Rnglists_Head rctx, |
1053 | | Dwarf_Error *error) |
1054 | 0 | { |
1055 | 0 | int res = 0; |
1056 | 0 | Dwarf_Small * data = rctx->rh_rlepointer; |
1057 | 0 | Dwarf_Unsigned dataoffset = rctx->rh_rlearea_offset; |
1058 | 0 | Dwarf_Small *enddata = rctx->rh_end_data_area; |
1059 | 0 | unsigned address_size = rctx->rh_address_size; |
1060 | 0 | Dwarf_Unsigned bytescounttotal= 0; |
1061 | 0 | Dwarf_Unsigned latestbaseaddr = 0; |
1062 | 0 | Dwarf_Bool foundbaseaddr = FALSE; |
1063 | 0 | int done = FALSE; |
1064 | 0 | Dwarf_Bool no_debug_addr_available = FALSE; |
1065 | |
|
1066 | 0 | if (rctx->rh_cu_base_address_present) { |
1067 | | /* The CU DIE had DW_AT_low_pc |
1068 | | and it is a base address. */ |
1069 | 0 | latestbaseaddr = rctx->rh_cu_base_address; |
1070 | 0 | foundbaseaddr = TRUE; |
1071 | 0 | } |
1072 | 0 | for ( ; !done ; ) { |
1073 | 0 | unsigned entrylen = 0; |
1074 | 0 | unsigned code = 0; |
1075 | 0 | Dwarf_Unsigned val1 = 0; |
1076 | 0 | Dwarf_Unsigned val2 = 0; |
1077 | 0 | Dwarf_Addr addr1= 0; |
1078 | 0 | Dwarf_Addr addr2 = 0; |
1079 | 0 | Dwarf_Rnglists_Entry e = 0; |
1080 | |
|
1081 | 0 | res = read_single_rle_entry(dbg, |
1082 | 0 | data,dataoffset, enddata, |
1083 | 0 | address_size,&entrylen, |
1084 | 0 | &code,&val1, &val2,error); |
1085 | 0 | if (res != DW_DLV_OK) { |
1086 | 0 | return res; |
1087 | 0 | } |
1088 | 0 | res = alloc_rle_and_append_to_list(dbg,rctx,&e,error); |
1089 | 0 | if (res != DW_DLV_OK) { |
1090 | 0 | return res; |
1091 | 0 | } |
1092 | 0 | e->rle_code = code, |
1093 | 0 | e->rle_entrylen = entrylen; |
1094 | 0 | e->rle_raw1 = val1; |
1095 | 0 | e->rle_raw2 = val2; |
1096 | 0 | bytescounttotal += entrylen; |
1097 | 0 | data += entrylen; |
1098 | 0 | if (code == DW_RLE_end_of_list) { |
1099 | 0 | done = TRUE; |
1100 | 0 | break; |
1101 | 0 | } |
1102 | 0 | switch(code) { |
1103 | 0 | case DW_RLE_base_addressx: |
1104 | 0 | if (no_debug_addr_available) { |
1105 | 0 | res = DW_DLV_NO_ENTRY; |
1106 | 0 | } else { |
1107 | 0 | res = _dwarf_look_in_local_and_tied_by_index( |
1108 | 0 | dbg,rctx->rh_context,val1,&addr1, |
1109 | 0 | error); |
1110 | 0 | } |
1111 | 0 | if (res != DW_DLV_OK) { |
1112 | 0 | no_debug_addr_available = TRUE; |
1113 | 0 | e->rle_index_failed = TRUE; |
1114 | 0 | e->rle_cooked1 = 0; |
1115 | 0 | foundbaseaddr = FALSE; |
1116 | 0 | } else { |
1117 | 0 | foundbaseaddr = TRUE; |
1118 | 0 | e->rle_cooked1 = addr1; |
1119 | 0 | latestbaseaddr = addr1; |
1120 | 0 | } |
1121 | 0 | break; |
1122 | 0 | case DW_RLE_startx_endx: |
1123 | 0 | if (no_debug_addr_available) { |
1124 | 0 | res = DW_DLV_NO_ENTRY; |
1125 | 0 | } else { |
1126 | 0 | res = _dwarf_look_in_local_and_tied_by_index( |
1127 | 0 | dbg,rctx->rh_context,val1,&addr1, |
1128 | 0 | error); |
1129 | 0 | } |
1130 | 0 | if (res != DW_DLV_OK) { |
1131 | 0 | no_debug_addr_available = TRUE; |
1132 | 0 | e->rle_index_failed = TRUE; |
1133 | 0 | e->rle_cooked1 = 0; |
1134 | 0 | } else { |
1135 | 0 | e->rle_cooked1 = addr1; |
1136 | 0 | } |
1137 | 0 | if (no_debug_addr_available) { |
1138 | 0 | res = DW_DLV_NO_ENTRY; |
1139 | 0 | } else { |
1140 | 0 | res = _dwarf_look_in_local_and_tied_by_index( |
1141 | 0 | dbg,rctx->rh_context,val2,&addr2, |
1142 | 0 | error); |
1143 | 0 | } |
1144 | 0 | if (res != DW_DLV_OK) { |
1145 | 0 | no_debug_addr_available = TRUE; |
1146 | 0 | e->rle_index_failed = TRUE; |
1147 | 0 | e->rle_cooked2 = 0; |
1148 | 0 | return res; |
1149 | 0 | } else { |
1150 | 0 | e->rle_cooked2 = addr2; |
1151 | 0 | } |
1152 | 0 | break; |
1153 | 0 | case DW_RLE_startx_length: |
1154 | 0 | if (no_debug_addr_available) { |
1155 | 0 | res = DW_DLV_NO_ENTRY; |
1156 | 0 | } else { |
1157 | 0 | res = _dwarf_look_in_local_and_tied_by_index( |
1158 | 0 | dbg,rctx->rh_context,val1,&addr1, |
1159 | 0 | error); |
1160 | 0 | } |
1161 | 0 | if (res != DW_DLV_OK) { |
1162 | 0 | no_debug_addr_available = TRUE; |
1163 | 0 | e->rle_index_failed = TRUE; |
1164 | 0 | e->rle_cooked2 = 0; |
1165 | 0 | e->rle_cooked1 = 0; |
1166 | 0 | return res; |
1167 | |
|
1168 | 0 | } else { |
1169 | 0 | e->rle_cooked1 = addr1; |
1170 | 0 | e->rle_cooked2 = val2+addr1; |
1171 | 0 | } |
1172 | 0 | break; |
1173 | 0 | case DW_RLE_offset_pair: |
1174 | 0 | if (foundbaseaddr) { |
1175 | 0 | e->rle_cooked1 = val1+latestbaseaddr; |
1176 | 0 | e->rle_cooked2 = val2+latestbaseaddr; |
1177 | 0 | } else { |
1178 | | /* Well, something failed, could be |
1179 | | missing debug_addr. */ |
1180 | 0 | e->rle_index_failed = TRUE; |
1181 | 0 | e->rle_cooked2 = 0; |
1182 | 0 | e->rle_cooked1 = 0; |
1183 | 0 | } |
1184 | 0 | break; |
1185 | 0 | case DW_RLE_base_address: |
1186 | 0 | foundbaseaddr = TRUE; |
1187 | 0 | latestbaseaddr = val1; |
1188 | 0 | e->rle_cooked1 = val1; |
1189 | 0 | break; |
1190 | 0 | case DW_RLE_start_end: |
1191 | 0 | e->rle_cooked1 = val1; |
1192 | 0 | e->rle_cooked2 = val2; |
1193 | 0 | break; |
1194 | 0 | case DW_RLE_start_length: |
1195 | 0 | e->rle_cooked1 = val1; |
1196 | 0 | e->rle_cooked2 = val2+val1; |
1197 | 0 | break; |
1198 | 0 | default: { |
1199 | 0 | dwarfstring m; |
1200 | |
|
1201 | 0 | dwarfstring_constructor(&m); |
1202 | 0 | dwarfstring_append_printf_u(&m, |
1203 | 0 | " DW_DLE_RNGLISTS_ERROR: " |
1204 | 0 | " The .debug_rnglists " |
1205 | 0 | " rangelist code 0x%x is unknown, " |
1206 | 0 | " DWARF5 is corrupted.",code); |
1207 | 0 | _dwarf_error_string(dbg, error, |
1208 | 0 | DW_DLE_RNGLISTS_ERROR, |
1209 | 0 | dwarfstring_string(&m)); |
1210 | 0 | dwarfstring_destructor(&m); |
1211 | 0 | return DW_DLV_ERROR; |
1212 | 0 | } |
1213 | 0 | } |
1214 | 0 | } |
1215 | 0 | if (rctx->rh_count > 0) { |
1216 | 0 | Dwarf_Rnglists_Entry* array = 0; |
1217 | 0 | Dwarf_Rnglists_Entry cur = 0; |
1218 | 0 | Dwarf_Unsigned i = 0; |
1219 | | |
1220 | | /* Creating an array of pointers. */ |
1221 | 0 | array = (Dwarf_Rnglists_Entry*)malloc( |
1222 | 0 | rctx->rh_count *sizeof(Dwarf_Rnglists_Entry)); |
1223 | 0 | if (!array) { |
1224 | 0 | _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, |
1225 | 0 | "DW_DLE_ALLOC_FAIL: Out of memory in " |
1226 | 0 | "turning list of rnglists entries on a DIE" |
1227 | 0 | "into a pointer array"); |
1228 | 0 | return DW_DLV_ERROR; |
1229 | 0 | } |
1230 | 0 | cur = rctx->rh_first; |
1231 | 0 | for ( ; i < rctx->rh_count; ++i) { |
1232 | 0 | array[i] = cur; |
1233 | 0 | cur = cur->rle_next; |
1234 | 0 | } |
1235 | 0 | rctx->rh_rnglists = array; |
1236 | 0 | rctx->rh_first = 0; |
1237 | 0 | rctx->rh_last = 0; |
1238 | 0 | } |
1239 | 0 | rctx->rh_bytes_total = bytescounttotal; |
1240 | 0 | return DW_DLV_OK; |
1241 | 0 | } |
1242 | | |
1243 | | /* Build a head with all the relevent Entries |
1244 | | attached. |
1245 | | */ |
1246 | | int |
1247 | | dwarf_rnglists_get_rle_head( |
1248 | | Dwarf_Attribute attr, |
1249 | | Dwarf_Half theform, |
1250 | | /* attr_val is either an offset |
1251 | | (theform == DW_FORM_sec_offset) |
1252 | | or an index DW_FORM_rnglistx. */ |
1253 | | Dwarf_Unsigned attr_val, |
1254 | | Dwarf_Rnglists_Head *head_out, |
1255 | | Dwarf_Unsigned *entries_count_out, |
1256 | | Dwarf_Unsigned *global_offset_of_rle_set, |
1257 | | Dwarf_Error *error) |
1258 | 0 | { |
1259 | 0 | int res = 0; |
1260 | 0 | Dwarf_Unsigned rnglists_contextnum = 0; |
1261 | 0 | Dwarf_Small *table_base = 0; |
1262 | 0 | Dwarf_Small *table_entry = 0; |
1263 | 0 | Dwarf_Small *enddata = 0; |
1264 | 0 | Dwarf_Rnglists_Context *array = 0; |
1265 | 0 | Dwarf_Rnglists_Context rctx = 0; |
1266 | 0 | Dwarf_Unsigned entrycount = 0; |
1267 | 0 | unsigned offsetsize = 0; |
1268 | 0 | Dwarf_Unsigned rle_global_offset = 0; |
1269 | 0 | Dwarf_Rnglists_Head lhead = 0; |
1270 | 0 | Dwarf_CU_Context ctx = 0; |
1271 | 0 | struct Dwarf_Rnglists_Head_s shead; |
1272 | 0 | Dwarf_Unsigned offset_in_rnglists = 0; |
1273 | 0 | Dwarf_Debug dbg = 0; |
1274 | 0 | Dwarf_Bool is_rnglistx = FALSE; |
1275 | |
|
1276 | 0 | if (!attr) { |
1277 | 0 | _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, |
1278 | 0 | "DW_DLE_DBG_NULL " |
1279 | 0 | "NULL attribute " |
1280 | 0 | "argument passed to " |
1281 | 0 | "dwarf_rnglists_get_rle_head()"); |
1282 | 0 | return DW_DLV_ERROR; |
1283 | 0 | } |
1284 | 0 | memset(&shead,0,sizeof(shead)); |
1285 | 0 | ctx = attr->ar_cu_context; |
1286 | 0 | dbg = ctx->cc_dbg; |
1287 | 0 | CHECK_DBG(dbg,error, |
1288 | 0 | "dwarf_rnglists_get_rle_head() via attribute"); |
1289 | 0 | array = dbg->de_rnglists_context; |
1290 | 0 | if (theform == DW_FORM_rnglistx) { |
1291 | 0 | is_rnglistx = TRUE; |
1292 | 0 | } |
1293 | | /* ASSERT: the 3 pointers just set are non-null */ |
1294 | | /* the context cc_rnglists_base gives the offset |
1295 | | of the array. of offsets (if cc_rnglists_base_present) */ |
1296 | 0 | offset_in_rnglists = attr_val; |
1297 | 0 | if (is_rnglistx) { |
1298 | 0 | if (ctx->cc_rnglists_base_present) { |
1299 | 0 | offset_in_rnglists = ctx->cc_rnglists_base; |
1300 | |
|
1301 | 0 | } else { |
1302 | | /* FIXME: check in tied file for a cc_rnglists_base */ |
1303 | 0 | dwarfstring m; |
1304 | |
|
1305 | 0 | dwarfstring_constructor(&m); |
1306 | 0 | dwarfstring_append_printf_u(&m, |
1307 | 0 | "DW_DLE_RNGLISTS_ERROR: rnglists table index of" |
1308 | 0 | " %u" ,attr_val); |
1309 | 0 | dwarfstring_append(&m, |
1310 | 0 | " is unusable unless it is in a tied file." |
1311 | 0 | " Possibly libdwarf is incomplete.FIXME"); |
1312 | 0 | _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, |
1313 | 0 | dwarfstring_string(&m)); |
1314 | 0 | dwarfstring_destructor(&m); |
1315 | 0 | return DW_DLV_ERROR; |
1316 | 0 | } |
1317 | 0 | } else { |
1318 | 0 | offset_in_rnglists = attr_val; |
1319 | 0 | } |
1320 | 0 | res = _dwarf_which_rnglists_context(dbg,ctx, |
1321 | 0 | offset_in_rnglists, |
1322 | 0 | &rnglists_contextnum,error); |
1323 | 0 | if (res != DW_DLV_OK) { |
1324 | 0 | return res; |
1325 | 0 | } |
1326 | 0 | rctx = array[rnglists_contextnum]; |
1327 | 0 | table_base = rctx->rc_offsets_array; |
1328 | 0 | entrycount = rctx->rc_offset_entry_count; |
1329 | 0 | offsetsize = rctx->rc_offset_size; |
1330 | 0 | enddata = rctx->rc_endaddr; |
1331 | |
|
1332 | 0 | if (is_rnglistx && attr_val >= entrycount) { |
1333 | 0 | dwarfstring m; |
1334 | |
|
1335 | 0 | dwarfstring_constructor(&m); |
1336 | 0 | dwarfstring_append_printf_u(&m, |
1337 | 0 | "DW_DLE_RNGLISTS_ERROR: rnglists table index of" |
1338 | 0 | " %u" ,attr_val); |
1339 | 0 | dwarfstring_append_printf_u(&m, |
1340 | 0 | " too large for table of %u " |
1341 | 0 | "entries.",entrycount); |
1342 | 0 | _dwarf_error_string(dbg,error, |
1343 | 0 | DW_DLE_RNGLISTS_ERROR, |
1344 | 0 | dwarfstring_string(&m)); |
1345 | 0 | dwarfstring_destructor(&m); |
1346 | 0 | return DW_DLV_ERROR; |
1347 | 0 | } |
1348 | 0 | shead.rh_context = ctx; |
1349 | 0 | shead.rh_magic = RNGLISTS_MAGIC; |
1350 | 0 | shead.rh_localcontext = rctx; |
1351 | 0 | shead.rh_index = rnglists_contextnum; |
1352 | 0 | shead.rh_version = rctx->rc_version; |
1353 | 0 | shead.rh_offset_size = offsetsize; |
1354 | 0 | shead.rh_address_size = rctx->rc_address_size; |
1355 | 0 | shead.rh_segment_selector_size = |
1356 | 0 | rctx->rc_segment_selector_size; |
1357 | | |
1358 | | /* DW_AT_rnglists_base from CU */ |
1359 | 0 | shead.rh_at_rnglists_base_present = |
1360 | 0 | ctx->cc_rnglists_base_present; |
1361 | 0 | shead.rh_at_rnglists_base = ctx->cc_rnglists_base; |
1362 | | |
1363 | | /* DW_AT_low_pc, if present. From CU */ |
1364 | 0 | shead.rh_cu_base_address_present = ctx->cc_low_pc_present; |
1365 | 0 | shead.rh_cu_base_address = ctx->cc_low_pc; |
1366 | | |
1367 | | /* base address DW_AT_addr_base of our part of |
1368 | | .debug_addr, from CU */ |
1369 | 0 | shead.rh_cu_addr_base = ctx->cc_addr_base; |
1370 | 0 | shead.rh_cu_addr_base_present = ctx->cc_addr_base_present; |
1371 | 0 | if (is_rnglistx) { |
1372 | 0 | Dwarf_Unsigned table_entryval = 0; |
1373 | |
|
1374 | 0 | table_entry = attr_val*offsetsize + table_base; |
1375 | | /* No malloc here yet so no leak if the macro returns |
1376 | | DW_DLV_ERROR */ |
1377 | 0 | READ_UNALIGNED_CK(dbg,table_entryval, Dwarf_Unsigned, |
1378 | 0 | table_entry,offsetsize,error,enddata); |
1379 | 0 | rle_global_offset = rctx->rc_offsets_off_in_sect + |
1380 | 0 | table_entryval; |
1381 | 0 | } else { |
1382 | 0 | rle_global_offset = attr_val; |
1383 | 0 | } |
1384 | | |
1385 | 0 | shead.rh_end_data_area = enddata; |
1386 | 0 | shead.rh_rlearea_offset = rle_global_offset; |
1387 | 0 | shead.rh_rlepointer = rle_global_offset + |
1388 | 0 | dbg->de_debug_rnglists.dss_data; |
1389 | 0 | lhead = (Dwarf_Rnglists_Head) |
1390 | 0 | _dwarf_get_alloc(dbg,DW_DLA_RNGLISTS_HEAD,1); |
1391 | 0 | if (!lhead) { |
1392 | 0 | _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, |
1393 | 0 | "Allocating a Dwarf_Rnglists_Head struct fails" |
1394 | 0 | " in libdwarf function " |
1395 | 0 | "dwarf_rnglists_index_get_rle_head()"); |
1396 | 0 | return DW_DLV_ERROR; |
1397 | 0 | } |
1398 | 0 | shead.rh_dbg = dbg; |
1399 | 0 | *lhead = shead; |
1400 | 0 | res = build_array_of_rle(dbg,lhead,error); |
1401 | 0 | if (res != DW_DLV_OK) { |
1402 | 0 | dwarf_dealloc(dbg,lhead,DW_DLA_RNGLISTS_HEAD); |
1403 | 0 | return res; |
1404 | 0 | } |
1405 | 0 | if (global_offset_of_rle_set) { |
1406 | 0 | *global_offset_of_rle_set = rle_global_offset; |
1407 | 0 | } |
1408 | | /* Caller needs the head pointer else there will be leaks. */ |
1409 | 0 | *head_out = lhead; |
1410 | 0 | if (entries_count_out) { |
1411 | 0 | *entries_count_out = lhead->rh_count; |
1412 | 0 | } |
1413 | 0 | return DW_DLV_OK; |
1414 | 0 | } |
1415 | | |
1416 | | /* As of 18 Aug 2020 |
1417 | | this ignores null pointer inputs for the various |
1418 | | pointers-returning-values (rle_value_out etc) |
1419 | | for the convenience of callers. */ |
1420 | | int |
1421 | | dwarf_get_rnglists_entry_fields_a( |
1422 | | Dwarf_Rnglists_Head head, |
1423 | | Dwarf_Unsigned entrynum, |
1424 | | unsigned *entrylen, |
1425 | | unsigned *rle_value_out, |
1426 | | Dwarf_Unsigned *raw1, |
1427 | | Dwarf_Unsigned *raw2, |
1428 | | Dwarf_Bool *debug_addr_unavailable, |
1429 | | Dwarf_Unsigned *cooked1, |
1430 | | Dwarf_Unsigned *cooked2, |
1431 | | Dwarf_Error *error) |
1432 | 0 | { |
1433 | 0 | Dwarf_Rnglists_Entry e = 0; |
1434 | |
|
1435 | 0 | if (!head || !head->rh_dbg || head->rh_magic != RNGLISTS_MAGIC) { |
1436 | 0 | _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, |
1437 | 0 | "DW_DLE_DBG_NULL " |
1438 | 0 | "NULL or invalid Dwarf_Rnglists_Head " |
1439 | 0 | "argument passed to " |
1440 | 0 | "dwarf_get_rnglists_entry_fields_a()"); |
1441 | 0 | return DW_DLV_ERROR; |
1442 | 0 | } |
1443 | 0 | if (entrynum >= head->rh_count) { |
1444 | 0 | return DW_DLV_NO_ENTRY; |
1445 | 0 | } |
1446 | 0 | e = head->rh_rnglists[entrynum]; |
1447 | 0 | if (entrylen) { |
1448 | 0 | *entrylen = e->rle_entrylen; |
1449 | 0 | } |
1450 | 0 | if (rle_value_out) { |
1451 | 0 | *rle_value_out = e->rle_code; |
1452 | 0 | } |
1453 | 0 | if (raw1) { |
1454 | 0 | *raw1 = e->rle_raw1; |
1455 | 0 | } |
1456 | 0 | if (raw2) { |
1457 | 0 | *raw2 = e->rle_raw2; |
1458 | 0 | } |
1459 | 0 | if (debug_addr_unavailable) { |
1460 | 0 | *debug_addr_unavailable = e->rle_index_failed; |
1461 | 0 | } |
1462 | 0 | if (cooked1) { |
1463 | 0 | *cooked1 = e->rle_cooked1; |
1464 | 0 | } |
1465 | 0 | if (cooked2) { |
1466 | 0 | *cooked2 = e->rle_cooked2; |
1467 | 0 | } |
1468 | 0 | return DW_DLV_OK; |
1469 | 0 | } |
1470 | | |
1471 | | /* Deals with both fully and partially build head */ |
1472 | | static void |
1473 | | _dwarf_free_rnglists_head(Dwarf_Rnglists_Head head) |
1474 | 0 | { |
1475 | 0 | if (head->rh_first) { |
1476 | | /* partially built head. */ |
1477 | | /* ASSERT: rh_rnglists is NULL */ |
1478 | 0 | Dwarf_Rnglists_Entry cur = head->rh_first; |
1479 | 0 | Dwarf_Rnglists_Entry next = 0; |
1480 | |
|
1481 | 0 | for ( ; cur ; cur = next) { |
1482 | 0 | next = cur->rle_next; |
1483 | 0 | free(cur); |
1484 | 0 | } |
1485 | 0 | head->rh_first = 0; |
1486 | 0 | head->rh_last = 0; |
1487 | 0 | head->rh_count = 0; |
1488 | 0 | } else { |
1489 | | /* ASSERT: rh_first and rh_last are NULL */ |
1490 | | /* fully built head. */ |
1491 | 0 | Dwarf_Unsigned i = 0; |
1492 | | |
1493 | | /* Deal with the array form. */ |
1494 | 0 | for ( ; i < head->rh_count; ++i) { |
1495 | 0 | free(head->rh_rnglists[i]); |
1496 | 0 | } |
1497 | 0 | free(head->rh_rnglists); |
1498 | 0 | head->rh_rnglists = 0; |
1499 | 0 | } |
1500 | 0 | } |
1501 | | |
1502 | | void |
1503 | | _dwarf_rnglists_head_destructor(void *head) |
1504 | 0 | { |
1505 | 0 | Dwarf_Rnglists_Head h = head; |
1506 | |
|
1507 | 0 | _dwarf_free_rnglists_head(h); |
1508 | 0 | } |