tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_init_finish.c
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_init_finish.c	Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,822 @@
+/*
+
+  Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc.  All Rights Reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2.1 of the GNU Lesser General Public License 
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it would be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+  Further, this software is distributed without any warranty that it is
+  free of the rightful claim of any third person regarding infringement 
+  or the like.  Any license provided herein, whether implied or 
+  otherwise, applies only to this software file.  Patent licenses, if
+  any, provided herein do not apply to combinations of this program with 
+  other software, or any other product whatsoever.  
+
+  You should have received a copy of the GNU Lesser General Public 
+  License along with this program; if not, write the Free Software 
+  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+  USA.
+
+  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
+  Mountain View, CA 94043, or:
+
+  http://www.sgi.com
+
+  For further information regarding this notice, see:
+
+  http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) )
+#endif
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef __SGI_FAST_LIBELF
+#include <libelf_sgi.h>
+#else
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "dwarf_incl.h"
+#include "malloc_check.h"
+
+#define DWARF_DBG_ERROR(dbg,errval,retval) \
+     _dwarf_error(dbg, error, errval); return(retval);
+
+#define FALSE	0
+#define TRUE	1
+
+#ifdef __SGI_FAST_LIBELF
+#else
+#ifdef HAVE_ELF64_GETEHDR
+extern Elf64_Ehdr *elf64_getehdr(Elf *);
+#endif
+#ifdef HAVE_ELF64_GETSHDR
+extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
+#endif
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+
+/* This static is copied to the dbg on dbg init
+   so that the static need not be referenced at
+   run time, preserving better locality of
+   reference.
+   Value is 0 means do the string check.
+   Value non-zero means do not do the check.
+*/
+static Dwarf_Small _dwarf_assume_string_bad;
+
+
+int
+dwarf_set_stringcheck(int newval)
+{
+    int oldval = _dwarf_assume_string_bad;
+
+    _dwarf_assume_string_bad = newval;
+    return oldval;
+}
+
+#ifdef __SGI_FAST_LIBELF
+/*
+	This function translates an elf_sgi error code into a libdwarf
+	code.
+ */
+static int
+_dwarf_error_code_from_elf_sgi_error_code(enum elf_sgi_error_type val)
+{
+    switch (val) {
+    case ELF_SGI_ERROR_OK:
+	return DW_DLE_NE;
+    case ELF_SGI_ERROR_BAD_ALLOC:
+	return DW_DLE_MAF;
+    case ELF_SGI_ERROR_FORMAT:
+	return DW_DLE_MDE;
+    case ELF_SGI_ERROR_ERRNO:
+	return DW_DLE_IOF;
+    case ELF_SGI_ERROR_TOO_BIG:
+	return DW_DLE_MOF;
+    default:
+	return DW_DLE_LEE;
+    }
+}
+#endif
+
+/*
+    Given an Elf ptr, set up dbg with pointers
+    to all the Dwarf data sections.
+    Return NULL on error.
+
+    This function is also responsible for determining
+    whether the given object contains Dwarf information
+    or not.  The test currently used is that it contains
+    either a .debug_info or a .debug_frame section.  If 
+    not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to 
+    return DW_DLV_NO_ENTRY.  Earlier, we had thought of using only 
+    the presence/absence of .debug_info to test, but we 
+    added .debug_frame since there could be stripped objects 
+    that have only a .debug_frame section for exception 
+    processing.
+    DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR
+*/
+static int
+_dwarf_setup(Dwarf_Debug dbg, dwarf_elf_handle elf, Dwarf_Error * error)
+{
+#ifdef __SGI_FAST_LIBELF
+    Elf64_Ehdr ehdr;
+    Elf64_Shdr shdr;
+    enum elf_sgi_error_type sres;
+    unsigned char const *ehdr_ident = 0;
+#else
+    Elf32_Ehdr *ehdr32 = 0;
+
+#ifdef HAVE_ELF64_GETEHDR
+    Elf64_Ehdr *ehdr64 = 0;
+#endif
+    Elf32_Shdr *shdr32 = 0;
+
+#ifdef HAVE_ELF64_GETSHDR
+    Elf64_Shdr *shdr64 = 0;
+#endif
+    Elf_Scn *scn = 0;
+    char *ehdr_ident = 0;
+#endif /* !defined(__SGI_FAST_LIBELF) */
+    Dwarf_Half machine = 0;
+    char *scn_name = 0;
+    int is_64bit = 0;
+    int foundDwarf = 0;
+
+    Dwarf_Unsigned section_size = 0;
+    Dwarf_Unsigned section_count = 0;
+    Dwarf_Half section_index = 0;
+    Dwarf_Addr section_addr = 0;
+
+    foundDwarf = FALSE;
+    dbg->de_elf = elf;
+
+    dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad;
+
+#ifdef __SGI_FAST_LIBELF
+    sres = elf_sgi_ehdr(elf, &ehdr);
+    if (sres != ELF_SGI_ERROR_OK) {
+	DWARF_DBG_ERROR(dbg,
+			_dwarf_error_code_from_elf_sgi_error_code(sres),
+			DW_DLV_ERROR);
+    }
+    ehdr_ident = ehdr.e_ident;
+    section_count = ehdr.e_shnum;
+    machine = ehdr.e_machine;
+#else
+    if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
+	DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETIDENT_ERROR, DW_DLV_ERROR);
+    }
+#endif
+
+    is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
+
+
+    dbg->de_same_endian = 1;
+    dbg->de_copy_word = memcpy;
+#ifdef WORDS_BIGENDIAN
+    dbg->de_big_endian_object = 1;
+    if (ehdr_ident[EI_DATA] == ELFDATA2LSB) {
+	dbg->de_same_endian = 0;
+	dbg->de_big_endian_object = 0;
+	dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+    }
+#else /* little endian */
+    dbg->de_big_endian_object = 0;
+    if (ehdr_ident[EI_DATA] == ELFDATA2MSB) {
+	dbg->de_same_endian = 0;
+	dbg->de_big_endian_object = 1;
+	dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+    }
+#endif /* !WORDS_BIGENDIAN */
+
+    /* The following de_length_size is Not Too Significant. Only used
+       one calculation, and an approximate one at that. */
+    dbg->de_length_size = is_64bit ? 8 : 4;
+    dbg->de_pointer_size = is_64bit ? 8 : 4;
+
+
+#ifdef __SGI_FAST_LIBELF
+    /* We've already loaded the ELF header, so there's nothing to do
+       here */
+#else
+#ifdef HAVE_ELF64_GETEHDR
+    if (is_64bit) {
+	ehdr64 = elf64_getehdr(elf);
+	if (ehdr64 == NULL) {
+	    DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
+			    DW_DLV_ERROR);
+	}
+	section_count = ehdr64->e_shnum;
+	machine = ehdr64->e_machine;
+    } else
+#endif
+    {
+	ehdr32 = elf32_getehdr(elf);
+	if (ehdr32 == NULL) {
+	    DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
+			    DW_DLV_ERROR);
+	}
+	section_count = ehdr32->e_shnum;
+	machine = ehdr32->e_machine;
+    }
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+    if (is_64bit && machine != EM_MIPS) {
+	/* MIPS/IRIX makes pointer size and length size 8 for -64.
+	   Other platforms make length 4 always. */
+	/* 4 here supports 32bit-offset dwarf2, as emitted by cygnus
+	   tools, and the dwarfv2.1 64bit extension setting. */
+	dbg->de_length_size = 4;
+    }
+
+    /* We start at index 1 to skip the initial empty section. */
+    for (section_index = 1; section_index < section_count;
+	 ++section_index) {
+
+#ifdef __SGI_FAST_LIBELF
+	sres = elf_sgi_shdr(elf, section_index, &shdr);
+	if (sres != ELF_SGI_ERROR_OK) {
+	    DWARF_DBG_ERROR(dbg,
+			    _dwarf_error_code_from_elf_sgi_error_code
+			    (sres), DW_DLV_ERROR);
+	}
+
+	section_size = shdr.sh_size;
+	section_addr = shdr.sh_addr;
+
+	sres =
+	    elf_sgi_string(elf, ehdr.e_shstrndx, shdr.sh_name,
+			   (char const **) &scn_name);
+	if (sres != ELF_SGI_ERROR_OK) {
+	    DWARF_DBG_ERROR(dbg,
+			    _dwarf_error_code_from_elf_sgi_error_code
+			    (sres), DW_DLV_ERROR);
+	}
+#else /* !defined(__SGI_FAST_LIBELF) */
+	scn = elf_getscn(elf, section_index);
+	if (scn == NULL) {
+	    DWARF_DBG_ERROR(dbg, DW_DLE_MDE, DW_DLV_ERROR);
+	}
+#ifdef HAVE_ELF64_GETSHDR
+	if (is_64bit) {
+	    shdr64 = elf64_getshdr(scn);
+	    if (shdr64 == NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR,
+				DW_DLV_ERROR);
+	    }
+
+	    section_size = shdr64->sh_size;
+	    section_addr = shdr64->sh_addr;
+
+	    if ((scn_name = elf_strptr(elf, ehdr64->e_shstrndx,
+				       shdr64->sh_name))
+		== NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
+				DW_DLV_ERROR);
+	    }
+	} else
+#endif /* HAVE_ELF64_GETSHDR */
+	{
+	    if ((shdr32 = elf32_getshdr(scn)) == NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR, 0);
+	    }
+
+	    section_size = shdr32->sh_size;
+	    section_addr = shdr32->sh_addr;
+
+	    if ((scn_name = elf_strptr(elf, ehdr32->e_shstrndx,
+				       shdr32->sh_name)) == NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
+				DW_DLV_ERROR);
+	    }
+	}
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+	if (strncmp(scn_name, ".debug_", 7)
+	    && strcmp(scn_name, ".eh_frame")
+	    )
+	    continue;
+
+	else if (strcmp(scn_name, ".debug_info") == 0) {
+	    if (dbg->de_debug_info != NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* Know no reason to allow empty debug_info section */
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_NULL,
+				DW_DLV_ERROR);
+	    }
+	    foundDwarf = TRUE;
+	    dbg->de_debug_info_index = section_index;
+	    dbg->de_debug_info_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_abbrev") == 0) {
+	    if (dbg->de_debug_abbrev != NULL) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* Know no reason to allow empty debug_abbrev section */
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_NULL,
+				DW_DLV_ERROR);
+	    }
+	    dbg->de_debug_abbrev_index = section_index;
+	    dbg->de_debug_abbrev_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_aranges") == 0) {
+	    if (dbg->de_debug_aranges_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_ARANGES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_aranges_index = section_index;
+	    dbg->de_debug_aranges_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_line") == 0) {
+	    if (dbg->de_debug_line_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_LINE_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_line_index = section_index;
+	    dbg->de_debug_line_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_frame") == 0) {
+	    if (dbg->de_debug_frame_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_FRAME_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_frame_index = section_index;
+	    dbg->de_debug_frame_size = section_size;
+	    foundDwarf = TRUE;
+	} else if (strcmp(scn_name, ".eh_frame") == 0) {
+	    /* gnu egcs-1.1.2 data */
+	    if (dbg->de_debug_frame_eh_gnu_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_FRAME_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_frame_eh_gnu_index = section_index;
+	    dbg->de_debug_frame_size_eh_gnu = section_size;
+	    dbg->de_debug_frame_eh_addr = section_addr;
+	    foundDwarf = TRUE;
+	}
+
+	else if (strcmp(scn_name, ".debug_loc") == 0) {
+	    if (dbg->de_debug_loc_index != 0) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_LOC_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_loc_index = section_index;
+	    dbg->de_debug_loc_size = section_size;
+	}
+
+
+	else if (strcmp(scn_name, ".debug_pubnames") == 0) {
+	    if (dbg->de_debug_pubnames_index != 0) {
+		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_PUBNAMES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_pubnames_index = section_index;
+	    dbg->de_debug_pubnames_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_str") == 0) {
+	    if (dbg->de_debug_str_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_STR_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_str_index = section_index;
+	    dbg->de_debug_str_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_funcnames") == 0) {
+	    if (dbg->de_debug_funcnames_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_funcnames_index = section_index;
+	    dbg->de_debug_funcnames_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_typenames") == 0) {
+	    /* SGI IRIX-only, created years before DWARF3. Content
+	       essentially identical to .debug_pubtypes.  */
+	    if (dbg->de_debug_typenames_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_TYPENAMES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_typenames_index = section_index;
+	    dbg->de_debug_typenames_size = section_size;
+	} else if (strcmp(scn_name, ".debug_pubtypes") == 0) {
+	    /* Section new in DWARF3.  */
+	    if (dbg->de_debug_pubtypes_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_PUBTYPES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_pubtypes_index = section_index;
+	    dbg->de_debug_pubtypes_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_varnames") == 0) {
+	    if (dbg->de_debug_varnames_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_VARNAMES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_varnames_index = section_index;
+	    dbg->de_debug_varnames_size = section_size;
+	}
+
+	else if (strcmp(scn_name, ".debug_weaknames") == 0) {
+	    if (dbg->de_debug_weaknames_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_weaknames_index = section_index;
+	    dbg->de_debug_weaknames_size = section_size;
+	} else if (strcmp(scn_name, ".debug_macinfo") == 0) {
+	    if (dbg->de_debug_macinfo_index != 0) {
+		DWARF_DBG_ERROR(dbg,
+				DW_DLE_DEBUG_MACINFO_DUPLICATE,
+				DW_DLV_ERROR);
+	    }
+	    if (section_size == 0) {
+		/* a zero size section is just empty. Ok, no error */
+		continue;
+	    }
+	    dbg->de_debug_macinfo_index = section_index;
+	    dbg->de_debug_macinfo_size = section_size;
+	}
+    }
+    if (foundDwarf) {
+	return DW_DLV_OK;
+    }
+
+    return (DW_DLV_NO_ENTRY);
+}
+
+
+/*
+    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;
+    dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
+    dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
+
+
+    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) {
+	elf_sgi_free(elf);
+	DWARF_DBG_ERROR(dbg,
+			_dwarf_error_code_from_elf_sgi_error_code(sres),
+			DW_DLV_ERROR);
+    }
+#else /* ! __SGI_FAST_LIBELF */
+    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 /* !HAVE_ELF_C_READ_MMAP */
+    /* ELF_C_READ is a portable value */
+    what_kind_of_elf_read = ELF_C_READ;
+#endif /* HAVE_ELF_C_READ_MMAP */
+
+    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) {
+#ifdef __SGI_FAST_LIBELF
+	elf_sgi_free(elf);
+#else
+	elf_end(elf);
+#endif
+	free(dbg);
+	return (res);
+    }
+
+    /* call cannot fail: no malloc or free involved */
+    _dwarf_setup_debug(dbg);
+
+    *ret_dbg = dbg;
+    return (DW_DLV_OK);
+}
+
+
+/*
+    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;
+    dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
+    dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
+
+    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);
+}
+
+
+/*
+	Frees all memory that was not previously freed
+	by dwarf_dealloc.
+	Aside from certain categories.
+*/
+int
+dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+    int res = DW_DLV_OK;
+
+    if (dbg->de_elf_must_close) {
+	/* Must do this *before* _dwarf_free_all_of_one_debug() as that 
+	   zeroes out dbg contents */
+#ifdef __SGI_FAST_LIBELF
+	elf_sgi_free(dbg->de_elf);
+#else
+	elf_end(dbg->de_elf);
+#endif
+    }
+
+    res = _dwarf_free_all_of_one_debug(dbg);
+    if (res == DW_DLV_ERROR) {
+	DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
+    }
+    dwarf_malloc_check_complete("After Final free");
+
+    return res;
+
+
+}
+
+
+/*
+    This function returns the Elf * pointer
+    associated with a Dwarf_Debug.
+*/
+int
+dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
+	      Dwarf_Error * error)
+{
+    if (dbg == NULL) {
+	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+	return (DW_DLV_ERROR);
+    }
+
+    *elf = dbg->de_elf;
+    return (DW_DLV_OK);
+}
+
+
+/*
+	Load the ELF section with the specified index and set the
+	pointer pointed to by section_data to the memory where it
+	was loaded.
+ */
+int
+_dwarf_load_section(Dwarf_Debug dbg,
+		    Dwarf_Half section_index,
+		    Dwarf_Small ** section_data, Dwarf_Error * error)
+{
+    if (section_index == 0) {
+	return DW_DLV_NO_ENTRY;
+    }
+
+    /* check to see if the section is already loaded */
+    if (*section_data != NULL) {
+	return DW_DLV_OK;
+    }
+
+    {
+#ifdef __SGI_FAST_LIBELF
+	enum elf_sgi_error_type sres;
+
+	sres = elf_sgi_section(dbg->de_elf,
+			       section_index, (void **) section_data);
+	if (sres != ELF_SGI_ERROR_OK) {
+	    DWARF_DBG_ERROR(dbg,
+			    _dwarf_error_code_from_elf_sgi_error_code
+			    (sres), DW_DLV_ERROR);
+	}
+#else
+	Elf_Scn *scn;
+	Elf_Data *data;
+
+	scn = elf_getscn(dbg->de_elf, section_index);
+	if (scn == NULL) {
+	    _dwarf_error(dbg, error, DW_DLE_MDE);
+	    return DW_DLV_ERROR;
+	}
+
+	/* 
+	   When using libelf as a producer, section data may be stored
+	   in multiple buffers. In libdwarf however, we only use libelf
+	   as a consumer (there is a dwarf producer API, but it doesn't
+	   use libelf). Because of this, this single call to elf_getdata
+	   will retrieve the entire section in a single contiguous
+	   buffer. */
+	data = elf_getdata(scn, NULL);
+	if (data == NULL) {
+	    _dwarf_error(dbg, error, DW_DLE_MDE);
+	    return DW_DLV_ERROR;
+	}
+
+	*section_data = data->d_buf;
+#endif /* !defined(__SGI_FAST_LIBELF) */
+    }
+
+    return DW_DLV_OK;
+}
+
+/* This is a hack so clients can verify offsets.
+   Added April 2005 so that debugger can detect broken offsets
+   (which happened in an IRIX  -64 executable larger than 2GB
+    using MIPSpro 7.3.1.3 compilers. A couple .debug_pubnames
+    offsets were wrong.).
+*/
+int
+dwarf_get_section_max_offsets(Dwarf_Debug dbg,
+			      Dwarf_Unsigned * debug_info_size,
+			      Dwarf_Unsigned * debug_abbrev_size,
+			      Dwarf_Unsigned * debug_line_size,
+			      Dwarf_Unsigned * debug_loc_size,
+			      Dwarf_Unsigned * debug_aranges_size,
+			      Dwarf_Unsigned * debug_macinfo_size,
+			      Dwarf_Unsigned * debug_pubnames_size,
+			      Dwarf_Unsigned * debug_str_size,
+			      Dwarf_Unsigned * debug_frame_size,
+			      Dwarf_Unsigned * debug_ranges_size,
+			      Dwarf_Unsigned * debug_typenames_size)
+{
+    *debug_info_size = dbg->de_debug_info_size;
+    *debug_abbrev_size = dbg->de_debug_abbrev_size;
+    *debug_line_size = dbg->de_debug_line_size;
+    *debug_loc_size = dbg->de_debug_loc_size;
+    *debug_aranges_size = dbg->de_debug_aranges_size;
+    *debug_macinfo_size = dbg->de_debug_macinfo_size;
+    *debug_pubnames_size = dbg->de_debug_pubnames_size;
+    *debug_str_size = dbg->de_debug_str_size;
+    *debug_frame_size = dbg->de_debug_frame_size;
+    *debug_ranges_size = 0;	/* Not yet supported. */
+    *debug_typenames_size = dbg->de_debug_typenames_size;
+
+
+    return DW_DLV_OK;
+}