1 /* 2 3 Copyright (C) 2000,2004 Silicon Graphics, Inc. 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 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 26 Mountain View, CA 94043, or: 27 28 http://www.sgi.com 29 30 For further information regarding this notice, see: 31 32 http://oss.sgi.com/projects/GenInfo/NoticeExplan 33 34 */ 35 36 37 38 #include "config.h" 39 #include "libdwarfdefs.h" 40 #include <stdio.h> 41 #include <string.h> 42 #include <limits.h> 43 #include "pro_incl.h" 44 #include "pro_frame.h" 45 46 static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, 47 Dwarf_P_Frame_Pgm inst); 48 49 /*------------------------------------------------------------------------- 50 This function adds a cie struct to the debug pointer. Its in the 51 form of a linked list. 52 augmenter: string reps augmentation (implementation defined) 53 code_align: alignment of code 54 data_align: alignment of data 55 init_bytes: byts having initial instructions 56 init_n_bytes: number of bytes of initial instructions 57 --------------------------------------------------------------------------*/ 58 Dwarf_Unsigned 59 dwarf_add_frame_cie(Dwarf_P_Debug dbg, 60 char *augmenter, 61 Dwarf_Small code_align, 62 Dwarf_Small data_align, 63 Dwarf_Small return_reg, 64 Dwarf_Ptr init_bytes, 65 Dwarf_Unsigned init_n_bytes, Dwarf_Error * error) 66 { 67 Dwarf_P_Cie curcie; 68 69 if (dbg->de_frame_cies == NULL) { 70 dbg->de_frame_cies = (Dwarf_P_Cie) 71 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); 72 if (dbg->de_frame_cies == NULL) { 73 DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); 74 } 75 curcie = dbg->de_frame_cies; 76 dbg->de_n_cie = 1; 77 dbg->de_last_cie = curcie; 78 } else { 79 curcie = dbg->de_last_cie; 80 curcie->cie_next = (Dwarf_P_Cie) 81 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); 82 if (curcie->cie_next == NULL) { 83 DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); 84 } 85 curcie = curcie->cie_next; 86 dbg->de_n_cie++; 87 dbg->de_last_cie = curcie; 88 } 89 curcie->cie_version = DW_CIE_VERSION; 90 curcie->cie_aug = augmenter; 91 curcie->cie_code_align = code_align; 92 curcie->cie_data_align = data_align; 93 curcie->cie_ret_reg = return_reg; 94 curcie->cie_inst = (char *) init_bytes; 95 curcie->cie_inst_bytes = (long) init_n_bytes; 96 curcie->cie_next = NULL; 97 return dbg->de_n_cie; 98 } 99 100 101 /*------------------------------------------------------------------------- 102 This functions adds a fde struct to the debug pointer. Its in the 103 form of a linked list. 104 die: subprogram/function die corresponding to this fde 105 cie: cie referred to by this fde, obtained from call to 106 add_frame_cie() routine. 107 virt_addr: beginning address 108 code_len: length of code reps by the fde 109 --------------------------------------------------------------------------*/ 110 /*ARGSUSED*/ /* pretend all args used */ 111 Dwarf_Unsigned 112 dwarf_add_frame_fde(Dwarf_P_Debug dbg, 113 Dwarf_P_Fde fde, 114 Dwarf_P_Die die, 115 Dwarf_Unsigned cie, 116 Dwarf_Unsigned virt_addr, 117 Dwarf_Unsigned code_len, 118 Dwarf_Unsigned symidx, Dwarf_Error * error) 119 { 120 return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, 121 code_len, symidx, 0, 0, error); 122 } 123 124 /*ARGSUSED10*/ 125 Dwarf_Unsigned 126 dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, 127 Dwarf_P_Fde fde, 128 Dwarf_P_Die die, 129 Dwarf_Unsigned cie, 130 Dwarf_Unsigned virt_addr, 131 Dwarf_Unsigned code_len, 132 Dwarf_Unsigned symidx, 133 Dwarf_Unsigned symidx_of_end, 134 Dwarf_Addr offset_from_end_sym, 135 Dwarf_Error * error) 136 { 137 Dwarf_P_Fde curfde; 138 139 fde->fde_die = die; 140 fde->fde_cie = (long) cie; 141 fde->fde_initloc = virt_addr; 142 fde->fde_r_symidx = symidx; 143 fde->fde_addr_range = code_len; 144 fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET; 145 fde->fde_exception_table_symbol = 0; 146 fde->fde_end_symbol_offset = offset_from_end_sym; 147 fde->fde_end_symbol = symidx_of_end; 148 fde->fde_dbg = dbg; 149 150 curfde = dbg->de_last_fde; 151 if (curfde == NULL) { 152 dbg->de_frame_fdes = fde; 153 dbg->de_last_fde = fde; 154 dbg->de_n_fde = 1; 155 } else { 156 curfde->fde_next = fde; 157 dbg->de_last_fde = fde; 158 dbg->de_n_fde++; 159 } 160 return dbg->de_n_fde; 161 } 162 163 /*------------------------------------------------------------------------- 164 This functions adds information to an fde. The fde is 165 linked into the linked list of fde's maintained in the Dwarf_P_Debug 166 structure. 167 dbg: The debug descriptor. 168 fde: The fde to be added. 169 die: subprogram/function die corresponding to this fde 170 cie: cie referred to by this fde, obtained from call to 171 add_frame_cie() routine. 172 virt_addr: beginning address 173 code_len: length of code reps by the fde 174 symidx: The symbol id of the symbol wrt to which relocation needs 175 to be performed for 'virt_addr'. 176 offset_into_exception_tables: The start of exception tables for 177 this function (indicated as an offset into the exception 178 tables). A value of -1 indicates that there is no exception 179 table entries associated with this function. 180 exception_table_symbol: The symbol id of the section for exception 181 tables wrt to which the offset_into_exception_tables will 182 be relocated. 183 --------------------------------------------------------------------------*/ 184 Dwarf_Unsigned 185 dwarf_add_frame_info(Dwarf_P_Debug dbg, 186 Dwarf_P_Fde fde, 187 Dwarf_P_Die die, 188 Dwarf_Unsigned cie, 189 Dwarf_Unsigned virt_addr, 190 Dwarf_Unsigned code_len, 191 Dwarf_Unsigned symidx, 192 Dwarf_Signed offset_into_exception_tables, 193 Dwarf_Unsigned exception_table_symbol, 194 Dwarf_Error * error) 195 { 196 197 return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr, 198 code_len, symidx, 199 /* end_symbol */ 0, 200 /* offset_from_end */ 0, 201 offset_into_exception_tables, 202 exception_table_symbol, error); 203 204 } 205 206 /*ARGSUSED*/ /* pretend all args used */ 207 Dwarf_Unsigned 208 dwarf_add_frame_info_b(Dwarf_P_Debug dbg, 209 Dwarf_P_Fde fde, 210 Dwarf_P_Die die, 211 Dwarf_Unsigned cie, 212 Dwarf_Unsigned virt_addr, 213 Dwarf_Unsigned code_len, 214 Dwarf_Unsigned symidx, 215 Dwarf_Unsigned end_symidx, 216 Dwarf_Unsigned offset_from_end_symbol, 217 Dwarf_Signed offset_into_exception_tables, 218 Dwarf_Unsigned exception_table_symbol, 219 Dwarf_Error * error) 220 { 221 Dwarf_P_Fde curfde; 222 223 fde->fde_die = die; 224 fde->fde_cie = (long) cie; 225 fde->fde_initloc = virt_addr; 226 fde->fde_r_symidx = symidx; 227 fde->fde_addr_range = code_len; 228 fde->fde_offset_into_exception_tables = 229 offset_into_exception_tables; 230 fde->fde_exception_table_symbol = exception_table_symbol; 231 fde->fde_end_symbol_offset = offset_from_end_symbol; 232 fde->fde_end_symbol = end_symidx; 233 fde->fde_dbg = dbg; 234 235 curfde = dbg->de_last_fde; 236 if (curfde == NULL) { 237 dbg->de_frame_fdes = fde; 238 dbg->de_last_fde = fde; 239 dbg->de_n_fde = 1; 240 } else { 241 curfde->fde_next = fde; 242 dbg->de_last_fde = fde; 243 dbg->de_n_fde++; 244 } 245 return dbg->de_n_fde; 246 } 247 248 /* This is an alternate to inserting frame instructions 249 one instruction at a time. But use either this 250 or instruction level, not both in one fde. */ 251 int 252 dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg, 253 Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes, 254 Dwarf_Error *error) 255 { 256 if( len == 0) { 257 return DW_DLV_OK; 258 } 259 if(fde->fde_block || fde->fde_inst) { 260 DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK, 261 (int)DW_DLV_BADADDR); 262 } 263 fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len); 264 memcpy(fde->fde_block,ibytes,len); 265 fde->fde_inst_block_size = len; 266 fde->fde_n_bytes += len; 267 return DW_DLV_OK; 268 } 269 270 271 272 /*------------------------------------------------------------------- 273 Create a new fde. 274 ---------------------------------------------------------------------*/ 275 Dwarf_P_Fde 276 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error) 277 { 278 Dwarf_P_Fde fde; 279 280 fde = (Dwarf_P_Fde) 281 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s)); 282 if (fde == NULL) { 283 DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, 284 (Dwarf_P_Fde) DW_DLV_BADADDR); 285 } 286 287 fde->fde_uwordb_size = dbg->de_offset_size; 288 289 return fde; 290 } 291 292 293 /*------------------------------------------------------------------------ 294 Add a cfe_offset instruction to the fde passed in. 295 -------------------------------------------------------------------------*/ 296 Dwarf_P_Fde 297 dwarf_fde_cfa_offset(Dwarf_P_Fde fde, 298 Dwarf_Unsigned reg, 299 Dwarf_Signed offset, Dwarf_Error * error) 300 { 301 Dwarf_Ubyte opc, regno; 302 char *ptr; 303 Dwarf_P_Frame_Pgm curinst; 304 int nbytes; 305 int res; 306 char buff1[ENCODE_SPACE_NEEDED]; 307 Dwarf_P_Debug dbg = fde->fde_dbg; 308 309 curinst = (Dwarf_P_Frame_Pgm) 310 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); 311 if (curinst == NULL) { 312 DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, 313 (Dwarf_P_Fde) DW_DLV_BADADDR); 314 } 315 opc = DW_CFA_offset; 316 regno = reg; 317 if (regno & 0xc0) { 318 DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL, 319 (Dwarf_P_Fde) DW_DLV_BADADDR); 320 } 321 opc = opc | regno; /* lower 6 bits are register number */ 322 curinst->dfp_opcode = opc; 323 res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, 324 buff1, sizeof(buff1)); 325 if (res != DW_DLV_OK) { 326 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 327 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 328 } 329 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); 330 if (ptr == NULL) { 331 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 332 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 333 } 334 memcpy(ptr, buff1, nbytes); 335 336 curinst->dfp_args = ptr; 337 curinst->dfp_nbytes = nbytes; 338 curinst->dfp_next = NULL; 339 340 _dwarf_pro_add_to_fde(fde, curinst); 341 return fde; 342 } 343 344 /* 345 Generic routine to add opcode to fde instructions. val1 and 346 val2 are parameters whose interpretation depends on the 'op'. 347 348 This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS 349 for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as 350 these ops normally are addresses or (DW_CFA_set_loc) 351 or code lengths (DW_DVA_advance_loc*) and such must be 352 represented with relocations and symbol indices for 353 DW_DLC_SYMBOLIC_RELOCATIONS. 354 355 This does not treat all DW_CFA instructions yet. 356 357 For certain operations a val? value must be 358 signed (though passed in as unsigned here). 359 360 Currently this does not check that the frame 361 version is 3(for dwarf3) or 4 (for dwarf4) 362 when applying operations that are only valid for 363 dwarf3 or dwarf4. 364 365 */ 366 Dwarf_P_Fde 367 dwarf_add_fde_inst(Dwarf_P_Fde fde, 368 Dwarf_Small op, 369 Dwarf_Unsigned val1, 370 Dwarf_Unsigned val2, Dwarf_Error * error) 371 { 372 Dwarf_P_Frame_Pgm curinst; 373 int nbytes, nbytes1, nbytes2; 374 Dwarf_Ubyte db; 375 Dwarf_Half dh; 376 Dwarf_Word dw; 377 Dwarf_Unsigned du; 378 char *ptr; 379 int res; 380 char buff1[ENCODE_SPACE_NEEDED]; 381 char buff2[ENCODE_SPACE_NEEDED]; 382 Dwarf_P_Debug dbg = fde->fde_dbg; 383 /* This is a hack telling the code when to transform 384 a value to a signed leb number. */ 385 int signed_second = 0; 386 int signed_first = 0; 387 388 389 nbytes = 0; 390 ptr = NULL; 391 curinst = (Dwarf_P_Frame_Pgm) 392 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); 393 if (curinst == NULL) { 394 _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC); 395 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 396 } 397 398 switch (op) { 399 400 case DW_CFA_advance_loc: 401 if (val1 <= 0x3f) { 402 db = val1; 403 op |= db; 404 } 405 /* test not portable FIX */ 406 else if (val1 <= UCHAR_MAX) { 407 op = DW_CFA_advance_loc1; 408 db = val1; 409 ptr = (char *) _dwarf_p_get_alloc(dbg, 1); 410 if (ptr == NULL) { 411 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 412 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 413 } 414 memcpy((void *) ptr, (const void *) &db, 1); 415 nbytes = 1; 416 } 417 /* test not portable FIX */ 418 else if (val1 <= USHRT_MAX) { 419 op = DW_CFA_advance_loc2; 420 dh = val1; 421 ptr = (char *) _dwarf_p_get_alloc(dbg, 2); 422 if (ptr == NULL) { 423 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 424 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 425 } 426 memcpy((void *) ptr, (const void *) &dh, 2); 427 nbytes = 2; 428 } 429 /* test not portable FIX */ 430 else if (val1 <= ULONG_MAX) { 431 op = DW_CFA_advance_loc4; 432 dw = (Dwarf_Word) val1; 433 ptr = (char *) _dwarf_p_get_alloc(dbg, 4); 434 if (ptr == NULL) { 435 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 436 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 437 } 438 memcpy((void *) ptr, (const void *) &dw, 4); 439 nbytes = 4; 440 } else { 441 op = DW_CFA_MIPS_advance_loc8; 442 du = val1; 443 ptr = 444 (char *) _dwarf_p_get_alloc(dbg, 445 sizeof(Dwarf_Unsigned)); 446 if (ptr == NULL) { 447 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 448 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 449 } 450 memcpy((void *) ptr, (const void *) &du, 8); 451 nbytes = 8; 452 } 453 break; 454 455 case DW_CFA_offset: 456 if (val1 <= MAX_6_BIT_VALUE) { 457 db = val1; 458 op |= db; 459 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes, 460 buff1, sizeof(buff1)); 461 if (res != DW_DLV_OK) { 462 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 463 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 464 } 465 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); 466 if (ptr == NULL) { 467 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 468 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 469 } 470 memcpy(ptr, buff1, nbytes); 471 472 } else { 473 op = DW_CFA_offset_extended; 474 goto two_leb; 475 } 476 break; 477 case DW_CFA_offset_extended_sf: /* DWARF3 */ 478 signed_second = 1; 479 goto two_leb; 480 case DW_CFA_offset_extended: 481 goto two_leb; 482 483 case DW_CFA_undefined: 484 case DW_CFA_same_value: 485 goto one_leb; 486 487 case DW_CFA_val_offset: 488 goto two_leb; 489 case DW_CFA_val_offset_sf: 490 signed_second = 1; 491 goto two_leb; 492 case DW_CFA_def_cfa_sf: 493 signed_second = 1; 494 goto two_leb; 495 case DW_CFA_register: 496 case DW_CFA_def_cfa: 497 two_leb: 498 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, 499 buff1, sizeof(buff1)); 500 if (res != DW_DLV_OK) { 501 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 502 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 503 } 504 if (!signed_second) { 505 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, 506 buff2, sizeof(buff2)); 507 } else { 508 Dwarf_Signed val2s = val2; 509 res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2, 510 buff2, sizeof(buff2)); 511 } 512 513 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, 514 buff2, sizeof(buff2)); 515 if (res != DW_DLV_OK) { 516 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 517 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 518 } 519 520 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2); 521 if (ptr == NULL) { 522 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 523 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 524 } 525 memcpy(ptr, buff1, nbytes1); 526 memcpy(ptr + nbytes1, buff2, nbytes2); 527 nbytes = nbytes1 + nbytes2; 528 break; 529 530 case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ 531 signed_first = 1; 532 goto one_leb; 533 case DW_CFA_def_cfa_register: 534 case DW_CFA_def_cfa_offset: 535 one_leb: 536 if(!signed_first) { 537 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, 538 buff1, sizeof(buff1)); 539 } else { 540 Dwarf_Signed val1s = val1; 541 res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes, 542 buff1, sizeof(buff1)); 543 } 544 if (res != DW_DLV_OK) { 545 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 546 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 547 } 548 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); 549 if (ptr == NULL) { 550 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); 551 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 552 } 553 memcpy(ptr, buff1, nbytes); 554 break; 555 case DW_CFA_def_cfa_expression: /* DWARF3 */ 556 /* FIXME: argument is dwarf expr, not handled yet. */ 557 case DW_CFA_expression: /* DWARF3 */ 558 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. 559 FIXME: not handled yet. */ 560 case DW_CFA_val_expression: /* DWARF3f */ 561 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block. 562 FIXME: not handled yet. */ 563 default: 564 _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR); 565 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 566 } 567 568 curinst->dfp_opcode = op; 569 curinst->dfp_args = ptr; 570 curinst->dfp_nbytes = nbytes; 571 curinst->dfp_next = NULL; 572 573 _dwarf_pro_add_to_fde(fde, curinst); 574 return fde; 575 } 576 577 578 /*------------------------------------------------------------------------ 579 Instructions are added to an fde in the form of a linked 580 list. This function manages the linked list. 581 -------------------------------------------------------------------------*/ 582 void 583 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst) 584 { 585 if (fde->fde_last_inst) { 586 fde->fde_last_inst->dfp_next = curinst; 587 fde->fde_last_inst = curinst; 588 fde->fde_n_inst++; 589 fde->fde_n_bytes += 590 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); 591 } else { 592 fde->fde_last_inst = curinst; 593 fde->fde_inst = curinst; 594 fde->fde_n_inst = 1; 595 fde->fde_n_bytes = 596 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); 597 } 598 } 599