📄 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. */
bfd_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. */
bfd_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 bfd_boolean ieee_read_number
PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
static bfd_boolean ieee_read_optional_number
PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, bfd_boolean *));
static bfd_boolean ieee_read_id
PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
unsigned long *));
static bfd_boolean ieee_read_optional_id
PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
unsigned long *, bfd_boolean *));
static bfd_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 bfd_boolean ieee_alloc_type
PARAMS ((struct ieee_info *, unsigned int, bfd_boolean));
static bfd_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 bfd_boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean ieee_read_cxx_misc
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
static bfd_boolean ieee_read_cxx_class
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
static bfd_boolean ieee_read_cxx_defaults
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
static bfd_boolean ieee_read_reference
PARAMS ((struct ieee_info *, const bfd_byte **));
static bfd_boolean ieee_require_asn
PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
static bfd_boolean ieee_require_atn65
PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
unsigned long *));
/* Report an error in the IEEE debugging information. */
static void
ieee_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 void
ieee_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 bfd_boolean
ieee_read_number (info, pp, pv)
struct ieee_info *info;
const bfd_byte **pp;
bfd_vma *pv;
{
return ieee_read_optional_number (info, pp, pv, (bfd_boolean *) NULL);
}
/* Read a number in an IEEE file. If ppresent is not NULL, the number
need not be there. */
static bfd_boolean
ieee_read_optional_number (info, pp, pv, ppresent)
struct ieee_info *info;
const bfd_byte **pp;
bfd_vma *pv;
bfd_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 bfd_boolean
ieee_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, (bfd_boolean *) NULL);
}
/* Read a string from an IEEE file. If ppresent is not NULL, the
string is optional. */
static bfd_boolean
ieee_read_optional_id (info, pp, pname, pnamlen, ppresent)
struct ieee_info *info;
const bfd_byte **pp;
const char **pname;
unsigned long *pnamlen;
bfd_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 bfd_boolean
ieee_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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -