#include <config.h>
#include <string.h> /* strcmp() strlen() */
#include <time.h> /* ctime() */
#include <stdio.h> /* FILE decl for dd_esb.h, printf etc */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dd_defined_types.h"
#include "dd_checkutil.h"
#include "dd_glflags.h"
#include "dd_globals.h"
#include "dd_naming.h"
#include "dd_esb.h"
#include "dd_esb_using_functions.h"
#include "dd_sanitized.h"
#include "dd_uri.h"
#include "print_sections.h"
#define DW_LINE_VERSION5 5
static
void
print_source_intro(Dwarf_Debug dbg,Dwarf_Die cu_die)
{
int
ores = 0;
Dwarf_Off off = 0;
Dwarf_Error src_err = 0;
ores = dwarf_dieoffset(cu_die, &off, &src_err);
if
(ores == DW_DLV_OK) {
int
lres = 0;
const
char
*sec_name = 0;
lres = dwarf_get_die_section_name_b(cu_die,
&sec_name,&src_err);
if
(lres != DW_DLV_OK || !sec_name || !
strlen
(sec_name)) {
sec_name =
".debug_info"
;
}
printf
(
"Source lines (from CU-DIE at %s offset 0x%"
DW_PR_XZEROS DW_PR_DUx
"):\n"
,
sec_name,
(Dwarf_Unsigned) off);
DROP_ERROR_INSTANCE(dbg,lres,src_err);
}
else
{
DROP_ERROR_INSTANCE(dbg,ores,src_err);
printf
(
"Source lines (for the CU-DIE at unknown"
" location):\n"
);
}
}
static
void
print_common_line_error(
const
char
*where, Dwarf_Error line_err)
{
if
(checking_this_compiler()) {
struct
esb_s tmp_buff;
char
buftmp[ESB_FIXED_ALLOC_SIZE];
esb_constructor_fixed(&tmp_buff,buftmp,
sizeof
(buftmp));
esb_append_printf_s(&tmp_buff,
"Error getting line details calling %s"
,
where);
esb_append_printf_s(&tmp_buff,
" dwarf error is %s"
,
dwarf_errmsg(line_err));
DWARF_CHECK_ERROR(lines_result,esb_get_string(&tmp_buff));
esb_destructor(&tmp_buff);
}
}
static
void
check_last_line_of_table(Dwarf_Addr pc,
Dwarf_Addr elf_max_address,
const
char
* sec_name)
{
if
(glflags.gf_check_lines &&
checking_this_compiler()) {
DWARF_CHECK_COUNT(lines_result,1);
if
((pc != glflags.PU_high_address) &&
(glflags.PU_base_address !=
elf_max_address)) {
char
addr_tmp[140];
struct
esb_s cm;
esb_constructor_fixed(&cm,addr_tmp,
sizeof
(addr_tmp));
esb_append_printf_s(&cm,
"%s: Address"
,sanitized(sec_name));
esb_append_printf_u(&cm,
" 0x%"
DW_PR_XZEROS DW_PR_DUx
" DW_LNE_end_sequence address"
" does not exactly match"
,pc);
esb_append_printf_u(&cm,
" high function addr: "
" 0x%"
DW_PR_XZEROS DW_PR_DUx,
glflags.PU_high_address);
DWARF_CHECK_ERROR(lines_result,
esb_get_string(&cm));
esb_destructor(&cm);
}
}
}
static
int
process_line_table(Dwarf_Debug dbg,
const
char
*sec_name,
Dwarf_Line *linebuf,
Dwarf_Signed linecount,
Dwarf_Bool is_logicals_table,
Dwarf_Bool is_actuals_table,
Dwarf_Error *lt_err)
{
char
*padding = 0;
Dwarf_Signed i = 0;
Dwarf_Addr pc = 0;
Dwarf_Unsigned lineno = 0;
Dwarf_Unsigned logicalno = 0;
Dwarf_Unsigned column = 0;
Dwarf_Unsigned call_context = 0;
char
* subprog_name = 0;
char
* subprog_filename = 0;
Dwarf_Unsigned subprog_line = 0;
Dwarf_Bool newstatement = 0;
Dwarf_Bool lineendsequence = 0;
Dwarf_Bool new_basic_block = 0;
int
sres = 0;
int
ares = 0;
int
lires = 0;
int
cores = 0;
char
lastsrc_tmp[ESB_FIXED_ALLOC_SIZE];
struct
esb_s lastsrc;
Dwarf_Addr elf_max_address = 0;
Dwarf_Bool SkipRecord = FALSE;
esb_constructor_fixed(&lastsrc,lastsrc_tmp,
sizeof
(lastsrc_tmp));
glflags.current_section_id = DEBUG_LINE;
get_address_size_and_max(dbg,0,&elf_max_address,lt_err);
padding = glflags.gf_line_print_pc ?
" "
:
""
;
if
(glflags.gf_do_print_dwarf) {
printf
(
"\n"
);
if
(is_logicals_table) {
printf
(
"Logicals Table:\n"
);
printf
(
"%sNS new statement, PE prologue end, "
"EB epilogue begin\n"
,padding);
printf
(
"%sDI=val discriminator value\n"
,
padding);
printf
(
"%sCC=val context, SB=val subprogram\n"
,
padding);
}
else
if
(is_actuals_table) {
printf
(
"Actuals Table:\n"
);
printf
(
"%sBB new basic block, ET end of text sequence\n"
"%sIS=val ISA number\n"
,padding,padding);
}
else
{
printf
(
"%sNS new statement, BB new basic block, "
"ET end of text sequence\n"
,padding);
printf
(
"%sPE prologue end, EB epilogue begin\n"
,padding);
printf
(
"%sIS=val ISA number, "
"DI=val discriminator value\n"
,
padding);
}
if
(is_logicals_table || is_actuals_table) {
printf
(
"[ row] "
);
}
if
(glflags.gf_line_print_pc) {
printf
(
"<pc> "
);
}
if
(is_logicals_table) {
printf
(
"[lno,col] NS PE EB DI= CC= SB= uri:"
" \"filepath\"\n"
);
}
else
if
(is_actuals_table) {
printf
(
"[logical] BB ET IS=\n"
);
}
else
{
printf
(
"[lno,col] NS BB ET PE EB IS= DI= uri:"
" \"filepath\"\n"
);
}
}
for
(i = 0; i < linecount; i++) {
Dwarf_Line line = linebuf[i];
char
* lsrc_filename = 0;
int
nsres = 0;
Dwarf_Bool found_line_error = FALSE;
Dwarf_Bool has_is_addr_set = FALSE;
char
*where = NULL;
if
(glflags.gf_check_decl_file && checking_this_compiler()) {
if
(SkipRecord) {
ares = dwarf_line_is_addr_set(line,
&has_is_addr_set, lt_err);
if
(ares == DW_DLV_OK && has_is_addr_set) {
SkipRecord = FALSE;
}
else
{
continue
;
}
}
}
if
(glflags.gf_check_lines && checking_this_compiler()) {
DWARF_CHECK_COUNT(lines_result,1);
}
if
(!is_actuals_table) {
Dwarf_Error aterr = 0;
sres = dwarf_linesrc(line, &lsrc_filename, &aterr);
if
(sres == DW_DLV_ERROR) {
if
(glflags.gf_do_check_dwarf &&
checking_this_compiler()) {
where =
"dwarf_linesrc()"
;
print_common_line_error(where,aterr);
found_line_error = TRUE;
}
DROP_ERROR_INSTANCE(dbg,sres,aterr);
}
}
pc = 0;
ares = dwarf_lineaddr(line, &pc, lt_err);
if
(ares == DW_DLV_ERROR) {
if
(glflags.gf_do_check_dwarf &&
checking_this_compiler()) {
where =
"dwarf_lineaddr()"
;
print_common_line_error(where,*lt_err);
found_line_error = TRUE;
}
pc = 0;
DROP_ERROR_INSTANCE(dbg,ares,*lt_err);
}
if
(ares == DW_DLV_NO_ENTRY) {
pc = 0;
}
if
(is_actuals_table) {
lires = dwarf_linelogical(line, &logicalno, lt_err);
if
(lires == DW_DLV_ERROR) {
if
(glflags.gf_do_check_dwarf &&
checking_this_compiler()) {
where =
"dwarf_linelogical()"
;
print_common_line_error(where,*lt_err);
found_line_error = TRUE;
}
DROP_ERROR_INSTANCE(dbg,lires,*lt_err);
}
if
(lires == DW_DLV_NO_ENTRY) {
logicalno = 0;
}
column = 0;
}
else
{
lires = dwarf_lineno(line, &lineno, lt_err);
if
(lires == DW_DLV_ERROR) {
where =
"dwarf_lineno()"
;
print_common_line_error(where,*lt_err);
found_line_error = TRUE;
DROP_ERROR_INSTANCE(dbg,lires,*lt_err);
}
if
(lires == DW_DLV_NO_ENTRY) {
lineno = 0;
}
cores = dwarf_lineoff_b(line, &column, lt_err);
if
(cores == DW_DLV_ERROR) {
if
(glflags.gf_do_check_dwarf &&
checking_this_compiler()) {
where =
"dwarf_lineoff()"
;
print_common_line_error(where,*lt_err);
found_line_error = TRUE;
}
DROP_ERROR_INSTANCE(dbg,cores,*lt_err);
}
if
(cores == DW_DLV_NO_ENTRY) {
column = 0;
}
}
if
((glflags.gf_check_decl_file ||
glflags.gf_check_lines) &&
checking_this_compiler()) {
DWARF_CHECK_COUNT(decl_file_result,1);
if
(found_line_error) {
#if 0
DWARF_CHECK_ERROR2(decl_file_result,where,
dwarf_errmsg(lt_err);
#endif
}
else
if
(glflags.gf_do_check_dwarf) {
if
(IsValidInBucketGroup(glflags.pRangesInfo,pc)) {
}
else
{
if
(glflags.gf_check_lines &&
checking_this_compiler()) {
DWARF_CHECK_COUNT(lines_result,1);
}
if
(FindAddressInBucketGroup(
glflags.pLinkonceInfo,pc)){
}
else
{
if
(pc) {
if
(glflags.gf_check_lines &&
checking_this_compiler()) {
char
abuf[50];
struct
esb_s atm;
esb_constructor_fixed(&atm,
abuf,
sizeof
(abuf));
esb_append_printf_s(&atm,
"%s: Address"
,
sanitized(sec_name));
esb_append_printf_u(&atm,
" 0x%"
DW_PR_XZEROS DW_PR_DUx
" outside a valid .text range"
,
pc);
DWARF_CHECK_ERROR(lines_result,
esb_get_string(&atm));
esb_destructor(&atm);
}
}
else
{
SkipRecord = TRUE;
}
}
}
if
((i + 1 == linecount) &&
glflags.seen_PU_high_address &&
!is_logicals_table) {
check_last_line_of_table(pc,
elf_max_address,sec_name);
}
}
}
if
(found_line_error || glflags.gf_record_dwarf_error) {
if
(glflags.gf_check_verbose_mode && PRINTING_UNIQUE) {
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,
lsrc_filename?sanitized(lsrc_filename):
""
);
if
(!glflags.gf_check_decl_file) {
PRINT_CU_INFO();
}
}
glflags.gf_record_dwarf_error = FALSE;
if
(found_line_error) {
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
continue
;
}
}
if
(glflags.gf_do_print_dwarf) {
if
(is_logicals_table || is_actuals_table) {
printf
(
"[%4"
DW_PR_DUu
"] "
, i + 1);
}
if
(glflags.gf_line_print_pc) {
printf
(
"0x%"
DW_PR_XZEROS DW_PR_DUx
" "
, pc);
}
if
(is_actuals_table) {
printf
(
"[%7"
DW_PR_DUu
"]"
, logicalno);
}
else
{
printf
(
"[%4"
DW_PR_DUu
",%2"
DW_PR_DUu
"]"
,
lineno, column);
}
}
if
(!is_actuals_table) {
nsres = dwarf_linebeginstatement(line,
&newstatement, lt_err);
if
(nsres == DW_DLV_OK) {
if
(newstatement && glflags.gf_do_print_dwarf) {
printf
(
" %s"
,
"NS"
);
}
}
else
if
(nsres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_linebeginstatement failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
nsres;
}
}
if
(!is_logicals_table) {
nsres = dwarf_lineblock(line,
&new_basic_block, lt_err);
if
(nsres == DW_DLV_OK) {
if
(new_basic_block && glflags.gf_do_print_dwarf) {
printf
(
" %s"
,
"BB"
);
}
}
else
if
(nsres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_lineblock failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
nsres;
}
nsres = dwarf_lineendsequence(line,
&lineendsequence, lt_err);
if
(nsres == DW_DLV_OK) {
if
(lineendsequence &&
glflags.gf_do_print_dwarf) {
printf
(
" %s"
,
"ET"
);
}
}
else
if
(nsres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_lineendsequence failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
nsres;
}
}
if
(glflags.gf_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,lt_err);
if
(disres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_prologue_end_etc() failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
disres;
}
if
(prologue_end && !is_actuals_table) {
printf
(
" PE"
);
}
if
(epilogue_begin && !is_actuals_table) {
printf
(
" EB"
);
}
if
(isa && !is_logicals_table) {
printf
(
" IS=0x%"
DW_PR_DUx, isa);
}
if
(discriminator && !is_actuals_table) {
printf
(
" DI=0x%"
DW_PR_DUx, discriminator);
}
if
(is_logicals_table) {
call_context = 0;
disres = dwarf_linecontext(line,
&call_context, lt_err);
if
(disres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_linecontext() failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
disres;
}
if
(call_context) {
printf
(
" CC=%"
DW_PR_DUu, call_context);
}
{
Dwarf_Unsigned subprogno = 0;
disres = dwarf_line_subprogno(line,
&subprogno,0);
if
(disres == DW_DLV_OK) {
}
else
{
printf
(
"ERROR: dwarf_line_subprogno()"
" impossibly! "
"fails. with result %d\n"
,disres);
glflags.gf_count_major_errors++;
}
}
subprog_name = 0;
disres = dwarf_line_subprog(line,
&subprog_name,
&subprog_filename,
&subprog_line, lt_err);
if
(disres == DW_DLV_ERROR) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_u(&m,
"\nERROR: dwarf_line_subprog() failed"
" on linebuf index %u "
,i);
esb_append_printf_u(&m,
"of %u line records in the linebuf."
,
linecount);
simple_err_return_action(nsres,
esb_get_string(&m));
esb_destructor(&m);
dwarf_dealloc(dbg, lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
return
disres;
}
if
(subprog_name &&
strlen
(subprog_name)) {
printf
(
" SB=\"%s\""
, sanitized(subprog_name));
}
dwarf_dealloc(dbg,subprog_filename, DW_DLA_STRING);
subprog_filename = 0;
}
}
if
(!is_actuals_table) {
if
(i == 0 || glflags.verbose > 2 ||
strcmp
(lsrc_filename?lsrc_filename:
""
,
esb_get_string(&lastsrc))) {
struct
esb_s urs;
char
atmp2[ESB_FIXED_ALLOC_SIZE];
esb_constructor_fixed(&urs,atmp2,
sizeof
(atmp2));
esb_append(&urs,
" uri: \""
);
translate_to_uri(lsrc_filename?
lsrc_filename:
""
,
&urs);
esb_append(&urs,
"\""
);
if
(glflags.gf_do_print_dwarf) {
printf
(
"%s"
,esb_get_string(&urs));
}
esb_destructor(&urs);
esb_empty_string(&lastsrc);
esb_append(&lastsrc,
lsrc_filename?lsrc_filename:
""
);
}
else
{
}
}
if
(glflags.gf_do_print_dwarf) {
printf
(
"\n"
);
}
dwarf_dealloc(dbg,lsrc_filename, DW_DLA_STRING);
lsrc_filename = 0;
}
esb_destructor(&lastsrc);
return
DW_DLV_OK;
}
static
int
print_line_context_record(Dwarf_Line_Context line_context,
Dwarf_Error *err)
{
int
vres = 0;
Dwarf_Unsigned lsecoff = 0;
Dwarf_Unsigned version = 0;
Dwarf_Signed dir_count = 0;
Dwarf_Signed baseindex = 0;
Dwarf_Signed file_count = 0;
Dwarf_Signed endindex = 0;
Dwarf_Signed i = 0;
Dwarf_Signed subprog_count = 0;
const
char
*name = 0;
Dwarf_Small table_count = 0;
struct
esb_s bufr;
Dwarf_Signed include_dir_base = 1;
Dwarf_Signed include_dir_limit = 0;
char
bufr_tmp[ESB_FIXED_ALLOC_SIZE];
esb_constructor_fixed(&bufr,bufr_tmp,
sizeof
(bufr_tmp));
printf
(
"Line Context data\n"
);
vres = dwarf_srclines_table_offset(line_context,&lsecoff,
err);
if
(vres != DW_DLV_OK) {
simple_err_return_action(vres,
"\nERROR: dwarf_srclines_table_offset() failed"
". Something broken"
);
return
vres;
}
printf
(
" Line Section Offset 0x%"
DW_PR_XZEROS DW_PR_DUx
"\n"
, lsecoff);
vres = dwarf_srclines_version(line_context,&version,
&table_count, err);
if
(vres != DW_DLV_OK) {
simple_err_return_action(vres,
"\nERROR: dwarf_srclines_version() failed"
". Something broken"
);
return
vres;
}
printf
(
" version number 0x%"
DW_PR_DUx
" %"
DW_PR_DUu
"\n"
,
version,version);
printf
(
" number of line tables %d.\n"
, table_count);
vres = dwarf_srclines_comp_dir(line_context,&name,err);
if
(vres != DW_DLV_OK) {
simple_err_return_action(vres,
"\nERROR: dwarf_srclines_comp_dir() failed"
". Something broken"
);
return
vres;
}
if
(name) {
printf
(
" Compilation directory: %s\n"
,name);
}
else
{
printf
(
" Compilation directory: <unknown"
" no DW_AT_comp_dir>\n"
);
}
vres = dwarf_srclines_include_dir_count(line_context,
&dir_count,err);
if
(vres != DW_DLV_OK) {
simple_err_return_action(vres,
"\nERROR: dwarf_srclines_comp_dir() failed"
". Something broken"
);
return
vres;
}
printf
(
" include directory count 0x%"
DW_PR_DUx
" %"
DW_PR_DSd
"\n"
,
(Dwarf_Unsigned)dir_count,dir_count);
if
(version == DW_LINE_VERSION5) {
include_dir_base = 0;
include_dir_limit = dir_count;
}
else
{
include_dir_base = 1;
include_dir_limit = dir_count+1;
}
for
(i = include_dir_base; i < include_dir_limit; ++i) {
vres = dwarf_srclines_include_dir_data(line_context,i,
&name,err);
if
(vres != DW_DLV_OK) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_i(&m,
"\nERROR: Error accessing include directory "
" %d "
,i);
esb_append_printf_i(&m,
"(max allowed index is %d)."
,dir_count);
simple_err_return_action(vres,
esb_get_string(&m));
esb_destructor(&m);
return
vres;
}
printf
(
" [%2"
DW_PR_DSd
"] \"%s\"\n"
,i,name);
}
vres = dwarf_srclines_files_indexes(line_context,
&baseindex,&file_count,&endindex,err);
if
(vres != DW_DLV_OK) {
simple_err_return_action(vres,
"\nERROR: Error accessing files indexes"
);
return
vres;
}
printf
(
" files count 0x%"
DW_PR_DUx
" %"
DW_PR_DUu
"\n"
,
file_count,file_count);
for
(i = baseindex; i < endindex; ++i) {
Dwarf_Unsigned dirindex = 0;
Dwarf_Unsigned modtime = 0;
Dwarf_Unsigned flength = 0;
Dwarf_Form_Data16 *md5data = 0;
vres = dwarf_srclines_files_data_b(line_context,i,
&name,&dirindex, &modtime,&flength,
&md5data,err);
if
(vres != DW_DLV_OK) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_i(&m,
"\nERROR: Error accessing line_context "
" calling dwarf_srclines_files_data_b() "
"with index %d "
,i);
esb_append_printf_i(&m,
"(end index is %d)."
,endindex);
simple_err_return_action(vres,
esb_get_string(&m));
esb_destructor(&m);
return
vres;
}
esb_empty_string(&bufr);
if
(name) {
esb_empty_string(&bufr);
esb_append(&bufr,
"\""
);
esb_append(&bufr,name);
esb_append(&bufr,
"\""
);
}
else
{
esb_append(&bufr,
"<ERROR:NULL name in files list>"
);
}
printf
(
" [%2"
DW_PR_DSd
"] %-24s ,"
,
i,esb_get_string(&bufr));
printf
(
" directory index %2"
DW_PR_DUu ,dirindex);
printf
(
", file length %2"
DW_PR_DUu ,flength);
if
(md5data) {
char
*c = (
char
*)md5data;
char
*end = c+
sizeof
(*md5data);
printf
(
", file md5 value 0x"
);
while
(c < end) {
printf
(
"%02x"
,0xff&*c);
++c;
}
printf
(
" "
);
}
if
(modtime) {
time_t
tt3 = (
time_t
)modtime;
printf
(
"file mod time 0x%lx %s"
, (unsigned
long
)tt3,
ctime
(&tt3));
}
else
{
printf
(
" file mod time 0\n"
);
}
}
esb_destructor(&bufr);
vres = dwarf_srclines_subprog_count(line_context,&subprog_count,
err);
if
(vres != DW_DLV_OK) {
simple_err_return_msg_either_action(vres,
"ERROR: dwarf_srclines_subprog_count() on a "
"line_context fails"
);
return
vres;
}
if
(subprog_count == 0) {
return
DW_DLV_OK;
}
printf
(
" subprograms count (experimental) 0x%"
DW_PR_DUx
" %"
DW_PR_DUu
"\n"
,
subprog_count,subprog_count);
for
(i = 1; i <= subprog_count; ++i) {
Dwarf_Unsigned decl_file = 0;
Dwarf_Unsigned decl_line = 0;
vres = dwarf_srclines_subprog_data(line_context,i,
&name,&decl_file, &decl_line,err);
if
(vres != DW_DLV_OK) {
struct
esb_s m;
esb_constructor(&m);
esb_append_printf_i(&m,
"\nERROR: Error accessing line_context "
" calling dwarf_srclines_subprog_data() "
"with index %d "
,i);
esb_append_printf_i(&m,
"(end index is %d)."
,subprog_count);
simple_err_return_action(vres,
esb_get_string(&m));
esb_destructor(&m);
return
vres;
}
printf
(
" [%2"
DW_PR_DSd
"] \"%s\""
", fileindex %2"
DW_PR_DUu
", lineindex %2"
DW_PR_DUu
"\n"
,
i,name,decl_file,decl_line);
}
return
DW_DLV_OK;
}
int
print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die,
char
**srcfiles,
Dwarf_Signed srcf_count,
Dwarf_Error *err)
{
Dwarf_Unsigned lineversion = 0;
Dwarf_Signed linecount = 0;
Dwarf_Line *linebuf = NULL;
Dwarf_Signed linecount_actuals = 0;
Dwarf_Line *linebuf_actuals = NULL;
Dwarf_Small table_count = 0;
int
lres = 0;
int
line_errs = 0;
Dwarf_Line_Context line_context = 0;
const
char
*sec_name = 0;
Dwarf_Off cudie_local_offset = 0;
Dwarf_Off dieprint_cu_goffset = 0;
int
atres = 0;
glflags.current_section_id = DEBUG_LINE;
lres = dwarf_get_line_section_name_from_die(cu_die,
&sec_name,err);
if
(lres != DW_DLV_OK || !sec_name || !
strlen
(sec_name)) {
sec_name =
".debug_line"
;
}
DROP_ERROR_INSTANCE(dbg,lres,*err);
atres = dwarf_die_offsets(cu_die,&dieprint_cu_goffset,
&cudie_local_offset,err);
DROP_ERROR_INSTANCE(dbg,atres,*err);
if
(glflags.gf_do_print_dwarf) {
struct
esb_s truename;
char
buf[ESB_FIXED_ALLOC_SIZE];
esb_constructor_fixed(&truename,buf,
sizeof
(buf));
get_true_section_name(dbg,
".debug_line"
,
&truename,FALSE);
printf
(
"\n%s: line number info for a single cu\n"
,
sanitized(esb_get_string(&truename)));
esb_destructor(&truename);
}
else
{
Dwarf_Half tag = 0;
int
tres = dwarf_tag(cu_die, &tag, err);
if
(tres != DW_DLV_OK) {
struct
esb_s m;
esb_constructor(&m);
esb_append(&m,
"\nERROR: Unable to get CU DIE dwarf tag "
"attempting to print line numbers for a CU "
);
if
(tres == DW_DLV_ERROR) {
esb_append(&m,dwarf_errmsg(*err));
}
simple_err_return_msg_either_action(tres,
esb_get_string(&m));
esb_destructor(&m);
return
tres;
}
else
if
(tag == DW_TAG_type_unit) {
return
DW_DLV_NO_ENTRY;
}
}
if
(glflags.verbose > 1) {
int
errcount = 0;
Dwarf_Bool attr_dup = FALSE;
int
lresv = 0;
print_source_intro(dbg,cu_die);
lresv = print_one_die(dbg, cu_die,
dieprint_cu_goffset,
1,
0,
srcfiles,srcf_count,
&attr_dup,
TRUE,
err);
if
(lresv == DW_DLV_ERROR) {
return
lresv;
}
DWARF_CHECK_COUNT(lines_result,1);
lresv = dwarf_print_lines(cu_die, err,&errcount);
if
(errcount > 0) {
DWARF_ERROR_COUNT(lines_result,errcount);
DWARF_CHECK_COUNT(lines_result,(errcount-1));
}
if
(lresv == DW_DLV_ERROR) {
print_error_and_continue(
"Failed to print CU lines"
,
lresv, *err);
}
return
lresv;
}
if
(glflags.gf_check_lines && checking_this_compiler()) {
int
lres2 = 0;
DWARF_CHECK_COUNT(lines_result,1);
lres2 = dwarf_check_lineheader_b(cu_die,&line_errs,
err);
if
(lres2 == DW_DLV_ERROR) {
print_error_and_continue(
"dwarf_check_lineheader_b found a serious error"
,
lres2, *err);
dwarf_dealloc(dbg,*err,DW_DLA_ERROR);
*err = 0;
}
if
(line_errs > 0) {
DWARF_CHECK_ERROR_PRINT_CU();
DWARF_ERROR_COUNT(lines_result,line_errs);
DWARF_CHECK_COUNT(lines_result,(line_errs-1));
}
}
if
(glflags.gf_line_flag_selection == singledw5) {
lres = dwarf_srclines_b(cu_die,&lineversion,
&table_count,&line_context,
err);
if
(lres == DW_DLV_OK) {
lres = dwarf_srclines_from_linecontext(line_context,
&linebuf, &linecount,err);
}
}
else
{
lres = dwarf_srclines_b(cu_die,&lineversion,
&table_count,&line_context,
err);
if
(lres == DW_DLV_OK) {
lres = dwarf_srclines_two_level_from_linecontext(
line_context,
&linebuf, &linecount,
&linebuf_actuals, &linecount_actuals,
err);
}
}
if
(lres == DW_DLV_ERROR) {
if
(glflags.gf_check_decl_file ||
glflags.gf_check_lines) {
DWARF_CHECK_COUNT(decl_file_result,1);
DWARF_CHECK_ERROR2(decl_file_result,
"dwarf_srclines"
,
dwarf_errmsg(*err));
glflags.gf_record_dwarf_error = FALSE;
}
else
{
print_error_and_continue(
"dwarf_srclines"
,
lres, *err);
}
DROP_ERROR_INSTANCE(dbg,lres,*err);
return
DW_DLV_OK;
}
else
if
(lres == DW_DLV_NO_ENTRY) {
}
else
if
(table_count > 0) {
if
(glflags.gf_do_print_dwarf) {
if
(line_context && glflags.verbose) {
lres = print_line_context_record(line_context,err);
if
(lres != DW_DLV_OK){
dwarf_srclines_dealloc_b(line_context);
return
lres;
}
}
print_source_intro(dbg,cu_die);
if
(glflags.verbose) {
int
dres = 0;
Dwarf_Bool attr_dup = FALSE;
dres = print_one_die(dbg, cu_die,
dieprint_cu_goffset,
TRUE,
0,
0,
0,
&attr_dup,
TRUE,err);
if
(dres == DW_DLV_ERROR) {
dwarf_srclines_dealloc_b(line_context);
return
dres;
}
}
}
if
(glflags.gf_line_flag_selection == singledw5 ||
glflags.gf_line_flag_selection == s2l) {
int
ltres = 0;
if
(table_count == 0 || table_count == 1) {
Dwarf_Bool is_logicals = FALSE;
Dwarf_Bool is_actuals = FALSE;
ltres = process_line_table(dbg,sec_name,
linebuf, linecount,
is_logicals,is_actuals,err);
if
(ltres == DW_DLV_ERROR) {
dwarf_srclines_dealloc_b(line_context);
return
ltres;
}
}
else
{
Dwarf_Bool is_logicals = TRUE;
Dwarf_Bool is_actuals = FALSE;
ltres = process_line_table(dbg,sec_name,
linebuf, linecount,
is_logicals, is_actuals,err);
if
(ltres != DW_DLV_OK) {
dwarf_srclines_dealloc_b(line_context);
return
ltres;
}
ltres = process_line_table(dbg,sec_name,
linebuf_actuals,
linecount_actuals,
!is_logicals, !is_actuals,err);
if
(ltres != DW_DLV_OK) {
dwarf_srclines_dealloc_b(line_context);
return
ltres;
}
}
dwarf_srclines_dealloc_b(line_context);
line_context = 0;
linebuf = 0;
}
}
else
{
if
(glflags.gf_do_print_dwarf) {
int
ores = 0;
Dwarf_Unsigned off = 0;
print_source_intro(dbg,cu_die);
if
(glflags.verbose) {
int
dpres = 0;
Dwarf_Bool attr_dup = FALSE;
dpres = print_one_die(dbg, cu_die,
dieprint_cu_goffset,
TRUE,
0,
0,
0,
&attr_dup,
TRUE,
err);
if
(dpres == DW_DLV_ERROR) {
dwarf_srclines_dealloc_b(line_context);
return
dpres;
}
}
if
(line_context) {
if
(glflags.verbose > 2) {
ores = print_line_context_record(
line_context,err);
if
(ores != DW_DLV_OK) {
simple_err_return_msg_either_action(
ores,
"ERROR: line context record "
" where table count is 0 has a"
" problem"
);
dwarf_srclines_dealloc_b(line_context);
return
ores;
}
}
ores = dwarf_srclines_table_offset(
line_context,
&off,err);
if
(ores != DW_DLV_OK) {
simple_err_return_msg_either_action(
ores,
"ERROR: line context table_offset "
" where table count is 0 has a"
" problem"
);
dwarf_srclines_dealloc_b(line_context);
return
ores;
}
else
{
printf
(
" Line table is present (offset 0x%"
DW_PR_XZEROS DW_PR_DUx
") but no lines present\n"
, off);
}
}
else
{
printf
(
" Line table is present but"
" no lines present\n"
);
}
}
if
(glflags.gf_line_flag_selection == singledw5 ||
glflags.gf_line_flag_selection == s2l) {
dwarf_srclines_dealloc_b(line_context);
line_context = 0;
linebuf = 0;
}
}
if
(line_context) {
dwarf_srclines_dealloc_b(line_context);
line_context = 0;
linebuf = 0;
}
return
DW_DLV_OK;
}