1 /* 2 3 Copyright (C) 2000 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, 23 USA. 24 25 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 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 functions 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 149 curfde = dbg->de_last_fde; 150 if (curfde == NULL) { 151 dbg->de_frame_fdes = fde; 152 dbg->de_last_fde = fde; 153 dbg->de_n_fde = 1; 154 } else { 155 curfde->fde_next = fde; 156 dbg->de_last_fde = fde; 157 dbg->de_n_fde++; 158 } 159 return dbg->de_n_fde; 160 } 161 162 /*------------------------------------------------------------------------- 163 This functions adds information to an fde. The fde is 164 linked into the linked list of fde's maintained in the Dwarf_P_Debug 165 structure. 166 dbg: The debug descriptor. 167 fde: The fde to be added. 168 die: subprogram/function die corresponding to this fde 169 cie: cie referred to by this fde, obtained from call to 170 add_frame_cie() routine. 171 virt_addr: beginning address 172 code_len: length of code reps by the fde 173 symidx: The symbol id of the symbol wrt to which relocation needs 174 to be performed for 'virt_addr'. 175 offset_into_exception_tables: The start of exception tables for 176 this function (indicated as an offset into the exception 177 tables). A value of -1 indicates that there is no exception 178 table entries associated with this function. 179 exception_table_symbol: The symbol id of the section for exception 180 tables wrt to which the offset_into_exception_tables will 181 be relocated. 182 --------------------------------------------------------------------------*/ 183 Dwarf_Unsigned 184 dwarf_add_frame_info(Dwarf_P_Debug dbg, 185 Dwarf_P_Fde fde, 186 Dwarf_P_Die die, 187 Dwarf_Unsigned cie, 188 Dwarf_Unsigned virt_addr, 189 Dwarf_Unsigned code_len, 190 Dwarf_Unsigned symidx, 191 Dwarf_Signed offset_into_exception_tables, 192 Dwarf_Unsigned exception_table_symbol, 193 Dwarf_Error * error) 194 { 195 196 return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr, 197 code_len, symidx, 198 /* end_symbol */ 0, 199 /* offset_from_end */ 0, 200 offset_into_exception_tables, 201 exception_table_symbol, error); 202 203 } 204 205 /*ARGSUSED*/ /* pretend all args used */ 206 Dwarf_Unsigned 207 dwarf_add_frame_info_b(Dwarf_P_Debug dbg, 208 Dwarf_P_Fde fde, 209 Dwarf_P_Die die, 210 Dwarf_Unsigned cie, 211 Dwarf_Unsigned virt_addr, 212 Dwarf_Unsigned code_len, 213 Dwarf_Unsigned symidx, 214 Dwarf_Unsigned end_symidx, 215 Dwarf_Unsigned offset_from_end_symbol, 216 Dwarf_Signed offset_into_exception_tables, 217 Dwarf_Unsigned exception_table_symbol, 218 Dwarf_Error * error) 219 { 220 Dwarf_P_Fde curfde; 221 222 fde->fde_die = die; 223 fde->fde_cie = (long) cie; 224 fde->fde_initloc = virt_addr; 225 fde->fde_r_symidx = symidx; 226 fde->fde_addr_range = code_len; 227 fde->fde_offset_into_exception_tables = 228 offset_into_exception_tables; 229 fde->fde_exception_table_symbol = exception_table_symbol; 230 fde->fde_end_symbol_offset = offset_from_end_symbol; 231 fde->fde_end_symbol = end_symidx; 232 233 234 curfde = dbg->de_last_fde; 235 if (curfde == NULL) { 236 dbg->de_frame_fdes = fde; 237 dbg->de_last_fde = fde; 238 dbg->de_n_fde = 1; 239 } else { 240 curfde->fde_next = fde; 241 dbg->de_last_fde = fde; 242 dbg->de_n_fde++; 243 } 244 return dbg->de_n_fde; 245 } 246 247 248 /*------------------------------------------------------------------- 249 Create a new fde 250 ---------------------------------------------------------------------*/ 251 Dwarf_P_Fde 252 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error) 253 { 254 Dwarf_P_Fde fde; 255 256 fde = (Dwarf_P_Fde) 257 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s)); 258 if (fde == NULL) { 259 DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, 260 (Dwarf_P_Fde) DW_DLV_BADADDR); 261 } 262 fde->fde_next = NULL; 263 fde->fde_inst = NULL; 264 fde->fde_n_inst = 0; 265 fde->fde_n_bytes = 0; 266 fde->fde_last_inst = NULL; 267 fde->fde_uwordb_size = dbg->de_offset_size; 268 return fde; 269 } 270 271 /*------------------------------------------------------------------------ 272 Add cfe_offset instruction to fde 273 -------------------------------------------------------------------------*/ 274 Dwarf_P_Fde 275 dwarf_fde_cfa_offset(Dwarf_P_Fde fde, 276 Dwarf_Unsigned reg, 277 Dwarf_Signed offset, Dwarf_Error * error) 278 { 279 Dwarf_Ubyte opc, regno; 280 char *ptr; 281 Dwarf_P_Frame_Pgm curinst; 282 int nbytes; 283 int res; 284 char buff1[ENCODE_SPACE_NEEDED]; 285 286 curinst = (Dwarf_P_Frame_Pgm) 287 _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s)); 288 if (curinst == NULL) { 289 DWARF_P_DBG_ERROR(NULL, DW_DLE_FPGM_ALLOC, 290 (Dwarf_P_Fde) DW_DLV_BADADDR); 291 } 292 opc = DW_CFA_offset; 293 regno = reg; 294 if (regno & 0xc0) { 295 DWARF_P_DBG_ERROR(NULL, DW_DLE_REGNO_OVFL, 296 (Dwarf_P_Fde) DW_DLV_BADADDR); 297 } 298 opc = opc | regno; /* lower 6 bits are register number */ 299 curinst->dfp_opcode = opc; 300 res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, 301 buff1, sizeof(buff1)); 302 if (res != DW_DLV_OK) { 303 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 304 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 305 } 306 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); 307 if (ptr == NULL) { 308 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 309 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 310 } 311 memcpy(ptr, buff1, nbytes); 312 313 curinst->dfp_args = ptr; 314 curinst->dfp_nbytes = nbytes; 315 curinst->dfp_next = NULL; 316 317 _dwarf_pro_add_to_fde(fde, curinst); 318 return fde; 319 } 320 321 /* 322 Generic routine to add opcode to fde instructions. val1 and 323 val2 are parameters whose interpretation depends on the 'op'. 324 325 This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS 326 for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as 327 these ops normally are addresses or (DW_CFA_set_loc) 328 or code lengths (DW_DVA_advance_loc*) and such must be 329 represented with relocations and symbol indices for 330 DW_DLC_SYMBOLIC_RELOCATIONS. 331 332 */ 333 Dwarf_P_Fde 334 dwarf_add_fde_inst(Dwarf_P_Fde fde, 335 Dwarf_Small op, 336 Dwarf_Unsigned val1, 337 Dwarf_Unsigned val2, Dwarf_Error * error) 338 { 339 Dwarf_P_Frame_Pgm curinst; 340 int nbytes, nbytes1, nbytes2; 341 Dwarf_Ubyte db; 342 Dwarf_Half dh; 343 Dwarf_Word dw; 344 Dwarf_Unsigned du; 345 char *ptr; 346 int res; 347 char buff1[ENCODE_SPACE_NEEDED]; 348 char buff2[ENCODE_SPACE_NEEDED]; 349 350 351 nbytes = 0; 352 ptr = NULL; 353 curinst = (Dwarf_P_Frame_Pgm) 354 _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s)); 355 if (curinst == NULL) { 356 _dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC); 357 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 358 } 359 360 switch (op) { 361 362 case DW_CFA_advance_loc: 363 if (val1 <= 0x3f) { 364 db = val1; 365 op |= db; 366 } 367 /* test not portable FIX */ 368 else if (val1 <= UCHAR_MAX) { 369 op = DW_CFA_advance_loc1; 370 db = val1; 371 ptr = (char *) _dwarf_p_get_alloc(NULL, 1); 372 if (ptr == NULL) { 373 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 374 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 375 } 376 memcpy((void *) ptr, (const void *) &db, 1); 377 nbytes = 1; 378 } 379 /* test not portable FIX */ 380 else if (val1 <= USHRT_MAX) { 381 op = DW_CFA_advance_loc2; 382 dh = val1; 383 ptr = (char *) _dwarf_p_get_alloc(NULL, 2); 384 if (ptr == NULL) { 385 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 386 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 387 } 388 memcpy((void *) ptr, (const void *) &dh, 2); 389 nbytes = 2; 390 } 391 /* test not portable FIX */ 392 else if (val1 <= ULONG_MAX) { 393 op = DW_CFA_advance_loc4; 394 dw = (Dwarf_Word) val1; 395 ptr = (char *) _dwarf_p_get_alloc(NULL, 4); 396 if (ptr == NULL) { 397 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 398 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 399 } 400 memcpy((void *) ptr, (const void *) &dw, 4); 401 nbytes = 4; 402 } else { 403 op = DW_CFA_MIPS_advance_loc8; 404 du = val1; 405 ptr = 406 (char *) _dwarf_p_get_alloc(NULL, 407 sizeof(Dwarf_Unsigned)); 408 if (ptr == NULL) { 409 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 410 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 411 } 412 memcpy((void *) ptr, (const void *) &du, 8); 413 nbytes = 8; 414 } 415 break; 416 417 case DW_CFA_offset: 418 if (val1 <= MAX_6_BIT_VALUE) { 419 db = val1; 420 op |= db; 421 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes, 422 buff1, sizeof(buff1)); 423 if (res != DW_DLV_OK) { 424 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 425 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 426 } 427 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); 428 if (ptr == NULL) { 429 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 430 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 431 } 432 memcpy(ptr, buff1, nbytes); 433 434 } else { 435 op = DW_CFA_offset_extended; 436 437 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, 438 buff1, sizeof(buff1)); 439 if (res != DW_DLV_OK) { 440 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 441 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 442 } 443 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, 444 buff2, sizeof(buff2)); 445 if (res != DW_DLV_OK) { 446 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 447 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 448 } 449 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2); 450 if (ptr == NULL) { 451 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 452 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 453 } 454 memcpy(ptr, buff1, nbytes1); 455 memcpy(ptr + nbytes1, buff2, nbytes2); 456 nbytes = nbytes1 + nbytes2; 457 } 458 break; 459 460 case DW_CFA_undefined: 461 case DW_CFA_same_value: 462 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, 463 buff1, sizeof(buff1)); 464 if (res != DW_DLV_OK) { 465 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 466 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 467 } 468 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); 469 if (ptr == NULL) { 470 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 471 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 472 } 473 memcpy(ptr, buff1, nbytes); 474 break; 475 476 case DW_CFA_register: 477 case DW_CFA_def_cfa: 478 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, 479 buff1, sizeof(buff1)); 480 if (res != DW_DLV_OK) { 481 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 482 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 483 } 484 485 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, 486 buff2, sizeof(buff2)); 487 if (res != DW_DLV_OK) { 488 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 489 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 490 } 491 492 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2); 493 if (ptr == NULL) { 494 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 495 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 496 } 497 memcpy(ptr, buff1, nbytes1); 498 memcpy(ptr + nbytes1, buff2, nbytes2); 499 nbytes = nbytes1 + nbytes2; 500 break; 501 502 case DW_CFA_def_cfa_register: 503 case DW_CFA_def_cfa_offset: 504 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, 505 buff1, sizeof(buff1)); 506 if (res != DW_DLV_OK) { 507 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 508 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 509 } 510 ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); 511 if (ptr == NULL) { 512 _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); 513 return ((Dwarf_P_Fde) DW_DLV_BADADDR); 514 } 515 memcpy(ptr, buff1, nbytes); 516 break; 517 518 default: 519 break; 520 } 521 522 curinst->dfp_opcode = op; 523 curinst->dfp_args = ptr; 524 curinst->dfp_nbytes = nbytes; 525 curinst->dfp_next = NULL; 526 527 _dwarf_pro_add_to_fde(fde, curinst); 528 return fde; 529 } 530 531 532 /*------------------------------------------------------------------------ 533 instructions are added to fde in the form of a linked 534 list. This function manages the linked list 535 -------------------------------------------------------------------------*/ 536 void 537 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst) 538 { 539 if (fde->fde_last_inst) { 540 fde->fde_last_inst->dfp_next = curinst; 541 fde->fde_last_inst = curinst; 542 fde->fde_n_inst++; 543 fde->fde_n_bytes += 544 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); 545 } else { 546 fde->fde_last_inst = curinst; 547 fde->fde_inst = curinst; 548 fde->fde_n_inst = 1; 549 fde->fde_n_bytes = 550 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte)); 551 } 552 } 553