1 /* 2 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. 3 Portions Copyright 2011-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 "libdwarfdefs.h" 29 #include <stdio.h> 30 #include <string.h> 31 32 #include "pro_incl.h" 33 #include <stddef.h> 34 #include "dwarf.h" 35 #include "libdwarf.h" 36 #include "pro_opaque.h" 37 #include "pro_error.h" 38 #include "pro_alloc.h" 39 #include "pro_encode_nm.h" 40 #include "pro_line.h" 41 42 static int _dwarf_pro_add_line_entry(Dwarf_P_Debug, 43 Dwarf_Unsigned file_index, 44 Dwarf_Addr code_address, 45 Dwarf_Unsigned symidx, 46 Dwarf_Unsigned line_no, 47 Dwarf_Signed col_no, 48 Dwarf_Bool is_stmt_begin, 49 Dwarf_Bool is_bb_begin, 50 Dwarf_Ubyte opc, 51 Dwarf_Bool isepilbeg, 52 Dwarf_Bool isprolend, 53 Dwarf_Unsigned isa, 54 Dwarf_Unsigned discriminator, 55 Dwarf_Error * error); 56 57 /* Add a entry to the line information section 58 file_index: index of file in file entries, obtained from 59 add_file_entry() call. 60 61 This function actually calls _dwarf_pro_add_line_entry(), with 62 an extra parameter, the opcode. Done so that interface calls 63 dwarf_lne_set_address() and dwarf_lne_end_sequence() can use 64 this internal routine. 65 66 The return value of the original 67 interfaces is really signed. Bogus interface. 68 With dwarf_add_line_entry_c the interface is corrected. */ 69 Dwarf_Unsigned 70 dwarf_add_line_entry_b(Dwarf_P_Debug dbg, 71 Dwarf_Unsigned file_index, 72 Dwarf_Addr code_address, 73 Dwarf_Unsigned line_no, 74 Dwarf_Signed col_no, 75 Dwarf_Bool is_stmt_begin, 76 Dwarf_Bool is_bb_begin, 77 Dwarf_Bool isepilbeg, 78 Dwarf_Bool isprolend, 79 Dwarf_Unsigned isa, 80 Dwarf_Unsigned discriminator, 81 Dwarf_Error * error) 82 { 83 Dwarf_Unsigned retval = 0; 84 Dwarf_Ubyte opc = 0; 85 Dwarf_Unsigned symidx = 0; 86 87 retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 88 symidx, 89 line_no, col_no, is_stmt_begin, 90 is_bb_begin, 91 opc, 92 isepilbeg,isprolend,isa,discriminator, error); 93 if (retval != DW_DLV_OK) { 94 return DW_DLV_NOCOUNT; 95 } 96 return 0; 97 } 98 int 99 dwarf_add_line_entry_c(Dwarf_P_Debug dbg, 100 Dwarf_Unsigned file_index, 101 Dwarf_Addr code_address, 102 Dwarf_Unsigned line_no, 103 Dwarf_Signed col_no, 104 Dwarf_Bool is_stmt_begin, 105 Dwarf_Bool is_bb_begin, 106 Dwarf_Bool isepilbeg, 107 Dwarf_Bool isprolend, 108 Dwarf_Unsigned isa, 109 Dwarf_Unsigned discriminator, 110 Dwarf_Error * error) 111 { 112 int retval = 0; 113 Dwarf_Ubyte opc = 0; 114 Dwarf_Unsigned symidx = 0; 115 116 retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 117 symidx, 118 line_no, col_no, is_stmt_begin, 119 is_bb_begin, 120 opc, 121 isepilbeg,isprolend,isa,discriminator, error); 122 return retval; 123 } 124 125 126 127 /* The return value is really signed. Bogus interface.*/ 128 Dwarf_Unsigned 129 dwarf_add_line_entry(Dwarf_P_Debug dbg, 130 Dwarf_Unsigned file_index, 131 Dwarf_Addr code_address, 132 Dwarf_Unsigned line_no, 133 Dwarf_Signed col_no, /* Wrong, should be unsigned. */ 134 Dwarf_Bool is_stmt_begin, 135 Dwarf_Bool is_bb_begin, Dwarf_Error * error) 136 { 137 int retval = 0; 138 Dwarf_Ubyte opc = 0; 139 Dwarf_Unsigned symidx = 0; 140 Dwarf_Bool isepilbeg = 0; 141 Dwarf_Bool isprolend = 0; 142 Dwarf_Unsigned isa = 0; 143 Dwarf_Unsigned discriminator = 0; 144 145 retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 146 symidx, 147 line_no, col_no, is_stmt_begin, 148 is_bb_begin, 149 opc, 150 isepilbeg, isprolend, isa, discriminator, 151 error); 152 if (retval != DW_DLV_OK) { 153 return DW_DLV_NOCOUNT; 154 } 155 return 0; 156 } 157 158 void 159 _dwarf_init_default_line_header_vals(Dwarf_P_Debug dbg) 160 { 161 dbg->de_line_inits.pi_linetable_version = dbg->de_output_version; 162 dbg->de_line_inits.pi_default_is_stmt = 163 /* is false pro_line.h */ 164 DEFAULT_IS_STMT; 165 dbg->de_line_inits.pi_minimum_instruction_length = 166 /* is 1 or 4 depending on ifdefs in pro_line.h */ 167 MIN_INST_LENGTH; 168 dbg->de_line_inits.pi_maximum_operations_per_instruction = 169 /* Assuming the instruction set is not VLIW, 170 used in the line table */ 171 1; 172 dbg->de_line_inits.pi_opcode_base = 173 /* is 10 in pro_line.h but should be 13 in DWARF3 174 and later. */ 175 OPCODE_BASE; 176 dbg->de_line_inits.pi_line_base = 177 /* is -1 in pro_line.h */ 178 LINE_BASE; 179 dbg->de_line_inits.pi_line_range = 180 /* is 4 in pro_line.h */ 181 LINE_RANGE; 182 183 /* Applies to line table and everywhere else 184 for a CU. */ 185 dbg->de_line_inits.pi_address_size = dbg->de_pointer_size; 186 187 /* Assuming no segments. */ 188 dbg->de_line_inits.pi_segment_selector_size = 0; 189 dbg->de_line_inits.pi_segment_size = 0; 190 } 191 192 193 /* Ask to emit DW_LNE_set_address opcode explicitly. Used by be 194 to emit start of a new .text section, or to force a relocated 195 address into debug line information entry. */ 196 Dwarf_Unsigned 197 dwarf_lne_set_address(Dwarf_P_Debug dbg, 198 Dwarf_Addr offs, 199 Dwarf_Unsigned symidx, Dwarf_Error * error) 200 { 201 int res = 0; 202 203 res = dwarf_lne_set_address_a(dbg,offs,symidx,error); 204 if (res != DW_DLV_OK) { 205 return DW_DLV_NOCOUNT; 206 } 207 return 0; 208 209 } 210 int 211 dwarf_lne_set_address_a(Dwarf_P_Debug dbg, 212 Dwarf_Addr offs, 213 Dwarf_Unsigned symidx, Dwarf_Error * error) 214 { 215 int retval = 0; 216 Dwarf_Ubyte opc = 0; 217 Dwarf_Unsigned file_index = 0; 218 Dwarf_Unsigned line_no = 0; 219 Dwarf_Signed col_no = 0; 220 Dwarf_Bool is_stmt = 0; 221 Dwarf_Bool is_bb = 0; 222 Dwarf_Bool isepilbeg = 0; 223 Dwarf_Bool isprolend = 0; 224 Dwarf_Unsigned isa = 0; 225 Dwarf_Unsigned discriminator = 0; 226 227 228 opc = DW_LNE_set_address; 229 retval = _dwarf_pro_add_line_entry(dbg, file_index, offs, 230 symidx, 231 line_no, col_no, is_stmt, 232 is_bb, 233 opc, 234 isepilbeg, isprolend, isa, discriminator, 235 error); 236 return retval; 237 } 238 239 /* Ask to emit end_seqence opcode. Used normally at the end of a 240 compilation unit. Can also be used in the middle if there 241 are gaps in the region described by the code address. */ 242 Dwarf_Unsigned 243 dwarf_lne_end_sequence(Dwarf_P_Debug dbg, 244 Dwarf_Addr end_address, Dwarf_Error * error) 245 { 246 int retval = 0; 247 248 retval = dwarf_lne_end_sequence_a(dbg,end_address,error); 249 if (retval != DW_DLV_OK) { 250 return DW_DLV_NOCOUNT; 251 } 252 return 0; 253 } 254 int 255 dwarf_lne_end_sequence_a(Dwarf_P_Debug dbg, 256 Dwarf_Addr end_address, Dwarf_Error * error) 257 { 258 Dwarf_Ubyte opc = 0; 259 int retval = 0; 260 Dwarf_Unsigned file_index = 0; 261 Dwarf_Unsigned symidx = 0; 262 Dwarf_Unsigned line_no = 0; 263 Dwarf_Bool is_stmt = 0; 264 Dwarf_Bool is_bb = 0; 265 Dwarf_Signed col_no = 0;/* Wrong, should be unsigned. */ 266 Dwarf_Bool isepilbeg = 0; 267 Dwarf_Bool isprolend = 0; 268 Dwarf_Unsigned isa = 0; 269 Dwarf_Unsigned discriminator = 0; 270 271 opc = DW_LNE_end_sequence; 272 retval = _dwarf_pro_add_line_entry(dbg, file_index, end_address, 273 symidx, 274 line_no, col_no, is_stmt, 275 is_bb, 276 opc, 277 isepilbeg, isprolend, isa, discriminator, 278 error); 279 return retval; 280 } 281 282 /* As of December 2018 this returns DW_DLV_OK, DW_DLV_ERROR 283 not 0, DW_DLV_NOCOUNT*/ 284 /* Add an entry in the internal list of lines mantained by producer. 285 Opc indicates if an opcode needs to be generated, rather than just 286 an entry in the matrix. During opcodes generation time, these 287 opcodes will be used. */ 288 static int 289 _dwarf_pro_add_line_entry(Dwarf_P_Debug dbg, 290 Dwarf_Unsigned file_index, 291 Dwarf_Addr code_address, 292 Dwarf_Unsigned symidx, 293 Dwarf_Unsigned line_no, 294 Dwarf_Signed col_no, 295 Dwarf_Bool is_stmt_begin, 296 Dwarf_Bool is_bb_begin, 297 Dwarf_Ubyte opc, 298 Dwarf_Bool isepilbeg, 299 Dwarf_Bool isprolend, 300 Dwarf_Unsigned isa, 301 Dwarf_Unsigned discriminator, 302 Dwarf_Error * error) 303 { 304 if (dbg->de_lines == NULL) { 305 dbg->de_lines = (Dwarf_P_Line) 306 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); 307 if (dbg->de_lines == NULL) { 308 DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_ERROR); 309 } 310 dbg->de_last_line = dbg->de_lines; 311 _dwarf_pro_reg_init(dbg,dbg->de_lines); 312 313 } else { 314 dbg->de_last_line->dpl_next = (Dwarf_P_Line) 315 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s)); 316 if (dbg->de_last_line->dpl_next == NULL) { 317 DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_ERROR); 318 } 319 dbg->de_last_line = dbg->de_last_line->dpl_next; 320 _dwarf_pro_reg_init(dbg,dbg->de_last_line); 321 } 322 dbg->de_last_line->dpl_address = code_address; 323 dbg->de_last_line->dpl_file = (unsigned long) file_index; 324 dbg->de_last_line->dpl_line = (unsigned long) line_no; 325 dbg->de_last_line->dpl_column = (unsigned long) col_no; 326 dbg->de_last_line->dpl_is_stmt = is_stmt_begin; 327 dbg->de_last_line->dpl_basic_block = is_bb_begin; 328 dbg->de_last_line->dpl_opc = opc; 329 dbg->de_last_line->dpl_r_symidx = symidx; 330 dbg->de_last_line->dpl_prologue_end = isprolend; 331 dbg->de_last_line->dpl_epilogue_begin = isepilbeg; 332 dbg->de_last_line->dpl_isa = isa; 333 dbg->de_last_line->dpl_discriminator = discriminator; 334 return DW_DLV_OK; 335 } 336 337 /* Add a directory declaration to the debug_line section. Stored 338 in linked list. */ 339 Dwarf_Unsigned 340 dwarf_add_directory_decl(Dwarf_P_Debug dbg, 341 char *name, 342 Dwarf_Error * error) 343 { 344 Dwarf_Unsigned index = 0; 345 int res = 0; 346 /* DW_DLV_NOCOUNT on error, de_n_inc_dirs on success. */ 347 348 res = dwarf_add_directory_decl_a(dbg,name,&index,error); 349 if (res != DW_DLV_OK) { 350 return (Dwarf_Unsigned)DW_DLV_NOCOUNT; 351 } 352 return index; 353 } 354 int 355 dwarf_add_directory_decl_a(Dwarf_P_Debug dbg, 356 char *name, 357 Dwarf_Unsigned *index_in_directories, 358 Dwarf_Error * error) 359 { 360 if (dbg->de_inc_dirs == NULL) { 361 dbg->de_inc_dirs = (Dwarf_P_F_Entry) 362 _dwarf_p_get_alloc(dbg, 363 sizeof(struct Dwarf_P_F_Entry_s)); 364 if (dbg->de_inc_dirs == NULL) { 365 DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, 366 DW_DLV_ERROR); 367 } 368 dbg->de_last_inc_dir = dbg->de_inc_dirs; 369 dbg->de_n_inc_dirs = 1; 370 } else { 371 dbg->de_last_inc_dir->dfe_next = (Dwarf_P_F_Entry) 372 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); 373 if (dbg->de_last_inc_dir->dfe_next == NULL) { 374 DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, 375 DW_DLV_ERROR); 376 } 377 dbg->de_last_inc_dir = dbg->de_last_inc_dir->dfe_next; 378 dbg->de_n_inc_dirs++; 379 } 380 dbg->de_last_inc_dir->dfe_name = 381 (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); 382 if (dbg->de_last_inc_dir->dfe_name == NULL) { 383 DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_ERROR); 384 } 385 strcpy(dbg->de_last_inc_dir->dfe_name, name); 386 dbg->de_last_inc_dir->dfe_next = NULL; 387 388 *index_in_directories = dbg->de_n_inc_dirs; 389 return DW_DLV_OK; 390 } 391 392 /* Add a file entry declaration to the debug_line section. Stored 393 in linked list. The data is immediately encoded as leb128 394 and stored in Dwarf_P_F_Entry_s struct. */ 395 Dwarf_Unsigned 396 dwarf_add_file_decl(Dwarf_P_Debug dbg, 397 char *name, 398 Dwarf_Unsigned dir_idx, 399 Dwarf_Unsigned time_mod, 400 Dwarf_Unsigned length, 401 Dwarf_Error * error) 402 { 403 Dwarf_Unsigned filecount = 0; 404 int res = 0; 405 406 res = dwarf_add_file_decl_a(dbg,name,dir_idx, 407 time_mod,length,&filecount,error); 408 if (res != DW_DLV_OK) { 409 return DW_DLV_NOCOUNT; 410 } 411 return filecount; 412 } 413 int 414 dwarf_add_file_decl_a(Dwarf_P_Debug dbg, 415 char *name, 416 Dwarf_Unsigned dir_idx, 417 Dwarf_Unsigned time_mod, 418 Dwarf_Unsigned length, 419 Dwarf_Unsigned *file_entry_count_out, 420 Dwarf_Error * error) 421 { 422 Dwarf_P_F_Entry cur; 423 char *ptr = 0; 424 int nbytes_idx, nbytes_time, nbytes_len; 425 char buffidx[ENCODE_SPACE_NEEDED]; 426 char bufftime[ENCODE_SPACE_NEEDED]; 427 char bufflen[ENCODE_SPACE_NEEDED]; 428 int res = 0; 429 430 if (dbg->de_file_entries == NULL) { 431 dbg->de_file_entries = (Dwarf_P_F_Entry) 432 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); 433 if (dbg->de_file_entries == NULL) { 434 DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, 435 DW_DLV_ERROR); 436 } 437 cur = dbg->de_file_entries; 438 dbg->de_last_file_entry = cur; 439 dbg->de_n_file_entries = 1; 440 } else { 441 cur = dbg->de_last_file_entry; 442 cur->dfe_next = (Dwarf_P_F_Entry) 443 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s)); 444 if (cur->dfe_next == NULL) { 445 DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC, 446 DW_DLV_ERROR); 447 } 448 cur = cur->dfe_next; 449 dbg->de_last_file_entry = cur; 450 dbg->de_n_file_entries++; 451 } 452 cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1); 453 if (cur->dfe_name == NULL) { 454 DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_ERROR); 455 } 456 strcpy((char *) cur->dfe_name, name); 457 res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx, 458 buffidx, sizeof(buffidx)); 459 if (res != DW_DLV_OK) { 460 /* DW_DLV_NO_ENTRY impossible */ 461 DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR); 462 } 463 res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time, 464 bufftime, sizeof(bufftime)); 465 if (res != DW_DLV_OK) { 466 /* DW_DLV_NO_ENTRY impossible */ 467 DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR); 468 } 469 res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len, 470 bufflen, sizeof(bufflen)); 471 if (res != DW_DLV_OK) { 472 /* DW_DLV_NO_ENTRY impossible */ 473 DWARF_P_DBG_ERROR(dbg,DW_DLE_LEB_OUT_ERROR,DW_DLV_ERROR); 474 } 475 cur->dfe_args = (char *) 476 _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len); 477 if (cur->dfe_args == NULL) { 478 DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_ERROR); 479 } 480 ptr = cur->dfe_args; 481 memcpy((void *) ptr, buffidx, nbytes_idx); 482 ptr += nbytes_idx; 483 memcpy((void *) ptr, bufftime, nbytes_time); 484 ptr += nbytes_time; 485 memcpy((void *) ptr, bufflen, nbytes_len); 486 cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len; 487 cur->dfe_next = NULL; 488 *file_entry_count_out = dbg->de_n_file_entries; 489 return DW_DLV_OK; 490 } 491 492 493 /* Initialize a row of the matrix for line numbers, meaning 494 initialize the struct corresponding to it */ 495 void 496 _dwarf_pro_reg_init(Dwarf_P_Debug dbg, Dwarf_P_Line cur_line) 497 { 498 cur_line->dpl_address = 0; 499 cur_line->dpl_file = 1; 500 cur_line->dpl_line = 1; 501 cur_line->dpl_column = 0; 502 cur_line->dpl_is_stmt = dbg->de_line_inits.pi_default_is_stmt; 503 cur_line->dpl_basic_block = false; 504 cur_line->dpl_next = NULL; 505 cur_line->dpl_prologue_end = 0; 506 cur_line->dpl_epilogue_begin = 0; 507 cur_line->dpl_isa = 0; 508 cur_line->dpl_discriminator = 0; 509 cur_line->dpl_opc = 0; 510 } 511