tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_macro.c
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_macro.c	Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,473 @@
+/*
+
+  Copyright (C) 2000,2002,2004 Silicon Graphics, Inc.  All Rights Reserved.
+  Portions Copyright (C) 2007 David Anderson. 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
+
+*/
+/* The address of the Free Software Foundation is
+   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 
+   Boston, MA 02110-1301, USA.
+   SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <limits.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "dwarf_macro.h"
+
+
+#define LEFTPAREN '('
+#define RIGHTPAREN ')'
+#define SPACE ' '
+
+/*
+	Given the dwarf macro string, return a pointer to
+	the value.  Returns pointer to 0 byte at end of string
+	if no value found (meaning the value is the empty string).
+
+	Only understands well-formed dwarf macinfo strings.
+*/
+char *
+dwarf_find_macro_value_start(char *str)
+{
+    char *lcp;
+    int funclike = 0;
+
+    for (lcp = str; *lcp; ++lcp) {
+	switch (*lcp) {
+	case LEFTPAREN:
+	    funclike = 1;
+	    break;
+	case RIGHTPAREN:
+	    /* lcp+1 must be a space, and following char is the value */
+	    return lcp + 2;
+	case SPACE:
+	    /* we allow extraneous spaces inside macro parameter **
+	       list, just in case... This is not really needed. */
+	    if (!funclike) {
+		return lcp + 1;
+	    }
+	    break;
+	}
+    }
+    /* never found value: returns pointer to the 0 byte at end of
+       string */
+    return lcp;
+
+}
+
+
+/*
+   Try to keep fileindex correct in every Macro_Details
+   record by tracking file starts and ends.
+   Uses high water mark: space reused, not freed.
+   Presumption is that this makes sense for most uses.
+   STARTERMAX is set so that the array need not be expanded for
+   most files: it is the initial include file depth.
+*/
+struct macro_stack_s {
+    Dwarf_Signed *st_base;
+    long max;
+    long next_to_use;
+    int was_fault;
+};
+
+static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms);
+static void
+free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms)
+{
+    dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING);
+    _dwarf_reset_index_macro_stack(ms);
+}
+
+#define STARTERMAX 10
+static void
+_dwarf_reset_index_macro_stack(struct macro_stack_s *ms)
+{
+    ms->st_base = 0;
+    ms->max = 0;
+    ms->next_to_use = 0;
+    ms->was_fault = 0;
+}
+static int
+_dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx,
+			      struct macro_stack_s *ms)
+{
+    Dwarf_Signed *newbase;
+
+    if (ms->next_to_use >= ms->max) {
+	long new_size;
+
+	if (ms->max == 0) {
+	    ms->max = STARTERMAX;
+	}
+	new_size = ms->max * 2;
+	newbase =
+	    _dwarf_get_alloc(dbg, DW_DLA_STRING,
+			     new_size * sizeof(Dwarf_Signed));
+	if (newbase == 0) {
+	    /* just leave the old array in place */
+	    ms->was_fault = 1;
+	    return DW_DLV_ERROR;
+	}
+        if(ms->st_base) {
+	    memcpy(newbase, ms->st_base,
+	       ms->next_to_use * sizeof(Dwarf_Signed));
+	    dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING);
+        }
+	ms->st_base = newbase;
+	ms->max = new_size;
+    }
+    ms->st_base[ms->next_to_use] = indx;
+    ++ms->next_to_use;
+    return DW_DLV_OK;
+}
+
+static Dwarf_Signed
+_dwarf_macro_stack_pop_index(struct macro_stack_s *ms)
+{
+    if (ms->was_fault) {
+	return -1;
+    }
+    if (ms->next_to_use > 0) {
+	ms->next_to_use--;
+	return (ms->st_base[ms->next_to_use]);
+    } else {
+        ms->was_fault = 1;
+    }
+    return -1;
+}
+
+/* starting at macro_offset in .debug_macinfo,
+	if maximum_count is 0, treat as if it is infinite.
+	get macro data up thru
+	maximum_count entries or the end of a compilation
+	unit's entries (whichever comes first). 
+*/
+
+int
+dwarf_get_macro_details(Dwarf_Debug dbg,
+			Dwarf_Off macro_offset,
+			Dwarf_Unsigned maximum_count,
+			Dwarf_Signed * entry_count,
+			Dwarf_Macro_Details ** details,
+			Dwarf_Error * error)
+{
+    Dwarf_Small *macro_base = 0;
+    Dwarf_Small *pnext = 0;
+    Dwarf_Unsigned endloc = 0;
+    unsigned char uc = 0;
+    unsigned long depth = 0;	/* By section 6.3.2 Dwarf3 draft 8/9,
+				   the base file should appear as
+				   DW_MACINFO_start_file. See
+				   http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html
+				   on "[Bug debug/20253] New: [3.4/4.0 regression]:
+				   Macro debug info broken due to lexer change" for how
+				   gcc is broken in some versions. We no longer use
+				   depth as a stopping point, it's not needed as a
+				   stopping point anyway.  */
+
+
+    int res = 0;
+
+    /* count space used by strings */
+    unsigned long str_space = 0;
+    int done = 0;
+    unsigned long space_needed = 0;
+    unsigned long string_offset = 0;
+    Dwarf_Small *return_data = 0;
+    Dwarf_Small *pdata = 0;
+    unsigned long final_count = 0;
+    Dwarf_Signed fileindex = -1;
+    Dwarf_Small *latest_str_loc = 0;
+    struct macro_stack_s msdata;
+
+    unsigned long count = 0;
+    unsigned long max_count = (unsigned long) maximum_count;
+
+    _dwarf_reset_index_macro_stack(&msdata);
+    if (dbg == NULL) {
+	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+	free_macro_stack(dbg,&msdata);
+	return (DW_DLV_ERROR);
+    }
+
+    res =
+	_dwarf_load_section(dbg,
+			    dbg->de_debug_macinfo_index,
+			    &dbg->de_debug_macinfo, error);
+    if (res != DW_DLV_OK) {
+	free_macro_stack(dbg,&msdata);
+	return res;
+    }
+
+    macro_base = dbg->de_debug_macinfo;
+    if (macro_base == NULL) {
+	free_macro_stack(dbg,&msdata);
+	return (DW_DLV_NO_ENTRY);
+    }
+    if (macro_offset >= dbg->de_debug_macinfo_size) {
+	free_macro_stack(dbg,&msdata);
+	return (DW_DLV_NO_ENTRY);
+    }
+
+    pnext = macro_base + macro_offset;
+    if (maximum_count == 0) {
+	max_count = ULONG_MAX;
+    }
+
+
+    /* how many entries and how much space will they take? */
+
+    endloc = (pnext - macro_base);
+    if (endloc >= dbg->de_debug_macinfo_size) {
+	if (endloc == dbg->de_debug_macinfo_size) {
+	    /* normal: found last entry */
+	    free_macro_stack(dbg,&msdata);
+	    return DW_DLV_NO_ENTRY;
+	}
+	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+	free_macro_stack(dbg,&msdata);
+	return (DW_DLV_ERROR);
+    }
+    for (count = 0; !done && count < max_count; ++count) {
+	unsigned long slen;
+	Dwarf_Word len;
+
+	uc = *pnext;
+	++pnext;		/* get past the type code */
+	switch (uc) {
+	case DW_MACINFO_define:
+	case DW_MACINFO_undef:
+	    /* line, string */
+	case DW_MACINFO_vendor_ext:
+	    /* number, string */
+	    (void) _dwarf_decode_u_leb128(pnext, &len);
+
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    slen = strlen((char *) pnext) + 1;
+	    pnext += slen;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    str_space += slen;
+	    break;
+	case DW_MACINFO_start_file:
+	    /* line, file index */
+	    (void) _dwarf_decode_u_leb128(pnext, &len);
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    (void) _dwarf_decode_u_leb128(pnext, &len);
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    ++depth;
+	    break;
+
+	case DW_MACINFO_end_file:
+	    if (--depth == 0) {
+		/* done = 1; no, do not stop here, at least one gcc had 
+		   the wrong depth settings in the gcc 3.4 timeframe. */
+	    }
+	    break;		/* no string or number here */
+	case 0:
+	    /* end of cu's entries */
+	    done = 1;
+	    break;
+	default:
+	    free_macro_stack(dbg,&msdata);
+	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
+	    return (DW_DLV_ERROR);
+	    /* bogus macinfo! */
+	}
+
+	endloc = (pnext - macro_base);
+	if (endloc == dbg->de_debug_macinfo_size) {
+	    done = 1;
+	} else if (endloc > dbg->de_debug_macinfo_size) {
+	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+	    free_macro_stack(dbg,&msdata);
+	    return (DW_DLV_ERROR);
+	}
+    }
+    if (count == 0) {
+	free_macro_stack(dbg,&msdata);
+	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR);
+	return (DW_DLV_ERROR);
+    }
+
+    /* we have 'count' array entries to allocate and str_space bytes of 
+       string space to provide for. */
+
+    string_offset = count * sizeof(Dwarf_Macro_Details);
+
+    /* extra 2 not really needed */
+    space_needed = string_offset + str_space + 2;
+    return_data = pdata =
+	_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
+    latest_str_loc = pdata + string_offset;
+    if (pdata == 0) {
+	free_macro_stack(dbg,&msdata);
+	_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
+	return (DW_DLV_ERROR);
+    }
+    pnext = macro_base + macro_offset;
+
+    done = 0;
+
+    /* A series ends with a type code of 0. */
+
+    for (final_count = 0; !done && final_count < count; ++final_count) {
+	unsigned long slen;
+	Dwarf_Word len;
+	Dwarf_Unsigned v1;
+	Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
+		(final_count * sizeof (Dwarf_Macro_Details)));
+
+	endloc = (pnext - macro_base);
+	if (endloc > dbg->de_debug_macinfo_size) {
+	    free_macro_stack(dbg,&msdata);
+	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+	    return (DW_DLV_ERROR);
+	}
+	uc = *pnext;
+	pdmd->dmd_offset = (pnext - macro_base);
+	pdmd->dmd_type = uc;
+	pdmd->dmd_fileindex = fileindex;
+	pdmd->dmd_lineno = 0;
+	pdmd->dmd_macro = 0;
+	++pnext;		/* get past the type code */
+	switch (uc) {
+	case DW_MACINFO_define:
+	case DW_MACINFO_undef:
+	    /* line, string */
+	case DW_MACINFO_vendor_ext:
+	    /* number, string */
+	    v1 = _dwarf_decode_u_leb128(pnext, &len);
+	    pdmd->dmd_lineno = v1;
+
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    slen = strlen((char *) pnext) + 1;
+	    strcpy((char *) latest_str_loc, (char *) pnext);
+	    pdmd->dmd_macro = (char *) latest_str_loc;
+	    latest_str_loc += slen;
+	    pnext += slen;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    break;
+	case DW_MACINFO_start_file:
+	    /* Line, file index */
+	    v1 = _dwarf_decode_u_leb128(pnext, &len);
+	    pdmd->dmd_lineno = v1;
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    v1 = _dwarf_decode_u_leb128(pnext, &len);
+	    pdmd->dmd_fileindex = v1;
+	    (void) _dwarf_macro_stack_push_index(dbg, fileindex,
+						 &msdata);
+	    /* We ignore the error, we just let fileindex ** be -1 when 
+	       we pop this one. */
+	    fileindex = v1;
+	    pnext += len;
+	    if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+		free_macro_stack(dbg,&msdata);
+                dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+		_dwarf_error(dbg, error,
+			     DW_DLE_DEBUG_MACRO_INCONSISTENT);
+		return (DW_DLV_ERROR);
+	    }
+	    break;
+
+	case DW_MACINFO_end_file:
+	    fileindex = _dwarf_macro_stack_pop_index(&msdata);
+	    break;		/* no string or number here */
+	case 0:
+	    /* Type code of 0 means the end of cu's entries. */
+	    done = 1;
+	    break;
+	default:
+	    /* Bogus macinfo! */
+            dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+	    free_macro_stack(dbg,&msdata);
+	    _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
+	    return (DW_DLV_ERROR);
+	}
+    }
+    *entry_count = count;
+    *details = (Dwarf_Macro_Details *) return_data;
+
+    free_macro_stack(dbg,&msdata);
+    return DW_DLV_OK;
+}