📄 ieee.c
字号:
/* ieee.c -- Read and write IEEE-695 debugging information. Copyright 1996, 1998, 2000, 2001 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@cygnus.com>. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This file reads and writes IEEE-695 debugging information. */#include <stdio.h>#include <assert.h>#include "bfd.h"#include "ieee.h"#include "bucomm.h"#include "libiberty.h"#include "debug.h"#include "budbg.h"#include "filenames.h"/* This structure holds an entry on the block stack. */struct ieee_block{ /* The kind of block. */ int kind; /* The source file name, for a BB5 block. */ const char *filename; /* The index of the function type, for a BB4 or BB6 block. */ unsigned int fnindx; /* True if this function is being skipped. */ boolean skip;};/* This structure is the block stack. */#define BLOCKSTACK_SIZE (16)struct ieee_blockstack{ /* The stack pointer. */ struct ieee_block *bsp; /* The stack. */ struct ieee_block stack[BLOCKSTACK_SIZE];};/* This structure holds information for a variable. */struct ieee_var{ /* Start of name. */ const char *name; /* Length of name. */ unsigned long namlen; /* Type. */ debug_type type; /* Slot if we make an indirect type. */ debug_type *pslot; /* Kind of variable or function. */ enum { IEEE_UNKNOWN, IEEE_EXTERNAL, IEEE_GLOBAL, IEEE_STATIC, IEEE_LOCAL, IEEE_FUNCTION } kind;};/* This structure holds all the variables. */struct ieee_vars{ /* Number of slots allocated. */ unsigned int alloc; /* Variables. */ struct ieee_var *vars;};/* This structure holds information for a type. We need this because we don't want to represent bitfields as real types. */struct ieee_type{ /* Type. */ debug_type type; /* Slot if this is type is referenced before it is defined. */ debug_type *pslot; /* Slots for arguments if we make indirect types for them. */ debug_type *arg_slots; /* If this is a bitfield, this is the size in bits. If this is not a bitfield, this is zero. */ unsigned long bitsize;};/* This structure holds all the type information. */struct ieee_types{ /* Number of slots allocated. */ unsigned int alloc; /* Types. */ struct ieee_type *types; /* Builtin types. */#define BUILTIN_TYPE_COUNT (60) debug_type builtins[BUILTIN_TYPE_COUNT];};/* This structure holds a linked last of structs with their tag names, so that we can convert them to C++ classes if necessary. */struct ieee_tag{ /* Next tag. */ struct ieee_tag *next; /* This tag name. */ const char *name; /* The type of the tag. */ debug_type type; /* The tagged type is an indirect type pointing at this slot. */ debug_type slot; /* This is an array of slots used when a field type is converted into a indirect type, in case it needs to be later converted into a reference type. */ debug_type *fslots;};/* This structure holds the information we pass around to the parsing functions. */struct ieee_info{ /* The debugging handle. */ PTR dhandle; /* The BFD. */ bfd *abfd; /* The start of the bytes to be parsed. */ const bfd_byte *bytes; /* The end of the bytes to be parsed. */ const bfd_byte *pend; /* The block stack. */ struct ieee_blockstack blockstack; /* Whether we have seen a BB1 or BB2. */ boolean saw_filename; /* The variables. */ struct ieee_vars vars; /* The global variables, after a global typedef block. */ struct ieee_vars *global_vars; /* The types. */ struct ieee_types types; /* The global types, after a global typedef block. */ struct ieee_types *global_types; /* The list of tagged structs. */ struct ieee_tag *tags;};/* Basic builtin types, not including the pointers. */enum builtin_types{ builtin_unknown = 0, builtin_void = 1, builtin_signed_char = 2, builtin_unsigned_char = 3, builtin_signed_short_int = 4, builtin_unsigned_short_int = 5, builtin_signed_long = 6, builtin_unsigned_long = 7, builtin_signed_long_long = 8, builtin_unsigned_long_long = 9, builtin_float = 10, builtin_double = 11, builtin_long_double = 12, builtin_long_long_double = 13, builtin_quoted_string = 14, builtin_instruction_address = 15, builtin_int = 16, builtin_unsigned = 17, builtin_unsigned_int = 18, builtin_char = 19, builtin_long = 20, builtin_short = 21, builtin_unsigned_short = 22, builtin_short_int = 23, builtin_signed_short = 24, builtin_bcd_float = 25};/* These are the values found in the derivation flags of a 'b' component record of a 'T' type extension record in a C++ pmisc record. These are bitmasks. *//* Set for a private base class, clear for a public base class. Protected base classes are not supported. */#define BASEFLAGS_PRIVATE (0x1)/* Set for a virtual base class. */#define BASEFLAGS_VIRTUAL (0x2)/* Set for a friend class, clear for a base class. */#define BASEFLAGS_FRIEND (0x10)/* These are the values found in the specs flags of a 'd', 'm', or 'v' component record of a 'T' type extension record in a C++ pmisc record. The same flags are used for a 'M' record in a C++ pmisc record. *//* The lower two bits hold visibility information. */#define CXXFLAGS_VISIBILITY (0x3)/* This value in the lower two bits indicates a public member. */#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)/* This value in the lower two bits indicates a private member. */#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)/* This value in the lower two bits indicates a protected member. */#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)/* Set for a static member. */#define CXXFLAGS_STATIC (0x4)/* Set for a virtual override. */#define CXXFLAGS_OVERRIDE (0x8)/* Set for a friend function. */#define CXXFLAGS_FRIEND (0x10)/* Set for a const function. */#define CXXFLAGS_CONST (0x20)/* Set for a volatile function. */#define CXXFLAGS_VOLATILE (0x40)/* Set for an overloaded function. */#define CXXFLAGS_OVERLOADED (0x80)/* Set for an operator function. */#define CXXFLAGS_OPERATOR (0x100)/* Set for a constructor or destructor. */#define CXXFLAGS_CTORDTOR (0x400)/* Set for a constructor. */#define CXXFLAGS_CTOR (0x200)/* Set for an inline function. */#define CXXFLAGS_INLINE (0x800)/* Local functions. */static void ieee_error PARAMS ((struct ieee_info *, const bfd_byte *, const char *));static void ieee_eof PARAMS ((struct ieee_info *));static char *savestring PARAMS ((const char *, unsigned long));static boolean ieee_read_number PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));static boolean ieee_read_optional_number PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *));static boolean ieee_read_id PARAMS ((struct ieee_info *, const bfd_byte **, const char **, unsigned long *));static boolean ieee_read_optional_id PARAMS ((struct ieee_info *, const bfd_byte **, const char **, unsigned long *, boolean *));static boolean ieee_read_expression PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));static debug_type ieee_builtin_type PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int));static boolean ieee_alloc_type PARAMS ((struct ieee_info *, unsigned int, boolean));static boolean ieee_read_type_index PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *));static int ieee_regno_to_genreg PARAMS ((bfd *, int));static int ieee_genreg_to_regno PARAMS ((bfd *, int));static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **));static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **));static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **));static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **));static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **));static boolean ieee_read_cxx_misc PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));static boolean ieee_read_cxx_class PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));static boolean ieee_read_cxx_defaults PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));static boolean ieee_read_reference PARAMS ((struct ieee_info *, const bfd_byte **));static boolean ieee_require_asn PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));static boolean ieee_require_atn65 PARAMS ((struct ieee_info *, const bfd_byte **, const char **, unsigned long *));/* Report an error in the IEEE debugging information. */static voidieee_error (info, p, s) struct ieee_info *info; const bfd_byte *p; const char *s;{ if (p != NULL) fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd), (unsigned long) (p - info->bytes), s, *p); else fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);}/* Report an unexpected EOF in the IEEE debugging information. */static voidieee_eof (info) struct ieee_info *info;{ ieee_error (info, (const bfd_byte *) NULL, _("unexpected end of debugging information"));}/* Save a string in memory. */static char *savestring (start, len) const char *start; unsigned long len;{ char *ret; ret = (char *) xmalloc (len + 1); memcpy (ret, start, len); ret[len] = '\0'; return ret;}/* Read a number which must be present in an IEEE file. */static booleanieee_read_number (info, pp, pv) struct ieee_info *info; const bfd_byte **pp; bfd_vma *pv;{ return ieee_read_optional_number (info, pp, pv, (boolean *) NULL);}/* Read a number in an IEEE file. If ppresent is not NULL, the number need not be there. */static booleanieee_read_optional_number (info, pp, pv, ppresent) struct ieee_info *info; const bfd_byte **pp; bfd_vma *pv; boolean *ppresent;{ ieee_record_enum_type b; if (*pp >= info->pend) { if (ppresent != NULL) { *ppresent = false; return true; } ieee_eof (info); return false; } b = (ieee_record_enum_type) **pp; ++*pp; if (b <= ieee_number_end_enum) { *pv = (bfd_vma) b; if (ppresent != NULL) *ppresent = true; return true; } if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum) { unsigned int i; i = (int) b - (int) ieee_number_repeat_start_enum; if (*pp + i - 1 >= info->pend) { ieee_eof (info); return false; } *pv = 0; for (; i > 0; i--) { *pv <<= 8; *pv += **pp; ++*pp; } if (ppresent != NULL) *ppresent = true; return true; } if (ppresent != NULL) { --*pp; *ppresent = false; return true; } ieee_error (info, *pp - 1, _("invalid number")); return false;}/* Read a required string from an IEEE file. */static booleanieee_read_id (info, pp, pname, pnamlen) struct ieee_info *info; const bfd_byte **pp; const char **pname; unsigned long *pnamlen;{ return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL);}/* Read a string from an IEEE file. If ppresent is not NULL, the string is optional. */static booleanieee_read_optional_id (info, pp, pname, pnamlen, ppresent) struct ieee_info *info; const bfd_byte **pp; const char **pname; unsigned long *pnamlen; boolean *ppresent;{ bfd_byte b; unsigned long len; if (*pp >= info->pend) { ieee_eof (info); return false; } b = **pp; ++*pp; if (b <= 0x7f) len = b; else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum) { len = **pp; ++*pp; } else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum) { len = (**pp << 8) + (*pp)[1]; *pp += 2; } else { if (ppresent != NULL) { --*pp; *ppresent = false; return true; } ieee_error (info, *pp - 1, _("invalid string length")); return false; } if ((unsigned long) (info->pend - *pp) < len) { ieee_eof (info); return false; } *pname = (const char *) *pp; *pnamlen = len; *pp += len; if (ppresent != NULL) *ppresent = true; return true;}/* Read an expression from an IEEE file. Since this code is only used to parse debugging information, I haven't bothered to write a full blown IEEE expression parser. I've only thrown in the things I've seen in debugging information. This can be easily extended if necessary. */static booleanieee_read_expression (info, pp, pv) struct ieee_info *info; const bfd_byte **pp; bfd_vma *pv;{ const bfd_byte *expr_start;#define EXPR_STACK_SIZE (10) bfd_vma expr_stack[EXPR_STACK_SIZE]; bfd_vma *esp; expr_start = *pp; esp = expr_stack; while (1) { const bfd_byte *start; bfd_vma val; boolean present; ieee_record_enum_type c; start = *pp; if (! ieee_read_optional_number (info, pp, &val, &present)) return false; if (present) { if (esp - expr_stack >= EXPR_STACK_SIZE) { ieee_error (info, start, _("expression stack overflow")); return false; } *esp++ = val; continue; } c = (ieee_record_enum_type) **pp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -