/*
	Return DW_DLV_OK, ERROR, or NO_ENTRY.
*/
static int
handle_debug_info(Dwarf_Debug dbg, int *errval)
{
    Dwarf_Unsigned nxtoff = 1;
    Dwarf_Unsigned hdr_length;
    Dwarf_Half version_stamp;
    Dwarf_Unsigned abbrev_offset;
    Dwarf_Half addr_size;
    Dwarf_Error err;
    int terminate_now = 0;
    int res = 0;
    Dwarf_Die sibdie;
    int sibres;
    int nres = DW_DLV_OK;


    for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
				     &abbrev_offset,
				     &addr_size, &nxtoff, &err);
	 terminate_now == 0 && nres == DW_DLV_OK;
	 nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
				     &abbrev_offset,
				     &addr_size, &nxtoff, &err)
	) {

	Dwarf_Die curdie = 0;

	/* try to get the compilation unit die */
	sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err);
	if (sibres == DW_DLV_OK) {
	    res = do_this_die_and_dealloc(dbg, sibdie, errval);
	    switch (res) {
	    case DW_DLV_OK:
		break;
	    case DW_DLV_NO_ENTRY:
		break;
	    default:
	    case DW_DLV_ERROR:
		return DW_DLV_ERROR;
	    }
	} else if (sibres == DW_DLV_ERROR) {
	    *errval = (int) dwarf_errno(err);
	    return DW_DLV_ERROR;
	} else {
	    /* NO ENTRY! */
	    /* impossible? */
	}

    }
    if (nres == DW_DLV_ERROR) {
	int localerr = (int) dwarf_errno(err);

	*errval = localerr;
	return DW_DLV_ERROR;
    }
    return DW_DLV_OK;
}
Exemple #2
0
int
_dwarf_get_string_from_tied(Dwarf_Debug dbg,
    Dwarf_Unsigned offset,
    char **return_str,
    Dwarf_Error*error)
{
    Dwarf_Debug tieddbg = 0;
    Dwarf_Small *secend = 0;
    Dwarf_Small *secbegin = 0;
    Dwarf_Small *strbegin = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Error localerror = 0;

    /* Attach errors to dbg, not tieddbg. */
    tieddbg = dbg->de_tied_data.td_tied_object;
    if (!tieddbg) {
        _dwarf_error(dbg, error, DW_DLE_NO_TIED_FILE_AVAILABLE);
        return  DW_DLV_ERROR;
    }
    /* The 'offset' into .debug_str is set. */
    res = _dwarf_load_section(tieddbg, &tieddbg->de_debug_str,&localerror);
    if (res == DW_DLV_ERROR) {
        Dwarf_Unsigned lerrno = dwarf_errno(localerror);
        dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR);
        _dwarf_error(dbg,error,lerrno);
        return res;
    } else if (res == DW_DLV_NO_ENTRY) {
        return res;
    }
    if (offset >= tieddbg->de_debug_str.dss_size) {
        /*  Badly damaged DWARF here. */
        _dwarf_error(dbg, error,  DW_DLE_NO_TIED_STRING_AVAILABLE);
        return (DW_DLV_ERROR);
    }
    secbegin = tieddbg->de_debug_str.dss_data;
    strbegin= tieddbg->de_debug_str.dss_data + offset;
    secend = tieddbg->de_debug_str.dss_data +
        tieddbg->de_debug_str.dss_size;

    /*  Ensure the offset lies within the .debug_str */
    if (offset >= tieddbg->de_debug_str.dss_size) {
        _dwarf_error(dbg, error,  DW_DLE_NO_TIED_STRING_AVAILABLE);
        return (DW_DLV_ERROR);
    }
    res= _dwarf_check_string_valid(tieddbg,secbegin,strbegin, secend,
        &localerror);
    if (res == DW_DLV_ERROR) {
        Dwarf_Unsigned lerrno = dwarf_errno(localerror);
        dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR);
        _dwarf_error(dbg,error,lerrno);
        return res;
    } else if (res == DW_DLV_NO_ENTRY) {
        return res;
    }
    *return_str = (char *) (tieddbg->de_debug_str.dss_data + offset);
    return DW_DLV_OK;
}
Exemple #3
0
/*  Often errs and errt point to the same Dwarf_Error,
    So exercise care.
    All the arguments MUST be non-null.*/
