Merge Apollo patches from Troy Rollo (troy@cbme.unsw.edu.au):
authorJim Kingdon <jkingdon@engr.sgi.com>
Fri, 22 Oct 1993 16:03:08 +0000 (16:03 +0000)
committerJim Kingdon <jkingdon@engr.sgi.com>
Fri, 22 Oct 1993 16:03:08 +0000 (16:03 +0000)
* dst.h, dstread.c, config/m68k/{apollo68b.mt,tm-apollo68b.h}:
New files.
* config/m68k/nm-apollo68b.h: Add more defines.
* configure.in: Recognize apollo target, not just host.

gdb/ChangeLog
gdb/config/m68k/.Sanitize
gdb/config/m68k/apollo68b.mt
gdb/config/m68k/nm-apollo68b.h
gdb/config/m68k/tm-apollo68b.h
gdb/configure.in
gdb/dst.h
gdb/dstread.c

index 4a5b0157624dce7257026404dfaddc9fd55005a0..fb69c3e043a5d05bac7e4ba55f4f476d90a709ad 100644 (file)
@@ -1,5 +1,11 @@
 Fri Oct 22 07:49:54 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
 
+       Merge Apollo patches from Troy Rollo (troy@cbme.unsw.edu.au):
+       * dst.h, dstread.c, config/m68k/{apollo68b.mt,tm-apollo68b.h}:
+       New files.
+       * config/m68k/nm-apollo68b.h: Add more defines.
+       * configure.in: Recognize apollo target, not just host.
+
        * configure.in: Add * to end of all OS names.
 
 Fri Oct 22 06:14:01 1993  Fred Fish  (fnf@cygnus.com)
index 9947f75c0eabc92fcf00732310811f3d8c2f99e1..9ebd0b4aca39d45546c3c9b7179a6bc8aa00e9ac 100644 (file)
@@ -28,6 +28,7 @@ altos.mt
 amix.mh
 amix.mt
 apollo68b.mh
+apollo68b.mt
 apollo68v.mh
 delta68.mh
 delta68.mt
@@ -65,6 +66,7 @@ sun3os3.mt
 sun3os4.mh
 sun3os4.mt
 tm-3b1.h
+tm-apollo68b.h
 tm-delta68.h
 tm-m68k-em.h
 tm-m68k.h
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e1fb1dce4085561c7d0a74b85406f8a47634795d 100644 (file)
@@ -0,0 +1,3 @@
+# Target: Apollo m68k in BSD mode
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o dstread.o
+TM_FILE= tm-apollo68b.h
index 6f28b62f4201c00420f836bdb02496658654bcb7..c90dfacbd889f536b8662322da48fda32722af3c 100644 (file)
@@ -21,3 +21,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define        FETCH_INFERIOR_REGISTERS
 
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 6
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+
+#define KERNEL_U_ADDR 0
+
+#undef FLOAT_INFO      /* No float info yet */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+       (addr) = (6 + 4 * (regno))
+
+/* Apollos don't really have a USER area,so trying to read it from the
+ * process address space will fail. It does support a read from a faked
+ * USER area using the "PEEKUSER" ptrace call.
+ */
+#define PT_READ_U 3
+
+#define        MEM_FNS_DECLARED        /* /usr/include/string.h can get it wrong */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd8fbfce8ec3c279df2cbf7c600e6a0cc7d70233 100644 (file)
@@ -0,0 +1,63 @@
+/* Parameters for execution on Apollo 68k running BSD.
+   Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Apollos use vector 0xb for the breakpoint vector */
+
+#define BPT_VECTOR 0xb
+
+/* Assume we have a coprocessor. If we don't, it still shouldn't hurt */
+
+#define        HAVE_68881 1
+
+#include "m68k/tm-m68k.h"
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
+
+/* These are the jmp_buf registers I could guess. There are 13 registers
+ * in the buffer. There are 8 data registers, 6 general address registers,
+ * the Frame Pointer, the Stack Pointer, the PC and the SR in the chip. I would
+ * guess that 12 is the SR, but we don't need that anyway. 0 and 1 have
+ * me stumped. 4 appears to be a5 for some unknown reason. If you care
+ * about this, disassemble setjmp to find out. But don't do it with gdb :)
+ */
+
+#undef JB_SP
+#undef JB_FP
+#undef JB_PC
+#undef JB_D0
+#undef JB_D1
+#undef JB_D2
+#undef JB_D3
+#undef JB_D4
+#undef JB_D5
+
+#define JB_SP 2
+#define JB_FP 3
+#define JB_PC 5
+#define JB_D0 6
+#define JB_D1 7
+#define JB_D2 8
+#define JB_D3 9
+#define JB_D4 10
+#define JB_D5 11
+
+/* How to decide if we're in a shared library function.  (Probably a wrong
+   definintion inherited from the VxWorks config file).  */
+#define        IN_SOLIB_TRAMPOLINE(pc, name) (name && strcmp(name, "<end_of_program>") == 0)
index a6a0c63cbe602e3ccaa07888c4d433fdfa671d8e..2766bb793ec7acbba9f6f6eab17b2fb3421aa85a 100644 (file)
@@ -222,6 +222,7 @@ m68*-hp-bsd*)               gdb_target=hp300bsd ;;
 m68*-hp-hpux*)         gdb_target=hp300hpux ;;
 
 m68*-altos-*)          gdb_target=altos ;;
+m68*-apollo*-bsd*)     gdb_target=apollo68b ;;
 m68*-att-*)            gdb_target=3b1 ;;
 m68*-ericsson-*)       gdb_target=es1800 ;;
 m68*-isi-*)            gdb_target=isi ;;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..252a3a86b8b10cab7e4a0025927d2c49b1bc579e 100644 (file)
