diff options
Diffstat (limited to 'dwarfdump/print_lines.c')
-rw-r--r-- | dwarfdump/print_lines.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/dwarfdump/print_lines.c b/dwarfdump/print_lines.c new file mode 100644 index 0000000..4b33994 --- /dev/null +++ b/dwarfdump/print_lines.c @@ -0,0 +1,433 @@ + +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 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 "naming.h" +#include "dwconf.h" +#include "esb.h" +#include "uri.h" +#include <ctype.h> + +#include "print_sections.h" + +/* + Print line number information: + [line] [address] <new statement> + new basic-block + filename +*/ + + +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) { + printf("Source lines (from CU-DIE at .debug_info offset 0x%" + DW_PR_XZEROS DW_PR_DUx "):\n", + (Dwarf_Unsigned) off); + } else { + printf("Source lines (for the CU-DIE at unknown location):\n"); + } +} + +static void +record_line_error(const char *where, Dwarf_Error err) +{ + char tmp_buff[500]; + if(check_lines && checking_this_compiler()) { + snprintf(tmp_buff, sizeof(tmp_buff), + "Error getting line details calling %s dwarf error is %s", + where,dwarf_errmsg(err)); + DWARF_CHECK_ERROR(lines_result,tmp_buff); + } +} + +extern void +print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die) +{ + Dwarf_Signed linecount = 0; + Dwarf_Line *linebuf = NULL; + Dwarf_Signed i = 0; + Dwarf_Addr pc = 0; + Dwarf_Unsigned lineno = 0; + Dwarf_Unsigned column = 0; + + Dwarf_Bool newstatement = 0; + Dwarf_Bool lineendsequence = 0; + Dwarf_Bool new_basic_block = 0; + int lres = 0; + int sres = 0; + int ares = 0; + int lires = 0; + int cores = 0; + int line_errs = 0; + + Dwarf_Bool SkipRecord = FALSE; + + current_section_id = DEBUG_LINE; + + /* line_flag is TRUE */ + + if (do_print_dwarf) { + printf("\n.debug_line: line number info for a single cu\n"); + } + if (verbose > 1) { + int errcount = 0; + print_source_intro(cu_die); + print_one_die(dbg, cu_die, + /* print_information= */ 1, + /* indent level */0, + /* srcfiles= */ 0, /* cnt= */ 0, + /* ignore_die_stack= */TRUE); + DWARF_CHECK_COUNT(lines_result,1); + 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); + 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)); + } + } + 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 { + struct esb_s lastsrc;; + esb_constructor(&lastsrc); + if (do_print_dwarf) { + print_source_intro(cu_die); + if (verbose) { + print_one_die(dbg, cu_die, + /* print_information= */ TRUE, + /* indent_level= */ 0, + /* srcfiles= */ 0, /* cnt= */ 0, + /* ignore_die_stack= */TRUE); + } + printf("\n<pc> [row,col] " + "NS BB ET PE EB IS= DI= uri: \"filepath\"\n"); + printf("NS new statement, BB new basic block, " + "ET end of text sequence\n"); + printf("PE prologue end, EB epilogue begin\n"); + printf("IA=val ISA number, DI=val discriminator value\n"); + } + for (i = 0; i < linecount; i++) { + Dwarf_Line line = linebuf[i]; + string filename = 0; + int nsres = 0; + Dwarf_Bool found_line_error = FALSE; + Dwarf_Bool has_is_addr_set = FALSE; + char *where = NULL; + + 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' */ + ares = dwarf_line_is_addr_set(line, &has_is_addr_set, &err); + if (ares == 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); + } + filename = "<unknown>"; + sres = dwarf_linesrc(line, &filename, &err); + if (sres == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_linesrc()"; + record_line_error(where,err); + found_line_error = TRUE; + } + + ares = dwarf_lineaddr(line, &pc, &err); + + if (ares == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineaddr()"; + record_line_error(where,err); + found_line_error = TRUE; + } + if (ares == DW_DLV_NO_ENTRY) { + pc = 0; + } + lires = dwarf_lineno(line, &lineno, &err); + if (lires == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineno()"; + record_line_error(where,err); + found_line_error = TRUE; + } + if (lires == DW_DLV_NO_ENTRY) { + lineno = -1LL; + } + cores = dwarf_lineoff_b(line, &column, &err); + if (cores == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineoff()"; + record_line_error(where,err); + found_line_error = TRUE; + } + 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 (IsValidInBucketGroup(pRangesInfo,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 (FindAddressInBucketGroup(pLinkonceInfo,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) && + 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 != PU_high_address) && + (PU_base_address != 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 */ + printf("Record = %" DW_PR_DUu + " Addr = 0x%" DW_PR_XZEROS DW_PR_DUx + " [%4" DW_PR_DUu ",%2" DW_PR_DUu "] '%s'\n", + i, pc,lineno,column,filename); + /* Flush due to the redirection of stderr */ + fflush(stdout); + /* 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) { + printf("0x%08" DW_PR_DUx + " [%4" DW_PR_DUu ",%2" DW_PR_DUu "]", pc, lineno, + column); + } + + nsres = dwarf_linebeginstatement(line, &newstatement, &err); + if (nsres == DW_DLV_OK) { + if (newstatement && do_print_dwarf) { + printf(" %s","NS"); + } + } else if (nsres == DW_DLV_ERROR) { + print_error(dbg, "linebeginstatment failed", nsres, err); + } + nsres = dwarf_lineblock(line, &new_basic_block, &err); + if (nsres == DW_DLV_OK) { + if (new_basic_block && do_print_dwarf) { + printf(" %s","BB"); + } + } else if (nsres == DW_DLV_ERROR) { + print_error(dbg, "lineblock failed", nsres, err); + } + nsres = dwarf_lineendsequence(line, &lineendsequence, &err); + if (nsres == DW_DLV_OK) { + if (lineendsequence && do_print_dwarf) { + printf(" %s", "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) { + printf(" PE"); + } + if(epilogue_begin) { + printf(" EB"); + } + if(isa) { + printf(" IS=0x%" DW_PR_DUx, isa); + } + if(discriminator) { + printf(" DI=0x%" DW_PR_DUx, discriminator); + } + } + + + if (i > 0 && verbose < 3 && + strcmp(filename,esb_get_string(&lastsrc)) == 0) { + /* Do not print name. */ + } else { + struct esb_s urs; + esb_constructor(&urs); + esb_append(&urs, " uri: \""); + translate_to_uri(filename,&urs); + esb_append(&urs,"\""); + if(do_print_dwarf) { + printf("%s",esb_get_string(&urs)); + } + esb_destructor(&urs); + esb_empty_string(&lastsrc); + esb_append(&lastsrc,filename); + } + if (sres == DW_DLV_OK) { + dwarf_dealloc(dbg, filename, DW_DLA_STRING); + } + if (do_print_dwarf) { + printf("\n"); + } + } + esb_destructor(&lastsrc); + dwarf_srclines_dealloc(dbg, linebuf, linecount); + } +} |