Ejemplo n.º 1
0
static void
tp_dwarf_lineno_sanity(void)
{
	Dwarf_Debug dbg;
	Dwarf_Error de;
	Dwarf_Line *linebuf;
	Dwarf_Signed linecount;
	Dwarf_Signed srccount;
	char **srcfiles;
	int fd;

	result = TET_UNRESOLVED;

	TS_DWARF_INIT(dbg, fd, de);

	if (dwarf_srclines(NULL, &linebuf, &linecount, &de) !=
	    DW_DLV_ERROR) {
		tet_infoline("dwarf_srclines didn't return DW_DLV_ERROR"
		    " when called with NULL arguments");
		result = TET_FAIL;
	}

	if (dwarf_srcfiles(NULL, &srcfiles, &srccount, &de) !=
	    DW_DLV_ERROR) {
		tet_infoline("dwarf_srcfiles didn't return DW_DLV_ERROR"
		    " when called with NULL arguments");
		result = TET_FAIL;
	}

	if (result == TET_UNRESOLVED)
		result = TET_PASS;
done:
	TS_DWARF_FINISH(dbg, de);
	TS_RESULT(result);
}
Ejemplo n.º 2
0
/**
 * @brief Get line number information from compilation unit DIE.
 * @param cu_die Compilation unit DIE.
 * @param lvl    Level (depth) of this die.
 * @return Loaded line element pointer or nullptr if some problem.
 */
DwarfLine *DwarfLineContainer::loadAndGetDie(Dwarf_Die cu_die, unsigned)
{
	// Get all lines to buffer.
	Dwarf_Signed lineCnt = 0;
	Dwarf_Line *lineBuf = nullptr;

	m_res = dwarf_srclines(cu_die, &lineBuf, &lineCnt, &m_error);

	if (m_res == DW_DLV_NO_ENTRY)
	{
		return nullptr;
	}
	else if (m_res != DW_DLV_OK)
	{
		DWARF_ERROR(getDwarfError(m_error));
		return nullptr;
	}

	// Iterate through lines and load each one of them.
	for (int i=0; i<lineCnt; i++)
	{
		loadLine(lineBuf[i]);
	}

	dwarf_srclines_dealloc(m_parentFile->m_dbg, lineBuf, lineCnt);
	return nullptr;
}
Ejemplo n.º 3
0
error_t get_addr(mygdb_info_t *gdb_info, cmd_info_t* cmd_info, Dwarf_Addr* addr){
	Dwarf_Error err;
	Dwarf_Signed cnt;
	Dwarf_Unsigned line_num;
	Dwarf_Line *linebuf;
	error_t result = E_NONE;
	int found = 0;
	size_t i;
	
	if(dwarf_srclines(gdb_info->cu_die, &linebuf, &cnt, &err) != DW_DLV_OK){	
		printf("dwarf_srclines() failed\n");
		return E_FATAL;
	}
	
	for(i = 0; i < cnt; i++){
		if(dwarf_lineno(linebuf[i], &line_num, &err) == DW_DLV_ERROR){
			printf("dwarf_lineno() failed\n");
			result = E_FATAL;
		}
		if(line_num == cmd_info->set_breakpoint.line_num){
			found = 1;
			if( dwarf_lineaddr(linebuf[i], addr, &err) == DW_DLV_ERROR )
				result = E_FATAL;
		}
	}
	
	if(!found){
		printf("Not a valid line number: %d\n", (unsigned int)cmd_info->set_breakpoint.line_num);
		result = E_NON_FATAL;
	}
	
	return result;
}
Ejemplo n.º 4
0
unsigned long get_iaddr_of_file_line(const char *file, unsigned line){
 
  Dwarf_Unsigned cu_h_len;
  Dwarf_Half verstamp;
  Dwarf_Unsigned abbrev_offset;
  Dwarf_Half addrsize;
  Dwarf_Unsigned next_cu;
  Dwarf_Error error; 
  int found = 0;
  while( dwarf_next_cu_header(d,&cu_h_len,&verstamp,&abbrev_offset,&addrsize,&next_cu,&error) == DW_DLV_OK ){

    Dwarf_Die cu_die = NULL;
    int sibret;
 
    int dieno = 0; 
    while((sibret = 
           dwarf_siblingof(d,cu_die,&cu_die,&error)) != DW_DLV_NO_ENTRY &&
           sibret                                    != DW_DLV_ERROR){

      Dwarf_Signed cnt;
      Dwarf_Line *linebuf;
      int sres;
      if((sres = dwarf_srclines(cu_die, &linebuf, &cnt, &error)) == DW_DLV_OK){
        int i;
        for(i = 0; i < cnt; i++){
          char *lf;
          Dwarf_Unsigned ll;
          dwarf_linesrc(linebuf[i], &lf, &error); 
          dwarf_lineno(linebuf[i], &ll, &error);
          if(line == ll && strstr(lf,file)){
            Dwarf_Addr la;
            dwarf_lineaddr(linebuf[i], &la, &error);
            return la;
          }
          dwarf_dealloc(d, linebuf[i], DW_DLA_LINE);
        }
        dwarf_dealloc(d, linebuf, DW_DLA_LIST);
      }
    }
  }
  return 0xffffffffffffffff; 
}
struct dwarf_lines * dwarf_get_line_info_from_cu(struct dwarf_compilation_unit * cu){
  Dwarf_Signed linecount = 0;
  Dwarf_Line *linebuf = NULL;
  Dwarf_Unsigned lineno = 0;
  Dwarf_Error err;
  Dwarf_Addr pc;

