int main(int argc, char** argv)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Error err;
    const char* progname;
    int fd = -1;

    if (argc < 2) {
        fprintf(stderr, "Expected a program name as argument\n");
        return 1;
    }

    progname = argv[1];
    if ((fd = open(progname, O_RDONLY)) < 0) {
        perror("open");
        return 1;
    }
    
    if (dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err) != DW_DLV_OK) {
        fprintf(stderr, "Failed DWARF initialization\n");
        return 1;
    }

    list_funcs_in_file(dbg);

    if (dwarf_finish(dbg, &err) != DW_DLV_OK) {
        fprintf(stderr, "Failed DWARF finalization\n");
        return 1;
    }

    close(fd);
    return 0;
}
Example #2
0
void
close_dwarf_executable (void)
{
  int dwStatus = -1;
  Elf *elfHandle = NULL;

  mpiPi_msg_debug ("enter close_dwarf_executable\n");

  assert (dwHandle != NULL);
  assert (dwFd != -1);
  dwStatus = dwarf_get_elf (dwHandle, &elfHandle, &dw_err);
  if (dwStatus != DW_DLV_OK)
    {
      mpiPi_msg_debug ("dwarf_get_elf failed; ignoring : %s\n", dwarf_errmsg(dw_err));
    }

  dwStatus = dwarf_finish (dwHandle, &dw_err);
  if (dwStatus != DW_DLV_OK)
    {
      mpiPi_msg_debug ("dwarf_finish failed; ignoring : %s\n", dwarf_errmsg(dw_err));
    }
  dwHandle = NULL;

  close (dwFd);
  dwFd = -1;

  AddrToSourceMap_Destroy ();
  FunctionMap_Destroy ();
}
Example #3
0
void CUsHolder::clean(void) throw()
{
  Dwarf_Error err = NULL;
  int ret = 0;

  for(size_t idx = 0; idx < size(); ++idx)
  {
    dwarf_dealloc(m_dbg, (*this)[idx], DW_DLA_DIE);
    (*this)[idx] = NULL;
  }

  ret = dwarf_finish(m_dbg, &err);
  if(ret != DW_DLV_OK)
  {
    MSG("libdwarf cleanup failed: %s\n", dwarf_errmsg(err));
  }

  clear();

  m_dbg = NULL;
  if(m_fd != -1)
  {
    close(m_fd), m_fd = -1;
  }
}
FLinuxCrashContext::~FLinuxCrashContext()
{
	if (BacktraceSymbols)
	{
		// glibc uses malloc() to allocate this, and we only need to free one pointer, see http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
		free(BacktraceSymbols);
		BacktraceSymbols = NULL;
	}

	if (DebugInfo)
	{
		Dwarf_Error ErrorInfo;
		dwarf_finish(DebugInfo, &ErrorInfo);
		DebugInfo = NULL;
	}

	if (ElfHdr)
	{
		elf_end(ElfHdr);
		ElfHdr = NULL;
	}

	if (ExeFd >= 0)
	{
		close(ExeFd);
		ExeFd = -1;
	}
}
Example #5
0
int 
main(int argc, char **argv)
{

    Dwarf_Debug dbg = 0;
    int fd = -1;
    const char *filepath = "<stdin>";
    int res = DW_DLV_ERROR;
    Dwarf_Error error;
    Dwarf_Handler errhand = 0;
    Dwarf_Ptr errarg = 0;

    if(argc < 2) {
        fd = 0; /* stdin */
    } else {
        filepath = argv[1];
        fd = open(filepath,O_RDONLY);
    }
    if(fd < 0) {
        printf("Failure attempting to open %s\n",filepath);
    }
    res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
    if(res != DW_DLV_OK) {
        printf("Giving up, cannot do DWARF processing\n");
        exit(1);
    }

    read_cu_list(dbg);
    res = dwarf_finish(dbg,&error);
    if(res != DW_DLV_OK) {
        printf("dwarf_finish failed!\n");
    }
    close(fd);
    return 0;
}
Example #6
0
File: rdwarf.c Project: kubo/rdwarf
static void rd_shared_data_free(rd_shared_data_t *sd)
{
    Dwarf_Error err;

    dwarf_finish(sd->dbg, &err);
    close(sd->fd);
    xfree(sd);
}
Example #7
0
void release_dbg(mygdb_info_t* gdb_info){

	Dwarf_Error* err = NULL;
	
	dwarf_finish(gdb_info->dbg, err);
	close(gdb_info->dbg_fd);
	gdb_info->dbg_fd = -1;

}
int 
main(int argc, char **argv)
{

    Dwarf_Debug dbg = 0;
    int fd = -1;
    const char *filepath = "<stdin>";
    int res = DW_DLV_ERROR;
    Dwarf_Error error;
    Dwarf_Handler errhand = 0;
    Dwarf_Ptr errarg = 0;
    
    
    /**/

    if(argc < 2) {
        fd = 0; /* stdin */
    } else {
        int i = 0;
        for(i = 1; i < (argc-1) ; ++i) {
            if(strcmp(argv[i],"--names") == 0) {
                namesoptionon=1;
            } else {
                printf("Unknown argument \"%s\" ignored\n",argv[i]);
            }
        }
        filepath = argv[i];
        fd = open(filepath,O_RDONLY);
    }
    if(argc > 2) {
    }

    /**/

    if(fd < 0) {
        printf("Failure attempting to open \"%s\"\n",filepath);
    }
    res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
    if(res != DW_DLV_OK) {
        printf("Giving up, cannot do DWARF processing\n");
        exit(1);
    }

    read_cu_list(dbg);
    res = dwarf_finish(dbg,&error);
    if(res != DW_DLV_OK) {
        printf("dwarf_finish failed!\n");
    }
    close(fd);
    return 0;
}
Example #9
0
static int process_one_file(Elf *elf)
{
    Dwarf_Debug dbg;
    int ret;

    ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, NULL);
    if (ret != DW_DLV_OK)
    {
        fprintf(stderr, "SET dwarf: Error in dwarf_elf_init()\n");
        return 1;
    }

    ret = process_CUs(dbg);
    dwarf_finish(dbg, NULL);

    return ret;
}
Example #10
0
int dwarf(int argc, char** argv)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Error err;
    const char* progname;
    char filename[TARGET_NAME_LEN];
    int fd = -1;
    FILE *fp = NULL;

    if (argc < 2) {
        fprintf(stderr, "Expected a program name as argument\n");
        return 1;
    }

    progname = argv[1];
    if ((fd = open(progname, O_RDONLY)) < 0) {
        perror("open");
        return 1;
    }

    strncpy(filename, progname, TARGET_NAME_LEN - strlen(suffix) - 1);
    strncat(filename, suffix, strlen(suffix));
    if ((fp = fopen(filename, "w")) < 0){
        perror("open");
        return 1;
    }
    
    if (dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err) != DW_DLV_OK) {
        fprintf(stderr, "Failed DWARF initialization\n");
        return 1;
    }

    list_funcs_in_file(dbg, fp);
    fclose(fp);

    if (dwarf_finish(dbg, &err) != DW_DLV_OK) {
        fprintf(stderr, "Failed DWARF finalization\n");
        return 1;
    }

    close(fd);
    return 0;
}
Example #11
0
File: gentype.c Project: nunb/ponyc
static bool make_tuple(compile_t* c, ast_t* ast, gentype_t* g)
{
  // An anonymous structure with no functions and no vtable.
  if(setup_name(c, ast, g, false))
    return true;

  setup_tuple_fields(g);

  dwarf_forward(&c->dwarf, g);

  bool ok = make_struct(c, g) && make_components(c, g);

  // Finalise debug symbols for tuple type.
  dwarf_composite(&c->dwarf, g);
  dwarf_finish(&c->dwarf);

  // Generate a descriptor.
  gendesc_init(c, g);

  free_fields(g);
  return ok;
}
void FLinuxCrashContext::InitFromSignal(int32 InSignal, siginfo_t* InInfo, void* InContext)
{
	Signal = InSignal;
	Info = InInfo;
	Context = reinterpret_cast< ucontext_t* >( InContext );

	// open ourselves for examination
	if (!FParse::Param( FCommandLine::Get(), TEXT(CMDARG_SUPPRESS_DWARF_PARSING)))
	{
		ExeFd = open("/proc/self/exe", O_RDONLY);
		if (ExeFd >= 0)
		{
			Dwarf_Error ErrorInfo;
			// allocate DWARF debug descriptor
			if (dwarf_init(ExeFd, DW_DLC_READ, NULL, NULL, &DebugInfo, &ErrorInfo) == DW_DLV_OK)
			{
				// get ELF descritor
				if (dwarf_get_elf(DebugInfo, &ElfHdr, &ErrorInfo) != DW_DLV_OK)
				{
					dwarf_finish(DebugInfo, &ErrorInfo);
					DebugInfo = NULL;

					close(ExeFd);
					ExeFd = -1;
				}
			}
			else
			{
				DebugInfo = NULL;
				close(ExeFd);
				ExeFd = -1;
			}
		}
	}

	FCString::Strcat(SignalDescription, ARRAY_COUNT( SignalDescription ) - 1, *DescribeSignal(Signal, Info));
}
Example #13
0
File: gentype.c Project: nunb/ponyc
static bool make_nominal(compile_t* c, ast_t* ast, gentype_t* g, bool prelim)
{
  assert(ast_id(ast) == TK_NOMINAL);
  ast_t* def = (ast_t*)ast_data(ast);
  token_id id = ast_id(def);

  // For traits, just return a raw object pointer.
  switch(id)
  {
    case TK_INTERFACE:
    case TK_TRAIT:
      g->underlying = id;
      g->use_type = c->object_ptr;
      dwarf_trait(&c->dwarf, g);
      return true;

    default: {}
  }

  // If we already exist or we're preliminary, we're done.
  if(setup_name(c, ast, g, prelim))
    return true;

  if(g->primitive == NULL)
  {
    // Not a primitive type. Generate all the fields and a trace function.
    setup_type_fields(g);

    // Forward declare debug symbols for this nominal, if needed.
    // At this point, this can only be TK_STRUCT, TK_CLASS, TK_PRIMITIVE, or
    // TK_ACTOR ast nodes. TK_TYPE has been translated to any of the former
    // during reification.
    dwarf_forward(&c->dwarf, g);

    bool ok = make_struct(c, g);

    if(!g->done)
      ok = ok && make_trace(c, g) && make_components(c, g);

    if(!ok)
    {
      free_fields(g);
      return false;
    }

    // Finalise symbols for composite type.
    if(!g->done)
      dwarf_composite(&c->dwarf, g);
  } else {
    // Emit debug symbols for a basic type (U8, U16, U32...)
    dwarf_basic(&c->dwarf, g);

    // Create a box type.
    make_box_type(c, g);
  }

  if(!g->done)
  {
    // Generate a dispatch function if necessary.
    make_dispatch(c, g);

    // Create a unique global instance if we need one.
    make_global_instance(c, g);

    // Generate all the methods.
    if(!genfun_methods(c, g))
    {
      free_fields(g);
      return false;
    }

    if(g->underlying != TK_STRUCT)
      gendesc_init(c, g);

    // Finish off the dispatch function.
    if(g->underlying == TK_ACTOR)
    {
      codegen_startfun(c, g->dispatch_fn, false);
      codegen_finishfun(c);
    }

    // Finish the dwarf frame.
    dwarf_finish(&c->dwarf);
  }

  free_fields(g);
  g->done = true;
  return true;
}
Example #14
0
File: genexpr.c Project: ozra/ponyc
LLVMValueRef gen_expr(compile_t* c, ast_t* ast)
{
  LLVMValueRef ret;
  bool has_scope = ast_has_scope(ast);
  bool has_source = codegen_hassource(c);

  if(has_scope)
  {
    codegen_pushscope(c);

    // Dwarf a new lexical scope, if necessary.
    if(has_source)
      dwarf_lexicalscope(&c->dwarf, ast);
  }

  switch(ast_id(ast))
  {
    case TK_SEQ:
      ret = gen_seq(c, ast);
      break;

    case TK_FVARREF:
    case TK_FLETREF:
      ret = gen_fieldload(c, ast);
      break;

    case TK_PARAMREF:
      ret = gen_param(c, ast);
      break;

    case TK_VAR:
    case TK_LET:
      ret = gen_localdecl(c, ast);
      break;

    case TK_VARREF:
    case TK_LETREF:
      ret = gen_localload(c, ast);
      break;

    case TK_IF:
      ret = gen_if(c, ast);
      break;

    case TK_WHILE:
      ret = gen_while(c, ast);
      break;

    case TK_REPEAT:
      ret = gen_repeat(c, ast);
      break;

    case TK_TRY:
    case TK_TRY_NO_CHECK:
      ret = gen_try(c, ast);
      break;

    case TK_MATCH:
      ret = gen_match(c, ast);
      break;

    case TK_CALL:
      ret = gen_call(c, ast);
      break;

    case TK_CONSUME:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_RECOVER:
      ret = gen_expr(c, ast_childidx(ast, 1));
      break;

    case TK_BREAK:
      ret = gen_break(c, ast);
      break;

    case TK_CONTINUE:
      ret = gen_continue(c, ast);
      break;

    case TK_RETURN:
      ret = gen_return(c, ast);
      break;

    case TK_ERROR:
      ret = gen_error(c, ast);
      break;

    case TK_IS:
      ret = gen_is(c, ast);
      break;

    case TK_ISNT:
      ret = gen_isnt(c, ast);
      break;

    case TK_ASSIGN:
      ret = gen_assign(c, ast);
      break;

    case TK_THIS:
      ret = gen_this(c, ast);
      break;

    case TK_TRUE:
      ret = LLVMConstInt(c->i1, 1, false);
      break;

    case TK_FALSE:
      ret = LLVMConstInt(c->i1, 0, false);
      break;

    case TK_INT:
      ret = gen_int(c, ast);
      break;

    case TK_FLOAT:
      ret = gen_float(c, ast);
      break;

    case TK_STRING:
      ret = gen_string(c, ast);
      break;

    case TK_TUPLE:
      ret = gen_tuple(c, ast);
      break;

    case TK_FFICALL:
      ret = gen_ffi(c, ast);
      break;

    case TK_AMP:
      ret = gen_addressof(c, ast);
      break;

    case TK_IDENTITY:
      ret = gen_identity(c, ast);
      break;

    case TK_DONTCARE:
      ret = GEN_NOVALUE;
      break;

    case TK_COMPILER_INTRINSIC:
      ast_error(ast, "unimplemented compiler intrinsic");
      LLVMBuildUnreachable(c->builder);
      ret = GEN_NOVALUE;
      break;

    default:
      ast_error(ast, "not implemented (codegen unknown)");
      return NULL;
  }

  if(has_scope)
  {
    codegen_popscope(c);

    if(has_source)
      dwarf_finish(&c->dwarf);
  }

  return ret;
}
Example #15
0
int
main(int argc, char **argv)
{
	Elf *e;
	Dwarf_Debug dbg;
	Dwarf_Error de;
	const char *exe, *section;
	char line[1024];
	int fd, i, opt;

	exe = NULL;
	section = NULL;
	while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) !=
	    -1) {
		switch (opt) {
		case 'b':
			/* ignored */
			break;
		case 'C':
			demangle = 1;
			break;
		case 'e':
			exe = optarg;
			break;
		case 'f':
			func = 1;
			break;
		case 'j':
			section = optarg;
			break;
		case 's':
			base = 1;
			break;
		case 'H':
			usage();
		case 'V':
			version();
		default:
			usage();
		}
	}

	argv += optind;
	argc -= optind;

	if (exe == NULL)
		exe = "a.out";

	if ((fd = open(exe, O_RDONLY)) < 0)
		err(EXIT_FAILURE, "%s", exe);

	if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de))
		errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de));

	if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK)
		errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de));

	if (section)
		find_section_base(exe, e, section);
	else
		section_base = 0;

	if (argc > 0)
		for (i = 0; i < argc; i++)
			translate(dbg, argv[i]);
	else
		while (fgets(line, sizeof(line), stdin) != NULL) {
			translate(dbg, line);
			fflush(stdout);
		}

	dwarf_finish(dbg, &de);

	(void) elf_end(e);

	exit(0);
}
Example #16
0
/* get_compiler_info */
int get_compiler_info(void) {
    Dwarf_Unsigned   cu_header_length, abbrev_offset, next_cu_header;
    Dwarf_Half       version, address_size;
    Dwarf_Signed     attrcount, i, language;
    Dwarf_Die        no_die = 0, cu_die;
    Dwarf_Attribute *attrs;
    Dwarf_Half       attrcode;
    Dwarf_Debug      dbg = 0;
    Dwarf_Error      err;
    char *compiler = NULL;
    int fd = -1;

    OUTPUT_VERBOSE((5, "%s", _BLUE("Extracting DWARF info")));

    /* Open the binary */
    if (0 > (fd = open(globals.program_full, O_RDONLY))) {
        OUTPUT(("%s [%s]", _ERROR("opening program binary"),
            globals.program_full));
        return PERFEXPERT_ERROR;
    }

    /* Initialize DWARF library  */
    if (DW_DLV_OK != dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err)) {
        OUTPUT(("%s", _ERROR("failed DWARF initialization")));
        return PERFEXPERT_ERROR;
    }

    /* Find compilation unit header */
    if (DW_DLV_ERROR == dwarf_next_cu_header(dbg, &cu_header_length,
        &version, &abbrev_offset, &address_size, &next_cu_header, &err)) {
        OUTPUT(("%s", _ERROR("reading DWARF CU header")));
        return PERFEXPERT_ERROR;
    }

    /* Expect the CU to have a single sibling, a DIE */
    if (DW_DLV_ERROR == dwarf_siblingof(dbg, no_die, &cu_die, &err)) {
        OUTPUT(("%s", _ERROR("getting sibling of CU")));
        return PERFEXPERT_ERROR;
    }

    /* Find the DIEs attributes */
    if (DW_DLV_OK != dwarf_attrlist(cu_die, &attrs, &attrcount, &err)) {
        OUTPUT(("%s", _ERROR("in dwarf_attlist")));
        return PERFEXPERT_ERROR;
    }

    /* For each attribute... */
    for (i = 0; i < attrcount; ++i) {
        if (DW_DLV_OK != dwarf_whatattr(attrs[i], &attrcode, &err)) {
            OUTPUT(("%s [%s]", _ERROR("in dwarf_whatattr")));
            return PERFEXPERT_ERROR;
        }
        if (DW_AT_producer == attrcode) {
            if (DW_DLV_OK != dwarf_formstring(attrs[i], &compiler, &err)) {
                OUTPUT(("%s [%s]", _ERROR("in dwarf_formstring")));
                return PERFEXPERT_ERROR;
            } else {
                OUTPUT_VERBOSE((5, "   Compiler: %s", _CYAN(compiler)));
            }
        }
        if (DW_AT_language == attrcode) {
            if (DW_DLV_OK != dwarf_formsdata(attrs[i], &language, &err)) {
                OUTPUT(("%s [%s]", _ERROR("in dwarf_formsdata")));
                return PERFEXPERT_ERROR;
            } else {
                OUTPUT_VERBOSE((5, "   Language: %d", language));
            }
        }
    }

    if (PERFEXPERT_SUCCESS != database_write(compiler, language)) {
        OUTPUT(("%s", _ERROR("writing to database")));
        return PERFEXPERT_ERROR;
    }

    /* Finalize DWARF library  */
    if (DW_DLV_OK != dwarf_finish(dbg, &err)) {
        OUTPUT(("%s", _ERROR("failed DWARF finalization")));
        return PERFEXPERT_ERROR;
    }

    close(fd);

    return PERFEXPERT_SUCCESS;
}
Example #17
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() */
int
_dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
		   Dwarf_addr_callback_func cb_func, int *dwerr)
{

    Dwarf_Error err = 0;
    Dwarf_Debug dbg = 0;
    int res = 0;
    int errval = 0;
    int sections_found = 0;

    res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0,
			 /* errarg */ 0, &dbg, &err);
    if (res == DW_DLV_ERROR) {
	int errv = (int) dwarf_errno(err);

	return errv;
    }
    if (res == DW_DLV_NO_ENTRY) {
	return res;
    }

    send_addr_note = cb_func;

    res = handle_debug_info(dbg, &errval);
    switch (res) {
    case DW_DLV_OK:
	++sections_found;
	break;
    case DW_DLV_NO_ENTRY:

	break;
    default:
    case DW_DLV_ERROR:
	dwarf_finish(dbg, &err);
	*dwerr = errval;
	return res;
    }

    res = handle_debug_aranges(dbg, cb_func, &errval);
    switch (res) {
    case DW_DLV_OK:
	++sections_found;
	break;
    case DW_DLV_NO_ENTRY:
	break;
    default:
    case DW_DLV_ERROR:
	dwarf_finish(dbg, &err);
	*dwerr = errval;
	return res;
    }
    res = handle_debug_frame(dbg, cb_func, &errval);
    switch (res) {
    case DW_DLV_OK:
	++sections_found;
	break;
    case DW_DLV_NO_ENTRY:
	break;
    default:
    case DW_DLV_ERROR:
	dwarf_finish(dbg, &err);
	*dwerr = errval;
	return res;
    }

    res = handle_debug_loc();	/* does nothing */
    switch (res) {
    case DW_DLV_OK:
	++sections_found;
	break;
    case DW_DLV_NO_ENTRY:
	break;
    default:
    case DW_DLV_ERROR:
	/* IMPOSSIBLE : handle_debug_loc cannot return this */
	dwarf_finish(dbg, &err);
	*dwerr = errval;
	return res;
    }



    *dwerr = 0;
    res = dwarf_finish(dbg, &err);
    if (res == DW_DLV_ERROR) {
	*dwerr = (int) dwarf_errno(err);
	return DW_DLV_ERROR;
    }
    if (sections_found == 0) {
	return DW_DLV_NO_ENTRY;
    }
    return DW_DLV_OK;

}