diff options
author | Ian Lance Taylor <ian@airs.com> | 1996-01-04 21:35:04 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1996-01-04 21:35:04 +0000 |
commit | f51679867952529ebbe8edbe20f34271989b384c (patch) | |
tree | 6542f4e7b290a92bb5e5de40382974fe517531cb /binutils/ieee.c | |
parent | f8254a3cc5d621c0362bceed642a8969db5fe161 (diff) | |
download | gdb-f51679867952529ebbe8edbe20f34271989b384c.zip gdb-f51679867952529ebbe8edbe20f34271989b384c.tar.gz gdb-f51679867952529ebbe8edbe20f34271989b384c.tar.bz2 |
* ieee.c: New file with code to read IEEE debugging information.
* budbg.h (parse_ieee): Declare.
* rddbg.c (read_debugging_info): Handle IEEE flavour files.
(read_ieee_debugging_info): New static function.
* Makefile.in: Rebuild dependencies.
(CFILES): Add ieee.c.
(OBJDUMP_OBJS): Add ieee.o.
Diffstat (limited to 'binutils/ieee.c')
-rw-r--r-- | binutils/ieee.c | 2178 |
1 files changed, 2178 insertions, 0 deletions
diff --git a/binutils/ieee.c b/binutils/ieee.c new file mode 100644 index 0000000..9f95d5c --- /dev/null +++ b/binutils/ieee.c @@ -0,0 +1,2178 @@ +/* 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); +} |