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 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 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 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. */ 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 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 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 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 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 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 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 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 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 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