00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "config.h"
00043 #include "dwarf_incl.h"
00044 #include <stdio.h>
00045 #include <time.h>
00046 #include "dwarf_line.h"
00047 #ifdef HAVE_ALLOCA_H
00048 #include <alloca.h>
00049 #endif
00050
00051 static void
00052 print_line_header(void)
00053 {
00054 printf
00055 (" s b e\n"
00056 " t l s\n"
00057 " m c e\n"
00058 " section op col t k q\n"
00059 " offset code address file line umn ? ? ?\n");
00060 }
00061
00062 static void
00063 print_line_detail(char *prefix,
00064 int opcode,
00065 unsigned long long address,
00066 unsigned long file,
00067 unsigned long line,
00068 unsigned long column,
00069 int is_stmt, int basic_block, int end_sequence)
00070 {
00071 printf("%-15s %2d 0x%08llx "
00072 "%2lu %4lu %2lu %1d %1d %1d\n",
00073 prefix,
00074 (int) opcode,
00075 (long long) address,
00076 (unsigned long) file,
00077 (unsigned long) line,
00078 (unsigned long) column,
00079 (int) is_stmt, (int) basic_block, (int) end_sequence);
00080
00081 }
00082
00083
00084
00085
00086
00087 int
00088 _dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error)
00089 {
00090
00091
00092
00093 Dwarf_Small *line_ptr;
00094 Dwarf_Small *orig_line_ptr;
00095
00096
00097
00098
00099 Dwarf_Small *line_ptr_end;
00100
00101
00102
00103
00104
00105 Dwarf_Small *check_line_ptr;
00106
00107
00108
00109
00110 Dwarf_Attribute stmt_list_attr;
00111
00112
00113 Dwarf_Attribute comp_dir_attr;
00114
00115
00116 Dwarf_Small *comp_dir = NULL;
00117
00118
00119
00120
00121 Dwarf_Unsigned line_offset;
00122
00123
00124 Dwarf_Unsigned total_length;
00125 Dwarf_Half version;
00126 Dwarf_Unsigned prologue_length;
00127 Dwarf_Small minimum_instruction_length;
00128 Dwarf_Small default_is_stmt;
00129 Dwarf_Sbyte line_base;
00130 Dwarf_Small line_range;
00131 Dwarf_Small opcode_base;
00132
00133 Dwarf_Small *opcode_length;
00134
00135
00136 Dwarf_Addr address;
00137 Dwarf_Word file;
00138 Dwarf_Word line;
00139 Dwarf_Word column;
00140 Dwarf_Bool is_stmt;
00141 Dwarf_Bool basic_block;
00142 Dwarf_Bool end_sequence;
00143
00144 Dwarf_Sword i, file_entry_count, include_directories_count;
00145
00146
00147
00148 Dwarf_Small opcode;
00149
00150
00151
00152
00153
00154 Dwarf_Line_Context line_context;
00155
00156
00157
00158
00159
00160
00161 Dwarf_Word leb128_num;
00162 Dwarf_Word leb128_length;
00163 Dwarf_Sword advance_line;
00164
00165
00166
00167
00168 Dwarf_Half fixed_advance_pc;
00169
00170
00171 Dwarf_Word instr_length;
00172 Dwarf_Small ext_opcode;
00173 int local_length_size;
00174
00175 int local_extension_size;
00176
00177
00178 Dwarf_Debug dbg;
00179 int resattr;
00180 int lres;
00181
00182 int res;
00183
00184
00185
00186 if (error != NULL)
00187 *error = NULL;
00188
00189 CHECK_DIE(die, DW_DLV_ERROR)
00190 dbg = die->di_cu_context->cc_dbg;
00191
00192 res =
00193 _dwarf_load_section(dbg,
00194 dbg->de_debug_line_index,
00195 &dbg->de_debug_line,
00196 error);
00197 if (res != DW_DLV_OK) {
00198 return res;
00199 }
00200
00201 resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
00202 if (resattr != DW_DLV_OK) {
00203 return resattr;
00204 }
00205
00206
00207
00208 lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
00209 if (lres != DW_DLV_OK) {
00210 return lres;
00211 }
00212
00213 if (line_offset >= dbg->de_debug_line_size) {
00214 _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
00215 return (DW_DLV_ERROR);
00216 }
00217 orig_line_ptr = dbg->de_debug_line;
00218 line_ptr = dbg->de_debug_line + line_offset;
00219 dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
00220
00221
00222
00223
00224 resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
00225 if (resattr == DW_DLV_ERROR) {
00226 return resattr;
00227 }
00228 if (resattr == DW_DLV_OK) {
00229 int cres;
00230 char *cdir;
00231
00232 cres = dwarf_formstring(comp_dir_attr, &cdir, error);
00233 if (cres == DW_DLV_ERROR) {
00234 return cres;
00235 } else if (cres == DW_DLV_OK) {
00236 comp_dir = (Dwarf_Small *) cdir;
00237 }
00238 }
00239 if (resattr == DW_DLV_OK) {
00240 dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
00241 }
00242
00243
00244
00245
00246
00247
00248 READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
00249 line_ptr, local_length_size, local_extension_size);
00250
00251
00252
00253 line_ptr_end = line_ptr + total_length;
00254 if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
00255 _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
00256 return (DW_DLV_ERROR);
00257 }
00258
00259 printf("total line info length %ld bytes, "
00260 "line offset 0x%llx %lld\n",
00261 (long) total_length,
00262 (long long) line_offset, (long long) line_offset);
00263 printf("compilation_directory %s\n",
00264 comp_dir ? ((char *) comp_dir) : "");
00265 READ_UNALIGNED(dbg, version, Dwarf_Half,
00266 line_ptr, sizeof(Dwarf_Half));
00267 line_ptr += sizeof(Dwarf_Half);
00268 if (version != CURRENT_VERSION_STAMP) {
00269 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
00270 return (DW_DLV_ERROR);
00271 }
00272
00273 READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
00274 line_ptr, local_length_size);
00275 line_ptr += local_length_size;
00276 check_line_ptr = line_ptr;
00277
00278 minimum_instruction_length = *(Dwarf_Small *) line_ptr;
00279 line_ptr = line_ptr + sizeof(Dwarf_Small);
00280
00281 default_is_stmt = *(Dwarf_Small *) line_ptr;
00282 line_ptr = line_ptr + sizeof(Dwarf_Small);
00283
00284 line_base = *(Dwarf_Sbyte *) line_ptr;
00285 line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
00286
00287 line_range = *(Dwarf_Small *) line_ptr;
00288 line_ptr = line_ptr + sizeof(Dwarf_Small);
00289
00290 opcode_base = *(Dwarf_Small *) line_ptr;
00291 line_ptr = line_ptr + sizeof(Dwarf_Small);
00292 printf(" min instruction length %d\n",
00293 (int) minimum_instruction_length);
00294 printf(" default is stmt %d\n", (int) default_is_stmt);
00295 printf(" line base %d\n", (int) line_base);
00296 printf(" line_range %d\n", (int) line_range);
00297
00298 opcode_length = (Dwarf_Small *)
00299 alloca(sizeof(Dwarf_Small) * opcode_base);
00300
00301 for (i = 1; i < opcode_base; i++) {
00302 opcode_length[i] = *(Dwarf_Small *) line_ptr;
00303 printf(" opcode[%d] length %d\n", (int) i,
00304 (int) opcode_length[i]);
00305 line_ptr = line_ptr + sizeof(Dwarf_Small);
00306 }
00307
00308 include_directories_count = 0;
00309 while ((*(char *) line_ptr) != '\0') {
00310 printf(" include dir[%d] %s\n",
00311 (int) include_directories_count, line_ptr);
00312 line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
00313 include_directories_count++;
00314 }
00315 line_ptr++;
00316
00317 file_entry_count = 0;
00318 while (*(char *) line_ptr != '\0') {
00319
00320 Dwarf_Unsigned tlm2;
00321 Dwarf_Unsigned di;
00322 Dwarf_Unsigned fl;
00323
00324 printf(" file[%d] %s\n",
00325 (int) file_entry_count, (char *) line_ptr);
00326
00327 line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
00328
00329 di = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
00330 line_ptr = line_ptr + leb128_length;
00331
00332 tlm2 = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
00333 line_ptr = line_ptr + leb128_length;
00334
00335 fl = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
00336 line_ptr = line_ptr + leb128_length;
00337
00338 printf(" dir index %d\n", (int) di);
00339 {
00340 time_t tt = (time_t) tlm2;
00341
00342 printf(" last time 0x%x %s",
00343
00344 (unsigned) tlm2, ctime(&tt));
00345 }
00346 printf(" file length %ld 0x%lx\n",
00347 (long) fl, (unsigned long) fl);
00348
00349
00350 file_entry_count++;
00351 }
00352 line_ptr++;
00353
00354 if (line_ptr != check_line_ptr + prologue_length) {
00355 _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
00356 return (DW_DLV_ERROR);
00357 }
00358
00359
00360 line_context = (Dwarf_Line_Context)
00361 _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
00362 if (line_context == NULL) {
00363 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
00364 return (DW_DLV_ERROR);
00365 }
00366
00367 printf(" statement prog offset in section: %lld 0x%llx\n",
00368 (long long) (line_ptr - orig_line_ptr),
00369 (long long) (line_ptr - orig_line_ptr));
00370
00371
00372 address = 0;
00373 file = 1;
00374 line = 1;
00375 column = 0;
00376 is_stmt = default_is_stmt;
00377 basic_block = false;
00378 end_sequence = false;
00379
00380 print_line_header();
00381
00382 while (line_ptr < line_ptr_end) {
00383 int type;
00384
00385 printf(" [0x%06llx] ", (long long) (line_ptr - orig_line_ptr));
00386 opcode = *(Dwarf_Small *) line_ptr;
00387 line_ptr++;
00388
00389 WHAT_IS_OPCODE(type, opcode, opcode_base,
00390 opcode_length, line_ptr);
00391
00392
00393
00394 if (type == LOP_DISCARD) {
00395
00396 } else if (type == LOP_SPECIAL) {
00397
00398
00399
00400
00401
00402 char special[50];
00403 unsigned origop = opcode;
00404
00405 opcode = opcode - opcode_base;
00406 address = address + minimum_instruction_length *
00407 (opcode / line_range);
00408 line = line + line_base + opcode % line_range;
00409
00410 sprintf(special, "Specialop %3u", origop);
00411 print_line_detail(special,
00412 opcode, address, (int) file, line, column,
00413 is_stmt, basic_block, end_sequence);
00414
00415 basic_block = false;
00416
00417 } else if (type == LOP_STANDARD) {
00418 switch (opcode) {
00419
00420 case DW_LNS_copy:{
00421 if (opcode_length[DW_LNS_copy] != 0) {
00422 _dwarf_error(dbg, error,
00423 DW_DLE_LINE_NUM_OPERANDS_BAD);
00424 return (DW_DLV_ERROR);
00425 }
00426
00427 print_line_detail("DW_LNS_copy",
00428 opcode, address, file, line,
00429 column, is_stmt, basic_block,
00430 end_sequence);
00431
00432 basic_block = false;
00433 break;
00434 }
00435
00436 case DW_LNS_advance_pc:{
00437 Dwarf_Unsigned utmp2;
00438
00439 if (opcode_length[DW_LNS_advance_pc] != 1) {
00440 _dwarf_error(dbg, error,
00441 DW_DLE_LINE_NUM_OPERANDS_BAD);
00442 return (DW_DLV_ERROR);
00443 }
00444
00445 DECODE_LEB128_UWORD(line_ptr, utmp2)
00446 printf("DW_LNS_advance_pc val %lld 0x%llx\n",
00447 (long long) (Dwarf_Word) utmp2,
00448 (long long) (Dwarf_Word) utmp2);
00449 leb128_num = (Dwarf_Word) utmp2;
00450 address =
00451 address +
00452 minimum_instruction_length * leb128_num;
00453 break;
00454 }
00455
00456 case DW_LNS_advance_line:{
00457 Dwarf_Signed stmp;
00458
00459 if (opcode_length[DW_LNS_advance_line] != 1) {
00460 _dwarf_error(dbg, error,
00461 DW_DLE_LINE_NUM_OPERANDS_BAD);
00462 return (DW_DLV_ERROR);
00463 }
00464
00465 DECODE_LEB128_SWORD(line_ptr, stmp)
00466 advance_line = (Dwarf_Sword) stmp;
00467 printf("DW_LNS_advance_line val %lld 0x%llx\n",
00468 (long long) advance_line,
00469 (long long) advance_line);
00470 line = line + advance_line;
00471 break;
00472 }
00473
00474 case DW_LNS_set_file:{
00475 Dwarf_Unsigned utmp2;
00476
00477 if (opcode_length[DW_LNS_set_file] != 1) {
00478 _dwarf_error(dbg, error,
00479 DW_DLE_LINE_NUM_OPERANDS_BAD);
00480 return (DW_DLV_ERROR);
00481 }
00482
00483 DECODE_LEB128_UWORD(line_ptr, utmp2)
00484 file = (Dwarf_Word) utmp2;
00485 printf("DW_LNS_set_file %ld\n", (long) file);
00486 break;
00487 }
00488
00489 case DW_LNS_set_column:{
00490 Dwarf_Unsigned utmp2;
00491
00492 if (opcode_length[DW_LNS_set_column] != 1) {
00493 _dwarf_error(dbg, error,
00494 DW_DLE_LINE_NUM_OPERANDS_BAD);
00495 return (DW_DLV_ERROR);
00496 }
00497
00498 DECODE_LEB128_UWORD(line_ptr, utmp2)
00499 column = (Dwarf_Word) utmp2;
00500 printf("DW_LNS_set_column val %lld 0x%llx\n",
00501 (long long) column, (long long) column);
00502 break;
00503 }
00504
00505 case DW_LNS_negate_stmt:{
00506 if (opcode_length[DW_LNS_negate_stmt] != 0) {
00507 _dwarf_error(dbg, error,
00508 DW_DLE_LINE_NUM_OPERANDS_BAD);
00509 return (DW_DLV_ERROR);
00510 }
00511
00512 is_stmt = !is_stmt;
00513 printf("DW_LNS_negate_stmt\n");
00514 break;
00515 }
00516
00517 case DW_LNS_set_basic_block:{
00518 if (opcode_length[DW_LNS_set_basic_block] != 0) {
00519 _dwarf_error(dbg, error,
00520 DW_DLE_LINE_NUM_OPERANDS_BAD);
00521 return (DW_DLV_ERROR);
00522 }
00523
00524 printf("DW_LNS_set_basic_block\n");
00525 basic_block = true;
00526 break;
00527 }
00528
00529 case DW_LNS_const_add_pc:{
00530 opcode = MAX_LINE_OP_CODE - opcode_base;
00531 address = address + minimum_instruction_length *
00532 (opcode / line_range);
00533
00534 printf("DW_LNS_const_add_pc new address 0x%llx\n",
00535 (long long) address);
00536 break;
00537 }
00538
00539 case DW_LNS_fixed_advance_pc:{
00540 if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
00541 _dwarf_error(dbg, error,
00542 DW_DLE_LINE_NUM_OPERANDS_BAD);
00543 return (DW_DLV_ERROR);
00544 }
00545
00546 READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
00547 line_ptr, sizeof(Dwarf_Half));
00548 line_ptr += sizeof(Dwarf_Half);
00549 address = address + fixed_advance_pc;
00550 printf("DW_LNS_fixed_advance_pc val %lld 0x%llx"
00551 " new address 0x%llx\n",
00552 (long long) fixed_advance_pc,
00553 (long long) fixed_advance_pc,
00554 (long long) address);
00555 break;
00556 }
00557 }
00558
00559 } else if (type == LOP_EXTENDED) {
00560 Dwarf_Unsigned utmp3;
00561
00562 DECODE_LEB128_UWORD(line_ptr, utmp3)
00563 instr_length = (Dwarf_Word) utmp3;
00564 ext_opcode = *(Dwarf_Small *) line_ptr;
00565 line_ptr++;
00566 switch (ext_opcode) {
00567
00568 case DW_LNE_end_sequence:{
00569 end_sequence = true;
00570
00571 print_line_detail("DW_LNE_end_sequence extended",
00572 opcode, address, file, line,
00573 column, is_stmt, basic_block,
00574 end_sequence);
00575
00576 address = 0;
00577 file = 1;
00578 line = 1;
00579 column = 0;
00580 is_stmt = default_is_stmt;
00581 basic_block = false;
00582 end_sequence = false;
00583
00584 break;
00585 }
00586
00587 case DW_LNE_set_address:{
00588 if (instr_length - 1 == dbg->de_pointer_size) {
00589 READ_UNALIGNED(dbg, address, Dwarf_Addr,
00590 line_ptr, dbg->de_pointer_size);
00591
00592 line_ptr += dbg->de_pointer_size;
00593 printf("DW_LNE_set_address address 0x%llx\n",
00594 (long long) address);
00595 } else {
00596 _dwarf_error(dbg, error,
00597 DW_DLE_LINE_SET_ADDR_ERROR);
00598 return (DW_DLV_ERROR);
00599 }
00600
00601 break;
00602 }
00603
00604 case DW_LNE_define_file:{
00605
00606
00607 Dwarf_Small *fn;
00608 Dwarf_Signed di;
00609 Dwarf_Signed tlm;
00610 Dwarf_Unsigned fl;
00611
00612 fn = (Dwarf_Small *) line_ptr;
00613 line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
00614
00615 di = _dwarf_decode_u_leb128(line_ptr,
00616 &leb128_length);
00617 line_ptr = line_ptr + leb128_length;
00618
00619 tlm =
00620 _dwarf_decode_u_leb128(line_ptr,
00621 &leb128_length);
00622 line_ptr = line_ptr + leb128_length;
00623
00624 fl = _dwarf_decode_u_leb128(line_ptr,
00625 &leb128_length);
00626 line_ptr = line_ptr + leb128_length;
00627
00628
00629 printf("DW_LNE_define_file %s \n", fn);
00630 printf(" dir index %d\n", (int) di);
00631 {
00632 time_t tt3 = (time_t) tlm;
00633
00634
00635 printf(" last time 0x%x %s",
00636 (unsigned) tlm, ctime(&tt3));
00637 }
00638 printf(" file length %ld 0x%lx\n",
00639 (long) fl, (unsigned long) fl);
00640
00641 break;
00642 }
00643
00644 default:{
00645 _dwarf_error(dbg, error,
00646 DW_DLE_LINE_EXT_OPCODE_BAD);
00647 return (DW_DLV_ERROR);
00648 }
00649 }
00650
00651 }
00652 }
00653
00654 return (DW_DLV_OK);
00655 }
00656
00657
00658
00659
00660 int
00661 _dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
00662 {
00663 int res;
00664
00665 res = _dwarf_internal_printlines(die, error);
00666 if (res != DW_DLV_OK) {
00667 return res;
00668 }
00669 return res;
00670 }