  int lres = dwarf_srclines(cu->root_die, &linebuf, &linecount, &err);
  struct dwarf_line_of_code * lines = malloc(sizeof(struct dwarf_line_of_code) * linecount);
  int i=0;
  for (; i<linecount; i++) {
    Dwarf_Line line = linebuf[i];
    dwarf_lineaddr(line, &pc, &err);

    lines[i].addr = (unsigned long)pc;
    dwarf_lineno(line, &lineno, &err);
    lines[i].line_number = (unsigned int)lineno;
  }
  struct dwarf_lines * dwarf_lines = malloc(sizeof(struct dwarf_lines));
  dwarf_lines->lines = lines;
  dwarf_lines->number_of_lines = linecount;
  return dwarf_lines;
}
Ejemplo n.º 6
0
extern void
print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die)
{
    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;

    current_section_id = DEBUG_LINE;

    /* line_flag is TRUE */


    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";
    }
    if (do_print_dwarf) {
        printf("\n%s: line number info for a single cu\n", sec_name);
    } else {
        /* We are checking, not printing. */
        Dwarf_Half tag = 0;
        int tres = dwarf_tag(cu_die, &tag, &err);
        if (tres != DW_DLV_OK) {
            /*  Something broken here. */
            print_error(dbg,"Unable to see CU DIE tag "
                "though we could see it earlier. Something broken.",
                tres,err);
            return;
        } else if (tag == DW_TAG_type_unit) {
            /*  Not checking since type units missing
                address or range in CU header. */
            return;
        }
    }

    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));
        }
    }
    /*  The following is complicated by a desire to test
        various line table interface functions.  Hence
        we test line_flag_selection.

        Normal code should pick an interface
        (for most  the best choice is what we here call
        line_flag_selection == std)
        and use just that interface set.

        Sorry about the length of the code that
        results from having so many interfaces.  */
    if (line_flag_selection == std) {
        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 if (line_flag_selection == orig) {
        /* DWARF2,3,4, ok for 5. */
        /* Useless for experimental line tables */
        lres = dwarf_srclines(cu_die,
            &linebuf, &linecount, &err);
        if(lres == DW_DLV_OK && linecount ){
            table_count++;
        }
    } else if (line_flag_selection == orig2l) {
        lres = dwarf_srclines_two_level(cu_die,
            &lineversion,
            &linebuf, &linecount,
            &linebuf_actuals, &linecount_actuals,
            &err);
        if(lres == DW_DLV_OK && linecount){
            table_count++;
        }
        if(lres == DW_DLV_OK && linecount_actuals){
            table_count++;
        }
    } else if (line_flag_selection == s2l) {
        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) {
        /* 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 (table_count > 0) {
        /* DW_DLV_OK */
        if(line_context && verbose) {
            print_line_context_record(dbg,line_context);
        }
        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);
            }
        }
        if(line_flag_selection == std || line_flag_selection == s2l) {
            if (table_count == 0 || table_count == 1) {
                /* ASSERT: is_single_table == true */
                Dwarf_Bool is_logicals = FALSE;
                Dwarf_Bool is_actuals = FALSE;
                process_line_table(dbg,sec_name, linebuf, linecount,
                    is_logicals,is_actuals);
            } else {
                Dwarf_Bool is_logicals = TRUE;
                Dwarf_Bool is_actuals = FALSE;
                process_line_table(dbg,sec_name, linebuf, linecount,
                    is_logicals, is_actuals);
                process_line_table(dbg,sec_name, linebuf_actuals,
                    linecount_actuals,
                    !is_logicals, !is_actuals);
            }
            dwarf_srclines_dealloc_b(line_context);
        } else if (line_flag_selection == orig) {
            Dwarf_Bool is_logicals = FALSE;
            Dwarf_Bool is_actuals = FALSE;
            process_line_table(dbg,sec_name, linebuf, linecount,
                is_logicals, is_actuals);
            dwarf_srclines_dealloc(dbg,linebuf,linecount);
        } else if (line_flag_selection == orig2l) {
            if (table_count == 1 || table_count == 0) {
                Dwarf_Bool is_logicals = FALSE;
                Dwarf_Bool is_actuals = FALSE;
                process_line_table(dbg,sec_name, linebuf, linecount,
                    is_logicals, is_actuals);
            } else {
                Dwarf_Bool is_logicals = TRUE;
                Dwarf_Bool is_actuals = FALSE;
                process_line_table(dbg,sec_name, linebuf, linecount,
                    is_logicals, is_actuals);
                process_line_table(dbg,sec_name, linebuf_actuals, linecount_actuals,
                    !is_logicals, !is_actuals);
            }
            dwarf_srclines_dealloc(dbg,linebuf,linecount);
        }
        /* end, table_count > 0 */
    } else {
        /* DW_DLV_OK */
        /*  table_count == 0. no lines in table.
            Just a line table header. */
        if (do_print_dwarf) {
            int ores = 0;
            Dwarf_Unsigned off = 0;

            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);
            }
            if(line_context) {
                if (verbose > 2) {
                    print_line_context_record(dbg,line_context);
                }
                ores = dwarf_srclines_table_offset(line_context,
                    &off,&err);
                if (ores != DW_DLV_OK) {
                    print_error(dbg,"dwarf_srclines_table_offset fail",ores,err);
                } 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(line_flag_selection == std ||
            line_flag_selection == s2l) {
            dwarf_srclines_dealloc_b(line_context);
        } else {
            /* Original allocation. */
            dwarf_srclines_dealloc(dbg,linebuf,linecount);
        }
        /* end, linecounttotal == 0 */
    }
}
Ejemplo n.º 7
0
static void
_dwarf_lineno(Dwarf_Die die)
{
	Dwarf_Line *linebuf, ln;
	Dwarf_Signed linecount, lineoff;
	Dwarf_Unsigned lineno, srcfileno;
	Dwarf_Addr lineaddr;
	Dwarf_Half tag;
	Dwarf_Error de;
	Dwarf_Bool linebeginstatement, lineendsequence, lineblock;
	char *linesrc;
	int r_srclines;
	int i;

	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
		tet_printf("dwarf_tag failed: %s\n", dwarf_errmsg(de));
		result = TET_FAIL;
		return;
	}

	r_srclines = dwarf_srclines(die, &linebuf, &linecount, &de);
	TS_CHECK_INT(r_srclines);

	if (r_srclines == DW_DLV_ERROR) {
		tet_printf("dwarf_srclines should not fail but still failed:",
		    " %s", dwarf_errmsg(de));
		return;
	}

	if (r_srclines != DW_DLV_OK)
		return;

	for (i = 0; i < linecount; i++) {

		ln = linebuf[i];

		if (dwarf_linebeginstatement(ln, &linebeginstatement,
		     &de) != DW_DLV_OK) {
			tet_printf("dwarf_linebeginstatement failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_INT(linebeginstatement);

		if (dwarf_linebeginstatement(ln, &linebeginstatement,
		     &de) != DW_DLV_OK) {
			tet_printf("dwarf_linebeginstatement failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_INT(linebeginstatement);

		if (dwarf_lineendsequence(ln, &lineendsequence,
		     &de) != DW_DLV_OK) {
			tet_printf("dwarf_lineendsequence failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_INT(lineendsequence);

		if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK) {
			tet_printf("dwarf_lineno failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_UINT(lineno);

		if (dwarf_line_srcfileno(ln, &srcfileno, &de) != DW_DLV_OK) {
			tet_printf("dwarf_line_srcfileno failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_UINT(srcfileno);

		if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK) {
			tet_printf("dwarf_lineaddr failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_UINT(lineaddr);

		if (dwarf_lineoff(ln, &lineoff, &de) != DW_DLV_OK) {
			tet_printf("dwarf_lineoff failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_INT(lineoff);

		if (dwarf_linesrc(ln, &linesrc, &de) != DW_DLV_OK) {
			tet_printf("dwarf_linesrc failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_STRING(linesrc);

		if (dwarf_lineblock(ln, &lineblock, &de) != DW_DLV_OK) {
			tet_printf("dwarf_lineblock failed: %s",
			    dwarf_errmsg(de));
			result = TET_FAIL;
		}
		TS_CHECK_INT(lineblock);
	}
}
Ejemplo n.º 8
0
bool FLinuxCrashContext::GetInfoForAddress(void * Address, const char **OutFunctionNamePtr, const char **OutSourceFilePtr, int *OutLineNumberPtr)
{
	if (DebugInfo == NULL)
	{
		return false;
	}

	Dwarf_Die Die;
	Dwarf_Unsigned Addr = reinterpret_cast< Dwarf_Unsigned >( Address ), LineNumber = 0;
	const char * SrcFile = NULL;

	checkAtCompileTime(sizeof(Dwarf_Unsigned) >= sizeof(Address), _Dwarf_Unsigned_type_should_be_long_enough_to_represent_pointers_Check_libdwarf_bitness);

	int ReturnCode = DW_DLV_OK;
	Dwarf_Error ErrorInfo;
	bool bExitHeaderLoop = false;
	int32 MaxCompileUnitsAllowed = 16 * 1024 * 1024;	// safeguard to make sure we never get into an infinite loop
	const int32 kMaxBufferLinesAllowed = 16 * 1024 * 1024;	// safeguard to prevent too long line loop
	for(;;)
	{
		if (--MaxCompileUnitsAllowed <= 0)
		{
			fprintf(stderr, "Breaking out from what seems to be an infinite loop during DWARF parsing (too many compile units).\n");
			ReturnCode = DW_DLE_DIE_NO_CU_CONTEXT;	// invalidate
			break;
		}

		if (bExitHeaderLoop)
			break;

		ReturnCode = dwarf_next_cu_header(DebugInfo, NULL, NULL, NULL, NULL, NULL, &ErrorInfo);
		if (ReturnCode != DW_DLV_OK)
			break;

		Die = NULL;

		while(dwarf_siblingof(DebugInfo, Die, &Die, &ErrorInfo) == DW_DLV_OK)
		{
			Dwarf_Half Tag;
			if (dwarf_tag(Die, &Tag, &ErrorInfo) != DW_DLV_OK)
			{
				bExitHeaderLoop = true;
				break;
			}

			if (Tag == DW_TAG_compile_unit)
			{
				break;
			}
		}

		if (Die == NULL)
		{
			break;
		}

		// check if address is inside this CU
		Dwarf_Unsigned LowerPC, HigherPC;
		if (!dwarf_attrval_unsigned(Die, DW_AT_low_pc, &LowerPC, &ErrorInfo) && !dwarf_attrval_unsigned(Die, DW_AT_high_pc, &HigherPC, &ErrorInfo))
		{
			if (Addr < LowerPC || Addr >= HigherPC)
			{
				continue;
			}
		}

		Dwarf_Line * LineBuf;
		Dwarf_Signed NumLines = kMaxBufferLinesAllowed;
		if (dwarf_srclines(Die, &LineBuf, &NumLines, &ErrorInfo) != DW_DLV_OK)
		{
			// could not get line info for some reason
			break;
		}

		if (NumLines >= kMaxBufferLinesAllowed)
		{
			fprintf(stderr, "Number of lines associated with a DIE looks unreasonable (%ld), early quitting.\n", NumLines);
			ReturnCode = DW_DLE_DIE_NO_CU_CONTEXT;	// invalidate
			break;
		}

		// look which line is that
		Dwarf_Addr LineAddress, PrevLineAddress = ~0ULL;
		Dwarf_Unsigned PrevLineNumber = 0;
		const char * PrevSrcFile = NULL;
		char * SrcFileTemp = NULL;
		for (int Idx = 0; Idx < NumLines; ++Idx)
		{
			if (dwarf_lineaddr(LineBuf[Idx], &LineAddress, &ErrorInfo) != 0 ||
				dwarf_lineno(LineBuf[Idx], &LineNumber, &ErrorInfo) != 0)
			{
				bExitHeaderLoop = true;
				break;
			}

			if (!dwarf_linesrc(LineBuf[Idx], &SrcFileTemp, &ErrorInfo))
			{
				SrcFile = SrcFileTemp;
			}

			// check if we hit the exact line
			if (Addr == LineAddress)
			{
				bExitHeaderLoop = true;
				break;
			}
			else if (PrevLineAddress < Addr && Addr < LineAddress)
			{
				LineNumber = PrevLineNumber;
				SrcFile = PrevSrcFile;
				bExitHeaderLoop = true;
				break;
			}

			PrevLineAddress = LineAddress;
			PrevLineNumber = LineNumber;
			PrevSrcFile = SrcFile;
		}

	}

	const char * FunctionName = NULL;
	if (ReturnCode == DW_DLV_OK)
	{
		FindFunctionNameInDIEAndChildren(DebugInfo, Die, Addr, &FunctionName);
	}

	if (OutFunctionNamePtr != NULL && FunctionName != NULL)
	{
		*OutFunctionNamePtr = FunctionName;
	}

	if (OutSourceFilePtr != NULL && SrcFile != NULL)
	{
		*OutSourceFilePtr = SrcFile;
		
		if (OutLineNumberPtr != NULL)
		{
			*OutLineNumberPtr = LineNumber;
		}
	}

	// Resets internal CU pointer, so next time we get here it begins from the start
	while (ReturnCode != DW_DLV_NO_ENTRY) 
	{
		if (ReturnCode == DW_DLV_ERROR)
			break;
		ReturnCode = dwarf_next_cu_header(DebugInfo, NULL, NULL, NULL, NULL, NULL, &ErrorInfo);
	}

	// if we weren't able to find a function name, don't trust the source file either
	return FunctionName != NULL;
}
Ejemplo n.º 9
0
int
open_dwarf_executable (char *fileName)
{
  int dwStatus = -1;


  mpiPi_msg_debug ("enter open_dwarf_executable\n");
  if (fileName == NULL)
    {
      mpiPi_msg_warn ("Executable file name is NULL!\n");
      mpiPi_msg_warn
	("If this is a Fortran application, you may be using the incorrect mpiP library.\n");
    }

  /* open the executable */
  assert (dwFd == -1);
  mpiPi_msg_debug ("opening file %s\n", fileName);
  dwFd = open (fileName, O_RDONLY);
  if (dwFd == -1)
    {
      mpiPi_msg_warn ("could not open file %s\n", fileName);
      return 0;
    }

  /* initialize the DWARF library */
  assert (dwHandle == NULL);
  dwStatus = dwarf_init (dwFd,	/* exe file descriptor */
			 DW_DLC_READ,	/* desired access */
			 NULL,	/* error handler */
			 NULL,	/* error argument */
			 &dwHandle,	/* session handle */
			 &dw_err);	/* error object */
  if (dwStatus == DW_DLV_ERROR)
    {
      close (dwFd);
      dwFd = -1;
      mpiPi_abort ("could not initialize DWARF library : %s\n", dwarf_errmsg(dw_err));
    }

  if (dwStatus == DW_DLV_NO_ENTRY)
    {
      mpiPi_msg_warn ("No symbols in the executable\n");
      return 0;
    }

  /* initialize our function and addr-to-source mappings */
  AddrToSourceMap_Init ();
  FunctionMap_Init ();

  /* access symbol info */
  while (1)
    {
      Dwarf_Unsigned nextCompilationUnitHeaderOffset = 0;
      Dwarf_Die currCompileUnitDIE = NULL;
      Dwarf_Line *lineEntries = NULL;
      Dwarf_Signed nLineEntries = 0;
      Dwarf_Half currDIETag;
      Dwarf_Die currChildDIE = NULL;
      Dwarf_Die nextChildDIE = NULL;
      Dwarf_Die oldChildDIE = NULL;


      /* access next compilation unit header */
      dwStatus = dwarf_next_cu_header (dwHandle, NULL,	/* cu_header_length */
				       NULL,	/* version_stamp */
				       NULL,	/* abbrev_offset */
				       NULL,	/* address_size */
				       &nextCompilationUnitHeaderOffset, &dw_err);	/* error object */
      if (dwStatus != DW_DLV_OK)
	{
	  if (dwStatus != DW_DLV_NO_ENTRY)
	    {
	      mpiPi_abort ("failed to access next DWARF cu header : %s\n", dwarf_errmsg(dw_err));
	    }
	  break;
	}

      /* access the first debug info entry (DIE) for this computation unit */
      dwStatus = dwarf_siblingof (dwHandle, NULL,	/* current DIE */
				  &currCompileUnitDIE,	/* sibling DIE */
				  &dw_err);	/* error object */
      if (dwStatus != DW_DLV_OK)
	{
	  mpiPi_abort ("failed to access first DWARF DIE : %s\n", dwarf_errmsg(dw_err));
	}

      /* get line number information for this compilation 
       * unit, if available 
       */
      dwStatus = dwarf_srclines (currCompileUnitDIE,
				 &lineEntries, &nLineEntries, &dw_err);
      if (dwStatus == DW_DLV_OK)
	{
	  unsigned int i;


	  /*
	   * Extract and save address-to-source line mapping.
	   * 
	   * NOTE: At least on the Cray X1, we see line number 
	   * information with the same address mapping to different lines.
	   * It seems like when there are multiple entries for a given
	   * address, the last one is the correct one.  (Needs verification.)
	   * If we see multiple entries for a given address, we only 
	   * save the last one.
	   */
	  for (i = 0; i < nLineEntries; i++)
	    {
	      Dwarf_Unsigned lineNumber = 0;
	      Dwarf_Addr lineAddress = 0;
	      char *lineSourceFile = NULL;


	      int lineNoStatus, lineAddrStatus, lineSrcFileStatus;

	      lineNoStatus = dwarf_lineno (lineEntries[i],
					   &lineNumber,
					   &dw_err);

              if (lineNoStatus != DW_DLV_OK)
                 mpiPi_msg_debug("Failed to get line number : %s\n", dwarf_errmsg(dw_err));

	      lineAddrStatus = dwarf_lineaddr (lineEntries[i],
						&lineAddress,
						&dw_err);

              if (lineAddrStatus != DW_DLV_OK)
                 mpiPi_msg_debug("Failed to get line address : %s\n", dwarf_errmsg(dw_err));

	      lineSrcFileStatus = dwarf_linesrc (lineEntries[i],
						 &lineSourceFile,
						 &dw_err);

              if (lineSrcFileStatus != DW_DLV_OK)
                 mpiPi_msg_debug("Failed to get source file status : %s\n", dwarf_errmsg(dw_err));

	      if ((lineNoStatus == DW_DLV_OK) &&
		  (lineAddrStatus == DW_DLV_OK)
		  && (lineSrcFileStatus == DW_DLV_OK))
		{
		  int saveCurrentEntry = 0;	/* bool */

		  if (i < (nLineEntries - 1))
		    {
		      /*
		       * We're not on the last line number entry -
		       * check the address associated with the next
		       * entry to see if it differs from this one.
		       * Only save the entry if it the next address
		       * differs.
		       */
		      Dwarf_Addr nextLineAddress = 0;
		      int nextLineAddrStatus =
			dwarf_lineaddr (lineEntries[i + 1],
					&nextLineAddress,
					&dw_err);
		      assert (nextLineAddrStatus == DW_DLV_OK);
		      if (nextLineAddress != lineAddress)
			{
			  saveCurrentEntry = 1;
			}
		    }
		  else
		    {
		      /* we're on the last line number entry */
		      saveCurrentEntry = 1;
		    }

		  if (saveCurrentEntry)
		    {
		      /* save the mapping entry */
		      AddrToSourceMap_Add (lineAddress, lineSourceFile,
					   lineNumber);
		    }
		}

	      if (lineSourceFile != NULL)
		{
		  dwarf_dealloc (dwHandle, lineSourceFile, DW_DLA_STRING);
		}
	    }

	  /* release the line number info */
	  for (i = 0; i < nLineEntries; i++)
	    {
	      dwarf_dealloc (dwHandle, lineEntries[i], DW_DLA_LINE);
	    }
	  dwarf_dealloc (dwHandle, lineEntries, DW_DLA_LIST);
	}
      else if (dwStatus != DW_DLV_ERROR)
	{
	  /*
	   * no line information for the current DIE - 
	   * not an error, just unfortunate
	   */
	}
      else
	{
	  mpiPi_abort ("failed to obtain line info for the current DIE : %s\n", dwarf_errmsg(dw_err));
	}

      /* discover function information for the current compilation unit */
      /* 
       * NOTE: DWARF debug information entries can be organized in 
       * a hierarchy.  However, we presume that the function entries are
       * all children of the compilation unit DIE.
       */
      dwStatus = dwarf_tag (currCompileUnitDIE, &currDIETag, &dw_err);
      assert ((dwStatus == DW_DLV_OK) && (currDIETag == DW_TAG_compile_unit));

      /* access the first child DIE of the compile unit DIE */
      dwStatus = dwarf_child (currCompileUnitDIE, &currChildDIE, &dw_err);
      if (dwStatus == DW_DLV_NO_ENTRY)
	{
          // On some Cray systems, executables are linked with assembly compile units
          // with no functions.
          // mpiPi_abort ("no child DIEs of compile unit DIE\n");
	}
      else if (dwStatus != DW_DLV_OK)
	{
	  mpiPi_abort
	    ("failed to access first child DIE of compile unit DIE\n");
	}

      while (dwStatus == DW_DLV_OK)
	{
	  /* determine the type of the child DIE */
	  dwStatus = dwarf_tag (currChildDIE, &currDIETag, &dw_err);
	  if (dwStatus == DW_DLV_OK)
	    {
	      if ((currDIETag == DW_TAG_subprogram) ||
		  (currDIETag == DW_TAG_entry_point))
		{
		  HandleFunctionDIE (dwHandle, currChildDIE);
		}
	    }
	  else
	    {
	      mpiPi_abort ("unable to determine tag of current child DIE : %s \n", dwarf_errmsg(dw_err));
	    }

	  /* advance to the next child DIE */
	  oldChildDIE = currChildDIE;
	  dwStatus = dwarf_siblingof (dwHandle,
				      currChildDIE, &nextChildDIE, &dw_err);
	  if (dwStatus == DW_DLV_OK)
	    {
	      currChildDIE = nextChildDIE;
	      nextChildDIE = NULL;
	    }
	  else if (dwStatus != DW_DLV_NO_ENTRY)
	    {
	      mpiPi_abort
		("unable to access next child DIE of current compilation unit : %s\n", dwarf_errmsg(dw_err));
	    }

	  if (oldChildDIE != NULL)
	    {
	      dwarf_dealloc (dwHandle, oldChildDIE, DW_DLA_DIE);
	    }
	}

      /* release the current compilation unit DIE */
      dwarf_dealloc (dwHandle, currCompileUnitDIE, DW_DLA_DIE);
    }

  /*
   * DWARF address-to-source line information does not give
   * address ranges, so we need to patch the address ranges
   * in our address-to-source map.
   */
  AddrToSourceMap_PatchRanges ();

  return 1;
}
Ejemplo n.º 10
0
int list_func_die(struct Ripdebuginfo *info, Dwarf_Die *die, uint64_t addr)
{
	_Dwarf_Line ln;
	Dwarf_Attribute *low;
	Dwarf_Attribute *high;
	Dwarf_CU *cu = die->cu_header;
	Dwarf_Die *cudie = die->cu_die; 
	Dwarf_Die ret, sib=*die; 
	Dwarf_Attribute *attr;
	uint64_t offset;
	uint64_t ret_val=8;
	
	if(die->die_tag != DW_TAG_subprogram)
		return 0;

	memset(&ln, 0, sizeof(_Dwarf_Line));

	low  = _dwarf_attr_find(die, DW_AT_low_pc);
	high = _dwarf_attr_find(die, DW_AT_high_pc);

	if((low && (low->u[0].u64 < addr)) && (high && (high->u[0].u64 > addr)))
	{
		info->rip_file = die->cu_die->die_name;

		info->rip_fn_name = die->die_name;
		info->rip_fn_namelen = strlen(die->die_name);

		info->rip_fn_addr = (uintptr_t)low->u[0].u64;

		assert(die->cu_die);	
		dwarf_srclines(die->cu_die, &ln, addr, NULL); 

		info->rip_line = ln.ln_lineno;
		info->rip_fn_narg = 0;

		Dwarf_Attribute* attr;

		if(dwarf_child(dbg, cu, &sib, &ret) != DW_DLE_NO_ENTRY)
		{
			if(ret.die_tag != DW_TAG_formal_parameter)
				goto last;

			attr = _dwarf_attr_find(&ret, DW_AT_type);
	
		try_again:
			if(attr != NULL)
			{
				offset = (uint64_t)cu->cu_offset + attr->u[0].u64;
				dwarf_offdie(dbg, offset, &sib, *cu);
				attr = _dwarf_attr_find(&sib, DW_AT_byte_size);
		
				if(attr != NULL)
				{
					ret_val = attr->u[0].u64;
				}
				else
				{
					attr = _dwarf_attr_find(&sib, DW_AT_type);
					goto try_again;
				}
			}
			info->size_fn_arg[info->rip_fn_narg] = ret_val;
			info->rip_fn_narg++;
			sib = ret; 

			while(dwarf_siblingof(dbg, &sib, &ret, cu) == DW_DLV_OK)	
			{
				if(ret.die_tag != DW_TAG_formal_parameter)
					break;

				attr = _dwarf_attr_find(&ret, DW_AT_type);
    
				if(attr != NULL)
				{	   
					offset = (uint64_t)cu->cu_offset + attr->u[0].u64;
					dwarf_offdie(dbg, offset, &sib, *cu);
					attr = _dwarf_attr_find(&sib, DW_AT_byte_size);
        
					if(attr != NULL)
					{
						ret_val = attr->u[0].u64;
					}
				}
	
				info->size_fn_arg[info->rip_fn_narg]=ret_val;// _get_arg_size(ret);
				info->rip_fn_narg++;
				sib = ret; 
			}
		}
	last:	
		return 1;
	}

	return 0;
}
Ejemplo n.º 11
0
void mapped_module::parseFileLineInfo() {
	/* Determine if we've parsed this file already. */
	image * moduleImage = obj()->parse_img();
	assert( moduleImage != NULL );
	const Object & moduleObject = moduleImage->getObject();	
	const char * fileName = moduleObject.getFileName();

	/* We have not parsed this file already, so wind up libdwarf. */
	int fd = open( fileName, O_RDONLY );
   if (fd == -1)
      return;
	
	Dwarf_Debug dbg;
	int status = dwarf_init(	fd, DW_DLC_READ, & pd_dwarf_handler,
								moduleObject.getErrFunc(),
								& dbg, NULL );
	if( status != DW_DLV_OK ) { P_close( fd ); return; }
	
	/* Itereate over the CU headers. */
	Dwarf_Unsigned header;
	while( dwarf_next_cu_header( dbg, NULL, NULL, NULL, NULL, & header, NULL ) == DW_DLV_OK ) {
		/* Acquire the CU DIE. */
		Dwarf_Die cuDIE;
		status = dwarf_siblingof( dbg, NULL, & cuDIE, NULL);
		if( status != DW_DLV_OK ) { 
			/* If we can get no (more) CUs, we're done. */
			break;
			}
		
		/* Acquire this CU's source lines. */
		Dwarf_Line * lineBuffer;
		Dwarf_Signed lineCount;
		status = dwarf_srclines( cuDIE, & lineBuffer, & lineCount, NULL );
		
		/* See if we can get anything useful out of the next CU
		   if this one is corrupt. */
		if( status == DW_DLV_ERROR ) {
			dwarf_printf( "%s[%d]: dwarf_srclines() error.\n" );
			}
		
		/* It's OK for a CU not to have line information. */
		if( status != DW_DLV_OK ) {
			/* Free this CU's DIE. */
			dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
			continue;
			}
		assert( status == DW_DLV_OK );
		
		/* The 'lines' returned are actually interval markers; the code
		   generated from lineNo runs from lineAddr up to but not including
		   the lineAddr of the next line. */			   
		bool isPreviousValid = false;
		Dwarf_Unsigned previousLineNo = 0;
		Dwarf_Addr previousLineAddr = 0x0;
		char * previousLineSource = NULL;
		
		Address baseAddr = obj()->codeBase();
		
		/* Iterate over this CU's source lines. */
		for( int i = 0; i < lineCount; i++ ) {
			/* Acquire the line number, address, source, and end of sequence flag. */
			Dwarf_Unsigned lineNo;
			status = dwarf_lineno( lineBuffer[i], & lineNo, NULL );
			if( status != DW_DLV_OK ) { continue; }
				
			Dwarf_Addr lineAddr;
			status = dwarf_lineaddr( lineBuffer[i], & lineAddr, NULL );
			if( status != DW_DLV_OK ) { continue; }
			lineAddr += baseAddr;
			
			char * lineSource;
			status = dwarf_linesrc( lineBuffer[i], & lineSource, NULL );
			if( status != DW_DLV_OK ) { continue; }
						
			Dwarf_Bool isEndOfSequence;
			status = dwarf_lineendsequence( lineBuffer[i], & isEndOfSequence, NULL );
			if( status != DW_DLV_OK ) { continue; }
			
			if( isPreviousValid ) {
				/* If we're talking about the same (source file, line number) tuple,
				   and it isn't the end of the sequence, we can coalesce the range.
				   (The end of sequence marker marks discontinuities in the ranges.) */
				if( lineNo == previousLineNo && strcmp( lineSource, previousLineSource ) == 0 && ! isEndOfSequence ) {
					/* Don't update the prev* values; just keep going until we hit the end of a sequence or
					   a new sourcefile. */
					continue;
					} /* end if we can coalesce this range */
                                
				/* Determine into which mapped_module this line information should be inserted. */
				int_function * currentFunction = obj()->findFuncByAddr( previousLineAddr );
				if( currentFunction == NULL ) {
					// /* DEBUG */ fprintf( stderr, "%s[%d]: failed to find function containing address 0x%lx; line number information will be lost.\n", __FILE__, __LINE__, lineAddr );
					}
				else {
					mapped_module * currentModule = currentFunction->mod();
					assert( currentModule != NULL );
					
					char * canonicalLineSource = strrchr( previousLineSource, '/' );
					if( canonicalLineSource == NULL ) { canonicalLineSource = previousLineSource; }
					else { ++canonicalLineSource; }
					
					/* The line 'canonicalLineSource:previousLineNo' has an address range of [previousLineAddr, lineAddr). */
					currentModule->lineInfo_.addLine( canonicalLineSource, previousLineNo, previousLineAddr, lineAddr );
				
					// /* DEBUG */ fprintf( stderr, "%s[%d]: inserted address range [0x%lx, 0x%lx) for source '%s:%u' into module '%s'.\n", __FILE__, __LINE__, previousLineAddr, lineAddr, canonicalLineSource, previousLineNo, currentModule->fileName().c_str() );
					} /* end if we found the function by its address */
				} /* end if the previous* variables are valid */
				
			/* If the current line ends the sequence, invalidate previous; otherwise, update. */
			if( isEndOfSequence ) {
				dwarf_dealloc( dbg, lineSource, DW_DLA_STRING );
				
				isPreviousValid = false;
				}
			else {
				if( isPreviousValid ) { dwarf_dealloc( dbg, previousLineSource, DW_DLA_STRING ); }

				previousLineNo = lineNo;
				previousLineSource = lineSource;
				previousLineAddr = lineAddr;
							
				isPreviousValid = true;
				} /* end if line was not the end of a sequence */
			} /* end iteration over source line entries. */
		
		/* Free this CU's source lines. */
		for( int i = 0; i < lineCount; i++ ) {
			dwarf_dealloc( dbg, lineBuffer[i], DW_DLA_LINE );
			}
		dwarf_dealloc( dbg, lineBuffer, DW_DLA_LIST );
		
		/* Free this CU's DIE. */
		dwarf_dealloc( dbg, cuDIE, DW_DLA_DIE );
		} /* end CU header iteration */

	/* Wind down libdwarf. */
	status = dwarf_finish( dbg, NULL );
	if( status != DW_DLV_OK ) {
		dwarf_printf( "%s[%d]: failed to dwarf_finish()\n" );
		}
	P_close( fd );
	
	/* Note that we've parsed this file. */
	} /* end parseFileLineInfo() */
Ejemplo n.º 12
0
static void
translate(Dwarf_Debug dbg, const char* addrstr)
{
	Dwarf_Die die, ret_die;
	Dwarf_Line *lbuf;
	Dwarf_Error de;
	Dwarf_Half tag;
	Dwarf_Unsigned lopc, hipc, addr, lineno, plineno;
	Dwarf_Signed lcount;
	Dwarf_Addr lineaddr, plineaddr;
	char *funcname;
	char *file, *file0, *pfile;
	char demangled[1024];
	int i, ret;

	addr = strtoull(addrstr, NULL, 16);
	addr += section_base;
	lineno = 0;
	file = unknown;
	die = NULL;
	lbuf = NULL;
	lcount = 0;

	while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
	    &de)) ==  DW_DLV_OK) {
		die = NULL;
		while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) {
			if (die != NULL)
				dwarf_dealloc(dbg, die, DW_DLA_DIE);
			die = ret_die;
			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
				warnx("dwarf_tag failed: %s",
				    dwarf_errmsg(de));
				goto next_cu;
			}

			/* XXX: What about DW_TAG_partial_unit? */
			if (tag == DW_TAG_compile_unit)
				break;
		}
		if (ret_die == NULL) {
			warnx("could not find DW_TAG_compile_unit die");
			goto next_cu;
		}
		if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) &&
		    !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) {
			/*
			 * Check if the address falls into the PC range of
			 * this CU.
			 */
			if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
				goto next_cu;
			if (addr < lopc || addr >= hipc)
				goto next_cu;
		}

		switch (dwarf_srclines(die, &lbuf, &lcount, &de)) {
		case DW_DLV_OK:
			break;
		case DW_DLV_NO_ENTRY:
			/* If a CU lacks debug info, just skip it. */
			goto next_cu;
		default:
			warnx("dwarf_srclines: %s", dwarf_errmsg(de));
			goto out;
		}

		plineaddr = ~0ULL;
		plineno = 0;
		pfile = unknown;
		for (i = 0; i < lcount; i++) {
			if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) {
				warnx("dwarf_lineaddr: %s",
				    dwarf_errmsg(de));
				goto out;
			}
			if (dwarf_lineno(lbuf[i], &lineno, &de)) {
				warnx("dwarf_lineno: %s",
				    dwarf_errmsg(de));
				goto out;
			}
			if (dwarf_linesrc(lbuf[i], &file0, &de)) {
				warnx("dwarf_linesrc: %s",
				    dwarf_errmsg(de));
			} else
				file = file0;
			if (addr == lineaddr)
				goto out;
			else if (addr < lineaddr && addr > plineaddr) {
				lineno = plineno;
				file = pfile;
				goto out;
			}
			plineaddr = lineaddr;
			plineno = lineno;
			pfile = file;
		}
	next_cu:
		if (die != NULL) {
			dwarf_dealloc(dbg, die, DW_DLA_DIE);
			die = NULL;
		}
	}

out:
	funcname = NULL;
	if (ret == DW_DLV_OK && func) {
		search_func(dbg, die, addr, &funcname);
		die = NULL;
	}

	if (func) {
		if (funcname == NULL)
			if ((funcname = strdup(unknown)) == NULL)
				err(EXIT_FAILURE, "strdup");
		if (demangle &&
		    !elftc_demangle(funcname, demangled, sizeof(demangled), 0))
			printf("%s\n", demangled);
		else
			printf("%s\n", funcname);
		free(funcname);
	}

	(void) printf("%s:%ju\n", base ? basename(file) : file, lineno);

	if (die != NULL)
		dwarf_dealloc(dbg, die, DW_DLA_DIE);

	/*
	 * Reset internal CU pointer, so we will start from the first CU
	 * next round.
	 */
	while (ret != DW_DLV_NO_ENTRY) {
		if (ret == DW_DLV_ERROR)
			errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
			    dwarf_errmsg(de));
		ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
		    &de);
	}
}