void
_dwarf_error_mv_s_to_t(Dwarf_Debug dbgs,Dwarf_Error *errs,
    Dwarf_Debug dbgt,Dwarf_Error *errt)
{
    if (!errt || !errs) {
        return;
    }
    if (!dbgs || !dbgt) {
        return;
    }
    if(dbgs == dbgt) {
        if(errs != errt) {
            Dwarf_Error ers = *errs;
            *errs = 0;
            *errt = ers;
        }
    } else {
        /*  Do not stomp on the system errno
            variable if there is one! */
        int mydw_errno = dwarf_errno(*errs);

        dwarf_dealloc(dbgs,*errs, DW_DLA_ERROR);
        *errs = 0;
        _dwarf_error(dbgt,errt, mydw_errno);
    }
}
static int
handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
		  Dwarf_addr_callback_func cb_func, int *errval)
{
    int retval = DW_DLV_OK;
    int res;
    Dwarf_Error err;
    Dwarf_Addr *addrlist;
    Dwarf_Off *offsetlist;
    Dwarf_Unsigned count;
    Dwarf_Unsigned i;

    res =
	_dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist,
				    &count, &err);
    if (res == DW_DLV_OK) {
	for (i = 0; i < count; i++) {
	    cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]);

	}
	dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
	dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
    } else if (res == DW_DLV_NO_ENTRY) {
	retval = res;
    } else {
	*errval = (int) dwarf_errno(err);
	retval = DW_DLV_ERROR;
    }
    return retval;
}
static int
handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
		     int *errval)
{
    int retval = DW_DLV_OK;
    Dwarf_Error err;
    Dwarf_Addr *aranges;
    Dwarf_Signed count;
    int indx;
    Dwarf_Off *offsets;

    retval =
	_dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count,
					&err);
    if (retval == DW_DLV_OK) {
	if (count == 0) {
	    retval = DW_DLV_NO_ENTRY;
	} else {
	    for (indx = 0; indx < count; indx++) {
		cb_func(DW_SECTION_ARANGES, offsets[indx],
			aranges[indx]);
	    }
	}
	dwarf_dealloc(dbg, aranges, DW_DLA_ADDR);
	dwarf_dealloc(dbg, offsets, DW_DLA_ADDR);
    } else if (retval == DW_DLV_NO_ENTRY) {
	;			/* do nothing */
    } else {
	*errval = (int) dwarf_errno(err);
	retval = DW_DLV_ERROR;
    }
    return retval;
}
int
main (int argc, char *argv[])
{
  assert (argc >= 3);
  const char *name = argv[1];
  ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
  bool new_style = argc > 3;

  int fd = open (name, O_RDONLY);
  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);

  Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);

  for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0;
       (off = dwarf_getmacros (cudie, mac, dbg, off)); )
    if (off == -1)
      {
	puts (dwarf_errmsg (dwarf_errno ()));
	break;
      }

  dwarf_end (dbg);

  return 0;
}
static void
include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token)
{
  while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
    if (token == -1)
      {
	puts (dwarf_errmsg (dwarf_errno ()));
	break;
      }
}
Exemple #8
0
static int
reloc_incomplete(Dwarf_Error err)
{
    int e = dwarf_errno(err);
    if( e == DW_DLE_RELOC_MISMATCH_INDEX       ||
        e == DW_DLE_RELOC_MISMATCH_RELOC_INDEX  ||
        e == DW_DLE_RELOC_MISMATCH_STRTAB_INDEX ||
        e == DW_DLE_RELOC_SECTION_MISMATCH      ||
        e == DW_DLE_RELOC_SECTION_MISSING_INDEX  ||
        e == DW_DLE_RELOC_SECTION_LENGTH_ODD     ||
        e == DW_DLE_RELOC_SECTION_PTR_NULL        ||
        e == DW_DLE_RELOC_SECTION_MALLOC_FAIL      ||
        e == DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD  ) {
        return 1;
    }
    return 0;
}
Exemple #9
0
void
_dwarf_error_mv_s_to_t(Dwarf_Debug dbgs,Dwarf_Error *errs,
    Dwarf_Debug dbgt,Dwarf_Error *errt)
{
    if(dbgs == dbgt) {
        if(errs != errt) {
            Dwarf_Error ers = *errs;
            *errs = 0;
            *errt = ers;
        }
    } else {
        int errno = dwarf_errno(*errs);
        dwarf_dealloc(dbgs,*errs, DW_DLA_ERROR);
        *errs = 0;
        _dwarf_error(dbgt,errt, errno);
    }
}
Exemple #10
0
void
deal_with_name_offset_err(Dwarf_Debug dbg,
    char *err_loc,
    char *name, Dwarf_Unsigned die_off,
    int nres, Dwarf_Error err)
{
    if (nres == DW_DLV_ERROR) {
        Dwarf_Unsigned myerr = dwarf_errno(err);

        if (myerr == DW_DLE_OFFSET_BAD) {
            printf("Error: bad offset %s, %s %" DW_PR_DUu
                " (0x%08" DW_PR_DUx ")\n",
                err_loc,
                name,
                die_off,
                die_off);
        }
        print_error(dbg, err_loc, nres, err);
    }
}
Exemple #11
0
static void __dead2
_dwarf_err(const char *fn, unsigned ln, const char *func, int ex, int error,
    const char *fmt, ...)
{
	va_list ap;

	printf("%s:%u: %s: ", fn, ln, func);

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);

	/*
	 * Bizarrely, this clears the global DWARF error, breaking
	 * dwarf_errmsg(-1):
	 */
	if (error == -1)
		error = dwarf_errno();
	printf(": %s(%d)\n", dwarf_errmsg(error), error);
	exit(ex);
}
Exemple #12
0
static int
mac (Dwarf_Macro *macro, void *dbg)
{
  static int level = 0;

  unsigned int opcode;
  dwarf_macro_opcode (macro, &opcode);
  switch (opcode)
    {
    case DW_MACRO_GNU_transparent_include:
      {
	Dwarf_Attribute at;
	int r = dwarf_macro_param (macro, 0, &at);
	assert (r == 0);

	Dwarf_Word w;
	r = dwarf_formudata (&at, &w);
	assert (r == 0);

	printf ("%*sinclude %#" PRIx64 "\n", level, "", w);
	++level;
	include (dbg, w, DWARF_GETMACROS_START);
	--level;
	printf ("%*s/include\n", level, "");
	break;
      }

    case DW_MACRO_GNU_start_file:
      {
	Dwarf_Files *files;
	size_t nfiles;
	if (dwarf_macro_getsrcfiles (dbg, macro, &files, &nfiles) < 0)
	  printf ("dwarf_macro_getsrcfiles: %s\n",
		  dwarf_errmsg (dwarf_errno ()));

	Dwarf_Word w = 0;
	dwarf_macro_param2 (macro, &w, NULL);

	const char *name = dwarf_filesrc (files, (size_t) w, NULL, NULL);
	printf ("%*sfile %s\n", level, "", name);
	++level;
	break;
      }

    case DW_MACRO_GNU_end_file:
      {
	--level;
	printf ("%*s/file\n", level, "");
	break;
      }

    case DW_MACINFO_define:
    case DW_MACRO_GNU_define_indirect:
      {
	const char *value;
	dwarf_macro_param2 (macro, NULL, &value);
	printf ("%*s%s\n", level, "", value);
	break;
      }

    case DW_MACINFO_undef:
    case DW_MACRO_GNU_undef_indirect:
      break;

    default:
      {
	size_t paramcnt;
	dwarf_macro_getparamcnt (macro, &paramcnt);
	printf ("%*sopcode %u with %zd arguments\n",
		level, "", opcode, paramcnt);
	break;
      }
    }

  return DWARF_CB_ABORT;
}
/*
  Return DW_DLV_OK, or DW_DLV_ERROR

  Handle the addrs in a single die.
*/
static int
process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval)
{
    Dwarf_Error err;
    Dwarf_Half i;
    Dwarf_Half newattrnum;
    int res;
    int tres;
    Dwarf_Half ltag;

    Dwarf_Off doff;
    int doffres = dwarf_dieoffset(newdie, &doff, &err);

    if (doffres != DW_DLV_OK) {
	if (doffres == DW_DLV_ERROR) {
	    *errval = (int) dwarf_errno(err);
	}
	return doffres;
    }
    tres = dwarf_tag(newdie, &ltag, &err);
    if (tres != DW_DLV_OK) {
	return tres;
    }
    if (DW_TAG_compile_unit == ltag) {
	/* because of the way the dwarf_line code works, we ** do lines 
	   only per compile unit. ** This may turn out to be wrong if
	   we have lines ** left unconnected to a CU. ** of course such 
	   lines will not, at present, be ** used by gnome ** This is
	   not ideal as coded due to the dwarf_line.c issue. */
	int lres;

	lres = handle_debug_line(dbg, newdie, send_addr_note, errval);
	if (lres == DW_DLV_ERROR) {
	    return lres;
	}
    }

    for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) {
	int resattr;
	Dwarf_Bool hasattr;

	newattrnum = might_have_addr[i];
	err = 0;
	resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
	if (DW_DLV_OK == resattr) {
	    if (hasattr) {
		res = handle_attr_addr(dbg, newdie, newattrnum, &err);
		if (res != DW_DLV_OK) {
		    *errval = (int) dwarf_errno(err);
		    return DW_DLV_ERROR;
		}
	    }
	} else {
	    if (resattr == DW_DLV_ERROR) {
		*errval = (int) dwarf_errno(err);
		return resattr;
	    }
	}
    }
    for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) {
	int resattr;
	Dwarf_Bool hasattr;

	newattrnum = might_have_locdesc[i];
	err = 0;
	resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
	if (DW_DLV_OK == resattr) {
	    if (hasattr) {
		res =
		    handle_attr_locdesc(dbg, newdie, newattrnum, &err);
		if (res != DW_DLV_OK) {
		    *errval = (int) dwarf_errno(err);
		    return DW_DLV_ERROR;
		}
	    }
	} else {
	    if (resattr == DW_DLV_ERROR) {
		*errval = (int) dwarf_errno(err);
		return resattr;
	    }
	}
    }

    return DW_DLV_OK;
}
/*
	Handle siblings as a list,
	Do children by recursing.
	Effectively this is walking the tree preorder.

	This dealloc's any die passed to it, so the
	caller should not do that dealloc.
	It seems more logical to have the one causing
	the alloc to do the dealloc, but that way this
	routine became a mess.

*/
static int
do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval)
{

    Dwarf_Die prevdie = 0;
    Dwarf_Die newdie = die;
    Dwarf_Error err = 0;
    int res = 0;
    int sibres = DW_DLV_OK;
    int tres = DW_DLV_OK;
    Dwarf_Die sibdie;

    while (sibres == DW_DLV_OK) {
	Dwarf_Die ch_die;


	res = process_this_die_attrs(dbg, newdie, errval);
	switch (res) {
	case DW_DLV_OK:
	    break;
	case DW_DLV_NO_ENTRY:
	    break;
	default:
	case DW_DLV_ERROR:
	    if (prevdie) {
		dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
		prevdie = 0;
	    }
	    return DW_DLV_ERROR;
	}

	tres = dwarf_child(newdie, &ch_die, &err);

	if (tres == DW_DLV_OK) {
	    res = do_this_die_and_dealloc(dbg, ch_die, errval);
	    switch (res) {
	    case DW_DLV_OK:
		break;
	    case DW_DLV_NO_ENTRY:
		break;
	    default:
	    case DW_DLV_ERROR:
		if (prevdie) {
		    dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
		    prevdie = 0;
		}
		return DW_DLV_ERROR;
	    }
	} else if (tres == DW_DLV_ERROR) {
	    /* An error! */
	    *errval = (int) dwarf_errno(err);
	    if (prevdie) {
		dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
		prevdie = 0;
	    }
	    dwarf_dealloc(dbg, err, DW_DLA_ERROR);
	    return DW_DLV_ERROR;
	}			/* else was NO ENTRY */
	prevdie = newdie;
	sibdie = 0;
	sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err);
	if (prevdie) {
	    dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
	    prevdie = 0;
	}
	newdie = sibdie;

    }
    if (sibres == DW_DLV_NO_ENTRY) {
	return DW_DLV_OK;
    }
    /* error. */
    *errval = (int) dwarf_errno(err);
    if (prevdie) {
	dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
	prevdie = 0;
    }
    dwarf_dealloc(dbg, err, DW_DLA_ERROR);
    return DW_DLV_ERROR;

}
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;

}
Exemple #16
0
/*
    Use a Dwarf_Obj_Access_Interface to kick things off. All other
    init routines eventually use this one.
    The returned Dwarf_Debug contains a copy of *obj
    the callers copy of *obj may be freed whenever the caller
    wishes.
*/
int
dwarf_object_init(Dwarf_Obj_Access_Interface* obj, Dwarf_Handler errhand,
    Dwarf_Ptr errarg, Dwarf_Debug* ret_dbg,
    Dwarf_Error* error)
{
    Dwarf_Debug dbg = 0;
    int setup_result = DW_DLV_OK;

    dbg = _dwarf_get_debug();
    if (dbg == NULL) {
        DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
    }
    dbg->de_errhand = errhand;
    dbg->de_errarg = errarg;
    dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
    dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
#ifdef HAVE_OLD_FRAME_CFA_COL
    /*  DW_FRAME_CFA_COL is really only suitable for old libdwarf frame
        interfaces and its value of 0 there is only usable where
        (as in MIPS) register 0 has no value other than 0 so
        we can use the frame table column 0 for the CFA value
        (and rely on client software to know when 'register 0'
        is the cfa and when to just use a value 0 for register 0).
    */
    dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL;
#else
    dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3;
#endif
    dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL;
    dbg->de_frame_undefined_value_number  = DW_FRAME_UNDEFINED_VAL;

    dbg->de_obj_file = obj;

    setup_result = _dwarf_setup(dbg, error);
    if (setup_result == DW_DLV_OK) {
        int fission_result = load_debugfission_tables(dbg,error);
        /*  In most cases we get
            setup_result == DW_DLV_NO_ENTRY here
            as having debugfission (.dwp objects)
            is fairly rare. */
        if (fission_result == DW_DLV_ERROR) {
            /*  Something is very wrong. */
            setup_result = fission_result;
        }
    }
    if (setup_result != DW_DLV_OK) {
        int freeresult = 0;
        /* We cannot use any _dwarf_setup()
            error here as
            we are freeing dbg, making that error (setup
            as part of dbg) stale.
            Hence we have to make a new error without a dbg.
            But error might be NULL and the init call
            error-handler function might be set.
        */
        int myerr = 0;
        if ( (setup_result == DW_DLV_ERROR) && error ) {
            /*  Preserve our _dwarf_setup error number, but
                this does not apply if error NULL. */
            myerr = dwarf_errno(*error);
            /*  deallocate the soon-stale error pointer. */
            dwarf_dealloc(dbg,*error,DW_DLA_ERROR);
            *error = 0;
        }
        /*  The status we want to return  here is of _dwarf_setup,
            not of the  _dwarf_free_all_of_one_debug(dbg) call.
            So use a local status variable for the free.  */
        freeresult = _dwarf_free_all_of_one_debug(dbg);
        dbg = 0;
        /* DW_DLV_NO_ENTRY not possible in freeresult */
        if (freeresult == DW_DLV_ERROR) {
            /*  Use the _dwarf_setup error number.
                If error is NULL the following will issue
                a message on stderr and abort(), as without
                dbg there is no error-handler function.
                */
            _dwarf_error(NULL,error,DW_DLE_DBG_ALLOC);
            return DW_DLV_ERROR;
        }
        if (setup_result == DW_DLV_ERROR) {
            /*  Use the _dwarf_setup error number.
                If error is NULL the following will issue
                a message on stderr and abort(), as without
                dbg there is no error-handler function.
                */
            _dwarf_error(NULL,error,myerr);
        }
        return setup_result;
    }
    dwarf_harmless_init(&dbg->de_harmless_errors,
        DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE);
    *ret_dbg = dbg;
    return DW_DLV_OK;
}
Exemple #17
0
int
main(int argc, char **argv)
{
	Dwarf_Off off, lastoff;
	Dwarf *dw;

	size_t hdr_size;
	int cufd, error;

	argv0 = argv[0];
	if (argc < 3)
		usage();

	structname = argv[1];
	binary = argv[2];

	elf_version(EV_CURRENT);

	cufd = open(binary, O_RDONLY);
	if (cufd == -1)
		err(EX_USAGE, "open");

	dw = dwarf_begin(cufd, DWARF_C_READ);
	if (dw == NULL) {
		error = dwarf_errno();
		if (error == DWARF_E_NO_REGFILE)
			errx(EX_USAGE, "%s: Not a regular file", binary);
		dwarf_err_errno(EX_DATAERR, error, "dwarf_begin");
	}

	get_elf_pointer_size(dw);

	/* XXX worry about .debug_types sections later. */

	lastoff = off = 0;
	while (dwarf_nextcu(dw, off, &off, &hdr_size, NULL, NULL, NULL) == 0) {
		Dwarf_Die cu_die, die;
		int x;

		if (dwarf_offdie(dw, lastoff + hdr_size, &cu_die) == NULL)
			continue;
		lastoff = off;

		/*
		 * A CU may be empty because e.g. an empty (or fully #if0'd)
		 * file is compiled.
		 */
		if (dwarf_child(&cu_die, &die))
			continue;

		/* Loop through all DIEs in the CU. */
		do {
			if (isstruct(dwarf_tag(&die)) &&
			    dwarf_haschildren(&die) &&
			    dwarf_diename(&die) &&
			    strcmp(dwarf_diename(&die), structname) == 0) {
				structprobe(dw, &die);
				goto out;
			}

		} while ((x = dwarf_siblingof(&die, &die)) == 0);
		if (x == -1)
			dwarf_err(EX_DATAERR, "dwarf_siblingof");
	}

out:
	if (dwarf_end(dw))
		dwarf_err(EX_SOFTWARE, "dwarf_end");

	return (EX_OK);
}
/*  Here a DW_DLV_NO_ENTRY return means the macro operator
    is not a def/undef operator. */
