1 /* 2 3 Copyright (C) 2014-2019 David Anderson. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of version 2.1 of the GNU Lesser General Public License 7 as published by the Free Software Foundation. 8 9 This program is distributed in the hope that it would be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 Further, this software is distributed without any warranty that it is 14 free of the rightful claim of any third person regarding infringement 15 or the like. Any license provided herein, whether implied or 16 otherwise, applies only to this software file. Patent licenses, if 17 any, provided herein do not apply to combinations of this program with 18 other software, or any other product whatsoever. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this program; if not, write the Free Software 22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 23 USA. 24 25 */ 26 27 #include "config.h" 28 #include <stdio.h> 29 #ifdef HAVE_STDLIB_H 30 #include <stdlib.h> 31 #endif /* HAVE_STDLIB_H */ 32 #include "dwarf_incl.h" 33 #include "dwarf_alloc.h" 34 #include "dwarf_error.h" 35 #include "dwarf_util.h" 36 #include "memcpy_swap.h" 37 #include "dwarf_gdbindex.h" 38 39 #define TRUE 1 40 #define FALSE 0 41 42 /* The dwarf_util macro READ_UNALIGNED 43 cannot be directly used because 44 gdb defines the section contents of 45 .gdb_index as little-endian always. 46 */ 47 48 #if WORDS_BIGENDIAN /* meaning on this host */ 49 #define READ_GDBINDEX(dest,desttype, source, length) \ 50 do { \ 51 BIGGEST_UINT _ltmp = 0; \ 52 _dwarf_memcpy_swap_bytes((((char *)(&_ltmp)) + sizeof(_ltmp) - length), \ 53 source, length) ; \ 54 dest = (desttype)_ltmp; \ 55 } while (0) 56 #else /* little-endian on this host */ 57 #define READ_GDBINDEX(dest,desttype, source, length) \ 58 do { \ 59 BIGGEST_UINT _ltmp = 0; \ 60 memcpy(((char *)(&_ltmp)) , \ 61 source, length) ; \ 62 dest = (desttype)_ltmp; \ 63 } while (0) 64 65 #endif 66 67 68 struct gi_fileheader_s { 69 char gfs [4][6]; 70 }; 71 72 struct dwarf_64bitpair { 73 gdbindex_64 offset; 74 gdbindex_64 length; 75 }; 76 77 static int 78 set_base(Dwarf_Debug dbg, 79 struct Dwarf_Gdbindex_array_instance_s * hdr, 80 Dwarf_Small *start, 81 Dwarf_Small *end, 82 /* entrylen is the length of a single struct as seen in the object. */ 83 Dwarf_Unsigned entrylen, 84 /* The size of each field in the struct in the object. */ 85 Dwarf_Unsigned fieldlen, 86 enum gdbindex_type_e type, 87 Dwarf_Error * err) 88 { 89 90 if (type == git_std || type == git_cuvec) { 91 /* cuvec is sort of a fake as a simple 92 section, but a useful one. */ 93 Dwarf_Unsigned count = 0; 94 if( end < start) { 95 _dwarf_error(dbg, err,DW_DLE_GDB_INDEX_COUNT_ERROR); 96 return DW_DLV_ERROR; 97 } 98 count = end - start; 99 count = count / entrylen; 100 hdr->dg_type = type; 101 hdr->dg_base = start; 102 hdr->dg_count = count; 103 hdr->dg_entry_length = entrylen; 104 hdr->dg_fieldlen = fieldlen; 105 } else { 106 /* address area. */ 107 /* 64bit, 64bit, offset. Then 32bit pad. */ 108 Dwarf_Unsigned count = 0; 109 hdr->dg_base = start; 110 if( end < start) { 111 _dwarf_error(dbg, err,DW_DLE_GDB_INDEX_COUNT_ADDR_ERROR); 112 return DW_DLV_ERROR; 113 } 114 /* entry length includes pad. */ 115 hdr->dg_entry_length = 2*sizeof(gdbindex_64) + 116 DWARF_32BIT_SIZE; 117 count = end - start; 118 count = count / hdr->dg_entry_length; 119 hdr->dg_count = count; 120 /* The dg_fieldlen is a fake, the fields are not 121 all the same length. */ 122 hdr->dg_fieldlen = DWARF_32BIT_SIZE; 123 hdr->dg_type = type; 124 } 125 return DW_DLV_OK; 126 } 127 128 int 129 dwarf_gdbindex_header(Dwarf_Debug dbg, 130 Dwarf_Gdbindex * gdbindexptr, 131 Dwarf_Unsigned * version, 132 Dwarf_Unsigned * cu_list_offset, 133 Dwarf_Unsigned * types_cu_list_offset, 134 Dwarf_Unsigned * address_area_offset, 135 Dwarf_Unsigned * symbol_table_offset, 136 Dwarf_Unsigned * constant_pool_offset, 137 Dwarf_Unsigned * section_size, 138 Dwarf_Unsigned * unused_reserved, 139 const char ** section_name, 140 Dwarf_Error * error) 141 { 142 143 struct gi_fileheader_s header; 144 Dwarf_Gdbindex indexptr = 0; 145 int res = DW_DLV_ERROR; 146 147 if (!dbg->de_debug_gdbindex.dss_size) { 148 return DW_DLV_NO_ENTRY; 149 } 150 if (!dbg->de_debug_gdbindex.dss_data) { 151 res = _dwarf_load_section(dbg, &dbg->de_debug_gdbindex,error); 152 if (res != DW_DLV_OK) { 153 return res; 154 } 155 } 156 157 if (dbg->de_debug_gdbindex.dss_size < 158 sizeof(struct gi_fileheader_s) ) { 159 _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION); 160 return (DW_DLV_ERROR); 161 } 162 memcpy(&header,dbg->de_debug_gdbindex.dss_data, 163 sizeof(struct gi_fileheader_s)); 164 indexptr = (Dwarf_Gdbindex)_dwarf_get_alloc(dbg,DW_DLA_GDBINDEX,1); 165 if (indexptr == NULL) { 166 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 167 return (DW_DLV_ERROR); 168 } 169 170 indexptr->gi_dbg = dbg; 171 indexptr->gi_section_data = dbg->de_debug_gdbindex.dss_data; 172 indexptr->gi_section_length = dbg->de_debug_gdbindex.dss_size; 173 READ_GDBINDEX(indexptr->gi_version ,Dwarf_Unsigned, 174 dbg->de_debug_gdbindex.dss_data, 175 DWARF_32BIT_SIZE); 176 READ_GDBINDEX(indexptr->gi_cu_list_offset ,Dwarf_Unsigned, 177 dbg->de_debug_gdbindex.dss_data + DWARF_32BIT_SIZE, 178 DWARF_32BIT_SIZE); 179 READ_GDBINDEX(indexptr->gi_types_cu_list_offset ,Dwarf_Unsigned, 180 dbg->de_debug_gdbindex.dss_data + 2*DWARF_32BIT_SIZE, 181 DWARF_32BIT_SIZE); 182 READ_GDBINDEX(indexptr->gi_address_area_offset ,Dwarf_Unsigned, 183 dbg->de_debug_gdbindex.dss_data + 3*DWARF_32BIT_SIZE, 184 DWARF_32BIT_SIZE); 185 READ_GDBINDEX(indexptr->gi_symbol_table_offset ,Dwarf_Unsigned, 186 dbg->de_debug_gdbindex.dss_data + 4*DWARF_32BIT_SIZE, 187 DWARF_32BIT_SIZE); 188 READ_GDBINDEX(indexptr->gi_constant_pool_offset ,Dwarf_Unsigned, 189 dbg->de_debug_gdbindex.dss_data + 5*DWARF_32BIT_SIZE, 190 DWARF_32BIT_SIZE); 191 192 res = set_base(dbg,&indexptr->gi_culisthdr, 193 dbg->de_debug_gdbindex.dss_data + indexptr->gi_cu_list_offset, 194 dbg->de_debug_gdbindex.dss_data + indexptr->gi_types_cu_list_offset, 195 2*sizeof(gdbindex_64), 196 sizeof(gdbindex_64), 197 git_std,error); 198 if (res == DW_DLV_ERROR) { 199 return res; 200 } 201 res = set_base(dbg,&indexptr->gi_typesculisthdr, 202 dbg->de_debug_gdbindex.dss_data + indexptr->gi_types_cu_list_offset, 203 dbg->de_debug_gdbindex.dss_data + indexptr->gi_address_area_offset, 204 3*sizeof(gdbindex_64), 205 sizeof(gdbindex_64), 206 git_std,error); 207 if (res == DW_DLV_ERROR) { 208 return res; 209 } 210 res = set_base(dbg,&indexptr->gi_addressareahdr, 211 dbg->de_debug_gdbindex.dss_data + indexptr->gi_address_area_offset, 212 dbg->de_debug_gdbindex.dss_data + indexptr->gi_symbol_table_offset, 213 3*sizeof(gdbindex_64), 214 sizeof(gdbindex_64), 215 git_address,error); 216 if (res == DW_DLV_ERROR) { 217 return res; 218 } 219 res = set_base(dbg,&indexptr->gi_symboltablehdr, 220 dbg->de_debug_gdbindex.dss_data + indexptr->gi_symbol_table_offset, 221 dbg->de_debug_gdbindex.dss_data + indexptr->gi_constant_pool_offset, 222 2*DWARF_32BIT_SIZE, 223 DWARF_32BIT_SIZE, 224 git_std,error); 225 if (res == DW_DLV_ERROR) { 226 return res; 227 } 228 res = set_base(dbg,&indexptr->gi_cuvectorhdr, 229 dbg->de_debug_gdbindex.dss_data + indexptr->gi_constant_pool_offset, 230 /* There is no real single vector size. 231 but we'll use the entire rest as if there was. */ 232 dbg->de_debug_gdbindex.dss_data + indexptr->gi_section_length, 233 DWARF_32BIT_SIZE, 234 DWARF_32BIT_SIZE, 235 git_cuvec,error); 236 if (res == DW_DLV_ERROR) { 237 return res; 238 } 239 240 /* Really just pointing to constant pool area. */ 241 indexptr->gi_string_pool = dbg->de_debug_gdbindex.dss_data + 242 indexptr->gi_constant_pool_offset; 243 *gdbindexptr = indexptr; 244 *version = indexptr->gi_version; 245 *cu_list_offset = indexptr->gi_cu_list_offset; 246 *types_cu_list_offset = indexptr->gi_types_cu_list_offset; 247 *address_area_offset = indexptr->gi_address_area_offset; 248 *symbol_table_offset = indexptr->gi_symbol_table_offset; 249 *constant_pool_offset = indexptr->gi_constant_pool_offset; 250 *section_size = indexptr->gi_section_length; 251 *unused_reserved = 0; 252 *section_name = dbg->de_debug_gdbindex.dss_name; 253 return DW_DLV_OK; 254 255 256 } 257 258 259 int 260 dwarf_gdbindex_culist_array(Dwarf_Gdbindex gdbindexptr, 261 Dwarf_Unsigned * list_length, 262 UNUSEDARG Dwarf_Error * error) 263 { 264 *list_length = gdbindexptr->gi_culisthdr.dg_count; 265 return DW_DLV_OK; 266 } 267 268 /* entryindex: 0 to list_length-1 */ 269 int 270 dwarf_gdbindex_culist_entry(Dwarf_Gdbindex gdbindexptr, 271 Dwarf_Unsigned entryindex, 272 Dwarf_Unsigned * cu_offset, 273 Dwarf_Unsigned * cu_length, 274 Dwarf_Error * error) 275 { 276 Dwarf_Unsigned max = gdbindexptr->gi_culisthdr.dg_count; 277 Dwarf_Small * base = 0; 278 Dwarf_Unsigned offset = 0; 279 Dwarf_Unsigned length = 0; 280 unsigned fieldlen = gdbindexptr->gi_culisthdr.dg_fieldlen; 281 282 if (entryindex >= max) { 283 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 284 return DW_DLV_ERROR; 285 } 286 base = gdbindexptr->gi_culisthdr.dg_base; 287 base += entryindex*gdbindexptr->gi_culisthdr.dg_entry_length; 288 289 READ_GDBINDEX(offset ,Dwarf_Unsigned, 290 base, 291 fieldlen); 292 READ_GDBINDEX(length ,Dwarf_Unsigned, 293 base+ fieldlen, 294 fieldlen); 295 *cu_offset = offset; 296 *cu_length = length; 297 return DW_DLV_OK; 298 } 299 300 int 301 dwarf_gdbindex_types_culist_array(Dwarf_Gdbindex gdbindexptr, 302 Dwarf_Unsigned * list_length, 303 UNUSEDARG Dwarf_Error * error) 304 { 305 *list_length = gdbindexptr->gi_typesculisthdr.dg_count; 306 return DW_DLV_OK; 307 } 308 309 /* entryindex: 0 to list_length-1 */ 310 int 311 dwarf_gdbindex_types_culist_entry(Dwarf_Gdbindex gdbindexptr, 312 Dwarf_Unsigned entryindex, 313 Dwarf_Unsigned * t_offset, 314 Dwarf_Unsigned * t_length, 315 Dwarf_Unsigned * t_signature, 316 Dwarf_Error * error) 317 { 318 Dwarf_Unsigned max = gdbindexptr->gi_typesculisthdr.dg_count; 319 Dwarf_Small * base = 0; 320 Dwarf_Unsigned offset = 0; 321 Dwarf_Unsigned length = 0; 322 Dwarf_Unsigned signature = 0; 323 unsigned fieldlen = gdbindexptr->gi_typesculisthdr.dg_fieldlen; 324 325 if (entryindex >= max) { 326 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 327 return DW_DLV_ERROR; 328 } 329 base = gdbindexptr->gi_typesculisthdr.dg_base; 330 base += entryindex*gdbindexptr->gi_typesculisthdr.dg_entry_length; 331 332 READ_GDBINDEX(offset ,Dwarf_Unsigned, 333 base, 334 fieldlen); 335 READ_GDBINDEX(length ,Dwarf_Unsigned, 336 base+ (1*fieldlen), 337 fieldlen); 338 READ_GDBINDEX(signature ,Dwarf_Unsigned, 339 base+ (2*fieldlen), 340 fieldlen); 341 *t_offset = offset; 342 *t_length = length; 343 *t_signature = signature; 344 return DW_DLV_OK; 345 } 346 347 int 348 dwarf_gdbindex_addressarea(Dwarf_Gdbindex gdbindexptr, 349 Dwarf_Unsigned * list_length, 350 UNUSEDARG Dwarf_Error * error) 351 { 352 *list_length = gdbindexptr->gi_addressareahdr.dg_count; 353 return DW_DLV_OK; 354 } 355 356 /* entryindex: 0 to addressarea_list_length-1 */ 357 int 358 dwarf_gdbindex_addressarea_entry( 359 Dwarf_Gdbindex gdbindexptr, 360 Dwarf_Unsigned entryindex, 361 Dwarf_Unsigned * low_address, 362 Dwarf_Unsigned * high_address, 363 Dwarf_Unsigned * cu_index, 364 Dwarf_Error * error) 365 { 366 Dwarf_Unsigned max = gdbindexptr->gi_addressareahdr.dg_count; 367 Dwarf_Small * base = 0; 368 Dwarf_Unsigned lowaddr = 0; 369 Dwarf_Unsigned highaddr = 0; 370 Dwarf_Unsigned cuindex = 0; 371 372 if (entryindex >= max) { 373 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 374 return DW_DLV_ERROR; 375 } 376 base = gdbindexptr->gi_addressareahdr.dg_base; 377 base += entryindex*gdbindexptr->gi_addressareahdr.dg_entry_length; 378 379 READ_GDBINDEX(lowaddr ,Dwarf_Unsigned, 380 base, 381 sizeof(gdbindex_64)); 382 READ_GDBINDEX(highaddr ,Dwarf_Unsigned, 383 base+ (1*sizeof(gdbindex_64)), 384 sizeof(gdbindex_64)); 385 READ_GDBINDEX(cuindex ,Dwarf_Unsigned, 386 base+ (2*sizeof(gdbindex_64)), 387 DWARF_32BIT_SIZE); 388 *low_address = lowaddr; 389 *high_address = highaddr; 390 *cu_index = cuindex; 391 return DW_DLV_OK; 392 } 393 394 int 395 dwarf_gdbindex_symboltable_array(Dwarf_Gdbindex gdbindexptr, 396 Dwarf_Unsigned * list_length, 397 UNUSEDARG Dwarf_Error * error) 398 { 399 *list_length = gdbindexptr->gi_symboltablehdr.dg_count; 400 return DW_DLV_OK; 401 } 402 403 /* entryindex: 0 to symtab_list_length-1 */ 404 int 405 dwarf_gdbindex_symboltable_entry( 406 Dwarf_Gdbindex gdbindexptr, 407 Dwarf_Unsigned entryindex, 408 Dwarf_Unsigned * string_offset, 409 Dwarf_Unsigned * cu_vector_offset, 410 Dwarf_Error * error) 411 { 412 Dwarf_Unsigned max = gdbindexptr->gi_symboltablehdr.dg_count; 413 Dwarf_Small * base = 0; 414 Dwarf_Unsigned symoffset = 0; 415 Dwarf_Unsigned cuoffset = 0; 416 unsigned fieldlen = gdbindexptr->gi_symboltablehdr.dg_fieldlen; 417 418 if (entryindex >= max) { 419 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 420 return DW_DLV_ERROR; 421 } 422 base = gdbindexptr->gi_symboltablehdr.dg_base; 423 base += entryindex*gdbindexptr->gi_symboltablehdr.dg_entry_length; 424 425 READ_GDBINDEX(symoffset ,Dwarf_Unsigned, 426 base, 427 fieldlen); 428 READ_GDBINDEX(cuoffset ,Dwarf_Unsigned, 429 base + fieldlen, 430 fieldlen); 431 *string_offset = symoffset; 432 *cu_vector_offset = cuoffset; 433 return DW_DLV_OK; 434 } 435 436 int 437 dwarf_gdbindex_cuvector_length(Dwarf_Gdbindex gdbindex, 438 Dwarf_Unsigned cuvector_offset, 439 Dwarf_Unsigned * innercount, 440 Dwarf_Error * error) 441 { 442 Dwarf_Small *base = gdbindex->gi_cuvectorhdr.dg_base; 443 Dwarf_Small *end = gdbindex->gi_section_data + gdbindex->gi_section_length; 444 Dwarf_Unsigned val = 0; 445 unsigned fieldlen = gdbindex->gi_cuvectorhdr.dg_entry_length; 446 447 base += cuvector_offset; 448 if ((base + fieldlen) >= end) { 449 _dwarf_error(gdbindex->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 450 return DW_DLV_ERROR; 451 } 452 453 READ_GDBINDEX(val,Dwarf_Unsigned, 454 base, 455 fieldlen); 456 *innercount = val; 457 return DW_DLV_OK; 458 } 459 460 int 461 dwarf_gdbindex_cuvector_inner_attributes(Dwarf_Gdbindex gdbindexptr, 462 Dwarf_Unsigned cuvector_offset, 463 Dwarf_Unsigned innerindex, 464 /* The attr_value is a field of bits. For expanded version 465 use dwarf_gdbindex_instance_expand_value() */ 466 Dwarf_Unsigned * attributes, 467 Dwarf_Error * error) 468 { 469 Dwarf_Small *base = gdbindexptr->gi_cuvectorhdr.dg_base; 470 Dwarf_Small *end = gdbindexptr->gi_section_data + 471 gdbindexptr->gi_section_length; 472 Dwarf_Unsigned val = 0; 473 unsigned fieldlen = gdbindexptr->gi_cuvectorhdr.dg_entry_length; 474 475 base += cuvector_offset; 476 if ((base+fieldlen) >= end) { 477 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 478 return DW_DLV_ERROR; 479 } 480 base += fieldlen; 481 base += innerindex*fieldlen; 482 483 READ_GDBINDEX(val ,Dwarf_Unsigned, 484 base, 485 fieldlen); 486 *attributes = val; 487 return DW_DLV_OK; 488 } 489 490 491 int 492 dwarf_gdbindex_cuvector_instance_expand_value( 493 UNUSEDARG Dwarf_Gdbindex gdbindexptr, 494 Dwarf_Unsigned value, 495 Dwarf_Unsigned * cu_index, 496 Dwarf_Unsigned * reserved1, 497 Dwarf_Unsigned * symbol_kind, 498 Dwarf_Unsigned * is_static, 499 UNUSEDARG Dwarf_Error * error) 500 { 501 *cu_index = value & 0xffffff; 502 *reserved1 = (value >> 24) & 0xf; 503 *symbol_kind = (value >> 28) & 0x7; 504 *is_static = (value >> 31) & 1; 505 return DW_DLV_OK; 506 } 507 508 509 /* The strings in the pool follow (in memory) the cu index 510 set and are NUL terminated. */ 511 int 512 dwarf_gdbindex_string_by_offset(Dwarf_Gdbindex gdbindexptr, 513 Dwarf_Unsigned stringoffsetinpool, 514 const char ** string_ptr, 515 UNUSEDARG Dwarf_Error * error) 516 { 517 Dwarf_Small *pooldata = 0; 518 Dwarf_Small *section_end = 0; 519 Dwarf_Small *stringitself = 0; 520 521 /* If gdbindexptr NULL or gdbindexptr->gi_dbg is NULL 522 this is not going to go very well. Ugh. FIXME */ 523 pooldata = gdbindexptr->gi_section_data + 524 gdbindexptr->gi_constant_pool_offset; 525 section_end = gdbindexptr->gi_section_data + 526 gdbindexptr->gi_section_length; 527 stringitself = pooldata + stringoffsetinpool; 528 if (stringitself > section_end) { 529 _dwarf_error(gdbindexptr->gi_dbg, error,DW_DLE_GDB_INDEX_INDEX_ERROR); 530 return DW_DLV_ERROR; 531 } 532 *string_ptr = (const char *)stringitself; 533 return DW_DLV_OK; 534 } 535 536 537 538 539 void 540 dwarf_gdbindex_free(Dwarf_Gdbindex indexptr) 541 { 542 if(indexptr) { 543 Dwarf_Debug dbg = indexptr->gi_dbg; 544 dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX); 545 } 546 } 547