mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-29 15:00:34 +00:00
2179 lines
50 KiB
C
2179 lines
50 KiB
C
|
/* ieee.c -- Write out IEEE-695 debugging information.
|
||
|
Copyright (C) 1996 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"
|
||
|
|
||
|
/* 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;
|
||
|
};
|
||
|
|
||
|
/* 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;
|
||
|
};
|
||
|
|
||
|
/* 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;
|
||
|
/* If this is a bitfield, this is the size in bits. If this is not
|
||
|
a bitfield, this is zero. */
|
||
|
unsigned long bitsize;
|
||
|
/* If this is a function type ('x' or 'X') this is the return type. */
|
||
|
debug_type return_type;
|
||
|
};
|
||
|
|
||
|
/* 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];
|
||
|
};
|
||
|
|
||
|
static void ieee_error
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte *, const char *));
|
||
|
static void ieee_eof PARAMS ((bfd *));
|
||
|
static char *savestring PARAMS ((const char *, unsigned long));
|
||
|
static boolean ieee_read_number
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
bfd_vma *));
|
||
|
static boolean ieee_read_optional_number
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
bfd_vma *, boolean *));
|
||
|
static boolean ieee_read_id
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
const char **, unsigned long *));
|
||
|
static boolean ieee_read_optional_id
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
const char **, unsigned long *, boolean *));
|
||
|
static boolean ieee_read_expression
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
bfd_vma *));
|
||
|
static debug_type ieee_builtin_type
|
||
|
PARAMS ((PTR, bfd *, struct ieee_types *, const bfd_byte *,
|
||
|
const bfd_byte *, unsigned int));
|
||
|
static boolean ieee_read_type_index
|
||
|
PARAMS ((PTR, bfd *, struct ieee_types *, const bfd_byte *,
|
||
|
const bfd_byte **, const bfd_byte *, debug_type *));
|
||
|
static int ieee_regno_to_gen PARAMS ((bfd *, int));
|
||
|
static boolean parse_ieee_bb
|
||
|
PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_blockstack *,
|
||
|
const bfd_byte *, const bfd_byte **, const bfd_byte *));
|
||
|
static boolean parse_ieee_be
|
||
|
PARAMS ((PTR, bfd *, struct ieee_blockstack *, const bfd_byte *,
|
||
|
const bfd_byte **, const bfd_byte *));
|
||
|
static boolean parse_ieee_nn
|
||
|
PARAMS ((PTR, bfd *, struct ieee_vars *, const bfd_byte *,
|
||
|
const bfd_byte **, const bfd_byte *));
|
||
|
static boolean parse_ieee_ty
|
||
|
PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_vars *,
|
||
|
const bfd_byte *, const bfd_byte **, const bfd_byte *));
|
||
|
static boolean parse_ieee_atn
|
||
|
PARAMS ((PTR, bfd *, struct ieee_types *, struct ieee_vars *, int,
|
||
|
const bfd_byte *, const bfd_byte **, const bfd_byte *));
|
||
|
static boolean ieee_require_asn
|
||
|
PARAMS ((bfd *, const bfd_byte *, const bfd_byte **, const bfd_byte *,
|
||
|
bfd_vma *));
|
||
|
|
||
|
/* Report an error in the IEEE debugging information. */
|
||
|
|
||
|
static void
|
||
|
ieee_error (abfd, bytes, p, s)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte *p;
|
||
|
const char *s;
|
||
|
{
|
||
|
if (p != NULL)
|
||
|
fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (abfd),
|
||
|
(unsigned long) (p - bytes), s, *p);
|
||
|
else
|
||
|
fprintf (stderr, "%s: %s\n", bfd_get_filename (abfd), s);
|
||
|
}
|
||
|
|
||
|
/* Report an unexpected EOF in the IEEE debugging information. */
|
||
|
|
||
|
static void
|
||
|
ieee_eof (abfd)
|
||
|
bfd *abfd;
|
||
|
{
|
||
|
ieee_error (abfd, (const bfd_byte *) NULL, (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 boolean
|
||
|
ieee_read_number (abfd, bytes, pp, pend, pv)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
bfd_vma *pv;
|
||
|
{
|
||
|
return ieee_read_optional_number (abfd, bytes, pp, pend, pv,
|
||
|
(boolean *) NULL);
|
||
|
}
|
||
|
|
||
|
/* Read a number in an IEEE file. If ppresent is not NULL, the number
|
||
|
need not be there. */
|
||
|
|
||
|
static boolean
|
||
|
ieee_read_optional_number (abfd, bytes, pp, pend, pv, ppresent)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
bfd_vma *pv;
|
||
|
boolean *ppresent;
|
||
|
{
|
||
|
ieee_record_enum_type b;
|
||
|
|
||
|
if (*pp >= pend)
|
||
|
{
|
||
|
if (ppresent != NULL)
|
||
|
{
|
||
|
*ppresent = false;
|
||
|
return true;
|
||
|
}
|
||
|
ieee_eof (abfd);
|
||
|
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 >= pend)
|
||
|
{
|
||
|
ieee_eof (abfd);
|
||
|
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 (abfd, bytes, *pp - 1, "invalid number");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Read a required string from an IEEE file. */
|
||
|
|
||
|
static boolean
|
||
|
ieee_read_id (abfd, bytes, pp, pend, pname, pnamlen)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
const char **pname;
|
||
|
unsigned long *pnamlen;
|
||
|
{
|
||
|
return ieee_read_optional_id (abfd, bytes, pp, pend, pname, pnamlen,
|
||
|
(boolean *) NULL);
|
||
|
}
|
||
|
|
||
|
/* Read a string from an IEEE file. If ppresent is not NULL, the
|
||
|
string is optional. */
|
||
|
|
||
|
static boolean
|
||
|
ieee_read_optional_id (abfd, bytes, pp, pend, pname, pnamlen, ppresent)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
const char **pname;
|
||
|
unsigned long *pnamlen;
|
||
|
boolean *ppresent;
|
||
|
{
|
||
|
bfd_byte b;
|
||
|
unsigned long len;
|
||
|
|
||
|
if (*pp >= pend)
|
||
|
{
|
||
|
ieee_eof (abfd);
|
||
|
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 (abfd, bytes, *pp - 1, "invalid string length");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ((unsigned long) (pend - *pp) < len)
|
||
|
{
|
||
|
ieee_eof (abfd);
|
||
|
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 boolean
|
||
|
ieee_read_expression (abfd, bytes, pp, pend, pv)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
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 (abfd, bytes, pp, pend, &val, &present))
|
||
|
return false;
|
||
|
|
||
|
if (present)
|
||
|
{
|
||
|
if (esp - expr_stack >= EXPR_STACK_SIZE)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "expression stack overflow");
|
||
|
return false;
|
||
|
}
|
||
|
*esp++ = val;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
c = (ieee_record_enum_type) **pp;
|
||
|
|
||
|
if (c >= ieee_module_beginning_enum)
|
||
|
break;
|
||
|
|
||
|
++*pp;
|
||
|
|
||
|
if (c == ieee_comma)
|
||
|
break;
|
||
|
|
||
|
switch (c)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, start,
|
||
|
"unsupported IEEE expression operator");
|
||
|
break;
|
||
|
|
||
|
case ieee_variable_R_enum:
|
||
|
{
|
||
|
bfd_vma indx;
|
||
|
asection *s;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &indx))
|
||
|
return false;
|
||
|
for (s = abfd->sections; s != NULL; s = s->next)
|
||
|
if ((bfd_vma) s->target_index == indx)
|
||
|
break;
|
||
|
if (s == NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "unknown section");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (esp - expr_stack >= EXPR_STACK_SIZE)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "expression stack overflow");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*esp++ = bfd_get_section_vma (abfd, s);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ieee_function_plus_enum:
|
||
|
case ieee_function_minus_enum:
|
||
|
{
|
||
|
bfd_vma v1, v2;
|
||
|
|
||
|
if (esp - expr_stack < 2)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "expression stack underflow");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
v1 = *--esp;
|
||
|
v2 = *--esp;
|
||
|
*esp++ = v1 + v2;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (esp - 1 != expr_stack)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, expr_start, "expression stack mismatch");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*pv = *--esp;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Return an IEEE builtin type. */
|
||
|
|
||
|
static debug_type
|
||
|
ieee_builtin_type (dhandle, abfd, types, bytes, p, indx)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_types *types;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte *p;
|
||
|
unsigned int indx;
|
||
|
{
|
||
|
boolean ptr;
|
||
|
debug_type type;
|
||
|
const char *name;
|
||
|
|
||
|
if (indx < BUILTIN_TYPE_COUNT
|
||
|
&& types->builtins[indx] != DEBUG_TYPE_NULL)
|
||
|
return types->builtins[indx];
|
||
|
|
||
|
ptr = false;
|
||
|
switch (indx)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, p, "unknown builtin type");
|
||
|
return NULL;
|
||
|
|
||
|
case 32:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 0:
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
name = NULL;
|
||
|
break;
|
||
|
|
||
|
case 33:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 1:
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
name = "void";
|
||
|
break;
|
||
|
|
||
|
case 34:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 2:
|
||
|
type = debug_make_int_type (dhandle, 1, false);
|
||
|
name = "signed char";
|
||
|
break;
|
||
|
|
||
|
case 35:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 3:
|
||
|
type = debug_make_int_type (dhandle, 1, true);
|
||
|
name = "unsigned char";
|
||
|
break;
|
||
|
|
||
|
case 36:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 4:
|
||
|
type = debug_make_int_type (dhandle, 2, false);
|
||
|
name = "signed short int";
|
||
|
break;
|
||
|
|
||
|
case 37:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 5:
|
||
|
type = debug_make_int_type (dhandle, 2, true);
|
||
|
name = "unsigned short int";
|
||
|
break;
|
||
|
|
||
|
case 38:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 6:
|
||
|
type = debug_make_int_type (dhandle, 4, false);
|
||
|
name = "signed long";
|
||
|
break;
|
||
|
|
||
|
case 39:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 7:
|
||
|
type = debug_make_int_type (dhandle, 4, true);
|
||
|
name = "unsigned long";
|
||
|
break;
|
||
|
|
||
|
case 40:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 8:
|
||
|
type = debug_make_int_type (dhandle, 8, false);
|
||
|
name = "signed long long";
|
||
|
break;
|
||
|
|
||
|
case 41:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 9:
|
||
|
type = debug_make_int_type (dhandle, 8, true);
|
||
|
name = "unsigned long long";
|
||
|
break;
|
||
|
|
||
|
case 42:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 10:
|
||
|
type = debug_make_float_type (dhandle, 4);
|
||
|
name = "float";
|
||
|
break;
|
||
|
|
||
|
case 43:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 11:
|
||
|
type = debug_make_float_type (dhandle, 8);
|
||
|
name = "double";
|
||
|
break;
|
||
|
|
||
|
case 44:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 12:
|
||
|
/* FIXME: The size for this type should depend upon the
|
||
|
processor. */
|
||
|
type = debug_make_float_type (dhandle, 12);
|
||
|
name = "long double";
|
||
|
break;
|
||
|
|
||
|
case 45:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 13:
|
||
|
type = debug_make_float_type (dhandle, 16);
|
||
|
name = "long long double";
|
||
|
break;
|
||
|
|
||
|
case 46:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 14:
|
||
|
type = debug_make_array_type (dhandle,
|
||
|
ieee_builtin_type (dhandle, abfd, types,
|
||
|
bytes, p, 19),
|
||
|
ieee_builtin_type (dhandle, abfd, types,
|
||
|
bytes, p, 16),
|
||
|
0, -1, true);
|
||
|
name = "QUOTED STRING";
|
||
|
break;
|
||
|
|
||
|
case 47:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 15:
|
||
|
/* FIXME: This should be a code address. */
|
||
|
type = debug_make_int_type (dhandle, 4, true);
|
||
|
name = "instruction address";
|
||
|
break;
|
||
|
|
||
|
case 48:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 16:
|
||
|
/* FIXME: The size for this type should depend upon the
|
||
|
processor. */
|
||
|
type = debug_make_int_type (dhandle, 4, false);
|
||
|
name = "int";
|
||
|
break;
|
||
|
|
||
|
case 49:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 17:
|
||
|
/* FIXME: The size for this type should depend upon the
|
||
|
processor. */
|
||
|
type = debug_make_int_type (dhandle, 4, true);
|
||
|
name = "unsigned";
|
||
|
break;
|
||
|
|
||
|
case 50:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 18:
|
||
|
/* FIXME: The size for this type should depend upon the
|
||
|
processor. */
|
||
|
type = debug_make_int_type (dhandle, 4, true);
|
||
|
name = "unsigned int";
|
||
|
break;
|
||
|
|
||
|
case 51:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 19:
|
||
|
type = debug_make_int_type (dhandle, 1, false);
|
||
|
name = "char";
|
||
|
break;
|
||
|
|
||
|
case 52:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 20:
|
||
|
type = debug_make_int_type (dhandle, 4, false);
|
||
|
name = "long";
|
||
|
break;
|
||
|
|
||
|
case 53:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 21:
|
||
|
type = debug_make_int_type (dhandle, 2, false);
|
||
|
name = "short";
|
||
|
break;
|
||
|
|
||
|
case 54:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 22:
|
||
|
type = debug_make_int_type (dhandle, 2, true);
|
||
|
name = "unsigned short";
|
||
|
break;
|
||
|
|
||
|
case 55:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 23:
|
||
|
type = debug_make_int_type (dhandle, 2, false);
|
||
|
name = "short int";
|
||
|
break;
|
||
|
|
||
|
case 56:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 24:
|
||
|
type = debug_make_int_type (dhandle, 2, false);
|
||
|
name = "signed short";
|
||
|
break;
|
||
|
|
||
|
case 57:
|
||
|
ptr = true;
|
||
|
/* Fall through. */
|
||
|
case 25:
|
||
|
ieee_error (abfd, bytes, p, "BCD float type not supported");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (ptr)
|
||
|
type = debug_make_pointer_type (dhandle, type);
|
||
|
else if (name != NULL)
|
||
|
type = debug_name_type (dhandle, name, type);
|
||
|
|
||
|
assert (indx < BUILTIN_TYPE_COUNT);
|
||
|
|
||
|
types->builtins[indx] = type;
|
||
|
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
/* Read a type index and return the corresponding type. */
|
||
|
|
||
|
static boolean
|
||
|
ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, ptype)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_types *types;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
debug_type *ptype;
|
||
|
{
|
||
|
const bfd_byte *start;
|
||
|
bfd_vma indx;
|
||
|
|
||
|
start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &indx))
|
||
|
return false;
|
||
|
|
||
|
if (indx < 256)
|
||
|
{
|
||
|
*ptype = ieee_builtin_type (dhandle, abfd, types, bytes, start, indx);
|
||
|
if (*ptype == NULL)
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
indx -= 256;
|
||
|
if (indx >= types->alloc
|
||
|
|| types->types[indx].type == DEBUG_TYPE_NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "undefined type");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*ptype = types->types[indx].type;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Convert a register number in IEEE debugging information into a
|
||
|
generic register number. */
|
||
|
|
||
|
static int
|
||
|
ieee_regno_to_gen (abfd, r)
|
||
|
bfd *abfd;
|
||
|
int r;
|
||
|
{
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
/* Parse IEEE debugging information for a file. This is passed the
|
||
|
bytes which compose the Debug Information Part of an IEEE file. */
|
||
|
|
||
|
boolean
|
||
|
parse_ieee (dhandle, abfd, bytes, len)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
bfd_size_type len;
|
||
|
{
|
||
|
struct ieee_blockstack blockstack;
|
||
|
struct ieee_vars vars;
|
||
|
struct ieee_types types;
|
||
|
unsigned int i;
|
||
|
const bfd_byte *p, *pend;
|
||
|
|
||
|
blockstack.bsp = blockstack.stack;
|
||
|
vars.alloc = 0;
|
||
|
vars.vars = NULL;
|
||
|
types.alloc = 0;
|
||
|
types.types = NULL;
|
||
|
for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
|
||
|
types.builtins[i] = DEBUG_TYPE_NULL;
|
||
|
|
||
|
p = bytes;
|
||
|
pend = bytes + len;
|
||
|
while (p < pend)
|
||
|
{
|
||
|
const bfd_byte *record_start;
|
||
|
ieee_record_enum_type c;
|
||
|
|
||
|
record_start = p;
|
||
|
|
||
|
c = (ieee_record_enum_type) *p++;
|
||
|
|
||
|
if (c == ieee_at_record_enum)
|
||
|
c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
|
||
|
|
||
|
if (c <= ieee_number_repeat_end_enum)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, record_start, "unexpected number");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
switch (c)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, record_start, "unexpected record type");
|
||
|
return false;
|
||
|
|
||
|
case ieee_bb_record_enum:
|
||
|
if (! parse_ieee_bb (dhandle, abfd, &types, &blockstack, bytes,
|
||
|
&p, pend))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case ieee_be_record_enum:
|
||
|
if (! parse_ieee_be (dhandle, abfd, &blockstack, bytes, &p, pend))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case ieee_nn_record:
|
||
|
if (! parse_ieee_nn (dhandle, abfd, &vars, bytes, &p, pend))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case ieee_ty_record_enum:
|
||
|
if (! parse_ieee_ty (dhandle, abfd, &types, &vars, bytes, &p, pend))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case ieee_atn_record_enum:
|
||
|
if (! parse_ieee_atn (dhandle, abfd, &types, &vars,
|
||
|
(blockstack.bsp <= blockstack.stack
|
||
|
? 0
|
||
|
: blockstack.bsp[-1].kind),
|
||
|
bytes, &p, pend))
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (blockstack.bsp != blockstack.stack)
|
||
|
{
|
||
|
ieee_error (abfd, (const bfd_byte *) NULL, (const bfd_byte *) NULL,
|
||
|
"blocks left on stack at end");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Handle an IEEE BB record. */
|
||
|
|
||
|
static boolean
|
||
|
parse_ieee_bb (dhandle, abfd, types, blockstack, bytes, pp, pend)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_types *types;
|
||
|
struct ieee_blockstack *blockstack;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
{
|
||
|
const bfd_byte *block_start;
|
||
|
bfd_byte b;
|
||
|
bfd_vma size;
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
char *namcopy;
|
||
|
|
||
|
block_start = *pp;
|
||
|
|
||
|
b = **pp;
|
||
|
++*pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size)
|
||
|
|| ! ieee_read_id (abfd, bytes, pp, pend, &name, &namlen))
|
||
|
return false;
|
||
|
|
||
|
switch (b)
|
||
|
{
|
||
|
case 1:
|
||
|
/* BB1: Type definitions local to a module. */
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (namcopy == NULL)
|
||
|
return false;
|
||
|
if (! debug_set_filename (dhandle, namcopy))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
/* BB2: Global type definitions. The name is supposed to be
|
||
|
empty, but we don't check. */
|
||
|
if (! debug_set_filename (dhandle, "*global*"))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
/* BB3: High level module block begin. We don't have to do
|
||
|
anything here. The name is supposed to be the same as for
|
||
|
the BB1, but we don't check. */
|
||
|
break;
|
||
|
|
||
|
case 4:
|
||
|
/* BB4: Global function. */
|
||
|
{
|
||
|
bfd_vma stackspace, typindx, offset;
|
||
|
debug_type return_type;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &stackspace)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &typindx)
|
||
|
|| ! ieee_read_expression (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
|
||
|
/* We have no way to record the stack space. FIXME. */
|
||
|
|
||
|
if (typindx < 256)
|
||
|
{
|
||
|
return_type = ieee_builtin_type (dhandle, abfd, types, bytes,
|
||
|
block_start, typindx);
|
||
|
if (return_type == NULL)
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
typindx -= 256;
|
||
|
if (typindx >= types->alloc
|
||
|
|| types->types[typindx].type == DEBUG_TYPE_NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, block_start, "undefined type index");
|
||
|
return false;
|
||
|
}
|
||
|
return_type = types->types[typindx].return_type;
|
||
|
if (return_type == NULL)
|
||
|
return_type = types->types[typindx].type;
|
||
|
}
|
||
|
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (namcopy == NULL)
|
||
|
return false;
|
||
|
if (! debug_record_function (dhandle, namcopy, return_type,
|
||
|
true, offset))
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 5:
|
||
|
/* BB5: File name for source line numbers. */
|
||
|
{
|
||
|
unsigned int i;
|
||
|
|
||
|
/* We ignore the date and time. FIXME. */
|
||
|
for (i = 0; i < 6; i++)
|
||
|
{
|
||
|
bfd_vma ignore;
|
||
|
boolean present;
|
||
|
|
||
|
if (! ieee_read_optional_number (abfd, bytes, pp, pend, &ignore,
|
||
|
&present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (namcopy == NULL)
|
||
|
return false;
|
||
|
if (! debug_start_source (dhandle, namcopy))
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 6:
|
||
|
/* BB6: Local function or block. */
|
||
|
{
|
||
|
bfd_vma stackspace, typindx, offset;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &stackspace)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &typindx)
|
||
|
|| ! ieee_read_expression (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
|
||
|
/* We have no way to record the stack space. FIXME. */
|
||
|
|
||
|
if (namlen == 0)
|
||
|
{
|
||
|
if (! debug_start_block (dhandle, offset))
|
||
|
return false;
|
||
|
/* Change b to indicate that this is a block
|
||
|
rather than a function. */
|
||
|
b = 0x86;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
debug_type return_type;
|
||
|
|
||
|
if (typindx < 256)
|
||
|
{
|
||
|
return_type = ieee_builtin_type (dhandle, abfd, types, bytes,
|
||
|
block_start, typindx);
|
||
|
if (return_type == NULL)
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
typindx -= 256;
|
||
|
if (typindx >= types->alloc
|
||
|
|| types->types[typindx].type == DEBUG_TYPE_NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, block_start,
|
||
|
"undefined type index");
|
||
|
return false;
|
||
|
}
|
||
|
return_type = types->types[typindx].return_type;
|
||
|
if (return_type == NULL)
|
||
|
return_type = types->types[typindx].type;
|
||
|
}
|
||
|
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (namcopy == NULL)
|
||
|
return false;
|
||
|
if (! debug_record_function (dhandle, namcopy, return_type,
|
||
|
false, offset))
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 10:
|
||
|
/* BB10: Assembler module scope. We completely ignore all this
|
||
|
information. FIXME. */
|
||
|
{
|
||
|
const char *inam, *vstr;
|
||
|
unsigned long inamlen, vstrlen;
|
||
|
bfd_vma tool_type;
|
||
|
boolean present;
|
||
|
unsigned int i;
|
||
|
|
||
|
if (! ieee_read_id (abfd, bytes, pp, pend, &inam, &inamlen)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &tool_type)
|
||
|
|| ! ieee_read_optional_id (abfd, bytes, pp, pend, &vstr, &vstrlen,
|
||
|
&present))
|
||
|
return false;
|
||
|
for (i = 0; i < 6; i++)
|
||
|
{
|
||
|
bfd_vma ignore;
|
||
|
|
||
|
if (! ieee_read_optional_number (abfd, bytes, pp, pend, &ignore,
|
||
|
&present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 11:
|
||
|
/* BB11: Module section. We completely ignore all this
|
||
|
information. FIXME. */
|
||
|
{
|
||
|
bfd_vma sectype, secindx, offset, map;
|
||
|
boolean present;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, §ype)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &secindx)
|
||
|
|| ! ieee_read_expression (abfd, bytes, pp, pend, &offset)
|
||
|
|| ! ieee_read_optional_number (abfd, bytes, pp, pend, &map,
|
||
|
&present))
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, block_start, "unknown BB type");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Push this block on the block stack. */
|
||
|
|
||
|
if (blockstack->bsp >= blockstack->stack + BLOCKSTACK_SIZE)
|
||
|
{
|
||
|
ieee_error (abfd, (const bfd_byte *) NULL, (const bfd_byte *) NULL,
|
||
|
"stack overflow");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
blockstack->bsp->kind = b;
|
||
|
if (b == 5)
|
||
|
blockstack->bsp->filename = namcopy;
|
||
|
++blockstack->bsp;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Handle an IEEE BE record. */
|
||
|
|
||
|
static boolean
|
||
|
parse_ieee_be (dhandle, abfd, blockstack, bytes, pp, pend)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_blockstack *blockstack;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
{
|
||
|
bfd_vma offset;
|
||
|
|
||
|
if (blockstack->bsp <= blockstack->stack)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, *pp, "stack underflow");
|
||
|
return false;
|
||
|
}
|
||
|
--blockstack->bsp;
|
||
|
|
||
|
switch (blockstack->bsp->kind)
|
||
|
{
|
||
|
case 4:
|
||
|
case 6:
|
||
|
if (! ieee_read_expression (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
if (! debug_end_function (dhandle, offset))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case 0x86:
|
||
|
/* This is BE6 when BB6 started a block rather than a local
|
||
|
function. */
|
||
|
if (! ieee_read_expression (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
if (! debug_end_block (dhandle, offset))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case 5:
|
||
|
/* When we end a BB5, we look up the stack for the last BB5, if
|
||
|
there is one, so that we can call debug_start_source. */
|
||
|
if (blockstack->bsp > blockstack->stack)
|
||
|
{
|
||
|
struct ieee_block *bl;
|
||
|
|
||
|
bl = blockstack->bsp;
|
||
|
do
|
||
|
{
|
||
|
--bl;
|
||
|
if (bl->kind == 5)
|
||
|
{
|
||
|
if (! debug_start_source (dhandle, bl->filename))
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
while (bl != blockstack->stack);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 11:
|
||
|
if (! ieee_read_expression (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
/* We just ignore the module size. FIXME. */
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* Other block types do not have any trailing information. */
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Parse an NN record. */
|
||
|
|
||
|
static boolean
|
||
|
parse_ieee_nn (dhandle, abfd, vars, bytes, pp, pend)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_vars *vars;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
{
|
||
|
const bfd_byte *nn_start;
|
||
|
bfd_vma varindx;
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
|
||
|
nn_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &varindx)
|
||
|
|| ! ieee_read_id (abfd, bytes, pp, pend, &name, &namlen))
|
||
|
return false;
|
||
|
|
||
|
if (varindx < 32)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, nn_start, "illegal variable index");
|
||
|
return false;
|
||
|
}
|
||
|
varindx -= 32;
|
||
|
|
||
|
if (varindx >= vars->alloc)
|
||
|
{
|
||
|
unsigned int alloc;
|
||
|
|
||
|
alloc = vars->alloc;
|
||
|
if (alloc == 0)
|
||
|
alloc = 4;
|
||
|
while (varindx >= alloc)
|
||
|
alloc *= 2;
|
||
|
vars->vars = ((struct ieee_var *)
|
||
|
xrealloc (vars->vars, alloc * sizeof *vars->vars));
|
||
|
memset (vars->vars + vars->alloc, 0,
|
||
|
(alloc - vars->alloc) * sizeof *vars->vars);
|
||
|
vars->alloc = alloc;
|
||
|
}
|
||
|
|
||
|
vars->vars[varindx].name = name;
|
||
|
vars->vars[varindx].namlen = namlen;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Parse a TY record. */
|
||
|
|
||
|
static boolean
|
||
|
parse_ieee_ty (dhandle, abfd, types, vars, bytes, pp, pend)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_types *types;
|
||
|
struct ieee_vars *vars;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
{
|
||
|
const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
|
||
|
bfd_vma typeindx, varindx, tc;
|
||
|
debug_type type;
|
||
|
boolean tag, typdef;
|
||
|
unsigned long type_bitsize;
|
||
|
debug_type return_type;
|
||
|
|
||
|
ty_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &typeindx))
|
||
|
return false;
|
||
|
|
||
|
if (typeindx < 256)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, ty_start, "illegal type index");
|
||
|
return false;
|
||
|
}
|
||
|
typeindx -= 256;
|
||
|
|
||
|
if (typeindx >= types->alloc)
|
||
|
{
|
||
|
unsigned int nalloc;
|
||
|
struct ieee_type *t, *tend;
|
||
|
|
||
|
nalloc = types->alloc;
|
||
|
if (nalloc == 0)
|
||
|
nalloc = 4;
|
||
|
while (typeindx >= nalloc)
|
||
|
nalloc *= 2;
|
||
|
types->types = ((struct ieee_type *)
|
||
|
xrealloc (types->types, nalloc * sizeof *types->types));
|
||
|
tend = types->types + nalloc;
|
||
|
for (t = types->types + types->alloc; t < tend; t++)
|
||
|
{
|
||
|
t->bitsize = 0;
|
||
|
t->type = DEBUG_TYPE_NULL;
|
||
|
}
|
||
|
types->alloc = nalloc;
|
||
|
}
|
||
|
|
||
|
if (**pp != 0xce)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, *pp, "unknown TY code");
|
||
|
return false;
|
||
|
}
|
||
|
++*pp;
|
||
|
|
||
|
ty_var_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &varindx))
|
||
|
return false;
|
||
|
|
||
|
if (varindx < 32)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, ty_var_start, "illegal variable index");
|
||
|
return false;
|
||
|
}
|
||
|
varindx -= 32;
|
||
|
|
||
|
if (varindx >= vars->alloc || vars->vars[varindx].name == NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, ty_var_start, "undefined variable in TY");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
ty_code_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &tc))
|
||
|
return false;
|
||
|
|
||
|
tag = false;
|
||
|
typdef = false;
|
||
|
type_bitsize = 0;
|
||
|
return_type = DEBUG_TYPE_NULL;
|
||
|
switch (tc)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, ty_code_start, "unknown TY code");
|
||
|
return false;
|
||
|
|
||
|
case '!':
|
||
|
/* Unknown type, with size. We treat it as int. FIXME. */
|
||
|
{
|
||
|
bfd_vma size;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size))
|
||
|
return false;
|
||
|
type = debug_make_int_type (dhandle, size, false);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'A': /* Array. */
|
||
|
case 'a': /* FORTRAN array in column/row order. FIXME: Not
|
||
|
distinguished from normal array. */
|
||
|
{
|
||
|
debug_type ele_type;
|
||
|
bfd_vma lower, upper;
|
||
|
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&ele_type)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &lower)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &upper))
|
||
|
return false;
|
||
|
type = debug_make_array_type (dhandle, ele_type,
|
||
|
debug_make_int_type (dhandle, 4, false),
|
||
|
(bfd_signed_vma) lower,
|
||
|
(bfd_signed_vma) upper,
|
||
|
false);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'E':
|
||
|
/* Simple enumeration. */
|
||
|
{
|
||
|
bfd_vma size;
|
||
|
unsigned int alloc;
|
||
|
const char **names;
|
||
|
unsigned int c;
|
||
|
bfd_signed_vma *vals;
|
||
|
unsigned int i;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size))
|
||
|
return false;
|
||
|
/* FIXME: we ignore the enumeration size. */
|
||
|
|
||
|
alloc = 10;
|
||
|
names = (const char **) xmalloc (alloc * sizeof *names);
|
||
|
memset (names, 0, alloc * sizeof *names);
|
||
|
c = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
boolean present;
|
||
|
|
||
|
if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name,
|
||
|
&namlen, &present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
|
||
|
if (c + 1 >= alloc)
|
||
|
{
|
||
|
alloc += 10;
|
||
|
names = ((const char **)
|
||
|
xrealloc (names, alloc * sizeof *names));
|
||
|
}
|
||
|
|
||
|
names[c] = savestring (name, namlen);
|
||
|
if (names[c] == NULL)
|
||
|
return false;
|
||
|
++c;
|
||
|
}
|
||
|
|
||
|
names[c] = NULL;
|
||
|
|
||
|
vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
|
||
|
for (i = 0; i < c; i++)
|
||
|
vals[i] = i;
|
||
|
|
||
|
type = debug_make_enum_type (dhandle, names, vals);
|
||
|
tag = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'G':
|
||
|
/* Struct with bit fields. */
|
||
|
{
|
||
|
bfd_vma size;
|
||
|
unsigned int alloc;
|
||
|
debug_field *fields;
|
||
|
unsigned int c;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size))
|
||
|
return false;
|
||
|
|
||
|
alloc = 10;
|
||
|
fields = (debug_field *) xmalloc (alloc * sizeof *fields);
|
||
|
c = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
boolean present;
|
||
|
debug_type ftype;
|
||
|
bfd_vma bitpos, bitsize;
|
||
|
|
||
|
if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name,
|
||
|
&namlen, &present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&ftype)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &bitpos)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &bitsize))
|
||
|
return false;
|
||
|
|
||
|
if (c + 1 >= alloc)
|
||
|
{
|
||
|
alloc += 10;
|
||
|
fields = ((debug_field *)
|
||
|
xrealloc (fields, alloc * sizeof *fields));
|
||
|
}
|
||
|
|
||
|
fields[c] = debug_make_field (dhandle, savestring (name, namlen),
|
||
|
ftype, bitpos, bitsize,
|
||
|
DEBUG_VISIBILITY_PUBLIC);
|
||
|
if (fields[c] == NULL)
|
||
|
return false;
|
||
|
++c;
|
||
|
}
|
||
|
|
||
|
fields[c] = NULL;
|
||
|
|
||
|
type = debug_make_struct_type (dhandle, true, size, fields);
|
||
|
tag = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'N':
|
||
|
/* Enumeration. */
|
||
|
{
|
||
|
unsigned int alloc;
|
||
|
const char **names;
|
||
|
bfd_signed_vma *vals;
|
||
|
unsigned int c;
|
||
|
|
||
|
alloc = 10;
|
||
|
names = (const char **) xmalloc (alloc * sizeof *names);
|
||
|
vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
|
||
|
c = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
boolean present;
|
||
|
bfd_vma val;
|
||
|
|
||
|
if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name,
|
||
|
&namlen, &present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &val))
|
||
|
return false;
|
||
|
|
||
|
/* If the length of the name is zero, then the value is
|
||
|
actually the size of the enum. We ignore this
|
||
|
information. FIXME. */
|
||
|
if (namlen == 0)
|
||
|
continue;
|
||
|
|
||
|
if (c + 1 >= alloc)
|
||
|
{
|
||
|
alloc += 10;
|
||
|
names = ((const char **)
|
||
|
xrealloc (names, alloc * sizeof *names));
|
||
|
vals = ((bfd_signed_vma *)
|
||
|
xrealloc (vals, alloc * sizeof *vals));
|
||
|
}
|
||
|
|
||
|
names[c] = savestring (name, namlen);
|
||
|
if (names[c] == NULL)
|
||
|
return false;
|
||
|
vals[c] = (bfd_signed_vma) val;
|
||
|
++c;
|
||
|
}
|
||
|
|
||
|
names[c] = NULL;
|
||
|
|
||
|
type = debug_make_enum_type (dhandle, names, vals);
|
||
|
tag = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'O': /* Small pointer. We don't distinguish small and large
|
||
|
pointers. FIXME. */
|
||
|
case 'P': /* Large pointer. */
|
||
|
{
|
||
|
debug_type t;
|
||
|
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, &t))
|
||
|
return false;
|
||
|
type = debug_make_pointer_type (dhandle, t);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'R':
|
||
|
/* Range. */
|
||
|
{
|
||
|
bfd_vma low, high, signedp, size;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &low)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &high)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &signedp)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &size))
|
||
|
return false;
|
||
|
|
||
|
type = debug_make_range_type (dhandle,
|
||
|
debug_make_int_type (dhandle, size,
|
||
|
! signedp),
|
||
|
(bfd_signed_vma) low,
|
||
|
(bfd_signed_vma) high);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'S': /* Struct. */
|
||
|
case 'U': /* Union. */
|
||
|
{
|
||
|
bfd_vma size;
|
||
|
unsigned int alloc;
|
||
|
debug_field *fields;
|
||
|
unsigned int c;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size))
|
||
|
return false;
|
||
|
|
||
|
alloc = 10;
|
||
|
fields = (debug_field *) xmalloc (alloc * sizeof *fields);
|
||
|
c = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
boolean present;
|
||
|
bfd_vma tindx;
|
||
|
bfd_vma offset;
|
||
|
debug_type ftype;
|
||
|
bfd_vma bitsize;
|
||
|
|
||
|
if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name,
|
||
|
&namlen, &present))
|
||
|
return false;
|
||
|
if (! present)
|
||
|
break;
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &tindx)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &offset))
|
||
|
return false;
|
||
|
|
||
|
if (tindx < 256)
|
||
|
{
|
||
|
ftype = ieee_builtin_type (dhandle, abfd, types, bytes,
|
||
|
ty_code_start, tindx);
|
||
|
bitsize = 0;
|
||
|
offset *= 8;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
struct ieee_type *t;
|
||
|
|
||
|
tindx -= 256;
|
||
|
if (tindx >= types->alloc
|
||
|
|| types->types[tindx].type == DEBUG_TYPE_NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, ty_start, "undefined type index");
|
||
|
return false;
|
||
|
}
|
||
|
t = &types->types[tindx];
|
||
|
ftype = t->type;
|
||
|
bitsize = t->bitsize;
|
||
|
if (bitsize == 0)
|
||
|
offset *= 8;
|
||
|
}
|
||
|
|
||
|
if (c + 1 >= alloc)
|
||
|
{
|
||
|
alloc += 10;
|
||
|
fields = ((debug_field *)
|
||
|
xrealloc (fields, alloc * sizeof *fields));
|
||
|
}
|
||
|
|
||
|
fields[c] = debug_make_field (dhandle, savestring (name, namlen),
|
||
|
ftype, offset, bitsize,
|
||
|
DEBUG_VISIBILITY_PUBLIC);
|
||
|
if (fields[c] == NULL)
|
||
|
return false;
|
||
|
++c;
|
||
|
}
|
||
|
|
||
|
fields[c] = NULL;
|
||
|
|
||
|
type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
|
||
|
tag = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'T':
|
||
|
/* Typedef. */
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&type))
|
||
|
return false;
|
||
|
typdef = true;
|
||
|
break;
|
||
|
|
||
|
case 'X':
|
||
|
/* Procedure. FIXME: This is an extern declaration, which we
|
||
|
have no way of representing. */
|
||
|
{
|
||
|
bfd_vma attr;
|
||
|
debug_type rtype;
|
||
|
bfd_vma nargs;
|
||
|
boolean present;
|
||
|
|
||
|
/* FIXME: We ignore the attribute and the argument names. */
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &attr)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&rtype)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &nargs))
|
||
|
return false;
|
||
|
do
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
|
||
|
if (! ieee_read_optional_id (abfd, bytes, pp, pend, &name,
|
||
|
&namlen, &present))
|
||
|
return false;
|
||
|
}
|
||
|
while (present);
|
||
|
|
||
|
type = debug_make_function_type (dhandle, rtype);
|
||
|
return_type = rtype;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'Z':
|
||
|
/* Array with 0 lower bound. */
|
||
|
{
|
||
|
debug_type etype;
|
||
|
bfd_vma high;
|
||
|
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&etype)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &high))
|
||
|
return false;
|
||
|
|
||
|
type = debug_make_array_type (dhandle, etype,
|
||
|
debug_make_int_type (dhandle, 4, false),
|
||
|
0, (bfd_signed_vma) high, false);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'c': /* Complex. */
|
||
|
case 'd': /* Double complex. */
|
||
|
{
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
|
||
|
/* FIXME: I don't know what the name means. */
|
||
|
|
||
|
if (! ieee_read_id (abfd, bytes, pp, pend, &name, &namlen))
|
||
|
return false;
|
||
|
|
||
|
type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'f':
|
||
|
/* Pascal file name. FIXME. */
|
||
|
ieee_error (abfd, bytes, ty_code_start,
|
||
|
"Pascal file name not supported");
|
||
|
return false;
|
||
|
|
||
|
case 'g':
|
||
|
/* Bitfield type. */
|
||
|
{
|
||
|
bfd_vma signedp, bitsize;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &signedp)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &bitsize)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&type))
|
||
|
return false;
|
||
|
|
||
|
/* FIXME: This is just a guess. */
|
||
|
if (! signedp)
|
||
|
type = debug_make_int_type (dhandle, 4, true);
|
||
|
type_bitsize = bitsize;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'n':
|
||
|
/* Qualifier. */
|
||
|
{
|
||
|
bfd_vma kind;
|
||
|
debug_type t;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &kind)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&t))
|
||
|
return false;
|
||
|
|
||
|
switch (kind)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, ty_start, "unsupported qualifer");
|
||
|
return false;
|
||
|
|
||
|
case 1:
|
||
|
type = debug_make_const_type (dhandle, t);
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
type = debug_make_volatile_type (dhandle, t);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 's':
|
||
|
/* Set. */
|
||
|
{
|
||
|
bfd_vma size;
|
||
|
debug_type etype;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &size)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&etype))
|
||
|
return false;
|
||
|
|
||
|
/* FIXME: We ignore the size. */
|
||
|
|
||
|
type = debug_make_set_type (dhandle, etype, false);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'x':
|
||
|
/* Procedure with compiler dependencies. FIXME: This is an
|
||
|
extern declaration, which we have no way of representing. */
|
||
|
{
|
||
|
bfd_vma attr, frame_type, push_mask, nargs, level, father;
|
||
|
debug_type rtype;
|
||
|
boolean present;
|
||
|
|
||
|
/* FIXME: We ignore almost all this information. */
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &attr)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &frame_type)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &push_mask)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend,
|
||
|
&rtype)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &nargs))
|
||
|
return false;
|
||
|
if (nargs != (bfd_vma) -1)
|
||
|
{
|
||
|
for (; nargs > 0; nargs--)
|
||
|
{
|
||
|
debug_type atype;
|
||
|
|
||
|
if (! ieee_read_type_index (dhandle, abfd, types, bytes, pp,
|
||
|
pend, &atype))
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &level)
|
||
|
|| ! ieee_read_optional_number (abfd, bytes, pp, pend, &father,
|
||
|
&present))
|
||
|
return false;
|
||
|
|
||
|
type = debug_make_function_type (dhandle, rtype);
|
||
|
return_type = rtype;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Record the type in the table. If the corresponding NN record has
|
||
|
a name, name it. FIXME: Is this always correct? */
|
||
|
|
||
|
if (type == NULL)
|
||
|
return false;
|
||
|
|
||
|
if ((tag || typdef)
|
||
|
&& vars->vars[varindx].namlen > 0)
|
||
|
{
|
||
|
const char *name;
|
||
|
|
||
|
name = savestring (vars->vars[varindx].name,
|
||
|
vars->vars[varindx].namlen);
|
||
|
if (tag)
|
||
|
type = debug_tag_type (dhandle, name, type);
|
||
|
else
|
||
|
type = debug_name_type (dhandle, name, type);
|
||
|
if (type == NULL)
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
types->types[typeindx].type = type;
|
||
|
types->types[typeindx].bitsize = type_bitsize;
|
||
|
types->types[typeindx].return_type = return_type;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/* Parse an ATN record. */
|
||
|
|
||
|
static boolean
|
||
|
parse_ieee_atn (dhandle, abfd, types, vars, blocktype, bytes, pp, pend)
|
||
|
PTR dhandle;
|
||
|
bfd *abfd;
|
||
|
struct ieee_types *types;
|
||
|
struct ieee_vars *vars;
|
||
|
int blocktype;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
{
|
||
|
const bfd_byte *atn_start, *atn_code_start;
|
||
|
bfd_vma varindx;
|
||
|
boolean zeroindx;
|
||
|
debug_type type;
|
||
|
bfd_vma atn_code;
|
||
|
bfd_vma v, v2, v3, v4, v5;
|
||
|
const char *name;
|
||
|
unsigned long namlen;
|
||
|
char *namcopy;
|
||
|
boolean present;
|
||
|
|
||
|
atn_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &varindx)
|
||
|
|| ! ieee_read_type_index (dhandle, abfd, types, bytes, pp, pend, &type))
|
||
|
return false;
|
||
|
|
||
|
atn_code_start = *pp;
|
||
|
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &atn_code))
|
||
|
return false;
|
||
|
|
||
|
if (varindx == 0)
|
||
|
{
|
||
|
zeroindx = true;
|
||
|
name = "";
|
||
|
namlen = 0;
|
||
|
}
|
||
|
else if (varindx < 32)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, atn_start, "illegal variable index");
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
varindx -= 32;
|
||
|
zeroindx = false;
|
||
|
if (varindx >= vars->alloc || vars->vars[varindx].name == NULL)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, atn_start, "undefined variable in ATN");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
vars->vars[varindx].type = type;
|
||
|
|
||
|
name = vars->vars[varindx].name;
|
||
|
namlen = vars->vars[varindx].namlen;
|
||
|
}
|
||
|
|
||
|
switch (atn_code)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, atn_code_start, "unknown ATN type");
|
||
|
return false;
|
||
|
|
||
|
case 1:
|
||
|
/* Automatic variable. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v))
|
||
|
return false;
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (type == NULL)
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
|
||
|
|
||
|
case 2:
|
||
|
/* Register variable. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v))
|
||
|
return false;
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (type == NULL)
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
|
||
|
ieee_regno_to_gen (abfd, v));
|
||
|
|
||
|
case 3:
|
||
|
/* Static variable. */
|
||
|
if (! ieee_require_asn (abfd, bytes, pp, pend, &v))
|
||
|
return false;
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (type == NULL)
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
return debug_record_variable (dhandle, namcopy, type,
|
||
|
(blocktype == 4 || blocktype == 6
|
||
|
? DEBUG_LOCAL_STATIC
|
||
|
: DEBUG_STATIC),
|
||
|
v);
|
||
|
|
||
|
case 4:
|
||
|
/* External function. We don't currently record these. FIXME. */
|
||
|
return true;
|
||
|
|
||
|
case 5:
|
||
|
/* External variable. We don't currently record these. FIXME. */
|
||
|
return true;
|
||
|
|
||
|
case 7:
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &v2)
|
||
|
|| ! ieee_read_optional_number (abfd, bytes, pp, pend, &v3,
|
||
|
&present))
|
||
|
return false;
|
||
|
if (present)
|
||
|
{
|
||
|
if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v4,
|
||
|
&present))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* We just ignore the two optional fields in v3 and v4, since
|
||
|
they are not defined. */
|
||
|
|
||
|
if (! ieee_require_asn (abfd, bytes, pp, pend, &v3))
|
||
|
return false;
|
||
|
|
||
|
/* We have no way to record the column number. FIXME. */
|
||
|
|
||
|
return debug_record_line (dhandle, v, v3);
|
||
|
|
||
|
case 8:
|
||
|
/* Global variable. */
|
||
|
if (! ieee_require_asn (abfd, bytes, pp, pend, &v))
|
||
|
return false;
|
||
|
namcopy = savestring (name, namlen);
|
||
|
if (type == NULL)
|
||
|
type = debug_make_void_type (dhandle);
|
||
|
return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
|
||
|
|
||
|
case 9:
|
||
|
/* Variable lifetime information. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v))
|
||
|
return false;
|
||
|
|
||
|
/* We have no way to record this information. FIXME. */
|
||
|
return true;
|
||
|
|
||
|
case 10:
|
||
|
/* Locked register. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &v2))
|
||
|
return false;
|
||
|
|
||
|
/* I don't know what this means. FIXME. */
|
||
|
|
||
|
ieee_error (abfd, bytes, atn_code_start, "unsupported ATN10");
|
||
|
|
||
|
/* Return true to keep going. */
|
||
|
return true;
|
||
|
|
||
|
case 11:
|
||
|
/* Reserved for FORTRAN common. */
|
||
|
ieee_error (abfd, bytes, atn_code_start, "unsupported ATN11");
|
||
|
|
||
|
/* Return true to keep going. */
|
||
|
return true;
|
||
|
|
||
|
case 12:
|
||
|
/* Based variable. */
|
||
|
v3 = 0;
|
||
|
v4 = 0x80;
|
||
|
v5 = 0;
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &v2)
|
||
|
|| ! ieee_read_optional_number (abfd, bytes, pp, pend, &v3,
|
||
|
&present))
|
||
|
return false;
|
||
|
if (present)
|
||
|
{
|
||
|
if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v4,
|
||
|
&present))
|
||
|
return false;
|
||
|
if (present)
|
||
|
{
|
||
|
if (! ieee_read_optional_number (abfd, bytes, pp, pend, &v5,
|
||
|
&present))
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* We have no way to record this information. FIXME. */
|
||
|
|
||
|
ieee_error (abfd, bytes, atn_code_start, "unsupported ATN12");
|
||
|
|
||
|
/* Return true to keep going. */
|
||
|
return true;
|
||
|
|
||
|
case 16:
|
||
|
/* Constant. The description of this that I have is ambiguous,
|
||
|
so I'm not going to try to implement it. */
|
||
|
ieee_error (abfd, bytes, atn_code_start, "unsupported ATN16");
|
||
|
return false;
|
||
|
|
||
|
case 19:
|
||
|
/* Static variable from assembler. */
|
||
|
v2 = 0;
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v)
|
||
|
|| ! ieee_read_optional_number (abfd, bytes, pp, pend, &v2,
|
||
|
&present)
|
||
|
|| ! ieee_require_asn (abfd, bytes, pp, pend, &v3))
|
||
|
return false;
|
||
|
namcopy = savestring (name, namlen);
|
||
|
/* We don't really handle this correctly. FIXME. */
|
||
|
return debug_record_variable (dhandle, namcopy,
|
||
|
debug_make_void_type (dhandle),
|
||
|
v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
|
||
|
v3);
|
||
|
|
||
|
case 62:
|
||
|
/* Procedure miscellaneous information. */
|
||
|
case 63:
|
||
|
/* Variable miscellaneous information. */
|
||
|
case 64:
|
||
|
/* Module miscellaneous information. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &v)
|
||
|
|| ! ieee_read_number (abfd, bytes, pp, pend, &v2)
|
||
|
|| ! ieee_read_optional_id (abfd, bytes, pp, pend, &name, &namlen,
|
||
|
&present))
|
||
|
return false;
|
||
|
|
||
|
/* We just ignore all of this stuff. FIXME. */
|
||
|
|
||
|
for (; v2 > 0; --v2)
|
||
|
{
|
||
|
ieee_record_enum_type c;
|
||
|
bfd_vma vindx;
|
||
|
const char *str;
|
||
|
unsigned long strlen;
|
||
|
|
||
|
c = (ieee_record_enum_type) **pp;
|
||
|
++*pp;
|
||
|
if (c != ieee_at_record_enum
|
||
|
&& c != ieee_e2_first_byte_enum)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, *pp - 1, "bad misc record");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
|
||
|
++*pp;
|
||
|
switch (c)
|
||
|
{
|
||
|
default:
|
||
|
ieee_error (abfd, bytes, *pp - 2, "bad misc record");
|
||
|
return false;
|
||
|
|
||
|
case ieee_atn_record_enum:
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &vindx))
|
||
|
return false;
|
||
|
if ((*pp)[0] != 0 || (*pp)[1] != 65)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, *pp, "bad atn in misc");
|
||
|
return false;
|
||
|
}
|
||
|
*pp += 2;
|
||
|
if (! ieee_read_id (abfd, bytes, pp, pend, &str, &strlen))
|
||
|
return false;
|
||
|
break;
|
||
|
|
||
|
case ieee_asn_record_enum:
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &vindx)
|
||
|
|| ! ieee_read_expression (abfd, bytes, pp, pend, &v3))
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*NOTREACHED*/
|
||
|
}
|
||
|
|
||
|
/* Require an ASN record. */
|
||
|
|
||
|
static boolean
|
||
|
ieee_require_asn (abfd, bytes, pp, pend, pv)
|
||
|
bfd *abfd;
|
||
|
const bfd_byte *bytes;
|
||
|
const bfd_byte **pp;
|
||
|
const bfd_byte *pend;
|
||
|
bfd_vma *pv;
|
||
|
{
|
||
|
const bfd_byte *start;
|
||
|
ieee_record_enum_type c;
|
||
|
bfd_vma varindx;
|
||
|
|
||
|
start = *pp;
|
||
|
|
||
|
c = (ieee_record_enum_type) **pp;
|
||
|
if (c != ieee_e2_first_byte_enum)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "missing required ASN");
|
||
|
return false;
|
||
|
}
|
||
|
++*pp;
|
||
|
|
||
|
c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
|
||
|
if (c != ieee_asn_record_enum)
|
||
|
{
|
||
|
ieee_error (abfd, bytes, start, "missing required ASN");
|
||
|
return false;
|
||
|
}
|
||
|
++*pp;
|
||
|
|
||
|
/* Just ignore the variable index. */
|
||
|
if (! ieee_read_number (abfd, bytes, pp, pend, &varindx))
|
||
|
return false;
|
||
|
|
||
|
return ieee_read_expression (abfd, bytes, pp, pend, pv);
|
||
|
}
|