int
dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context,
    Dwarf_Unsigned op_number,
    Dwarf_Unsigned * line_number,
    Dwarf_Unsigned * index,
    Dwarf_Unsigned * offset,
    Dwarf_Half     * forms_count,
    const char     ** macro_string,
    Dwarf_Error *error)
{
    Dwarf_Debug dbg = 0;
    Dwarf_Small *mdata = 0;
    int res = 0;
    Dwarf_Small *startptr = 0;
    Dwarf_Small *endptr = 0;
    Dwarf_Half lformscount = 0;
    struct Dwarf_Macro_Operator_s *curop = 0;
    unsigned macop = 0;

    if (!macro_context || macro_context->mc_sentinel != 0xada) {
        if(macro_context) {
            dbg = macro_context->mc_dbg;
        }
        _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
        return DW_DLV_ERROR;
    }
    dbg = macro_context->mc_dbg;
    if (op_number >= macro_context->mc_macro_ops_count) {
        _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
        return DW_DLV_ERROR;
    }
    curop = macro_context->mc_ops + op_number;
    macop = curop->mo_opcode;
    startptr = macro_context->mc_macro_header;
    endptr = startptr + macro_context->mc_total_length;
    mdata = curop->mo_data;
    lformscount = curop->mo_form->mf_formcount;
    if (lformscount != 2) {
        /*_dwarf_error(dbg, error,DW_DLE_MACRO_OPCODE_FORM_BAD);*/
        return DW_DLV_NO_ENTRY;
    }
    switch(macop){
    case DW_MACRO_define:
    case DW_MACRO_undef: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        const char * content = 0;

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;
        content = (const char *)mdata;
        res = _dwarf_check_string_valid(dbg,
            startptr,mdata, endptr, error);
        if(res != DW_DLV_OK) {
            return res;
        }
        *line_number = linenum;
        *index = 0;
        *offset = 0;
        *forms_count = lformscount;
        *macro_string = content;
        }
        return DW_DLV_OK;
    case DW_MACRO_define_strp:
    case DW_MACRO_undef_strp: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned stringoffset = 0;
        Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];
        char * localstr = 0;


        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        READ_UNALIGNED(dbg,stringoffset,Dwarf_Unsigned,
            mdata,macro_context->mc_offset_size);
        mdata += macro_context->mc_offset_size;

        res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
            form1,
            stringoffset,
            &localstr,
            error);
        *index = 0;
        *line_number = linenum;
        *offset = stringoffset;
        *forms_count = lformscount;
        if (res == DW_DLV_ERROR) {
            return res;
            *macro_string = "<Error: getting local .debug_str>";
        } else if (res == DW_DLV_NO_ENTRY) {
            *macro_string = "<Error: NO_ENTRY on .debug_string (strp)>";
        } else {
            *macro_string = (const char *)localstr;
        }
        }
        return DW_DLV_OK;
    case DW_MACRO_define_strx:
    case DW_MACRO_undef_strx: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned stringindex = 0;
        Dwarf_Unsigned offsettostr= 0;
        int res = 0;
        Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        *line_number = linenum;
        stringindex = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        /* leave mdata uchanged for call below */


        *index = stringindex;
        *forms_count = lformscount;

        /* FIXME */
        /* Redoes the index-getting. Gets offset. */
        res = _dwarf_extract_string_offset_via_str_offsets(dbg,
            mdata,
            DW_AT_macros, /*arbitrary, unused by called routine. */
            form1,
            macro_context->mc_cu_context,
            &offsettostr,
            error);
        if (res  == DW_DLV_ERROR) {
            return res;
        }
        if (res == DW_DLV_OK) {
            *index = stringindex;
            *offset = offsettostr;
            char *localstr = 0;
            res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
                form1,
                offsettostr,
                &localstr,
                error);
            if(res == DW_DLV_ERROR) {
                return res;
            } else if (res == DW_DLV_NO_ENTRY){
                *macro_string = "<:No string available>";
            } else {
                *macro_string = (const char *)localstr;
                /* All is ok. */
            }
        } else {
            *index = stringindex;
            *offset = 0;
            *macro_string = "<.debug_str_offsets not available>";
        }
        }
        return DW_DLV_OK;
    case DW_MACRO_define_sup:
    case DW_MACRO_undef_sup: {
        Dwarf_Unsigned linenum = 0;
        Dwarf_Word uleblen = 0;
        Dwarf_Unsigned supoffset = 0;
        char *localstring = 0;
        int res = 0;

        linenum = _dwarf_decode_u_leb128(mdata,
            &uleblen);
        mdata += uleblen;

        READ_UNALIGNED(dbg,supoffset,Dwarf_Unsigned,
            mdata,macro_context->mc_offset_size);
        mdata += macro_context->mc_offset_size;
        *line_number = linenum;
        *index = 0;
        *offset = supoffset;
        *forms_count = lformscount;
        res = _dwarf_get_string_from_tied(dbg, supoffset,
            &localstring, error);
        if (res != DW_DLV_OK) {
            if (res == DW_DLV_ERROR) {
                if(dwarf_errno(*error) == DW_DLE_NO_TIED_FILE_AVAILABLE) {
                    *macro_string =
                        (char *)"<DW_FORM_str_sup-no-tied_file>";
                } else {
                    *macro_string =
                        (char *)"<Error: DW_FORM_str_sup-got-error>";
                }
                dwarf_dealloc(dbg,*error,DW_DLA_ERROR);
            } else {
                *macro_string = "<DW_FORM_str_sup-no-entry>";
            }
        } else {
            *macro_string = (const char *)localstring;
        }
        return DW_DLV_OK;
        }
    }
    return DW_DLV_NO_ENTRY;
}
Exemple #19
0
/* Contrary to pre-2005 documentation,
   The string pointer returned thru return_str must
   never have dwarf_dealloc() applied to it.
   Documentation fixed July 2005.
*/
int
dwarf_formstring(Dwarf_Attribute attr,
    char **return_str, Dwarf_Error * error)
{
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Debug dbg = 0;
    Dwarf_Unsigned offset = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Small *secdataptr = 0;
    Dwarf_Small *secend = 0;
    Dwarf_Unsigned secdatalen = 0;
    Dwarf_Small *infoptr = attr->ar_debug_ptr;
    res  = get_attr_dbg(&dbg,&cu_context,attr,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    if (cu_context->cc_is_info) {
        secdataptr = (Dwarf_Small *)dbg->de_debug_info.dss_data;
        secdatalen = dbg->de_debug_info.dss_size;
    } else {
        secdataptr = (Dwarf_Small *)dbg->de_debug_types.dss_data;
        secdatalen = dbg->de_debug_types.dss_size;
    }
    switch(attr->ar_attribute_form) {
    case DW_FORM_string: {
        Dwarf_Small *begin = attr->ar_debug_ptr;
        Dwarf_Small *contextend = secdataptr +
            cu_context->cc_debug_offset +
            cu_context->cc_length +
            cu_context->cc_length_size +
            cu_context->cc_extension_size;
        secend = secdataptr + secdatalen;
        if (contextend < secend) {
            secend = contextend;
        }

        res= _dwarf_check_string_valid(dbg,secdataptr,begin, secend,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        *return_str = (char *) (begin);
        return DW_DLV_OK;
    }
    case DW_FORM_GNU_strp_alt:
    case DW_FORM_strp_sup:  {
        Dwarf_Error alterr = 0;
        /*  See dwarfstd.org issue 120604.1
            This is the offset in the .debug_str section
            of another object file.
            The 'tied' file notion should apply.
            It is not clear whether both a supplementary
            and a split object might be needed at the same time
            (hence two 'tied' files simultaneously). */
        Dwarf_Off soffset = 0;

        res = dwarf_global_formref(attr, &soffset,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        res = _dwarf_get_string_from_tied(dbg, soffset,
            return_str, &alterr);
        if (res == DW_DLV_ERROR) {
            if (dwarf_errno(alterr) == DW_DLE_NO_TIED_FILE_AVAILABLE) {
                dwarf_dealloc(dbg,alterr,DW_DLA_ERROR);
                if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) {
                    *return_str =
                        (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>";
                } else {
                    *return_str =
                        (char *)"<DW_FORM_strp_sup-no-tied-file>";
                }
                return DW_DLV_OK;
            }
            if (error) {
                *error = alterr;
            }
            return res;
        }
        if (res == DW_DLV_NO_ENTRY) {
            if( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) {
                *return_str =
                    (char *)"<DW_FORM_GNU_strp_alt-no-tied-file>";
            }else {
                *return_str =
                    (char *)"<DW_FORM_strp_sup-no-tied-file>";
            }
        }
        return res;
    }
    case DW_FORM_GNU_str_index:
    case DW_FORM_strx: {
        Dwarf_Unsigned offsettostr= 0;
        res = _dwarf_extract_string_offset_via_str_offsets(dbg,
            infoptr,
            attr->ar_attribute,
            attr->ar_attribute_form,
            cu_context,
            &offsettostr,
            error);
        if (res != DW_DLV_OK) {
            return res;
        }
        offset = offsettostr;
        break;
    }
    case DW_FORM_strp:
    case DW_FORM_line_strp:{
        READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
            infoptr,
            cu_context->cc_length_size);
        break;
    }
    default:
        _dwarf_error(dbg, error, DW_DLE_STRING_FORM_IMPROPER);
        return DW_DLV_ERROR;
    }
    /*  Now we have offset so read the string from
        debug_str or debug_line_str. */
    res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
        attr->ar_attribute_form,
        offset,
        return_str,
        error);
    return res;
}