summaryrefslogtreecommitdiff
path: root/libdwarf/dwarf_print_lines.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwarf/dwarf_print_lines.c')
-rw-r--r--libdwarf/dwarf_print_lines.c736
1 files changed, 736 insertions, 0 deletions
diff --git a/libdwarf/dwarf_print_lines.c b/libdwarf/dwarf_print_lines.c
new file mode 100644
index 0000000..263752b
--- /dev/null
+++ b/libdwarf/dwarf_print_lines.c
@@ -0,0 +1,736 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <time.h>
+#include "dwarf_line.h"
+
+/* FIXME Need to add prologue_end epilogue_begin isa fields. */
+static void
+print_line_header(void)
+{
+ printf
+ (" s b e p e i d\n"
+ " t l s r p s i\n"
+ " m c e o i a s\n"
+ " section op col t k q l l c\n"
+ " offset code address file line umn ? ? ? ? ? \n");
+}
+
+/* FIXME: print new line values: prologue_end epilogue_begin isa */
+static void
+print_line_detail(char *prefix,
+ int opcode,
+ Dwarf_Unsigned address,
+ unsigned long file,
+ unsigned long line,
+ unsigned long column,
+ int is_stmt, int basic_block, int end_sequence,
+ int prologue_end, int epilogue_begin, int isa,
+ Dwarf_Unsigned discriminator)
+{
+ printf("%-15s %2d 0x%" DW_PR_XZEROS DW_PR_DUx " "
+ "%2lu %4lu %2lu %1d %1d %1d",
+ prefix,
+ (int) opcode,
+ (Dwarf_Unsigned) address,
+ (unsigned long) file,
+ (unsigned long) line,
+ (unsigned long) column,
+ (int) is_stmt, (int) basic_block, (int) end_sequence);
+ if(discriminator || prologue_end || epilogue_begin || isa) {
+ printf(" %1d", prologue_end);
+ printf(" %1d", epilogue_begin);
+ printf(" %1d", isa);
+ printf(" 0x%" DW_PR_DUx , discriminator);
+ }
+ printf("\n");
+}
+
+
+/* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
+ If err_count_out is non-NULL, this is a special 'check'
+ call. */
+int
+_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error,
+int * err_count_out, int only_line_header)
+{
+ /* This pointer is used to scan the portion of the .debug_line
+ section for the current cu. */
+ Dwarf_Small *line_ptr = 0;
+ Dwarf_Small *orig_line_ptr = 0;
+
+ /* This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end = 0;
+
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ die. */
+ Dwarf_Attribute stmt_list_attr = 0;
+
+ /* Pointer to DW_AT_comp_dir attribute in die. */
+ Dwarf_Attribute comp_dir_attr = 0;
+
+ /* Pointer to name of compilation directory. */
+ Dwarf_Small *comp_dir = NULL;
+
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset = 0;
+
+ struct Line_Table_Prefix_s prefix;
+
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address = 0;
+ Dwarf_Word file = 1;
+ Dwarf_Word line = 1;
+ Dwarf_Word column = 0;
+ Dwarf_Bool is_stmt = false;
+ Dwarf_Bool basic_block = false;
+ Dwarf_Bool end_sequence = false;
+ Dwarf_Bool prologue_end = false;
+ Dwarf_Bool epilogue_begin = false;
+ Dwarf_Small isa = 0;
+ Dwarf_Unsigned op_index = 0;
+ Dwarf_Unsigned discriminator = 0;
+
+
+ Dwarf_Sword i=0;
+
+ /* This is the current opcode read from the statement program. */
+ Dwarf_Small opcode=0;
+
+
+ /* These variables are used to decode leb128 numbers. Leb128_num
+ holds the decoded number, and leb128_length is its length in
+ bytes. */
+ Dwarf_Word leb128_num=0;
+ Dwarf_Word leb128_length=0;
+ Dwarf_Sword advance_line=0;
+ Dwarf_Half attrform = 0;
+ /* This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc=0;
+
+ /* In case there are wierd bytes 'after' the line table
+ prologue this lets us print something. This is a gcc
+ compiler bug and we expect the bytes count to be 12. */
+ Dwarf_Small* bogus_bytes_ptr = 0;
+ Dwarf_Unsigned bogus_bytes_count = 0;
+
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg=0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ int res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+
+ if (error != NULL) {
+ *error = NULL;
+ }
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_line.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
+ if (resattr != DW_DLV_OK) {
+ return resattr;
+ }
+
+
+ /* The list of relevant FORMs is small.
+ DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset
+ */
+ lres = dwarf_whatform(stmt_list_attr,&attrform,error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
+ attrform != DW_FORM_sec_offset ) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ orig_line_ptr = dbg->de_debug_line.dss_data;
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
+ dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
+
+ /* If die has DW_AT_comp_dir attribute, get the string that names
+ the compilation directory. */
+ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
+ if (resattr == DW_DLV_ERROR) {
+ return resattr;
+ }
+ if (resattr == DW_DLV_OK) {
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
+ }
+ if (resattr == DW_DLV_OK) {
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
+ }
+
+ dwarf_init_line_table_prefix(&prefix);
+ {
+ Dwarf_Small *line_ptr_out = 0;
+ int dres = dwarf_read_line_table_prefix(dbg,
+ line_ptr,dbg->de_debug_line.dss_size - line_offset,
+ &line_ptr_out,
+ &prefix,
+ &bogus_bytes_ptr,
+ &bogus_bytes_count,
+ error,
+ err_count_out);
+ if (dres == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&prefix);
+ return dres;
+ }
+ if (dres == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&prefix);
+ return dres;
+ }
+ line_ptr_end = prefix.pf_line_ptr_end;
+ line_ptr = line_ptr_out;
+ }
+ if(only_line_header) {
+ /* Just checking for header errors, nothing more here.*/
+ dwarf_free_line_table_prefix(&prefix);
+ return DW_DLV_OK;
+ }
+
+ printf("total line info length %ld bytes, "
+ "line offset 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DSd "\n",
+ (long) prefix.pf_total_length,
+ (Dwarf_Unsigned) line_offset, (Dwarf_Signed) line_offset);
+ printf("line table version %d\n",(int) prefix.pf_version);
+ printf("line table length field length %d prologue length %d\n",
+ (int)prefix.pf_length_field_length,
+ (int)prefix.pf_prologue_length);
+ printf("compilation_directory %s\n",
+ comp_dir ? ((char *) comp_dir) : "");
+
+ printf(" min instruction length %d\n",
+ (int) prefix.pf_minimum_instruction_length);
+ printf(" default is stmt %d\n", (int) prefix.pf_default_is_stmt);
+ printf(" line base %d\n", (int) prefix.pf_line_base);
+ printf(" line_range %d\n", (int) prefix.pf_line_range);
+ printf(" opcode base %d\n", (int) prefix.pf_opcode_base);
+ printf(" standard opcode count %d\n", (int) prefix.pf_std_op_count);
+
+ for (i = 1; i < prefix.pf_opcode_base; i++) {
+ printf(" opcode[%2d] length %d\n", (int) i,
+ (int) prefix.pf_opcode_length_table[i - 1]);
+ }
+ printf(" include directories count %d\n",
+ (int) prefix.pf_include_directories_count);
+ for (i = 0; i < prefix.pf_include_directories_count; ++i) {
+ printf(" include dir[%d] %s\n",
+ (int) i, prefix.pf_include_directories[i]);
+ }
+ printf(" files count %d\n",
+ (int) prefix.pf_files_count);
+
+ for (i = 0; i < prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *lfile =
+ prefix.pf_line_table_file_entries + i;
+ Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time;
+ Dwarf_Unsigned di = lfile->lte_directory_index;
+ Dwarf_Unsigned fl = lfile->lte_length_of_file;
+
+ printf(" file[%d] %s (file-number: %d) \n",
+ (int) i, (char *) lfile->lte_filename,
+ (int)(i+1));
+ printf(" dir index %d\n", (int) di);
+ {
+ time_t tt = (time_t) tlm2;
+
+ /* ctime supplies newline */
+ printf(" last time 0x%x %s",
+ (unsigned) tlm2, ctime(&tt));
+ }
+ printf(" file length %ld 0x%lx\n",
+ (long) fl, (unsigned long) fl);
+
+ }
+
+
+ {
+ Dwarf_Unsigned offset = 0;
+ if(bogus_bytes_count > 0) {
+ Dwarf_Unsigned wcount = bogus_bytes_count;
+ Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr;
+ printf("*** DWARF CHECK: the line table prologue header_length "
+ " is %" DW_PR_DUu " too high, we pretend it is smaller."
+ "Section offset: 0x%" DW_PR_XZEROS DW_PR_DUx
+ " (%" DW_PR_DUu ") ***\n",
+ wcount, boffset,boffset);
+ *err_count_out += 1;
+ }
+ offset = line_ptr - orig_line_ptr;
+ printf(" statement prog offset in section: 0x%"
+ DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ")\n",
+ offset, offset);
+ }
+
+ /* Initialize the part of the state machine dependent on the
+ prefix. */
+ is_stmt = prefix.pf_default_is_stmt;
+
+ print_line_header();
+ /* Start of statement program. */
+ while (line_ptr < line_ptr_end) {
+ int type = 0;
+
+ printf(" [0x%06" DW_PR_DSx "] ",
+ (Dwarf_Signed) (line_ptr - orig_line_ptr));
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
+ prefix.pf_opcode_length_table, line_ptr,
+ prefix.pf_std_op_count);
+ if (type == LOP_DISCARD) {
+ int oc = 0;
+ int opcnt = prefix.pf_opcode_length_table[opcode];
+
+ printf("*** DWARF CHECK: DISCARD standard opcode %d "
+ "with %d operands: "
+ "not understood.", opcode, opcnt);
+ *err_count_out += 1;
+ for (oc = 0; oc < opcnt; oc++) {
+ /* Read and discard operands we don't
+ understand.
+ Arbitrary choice of unsigned read.
+ Signed read would work as well. */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ printf(" %" DW_PR_DUu
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ")",
+ (Dwarf_Unsigned) utmp2,
+ (Dwarf_Unsigned) utmp2);
+ }
+ printf("***\n");
+ /* Do nothing, necessary ops done */
+ } else if (type == LOP_SPECIAL) {
+ /* This op code is a special op in the object, no matter
+ that it might fall into the standard op range in this
+ compile Thatis, these are special opcodes between
+ special_opcode_base and MAX_LINE_OP_CODE. (including
+ special_opcode_base and MAX_LINE_OP_CODE) */
+ char special[50];
+ Dwarf_Unsigned operation_advance = 0;
+ unsigned origop = opcode;
+
+ opcode = opcode - prefix.pf_opcode_base;
+ operation_advance = (opcode / prefix.pf_line_range);
+ if(prefix.pf_maximum_ops_per_instruction < 2) {
+ address = address + (prefix.pf_minimum_instruction_length *
+ operation_advance);
+ } else {
+ address = address + (prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction));
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+ line = line + prefix.pf_line_base +
+ opcode % prefix.pf_line_range;
+ sprintf(special, "Specialop %3u", origop);
+ print_line_detail(special,
+ opcode, address, (int) file, line, column,
+ is_stmt, basic_block, end_sequence,
+ prologue_end, epilogue_begin, isa,discriminator);
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+
+ case DW_LNS_copy:{
+ print_line_detail("DW_LNS_copy",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence, prologue_end,
+ epilogue_begin, isa,discriminator);
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ }
+ break;
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ printf("DW_LNS_advance_pc val %"
+ DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Signed) (Dwarf_Word) utmp2,
+ (Dwarf_Unsigned) (Dwarf_Word) utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address = address +
+ prefix.pf_minimum_instruction_length * leb128_num;
+ }
+ break;
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp = 0;
+
+ DECODE_LEB128_SWORD(line_ptr, stmp);
+ advance_line = (Dwarf_Sword) stmp;
+ printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) advance_line,
+ (Dwarf_Signed) advance_line);
+ line = line + advance_line;
+ }
+ break;
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ file = (Dwarf_Word) utmp2;
+ printf("DW_LNS_set_file %ld\n", (long) file);
+ }
+ break;
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ column = (Dwarf_Word) utmp2;
+ printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) column, (Dwarf_Signed) column);
+ }
+ break;
+ case DW_LNS_negate_stmt:{
+ is_stmt = !is_stmt;
+ printf("DW_LNS_negate_stmt\n");
+ }
+ break;
+ case DW_LNS_set_basic_block:{
+ printf("DW_LNS_set_basic_block\n");
+ basic_block = true;
+ }
+ break;
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
+ if(prefix.pf_maximum_ops_per_instruction < 2) {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address +
+ prefix.pf_minimum_instruction_length *
+ operation_advance;
+ } else {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address + prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction);
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+
+ printf("DW_LNS_const_add_pc new address 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) address);
+ }
+ break;
+ case DW_LNS_fixed_advance_pc:{
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd
+ " 0x%" DW_PR_XZEROS DW_PR_DSx
+ " new address 0x%" DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) fixed_advance_pc,
+ (Dwarf_Signed) fixed_advance_pc,
+ (Dwarf_Signed) address);
+ op_index = 0;
+ }
+ break;
+ case DW_LNS_set_prologue_end:{
+ prologue_end = true;
+ printf("DW_LNS_set_prologue_end set true.\n");
+ }
+ break;
+ /* New in DWARF3 */
+ case DW_LNS_set_epilogue_begin:{
+ epilogue_begin = true;
+ printf("DW_LNS_set_epilogue_begin set true.\n");
+ }
+ break;
+
+ /* New in DWARF3 */
+ case DW_LNS_set_isa:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ isa = utmp2;
+ printf("DW_LNS_set_isa new value 0x%"
+ DW_PR_XZEROS DW_PR_DUx ".\n",
+ (Dwarf_Unsigned) utmp2);
+ if (isa != utmp2) {
+ /* The value of the isa did not fit in our
+ local so we record it wrong. declare an
+ error. */
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ break;
+ } /* end switch */
+ } else if (type == LOP_EXTENDED) {
+ Dwarf_Unsigned utmp3 = 0;
+ Dwarf_Word instr_length = 0;
+ Dwarf_Small ext_opcode = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp3);
+ instr_length = (Dwarf_Word) utmp3;
+ ext_opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ switch (ext_opcode) {
+
+ case DW_LNE_end_sequence:{
+ end_sequence = true;
+
+ print_line_detail("DW_LNE_end_sequence extended",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence, prologue_end,
+ epilogue_begin, isa,discriminator);
+
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = prefix.pf_default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ isa = 0;
+ discriminator = 0;
+ op_index = 0;
+ }
+ break;
+ case DW_LNE_set_address:{
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr,
+ die->di_cu_context->cc_address_size);
+
+ line_ptr += die->di_cu_context->cc_address_size;
+ printf("DW_LNE_set_address address 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Unsigned) address);
+
+ op_index = 0;
+ }
+ break;
+ case DW_LNE_define_file:{
+ Dwarf_Unsigned di = 0;
+ Dwarf_Unsigned tlm = 0;
+ Dwarf_Unsigned fl = 0;
+
+ Dwarf_Small *fn = (Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ di = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ tlm = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ fl = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ printf("DW_LNE_define_file %s \n", fn);
+ printf(" dir index %d\n", (int) di);
+ {
+ time_t tt3 = (time_t) tlm;
+
+ /* ctime supplies newline */
+ printf(" last time 0x%x %s",
+ (unsigned) tlm, ctime(&tt3));
+ }
+ printf(" file length %ld 0x%lx\n",
+ (long) fl, (unsigned long) fl);
+
+ }
+ break;
+ case DW_LNE_set_discriminator:{
+ /* new in DWARF4 */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ discriminator = (Dwarf_Word) utmp2;
+ printf("DW_LNE_set_discriminator 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",utmp2);
+ }
+ break;
+
+ default:{
+ /* This is an extended op code we do not know about,
+ other than we know now many bytes it is
+ (and the op code and the bytes of operand). */
+
+ Dwarf_Unsigned remaining_bytes = instr_length -1;
+ if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ printf("DW_LNE extended op 0x%x ",ext_opcode);
+ printf("Bytecount: %" DW_PR_DUu , (Dwarf_Unsigned)instr_length);
+ if(remaining_bytes > 0) {
+ printf(" linedata: 0x");
+ while (remaining_bytes > 0) {
+ printf("%02x",(unsigned char)(*(line_ptr)));
+ line_ptr++;
+ remaining_bytes--;
+ }
+ }
+ printf("\n");
+ }
+ break;
+ } /* Dnd switch */
+
+ }
+ }
+
+ dwarf_free_line_table_prefix(&prefix);
+ return (DW_DLV_OK);
+}
+
+/* This is support for dwarfdump: making it possible
+ for clients wanting line detail info on stdout
+ to get that detail without including internal libdwarf
+ header information.
+ Caller passes in compilation unit DIE.
+ The _dwarf_ version is obsolete (though supported for
+ compatibility).
+ The dwarf_ version is preferred.
+ The functions are intentionally identical: having
+ _dwarf_print_lines call dwarf_print_lines might
+ better emphasize they are intentionally identical, but
+ that seemed slightly silly given how short the functions are.
+ Interface adds error_count (output value) February 2009. */
+int
+dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error,int *error_count)
+{
+ int only_line_header = 0;
+ int res = _dwarf_internal_printlines(die, error,
+ error_count,
+ only_line_header);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ return res;
+}
+int
+_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
+{
+ int only_line_header = 0;
+ int err_count = 0;
+ int res = _dwarf_internal_printlines(die, error,
+ &err_count,
+ only_line_header);
+ /* No way to get error count back in this interface */
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ return res;
+}
+
+/* The check is in case we are not printing full line data,
+ this gets some of the issues noted with .debug_line,
+ but not all. Call dwarf_print_lines() to get all issues.
+ Intended for apps like dwarfdump.
+*/
+void
+dwarf_check_lineheader(Dwarf_Die die, int *err_count_out)
+{
+ Dwarf_Error err;
+ int only_line_header = 1;
+ _dwarf_internal_printlines(die, &err,err_count_out,
+ only_line_header);
+ return;
+}
+