summaryrefslogtreecommitdiff
path: root/dwarfdump2/print_lines.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dwarfdump2/print_lines.cc')
-rw-r--r--dwarfdump2/print_lines.cc435
1 files changed, 435 insertions, 0 deletions
diff --git a/dwarfdump2/print_lines.cc b/dwarfdump2/print_lines.cc
new file mode 100644
index 0000000..ce965ce
--- /dev/null
+++ b/dwarfdump2/print_lines.cc
@@ -0,0 +1,435 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-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 of the GNU 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 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
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* 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 "globals.h"
+#include <vector>
+#include "naming.h"
+#include "uri.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+static void
+print_source_intro(Dwarf_Die cu_die)
+{
+ Dwarf_Off off = 0;
+ int ores = dwarf_dieoffset(cu_die, &off, &err);
+
+ if (ores == DW_DLV_OK) {
+ cout << "Source lines (from CU-DIE at .debug_info offset ";
+ cout << IToHex0N(off,10);
+ cout << "):" << endl;
+ } else {
+ cout <<"Source lines (for the CU-DIE at unknown location):" <<
+ endl;
+ }
+}
+
+static void
+record_line_error(const std::string &where, Dwarf_Error err)
+{
+ if(check_lines && checking_this_compiler()) {
+ string msg("Error getting line details calling ");
+ msg.append(where);
+ msg.append(" dwarf error is ");
+
+ const char *estring = dwarf_errmsg(err);
+
+ msg.append(estring);
+ DWARF_CHECK_ERROR(lines_result,msg);
+ }
+}
+
+/* Print line number information:
+
+ filename
+ new basic-block
+ [line] [address] <new statement>
+*/
+
+void
+print_line_numbers_this_cu(DieHolder & hcudie)
+{
+ Dwarf_Die cu_die = hcudie.die();
+ Dwarf_Debug dbg = hcudie.dbg();
+
+ bool SkipRecord = false;
+
+ error_message_data.current_section_id = DEBUG_LINE;
+ if(do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_line: line number info for a single cu"<< endl;
+ }
+ if ( verbose > 1) {
+ int errcount = 0;
+ print_source_intro(cu_die);
+ SrcfilesHolder hsrcfiles;
+ print_one_die(hcudie, /* print_information= */ 1,
+ /* indent_level= */ 0,
+ hsrcfiles,
+ /* ignore_die_printed_flag= */true);
+ DWARF_CHECK_COUNT(lines_result,1);
+ int lres = dwarf_print_lines(cu_die, &err,&errcount);
+ if(errcount > 0) {
+ DWARF_ERROR_COUNT(lines_result,errcount);
+ DWARF_CHECK_COUNT(lines_result,(errcount-1));
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_srclines details", lres, err);
+ }
+ return;
+ }
+ if(check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ int line_errs = 0;
+ dwarf_check_lineheader(cu_die,&line_errs);
+ if(line_errs > 0) {
+ DWARF_CHECK_ERROR_PRINT_CU();
+ DWARF_ERROR_COUNT(lines_result,line_errs);
+ DWARF_CHECK_COUNT(lines_result,(line_errs-1));
+ }
+ }
+ Dwarf_Signed linecount = 0;
+ Dwarf_Line *linebuf = NULL;
+ int lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err);
+ if (lres == DW_DLV_ERROR) {
+ /* Do not terminate processing. */
+ if (check_decl_file) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ DWARF_CHECK_ERROR2(decl_file_result,"dwarf_srclines",
+ dwarf_errmsg(err));
+ record_dwarf_error = false; /* Clear error condition */
+ } else {
+ print_error(dbg, "dwarf_srclines", lres, err);
+ }
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ /* no line information is included */
+ } else {
+ if(do_print_dwarf) {
+ print_source_intro(cu_die);
+ if (verbose) {
+ SrcfilesHolder hsrcfiles;
+ print_one_die(hcudie, /* print_information= */ 1,
+ /* indent_level= */ 0,
+ hsrcfiles,
+ /* ignore_die_printed_flag= */true);
+ }
+ cout << endl;
+ cout <<
+ "<pc> [row,col] NS BB ET PE EB IS= DI= uri: \"filepath\""
+ << endl;
+ cout <<
+ "NS new statement, BB new basic block, ET end of text sequence"
+ << endl;
+ cout <<
+ "PE prologue end, EB epilogue begin"
+ << endl;
+ cout <<
+ "IA=val ISA number, DI=val discriminator value"
+ << endl;
+ }
+ string lastsrc = "";
+ for (Dwarf_Signed i = 0; i < linecount; i++) {
+ Dwarf_Line line = linebuf[i];
+ char *filenamearg = 0;
+ bool found_line_error = false;
+ Dwarf_Bool has_is_addr_set = 0;
+ string where;
+
+ if (check_decl_file && checking_this_compiler()) {
+ /* A line record with addr=0 was detected */
+ if (SkipRecord) {
+ /* Skip records that do not have ís_addr_set' */
+ int ares1 = dwarf_line_is_addr_set(line, &has_is_addr_set, &err);
+ if (ares1 == DW_DLV_OK && has_is_addr_set) {
+ SkipRecord = false;
+ } else {
+ /* Keep ignoring records until we have
+ one with 'is_addr_set' */
+ continue;
+ }
+ }
+ }
+
+
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ string filename("<unknown>");
+ int sres = dwarf_linesrc(line, &filenamearg, &err);
+ if (sres == DW_DLV_ERROR) {
+ where = "dwarf_linesrc()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (sres == DW_DLV_OK) {
+ filename = filenamearg;
+ dwarf_dealloc(dbg, filenamearg, DW_DLA_STRING);
+ filenamearg = 0;
+ }
+ Dwarf_Addr pc = 0;
+ int ares = dwarf_lineaddr(line, &pc, &err);
+ if (ares == DW_DLV_ERROR) {
+ where = "dwarf_lineaddr()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (ares == DW_DLV_NO_ENTRY) {
+ pc = 0;
+ }
+ Dwarf_Unsigned lineno = 0;
+ int lires = dwarf_lineno(line, &lineno, &err);
+ if (lires == DW_DLV_ERROR) {
+ where = "dwarf_lineno()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (lires == DW_DLV_NO_ENTRY) {
+ lineno = -1LL;
+ }
+ Dwarf_Unsigned column = 0;
+ int cores = dwarf_lineoff_b(line, &column, &err);
+ if (cores == DW_DLV_ERROR) {
+ where = "dwarf_lineoff()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (cores == DW_DLV_NO_ENTRY) {
+ /* Zero was always the correct default, meaning
+ the left edge. DWARF2/3/4 spec sec 6.2.2 */
+ column = 0;
+ }
+
+ /* Process any possible error condition, though
+ we won't be at the first such error. */
+ if (check_decl_file && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ if (found_line_error) {
+ DWARF_CHECK_ERROR2(decl_file_result,where,dwarf_errmsg(err));
+ } else if (do_check_dwarf) {
+ /* Check the address lies with a valid [lowPC:highPC]
+ in the .text section*/
+ if (pAddressRangesData->IsAddressInAddressRange(pc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we are dealing with
+ a linkonce symbol. The problem we have here
+ is we have consumed the deug_info section
+ and we are dealing just with the records
+ from the .debug_line, so no PU_name is
+ available and no high_pc. Traverse the linkonce
+ table if try to match the pc value with
+ one of those ranges.
+ */
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ if (pLinkOnceData->FindLinkOnceEntry(pc)){
+ /* Valid values; do nothing */
+ } else {
+ /* The SN Systems Linker generates
+ line records
+ with addr=0, when dealing with linkonce
+ symbols and no stripping */
+ if (pc) {
+ char addr_tmp[100];
+ if(check_lines && checking_this_compiler()) {
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " outside a valid .text range",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ } else {
+ SkipRecord = true;
+ }
+ }
+ }
+ /* Check the last record for the .debug_line,
+ the one created by DW_LNE_end_sequence,
+ is the same as the high_pc
+ address for the last known user program
+ unit (PU) */
+ if ((i + 1 == linecount) &&
+ error_message_data.seen_PU_high_address) {
+ /* Ignore those PU that have been stripped
+ by the linker; their low_pc values are
+ set to -1 (snc linker only) */
+ /* It is perfectly sensible for a compiler
+ to leave a few bytes of NOP or other stuff
+ after the last instruction in a subprogram,
+ for cache-alignment or other purposes, so
+ a mismatch here is not necessarily
+ an error. */
+
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ if ((pc != error_message_data.PU_high_address) &&
+ (error_message_data.PU_base_address !=
+ error_message_data.elf_max_address)) {
+ char addr_tmp[100];
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " may be incorrect"
+ " as DW_LNE_end_sequence address",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ }
+ }
+ }
+ }
+
+ /* Display the error information */
+ if (found_line_error || record_dwarf_error) {
+ if (check_verbose_mode) {
+ /* Print the record number for better error description */
+ cout << "Record = " <<
+ i << " Addr = " << IToHex0N(pc,10) <<
+ " [" << IToDec(lineno,4) <<
+ ","<< IToDec(column,2) <<
+ "] '" << filename << "'" << endl;
+ /* Flush due to the redirection of stderr */
+ cout.flush();
+ /* The compilation unit was already printed */
+ if (!check_decl_file) {
+ PRINT_CU_INFO();
+ }
+ }
+ record_dwarf_error = false;
+ /* Due to a fatal error, skip current record */
+ if (found_line_error) {
+ continue;
+ }
+ }
+
+ if(do_print_dwarf) {
+ cout << IToHex0N(pc,10) << " [" <<
+ IToDec(lineno,4) << "," <<
+ IToDec(column,2) <<
+ "]" ;
+ }
+
+ Dwarf_Bool newstatement = 0;
+ int nsres = dwarf_linebeginstatement(line, &newstatement, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && newstatement) {
+ cout <<" NS";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "linebeginstatment failed", nsres,
+ err);
+ }
+ Dwarf_Bool new_basic_block = 0;
+ nsres = dwarf_lineblock(line, &new_basic_block, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && new_basic_block) {
+ cout <<" BB";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ Dwarf_Bool lineendsequence = 0;
+ nsres = dwarf_lineendsequence(line, &lineendsequence, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && lineendsequence) {
+ cout <<" ET";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ if (do_print_dwarf) {
+ Dwarf_Bool prologue_end = 0;
+ Dwarf_Bool epilogue_begin = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+ int disres = dwarf_prologue_end_etc(line,
+ &prologue_end,&epilogue_begin,
+ &isa,&discriminator,&err);
+ if (disres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_prologue_end_etc() failed",
+ disres, err);
+ }
+ if(prologue_end) {
+ cout <<" PE";
+ }
+ if(epilogue_begin) {
+ cout <<" EB";
+ }
+ if(isa) {
+ cout <<" IS=";
+ cout << IToHex(isa);
+ }
+ if(discriminator) {
+ cout <<" DI=";
+ cout << IToHex(discriminator);
+ }
+ }
+
+ // Here avoid so much duplication of long file paths.
+ if (i > 0 && verbose < 3 && filename == lastsrc ){
+ /* print no name, leave blank. */
+ } else {
+ string urs(" uri: \"");
+ translate_to_uri(filename.c_str(),urs);
+ urs.append("\"");
+ if (do_print_dwarf) {
+ cout << urs ;
+ }
+ lastsrc = filename;
+ }
+ if(do_print_dwarf) {
+ cout << endl;
+ }
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, linecount);
+ }
+}
+