1 /* 2 3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. 4 Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. 5 Portions Copyright 2011-2017 David Anderson. All Rights Reserved. 6 7 This program is free software; you can redistribute it 8 and/or modify it under the terms of version 2.1 of the 9 GNU Lesser General Public License as published by the Free 10 Software Foundation. 11 12 This program is distributed in the hope that it would be 13 useful, but WITHOUT ANY WARRANTY; without even the implied 14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 PURPOSE. 16 17 Further, this software is distributed without any warranty 18 that it is free of the rightful claim of any third person 19 regarding infringement or the like. Any license provided 20 herein, whether implied or otherwise, applies only to this 21 software file. Patent licenses, if any, provided herein 22 do not apply to combinations of this program with other 23 software, or any other product whatsoever. 24 25 You should have received a copy of the GNU Lesser General 26 Public License along with this program; if not, write the 27 Free Software Foundation, Inc., 51 Franklin Street - Fifth 28 Floor, Boston MA 02110-1301, USA. 29 30 */ 31 32 #include "config.h" 33 #include "libdwarfdefs.h" 34 #include <stdio.h> 35 #ifdef HAVE_STDLIB_H 36 #include <stdlib.h> /* for exit(), C89 malloc */ 37 #endif /* HAVE_STDLIB_H */ 38 #ifdef HAVE_MALLOC_H 39 /* Useful include for some Windows compilers. */ 40 #include <malloc.h> 41 #endif /* HAVE_MALLOC_H */ 42 #ifdef HAVE_STDINT_H 43 #include <stdint.h> /* For uintptr_t */ 44 #endif /* HAVE_STDINT_H */ 45 #include <string.h> 46 #include <stddef.h> 47 #include "pro_incl.h" 48 #include "dwarf.h" 49 #include "libdwarf.h" 50 #include "pro_opaque.h" 51 #include "pro_error.h" 52 #include "pro_util.h" 53 #include "pro_alloc.h" 54 #include "pro_die.h" 55 #include "pro_section.h" 56 #include "dwarf_tsearch.h" 57 58 #ifndef R_MIPS_NONE 59 #define R_MIPS_NONE 0 60 #endif 61 62 #define TRUE 1 63 #define FALSE 0 64 65 /* This function creates a new die. 66 tag: tag of the new die to be created 67 parent,child,left,right: specify neighbors of the new die. Only 68 one of these may be non-null */ 69 Dwarf_P_Die 70 dwarf_new_die(Dwarf_P_Debug dbg, 71 Dwarf_Tag tag, 72 Dwarf_P_Die parent, 73 Dwarf_P_Die child, 74 Dwarf_P_Die left, Dwarf_P_Die right, 75 Dwarf_Error * error) 76 { 77 Dwarf_P_Die created = 0; 78 int res = 0; 79 80 res = dwarf_new_die_a(dbg,tag,parent,child, 81 left,right,&created,error); 82 if (res != DW_DLV_OK) { 83 return (Dwarf_P_Die)DW_DLV_BADADDR; 84 } 85 return created; 86 } 87 88 /* New September 2016. Preferred as error checking 89 is easier, no need for ugly cast. */ 90 int 91 dwarf_new_die_a(Dwarf_P_Debug dbg, 92 Dwarf_Tag tag, 93 Dwarf_P_Die parent, 94 Dwarf_P_Die child, 95 Dwarf_P_Die left, Dwarf_P_Die right, 96 Dwarf_P_Die *die_out, 97 Dwarf_Error *error) 98 { 99 Dwarf_P_Die ret_die = 0; 100 int res = 0; 101 102 ret_die = (Dwarf_P_Die) 103 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s)); 104 if (ret_die == NULL) { 105 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC, 106 DW_DLV_ERROR); 107 } 108 ret_die->di_parent = NULL; 109 ret_die->di_left = NULL; 110 ret_die->di_right = NULL; 111 ret_die->di_child = NULL; 112 ret_die->di_last_child = NULL; 113 ret_die->di_tag = tag; 114 ret_die->di_dbg = dbg; 115 ret_die->di_marker = 0; 116 res = dwarf_die_link_a(ret_die, parent, child, left, right, 117 error); 118 if (res != DW_DLV_OK) { 119 _dwarf_p_dealloc(dbg,(Dwarf_Small *)ret_die); 120 ret_die = 0; 121 } else { 122 *die_out = ret_die; 123 } 124 return res; 125 } 126 127 /* This function links up a die to specified neighbors 128 parent,child,left,right: specify neighbors of the new die. Only 129 one of these may be non-null 130 This is the original version. Use dwarf_die_link_a() 131 instead as that function is easier to use (in checking for error). 132 */ 133 Dwarf_P_Die 134 dwarf_die_link(Dwarf_P_Die new_die, 135 Dwarf_P_Die parent, 136 Dwarf_P_Die child, 137 Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) 138 { 139 int res = 0; 140 141 res = dwarf_die_link_a(new_die,parent,child,left,right,error); 142 if (res != DW_DLV_OK) { 143 return (Dwarf_P_Die)DW_DLV_BADADDR; 144 } 145 return new_die; 146 } 147 148 /* New September 2016. 149 Error return easier to deal with 150 than dwarf_die_link(). */ 151 int 152 dwarf_die_link_a(Dwarf_P_Die new_die, 153 Dwarf_P_Die parent, 154 Dwarf_P_Die child, 155 Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) 156 { 157 /* Count the # of non null neighbors. */ 158 int n_nulls = 0; 159 160 if (parent != NULL) { 161 n_nulls++; 162 if (new_die->di_parent != NULL) { 163 DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, 164 DW_DLV_ERROR); 165 } 166 new_die->di_parent = parent; 167 if (parent->di_child) { 168 169 /* di_last_child identifies the last sibling, the 170 die we want to attach new_die to. */ 171 /* ASSERT: if di_child is set so is di_last_child. */ 172 Dwarf_P_Die former_lastchild = parent->di_last_child; 173 parent->di_last_child = new_die; 174 /* Attach to the new die to end of the sibling list. */ 175 former_lastchild->di_right = new_die; 176 new_die->di_left = former_lastchild; 177 } else { 178 parent->di_child = new_die; 179 parent->di_last_child = new_die; 180 } 181 } 182 if (child != NULL) { 183 n_nulls++; 184 new_die->di_child = child; 185 new_die->di_last_child = child; 186 if (child->di_parent) { 187 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 188 DW_DLV_ERROR); 189 } else { 190 child->di_parent = new_die; 191 } 192 } 193 if (left != NULL) { 194 n_nulls++; 195 new_die->di_left = left; 196 if (left->di_right) { 197 /* There's already a right sibling of left, 198 insert the new die in the list. */ 199 new_die->di_right = left->di_right; 200 left->di_right->di_left = new_die; 201 } 202 left->di_right = new_die; 203 if (new_die->di_parent) { 204 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 205 DW_DLV_ERROR); 206 } else { 207 new_die->di_parent = left->di_parent; 208 } 209 } 210 if (right != NULL) { 211 n_nulls++; 212 new_die->di_right = right; 213 if (right->di_left) { 214 /* There is already a left sibling of the right die, 215 insert the new die in the list. */ 216 new_die->di_left = right->di_left; 217 right->di_left->di_right = new_die; 218 } 219 right->di_left = new_die; 220 if (new_die->di_parent) { 221 DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, 222 DW_DLV_ERROR); 223 } else { 224 new_die->di_parent = right->di_parent; 225 } 226 } 227 if (n_nulls > 1) { 228 /* Multiple neighbors! error! */ 229 DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, 230 DW_DLV_ERROR); 231 } 232 return DW_DLV_OK; 233 } 234 235 Dwarf_Unsigned 236 dwarf_add_die_marker(Dwarf_P_Debug dbg, 237 Dwarf_P_Die die, 238 Dwarf_Unsigned marker, 239 Dwarf_Error * error) { 240 if (die == NULL) { 241 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); 242 } 243 die->di_marker = marker; 244 return 0; 245 } 246 int 247 dwarf_add_die_marker_a(Dwarf_P_Debug dbg, 248 Dwarf_P_Die die, 249 Dwarf_Unsigned marker, 250 Dwarf_Error * error) 251 { 252 if (die == NULL) { 253 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, 254 DW_DLV_ERROR); 255 } 256 die->di_marker = marker; 257 return DW_DLV_OK; 258 } 259 260 261 Dwarf_Unsigned 262 dwarf_get_die_marker(Dwarf_P_Debug dbg, 263 Dwarf_P_Die die, 264 Dwarf_Unsigned * marker, 265 Dwarf_Error * error) 266 { 267 if (die == NULL) { 268 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, 269 DW_DLV_NOCOUNT); 270 } 271 *marker = die->di_marker; 272 return 0; 273 } 274 int 275 dwarf_get_die_marker_a(Dwarf_P_Debug dbg, 276 Dwarf_P_Die die, 277 Dwarf_Unsigned * marker, 278 Dwarf_Error * error) 279 { 280 if (die == NULL) { 281 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, 282 DW_DLV_ERROR); 283 } 284 *marker = die->di_marker; 285 return DW_DLV_ERROR; 286 } 287 288 289 /*--------------------------------------------------------- 290 This function adds a die to dbg struct. It should 291 be called using the root of all the dies. 292 ---------------------------------------------------------*/ 293 /* Original form of this call.. 294 dwarf_add_die_to_debug_a() is preferred now. */ 295 Dwarf_Unsigned 296 dwarf_add_die_to_debug(Dwarf_P_Debug dbg, 297 Dwarf_P_Die first_die, Dwarf_Error * error) 298 { 299 int res = dwarf_add_die_to_debug_a(dbg,first_die,error); 300 if (res == DW_DLV_ERROR) { 301 return DW_DLV_NOCOUNT; 302 } 303 return 0; 304 } 305 306 /* New September 2016. The new and preferred form. */ 307 int 308 dwarf_add_die_to_debug_a(Dwarf_P_Debug dbg, 309 Dwarf_P_Die first_die, Dwarf_Error * error) 310 { 311 if (first_die == NULL) { 312 DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, 313 DW_DLV_ERROR); 314 } 315 if (first_die->di_tag != DW_TAG_compile_unit) { 316 DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, 317 DW_DLV_ERROR); 318 } 319 dbg->de_dies = first_die; 320 return DW_DLV_OK; 321 } 322 323 int 324 _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, 325 Dwarf_P_Die first_die, Dwarf_Error * error) 326 { 327 Dwarf_P_Attribute new_attr; 328 int uwordb_size = dbg->de_dwarf_offset_size; 329 330 /* Add AT_stmt_list attribute */ 331 new_attr = (Dwarf_P_Attribute) 332 _dwarf_p_get_alloc(dbg, 333 sizeof(struct Dwarf_P_Attribute_s)); 334 if (new_attr == NULL) { 335 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, 336 DW_DLV_ERROR); 337 } 338 339 new_attr->ar_attribute = DW_AT_stmt_list; 340 new_attr->ar_attribute_form = 341 dbg->de_ar_data_attribute_form; 342 new_attr->ar_rel_type = dbg->de_offset_reloc; 343 344 new_attr->ar_nbytes = uwordb_size; 345 new_attr->ar_next = NULL; 346 new_attr->ar_reloc_len = uwordb_size; 347 new_attr->ar_data = (char *) 348 _dwarf_p_get_alloc(dbg, uwordb_size); 349 if (new_attr->ar_data == NULL) { 350 DWARF_P_DBG_ERROR(NULL,DW_DLE_ADDR_ALLOC, 351 DW_DLV_ERROR); 352 } 353 { 354 Dwarf_Unsigned du = 0; 355 356 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 357 (const void *) &du, sizeof(du), uwordb_size); 358 } 359 360 _dwarf_pro_add_at_to_die(first_die, new_attr); 361 return DW_DLV_OK; 362 } 363 364 static int 365 _dwarf_debug_str_compare_func(const void *l,const void *r) 366 { 367 const struct Dwarf_P_debug_str_entry_s*el = l; 368 const struct Dwarf_P_debug_str_entry_s*er = r; 369 char *lname = 0; 370 char *rname = 0; 371 int ir = 0; 372 373 if (el->dse_has_table_offset) { 374 /* When set the name is in the debug_str table. */ 375 /* ASSERT: dse_dbg->de_debug_str->ds_data 376 is non-zero. 377 ASSERT: dse_name NULL. */ 378 lname = el->dse_dbg->de_debug_str->ds_data + 379 el->dse_table_offset; 380 } else { 381 /* ASSERT: dse_name non-null */ 382 lname = el->dse_name; 383 } 384 if (er->dse_has_table_offset) { 385 /* When set the name is in the debug_str table. */ 386 /* ASSERT: dse_dbg->de_debug_str->ds_data 387 is non-zero. 388 ASSERT: dse_name NULL. */ 389 rname = er->dse_dbg->de_debug_str->ds_data + 390 er->dse_table_offset; 391 } else { 392 /* ASSERT: dse_name non-null */ 393 rname = er->dse_name; 394 } 395 ir = strcmp(lname,rname); 396 return ir; 397 } 398 399 static void 400 debug_str_entry_free_func(void *m) 401 { 402 free(m); 403 } 404 405 static int 406 make_debug_str_entry(Dwarf_P_Debug dbg, 407 struct Dwarf_P_debug_str_entry_s **mt_out, 408 char *name, 409 unsigned slen, 410 unsigned char has_offset, 411 Dwarf_Unsigned offset_in_table, 412 Dwarf_Error *error) 413 { 414 struct Dwarf_P_debug_str_entry_s *mt = 415 (struct Dwarf_P_debug_str_entry_s *)calloc( 416 sizeof(struct Dwarf_P_debug_str_entry_s),1); 417 if (!mt) { 418 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 419 return DW_DLV_ERROR; 420 } 421 422 mt->dse_slen = slen; 423 mt->dse_table_offset = 0; 424 mt->dse_dbg = dbg; 425 if (has_offset) { 426 mt->dse_has_table_offset = TRUE; 427 mt->dse_table_offset = offset_in_table; 428 mt->dse_name = 0; 429 } else { 430 /* ASSERT: name != NULL */ 431 mt->dse_has_table_offset = FALSE; 432 /* We just set dse_table_offset so it has 433 a known value, though nothing should refer 434 to dse_table_offset because 435 dse_has_table_offset is FALSE.*/ 436 mt->dse_table_offset = 0; 437 mt->dse_name = name; 438 } 439 *mt_out = mt; 440 return DW_DLV_OK; 441 } 442 #define STRTAB_BASE_ALLOC_SIZE 2048 443 static int 444 insert_debug_str_data_string(Dwarf_P_Debug dbg, 445 char *name, 446 unsigned slen, 447 Dwarf_P_Section_Data sd, 448 Dwarf_Unsigned*adding_at_offset, 449 Dwarf_Error * error) 450 { 451 Dwarf_Unsigned current_offset = 0; 452 453 if (!sd->ds_data) { 454 Dwarf_Unsigned initial_alloc = STRTAB_BASE_ALLOC_SIZE; 455 Dwarf_Unsigned base_insert_offset = 0; 456 457 /* Inserting our first string. 458 The GNU linker refuses to commonize strings 459 if the section starts with a NUL byte, 460 so start with real string, using a 461 base_insert_offset of 0. */ 462 if ( (slen + base_insert_offset) >= STRTAB_BASE_ALLOC_SIZE) { 463 initial_alloc = slen *2+ base_insert_offset; 464 } 465 if (initial_alloc < slen) { 466 _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND); 467 return DW_DLV_ERROR; 468 } 469 sd->ds_data = calloc(1,initial_alloc); 470 if (!sd->ds_data) { 471 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 472 return DW_DLV_ERROR; 473 } 474 sd->ds_orig_alloc = initial_alloc; 475 *adding_at_offset = base_insert_offset; 476 sd->ds_nbytes = slen + base_insert_offset; 477 strcpy(sd->ds_data+base_insert_offset,name); 478 return DW_DLV_OK; 479 } 480 current_offset = sd->ds_nbytes; 481 if ( (current_offset + slen) >= sd->ds_orig_alloc) { 482 unsigned updated_length = sd->ds_orig_alloc; 483 char *newbuf = 0; 484 if (slen > updated_length) { 485 /* Very long string passed in. */ 486 updated_length = slen *2; 487 } else { 488 updated_length = updated_length *2; 489 } 490 if (updated_length < sd->ds_orig_alloc) { 491 _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND); 492 return DW_DLV_ERROR; 493 } 494 newbuf = calloc(1,updated_length); 495 if (!newbuf) { 496 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 497 return DW_DLV_ERROR; 498 } 499 memcpy(newbuf,sd->ds_data,sd->ds_nbytes); 500 free(sd->ds_data); 501 sd->ds_data = newbuf; 502 sd->ds_orig_alloc = updated_length; 503 newbuf = 0; 504 } 505 strcpy(sd->ds_data + current_offset,name); 506 sd->ds_nbytes += slen; 507 *adding_at_offset = current_offset; 508 return DW_DLV_OK; 509 } 510 511 /* Find the string offset using the hash table, 512 and if not known, insert the new string. */ 513 int 514 _dwarf_insert_or_find_in_debug_str(Dwarf_P_Debug dbg, 515 char *name, 516 enum dwarf_which_hash whash, 517 unsigned slen, /* includes space for trailing NUL */ 518 Dwarf_Unsigned *offset_in_debug_str, 519 Dwarf_Error *error) 520 { 521 struct Dwarf_P_debug_str_entry_s *mt = 0; 522 struct Dwarf_P_debug_str_entry_s *mt2 = 0; 523 struct Dwarf_P_debug_str_entry_s *retval = 0; 524 struct Dwarf_P_debug_str_entry_s *re = 0; 525 int res = 0; 526 Dwarf_Unsigned adding_at_offset = 0; 527 void **hashtab = 0; 528 Dwarf_P_Section_Data sd = 0; 529 struct Dwarf_P_Str_stats_s * stats = 0; 530 531 switch (whash) { 532 case _dwarf_hash_debug_str: 533 hashtab = &dbg->de_debug_str_hashtab; 534 sd = dbg->de_debug_str; 535 stats = &dbg->de_stats.ps_strp; 536 break; 537 case _dwarf_hash_debug_line_str: 538 hashtab = &dbg->de_debug_line_str_hashtab; 539 sd = dbg->de_debug_line_str; 540 stats = &dbg->de_stats.ps_line_strp; 541 break; 542 case _dwarf_hash_debug_str_sup: 543 default: 544 /* Not supported or unknown. */ 545 _dwarf_p_error(dbg, error, DW_DLE_STRING_HASHTAB_IDENTITY_ERROR); 546 return DW_DLV_ERROR; 547 } 548 res = make_debug_str_entry(dbg,&mt,name, 549 slen,FALSE, 0, error); 550 if (res != DW_DLV_OK) { 551 return res; 552 } 553 /* We do a find as we do not want the string pointer passed in 554 to be in the hash table, we want a pointer into the 555 debug_str table in the hash table. */ 556 retval = dwarf_tfind(mt,(void *const*)hashtab, 557 _dwarf_debug_str_compare_func); 558 if (retval) { 559 560 stats->ps_strp_reused_count++; 561 stats->ps_strp_reused_len += slen; 562 563 re = *(struct Dwarf_P_debug_str_entry_s **)retval; 564 *offset_in_debug_str = re->dse_table_offset; 565 debug_str_entry_free_func(mt); 566 return DW_DLV_OK; 567 } 568 569 /* We know the string is not in .debug_str data yet. 570 Insert it into the big string table and get that 571 offset. */ 572 573 debug_str_entry_free_func(mt); 574 mt = 0; 575 res = insert_debug_str_data_string(dbg,name,slen,sd, 576 &adding_at_offset, error); 577 if (res != DW_DLV_OK) { 578 return res; 579 } 580 581 /* The name is in the string table itself, so use that pointer 582 and offset for the string. */ 583 res = make_debug_str_entry(dbg,&mt2, 0, 584 slen,TRUE,adding_at_offset,error); 585 if (res != DW_DLV_OK) { 586 return res; 587 } 588 retval = dwarf_tsearch(mt2, 589 (void *)hashtab, 590 _dwarf_debug_str_compare_func); 591 if (!retval) { 592 debug_str_entry_free_func(mt2); 593 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 594 return DW_DLV_ERROR; 595 } 596 597 /* This indirection is one of the surprises in using tsearch... */ 598 re = *(struct Dwarf_P_debug_str_entry_s **)retval; 599 if (re != mt2) { 600 debug_str_entry_free_func(mt2); 601 /* Found it in hash tab: illogical as the tsearch_find should 602 have found it. */ 603 _dwarf_p_error(dbg, error, DW_DLE_ILLOGICAL_TSEARCH); 604 return DW_DLV_ERROR; 605 } 606 stats->ps_strp_count_debug_str++; 607 stats->ps_strp_len_debug_str += slen; 608 /* we added it to hash, do not free mt2 (which == re). */ 609 *offset_in_debug_str = re->dse_table_offset; 610 return DW_DLV_OK; 611 } 612 613 /* Returns DW_DLV_OK or DW_DLV_ERROR. */ 614 int _dwarf_pro_set_string_attr(Dwarf_P_Attribute new_attr, 615 Dwarf_P_Debug dbg, 616 char *name, 617 Dwarf_Error *error) 618 { 619 int form = dbg->de_debug_default_str_form; 620 unsigned slen = strlen(name)+1; 621 622 if (form == DW_FORM_string || 623 slen <= dbg->de_dwarf_offset_size) { 624 new_attr->ar_nbytes = slen; 625 new_attr->ar_next = 0; 626 627 new_attr->ar_data = 628 (char *) _dwarf_p_get_alloc(dbg, slen); 629 if (new_attr->ar_data == NULL) { 630 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 631 return DW_DLV_ERROR; 632 } 633 dbg->de_stats.ps_str_count++; 634 dbg->de_stats.ps_str_total_length += slen; 635 636 strcpy(new_attr->ar_data, name); 637 new_attr->ar_attribute_form = DW_FORM_string; 638 new_attr->ar_rel_type = R_MIPS_NONE; 639 new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ 640 return DW_DLV_OK; 641 } 642 if (form == DW_FORM_strp) { 643 int uwordb_size = dbg->de_dwarf_offset_size; 644 Dwarf_Unsigned offset_in_debug_str = 0; 645 int res = 0; 646 647 res = _dwarf_insert_or_find_in_debug_str(dbg,name, 648 _dwarf_hash_debug_str,slen, 649 &offset_in_debug_str,error); 650 if(res != DW_DLV_OK) { 651 return res; 652 } 653 new_attr->ar_attribute_form = form; 654 new_attr->ar_rel_type = dbg->de_offset_reloc; 655 new_attr->ar_nbytes = uwordb_size; 656 new_attr->ar_next = NULL; 657 new_attr->ar_reloc_len = uwordb_size; 658 /* During transform to disk 659 a symbol index will be applied. */ 660 new_attr->ar_data = (char *) 661 _dwarf_p_get_alloc(dbg, uwordb_size); 662 if (new_attr->ar_data == NULL) { 663 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); 664 return DW_DLV_ERROR; 665 } 666 { 667 Dwarf_Unsigned du = offset_in_debug_str; 668 669 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 670 (const void *) &du, sizeof(du), uwordb_size); 671 } 672 673 return DW_DLV_OK; 674 } 675 _dwarf_p_error(dbg, error, DW_DLE_BAD_STRING_FORM); 676 return DW_DLV_ERROR; 677 678 } 679 680 681 /*------------------------------------------------------------------- 682 Add AT_name attribute to die 683 ---------------------------------------------------------------------*/ 684 /* Original function. dwarf_add_AT_name_a() is the 685 suggested alternative. */ 686 Dwarf_P_Attribute 687 dwarf_add_AT_name(Dwarf_P_Die die, 688 char *name, 689 Dwarf_Error * error) 690 { 691 Dwarf_P_Attribute a = 0; 692 int res = 0; 693 694 res = dwarf_add_AT_name_a(die, name, 695 &a, error); 696 if (res == DW_DLV_ERROR) { 697 return (Dwarf_P_Attribute)(DW_DLV_BADADDR); 698 } 699 return a; 700 } 701 702 /* New December 2018. */ 703 int 704 dwarf_add_AT_name_a(Dwarf_P_Die die, char *name, 705 Dwarf_P_Attribute *newattr_out, 706 Dwarf_Error * error) 707 { 708 Dwarf_P_Attribute new_attr = 0; 709 int res = 0; 710 711 if (die == NULL) { 712 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, 713 DW_DLV_ERROR); 714 } 715 new_attr = (Dwarf_P_Attribute) 716 _dwarf_p_get_alloc(die->di_dbg, 717 sizeof(struct Dwarf_P_Attribute_s)); 718 if (new_attr == NULL) { 719 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, 720 DW_DLV_ERROR); 721 } 722 723 /* fill in the information */ 724 new_attr->ar_attribute = DW_AT_name; 725 res = _dwarf_pro_set_string_attr(new_attr,die->di_dbg,name,error); 726 if (res != DW_DLV_OK) { 727 return DW_DLV_ERROR; 728 } 729 730 /* add attribute to the die */ 731 _dwarf_pro_add_at_to_die(die, new_attr); 732 *newattr_out = new_attr; 733 return DW_DLV_OK; 734 } 735 736 737 /*-------------------------------------------------------------------- 738 Add AT_comp_dir attribute to die 739 --------------------------------------------------------------------*/ 740 Dwarf_P_Attribute 741 dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie, 742 char *current_working_directory, 743 Dwarf_Error * error) 744 { 745 Dwarf_P_Attribute a = 0; 746 int res = 0; 747 748 res = dwarf_add_AT_comp_dir_a(ownerdie, 749 current_working_directory, 750 &a, error); 751 if (res != DW_DLV_OK) { 752 return (Dwarf_P_Attribute)(DW_DLV_BADADDR); 753 } 754 return a; 755 } 756 757 int 758 dwarf_add_AT_comp_dir_a(Dwarf_P_Die ownerdie, 759 char *current_working_directory, 760 Dwarf_P_Attribute *attr_out, 761 Dwarf_Error * error) 762 { 763 Dwarf_P_Attribute new_attr = 0; 764 int res = 0; 765 766 if (ownerdie == NULL) { 767 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, 768 DW_DLV_ERROR); 769 } 770 new_attr = (Dwarf_P_Attribute) 771 _dwarf_p_get_alloc(ownerdie->di_dbg, 772 sizeof(struct Dwarf_P_Attribute_s)); 773 if (new_attr == NULL) { 774 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, 775 DW_DLV_ERROR); 776 } 777 778 /* fill in the information */ 779 new_attr->ar_attribute = DW_AT_comp_dir; 780 res = _dwarf_pro_set_string_attr(new_attr,ownerdie->di_dbg, 781 current_working_directory,error); 782 if (res != DW_DLV_OK) { 783 return res; 784 } 785 786 /* add attribute to the die */ 787 _dwarf_pro_add_at_to_die(ownerdie, new_attr); 788 *attr_out = new_attr; 789 return DW_DLV_OK; 790 } 791 792 793 int 794 _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, 795 Dwarf_P_Die die, 796 Dwarf_Unsigned offset, Dwarf_Error * error) 797 { 798 Dwarf_P_Attribute new_attr; 799 int uwordb_size = dbg->de_dwarf_offset_size; 800 801 if (die == NULL) { 802 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR); 803 } 804 new_attr = (Dwarf_P_Attribute) 805 _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); 806 if (new_attr == NULL) { 807 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR); 808 } 809 810 /* fill in the information */ 811 new_attr->ar_attribute = DW_AT_MIPS_fde; 812 new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; 813 new_attr->ar_rel_type = dbg->de_offset_reloc; 814 new_attr->ar_nbytes = uwordb_size; 815 new_attr->ar_next = NULL; 816 new_attr->ar_reloc_len = uwordb_size; 817 new_attr->ar_data = (char *) 818 _dwarf_p_get_alloc(dbg, uwordb_size); 819 if (new_attr->ar_data == NULL) { 820 DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR); 821 } 822 { 823 Dwarf_Unsigned du = offset; 824 825 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 826 (const void *) &du, sizeof(du), uwordb_size); 827 } 828 _dwarf_pro_add_at_to_die(die, new_attr); 829 return DW_DLV_OK; 830 } 831 832 /* Sept 2016: returns DW_DLV_OK or DW_DLV_ERROR */ 833 int 834 _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, 835 Dwarf_P_Die die, 836 Dwarf_Unsigned offset, Dwarf_Error * error) 837 { 838 Dwarf_P_Attribute new_attr; 839 int uwordb_size = dbg->de_dwarf_offset_size; 840 841 if (die == NULL) { 842 DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR); 843 } 844 new_attr = (Dwarf_P_Attribute) 845 _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); 846 if (new_attr == NULL) { 847 DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR); 848 } 849 850 /* fill in the information */ 851 new_attr->ar_attribute = DW_AT_macro_info; 852 new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; 853 new_attr->ar_rel_type = dbg->de_offset_reloc; 854 855 new_attr->ar_nbytes = uwordb_size; 856 new_attr->ar_next = NULL; 857 new_attr->ar_reloc_len = uwordb_size; 858 new_attr->ar_data = (char *) 859 _dwarf_p_get_alloc(dbg, uwordb_size); 860 if (new_attr->ar_data == NULL) { 861 DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR); 862 } 863 { 864 Dwarf_Unsigned du = offset; 865 866 WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, 867 (const void *) &du, sizeof(du), uwordb_size); 868 } 869 870 _dwarf_pro_add_at_to_die(die, new_attr); 871 872 return DW_DLV_OK; 873 } 874 875 876 /* Updates the list of attributes on this Dwarf_P_Die 877 */ 878 void 879 _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr) 880 { 881 if (die->di_last_attr) { 882 /* Inserts new attr at the end */ 883 die->di_last_attr->ar_next = attr; 884 die->di_last_attr = attr; 885 die->di_n_attr++; 886 } else { 887 die->di_n_attr = 1; 888 die->di_attrs = die->di_last_attr = attr; 889 } 890 } 891