/*
    The alternate dwarf setup call for consumers
*/
int
dwarf_elf_init(dwarf_elf_handle elf_file_pointer,
	       Dwarf_Unsigned access,
	       Dwarf_Handler errhand,
	       Dwarf_Ptr errarg,
	       Dwarf_Debug * ret_dbg, Dwarf_Error * error)
{
    Dwarf_Debug dbg;
    int res;

    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;

    if (access != DW_DLC_READ) {
	DWARF_DBG_ERROR(dbg, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
    }
    dbg->de_access = access;

    dbg->de_elf_must_close = 0;
    if ((res = _dwarf_setup(dbg, elf_file_pointer, error)) != DW_DLV_OK) {
	free(dbg);
	return (res);
    }

    /* this call cannot fail: allocates nothing, releases nothing */
    _dwarf_setup_debug(dbg);

    *ret_dbg = dbg;
    return (DW_DLV_OK);
}
/*
    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) {
        /*  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.  */
        int freeresult = _dwarf_free_all_of_one_debug(dbg);
        if (freeresult == DW_DLV_ERROR) {
            DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
        }
        dwarf_malloc_check_complete("After Final free");
        return setup_result;
    }

    dwarf_harmless_init(&dbg->de_harmless_errors,
        DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE);

    /* This call cannot fail: allocates nothing, releases nothing */
    _dwarf_setup_debug(dbg);


    *ret_dbg = dbg;
    return DW_DLV_OK;    
}
/*
    The basic dwarf initializer function for consumers.
    Return NULL on error.
*/
int
dwarf_init(int fd,
	   Dwarf_Unsigned access,
	   Dwarf_Handler errhand,
	   Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error)
{
    Dwarf_Debug dbg;
    struct stat fstat_buf;
    dwarf_elf_handle elf;
    int res;
#ifdef __SGI_FAST_LIBELF
    enum elf_sgi_error_type sres;
#else
    Elf_Cmd what_kind_of_elf_read;
#endif

    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;

    if (fstat(fd, &fstat_buf) != 0) {
	DWARF_DBG_ERROR(dbg, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR);
    }
    if (!S_ISREG(fstat_buf.st_mode)) {
	DWARF_DBG_ERROR(dbg, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR);
    }

    if (access != DW_DLC_READ) {
	DWARF_DBG_ERROR(dbg, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
    }
    dbg->de_access = access;

#ifdef __SGI_FAST_LIBELF
    elf = elf_sgi_new();
    if (elf == NULL) {
	DWARF_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_ERROR);
    }

    sres = elf_sgi_begin_fd(elf, fd, 0);
    if (sres != ELF_SGI_ERROR_OK) {
	DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
			DW_DLV_ERROR);
    }
#else
    elf_version(EV_CURRENT);
    /* changed to mmap request per bug 281217. 6/95 */
#ifdef HAVE_ELF_C_READ_MMAP
    /* ELF_C_READ_MMAP is an SGI IRIX specific enum value from IRIX
       libelf.h meaning read but use mmap */
    what_kind_of_elf_read = ELF_C_READ_MMAP;
#else
    /* ELF_C_READ is a portable value */
    what_kind_of_elf_read  = ELF_C_READ;
#endif

    if ((elf = elf_begin(fd, what_kind_of_elf_read, 0)) == NULL) {
	DWARF_DBG_ERROR(dbg, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR);
    }
#endif /* !defined(__SGI_FAST_LIBELF) */

    dbg->de_elf_must_close = 1;
    if ((res = _dwarf_setup(dbg, elf, error)) != DW_DLV_OK) {
	free(dbg);
	return (res);
    }

    /* call cannot fail: no malloc or free involved */
    _dwarf_setup_debug(dbg);

    *ret_dbg = dbg;
    return (DW_DLV_OK);
}