--- a/gdb/dst.h
+++ b/gdb/dst.h
+/* <apollo/dst.h> */
+/* Apollo object module DST (debug symbol table) description */
+
+#ifndef apollo_dst_h
+#define apollo_dst_h 
+
+#if defined(apollo) && !defined(__GNUC__)
+#define ALIGNED1  __attribute( (aligned(1)) )
+#else
+/* Remove attribute directives from non-Apollo code: */
+#define ALIGNED1   /* nil */
+#endif
+
+
+
+/* Identification of this version of the debug symbol table.  Producers of the
+   debug symbol table must write these values into the version number field of
+   the compilation unit record in .blocks .
+*/
+#define dst_version_major    1    
+#define dst_version_minor    3    
+
+
+/*
+** Enumeration of debug record types appearing in .blocks and .symbols ...
+*/
+typedef enum
+    {
+    dst_typ_pad,                   /*  0 */
+    dst_typ_comp_unit,             /*  1 */
+    dst_typ_section_tab,           /*  2 */
+    dst_typ_file_tab,              /*  3 */
+    dst_typ_block,                 /*  4 */
+    dst_typ_5,
+    dst_typ_var,
+    dst_typ_pointer,               /*  7 */
+    dst_typ_array,                 /*  8 */
+    dst_typ_subrange,              /*  9 */
+    dst_typ_set,                   /* 10 */
+    dst_typ_implicit_enum,         /* 11 */
+    dst_typ_explicit_enum,         /* 12 */
+    dst_typ_short_rec,             /* 13 */
+    dst_typ_old_record,
+    dst_typ_short_union,           /* 15 */
+    dst_typ_old_union,
+    dst_typ_file,                  /* 17 */
+    dst_typ_offset,                /* 18 */
+    dst_typ_alias,                 /* 19 */
+    dst_typ_signature,             /* 20 */
+    dst_typ_21,
+    dst_typ_old_label,            /* 22 */
+    dst_typ_scope,                /* 23 */
+    dst_typ_end_scope,             /* 24 */
+    dst_typ_25,
+    dst_typ_26,
+    dst_typ_string_tab,            /* 27 */
+    dst_typ_global_name_tab,       /* 28 */
+    dst_typ_forward,               /* 29 */
+    dst_typ_aux_size,              /* 30 */
+    dst_typ_aux_align,             /* 31 */
+    dst_typ_aux_field_size,        /* 32 */
+    dst_typ_aux_field_off,         /* 33 */
+    dst_typ_aux_field_align,       /* 34 */
+    dst_typ_aux_qual,              /* 35 */
+    dst_typ_aux_var_bound,         /* 36 */
+    dst_typ_extension,             /* 37 */
+    dst_typ_string,                /* 38 */
+    dst_typ_old_entry,
+    dst_typ_const,                 /* 40 */
+    dst_typ_reference,             /* 41 */
+    dst_typ_record,                /* 42 */
+    dst_typ_union,                 /* 43 */
+    dst_typ_aux_type_deriv,        /* 44 */
+    dst_typ_locpool,               /* 45 */
+    dst_typ_variable,              /* 46 */
+    dst_typ_label,                 /* 47 */
+    dst_typ_entry,                 /* 48 */
+    dst_typ_aux_lifetime,          /* 49 */
+    dst_typ_aux_ptr_base,          /* 50 */
+    dst_typ_aux_src_range,         /* 51 */
+    dst_typ_aux_reg_val,           /* 52 */
+    dst_typ_aux_unit_names,        /* 53 */
+    dst_typ_aux_sect_info,         /* 54 */
+    dst_typ_END_OF_ENUM
+    }    
+    dst_rec_type_t;
+
+
+/*
+** Dummy bounds for variably dimensioned arrays:
+*/
+#define dst_dummy_array_size  100
+
+
+/*
+** Reference to another item in the symbol table.
+**
+** The value of a dst_rel_offset_t is the relative offset from the start of the
+** referencing record to the start of the referenced record, string, etc. 
+**
+** The value of a NIL dst_rel_offset_t is zero.
+*/
+
+typedef long dst_rel_offset_t  ALIGNED1;
+
+
+/* FIXME: Here and many places we make assumptions about sizes of host
+   data types, structure layout, etc.  Only needs to be fixed if we care
+   about cross-debugging, though.  */
+
+/*
+** Section-relative reference. 
+**
+** The section index field is an index into the local compilation unit's
+** section table (see dst_rec_section_tab_t)--NOT into the object module
+** section table!
+**
+** The sect_offset field is the offset in bytes into the section.
+**
+** A NIL dst_sect_ref_t has a sect_index field of zero.  Indexes originate
+** at one.
+*/
+
+typedef struct
+    {
+    unsigned short  sect_index;
+    unsigned long   sect_offset ALIGNED1;
+    }
+    dst_sect_ref_t;
+
+#define dst_sect_index_nil    0
+#define dst_sect_index_origin 1
+
+
+/*
+** Source location descriptor.
+**
+** The file_index field is an index into the local compilation unit's
+** file table (see dst_rec_file_tab_t).
+**
+** A NIL dst_src_loc_t has a file_index field of zero.  Indexes originate
+** at one.
+*/
+
+typedef struct
+    {
+    boolean  reserved    :  1;  /* reserved for future use */
+    int      file_index  : 11;  /* index into .blocks source file list */
+    int      line_number : 20;  /* source line number */
+    }
+    dst_src_loc_t;
+
+#define dst_file_index_nil    0
+#define dst_file_index_origin 1
+
+
+/*
+** Standard (primitive) type codes.
+*/
+
+typedef enum
+    {
+    dst_non_std_type,
+    dst_int8_type,         /* 8 bit integer */
+    dst_int16_type,        /* 16 bit integer */
+    dst_int32_type,        /* 32 bit integer */
+    dst_uint8_type,        /* 8 bit unsigned integer */
+    dst_uint16_type,       /* 16 bit unsigned integer */
+    dst_uint32_type,       /* 32 bit unsigned integer */
+    dst_real32_type,       /* single precision ieee floatining point */
+    dst_real64_type,       /* double precision ieee floatining point */
+    dst_complex_type,      /* single precision complex */    
+    dst_dcomplex_type,     /* double precision complex */
+    dst_bool8_type,        /* boolean =logical*1 */
+    dst_bool16_type,       /* boolean =logical*2 */
+    dst_bool32_type,       /* boolean =logical*4 */
+    dst_char_type,         /* 8 bit ascii character */
+    dst_string_type,       /* string of 8 bit ascii characters */
+    dst_ptr_type,          /* univ_pointer */
+    dst_set_type,          /* generic 256 bit set */
+    dst_proc_type,         /* generic procedure (signature not specified) */
+    dst_func_type,         /* generic function (signature not specified) */
+    dst_void_type,         /* c void type */
+    dst_uchar_type,        /* c unsigned char */
+    dst_std_type_END_OF_ENUM
+    }    
+    dst_std_type_t;
+
+
+/*
+** General data type descriptor
+**
+** If the user_defined_type bit is clear, then the type is a standard type, and
+** the remaining bits contain the dst_std_type_t of the type.  If the bit is
+** set, then the type is defined in a separate dst record, which is referenced
+** by the remaining bits as a dst_rel_offset_t.
+*/
+
+typedef union
+    {
+    struct
+        {
+        boolean         user_defined_type :  1;  /* tag field */
+        int             must_be_zero      : 23;  /* 23 bits of pad */
+        dst_std_type_t  dtc               :  8;  /* 8 bit primitive data */
+        }
+        std_type;
+   
+    struct
+        {
+        boolean         user_defined_type :  1;  /* tag field */
+        int             doffset           : 31;  /* offset to type record */
+        }
+        user_type;
+    }
+    dst_type_t ALIGNED1;
+
+/* The user_type.doffset field is a 31-bit signed value.  Some versions of C
+   do not support signed bit fields.  The following macro will extract that
+   field as a signed value:
+*/
+#define dst_user_type_offset(type_rec) \
+    ( ((int) ((type_rec).user_type.doffset << 1)) >> 1 )
+
+
+/*================================================*/
+/*========== RECORDS IN .blocks SECTION ==========*/
+/*================================================*/
+
+/*-----------------------
+  COMPILATION UNIT record 
+  -----------------------
+  This must be the first record in each .blocks section.
+  Provides a set of information describing the output of a single compilation
+  and pointers to additional information for the compilation unit.
+*/
+
+typedef enum
+    { 
+    dst_pc_code_locs,          /* ranges in loc strings are pc ranges */
+    dst_comp_unit_END_OF_ENUM
+    }    
+    dst_comp_unit_flag_t;
+
+typedef enum
+    {
+    dst_lang_unk,          /* unknown language */
+    dst_lang_pas,          /* Pascal */
+    dst_lang_ftn,          /* FORTRAN */
+    dst_lang_c,            /* C */
+    dst_lang_mod2,         /* Modula-2 */
+    dst_lang_asm_m68k,     /* 68K assembly language */
+    dst_lang_asm_a88k,     /* AT assembly language */
+    dst_lang_ada,          /* Ada */
+    dst_lang_cxx,          /* C++ */
+    dst_lang_END_OF_ENUM
+    }    
+    dst_lang_type_t;
+
+typedef struct
+    {
+    struct
+        {
+        unsigned char major_part;         /* = dst_version_major */
+        unsigned char minor_part;         /* = dst_version_minor */
+        }           
+        version;                          /* version of dst */
+    unsigned short    flags;              /* mask of dst_comp_unit_flag_t */
+    unsigned short   lang_type;          /* source language */
+    unsigned short    number_of_blocks;   /* number of blocks records */
+    dst_rel_offset_t  root_block_offset;  /* offset to root block (module?) */
+    dst_rel_offset_t  section_table       /* offset to section table record */;
+    dst_rel_offset_t  file_table;         /* offset to file table record */
+    unsigned long     data_size;          /* total size of .blocks data */
+    }
+    dst_rec_comp_unit_t ALIGNED1;
+
+
+/*--------------------
+  SECTION TABLE record
+  --------------------
+  There must be one section table associated with each compilation unit.
+  Other debug records refer to sections via their index in this table.  The
+  section base addresses in the table are virtual addresses of the sections,
+  relocated by the linker.
+*/
+
+typedef struct
+    {
+    unsigned short  number_of_sections;   /* size of array: */    
+    unsigned long   section_base[dst_dummy_array_size] ALIGNED1;
+    }
+    dst_rec_section_tab_t ALIGNED1;
+
+
+/*-----------------
+  FILE TABLE record
+  -----------------
+  There must be one file table associated with each compilation unit describing
+  the source (and include) files used by each compilation unit.  Other debug 
+  records refer to files via their index in this table.  The first entry is the
+  primary source file.
+*/
+
+typedef struct
+    {
+    long              dtm;        /* time last modified (time_$clock_t) */
+    dst_rel_offset_t  noffset;    /* offset to name string for source file */
+    }
+    dst_file_desc_t;
+
+typedef struct
+    {
+    unsigned short   number_of_files;    /* size of array: */
+    dst_file_desc_t  files[dst_dummy_array_size] ALIGNED1;
+    }
+    dst_rec_file_tab_t ALIGNED1;
+
+
+/*-----------------
+  NAME TABLE record
+  -----------------
+  A name table record may appear as an auxiliary record to the file table,
+  providing additional qualification of the file indexes for languages that 
+  need it (i.e. Ada).  Name table entries parallel file table entries of the
+  same file index.
+*/
+
+typedef struct
+    {
+    unsigned short    number_of_names;    /* size of array: */
+    dst_rel_offset_t  names[dst_dummy_array_size] ALIGNED1;
+    }
+    dst_rec_name_tab_t ALIGNED1;
+
+
+/*--------------
+  BLOCK record
+  --------------
+  Describes a lexical program block--a procedure, function, module, etc.
+*/
+
+/* Block types.  These may be used in any way desired by the compiler writers. 
+   The debugger uses them only to give a description to the user of the type of
+   a block.  The debugger makes no other assumptions about the meaning of any
+   of these.  For example, the fact that a block is executable (e.g., program)
+   or not (e.g., module) is expressed in block attributes (see below), not
+   guessed at from the block type.
+*/    
+typedef enum
+    {
+    dst_block_module,          /* some pascal = modula = ada types */
+    dst_block_program,         
+    dst_block_procedure,      
+    dst_block_function,        /* C function */
+    dst_block_subroutine,      /* some fortran block types */
+    dst_block_block_data,      
+    dst_block_stmt_function,  
+    dst_block_package,         /* a few particular to Ada */
+    dst_block_package_body,  
+    dst_block_subunit,        
+    dst_block_task,            
+    dst_block_file,            /* a C outer scope? */
+    dst_block_class,           /* C++ or Simula */
+    dst_block_END_OF_ENUM
+    }    
+    dst_block_type_t;
+
+/* Block attributes.  This is the information used by the debugger to represent
+   the semantics of blocks.
+*/
+typedef enum
+    {
+    dst_block_main_entry,      /* the block's entry point is a main entry into
+                                  the compilation unit */    
+    dst_block_executable,      /* the block has an entry point */
+    dst_block_attr_END_OF_ENUM
+    }    
+    dst_block_attr_t;
+
+/* Code range.  Each block has associated with it one or more code ranges. An
+   individual code range is identified by a range of source (possibly nil) and
+   a range of executable code.  For example, a block which has its executable
+   code spread over multiple sections will have one code range per section.
+*/
+typedef struct
+    {
+    unsigned long   code_size;      /* size of executable code (in bytes ) */
+    dst_sect_ref_t  code_start;     /* starting address of executable code */
+    dst_sect_ref_t  lines_start;    /* start of line number tables */
+    }
+    dst_code_range_t;
+
+typedef struct
+    {
+    dst_block_type_t  block_type : 8; 
+    unsigned short    flags      : 8;       /* mask of dst_block_attr_t flags */
+    dst_rel_offset_t  sibling_block_off;    /* offset to next sibling block */
+    dst_rel_offset_t  child_block_off;      /* offset to first contained block */
+    dst_rel_offset_t  noffset;              /* offset to block name string */    
+    dst_sect_ref_t    symbols_start;        /* start of debug symbols  */
+    unsigned short    n_of_code_ranges;     /* size of array... */
+    dst_code_range_t  code_ranges[dst_dummy_array_size] ALIGNED1;
+    }
+    dst_rec_block_t ALIGNED1;
+
+
+/*--------------------------
+  AUX SECT INFO TABLE record
+  --------------------------
+  Appears as an auxiliary to a block record.  Expands code range information
+  by providing references into additional, language-dependent sections for 
+  information related to specific code ranges of the block.  Sect info table
+  entries parallel code range array entries of the same index.
+*/
+
+typedef struct
+    {
+    unsigned char    tag;               /* currently can only be zero */
+    unsigned char    number_of_refs;    /* size of array: */
+    dst_sect_ref_t   refs[dst_dummy_array_size] ALIGNED1;
+    }
+    dst_rec_sect_info_tab_t ALIGNED1;
+
+/*=================================================*/
+/*========== RECORDS IN .symbols SECTION ==========*/
+/*=================================================*/
+
+/*-----------------
+  CONSTANT record
+  -----------------
+  Describes a symbolic constant.
+*/
+
+typedef struct
+    {
+    float    r;      /* real part */
+    float    i;      /* imaginary part */
+    }
+    dst_complex_t;
+
+typedef struct
+    {
+    double    dr;     /* real part */
+    double    di;     /* imaginary part */
+    }
+    dst_double_complex_t;
+
+/* The following record provides a way of describing constant values with 
+   non-standard type and no limit on size. 
+*/
+typedef union
+    {
+    char    char_data[dst_dummy_array_size];
+    short   int_data [dst_dummy_array_size];
+    long    long_data[dst_dummy_array_size];
+    }
+    dst_big_kon_t;
+
+/* Representation of the value of a general constant.
+*/
+typedef struct
+    {
+    unsigned short            length;     /* size of constant value (bytes) */
+
+    union
+        {
+        unsigned short        kon_int8;
+        short                 kon_int16;
+        long                  kon_int32   ALIGNED1;
+        float                 kon_real    ALIGNED1;
+        double                kon_dbl     ALIGNED1;
+        dst_complex_t         kon_cplx    ALIGNED1;
+        dst_double_complex_t  kon_dcplx   ALIGNED1;
+        char                  kon_char;
+        dst_big_kon_t         kon         ALIGNED1;
+        }                    
+        val;                              /* value data of constant */
+    }
+    dst_const_t ALIGNED1;
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* offset to name string */
+    dst_src_loc_t      src_loc;        /* file/line of const definition */
+    dst_type_t         type_desc;      /* type of this (manifest) constant */
+    dst_const_t        value; 
+    }
+    dst_rec_const_t ALIGNED1;
+
+/*----------------
+  VARIABLE record
+  ----------------
+  Describes a program variable.
+*/
+
+/* Variable attributes.  These define certain variable semantics to the
+   debugger.
+*/
+typedef enum
+    {
+    dst_var_attr_read_only,      /* is read-only (a program literal) */
+    dst_var_attr_volatile,       /* same as compiler's VOLATILE attribute */
+    dst_var_attr_global,         /* is a global definition or reference */    
+    dst_var_attr_compiler_gen,   /* is compiler-generated */
+    dst_var_attr_static,         /* has static location */
+    dst_var_attr_END_OF_ENUM
+    }    
+    dst_var_attr_t;
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;       /* offset to name string */
+    dst_rel_offset_t  loffset;       /* offset to loc string */
+    dst_src_loc_t     src_loc;       /* file/line of variable definition */
+    dst_type_t        type_desc;     /* type descriptor */
+    unsigned short    attributes;    /* mask of dst_var_attr_t flags */
+    }
+    dst_rec_variable_t ALIGNED1;
+
+
+/*----------------
+  old VAR record
+ -----------------
+ Used by older compilers to describe a variable
+*/
+
+typedef enum
+    {
+    dst_var_loc_unknown,       /* Actually defined as "unknown" */
+    dst_var_loc_abs,           /* Absolute address */
+    dst_var_loc_sect_off,      /* Absolute address as a section offset */
+    dst_var_loc_ind_sect_off,  /* An indexed section offset ???? */
+    dst_var_loc_reg,           /* register */
+    dst_var_loc_reg_rel,       /* register relative - usually fp */
+    dst_var_loc_ind_reg_rel,   /* Indexed register relative */
+    dst_var_loc_ftn_ptr_based, /* Fortran pointer based */
+    dst_var_loc_pc_rel,                /* PC relative. Really. */
+    dst_var_loc_external,      /* External */
+    dst_var_loc_END_OF_ENUM
+    }
+    dst_var_loc_t;
+
+/* Locations come in two versions. The sort, and the long. The difference
+ * between the short and the long is the addition of a statement number
+ * field to the start andend of the range of the long, and and unkown
+ * purpose field in the middle. Also, loc_type and loc_index aren't
+ * bitfields in the long version.
+ */
+
+typedef        struct
+    {
+    unsigned short     loc_type : 4;
+    unsigned short     loc_index : 12;
+    long               location;
+    short              start_line;     /* start_line and end_line? */
+    short              end_line;       /* I'm guessing here.       */
+    } dst_var_loc_short_t;
+
+typedef struct
+    {
+    unsigned short     loc_type;
+    unsigned short     loc_index;
+    long               location;
+    short              unknown;        /* Always 0003 or 3b3c. Why? */
+    short              start_statement;
+    short              start_line;
+    short              end_statement;
+    short              end_line;
+    } dst_var_loc_long_t;
+
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* offset to name string */
+    dst_src_loc_t      src_loc;        /* file/line of description */
+    dst_type_t         type_desc;      /* Type description */
+    unsigned short     attributes;     /* mask of dst_var_attr_t flags */
+    unsigned short     no_of_locs : 15;/* Number of locations */
+    unsigned short     short_locs : 1; /* True if short locations. */
+    union
+       {
+       dst_var_loc_short_t shorts[dst_dummy_array_size];
+       dst_var_loc_long_t longs[dst_dummy_array_size];
+       } locs;
+    } dst_rec_var_t;
+
+/*----------------
+  old LABEL record
+ -----------------
+ Used by older compilers to describe a label
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* offset to name string */
+    dst_src_loc_t      src_loc;        /* file/line of description */
+    char               location[12];   /* location string */
+    }
+    dst_rec_old_label_t ALIGNED1;
+
+/*----------------
+  POINTER record
+  ----------------
+  Describes a pointer type.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;    /* offset to the name string for this type */
+    dst_src_loc_t     src_loc;    /* file/line of definition */
+    dst_type_t        type_desc;  /* base type of this pointer */
+    }
+    dst_rec_pointer_t ALIGNED1;
+
+
+/*-------------
+  ARRAY record
+  -------------
+  Describes an array type.
+
+  Multidimensional arrays are described with a number of dst_rec_array_t 
+  records, one per array dimension, each linked to the next through the
+  elem_type_desc.doffset field.  Each record must have its multi_dim flag
+  set.
+
+  If column_major is true (as with FORTRAN arrays) then the last array bound in
+  the declaration is the first array index in memory, which is the opposite of
+  the usual case (as with Pascal and C arrays).
+
+  Variable array bounds are described by auxiliary records; if aux_var_bound
+  records are present, the lo_bound and hi_bound fields of this record are
+  ignored by the debugger.
+
+  span_comp identifies one of the language-dependent ways in which the distance
+  between successive array elements (span) is calculated.  
+     dst_use_span_field    -- the span is the value of span field.
+     dst_compute_from_prev -- the span is the size of the previous dimension.
+     dst_compute_from_next -- the span is the size of the next dimension.
+  In the latter two cases, the span field contains an amount of padding to add
+  to the size of the appropriate dimension to calculate the span.
+*/
+
+typedef enum
+    {
+    dst_use_span_field,  
+    dst_compute_from_prev,
+    dst_compute_from_next,        
+    dst_span_comp_END_OF_ENUM
+    }
+    dst_span_comp_t;
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;           /* offset to name string */
+    dst_src_loc_t     src_loc;           /* file/line of definition */
+    dst_type_t        elem_type_desc;    /* array element type */    
+    dst_type_t        indx_type_desc;    /* array index type */
+    long              lo_bound;          /* lower bound of index */
+    long              hi_bound;          /* upper bound of index */
+    unsigned long     span;              /* see above */
+    unsigned long     size;              /* total array size (bytes) */
+    boolean           multi_dim : 1;
+    boolean           is_packed : 1;     /* true if packed array */    
+    boolean           is_signed : 1;     /* true if packed elements are signed */
+    dst_span_comp_t   span_comp : 2;     /* how to compute span */
+    boolean           column_major : 1;
+    unsigned short    reserved  : 2;     /* must be zero */
+    unsigned short    elem_size : 8;     /* element size if packed (bits) */
+    }    
+    dst_rec_array_t ALIGNED1;
+
+
+/*-----------------
+  SUBRANGE record
+  -----------------
+  Describes a subrange type.
+*/
+
+/* Variable subrange bounds are described by auxiliary records; if aux_var_bound
+   records are present, the lo_bound and hi_bound fields of this record are
+   ignored by the debugger.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;       /* offset to name string */
+    dst_src_loc_t     src_loc;       /* file/line of subrange definition */
+    dst_type_t        type_desc;     /* parent type */    
+    long              lo_bound;      /* lower bound of subrange */
+    long              hi_bound;      /* upper bound of subrange */
+    unsigned short    size;          /* storage size (bytes) */
+    }
+    dst_rec_subrange_t ALIGNED1;
+
+
+/*---------------
+  STRING record 
+  ---------------
+  Describes a string type.
+*/
+
+/* Variable subrange bounds are described by auxiliary records; if aux_var_bound
+   records are present, the lo_bound and hi_bound fields of this record are
+   ignored by the debugger.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;          /* offset to name string */
+    dst_src_loc_t     src_loc;          /* file/line of string definition */
+    dst_type_t        elem_type_desc;   /* element type */    
+    dst_type_t        indx_type_desc;   /* index type */
+    long              lo_bound;         /* lower bound */
+    long              hi_bound;         /* upper bound */
+    unsigned long     size;             /* total string size (bytes) if fixed */
+    }
+    dst_rec_string_t ALIGNED1;
+
+
+/*---------------
+  SET record 
+  ---------------
+  Describes a set type.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;       /* offset to name string */
+    dst_src_loc_t     src_loc;       /* file/line of definition */
+    dst_type_t        type_desc;     /* element type */    
+    unsigned short    nbits;         /* number of bits in set */
+    unsigned short    size;          /* storage size (bytes) */
+    }
+    dst_rec_set_t ALIGNED1;
+
+
+/*-----------------------------
+  IMPLICIT ENUMERATION record 
+  -----------------------------
+  Describes an enumeration type with implicit element values = 0, 1, 2, ...
+  (Pascal-style).
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;      /* offset to name string */    
+    dst_src_loc_t      src_loc;      /* file/line of definition */
+    unsigned short     nelems;       /* number of elements in enumeration */
+    unsigned short     size;         /* storage size (bytes) */
+    /* offsets to name strings of elements 0, 1, 2, ... */
+    dst_rel_offset_t   elem_noffsets[dst_dummy_array_size]; 
+    }
+    dst_rec_implicit_enum_t ALIGNED1;
+
+
+/*-----------------------------
+  EXPLICIT ENUMERATION record 
+  -----------------------------
+  Describes an enumeration type with explicitly assigned element values
+  (C-style).
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;       /* offset to element name string */
+    long               value;         /* element value */
+    }
+    dst_enum_elem_t;
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;       /* offset to name string */
+    dst_src_loc_t      src_loc;       /* file/line of definition */
+    unsigned short     nelems;        /* number of elements in enumeration */
+    unsigned short     size;          /* storage size (bytes) */
+    /* name/value pairs, one describing each enumeration value: */
+    dst_enum_elem_t    elems[dst_dummy_array_size]; 
+    }
+    dst_rec_explicit_enum_t ALIGNED1;
+
+
+/*-----------------------
+  RECORD / UNION record 
+  -----------------------
+  Describes a record (struct) or union.
+
+  If the record is larger than 2**16 bytes then an attached aux record
+  specifies its size.  Also, if the record is stored in short form then
+  attached records specify field offsets larger than 2**16 bytes.
+
+  Whether the fields[] array or sfields[] array is used is selected by
+  the dst_rec_type_t of the overall dst record.
+*/
+
+/*
+   Record field descriptor, short form.  This form handles only fields which
+   are an even number of bytes long, located some number of bytes from the
+   start of the record.
+*/
+typedef struct
+    {
+    dst_rel_offset_t  noffset;     /* offset to field name string */
+    dst_type_t        type_desc;   /* field type */
+    unsigned short    foffset;     /* field offset from start of record (bytes) */
+    }
+    dst_short_field_t ALIGNED1;
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* offset to name string */
+    dst_type_t         type_desc;      /* field type */
+    unsigned short     foffset;        /* byte offset */
+    unsigned short     is_packed : 1;  /* True if field is packed */
+    unsigned short     bit_offset : 6; /* Bit offset */
+    unsigned short     size : 6;       /* Size in bits */
+    unsigned short     sign : 1;       /* True if signed */
+    unsigned short     pad : 2;        /* Padding. Must be 0 */
+    }
+    dst_old_field_t ALIGNED1;
+
+/* Tag enumeration for long record field descriptor:
+*/
+typedef enum
+    {
+    dst_field_byte,
+    dst_field_bit,
+    dst_field_loc,
+    dst_field_END_OF_ENUM
+    }
+    dst_field_format_t;
+
+/*
+   Record field descriptor, long form.  The format of the field information
+   is identified by the format_tag, which contains one of the above values.
+   The field_byte variant is equivalent to the short form of field descriptor.
+   The field_bit variant handles fields which are any number of bits long,
+   located some number of bits from the start of the record.  The field_loc
+   variant allows the location of the field to be described by a general loc
+   string.
+*/
+typedef struct
+    {
+    dst_rel_offset_t   noffset;                 /* offset to name of field */
+    dst_type_t         type_desc;               /* type of field */
+    union
+        {
+        struct {
+            dst_field_format_t format_tag: 2;   /* dst_field_byte */
+            unsigned long      offset: 30;      /* offset of field in bytes */
+            }
+            field_byte ALIGNED1;
+        struct {
+            dst_field_format_t format_tag: 2;   /* dst_field_bit */
+            unsigned long      nbits: 6;        /* bit size of field */
+            unsigned long      is_signed: 1;    /* signed/unsigned attribute */
+            unsigned long      bit_offset: 3;   /* bit offset from byte boundary */
+            int                pad: 4;          /* must be zero */
+            unsigned short     byte_offset;     /* offset of byte boundary */
+            }
+            field_bit ALIGNED1;
+        struct {
+            dst_field_format_t format_tag: 2;   /* dst_field_loc */
+            int                loffset: 30;     /* dst_rel_offset_t to loc string */
+            }
+            field_loc ALIGNED1;
+        }
+        f ALIGNED1;
+    }
+    dst_field_t;
+
+/* The field_loc.loffset field is a 30-bit signed value.  Some versions of C do
+   not support signed bit fields.  The following macro will extract that field
+   as a signed value:
+*/
+#define dst_field_loffset(field_rec) \
+    ( ((int) ((field_rec).f.field_loc.loffset << 2)) >> 2 )
+
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;      /* offset to record name string */
+    dst_src_loc_t      src_loc;      /* file/line where this record is defined */
+    unsigned short      size;        /* storage size (bytes) */
+    unsigned short      nfields;     /* number of fields in this record */
+    union
+        {
+        dst_field_t        fields[dst_dummy_array_size];
+        dst_short_field_t  sfields[dst_dummy_array_size];
+       dst_old_field_t    ofields[dst_dummy_array_size];
+        }
+        f;                           /* array of fields */
+    }
+    dst_rec_record_t ALIGNED1;
+
+
+/*-------------
+  FILE record
+  -------------
+  Describes a file type.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;       /* offset to name string */
+    dst_src_loc_t     src_loc;       /* file/line where type was defined */
+    dst_type_t        type_desc;     /* file element type */
+    }
+    dst_rec_file_t ALIGNED1;
+
+
+/*---------------
+  OFFSET record 
+  ---------------
+   Describes a Pascal offset type.
+   (This type, an undocumented Domain Pascal extension, is currently not
+   supported by the debugger)
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;           /* offset to the name string */
+    dst_src_loc_t      src_loc;           /* file/line of definition */
+    dst_type_t         area_type_desc;    /* area type */    
+    dst_type_t         base_type_desc;    /* base type */
+    long               lo_bound;          /* low bound of the offset range */
+    long               hi_bound;          /* high bound of the offset range */
+    long               bias;              /* bias */    
+    unsigned short     scale;             /* scale factor */
+    unsigned short     size;              /* storage size (bytes) */
+    }
+    dst_rec_offset_t ALIGNED1;
+
+
+/*--------------
+  ALIAS record 
+  --------------
+  Describes a type alias (e.g., typedef).
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;      /* offset to name string */
+    dst_src_loc_t      src_loc;      /* file/line of definition */
+    dst_type_t         type_desc;    /* parent type */
+    }
+    dst_rec_alias_t ALIGNED1;
+
+
+/*------------------
+  SIGNATURE record
+  ------------------
+  Describes a procedure/function type.
+*/
+
+/* Enumeration of argument semantics.  Note that most are mutually
+   exclusive.
+*/
+typedef enum
+    {
+    dst_arg_attr_val,          /* passed by value */
+    dst_arg_attr_ref,          /* passed by reference */
+    dst_arg_attr_name,         /* passed by name */
+    dst_arg_attr_in,           /* readable in the callee */
+    dst_arg_attr_out,          /* writable in the callee */    
+    dst_arg_attr_hidden,       /* not visible in the caller */
+    dst_arg_attr_END_OF_ENUM
+    }    
+    dst_arg_attr_t;
+
+/* Argument descriptor.  Actually points to a variable record for most of the
+   information.
+*/
+typedef struct
+    {
+    dst_rel_offset_t  var_offset;     /* offset to variable record */
+    unsigned short    attributes;     /* a mask of dst_arg_attr_t flags */
+    }
+    dst_arg_t ALIGNED1;
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;    /* offset to name string */
+    dst_src_loc_t      src_loc;    /* file/line of function definition */
+    dst_rel_offset_t   result;     /* offset to function result variable record */
+    unsigned short     nargs;      /* number of arguments */
+    dst_arg_t          args[dst_dummy_array_size]; 
+    }
+    dst_rec_signature_t ALIGNED1;
+
+/*--------------
+  SCOPE record
+  --------------
+  Obsolete. Use the new ENTRY type instead.
+  Old compilers may put this in as the first entry in a function,
+  terminated by an end of scope entry.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* Name offset */
+    dst_src_loc_t      start_line;     /* Starting line */
+    dst_src_loc_t      end_line;       /* Ending line */
+    }
+    dst_rec_scope_t ALIGNED1;
+
+/*--------------
+  ENTRY record
+  --------------
+  Describes a procedure/function entry point.  An entry record is to a
+  signature record roughly as a variable record is to a type descriptor record.
+
+  The entry_number field is keyed to the entry numbers in .lines -- the 
+  debugger locates the code location of an entry by searching the line
+  number table for an entry numbered with the value of entry_number.  The
+  main entry is numbered zero.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t  noffset;           /* offset to entry name string */
+    dst_rel_offset_t  loffset;           /* where to jump to call this entry */
+    dst_src_loc_t     src_loc;           /* file/line of definition */
+    dst_rel_offset_t  sig_desc;          /* offset to signature descriptor */
+    unsigned int      entry_number: 8;
+    int               pad: 8;            /* must be zero */
+    }
+    dst_rec_entry_t ALIGNED1;
+
+/*-----------------------
+  Old format ENTRY record
+  -----------------------
+  Supposedly obsolete but still used by some compilers.
+ */
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* Offset to entry name string */
+    dst_src_loc_t      src_loc;        /* Location in source */
+    dst_rel_offset_t   sig_desc;       /* Signature description */
+    char               unknown[36];
+    }
+    dst_rec_old_entry_t ALIGNED1;
+
+/*--------------
+  LABEL record 
+  --------------
+  Describes a program label.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   noffset;        /* offset to label string */
+    dst_rel_offset_t   loffset;        /* offset to loc string */
+    dst_src_loc_t      src_loc;        /* file/line of definition */
+    }
+    dst_rec_label_t ALIGNED1;
+
+
+/*-----------------------
+  AUXILIARY SIZE record
+  -----------------------
+  May appear in the auxiliary record list of any type or variable record to
+  modify the default size of the type or variable.
+*/
+
+typedef struct
+    {
+    unsigned long  size;       /* size (bytes) */
+    }
+    dst_rec_aux_size_t ALIGNED1;
+
+
+/*-----------------------
+  AUXILIARY ALIGN record
+  -----------------------
+  May appear in the auxiliary record list of any type or variable record to
+  modify the default alignment of the type or variable.
+*/
+
+typedef struct
+    {
+    unsigned short    alignment;  /* # of low order zero bits */
+    }
+    dst_rec_aux_align_t ALIGNED1;
+
+
+/*-----------------------------
+  AUXILIARY FIELD SIZE record
+  -----------------------------
+  May appear in the auxiliary record list of any RECORD/UNION record to 
+  modify the default size of a field.
+*/
+
+typedef struct
+    {
+    unsigned short field_no;       /* field number */
+    unsigned long  size;           /* size (bits) */
+    }
+    dst_rec_aux_field_size_t ALIGNED1;
+
+
+
+/*-----------------------------
+  AUXILIARY FIELD OFFSET record
+  -----------------------------
+  May appear in the auxiliary record list of any RECORD/UNION record to 
+  specify a field offset larger than 2**16.
+*/
+
+typedef struct
+    {
+    unsigned short field_no;       /* field number */
+    unsigned long  foffset;        /* offset */
+    }
+    dst_rec_aux_field_off_t ALIGNED1;
+
+
+/*-----------------------------
+  AUXILIARY FIELD ALIGN record
+  -----------------------------
+  May appear in the auxiliary record list of any RECORD/UNION record to 
+  modify the default alignment of a field.
+*/
+
+typedef struct
+    {
+    unsigned short field_no;       /* field number */
+    unsigned short alignment;      /* number of low order zero bits */
+    }
+    dst_rec_aux_field_align_t ALIGNED1;
+
+
+/*----------------------------
+  AUXILIARY VAR BOUND record
+  ----------------------------
+  May appear in the auxiliary record list of any ARRAY, SUBRANGE or STRING
+  record to describe a variable bound for the range of the type.
+*/
+
+typedef enum
+    {
+    dst_low_bound,       /* the low bound is variable */
+    dst_high_bound,      /* the high bound is variable */
+    dst_var_bound_END_OF_ENUM
+    }
+    dst_var_bound_t;
+
+typedef struct
+    {
+    unsigned short    which;              /* which bound */
+    dst_rel_offset_t   voffset ALIGNED1;   /* variable that defines bound */
+    }    
+    dst_rec_aux_var_bound_t ALIGNED1;
+
+
+/*----------------------------------
+  AUXILIARY TYPE DERIVATION record 
+  ----------------------------------
+  May appear in the auxiliary record list of any RECORD/UNION record to denote
+  class inheritance of that type from a parent type.
+
+  Inheritance implies that it is possible to convert the inheritor type to the
+  inherited type, retaining those fields which were inherited.  To allow this,
+  orig_field_no, a field number into the record type, is provided.  If 
+  orig_is_pointer is false, then the start of the inherited record is located
+  at the location of the field indexed by orig_field_no.  If orig_is_pointer
+  is true, then it is located at the address contained in the field indexed
+  by orig_field_no (assumed to be a pointer).
+*/
+
+typedef struct
+    {
+    dst_type_t     parent_type;             /* reference to inherited type */
+    unsigned short orig_field_no;
+    boolean        orig_is_pointer: 1;
+    int            unused: 15;              /* must be zero */
+    }
+    dst_rec_aux_type_deriv_t ALIGNED1;
+
+
+/*------------------------------------
+  AUXILIARY VARIABLE LIFETIME record
+  ------------------------------------
+  May appear in the auxiliary record list of a VARIABLE record to add location
+  information for an additional variable lifetime.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t loffset;
+    }
+    dst_rec_aux_lifetime_t ALIGNED1;
+
+
+/*-------------------------------
+  AUXILIARY POINTER BASE record 
+  -------------------------------
+  May appear in the auxiliary record list of a VARIABLE record to provide a
+  pointer base to substitute for references to any such bases in the location
+  string of the variable.  A pointer base is another VARIABLE record.  When
+  the variable is evaluated by the debugger, it uses the current value of the
+  pointer base variable in computing its location.
+
+  This is useful for representing FORTRAN pointer-based variables.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t voffset;
+    }
+    dst_rec_aux_ptr_base_t ALIGNED1;
+
+
+/*---------------------------------
+  AUXILIARY REGISTER VALUE record 
+  ---------------------------------
+  May appear in the auxiliary record list of an ENTRY record to specify
+  a register that must be set to a specific value before jumping to the entry
+  point in a debugger "call".  The debugger must set the debuggee register,
+  specified by the register code, to the value of the *address* to which the
+  location string resolves.  If the address is register-relative, then the
+  call cannot be made unless the current stack frame is the lexical parent
+  of the entry.  An example of this is when a (Pascal) nested procedure
+  contains references to its parent's variables, which it accesses through
+  a static link register.  The static link register must be set to some
+  address relative to the parent's stack base register.
+*/
+
+typedef struct
+    {
+    unsigned short    reg;        /* identifies register to set (isp enum) */
+    dst_rel_offset_t  loffset;    /* references a location string */
+    }
+    dst_rec_aux_reg_val_t ALIGNED1;
+
+
+/*==========================================================*/
+/*========== RECORDS USED IN .blocks AND .symbols ==========*/
+/*==========================================================*/
+
+/*---------------------
+  STRING TABLE record
+  ---------------------
+  A string table record contains any number of null-terminated, variable length
+  strings.   The length field gives the size in bytes of the text field, which
+  can be any size.
+
+  The global name table shares this format.  This record appears in the
+  .blocks section.  Each string in the table identifies a global defined in
+  the current compilation unit.
+
+  The loc pool record shares this format as well.  Loc strings are described
+  elsewhere.
+*/
+
+typedef struct
+    {
+    unsigned long length;               
+    char          text[dst_dummy_array_size];
+    }
+    dst_rec_string_tab_t ALIGNED1;
+
+
+/*-----------------------
+  AUXILIARY QUAL record 
+  -----------------------
+  May appear in the auxiliary record list of any BLOCK, VARIABLE, or type record
+  to provide it with a fully-qualified, language-dependent name.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   lang_qual_name;
+    }
+    dst_rec_aux_qual_t ALIGNED1;
+
+
+/*----------------
+  FORWARD record
+  ----------------
+  Reference to a record somewhere else.  This allows identical definitions in
+  different scopes to share data.
+*/
+
+typedef struct
+    {
+    dst_rel_offset_t   rec_off;
+    }
+    dst_rec_forward_t ALIGNED1;
+
+
+/*-------------------------------
+  AUXILIARY SOURCE RANGE record
+  -------------------------------
+  May appear in the auxiliary record list of any BLOCK record to specify a
+  range of source lines over which the block is active.
+*/
+
+typedef struct
+    {
+    dst_src_loc_t   first_line;             /* first source line */
+    dst_src_loc_t   last_line;              /* last source line */
+    }
+    dst_rec_aux_src_range_t ALIGNED1;
+
+
+/*------------------
+  EXTENSION record 
+  ------------------
+  Provision for "foreign" records, such as might be generated by a non-Apollo
+  compiler.  Apollo software will ignore these.
+*/
+
+typedef struct
+    {
+    unsigned short  rec_size;   /* record size (bytes) */
+    unsigned short  ext_type;   /* defined by whoever generates it */
+    unsigned short  ext_data;   /* place-holder for arbitrary amount of data */
+    }
+    dst_rec_extension_t ALIGNED1;
+
+
+/*
+** DEBUG SYMBOL record -- The wrapper for all .blocks and .symbols records.
+**
+** This record ties together all previous .blocks and .symbols records 
+** together in a union with a common header.  The rec_type field of the
+** header identifies the record type.  The rec_flags field currently only
+** defines auxiliary record lists. 
+**
+** If a record carries with it a non-null auxiliary record list, its
+** dst_flag_has_aux_recs flag is set, and each of the records that follow
+** it are treated as its auxiliary records, until the end of the compilation
+** unit or scope is reached, or until an auxiliary record with its
+** dst_flag_last_aux_rec flag set is reached.
+*/
+
+typedef enum
+    {
+    dst_flag_has_aux_recs,
+    dst_flag_last_aux_rec,
+    dst_rec_flag_END_OF_ENUM
+    }    
+    dst_rec_flags_t;
+
+typedef struct
+    {
+    dst_rec_type_t    rec_type : 8;     /* record type */
+    int               rec_flags: 8;     /* mask of dst_rec_flags_t */
+    union                               /* switched on rec_type field above */
+        {
+           /* dst_typ_pad requires no additional fields */
+        dst_rec_comp_unit_t        comp_unit_;
+        dst_rec_section_tab_t      section_tab_;
+        dst_rec_file_tab_t         file_tab_;  
+        dst_rec_block_t            block_;   
+       dst_rec_var_t              var_;
+        dst_rec_pointer_t          pointer_;   
+        dst_rec_array_t            array_; 
+        dst_rec_subrange_t         subrange_;
+        dst_rec_set_t              set_;
+        dst_rec_implicit_enum_t    implicit_enum_;   
+        dst_rec_explicit_enum_t    explicit_enum_;
+           /* dst_typ_short_{rec,union} are represented by 'rec' (below) */
+        dst_rec_file_t             file_;   
+        dst_rec_offset_t           offset_;   
+        dst_rec_alias_t            alias_; 
+        dst_rec_signature_t        signature_;
+       dst_rec_old_label_t        old_label_;
+       dst_rec_scope_t            scope_;
+           /* dst_typ_end_scope requires no additional fields */
+        dst_rec_string_tab_t       string_tab_;   
+           /* dst_typ_global_name_tab is represented by 'string_tab' (above) */
+        dst_rec_forward_t          forward_;   
+        dst_rec_aux_size_t         aux_size_;   
+        dst_rec_aux_align_t        aux_align_;  
+        dst_rec_aux_field_size_t   aux_field_size_; 
+        dst_rec_aux_field_off_t    aux_field_off_;
+        dst_rec_aux_field_align_t  aux_field_align_;
+        dst_rec_aux_qual_t         aux_qual_;   
+        dst_rec_aux_var_bound_t    aux_var_bound_;  
+        dst_rec_extension_t        extension_;
+        dst_rec_string_t           string_;  
+        dst_rec_const_t            const_; 
+           /* dst_typ_reference is represented by 'pointer' (above) */
+        dst_rec_record_t           record_; 
+           /* dst_typ_union is represented by 'record' (above) */
+        dst_rec_aux_type_deriv_t   aux_type_deriv_; 
+           /* dst_typ_locpool is represented by 'string_tab' (above) */
+        dst_rec_variable_t         variable_;  
+        dst_rec_label_t            label_; 
+        dst_rec_entry_t            entry_; 
+        dst_rec_aux_lifetime_t     aux_lifetime_;
+        dst_rec_aux_ptr_base_t     aux_ptr_base_;
+        dst_rec_aux_src_range_t    aux_src_range_;  
+        dst_rec_aux_reg_val_t      aux_reg_val_;
+        dst_rec_name_tab_t         aux_unit_names_;
+        dst_rec_sect_info_tab_t    aux_sect_info_;
+        }
+        rec_data    ALIGNED1;
+    }
+    dst_rec_t, *dst_rec_ptr_t;
+
+
+/*===============================================*/
+/*========== .lines SECTION DEFINITIONS =========*/
+/*===============================================*/
+/*
+  The .lines section contains a sequence of line number tables.  There is no
+  record structure within the section.  The start of the table for a routine
+  is pointed to by the block record, and the end of the table is signaled by
+  an escape code.
+
+  A line number table is a sequence of bytes.  The default entry contains a line
+  number delta (-7..+7) in the high 4 bits and a pc delta (0..15) in the low 4 
+  bits. Special cases, including when one or both of the values is too large
+  to fit in 4 bits and other special cases are handled through escape entries.
+  Escape entries are identified by the value 0x8 in the high 4 bits.  The low 4
+  bits are occupied by a function code.  Some escape entries are followed by
+  additional arguments, which may be bytes, words, or longwords.  This data is
+  not aligned. 
+
+  The initial PC offset, file number and line number are zero.  Normally, the
+  table begins with a dst_ln_file escape which establishes the initial file
+  and line number.  All PC deltas are unsigned (thus the table is ordered by
+  increasing PC); line number deltas are signed.  The table ends with a 
+  dst_ln_end escape, which is followed by a final table entry whose PC delta
+  gives the code size of the last statement.
+
+  Escape     Semantic
+  ---------  ------------------------------------------------------------
+  file       Changes file state.  The current source file remains constant
+             until another file escape.  Though the line number state is
+             also updated by a file escape, a file escape does NOT 
+             constitute a line table entry.
+
+  statement  Alters the statement number of the next table entry.  By 
+             default, all table entries refer to the first statement on a
+             line.  Statement number one is the second statement, and so on.
+
+  entry      Identifies the next table entry as the position of an entry 
+             point for the current block.  The PC position should follow 
+             any procedure prologue code.  An argument specifies the entry
+             number, which is keyed to the entry number of the corresponding
+             .symbols ENTRY record.
+
+  exit       Identifies the next table entry as the last position within 
+             the current block before a procedure epiloge and subsequent
+             procedure exit.
+
+  gap        By default, the executable code corresponding to a table entry 
+             is assumed to extend to the beginning of the next table entry.
+             If this is not the case--there is a "hole" in the table--then
+             a gap escape should follow the first table entry to specify
+             where the code for that entry ends.
+*/
+
+#define dst_ln_escape_flag    -8    
+
+/*
+  Escape function codes:
+*/
+typedef enum
+    {
+    dst_ln_pad,          /* pad byte */
+    dst_ln_file,         /* file escape.  Next 4 bytes are a dst_src_loc_t */
+    dst_ln_dln1_dpc1,    /* 1 byte line delta, 1 byte pc delta */    
+    dst_ln_dln2_dpc2,    /* 2 bytes line delta, 2 bytes pc delta */
+    dst_ln_ln4_pc4,      /* 4 bytes ABSOLUTE line number, 4 bytes ABSOLUTE pc */
+    dst_ln_dln1_dpc0,    /* 1 byte line delta, pc delta = 0 */
+    dst_ln_ln_off_1,     /* statement escape, stmt # = 1 (2nd stmt on line) */
+    dst_ln_ln_off,       /* statement escape, stmt # = next byte */
+    dst_ln_entry,        /* entry escape, next byte is entry number */    
+    dst_ln_exit,         /* exit escape */
+    dst_ln_stmt_end,     /* gap escape, 4 bytes pc delta */
+    dst_ln_escape_11,    /* reserved */
+    dst_ln_escape_12,    /* reserved */
+    dst_ln_escape_13,    /* reserved */
+    dst_ln_nxt_byte,     /* next byte contains the real escape code */
+    dst_ln_end,          /* end escape, final entry follows */
+    dst_ln_escape_END_OF_ENUM
+    }    
+    dst_ln_escape_t;
+
+/*
+  Line number table entry
+*/
+typedef union
+    {
+    struct
+        {
+        unsigned int    ln_delta : 4;           /* 4 bit line number delta */
+        unsigned int    pc_delta : 4;           /* 4 bit pc delta */
+        }
+        delta;
+    
+    struct
+        {
+        unsigned int    esc_flag : 4;       /* alias for ln_delta */
+        dst_ln_escape_t esc_code : 4;       /* escape function code */
+        }
+        esc;
+    
+    char               sdata;                  /* signed data byte */    
+    unsigned char      udata;                  /* unsigned data byte */
+    }
+    dst_ln_entry_t,
+    *dst_ln_entry_ptr_t,
+    dst_ln_table_t[dst_dummy_array_size];
+
+/* The following macro will extract the ln_delta field as a signed value:
+*/
+#define dst_ln_ln_delta(ln_rec) \
+    ( ((short) ((ln_rec).delta.ln_delta << 12)) >> 12 )
+
+
+
+
+typedef struct dst_sec_struct {
+       char    *buffer;
+       long    position;
+       long    size;
+       long    base;
+} dst_sec;
+
+
+/* Macros for access to the data */
+
+#define DST_comp_unit(x)       ((x)->rec_data.comp_unit_)
+#define DST_section_tab(x)     ((x)->rec_data.section_tab_)
+#define DST_file_tab(x)        ((x)->rec_data.file_tab_)
+#define DST_block(x)           ((x)->rec_data.block_)
+#define        DST_var(x)              ((x)->rec_data.var_)
+#define DST_pointer(x)                 ((x)->rec_data.pointer_)
+#define DST_array(x)           ((x)->rec_data.array_)
+#define DST_subrange(x)        ((x)->rec_data.subrange_)
+#define DST_set(x)             ((x)->rec_data.set_)
+#define DST_implicit_enum(x)   ((x)->rec_data.implicit_enum_)
+#define DST_explicit_enum(x)   ((x)->rec_data.explicit_enum_)
+#define DST_short_rec(x)       ((x)->rec_data.record_)
+#define DST_short_union(x)     ((x)->rec_data.record_)
+#define DST_file(x)            ((x)->rec_data.file_)
+#define DST_offset(x)          ((x)->rec_data.offset_)
+#define DST_alias(x)           ((x)->rec_data.alias_)
+#define DST_signature(x)       ((x)->rec_data.signature_)
+#define DST_old_label(x)       ((x)->rec_data.old_label_)
+#define DST_scope(x)           ((x)->rec_data.scope_)
+#define DST_string_tab(x)      ((x)->rec_data.string_tab_)
+#define DST_global_name_tab(x)         ((x)->rec_data.string_tab_)
+#define DST_forward(x)                 ((x)->rec_data.forward_)
+#define DST_aux_size(x)        ((x)->rec_data.aux_size_)
+#define DST_aux_align(x)       ((x)->rec_data.aux_align_)
+#define DST_aux_field_size(x)  ((x)->rec_data.aux_field_size_)
+#define DST_aux_field_off(x)   ((x)->rec_data.aux_field_off_)
+#define DST_aux_field_align(x)         ((x)->rec_data.aux_field_align_)
+#define DST_aux_qual(x)        ((x)->rec_data.aux_qual_)
+#define DST_aux_var_bound(x)   ((x)->rec_data.aux_var_bound_)
+#define DST_extension(x)       ((x)->rec_data.extension_)
+#define DST_string(x)          ((x)->rec_data.string_)
+#define DST_const(x)           ((x)->rec_data.const_)
+#define DST_reference(x)       ((x)->rec_data.pointer_)
+#define DST_record(x)          ((x)->rec_data.record_)
+#define DST_union(x)           ((x)->rec_data.record_)
+#define DST_aux_type_deriv(x)  ((x)->rec_data.aux_type_deriv_)
+#define DST_locpool(x)                 ((x)->rec_data.string_tab_)
+#define DST_variable(x)        ((x)->rec_data.variable_)
+#define DST_label(x)           ((x)->rec_data.label_)
+#define DST_entry(x)           ((x)->rec_data.entry_)
+#define DST_aux_lifetime(x)    ((x)->rec_data.aux_lifetime_)
+#define DST_aux_ptr_base(x)    ((x)->rec_data.aux_ptr_base_)
+#define DST_aux_src_range(x)   ((x)->rec_data.aux_src_range_)
+#define DST_aux_reg_val(x)     ((x)->rec_data.aux_reg_val_)
+#define DST_aux_unit_names(x)  ((x)->rec_data.aux_unit_names_)
+#define DST_aux_sect_info(x)   ((x)->rec_data.aux_sect_info_)
+
+
+/*
+ * Type codes for loc strings. I'm not entirely certain about all of
+ * these, but they seem to work.
+ *                             troy@cbme.unsw.EDU.AU
+ * If you find a variable whose location can't be decoded, you should
+ * find out it's code using "dstdump -s filename". It will record an
+ * entry for the variable, and give a text representation of what
+ * the locstring means. Before that explaination there will be a
+ * number. In the LOCSTRING table, that number will appear before
+ * the start of the location string. Location string codes are
+ * five bit codes with a 3 bit argument. Check the high 5 bits of
+ * the one byte code, and figure out where it goes in here.
+ * Then figure out exactly what the meaning is and code it in
+ * dstread.c
+ *
+ * Note that ranged locs mean that the variable is in different locations
+ * depending on the current PC. We ignore these because (a) gcc can't handle
+ * them, and (b), If you don't use high levels of optimisation they won't
+ * occur.
+ */
+typedef enum
+{
+       dst_lsc_end,            /* End of string */
+       dst_lsc_indirect,       /* Indirect through previous. Arg == 6 */
+                               /* Or register ax (x=arg) */
+       dst_lsc_dreg,           /* register dx (x=arg) */
+       dst_lsc_03,
+       dst_lsc_section,        /* Section (arg+1) */
+       dst_lsc_05,
+       dst_lsc_06,
+       dst_lsc_add,            /* Add (arg+1)*2 */
+       dst_lsc_sub,            /* Subtract (arg+1)*2 */
+       dst_lsc_09,
+       dst_lsc_0a,
+       dst_lsc_sec_byte,       /* Section of next byte+1 */
+       dst_lsc_add_byte,       /* Add next byte (arg == 5) or next word
+                                * (arg == 6)
+                                */
+       dst_lsc_sub_byte,       /* Subtract next byte. (arg == 1) or next
+                                * word (arg == 6 ?)
+                                */
+       dst_lsc_sbreg,          /* Stack base register (frame pointer). Arg==0*/
+       dst_lsc_0f,
+       dst_lsc_ranged,         /* location is pc dependent */
+       dst_lsc_11,
+       dst_lsc_12,
+       dst_lsc_13,
+       dst_lsc_14,
+       dst_lsc_15,
+       dst_lsc_16,
+       dst_lsc_17,
+       dst_lsc_18,
+       dst_lsc_19,
+       dst_lsc_1a,
+       dst_lsc_1b,
+       dst_lsc_1c,
+       dst_lsc_1d,
+       dst_lsc_1e,
+       dst_lsc_1f
+} dst_loc_string_code_t;
+
+/* If the following occurs after an addition/subtraction, that addition
+ * or subtraction should be multiplied by 256. It's a complete byte, not
+ * a code.
+ */
+
+#define        dst_multiply_256        ((char) 0x73)
+
+typedef struct
+{
+       char    code : 5;
+       char    arg : 3;
+} dst_loc_header_t ALIGNED1;
+
+typedef union
+{
+       dst_loc_header_t header;
+       char    data;
+} dst_loc_entry_t ALIGNED1;
+
+#undef ALIGNED1
+#endif  /* apollo_dst_h */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..64b68c6a78929b3d037cc91e119e808b0608c99e 100644 (file)
+/* Read apollo DST symbol tables and convert to internal format, for GDB.
+   Contributed by Troy Rollo, University of NSW (troy@cbme.unsw.edu.au).
+   Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+\f
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "breakpoint.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include <obstack.h>
+
+#include <string.h>
+
+#include "dst.h"
+
+CORE_ADDR cur_src_start_addr, cur_src_end_addr;
+dst_sec        blocks_info, lines_info, symbols_info;
+
+/* Vector of line number information.  */
+
+static struct linetable *line_vector;
+
+/* Index of next entry to go in line_vector_index.  */
+
+static int line_vector_index;
+
+/* Last line number recorded in the line vector.  */
+
+static int prev_line_number;
+
+/* Number of elements allocated for line_vector currently.  */
+
+static int line_vector_length;
+
+struct pending_block *pending_blocks;
+
+static struct blockvector *
+make_blockvector PARAMS ((struct objfile *));
+
+static int
+init_dst_sections PARAMS ((int));
+
+static void
+read_dst_symtab PARAMS ((struct objfile *));
+
+static void
+find_dst_sections PARAMS ((bfd *, sec_ptr, PTR));
+
+static void
+dst_symfile_init PARAMS ((struct objfile *));
+
+static void
+dst_new_init PARAMS ((struct objfile *));
+
+static void
+dst_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+dst_symfile_finish PARAMS ((struct objfile *));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type));
+
+static void
+dst_end_symtab PARAMS ((struct objfile *));
+
+static void
+complete_symtab PARAMS ((char *, CORE_ADDR, unsigned int));
+
+static void
+dst_start_symtab PARAMS ((void));
+
+static void
+dst_record_line PARAMS ((int, CORE_ADDR));
+
+static struct blockvector *
+make_blockvector (objfile)
+     struct objfile *objfile;
+{
+  register struct pending_block *next, *next1;
+  register struct blockvector *blockvector;
+  register int i;
+
+  /* Count the length of the list of blocks.  */
+
+  for (next = pending_blocks, i = 0; next; next = next->next, i++);
+
+  blockvector = (struct blockvector *)
+                 obstack_alloc (&objfile->symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *));
+
+  /* Copy the blocks into the blockvector.
+     This is done in reverse order, which happens to put
+     the blocks into the proper order (ascending starting address).
+   */
+
+  BLOCKVECTOR_NBLOCKS (blockvector) = i;
+  for (next = pending_blocks; next; next = next->next)
+    BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+
+  /* Now free the links of the list, and empty the list.  */
+
+  for (next = pending_blocks; next; next = next1)
+    {
+      next1 = next->next;
+      free ((PTR)next);
+    }
+  pending_blocks = 0;
+
+  return blockvector;
+}
+
+/* Manage the vector of line numbers.  */
+/* FIXME: Use record_line instead.  */
+
+static void
+dst_record_line (line, pc)
+     int line;
+     CORE_ADDR pc;
+{
+  struct linetable_entry *e;
+  /* Make sure line vector is big enough.  */
+
+  if (line_vector_index + 2 >= line_vector_length)
+    {
+      line_vector_length *= 2;
+      line_vector = (struct linetable *)
+       xrealloc ((char *) line_vector, sizeof (struct linetable)
+                 + (line_vector_length
+                    * sizeof (struct linetable_entry)));
+    }
+
+  e = line_vector->item + line_vector_index++;
+  e->line = line; e->pc = pc;
+}
+\f
+/* Start a new symtab for a new source file.
+   It indicates the start of data for one original source file.  */
+/* FIXME: use start_symtab, like coffread.c now does.  */
+
+static void
+dst_start_symtab ()
+{
+  /* Initialize the source file line number information for this file.  */
+
+  if (line_vector)             /* Unlikely, but maybe possible? */
+    free ((PTR)line_vector);
+  line_vector_index = 0;
+  line_vector_length = 1000;
+  prev_line_number = -2;       /* Force first line number to be explicit */
+  line_vector = (struct linetable *)
+    xmalloc (sizeof (struct linetable)
+            + line_vector_length * sizeof (struct linetable_entry));
+}
+
+/* Save the vital information from when starting to read a file,
+   for use when closing off the current file.
+   NAME is the file name the symbols came from, START_ADDR is the first
+   text address for the file, and SIZE is the number of bytes of text.  */
+
+static void
+complete_symtab (name, start_addr, size)
+    char *name;
+    CORE_ADDR start_addr;
+    unsigned int size;
+{
+  last_source_file = savestring (name, strlen (name));
+  cur_src_start_addr = start_addr;
+  cur_src_end_addr = start_addr + size;
+
+  if (current_objfile -> ei.entry_point >= cur_src_start_addr &&
+      current_objfile -> ei.entry_point <  cur_src_end_addr)
+    {
+      current_objfile -> ei.entry_file_lowpc = cur_src_start_addr;
+      current_objfile -> ei.entry_file_highpc = cur_src_end_addr;
+    }
+}
+
+/* Finish the symbol definitions for one main source file,
+   close off all the lexical contexts for that file
+   (creating struct block's for them), then make the
+   struct symtab for that file and put it in the list of all such. */
+/* FIXME: Use end_symtab, like coffread.c now does.  */
+
+static void
+dst_end_symtab (objfile)
+     struct objfile *objfile;
+{
+  register struct symtab *symtab;
+  register struct blockvector *blockvector;
+  register struct linetable *lv;
+
+  /* Create the blockvector that points to all the file's blocks.  */
+
+  blockvector = make_blockvector (objfile);
+
+  /* Now create the symtab object for this source file.  */
+  symtab = allocate_symtab (last_source_file, objfile);
+
+  /* Fill in its components.  */
+  symtab->blockvector = blockvector;
+  symtab->free_code = free_linetable;
+  symtab->free_ptr = 0;
+  symtab->filename = last_source_file;
+  symtab->dirname = NULL;
+  lv = line_vector;
+  lv->nitems = line_vector_index;
+  symtab->linetable = (struct linetable *)
+    xrealloc ((char *) lv, (sizeof (struct linetable)
+                  + lv->nitems * sizeof (struct linetable_entry)));
+
+  free_named_symtabs (symtab->filename);
+
+  /* Reinitialize for beginning of new file. */
+  line_vector = 0;
+  line_vector_length = -1;
+  last_source_file = NULL;
+}
+\f
+static void
+record_minimal_symbol (name, address, type)
+     char *name;
+     CORE_ADDR address;
+     enum minimal_symbol_type type;
+{
+  prim_record_minimal_symbol (savestring (name, strlen (name)),
+                            address,
+                            type);
+}
+\f
+/* dst_symfile_init ()
+   is the dst-specific initialization routine for reading symbols.
+
+   We will only be called if this is a DST or DST-like file.
+   BFD handles figuring out the format of the file, and code in symtab.c
+   uses BFD's determination to vector to us.
+
+   The ultimate result is a new symtab (or, FIXME, eventually a psymtab).  */
+
+static void
+dst_symfile_init (objfile)
+     struct objfile *objfile;
+{
+  asection     *section;
+  bfd *abfd = objfile->obfd;
+
+  init_entry_point_info (objfile);
+
+}
+
+/* This function is called for every section; it finds the outer limits
+   of the line table (minimum and maximum file offset) so that the
+   mainline code can read the whole thing for efficiency.  */
+
+/* ARGSUSED */
+static void
+find_dst_sections (abfd, asect, vpinfo)
+     bfd *abfd;
+     sec_ptr asect;
+     PTR vpinfo;
+{
+  int size, count;
+  long base;
+  file_ptr offset, maxoff;
+  dst_sec *section;
+
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+  size = asect->_raw_size;
+  offset = asect->filepos;
+  base = asect->vma;
+/* End of warning */
+
+  section = NULL;
+  if (!strcmp(asect->name, ".blocks"))
+    section = &blocks_info;
+  else if (!strcmp(asect->name, ".lines"))
+    section = &lines_info;
+  else if (!strcmp(asect->name, ".symbols"))
+    section = &symbols_info;
+  if (!section)
+    return;
+  section->size = size;
+  section->position = offset;
+  section->base = base;
+}
+
+
+/* The BFD for this file -- only good while we're actively reading
+   symbols into a psymtab or a symtab.  */
+
+static bfd *symfile_bfd;
+
+/* Read a symbol file, after initialization by dst_symfile_init.  */
+/* FIXME!  Addr and Mainline are not used yet -- this will not work for
+   shared libraries or add_file!  */
+
+/* ARGSUSED */
+static void
+dst_symfile_read (objfile, section_offsets, mainline)
+     struct objfile *objfile;
+     struct section_offsets *section_offsets;
+     int mainline;
+{
+  bfd *abfd = objfile->obfd;
+  char *name = bfd_get_filename (abfd);
+  int desc;
+  register int val;
+  int num_symbols;
+  int symtab_offset;
+  int stringtab_offset;
+
+  symfile_bfd = abfd;                  /* Kludge for swap routines */
+
+/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
+   desc = fileno ((FILE *)(abfd->iostream));   /* File descriptor */
+
+  /* Read the line number table, all at once.  */
+  bfd_map_over_sections (abfd, find_dst_sections, (PTR)NULL);
+
+  val = init_dst_sections (desc);
+  if (val < 0)
+    error ("\"%s\": error reading debugging symbol tables\n", name);
+
+  init_minimal_symbol_collection ();
+  make_cleanup (discard_minimal_symbols, 0);
+
+  /* Now that the executable file is positioned at symbol table,
+     process it and define symbols accordingly.  */
+
+  read_dst_symtab (objfile);
+
+  /* Sort symbols alphabetically within each block.  */
+
+  sort_all_symtab_syms ();
+
+  /* Install any minimal symbols that have been collected as the current
+     minimal symbols for this objfile. */
+
+  install_minimal_symbols (objfile);
+}
+
+static void
+dst_new_init (ignore)
+     struct objfile *ignore;
+{
+       /* Nothin' to do */
+}
+
+/* Perform any local cleanups required when we are done with a particular
+   objfile.  I.E, we are in the process of discarding all symbol information
+   for an objfile, freeing up all memory held for it, and unlinking the
+   objfile struct from the global list of known objfiles. */
+
+static void
+dst_symfile_finish (objfile)
+     struct objfile *objfile;
+{
+    /* Nothing to do */
+}
+
+\f
+/* Get the next line number from the DST. Returns 0 when we hit an
+ * end directive or cannot continue for any other reason.
+ *
+ * Note that ordinary pc deltas are multiplied by two. Apparently
+ * this is what was really intended.
+ */
+static int
+get_dst_line(buffer, pc)
+    signed char **buffer;
+    long *pc;
+{
+       static last_pc = 0;
+       static long last_line = 0;
+       static int last_file = 0;
+       dst_ln_entry_ptr_t entry;
+       int size;
+       dst_src_loc_t *src_loc;
+
+       if (*pc != -1)
+       {
+               last_pc = *pc;
+               *pc = -1;
+       }
+       entry = (dst_ln_entry_ptr_t) *buffer;
+
+       while (dst_ln_ln_delta(*entry) == dst_ln_escape_flag)
+       {
+               switch(entry->esc.esc_code)
+               {
+               case dst_ln_pad:
+                       size = 1;         /* pad byte */
+                       break;
+               case dst_ln_file:
+                       /* file escape.  Next 4 bytes are a dst_src_loc_t */
+                       size = 5;
+                       src_loc = (dst_src_loc_t *) (*buffer + 1);
+                       last_line = src_loc->line_number;
+                       last_file = src_loc->file_index;
+                       break;
+               case dst_ln_dln1_dpc1:
+                       /* 1 byte line delta, 1 byte pc delta */    
+                       last_line += (*buffer)[1];
+                       last_pc += 2 * (unsigned char) (*buffer)[2];
+                       dst_record_line(last_line, last_pc);
+                       size = 3;
+                       break;
+               case dst_ln_dln2_dpc2:
+                       /* 2 bytes line delta, 2 bytes pc delta */
+                       last_line += *(short *) (*buffer + 1);
+                       last_pc += 2 * (*(short *) (*buffer + 3));
+                       size = 5;
+                       dst_record_line(last_line, last_pc);
+                       break;
+               case dst_ln_ln4_pc4:
+                       /* 4 bytes ABSOLUTE line number, 4 bytes ABSOLUTE pc */
+                       last_line = *(unsigned long *) (*buffer + 1);
+                       last_pc = *(unsigned long *) (*buffer + 5);
+                       size = 9;
+                       dst_record_line(last_line, last_pc);
+                       break;
+               case dst_ln_dln1_dpc0:
+                       /* 1 byte line delta, pc delta = 0 */
+                       size = 2;
+                       last_line+= (*buffer)[1];
+                       break;
+                case dst_ln_ln_off_1:
+                       /* statement escape, stmt # = 1 (2nd stmt on line) */
+                       size = 1;
+                       break;
+               case dst_ln_ln_off:
+                       /* statement escape, stmt # = next byte */
+                       size = 2;
+                       break;
+               case dst_ln_entry:
+                       /* entry escape, next byte is entry number */    
+                       size = 2;
+                       break;
+               case dst_ln_exit:
+                       /* exit escape */
+                       size = 1;
+                       break;
+               case dst_ln_stmt_end:
+                       /* gap escape, 4 bytes pc delta */
+                       size = 5;
+                       /* last_pc += 2 * (*(long *) (*buffer + 1)); */
+                       /* Apparently this isn't supposed to actually modify
+                        * the pc value. Totally weird.
+                        */
+                       break;
+                case dst_ln_escape_11:
+                case dst_ln_escape_12:
+                case dst_ln_escape_13:
+                       size = 1;
+                       break;
+                case dst_ln_nxt_byte:
+                       /* This shouldn't happen. If it does, we're SOL */
+                       return 0;
+                       break;
+                case dst_ln_end:
+                       /* end escape, final entry follows */
+                       return 0;
+               }
+               *buffer += (size < 0) ? -size : size;
+               entry = (dst_ln_entry_ptr_t) *buffer;
+       }
+       last_line += dst_ln_ln_delta(*entry);
+       last_pc += entry->delta.pc_delta * 2;
+       (*buffer)++;
+       dst_record_line(last_line, last_pc);
+       return 1;
+}
+
+static void
+enter_all_lines(buffer, address)
+    char *buffer;
+    long address;
+{
+    if (buffer)
+       while (get_dst_line(&buffer, &address));
+}
+
+static int
+get_dst_entry(buffer, ret_entry)
+    char *buffer;
+    dst_rec_ptr_t *ret_entry;
+{
+    int size;
+    dst_rec_ptr_t entry;
+    static int last_type;
+    int        ar_size;
+    static unsigned lu3;
+
+    entry = (dst_rec_ptr_t) buffer;
+    switch(entry->rec_type)
+    {
+    case dst_typ_pad:
+       size = 0;
+       break;
+    case dst_typ_comp_unit:
+       size = sizeof(DST_comp_unit(entry));
+       break;
+    case dst_typ_section_tab:
+       size = sizeof(DST_section_tab(entry))
+               + ((int) DST_section_tab(entry).number_of_sections
+                  - dst_dummy_array_size) * sizeof(long);
+       break;
+    case dst_typ_file_tab:
+       size = sizeof(DST_file_tab(entry))
+               + ((int) DST_file_tab(entry).number_of_files
+                  - dst_dummy_array_size) * sizeof(dst_file_desc_t);
+       break;
+    case dst_typ_block:
+       size = sizeof(DST_block(entry))
+               + ((int) DST_block(entry).n_of_code_ranges
+                  - dst_dummy_array_size) * sizeof(dst_code_range_t);
+       break;
+    case dst_typ_5:
+       size = -1;
+       break;
+    case dst_typ_var:
+       size = sizeof(DST_var(entry)) -
+               sizeof(dst_var_loc_long_t) * dst_dummy_array_size +
+               DST_var(entry).no_of_locs *
+               ( DST_var(entry).short_locs ?
+                 sizeof(dst_var_loc_short_t):
+                 sizeof(dst_var_loc_long_t));
+       break;
+    case dst_typ_pointer:
+       size = sizeof(DST_pointer(entry));
+       break;
+    case dst_typ_array:
+       size = sizeof(DST_array(entry));
+       break;
+    case dst_typ_subrange:
+       size = sizeof(DST_subrange(entry));
+       break;
+    case dst_typ_set:
+       size = sizeof(DST_set(entry));
+       break;
+    case dst_typ_implicit_enum:
+       size = sizeof(DST_implicit_enum(entry))
+               + ((int) DST_implicit_enum(entry).nelems
+                  - dst_dummy_array_size) * sizeof(dst_rel_offset_t);
+       break;
+    case dst_typ_explicit_enum:
+       size = sizeof(DST_explicit_enum(entry))
+               + ((int) DST_explicit_enum(entry).nelems
+                  - dst_dummy_array_size) * sizeof(dst_enum_elem_t);
+       break;
+    case dst_typ_short_rec:
+       size = sizeof(DST_short_rec(entry))
+               + DST_short_rec(entry).nfields * sizeof(dst_short_field_t)
+               - dst_dummy_array_size * sizeof(dst_field_t);
+       break;
+    case dst_typ_short_union:
+       size = sizeof(DST_short_union(entry))
+               + DST_short_union(entry).nfields * sizeof(dst_short_field_t)
+               - dst_dummy_array_size * sizeof(dst_field_t);
+       break;
+    case dst_typ_file:
+       size = sizeof(DST_file(entry));
+       break;
+    case dst_typ_offset:
+       size = sizeof(DST_offset(entry));
+       break;
+    case dst_typ_alias:
+       size = sizeof(DST_alias(entry));
+       break;
+    case dst_typ_signature:
+       size = sizeof(DST_signature(entry)) +
+               ((int) DST_signature(entry).nargs -
+                dst_dummy_array_size) * sizeof(dst_arg_t);
+       break;
+    case dst_typ_21:
+       size = -1;
+       break;
+    case dst_typ_old_label:
+       size = sizeof(DST_old_label(entry));
+       break;
+    case dst_typ_scope:
+       size = sizeof(DST_scope(entry));
+       break;
+    case dst_typ_end_scope:
+       size = 0;
+       break;
+    case dst_typ_25:
+    case dst_typ_26:
+       size = -1;
+       break;
+    case dst_typ_string_tab:
+    case dst_typ_global_name_tab:
+       size = sizeof(DST_string_tab(entry))
+               + DST_string_tab(entry).length
+               - dst_dummy_array_size;
+       break;
+    case dst_typ_forward:
+       size = sizeof(DST_forward(entry));
+       get_dst_entry((char *) entry + DST_forward(entry).rec_off, &entry);
+       break;
+    case dst_typ_aux_size:
+       size = sizeof(DST_aux_size(entry));
+       break;
+    case dst_typ_aux_align:
+       size = sizeof(DST_aux_align(entry));
+       break;
+    case dst_typ_aux_field_size:
+       size = sizeof(DST_aux_field_size(entry));
+       break;
+    case dst_typ_aux_field_off:
+       size = sizeof(DST_aux_field_off(entry));
+       break;
+    case dst_typ_aux_field_align:
+       size = sizeof(DST_aux_field_align(entry));
+       break;
+    case dst_typ_aux_qual:
+       size = sizeof(DST_aux_qual(entry));
+       break;
+    case dst_typ_aux_var_bound:
+       size = sizeof(DST_aux_var_bound(entry));
+       break;
+    case dst_typ_extension:
+       size = DST_extension(entry).rec_size;
+       break;
+    case dst_typ_string:
+       size = sizeof(DST_string(entry));
+       break;
+    case dst_typ_old_entry:
+       size = 48; /* Obsolete entry type */
+       break;
+    case dst_typ_const:
+       size = sizeof(DST_const(entry))
+               + DST_const(entry).value.length
+               - sizeof(DST_const(entry).value.val);
+       break;
+    case dst_typ_reference:
+       size = sizeof(DST_reference(entry));
+       break;
+    case dst_typ_old_record:
+    case dst_typ_old_union:
+    case dst_typ_record:
+    case dst_typ_union:
+       size = sizeof(DST_record(entry))
+               + ((int) DST_record(entry).nfields
+                  - dst_dummy_array_size) * sizeof(dst_field_t);
+       break;
+    case dst_typ_aux_type_deriv:
+       size = sizeof(DST_aux_type_deriv(entry));
+       break;
+    case dst_typ_locpool:
+       size = sizeof(DST_locpool(entry))
+               + ((int) DST_locpool(entry).length -
+                  dst_dummy_array_size);
+       break;
+    case dst_typ_variable:
+       size = sizeof(DST_variable(entry));
+       break;
+    case dst_typ_label:
+       size = sizeof(DST_label(entry));
+       break;
+    case dst_typ_entry:
+       size = sizeof(DST_entry(entry));
+       break;
+    case dst_typ_aux_lifetime:
+       size = sizeof(DST_aux_lifetime(entry));
+       break;
+    case dst_typ_aux_ptr_base:
+       size = sizeof(DST_aux_ptr_base(entry));
+       break;
+    case dst_typ_aux_src_range:
+       size = sizeof(DST_aux_src_range(entry));
+       break;
+    case dst_typ_aux_reg_val:
+       size = sizeof(DST_aux_reg_val(entry));
+       break;
+    case dst_typ_aux_unit_names:
+       size = sizeof(DST_aux_unit_names(entry))
+               + ((int) DST_aux_unit_names(entry).number_of_names
+                  - dst_dummy_array_size) * sizeof(dst_rel_offset_t);
+       break;
+    case dst_typ_aux_sect_info:
+       size = sizeof(DST_aux_sect_info(entry))
+               + ((int) DST_aux_sect_info(entry).number_of_refs
+                  - dst_dummy_array_size) * sizeof(dst_sect_ref_t);
+       break;
+    default:
+       size = -1;
+       break;
+    }
+    if (size == -1)
+    {
+       fprintf(stderr, "Warning: unexpected DST entry type (%d) found\nLast valid entry was of type: %d\n",
+               (int) entry->rec_type,
+               last_type);
+       fprintf(stderr, "Last unknown_3 value: %d\n", lu3);
+       size = 0;
+    }
+    else
+       last_type = entry->rec_type;
+    if (size & 1) /* Align on a word boundary */
+       size++;
+   size += 2;
+   *ret_entry = entry;
+   return size;
+}
+
+static int next_dst_entry(buffer, entry, table)
+    char **buffer;
+    dst_rec_ptr_t *entry;
+    dst_sec *table;
+{
+    if (*buffer - table->buffer >= table->size)
+    {
+       *entry = NULL;
+       return 0;
+    }
+    *buffer += get_dst_entry(*buffer, entry);
+    return 1;
+}
+
+#define NEXT_BLK(a, b) next_dst_entry(a, b, &blocks_info)
+#define NEXT_SYM(a, b) next_dst_entry(a, b, &symbols_info)
+#define        DST_OFFSET(a, b) ((char *) (a) + (b))
+
+static dst_rec_ptr_t   section_table = NULL;
+
+char *
+get_sec_ref(ref)
+    dst_sect_ref_t *ref;
+{
+       dst_sec *section = NULL;
+       long offset;
+
+       if (!section_table || !ref->sect_index)
+               return NULL;
+       offset = DST_section_tab(section_table).section_base[ref->sect_index-1]
+               + ref->sect_offset;
+       if (offset >= blocks_info.base &&
+           offset < blocks_info.base + blocks_info.size)
+               section = &blocks_info;
+       else if (offset >= symbols_info.base &&
+                offset < symbols_info.base + symbols_info.size)
+               section = &symbols_info;
+       else if (offset >= lines_info.base &&
+                offset < lines_info.base + lines_info.size)
+               section = &lines_info;
+       if (!section)
+               return NULL;
+       return section->buffer + (offset - section->base);
+}
+
+CORE_ADDR
+dst_get_addr(int section, long offset)
+{
+       if (!section_table || !section)
+               return 0;
+       return DST_section_tab(section_table).section_base[section-1] + offset;
+}
+
+CORE_ADDR
+dst_sym_addr(ref)
+    dst_sect_ref_t *ref;
+{
+       if (!section_table || !ref->sect_index)
+               return 0;
+       return DST_section_tab(section_table).section_base[ref->sect_index-1]
+               + ref->sect_offset;
+}
+
+static struct type *
+create_new_type(objfile)
+    struct objfile *objfile;
+{
+       struct type *type;
+
+       type = (struct type *)
+               obstack_alloc (&objfile->symbol_obstack, sizeof (struct type));
+       memset(type, 0, sizeof(struct type));
+       return type;
+}
+
+static struct symbol *
+create_new_symbol(objfile, name)
+    struct objfile *objfile;
+    char *name;
+{
+       struct symbol *sym = (struct symbol *)
+              obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
+       memset (sym, 0, sizeof (struct symbol));
+       SYMBOL_NAME (sym) = obstack_copy0 (&objfile->symbol_obstack,
+                                               name, strlen (name));
+       SYMBOL_VALUE (sym) = 0;
+       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+       SYMBOL_CLASS (sym) = LOC_BLOCK;
+       return sym;
+};
+
+static struct type *
+decode_dst_type PARAMS ((struct objfile *, dst_rec_ptr_t));
+
+static struct type *
+decode_type_desc(objfile, type_desc, base)
+       struct objfile *objfile;
+       dst_type_t *type_desc;
+       dst_rec_ptr_t base;
+{
+       struct type *type;
+       dst_rec_ptr_t entry;
+       if (type_desc->std_type.user_defined_type)
+       {
+               entry = (dst_rec_ptr_t) DST_OFFSET(base,
+                                       dst_user_type_offset(*type_desc));
+               type = decode_dst_type(objfile, entry);
+       }
+       else
+       {
+               switch(type_desc->std_type.dtc)
+               {
+               case dst_int8_type:
+                       type = builtin_type_signed_char;
+                       break;
+               case dst_int16_type:
+                       type = builtin_type_short;
+                       break;
+               case dst_int32_type:
+                       type = builtin_type_long;
+                       break;
+               case dst_uint8_type:
+                       type = builtin_type_unsigned_char;
+                       break;
+               case dst_uint16_type:
+                       type = builtin_type_unsigned_short;
+                       break;
+               case dst_uint32_type:
+                       type = builtin_type_unsigned_long;
+                       break;
+               case dst_real32_type:
+                       type = builtin_type_float;
+                       break;
+               case dst_real64_type:
+                       type = builtin_type_double;
+                       break;
+               case dst_complex_type:
+                       type = builtin_type_complex;
+                       break;
+               case dst_dcomplex_type:
+                       type = builtin_type_double_complex;
+                       break;
+               case dst_bool8_type:
+                       type = builtin_type_char;
+                       break;
+               case dst_bool16_type:
+                       type = builtin_type_short;
+                       break;
+               case dst_bool32_type:
+                       type = builtin_type_long;
+                       break;
+               case dst_char_type:
+                       type = builtin_type_char;
+                       break;
+               /* The next few are more complex. I will take care
+                * of them properly at a later point.
+                */
+               case dst_string_type:
+                       type = builtin_type_void;
+                       break;
+               case dst_ptr_type:
+                       type = builtin_type_void;
+                       break;
+               case dst_set_type:
+                       type = builtin_type_void;
+                       break;
+               case dst_proc_type:
+                       type = builtin_type_void;
+                       break;
+               case dst_func_type:
+                       type = builtin_type_void;
+                       break;
+               /* Back tto some ordinary ones */
+               case dst_void_type:
+                       type = builtin_type_void;
+                       break;
+               case dst_uchar_type:
+                       type = builtin_type_unsigned_char;
+                       break;
+               default:
+                       type = builtin_type_void;
+                       break;
+               }
+       } 
+       return type;
+}
+
+struct structure_list
+    {
+    struct structure_list *next;
+    struct type *type;
+    };
+
+static struct structure_list *struct_list = NULL;
+
+static struct type *
+find_dst_structure(name)
+    char *name;
+{
+       struct structure_list *element;
+
+       for (element = struct_list; element; element = element->next)
+               if (!strcmp(name, TYPE_NAME(element->type)))
+                       return element->type;
+       return NULL;
+}
+
+
+static struct type *
+decode_dst_structure(objfile, entry, code, version)
+    struct objfile *objfile;
+    dst_rec_ptr_t entry;
+    int code;
+    int version;
+{
+       struct  type *type, *child_type;
+       char    *struct_name;
+       char    *name, *field_name;
+       int     i;
+       int     fieldoffset, fieldsize;
+       dst_type_t type_desc;
+       struct structure_list *element;
+
+       struct_name = DST_OFFSET(entry, DST_record(entry).noffset);
+       name = concat( (code == TYPE_CODE_UNION)?"union ":"struct ",
+                       struct_name, NULL);
+       type = find_dst_structure(name);
+       if (type)
+       {
+               free((PTR) name);
+               return type;
+       }
+       type = create_new_type(objfile);
+       TYPE_NAME(type) = obstack_copy0 (&objfile->symbol_obstack,
+                                               name, strlen(name));
+       free((PTR) name);
+       TYPE_CODE(type) = code;
+       TYPE_LENGTH(type) = DST_record(entry).size;
+       TYPE_NFIELDS(type) = DST_record(entry).nfields;
+       TYPE_FIELDS(type) = (struct field *)
+              obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) *
+                                       DST_record(entry).nfields);
+       fieldoffset = fieldsize = 0;
+       INIT_CPLUS_SPECIFIC(type);
+       element = (struct structure_list *)
+                               xmalloc(sizeof(struct structure_list));
+       element->type = type;
+       element->next = struct_list;
+       struct_list = element;
+       for (i = 0; i < DST_record(entry).nfields; i++)
+       {
+               switch (version)
+               {
+               case 2:
+                       field_name = DST_OFFSET(entry,
+                                       DST_record(entry).f.ofields[i].noffset);
+                       fieldoffset = DST_record(entry).f.ofields[i].foffset*8 +
+                                     DST_record(entry).f.ofields[i].bit_offset;
+                       fieldsize = DST_record(entry).f.ofields[i].size;
+                       type_desc = DST_record(entry).f.ofields[i].type_desc;
+                       break;
+               case 1:
+                       field_name = DST_OFFSET(entry,
+                                       DST_record(entry).f.fields[i].noffset);
+                       type_desc = DST_record(entry).f.fields[i].type_desc;
+                       switch(DST_record(entry).f.fields[i].f.field_loc.format_tag)
+                       {
+                       case dst_field_byte:
+                               fieldoffset = DST_record(entry).f.
+                                       fields[i].f.field_byte.offset * 8;
+                               fieldsize = -1;
+                               break;
+                       case dst_field_bit:
+                               fieldoffset = DST_record(entry).f.
+                                       fields[i].f.field_bit.byte_offset * 8 +
+                                             DST_record(entry).f.
+                                       fields[i].f.field_bit.bit_offset;
+                               fieldsize = DST_record(entry).f.
+                                       fields[i].f.field_bit.nbits;
+                               break;
+                       case dst_field_loc:
+                               fieldoffset += fieldsize;
+                               fieldsize = -1;
+                               break;
+                       }
+                       break;
+               case 0:
+                       field_name = DST_OFFSET(entry,
+                                       DST_record(entry).f.sfields[i].noffset);
+                       fieldoffset = DST_record(entry).f.sfields[i].foffset;
+                       type_desc = DST_record(entry).f.sfields[i].type_desc;
+                       if (i < DST_record(entry).nfields - 1)
+                               fieldsize = DST_record(entry).f.sfields[i+1].foffset;
+                       else
+                               fieldsize = DST_record(entry).size;
+                       fieldsize -= fieldoffset;
+                       fieldoffset *= 8;
+                       fieldsize *= 8;
+               }
+               TYPE_FIELDS(type)[i].name = 
+                       obstack_copy0 (&objfile->symbol_obstack,
+                                               field_name, strlen(field_name));
+               TYPE_FIELDS(type)[i].type = decode_type_desc(objfile,
+                                               &type_desc,
+                                               entry);
+               if (fieldsize == -1)
+                       fieldsize = TYPE_LENGTH(TYPE_FIELDS(type)[i].type) *
+                                       8;
+               TYPE_FIELDS(type)[i].bitsize = fieldsize;
+               TYPE_FIELDS(type)[i].bitpos = fieldoffset;
+       }
+       return type;
+}
+
+static struct type *
+decode_dst_type(objfile, entry)
+    struct objfile *objfile;
+    dst_rec_ptr_t entry;
+{
+       struct type *child_type, *type, *range_type, *index_type;
+
+       switch(entry->rec_type)
+       {
+       case dst_typ_var:
+               return decode_type_desc(objfile,
+                                       &DST_var(entry).type_desc,
+                                       entry);
+               break;
+       case dst_typ_variable:
+               return decode_type_desc(objfile,
+                                       &DST_variable(entry).type_desc,
+                                       entry);
+               break;
+       case dst_typ_short_rec:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,0);
+       case dst_typ_short_union:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 0);
+       case dst_typ_union:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 1);
+       case dst_typ_record:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,1);
+       case dst_typ_old_union:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_UNION, 2);
+       case dst_typ_old_record:
+               return decode_dst_structure(objfile, entry, TYPE_CODE_STRUCT,2);
+       case dst_typ_pointer:
+               return make_pointer_type(
+                               decode_type_desc(objfile,
+                                       &DST_pointer(entry).type_desc,
+                                       entry),
+                               NULL);
+       case dst_typ_array:
+               child_type = decode_type_desc(objfile,
+                                            &DST_pointer(entry).type_desc,
+                                            entry);
+               index_type = lookup_fundamental_type(objfile,
+                                                       FT_INTEGER);
+               range_type = create_range_type ((struct type *) NULL,
+                               index_type, DST_array(entry).lo_bound,
+                                       DST_array(entry).hi_bound);
+               return create_array_type ((struct type *) NULL, child_type,
+                                       range_type);
+       case dst_typ_alias:
+               return decode_type_desc(objfile,
+                                       &DST_alias(entry).type_desc,
+                                       entry);
+       default:
+               return builtin_type_int;
+       }
+}
+
+struct symbol_list {
+       struct symbol_list *next;
+       struct symbol *symbol;
+};
+
+static struct  symbol_list *dst_global_symbols = NULL;
+static int     total_globals = 0;
+
+static void
+decode_dst_locstring(locstr, sym)
+    char *locstr;
+    struct symbol *sym;
+{
+       dst_loc_entry_t *entry, *next_entry;
+       CORE_ADDR       temp;
+       int count = 0;
+
+       while(1)
+       {
+               if (count++ == 100)
+               {
+                       fprintf(stderr, "Error reading locstring\n");
+                       break;
+               }
+               entry = (dst_loc_entry_t *) locstr;
+               next_entry = (dst_loc_entry_t *) (locstr + 1);
+               switch (entry->header.code)
+               {
+               case dst_lsc_end:       /* End of string */
+                       return;
+               case dst_lsc_indirect:/* Indirect through previous. Arg == 6 */
+                                       /* Or register ax x == arg */
+                       if (entry->header.arg < 6)
+                       {
+                               SYMBOL_CLASS(sym) = LOC_REGISTER;
+                               SYMBOL_VALUE(sym) = entry->header.arg + 8;
+                       }
+                       /* We predict indirects */
+                       locstr++;
+                       break;
+               case dst_lsc_dreg:
+                       SYMBOL_CLASS(sym) = LOC_REGISTER;
+                       SYMBOL_VALUE(sym) = entry->header.arg;
+                       locstr++;
+                       break;
+               case dst_lsc_section:/* Section (arg+1) */
+                       SYMBOL_VALUE(sym) = dst_get_addr(entry->header.arg+1, 0);
+                       locstr++;
+                       break;
+               case dst_lsc_sec_byte: /* Section (next_byte+1) */
+                       SYMBOL_VALUE(sym) = dst_get_addr(locstr[1]+1, 0);
+                       locstr+=2;
+                       break;
+               case dst_lsc_add:       /* Add (arg+1)*2 */
+               case dst_lsc_sub:       /* Subtract (arg+1)*2 */
+                       temp = (entry->header.arg + 1) * 2;
+                       locstr++;
+                       if (*locstr == dst_multiply_256)
+                       {
+                               temp <<= 8;
+                               locstr++;
+                       }
+                       switch(entry->header.code)
+                       {
+                       case dst_lsc_add:
+                               if (SYMBOL_CLASS(sym) == LOC_LOCAL)
+                                       SYMBOL_CLASS(sym) = LOC_ARG;
+                               SYMBOL_VALUE(sym) += temp;
+                               break;
+                       case dst_lsc_sub:
+                               SYMBOL_VALUE(sym) -= temp;
+                               break;
+                       }
+                       break;
+               case dst_lsc_add_byte:
+               case dst_lsc_sub_byte:
+                       switch (entry->header.arg & 0x03)
+                       {
+                       case 1:
+                               temp = (unsigned char) locstr[1];
+                               locstr += 2;
+                               break;
+                       case 2:
+                               temp = * (unsigned short *) (locstr + 1);
+                               locstr += 3;
+                               break;
+                       case 3:
+                               temp = * (unsigned long *) (locstr + 1);
+                               locstr += 5;
+                               break;
+                       }
+                       if (*locstr == dst_multiply_256)
+                       {
+                               temp <<= 8;
+                               locstr++;
+                       }
+                       switch(entry->header.code)
+                       {
+                       case dst_lsc_add_byte:
+                               if (SYMBOL_CLASS(sym) == LOC_LOCAL)
+                                       SYMBOL_CLASS(sym) = LOC_ARG;
+                               SYMBOL_VALUE(sym) += temp;
+                               break;
+                       case dst_lsc_sub_byte:
+                               SYMBOL_VALUE(sym) -= temp;
+                               break;
+                       }
+                       break;
+               case dst_lsc_sbreg:     /* Stack base register (frame pointer). Arg==0*/
+                       if (next_entry->header.code != dst_lsc_indirect)
+                       {
+                               SYMBOL_VALUE(sym) = 0;
+                               SYMBOL_CLASS(sym) = LOC_STATIC;
+                               return;
+                       }
+                       SYMBOL_VALUE(sym) = 0;
+                       SYMBOL_CLASS(sym) = LOC_LOCAL;
+                       locstr++;
+                       break;
+               default:
+                       SYMBOL_VALUE(sym) = 0;
+                       SYMBOL_CLASS(sym) = LOC_STATIC;
+                       return;
+               }
+       }
+}
+
+static struct symbol_list *
+process_dst_symbols(objfile, entry, name, nsyms_ret)
+    struct objfile *objfile;
+    dst_rec_ptr_t entry;
+    char *name;
+    int *nsyms_ret;
+{
+       struct symbol_list *list = NULL, *element;
+       struct symbol *sym;
+       char *symname;
+       int nsyms = 0;
+       char *location;
+       long line;
+       dst_type_t symtype;
+       struct type *type;
+       dst_var_attr_t attr;
+       dst_var_loc_t loc_type;
+       unsigned loc_index;
+       long    loc_value;
+
+       if (!entry)
+       {
+               *nsyms_ret = 0;
+               return NULL;
+       }
+       location = (char *) entry;
+       while (NEXT_SYM(&location, &entry) &&
+              entry->rec_type != dst_typ_end_scope)
+       {
+               if (entry->rec_type == dst_typ_var)
+               {
+                       if (DST_var(entry).short_locs)
+                       {
+                               loc_type = DST_var(entry).locs.shorts[0].loc_type;
+                               loc_index = DST_var(entry).locs.shorts[0].loc_index;
+                               loc_value = DST_var(entry).locs.shorts[0].location;
+                       }
+                       else
+                       {
+                               loc_type = DST_var(entry).locs.longs[0].loc_type;
+                               loc_index = DST_var(entry).locs.longs[0].loc_index;
+                               loc_value = DST_var(entry).locs.longs[0].location;
+                       }
+                       if (loc_type == dst_var_loc_external)
+                               continue;
+                       symname = DST_OFFSET(entry, DST_var(entry).noffset);
+                       line = DST_var(entry).src_loc.line_number;
+                       symtype = DST_var(entry).type_desc;
+                       attr = DST_var(entry).attributes;
+               }
+               else if (entry->rec_type == dst_typ_variable)
+               {
+                       symname = DST_OFFSET(entry,
+                                               DST_variable(entry).noffset);
+                       line = DST_variable(entry).src_loc.line_number;
+                       symtype = DST_variable(entry).type_desc;
+                       attr = DST_variable(entry).attributes;
+               }
+               else
+               {
+                       continue;
+               }
+               if (symname && name && !strcmp(symname, name))
+                       /* It's the function return value */
+                       continue;
+               sym = create_new_symbol(objfile, symname);
+
+               if ((attr & (1<<dst_var_attr_global)) ||
+                   (attr & (1<<dst_var_attr_static)))
+                       SYMBOL_CLASS(sym) = LOC_STATIC;
+               else
+                       SYMBOL_CLASS(sym) = LOC_LOCAL;
+               SYMBOL_LINE(sym) = line;
+               SYMBOL_TYPE(sym) = decode_type_desc(objfile, &symtype,
+                                               entry);
+               SYMBOL_VALUE(sym) = 0;
+               switch (entry->rec_type)
+               {
+               case dst_typ_var:
+                       switch(loc_type)
+                       {
+                       case dst_var_loc_abs:
+                               SYMBOL_VALUE_ADDRESS(sym) = loc_value;
+                               break;
+                       case dst_var_loc_sect_off:
+                       case dst_var_loc_ind_sect_off: /* What is this? */
+                               SYMBOL_VALUE_ADDRESS(sym) = dst_get_addr(
+                                               loc_index,
+                                               loc_value);
+                               break;
+                       case dst_var_loc_ind_reg_rel: /* What is this? */
+                       case dst_var_loc_reg_rel:
+                               /* If it isn't fp relative, specify the
+                                * register it's relative to.
+                                */
+                               if (loc_index)
+                               {
+                                       sym->aux_value.basereg = loc_index;
+                               }
+                               SYMBOL_VALUE(sym) = loc_value;
+                               if (loc_value > 0 &&
+                                   SYMBOL_CLASS(sym) == LOC_BASEREG)
+                                       SYMBOL_CLASS(sym) = LOC_BASEREG_ARG;
+                               break;
+                       case dst_var_loc_reg:
+                               SYMBOL_VALUE(sym) = loc_index;
+                               SYMBOL_CLASS(sym) = LOC_REGISTER;
+                               break;
+                       }
+                       break;
+               case dst_typ_variable:
+                       /* External variable..... don't try to interpret
+                        * its nonexistant locstring.
+                        */
+                       if (DST_variable(entry).loffset == -1)
+                               continue;
+                       decode_dst_locstring(DST_OFFSET(entry,
+                                               DST_variable(entry).loffset),
+                                            sym);
+               }
+               element = (struct symbol_list *)
+                               xmalloc(sizeof(struct symbol_list));
+               
+               if (attr & (1<<dst_var_attr_global))
+               {
+                       element->next = dst_global_symbols;
+                       dst_global_symbols = element;
+                       total_globals++;
+               }
+               else
+               {
+                       element->next = list;
+                       list = element;
+                       nsyms++;
+               }
+               element->symbol = sym;
+       }
+       *nsyms_ret = nsyms;
+       return list;
+}
+
+
+static struct symbol *
+process_dst_function(objfile, entry, name, address)
+    struct objfile *objfile;
+    dst_rec_ptr_t entry;
+    char *name;
+    CORE_ADDR address;
+{
+       struct  symbol *sym;
+       struct  type *type, *ftype;
+       dst_rec_ptr_t sym_entry, typ_entry;
+       char *location;
+       struct symbol_list *element;
+
+       type = builtin_type_int;
+       sym = create_new_symbol(objfile, name);
+       SYMBOL_CLASS(sym) = LOC_BLOCK;
+
+       if (entry)
+       {
+               location = (char *) entry;
+               do
+               {
+                       NEXT_SYM(&location, &sym_entry);
+               } while (sym_entry && sym_entry->rec_type != dst_typ_signature);
+
+               if (sym_entry)
+               {
+                       SYMBOL_LINE(sym) =
+                               DST_signature(sym_entry).src_loc.line_number;
+                       if (DST_signature(sym_entry).result)
+                       {
+                               typ_entry = (dst_rec_ptr_t)
+                                           DST_OFFSET(sym_entry,
+                                           DST_signature(sym_entry).result);
+                               type = decode_dst_type(objfile, typ_entry);
+                       }
+               }
+       }
+
+       if (!type->function_type)
+       {
+               ftype = create_new_type(objfile);
+               type->function_type = ftype;
+               ftype->target_type = type;
+               ftype->code = TYPE_CODE_FUNC;
+       }
+       SYMBOL_TYPE(sym) = type->function_type;
+
+       /* Now add ourselves to the global symbols list */
+       element = (struct symbol_list *)
+                       xmalloc(sizeof(struct symbol_list));
+
+       element->next = dst_global_symbols;
+       dst_global_symbols = element;
+       total_globals++;
+       element->symbol = sym;
+
+       return sym;
+}
+
+static struct block *
+process_dst_block(objfile, entry)
+    struct objfile *objfile;
+    dst_rec_ptr_t entry;
+{
+       struct  block   *block;
+       struct  symbol  *function = NULL;
+       CORE_ADDR address;
+       long    size;
+       char    *name;
+       dst_rec_ptr_t child_entry, symbol_entry;
+       struct block *child_block;
+       int     total_symbols = 0;
+       struct pending_block *pblock;
+       char    fake_name[20];
+       static  long    fake_seq = 0;
+       struct symbol_list *symlist, *nextsym;
+       int     symnum;
+
+       if (DST_block(entry).noffset)
+               name = DST_OFFSET(entry, DST_block(entry).noffset);
+       else
+               name = NULL;
+       if (DST_block(entry).n_of_code_ranges)
+       {
+               address = dst_sym_addr(
+                               &DST_block(entry).code_ranges[0].code_start);
+               size = DST_block(entry).code_ranges[0].code_size;
+       }
+       else
+       {
+               address = -1;
+               size = 0;
+       }
+       symbol_entry = (dst_rec_ptr_t) get_sec_ref(&DST_block(entry).symbols_start);
+       switch(DST_block(entry).block_type)
+       {
+       /* These are all really functions. Even the "program" type.
+        * This is because the Apollo OS was written in Pascal, and
+        * in Pascal, the main procedure is described as the Program.
+        * Cute, huh?
+        */
+       case dst_block_procedure:
+       case dst_block_function:
+       case dst_block_subroutine:
+       case dst_block_program:
+               record_minimal_symbol(name, address, mst_text);
+               function = process_dst_function(
+                       objfile,
+                       symbol_entry,
+                       name,
+                       address);
+               enter_all_lines(get_sec_ref(&DST_block(entry).code_ranges[0].lines_start), address);
+               break;
+       case dst_block_block_data:
+               break;
+
+       default:
+               /* GDB has to call it something, and the module name
+                * won't cut it
+                */
+               sprintf(fake_name, "block_%08lx", fake_seq++);
+               function = process_dst_function(
+                       objfile, NULL, fake_name, address);
+               break;
+       }
+       symlist = process_dst_symbols(objfile, symbol_entry,
+                                       name, &total_symbols);
+       block = (struct block *)
+           obstack_alloc (&objfile->symbol_obstack,
+                               sizeof (struct block) +
+                               (total_symbols - 1) * sizeof (struct symbol *));
+
+       symnum = 0;
+       while (symlist)
+       {
+               nextsym = symlist->next;
+
+               block->sym[symnum] = symlist->symbol;
+
+               free((PTR) symlist);
+               symlist = nextsym;
+               symnum++;
+       }
+       BLOCK_NSYMS (block) = total_symbols;
+       BLOCK_START (block) = address;
+       BLOCK_END (block) = address + size;
+       BLOCK_SUPERBLOCK (block) = 0;
+       if (function)
+       {
+               SYMBOL_BLOCK_VALUE (function) = block;
+               BLOCK_FUNCTION (block) = function;
+       }
+       else
+               BLOCK_FUNCTION (block) = 0;
+
+       pblock = (struct pending_block *)
+                       xmalloc (sizeof (struct pending_block));
+       pblock->block = block;
+       pblock->next = pending_blocks;
+       pending_blocks = pblock;
+       if (DST_block(entry).child_block_off)
+       {
+               child_entry = (dst_rec_ptr_t) DST_OFFSET(entry,
+                                       DST_block(entry).child_block_off);
+               while (child_entry)
+               {
+                       child_block = process_dst_block(objfile, child_entry);
+                       if (child_block)
+                       {
+                               if (BLOCK_START(child_block) <
+                                    BLOCK_START(block) ||
+                                   BLOCK_START(block) == -1)
+                                       BLOCK_START(block) =
+                                            BLOCK_START(child_block);
+                               if (BLOCK_END(child_block) >
+                                    BLOCK_END(block) ||
+                                   BLOCK_END(block) == -1)
+                                       BLOCK_END(block) =
+                                            BLOCK_END(child_block);
+                               BLOCK_SUPERBLOCK (child_block) = block;
+                       }
+                       if (DST_block(child_entry).sibling_block_off)
+                               child_entry = (dst_rec_ptr_t) DST_OFFSET(
+                                       child_entry,
+                                       DST_block(child_entry).sibling_block_off);
+                       else
+                               child_entry = NULL;
+               }
+       }
+       return block;
+}
+
+
+static void
+read_dst_symtab (objfile)
+     struct objfile *objfile;
+{
+       char    *buffer;
+       dst_rec_ptr_t entry, file_table, root_block;
+       char    *source_file;
+       struct  block *block, *global_block;
+       struct  pending_block *pblock;
+       int     symnum;
+       struct symbol_list *nextsym;
+       int     module_num = 0;
+       struct  structure_list *element;
+
+       current_objfile = objfile;
+       buffer = blocks_info.buffer;
+       while (NEXT_BLK(&buffer, &entry))
+       {
+               if (entry->rec_type == dst_typ_comp_unit)
+               {
+                       file_table = (dst_rec_ptr_t) DST_OFFSET(entry,
+                                       DST_comp_unit(entry).file_table);
+                       section_table = (dst_rec_ptr_t) DST_OFFSET(entry,
+                                       DST_comp_unit(entry).section_table);
+                       root_block = (dst_rec_ptr_t) DST_OFFSET(entry,
+                                       DST_comp_unit(entry).root_block_offset);
+                       source_file = DST_OFFSET(file_table,
+                                       DST_file_tab(file_table).files[0].noffset);
+                       /* Point buffer to the start of the next comp_unit */
+                       buffer = DST_OFFSET(entry,
+                                       DST_comp_unit(entry).data_size);
+                       dst_start_symtab();
+
+                       pblock = (struct pending_block *)
+                               xmalloc (sizeof (struct pending_block));
+                       pblock->next = NULL;
+                       pending_blocks = pblock;
+       
+                       block = process_dst_block(objfile, root_block);
+
+                       global_block = (struct block *)
+                                   obstack_alloc (&objfile->symbol_obstack,
+                                       sizeof (struct block) +
+                                       (total_globals - 1) *
+                                       sizeof (struct symbol *));
+                       BLOCK_NSYMS(global_block) = total_globals;
+                       for (symnum = 0; symnum < total_globals; symnum++)
+                       {
+                               nextsym = dst_global_symbols->next;
+
+                               global_block->sym[symnum] =
+                                               dst_global_symbols->symbol;
+
+                               free((PTR) dst_global_symbols);
+                               dst_global_symbols = nextsym;
+                       }
+                       dst_global_symbols = NULL;
+                       total_globals = 0;
+                       BLOCK_FUNCTION(global_block) = 0;
+                       BLOCK_START(global_block) = BLOCK_START(block);
+                       BLOCK_END(global_block) = BLOCK_END(block);
+                       BLOCK_SUPERBLOCK(global_block) = 0;
+                       BLOCK_SUPERBLOCK(block) = global_block;
+                       pblock->block = global_block;
+
+                       complete_symtab(source_file,
+                                       BLOCK_START(block), 
+                                       BLOCK_END(block) - BLOCK_START(block));
+                       module_num++;
+                       dst_end_symtab(objfile);
+               }
+       }
+       if (module_num)
+               record_minimal_symbol("<end_of_program>",
+                               BLOCK_END(block), mst_text);
+       /* One more faked symbol to make sure nothing can ever run off the
+        * end of the symbol table. This one represents the end of the
+        * text space. It used to be (CORE_ADDR) -1 (effectively the highest
+        * int possible), but some parts of gdb treated it as a signed
+        * number and failed comparisons. We could equally use 7fffffff,
+        * but no functions are ever mapped to an address higher than
+        * 40000000
+        */
+       record_minimal_symbol("<end_of_text>",
+                               (CORE_ADDR) 0x40000000,
+                               mst_text);
+       while (struct_list)
+       {
+               element = struct_list;
+               struct_list = element->next;
+               free((PTR) element);
+       }
+}
+
+\f
+/* Support for line number handling */
+static char *linetab = NULL;
+static long linetab_offset;
+static unsigned long linetab_size;
+
+/* Read in all the line numbers for fast lookups later.  Leave them in
+   external (unswapped) format in memory; we'll swap them as we enter
+   them into GDB's data structures.  */
+static int
+init_one_section(chan, secinfo)
+    int chan;
+    dst_sec *secinfo;
+{
+  if (secinfo->size == 0
+      || lseek(chan, secinfo->position, 0) == -1
+      || (secinfo->buffer = xmalloc(secinfo->size)) == NULL
+      || myread(chan, secinfo->buffer, secinfo->size) == -1)
+       return 0;
+  else
+       return 1;
+}
+static int
+init_dst_sections (chan)
+    int chan;
+{
+
+  if (!init_one_section(chan, &blocks_info) ||
+      !init_one_section(chan, &lines_info) ||
+      !init_one_section(chan, &symbols_info))
+    return -1;
+  else
+    return 0;
+}
+
+/* Fake up support for relocating symbol addresses.  FIXME.  */
+
+struct section_offsets dst_symfile_faker = {0};
+
+struct section_offsets *
+dst_symfile_offsets (objfile, addr)
+     struct objfile *objfile;
+     CORE_ADDR addr;
+{
+  return &dst_symfile_faker;
+}
+
+/* Register our ability to parse symbols for DST BFD files */
+
+static struct sym_fns dst_sym_fns =
+{
+  "apollo",            /* sym_name: name or name prefix of BFD target type */
+  6,                   /* sym_namelen: number of significant sym_name chars */
+  dst_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dst_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dst_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dst_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  dst_symfile_offsets, /* sym_offsets:  xlate external to internal form */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_dstread ()
+{
+  add_symtab_fns(&dst_sym_fns);
+}