1 /*
2 Copyright (C) 2014-2019 David Anderson. All Rights Reserved.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of version 2.1 of the GNU Lesser General Public License
6 as published by the Free Software Foundation.
7
8 This program is distributed in the hope that it would be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
12 Further, this software is distributed without any warranty that it is
13 free of the rightful claim of any third person regarding infringement
14 or the like. Any license provided herein, whether implied or
15 otherwise, applies only to this software file. Patent licenses, if
16 any, provided herein do not apply to combinations of this program with
17 other software, or any other product whatsoever.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this program; if not, write the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
22 USA.
23
24 */
25
26 /* The file and functions have 'xu' because
27 the .debug_cu_index and .debug_tu_index
28 sections have the same layout and this deals with both.
29
30 This is DebugFission, part of DWARF5.
31
32 It allows fast section access in a .dwp object file
33 with debug-information to locate offsets
34 within and between sections.
35
36 See the DWARF5 Standard: section 7.3.5 and
37 examples in Appendix F.3.
38
39 A note about the index field from the index table.
40 See DWARF5 7.5.3.5.
41 The index table array index values are [1,S)
42 These value ae used to call functions requestiong
43 values from the offset table and size table.
44
45 Inside the code in this file we subtract 1 and use
46 0 origin as that is how we arranged the
47 table access here.
48 A zero in the index table is an unused signature
49 table signature and unused index.
50
51 By subtracting one and arranging things properly
52 in the offset table and size table we can refer
53 to the tables in an identical simple fashion
54 These tables are thus U rows and N columns.
55 Technically the Offset table physically
56 row zero is a separate set of numbers translating
57 the column number to a DW_SECT* value
58 so callers can request specific bases(offsets)
59 and sizes from the offset and size tables.
60 But we change things a little internally so both
61 tables look zero-origin.
62 */
63 #include "config.h"
64 #include <stdio.h>
65 #ifdef HAVE_STDLIB_H
66 #include <stdlib.h>
67 #endif /* HAVE_STDLIB_H */
68 #include "dwarf_incl.h"
69 #include "dwarf_alloc.h"
70 #include "dwarf_error.h"
71 #include "dwarf_util.h"
72 #include "dwarf_xu_index.h"
73 #include "dwarfstring.h"
74
75 #define HASHSIGNATURELEN 8
76 #define LEN32BIT 4
77
78 #define TRUE 1
79 #define FALSE 0
80
81 /* The following actually assumes (as used here)
82 that t is 8 bytes (integer) while s is
83 also 8 bytes (Dwarf_Sig8 struct). */
84 #ifdef WORDS_BIGENDIAN
85 #define ASNAR(t,s,l) \
86 do { \
87 unsigned tbyte = sizeof(t) - l; \
88 if (sizeof(t) < l) { \
89 _dwarf_error(dbg,error,DW_DLE_XU_HASH_INDEX_ERROR); \
90 return DW_DLV_ERROR; \
91 } \
92 t = 0; \
93 dbg->de_copy_word(((char *)&t)+tbyte ,&s[0],l);\
94 } while (0)
95 #else /* LITTLE ENDIAN */
96 #define ASNAR(t,s,l) \
97 do { \
98 t = 0; \
99 if (sizeof(t) < l) { \
100 _dwarf_error(dbg,error,DW_DLE_XU_HASH_INDEX_ERROR); \
101 return DW_DLV_ERROR; \
102 } \
103 dbg->de_copy_word(&t,&s[0],l); \
104 } while (0)
105 #endif /* end LITTLE- BIG-ENDIAN */
106
107 /* zerohashkey used as all-zero-bits for comparison. */
108 static const Dwarf_Sig8 zerohashkey;
109
110 #if 0
111 static void
112 dump_bytes(char * msg,Dwarf_Small * start, long len)
113 {
114 Dwarf_Small *end = start + len;
115 Dwarf_Small *cur = start;
116
117 printf("%s ",msg);
118 for (; cur < end; cur++) {
119 printf("%02x ", *cur);
120 }
121 printf("\n");
122 }
123 #endif
124
125 /* Precondition: headerline_offset + N*32 is within
126 the section. */
127 static int
fill_in_offsets_headerline(Dwarf_Debug dbg,Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned headerline_offset,Dwarf_Unsigned num_sects,Dwarf_Error * err)128 fill_in_offsets_headerline(Dwarf_Debug dbg,
129 Dwarf_Xu_Index_Header xuhdr,
130 Dwarf_Unsigned headerline_offset,
131 Dwarf_Unsigned num_sects,
132 Dwarf_Error *err)
133 {
134 Dwarf_Small *section_start = xuhdr->gx_section_data;
135 Dwarf_Small *section_end = xuhdr->gx_section_data+
136 xuhdr->gx_section_length;
137 Dwarf_Small *data = 0;
138 unsigned i = 0;
139
140 data = section_start +headerline_offset;
141 for( ; i < num_sects ; ++i) {
142 Dwarf_Unsigned v = 0;
143
144 READ_UNALIGNED_CK(dbg,v, Dwarf_Unsigned,
145 data,LEN32BIT,
146 err,section_end);
147 data += LEN32BIT;
148 if (v > DW_SECT_RNGLISTS) {
149 dwarfstring s;
150
151 dwarfstring_constructor(&s);
152 dwarfstring_append_printf_u(&s,
153 "ERROR: DW_DLE_XU_NAME_COL_ERROR The "
154 "section number of %u ",v);
155 dwarfstring_append(&s," is too high. "
156 "There sections 1-8 are listed in "
157 "DWARF5 table 7.1.");
158 _dwarf_error_string(dbg, err, DW_DLE_XU_NAME_COL_ERROR,
159 dwarfstring_string(&s));
160 dwarfstring_destructor(&s);
161 return DW_DLV_ERROR;
162 }
163 xuhdr->gx_section_id[i] = v;
164 }
165 return DW_DLV_OK;
166 }
167
168
169 /* Read in a cu or tu section and
170 return overview information.
171
172 For libdwarf-internal lookups
173 dwarf_init*() calls
174 dwarf_get_xu_index_header() when
175 the object file is opened and
176 dwarf_xu_header_free() is called
177 by dwarf_finish(), there is
178 no need for users to do this.
179
180 If one wants to call the various
181 tu/cu functions oneself (possibly to print the
182 .debug_cu_index or .debug_tu_index sections).
183 then you will need to call dwarf_get_xu_index_header()
184 and eventually dwarf_xu_header_free().
185
186 The libdwarf-internal data is kept in Dwarf_Debug
187 fields de_cu_hashindex_data/de_tu_hashindex_data.
188 */
189 int
dwarf_get_xu_index_header(Dwarf_Debug dbg,const char * section_type,Dwarf_Xu_Index_Header * xuptr,Dwarf_Unsigned * version,Dwarf_Unsigned * number_of_columns,Dwarf_Unsigned * number_of_CUs,Dwarf_Unsigned * number_of_slots,const char ** section_name,Dwarf_Error * error)190 dwarf_get_xu_index_header(Dwarf_Debug dbg,
191 /* Pass in section_type "tu" or "cu" */
192 const char * section_type,
193 Dwarf_Xu_Index_Header * xuptr,
194 Dwarf_Unsigned * version,
195 Dwarf_Unsigned * number_of_columns, /* L section count.*/
196 Dwarf_Unsigned * number_of_CUs, /* U unit count */
197 Dwarf_Unsigned * number_of_slots, /* S slot count */
198 /* Standard says S > U DWARF5 sec 7.3.5.3 */
199 const char ** section_name,
200 Dwarf_Error * error)
201 {
202 Dwarf_Xu_Index_Header indexptr = 0;
203 int res = DW_DLV_ERROR;
204 struct Dwarf_Section_s *sect = 0;
205 Dwarf_Unsigned local_version = 0;
206 Dwarf_Unsigned num_secs = 0;
207 Dwarf_Unsigned num_CUs = 0;
208 Dwarf_Unsigned num_slots = 0;
209 Dwarf_Small *data = 0;
210 Dwarf_Unsigned tables_end_offset = 0;
211 Dwarf_Unsigned hash_tab_offset = 0;
212 Dwarf_Unsigned indexes_tab_offset = 0;
213 Dwarf_Unsigned section_offsets_tab_offset = 0;
214 Dwarf_Unsigned section_offsets_headerline_offset = 0;
215 Dwarf_Unsigned section_sizes_tab_offset = 0;
216 unsigned datalen32 = LEN32BIT;
217 Dwarf_Small *section_end = 0;
218
219 if (!strcmp(section_type,"cu") ) {
220 sect = &dbg->de_debug_cu_index;
221 } else if (!strcmp(section_type,"tu") ) {
222 sect = &dbg->de_debug_tu_index;
223 } else {
224 _dwarf_error(dbg, error, DW_DLE_XU_TYPE_ARG_ERROR);
225 return DW_DLV_ERROR;
226 }
227 if (!sect->dss_size) {
228 return DW_DLV_NO_ENTRY;
229 }
230 if (!sect->dss_data) {
231 res = _dwarf_load_section(dbg, sect,error);
232 if (res != DW_DLV_OK) {
233 return res;
234 }
235 }
236
237 data = sect->dss_data;
238 section_end = data + sect->dss_size;
239
240 if (sect->dss_size < (4*datalen32) ) {
241 dwarfstring m;
242
243 dwarfstring_constructor(&m);
244 dwarfstring_append_printf_s(&m,
245 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION: "
246 "The size of the %s ",(char *)section_type);
247 dwarfstring_append_printf_u(&m,
248 " is just %u bytes, much to small to be "
249 " a correct section",sect->dss_size);
250 _dwarf_error_string(dbg, error,
251 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
252 dwarfstring_string(&m));
253 dwarfstring_destructor(&m);
254 return DW_DLV_ERROR;
255 }
256 READ_UNALIGNED_CK(dbg,local_version, Dwarf_Unsigned,
257 data,datalen32,
258 error,section_end);
259 data += datalen32;
260
261 /* reading N */
262 READ_UNALIGNED_CK(dbg,num_secs, Dwarf_Unsigned,
263 data,datalen32,
264 error,section_end);
265 data += datalen32;
266 /* reading U */
267 READ_UNALIGNED_CK(dbg,num_CUs, Dwarf_Unsigned,
268 data,datalen32,
269 error,section_end);
270 data += datalen32;
271 /* reading S */
272 READ_UNALIGNED_CK(dbg,num_slots, Dwarf_Unsigned,
273 data,datalen32,
274 error,section_end);
275 hash_tab_offset = datalen32*4;
276 indexes_tab_offset = hash_tab_offset +
277 (num_slots * HASHSIGNATURELEN);
278 /* Look for corrupt section data. */
279 if (num_slots > sect->dss_size) {
280 dwarfstring m;
281
282 dwarfstring_constructor(&m);
283 dwarfstring_append_printf_s(&m,
284 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION: "
285 "The size of the %s ",(char *)section_type);
286 dwarfstring_append_printf_u(&m,
287 " is just %u bytes,",sect->dss_size);
288 dwarfstring_append_printf_u(&m,
289 "while the number of slots (S) is %u. "
290 "which is clearly wrong",num_slots );
291 _dwarf_error_string(dbg, error,
292 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
293 dwarfstring_string(&m));
294 dwarfstring_destructor(&m);
295 return DW_DLV_ERROR;
296 }
297 if ( (4*num_slots) > sect->dss_size) {
298 dwarfstring m;
299
300 dwarfstring_constructor(&m);
301 dwarfstring_append_printf_s(&m,
302 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION: "
303 "The size of the %s ",(char *)section_type);
304 dwarfstring_append_printf_u(&m,
305 " is just %u bytes,",sect->dss_size);
306 dwarfstring_append_printf_u(&m,
307 "while the number of slots bytes (S) is at least %u. "
308 "which is clearly wrong",num_slots*4);
309 _dwarf_error_string(dbg, error,
310 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
311 dwarfstring_string(&m));
312 dwarfstring_destructor(&m);
313 return DW_DLV_ERROR;
314 }
315
316 /* This offset is to 1 row of N columns, each 32bit. */
317 section_offsets_headerline_offset = indexes_tab_offset +
318 (num_slots *datalen32);
319 /* Now we can make the real table part index normally.
320 This offset is to U row of N columns, each 32bit. */
321 section_offsets_tab_offset = section_offsets_headerline_offset
322 + (num_secs*datalen32);
323 if ( num_secs > sect->dss_size) {
324 dwarfstring m;
325
326 dwarfstring_constructor(&m);
327 dwarfstring_append_printf_s(&m,
328 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION: "
329 "The size of the %s ",(char *)section_type);
330 dwarfstring_append_printf_u(&m,
331 " is just %u bytes,",sect->dss_size);
332 dwarfstring_append_printf_u(&m,
333 "while the number of sections/columns (S) is %u. "
334 "which is clearly wrong",num_secs );
335 _dwarf_error_string(dbg, error,
336 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
337 dwarfstring_string(&m));
338 dwarfstring_destructor(&m);
339 return DW_DLV_ERROR;
340 }
341 if ( (datalen32*num_secs) > sect->dss_size) {
342 dwarfstring m;
343
344 dwarfstring_constructor(&m);
345 dwarfstring_append_printf_s(&m,
346 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION: "
347 "The size of the %s ",(char *)section_type);
348 dwarfstring_append_printf_u(&m,
349 " is just %u bytes,",sect->dss_size);
350 dwarfstring_append_printf_u(&m,
351 "while the number of sections/columns bytes (S)"
352 " is at least %u. "
353 "which is clearly wrong",num_secs*4);
354 _dwarf_error_string(dbg, error,
355 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
356 dwarfstring_string(&m));
357 dwarfstring_destructor(&m);
358 return DW_DLV_ERROR;
359 }
360 section_sizes_tab_offset = section_offsets_tab_offset +
361 (num_CUs *num_secs* datalen32) ;
362 tables_end_offset = section_sizes_tab_offset +
363 (num_CUs * num_secs * datalen32);
364 if ( tables_end_offset > sect->dss_size) {
365 /* Something is badly wrong here. */
366 dwarfstring m;
367
368 dwarfstring_constructor(&m);
369 dwarfstring_append_printf_u(&m,"ERROR: "
370 "DW_DLE_ERRONEOUS_XU_INDEX_SECTION as the end offset "
371 "0x%lx is greater than ",tables_end_offset);
372 dwarfstring_append_printf_u(&m,"the section size "
373 "0x%lx.",sect->dss_size);
374 _dwarf_error_string(dbg, error,
375 DW_DLE_ERRONEOUS_XU_INDEX_SECTION,
376 dwarfstring_string(&m));
377 dwarfstring_destructor(&m);
378 return DW_DLV_ERROR;
379 }
380 indexptr = (Dwarf_Xu_Index_Header)
381 _dwarf_get_alloc(dbg,DW_DLA_XU_INDEX,1);
382 if (indexptr == NULL) {
383 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
384 return (DW_DLV_ERROR);
385 }
386 /* Only "cu" or "tu" allowed, that is checked above.
387 But for safety we just copy the allowed bytes*/
388 indexptr->gx_type[0] = section_type[0];
389 indexptr->gx_type[1] = section_type[1];
390 indexptr->gx_type[2] = 0;
391 indexptr->gx_dbg = dbg;
392 indexptr->gx_section_length = sect->dss_size;
393 indexptr->gx_section_data = sect->dss_data;
394 indexptr->gx_section_name = sect->dss_name;
395 indexptr->gx_version = local_version;
396 indexptr->gx_column_count_sections = num_secs;
397 indexptr->gx_units_in_index = num_CUs;
398 indexptr->gx_slots_in_hash = num_slots;
399 indexptr->gx_hash_table_offset = hash_tab_offset;
400 indexptr->gx_index_table_offset = indexes_tab_offset;
401 indexptr->gx_section_offsets_headerline_offset=
402 section_offsets_headerline_offset;
403 indexptr->gx_section_offsets_offset= section_offsets_tab_offset;
404 indexptr->gx_section_sizes_offset = section_sizes_tab_offset;
405 res = fill_in_offsets_headerline(dbg,indexptr,
406 section_offsets_headerline_offset,
407 num_secs,error);
408 if (res != DW_DLV_OK) {
409 return res;
410 }
411 *xuptr = indexptr;
412 *version = indexptr->gx_version;
413 *number_of_columns = indexptr->gx_column_count_sections;
414 *number_of_CUs = indexptr->gx_units_in_index;
415 *number_of_slots = indexptr->gx_slots_in_hash;
416 *section_name = indexptr->gx_section_name;
417 return DW_DLV_OK;
418 }
419
420
421
dwarf_get_xu_index_section_type(Dwarf_Xu_Index_Header xuhdr,const char ** typename,const char ** sectionname,UNUSEDARG Dwarf_Error * err)422 int dwarf_get_xu_index_section_type(Dwarf_Xu_Index_Header xuhdr,
423 /* the function returns a pointer to
424 the immutable string "tu" or "cu" via
425 this arg. Do not free. */
426 const char ** typename,
427 /* the function returns a pointer to
428 the immutable section name. Do not free.
429 .debug_cu_index or .debug_tu_index */
430 const char ** sectionname,
431 UNUSEDARG Dwarf_Error * err)
432 {
433 *typename = &xuhdr->gx_type[0];
434 *sectionname = xuhdr->gx_section_name;
435 return DW_DLV_OK;
436 }
437
438 /* Index values 0 to S-1 are valid. */
dwarf_get_xu_hash_entry(Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned index,Dwarf_Sig8 * hash_value,Dwarf_Unsigned * index_to_sections,Dwarf_Error * err)439 int dwarf_get_xu_hash_entry(Dwarf_Xu_Index_Header xuhdr,
440 Dwarf_Unsigned index,
441 /* returns the hash value. 64 bits. */
442 Dwarf_Sig8 * hash_value,
443
444 /* returns the index into rows of offset/size tables. */
445 Dwarf_Unsigned * index_to_sections,
446 Dwarf_Error * err)
447 {
448 Dwarf_Debug dbg = xuhdr->gx_dbg;
449 Dwarf_Small *hashtab = xuhdr->gx_section_data +
450 xuhdr->gx_hash_table_offset;
451 Dwarf_Small *indextab = xuhdr->gx_section_data +
452 xuhdr->gx_index_table_offset;
453 Dwarf_Small *indexentry = 0;
454 Dwarf_Small *hashentry = 0;
455 Dwarf_Sig8 hashval;
456 Dwarf_Unsigned indexval = 0;
457 Dwarf_Small *section_end = xuhdr->gx_section_data +
458 xuhdr->gx_section_length;
459
460 hashval = zerohashkey;
461 if (xuhdr->gx_slots_in_hash > 0) {
462 if (index >= xuhdr->gx_slots_in_hash) {
463 dwarfstring m;
464
465 dwarfstring_constructor(&m);
466 dwarfstring_append_printf_u(&m,
467 "DW_DLE_XU_HASH_ROW_ERROR the index passed in, "
468 " %u, is greater than the number of slots "
469 " in the hash table.",index);
470 _dwarf_error_string(dbg, err, DW_DLE_XU_HASH_ROW_ERROR,
471 dwarfstring_string(&m));
472 dwarfstring_destructor(&m);
473 return DW_DLV_ERROR;
474 }
475 hashentry = hashtab + (index * HASHSIGNATURELEN);
476 memcpy(&hashval,hashentry,sizeof(hashval));
477 } else {
478 _dwarf_error_string(dbg, err, DW_DLE_XU_HASH_ROW_ERROR,
479 "DW_DLE_XU_HASH_ROW_ERROR the number of slots is zero"
480 " which seems wrong.");
481 return DW_DLV_ERROR;
482 }
483
484 indexentry = indextab + (index * LEN32BIT);
485 memcpy(hash_value,&hashval,sizeof(hashval));
486 READ_UNALIGNED_CK(dbg,indexval,Dwarf_Unsigned, indexentry,
487 LEN32BIT,
488 err,section_end);
489 indexentry += LEN32BIT;
490 if (indexval > xuhdr->gx_units_in_index) {
491 _dwarf_error(dbg, err, DW_DLE_XU_HASH_INDEX_ERROR);
492 return DW_DLV_ERROR;
493 }
494
495 *index_to_sections = indexval;
496 return DW_DLV_OK;
497 }
498
499
500 static const char * dwp_secnames[] = {
501 "No name for zero",
502 "DW_SECT_INFO" /* 1 */ /*".debug_info.dwo"*/,
503 "DW_SECT_TYPES" /* 2 */ /*".debug_types.dwo"*/,
504 "DW_SECT_ABBREV" /* 3 */ /*".debug_abbrev.dwo"*/,
505 "DW_SECT_LINE" /* 4 */ /*".debug_line.dwo"*/,
506 "DW_SECT_LOC" /* 5 */ /*".debug_loc.dwo"*/,
507 "DW_SECT_STR_OFFSETS" /* 6 */ /*".debug_str_offsets.dwo"*/,
508 "DW_SECT_MACRO" /* 7 */ /*".debug_macro.dwo"*/,
509 "DW_SECT_RNGLISTS" /* 8 */ /*".debug_rnglists.dwo"*/,
510 "No name > 8",
511 };
512
513 /* Row 0 of the Table of Section Offsets,
514 columns 0 to L-1, are the section id's,
515 and names, such as DW_SECT_INFO (ie, 1) */
516 int
dwarf_get_xu_section_names(Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned column_index,Dwarf_Unsigned * number,const char ** name,Dwarf_Error * err)517 dwarf_get_xu_section_names(Dwarf_Xu_Index_Header xuhdr,
518 Dwarf_Unsigned column_index,
519 Dwarf_Unsigned* number,
520 const char ** name,
521 Dwarf_Error * err)
522 {
523 Dwarf_Unsigned sec_num = 0;
524 Dwarf_Debug dbg = xuhdr->gx_dbg;
525
526 if( column_index >= xuhdr->gx_column_count_sections) {
527 dwarfstring s;
528
529 dwarfstring_constructor(&s);
530 dwarfstring_append_printf_u(&s,
531 "ERROR: DW_DLE_XU_NAME_COL_ERROR as the "
532 "column index of %u ",column_index);
533 dwarfstring_append_printf_u(&s," is too high. "
534 "There are %u sections.",
535 xuhdr->gx_column_count_sections);
536 _dwarf_error_string(dbg, err, DW_DLE_XU_NAME_COL_ERROR,
537 dwarfstring_string(&s));
538 dwarfstring_destructor(&s);
539 return DW_DLV_ERROR;
540 }
541 sec_num = xuhdr->gx_section_id[column_index];
542 if (sec_num < 1) {
543 return DW_DLV_NO_ENTRY;
544 }
545 *number = sec_num;
546 *name = dwp_secnames[sec_num];
547 return DW_DLV_OK;
548 }
549
550
551 /* Rows 0 to U-1
552 col 0 to L-1
553 are section offset and length values from
554 the Table of Section Offsets and Table of Section Sizes.
555 The formally the table of section offsets is a header
556 line of the section offsets we subtract 1 from
557 the incoming irow_index as our tables are
558 now zero origin. */
559 int
dwarf_get_xu_section_offset(Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned irow_index,Dwarf_Unsigned column_index,Dwarf_Unsigned * sec_offset,Dwarf_Unsigned * sec_size,Dwarf_Error * err)560 dwarf_get_xu_section_offset(Dwarf_Xu_Index_Header xuhdr,
561 Dwarf_Unsigned irow_index,
562 Dwarf_Unsigned column_index,
563 Dwarf_Unsigned* sec_offset,
564 Dwarf_Unsigned* sec_size,
565 Dwarf_Error * err)
566 {
567 /* We use zero origin in the arrays, Users see
568 one origin from the hash table. */
569 Dwarf_Debug dbg = xuhdr->gx_dbg;
570 /* get to base of tables first. */
571 Dwarf_Small *offsetrow = xuhdr->gx_section_offsets_offset +
572 xuhdr->gx_section_data;
573 Dwarf_Small *sizerow = xuhdr->gx_section_sizes_offset +
574 xuhdr->gx_section_data;
575 Dwarf_Small *offsetentry = 0;
576 Dwarf_Small *sizeentry = 0;
577 Dwarf_Unsigned offset = 0;
578 Dwarf_Unsigned size = 0;
579 Dwarf_Unsigned column_count = xuhdr->gx_column_count_sections;
580 Dwarf_Small *section_end = xuhdr->gx_section_data +
581 xuhdr->gx_section_length;
582 Dwarf_Unsigned row_index = irow_index-1;
583
584 if(!irow_index) {
585 dwarfstring s;
586
587 dwarfstring_constructor(&s);
588 dwarfstring_append(&s,
589 "ERROR: DW_DLE_ERRONEOUS_XU_INDEX_SECTION "
590 "The row index passed to dwarf_get_xu_section_offset() "
591 "is zero, which is not a valid row in "
592 " the offset-table or the size table as we think"
593 " of them as 1-origin.");
594 _dwarf_error_string(dbg, err, DW_DLE_XU_NAME_COL_ERROR,
595 dwarfstring_string(&s));
596 dwarfstring_destructor(&s);
597 return DW_DLV_ERROR;
598 }
599 if( row_index >= xuhdr->gx_units_in_index) {
600 dwarfstring s;
601
602 dwarfstring_constructor(&s);
603 dwarfstring_append_printf_u(&s,
604 "ERROR: DW_DLE_XU_NAME_COL_ERROR as the "
605 "row index of %u ",row_index);
606 dwarfstring_append_printf_u(&s," is too high. "
607 "Valid units must be < %u ",xuhdr->gx_units_in_index);
608 _dwarf_error_string(dbg, err, DW_DLE_XU_NAME_COL_ERROR,
609 dwarfstring_string(&s));
610 dwarfstring_destructor(&s);
611 return DW_DLV_ERROR;
612 }
613
614 if( column_index >= xuhdr->gx_column_count_sections) {
615 dwarfstring s;
616
617 dwarfstring_constructor(&s);
618 dwarfstring_append_printf_u(&s,
619 "ERROR: DW_DLE_XU_NAME_COL_ERROR as the "
620 "column index of %u ",column_index);
621 dwarfstring_append_printf_u(&s," is too high. "
622 "Valid column indexes must be < %u ",
623 xuhdr->gx_column_count_sections);
624 _dwarf_error_string(dbg, err, DW_DLE_XU_NAME_COL_ERROR,
625 dwarfstring_string(&s));
626 dwarfstring_destructor(&s);
627 return DW_DLV_ERROR;
628 }
629 /* As noted above we have hidden the extra initial
630 row from the offsets table so it is just
631 0 to U-1. */
632 offsetrow = offsetrow + (row_index*column_count * LEN32BIT);
633 offsetentry = offsetrow + (column_index * LEN32BIT);
634
635 sizerow = sizerow + (row_index*column_count * LEN32BIT);
636 sizeentry = sizerow + (column_index * LEN32BIT);
637
638 {
639 READ_UNALIGNED_CK(dbg,offset,Dwarf_Unsigned,
640 offsetentry,
641 LEN32BIT,err,section_end);
642 offsetentry += LEN32BIT;
643
644 READ_UNALIGNED_CK(dbg,size,Dwarf_Unsigned,
645 sizeentry,
646 LEN32BIT,err,section_end);
647 sizeentry += LEN32BIT;
648 }
649 *sec_offset = offset;
650 *sec_size = size;
651 return DW_DLV_OK;
652 }
653
654
655 static int
_dwarf_search_fission_for_key(UNUSEDARG Dwarf_Debug dbg,Dwarf_Xu_Index_Header xuhdr,Dwarf_Sig8 * key_in,Dwarf_Unsigned * percu_index_out,Dwarf_Error * error)656 _dwarf_search_fission_for_key(UNUSEDARG Dwarf_Debug dbg,
657 Dwarf_Xu_Index_Header xuhdr,
658 Dwarf_Sig8 *key_in,
659 Dwarf_Unsigned * percu_index_out,
660 Dwarf_Error *error)
661 {
662 Dwarf_Unsigned key = 0;
663 Dwarf_Unsigned primary_hash = 0;
664 Dwarf_Unsigned hashprime = 0;
665 Dwarf_Unsigned slots = xuhdr->gx_slots_in_hash;
666 Dwarf_Unsigned mask = slots -1;
667 Dwarf_Sig8 hashentry_key;
668 Dwarf_Unsigned percu_index = 0;
669
670 hashentry_key = zerohashkey;
671 /* Look for corrupt section data. */
672 if (slots > xuhdr->gx_section_length) {
673 dwarfstring s;
674
675 dwarfstring_constructor(&s);
676 dwarfstring_append_printf_u(&s,
677 "ERROR: DW_DLE_XU_NAME_COL_ERROR as the "
678 "slots count of %u ",slots);
679 dwarfstring_append_printf_u(&s," is too high. "
680 "given the section length of %u\n",
681 xuhdr->gx_section_length);
682 _dwarf_error_string(dbg, error, DW_DLE_XU_NAME_COL_ERROR,
683 dwarfstring_string(&s));
684 dwarfstring_destructor(&s);
685 return DW_DLV_ERROR;
686 }
687 if ( (4*slots) > xuhdr->gx_section_length) {
688 dwarfstring s;
689
690 dwarfstring_constructor(&s);
691 dwarfstring_append_printf_u(&s,
692 "ERROR: DW_DLE_XU_NAME_COL_ERROR as the "
693 "slots count *4 of %u ",slots*4);
694 dwarfstring_append_printf_u(&s," is too high. "
695 "given the section length of %u\n",
696 xuhdr->gx_section_length);
697 _dwarf_error_string(dbg, error, DW_DLE_XU_NAME_COL_ERROR,
698 dwarfstring_string(&s));
699 dwarfstring_destructor(&s);
700 return DW_DLV_ERROR;
701 }
702 if (sizeof (key) != sizeof(key_in)) {
703 /* The hash won't work right in this case */
704 _dwarf_error(dbg, error, DW_DLE_XU_HASH_ROW_ERROR);
705 }
706 ASNAR(key,key_in,sizeof(*key_in));
707 primary_hash = key & mask;
708 hashprime = (((key >>32) &mask) |1);
709 while (1) {
710 int res = 0;
711
712 res = dwarf_get_xu_hash_entry(xuhdr,
713 primary_hash,&hashentry_key,
714 &percu_index,error);
715 if (res != DW_DLV_OK) {
716 return res;
717 }
718 if (percu_index == 0 &&
719 !memcmp(&hashentry_key,&zerohashkey,sizeof(Dwarf_Sig8))) {
720 return DW_DLV_NO_ENTRY;
721 }
722 if (!memcmp(key_in,&hashentry_key,sizeof(Dwarf_Sig8))) {
723 /* FOUND */
724 *percu_index_out = percu_index;
725 return DW_DLV_OK;
726 }
727 primary_hash = (primary_hash + hashprime) % slots;
728 }
729 /* ASSERT: Cannot get here. */
730 return DW_DLV_NO_ENTRY;
731 }
732
733 /* Slow. Consider tsearch. */
734 /* For type units and for CUs. */
735 /* We're finding an index entry refers
736 to a global offset in some CU
737 and hence is unique in the target. */
738 static int
_dwarf_search_fission_for_offset(Dwarf_Debug dbg,Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned offset,Dwarf_Unsigned dfp_sect_num,Dwarf_Unsigned * percu_index_out,Dwarf_Sig8 * key_out,Dwarf_Error * error)739 _dwarf_search_fission_for_offset(Dwarf_Debug dbg,
740 Dwarf_Xu_Index_Header xuhdr,
741 Dwarf_Unsigned offset,
742 Dwarf_Unsigned dfp_sect_num, /* DW_SECT_INFO or TYPES */
743 Dwarf_Unsigned * percu_index_out,
744 Dwarf_Sig8 * key_out,
745 Dwarf_Error *error)
746 {
747 Dwarf_Unsigned i = 0;
748 Dwarf_Unsigned m = 0;
749 int secnum_index = -1; /* N index */
750 int res = 0;
751
752 for ( i = 0; i< xuhdr->gx_column_count_sections; i++) {
753 /* We could put the secnums array into xuhdr
754 if looping here is too slow. */
755 const char *name = 0;
756 Dwarf_Unsigned num = 0;
757 res = dwarf_get_xu_section_names(xuhdr,i,&num,&name,error);
758 if (res != DW_DLV_OK) {
759 return res;
760 }
761 if (num == dfp_sect_num) {
762 secnum_index = i;
763 break;
764 }
765 }
766 if (secnum_index == -1) {
767 _dwarf_error(dbg,error,DW_DLE_FISSION_SECNUM_ERR);
768 return DW_DLV_ERROR;
769 }
770 for ( m = 0; m < xuhdr->gx_slots_in_hash; ++m) {
771 Dwarf_Sig8 hash;
772 Dwarf_Unsigned indexn = 0;
773 Dwarf_Unsigned sec_offset = 0;
774 Dwarf_Unsigned sec_size = 0;
775
776 res = dwarf_get_xu_hash_entry(xuhdr,m,&hash,&indexn,error);
777 if (res != DW_DLV_OK) {
778 return res;
779 }
780 if (indexn == 0 &&
781 !memcmp(&hash,&zerohashkey,sizeof(Dwarf_Sig8))) {
782 /* Empty slot. */
783 continue;
784 }
785
786 res = dwarf_get_xu_section_offset(xuhdr,
787 indexn,secnum_index,&sec_offset,&sec_size,error);
788 if (res != DW_DLV_OK) {
789 return res;
790 }
791 if (sec_offset != offset) {
792 continue;
793 }
794 *percu_index_out = indexn;
795 *key_out = hash;
796 return DW_DLV_OK;
797 }
798 return DW_DLV_NO_ENTRY;
799 }
800
801 static int
_dwarf_get_xuhdr(Dwarf_Debug dbg,const char * sigtype,Dwarf_Xu_Index_Header * xuout,Dwarf_Error * error)802 _dwarf_get_xuhdr(Dwarf_Debug dbg,
803 const char *sigtype,
804 Dwarf_Xu_Index_Header *xuout,
805 Dwarf_Error *error)
806 {
807 if (!strcmp(sigtype,"tu")) {
808 if (!dbg->de_tu_hashindex_data) {
809 return DW_DLV_NO_ENTRY;
810 }
811 *xuout = dbg->de_tu_hashindex_data;
812 } else if (!strcmp(sigtype,"cu")) {
813 if (!dbg->de_cu_hashindex_data) {
814 return DW_DLV_NO_ENTRY;
815 }
816 *xuout = dbg->de_cu_hashindex_data;
817 } else {
818 _dwarf_error(dbg,error,DW_DLE_SIG_TYPE_WRONG_STRING);
819 return DW_DLV_ERROR;
820 }
821 return DW_DLV_OK;
822
823 }
824
825 static int
transform_xu_to_dfp(Dwarf_Xu_Index_Header xuhdr,Dwarf_Unsigned percu_index,Dwarf_Sig8 * key,const char * sig_type,Dwarf_Debug_Fission_Per_CU * percu_out,Dwarf_Error * error)826 transform_xu_to_dfp(Dwarf_Xu_Index_Header xuhdr,
827 Dwarf_Unsigned percu_index,
828 Dwarf_Sig8 *key,
829 const char *sig_type,
830 Dwarf_Debug_Fission_Per_CU * percu_out,
831 Dwarf_Error *error)
832 {
833 unsigned i = 0;
834 unsigned l = 0;
835 unsigned n = 1;
836 unsigned max_cols = xuhdr->gx_column_count_sections; /* L */
837 unsigned secnums[DW_FISSION_SECT_COUNT];
838 int res;
839 for ( i = 0; i< max_cols; i++) {
840 /* We could put the secnums array into xuhdr
841 if recreating it is too slow. */
842 const char *name = 0;
843 Dwarf_Unsigned num = 0;
844 res = dwarf_get_xu_section_names(xuhdr,i,&num,&name,error);
845 if (res != DW_DLV_OK) {
846 return res;
847 }
848 secnums[i] = num;
849 }
850 n = percu_index;
851 for(l = 0; l < max_cols; ++l) { /* L */
852 Dwarf_Unsigned sec_off = 0;
853 Dwarf_Unsigned sec_size = 0;
854 unsigned l_as_sect = secnums[l];
855 res = dwarf_get_xu_section_offset(xuhdr,n,l,
856 &sec_off,&sec_size,error);
857 if (res != DW_DLV_OK) {
858 return res;
859 }
860 percu_out->pcu_offset[l_as_sect] = sec_off;
861 percu_out->pcu_size[l_as_sect] = sec_size;
862 }
863 percu_out->pcu_type = sig_type;
864 percu_out->pcu_index = percu_index;
865 percu_out->pcu_hash = *key;
866 return DW_DLV_OK;
867 }
868
869 /* This should only be called for a CU, never a TU.
870 For a TU the type hash is known while reading
871 the TU Header. Not so for a CU. */
872 int
_dwarf_get_debugfission_for_offset(Dwarf_Debug dbg,Dwarf_Off offset_wanted,const char * key_type,struct Dwarf_Debug_Fission_Per_CU_s * percu_out,Dwarf_Error * error)873 _dwarf_get_debugfission_for_offset(Dwarf_Debug dbg,
874 Dwarf_Off offset_wanted,
875 const char * key_type, /* "cu" or "tu" */
876 struct Dwarf_Debug_Fission_Per_CU_s * percu_out,
877 Dwarf_Error *error)
878 {
879 Dwarf_Xu_Index_Header xuhdr = 0;
880 int sres = 0;
881 Dwarf_Unsigned percu_index = 0;
882 Dwarf_Unsigned sect_index_base = 0;
883 Dwarf_Sig8 key;
884
885 sect_index_base = DW_SECT_INFO;
886 key = zerohashkey;
887 sres = _dwarf_get_xuhdr(dbg,key_type, &xuhdr,error);
888 if (sres != DW_DLV_OK) {
889 return sres;
890 }
891 sres = _dwarf_search_fission_for_offset(dbg,
892 xuhdr,offset_wanted, sect_index_base, &percu_index,
893 &key,
894 error);
895 if (sres != DW_DLV_OK) {
896 return sres;
897 }
898 sres = transform_xu_to_dfp(xuhdr,percu_index,&key,
899 key_type,percu_out, error);
900 return sres;
901
902 }
903 int
dwarf_get_debugfission_for_key(Dwarf_Debug dbg,Dwarf_Sig8 * key,const char * key_type,Dwarf_Debug_Fission_Per_CU * percu_out,Dwarf_Error * error)904 dwarf_get_debugfission_for_key(Dwarf_Debug dbg,
905 Dwarf_Sig8 * key /* pointer to hash signature */,
906 const char * key_type /* "cu" or "tu" */,
907 Dwarf_Debug_Fission_Per_CU * percu_out,
908 Dwarf_Error * error )
909 {
910 int sres = 0;
911 Dwarf_Unsigned percu_index = 0;
912 Dwarf_Xu_Index_Header xuhdr = 0;
913
914 sres = _dwarf_load_debug_info(dbg,error);
915 if (sres == DW_DLV_ERROR) {
916 return sres;
917 }
918 sres = _dwarf_load_debug_types(dbg,error);
919 if (sres == DW_DLV_ERROR) {
920 return sres;
921 }
922 /* Returns already existing xuhdr */
923 sres = _dwarf_get_xuhdr(dbg,key_type, &xuhdr,error);
924 if (sres != DW_DLV_OK) {
925 return sres;
926 }
927 /* Search in that xu data. */
928 sres = _dwarf_search_fission_for_key(dbg,
929 xuhdr,key,&percu_index,error);
930 if (sres != DW_DLV_OK) {
931 return sres;
932 }
933 sres = transform_xu_to_dfp(xuhdr,percu_index,key,
934 key_type,percu_out,error);
935 return sres;
936 }
937
938 void
dwarf_xu_header_free(Dwarf_Xu_Index_Header indexptr)939 dwarf_xu_header_free(Dwarf_Xu_Index_Header indexptr)
940 {
941 if(indexptr) {
942 Dwarf_Debug dbg = indexptr->gx_dbg;
943 dwarf_dealloc(dbg,indexptr,DW_DLA_XU_INDEX);
944 }
945 }
946