aboutsummaryrefslogtreecommitdiff
path: root/bfd/vms-hdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/vms-hdr.c')
-rw-r--r--bfd/vms-hdr.c1382
1 files changed, 0 insertions, 1382 deletions
diff --git a/bfd/vms-hdr.c b/bfd/vms-hdr.c
deleted file mode 100644
index 343f53e..0000000
--- a/bfd/vms-hdr.c
+++ /dev/null
@@ -1,1382 +0,0 @@
-/* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
- EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
- 2007, 2008, 2009 Free Software Foundation, Inc.
-
- HDR record handling functions
- EMH record handling functions
-
- EOM record handling functions
- EEOM record handling functions
-
- IHD record handling functions
- EIHD record handling functions
-
- ISD record handling functions
- EISD record handling functions
-
- IHS record handling functions
- EIHS record handling functions
-
- DBG record handling functions
- EDBG record handling functions
-
- TBT record handling functions
- ETBT record handling functions
-
- DST/DMT section handling functions
-
- Written by Klaus K"ampf (kkaempf@rmi.de)
-
- 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
-
-#include "sysdep.h"
-#include "bfd.h"
-#include "bfdver.h"
-#include "bfdlink.h"
-#include "safe-ctype.h"
-#include "libbfd.h"
-
-#include "vms.h"
-
-static struct module *new_module (bfd *);
-static void parse_module
- (bfd *, struct module *, unsigned char *, unsigned int);
-static struct module *build_module_list (bfd *);
-static bfd_boolean module_find_nearest_line
- (bfd *, struct module *, bfd_vma, const char **, const char **,
- unsigned int *);
-static int vms_slurp_debug (bfd *);
-
-#define SET_MODULE_PARSED(m) \
- do { if ((m)->name == NULL) (m)->name = ""; } while (0)
-#define IS_MODULE_PARSED(m) ((m)->name != NULL)
-
-
-/* Read & process emh record
- return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_hdr (bfd *abfd, int objtype)
-{
- unsigned char *ptr;
- unsigned char *vms_rec;
- int subtype;
-
- vms_rec = PRIV(vms_rec);
-
-#if VMS_DEBUG
- vms_debug(2, "HDR/EMH\n");
-#endif
-
- switch (objtype)
- {
- case OBJ_S_C_HDR:
- subtype = vms_rec[1];
- break;
- case EOBJ_S_C_EMH:
- subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET;
- break;
- default:
- subtype = -1;
- }
-
-#if VMS_DEBUG
- vms_debug(3, "subtype %d\n", subtype);
-#endif
-
- switch (subtype)
- {
- case MHD_S_C_MHD:
- /* Module header. */
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[2];
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3);
- PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5);
- ptr = vms_rec + 5 + vms_rec[5] + 1;
- PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr);
- ptr += *ptr + 1;
- PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
- break;
-
- case MHD_S_C_LNM:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case MHD_S_C_SRC:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case MHD_S_C_TTL:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
- break;
-
- case EMH_S_C_MHD + EVAX_OFFSET:
- /* Module header. */
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
- PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
- PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
- PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20);
- ptr = vms_rec + 20 + vms_rec[20] + 1;
- PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
- ptr += *ptr + 1;
- PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
- break;
-
- case EMH_S_C_LNM + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case EMH_S_C_SRC + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case EMH_S_C_TTL + EVAX_OFFSET:
- PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
- break;
-
- case MHD_S_C_CPR:
- case MHD_S_C_MTC:
- case MHD_S_C_GTX:
- case EMH_S_C_CPR + EVAX_OFFSET:
- case EMH_S_C_MTC + EVAX_OFFSET:
- case EMH_S_C_GTX + EVAX_OFFSET:
- break;
-
- default:
- bfd_set_error (bfd_error_wrong_format);
- return -1;
- }
-
- return 0;
-}
-
-/* Output routines. */
-
-/* Manufacture a VMS like time on a unix based system.
- stolen from obj-vms.c. */
-
-static unsigned char *
-get_vms_time_string (void)
-{
- static unsigned char tbuf[18];
-#ifndef VMS
-#include <time.h>
-
- char *pnt;
- time_t timeb;
-
- time (& timeb);
- pnt = ctime (&timeb);
- pnt[3] = 0;
- pnt[7] = 0;
- pnt[10] = 0;
- pnt[16] = 0;
- pnt[24] = 0;
- sprintf ((char *) tbuf, "%2s-%3s-%s %s",
- pnt + 8, pnt + 4, pnt + 20, pnt + 11);
-#else
-#include <starlet.h>
- struct
- {
- int Size;
- unsigned char *Ptr;
- } Descriptor;
- Descriptor.Size = 17;
- Descriptor.Ptr = tbuf;
- SYS$ASCTIM (0, &Descriptor, 0, 0);
-#endif /* not VMS */
-
-#if VMS_DEBUG
- vms_debug (6, "vmstimestring:'%s'\n", tbuf);
-#endif
-
- return tbuf;
-}
-
-/* Write object header for bfd abfd. */
-
-int
-_bfd_vms_write_hdr (bfd *abfd, int objtype)
-{
- asymbol *symbol;
- unsigned int symnum;
- int had_case = 0;
- int had_file = 0;
- char version [256];
-
-#if VMS_DEBUG
- vms_debug (2, "vms_write_hdr (%p)\n", abfd);
-#endif
-
- _bfd_vms_output_alignment (abfd, 2);
-
- /* MHD. */
- if (objtype != OBJ_S_C_HDR)
- {
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD);
- _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL);
- _bfd_vms_output_long (abfd, 0);
- _bfd_vms_output_long (abfd, 0);
- _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE);
- }
-
- /* Create module name from filename. */
- if (bfd_get_filename (abfd) != 0)
- {
- char *module = vms_get_module_name (bfd_get_filename (abfd), TRUE);
- _bfd_vms_output_counted (abfd, module);
- free (module);
- }
- else
- _bfd_vms_output_counted (abfd, "NONAME");
-
- _bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
- _bfd_vms_output_dump (abfd, get_vms_time_string (), EMH_DATE_LENGTH);
- _bfd_vms_output_fill (abfd, 0, EMH_DATE_LENGTH);
- _bfd_vms_output_flush (abfd);
-
- /* LMN. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
- snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING);
- _bfd_vms_output_dump (abfd, (unsigned char *)version, strlen (version));
- _bfd_vms_output_flush (abfd);
-
- /* SRC. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC);
-
- for (symnum = 0; symnum < abfd->symcount; symnum++)
- {
- symbol = abfd->outsymbols[symnum];
-
- if (symbol->flags & BSF_FILE)
- {
- if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
- {
- PRIV (flag_hash_long_names) = symbol->name[6] - '0';
- PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
-
- if (had_file)
- break;
- had_case = 1;
- continue;
- }
-
- _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name,
- (int) strlen (symbol->name));
- if (had_case)
- break;
- had_file = 1;
- }
- }
-
- if (symnum == abfd->symcount)
- _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("noname"));
-
- _bfd_vms_output_flush (abfd);
-
- /* TTL. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL);
- _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("TTL"));
- _bfd_vms_output_flush (abfd);
-
- /* CPR. */
- _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR);
- _bfd_vms_output_dump (abfd,
- (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
- 39);
- _bfd_vms_output_flush (abfd);
-
- return 0;
-}
-
-/* Process EOM/EEOM record
- return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_eom (bfd *abfd, int objtype)
-{
- unsigned char *vms_rec;
-
-#if VMS_DEBUG
- vms_debug(2, "EOM/EEOM\n");
-#endif
-
- vms_rec = PRIV (vms_rec);
-
- if ((objtype == OBJ_S_C_EOM)
- || (objtype == OBJ_S_C_EOMW))
- {
- }
- else
- {
- PRIV (eom_data).eom_l_total_lps
- = bfd_getl32 (vms_rec + EEOM_S_L_TOTAL_LPS);
- PRIV (eom_data).eom_w_comcod = bfd_getl16 (vms_rec + EEOM_S_W_COMCOD);
- if (PRIV (eom_data).eom_w_comcod > 1)
- {
- (*_bfd_error_handler) (_("Object module NOT error-free !\n"));
- bfd_set_error (bfd_error_bad_value);
- return -1;
- }
- PRIV (eom_data).eom_has_transfer = FALSE;
- if (PRIV (rec_size) > 10)
- {
- PRIV (eom_data).eom_has_transfer = TRUE;
- PRIV (eom_data).eom_b_tfrflg = vms_rec[EEOM_S_B_TFRFLG];
- PRIV (eom_data).eom_l_psindx
- = bfd_getl32 (vms_rec + EEOM_S_L_PSINDX);
- PRIV (eom_data).eom_l_tfradr
- = bfd_getl32 (vms_rec + EEOM_S_L_TFRADR);
-
- abfd->start_address = PRIV (eom_data).eom_l_tfradr;
- }
- }
- return 0;
-}
-
-/* Write eom record for bfd abfd. */
-
-int
-_bfd_vms_write_eom (bfd *abfd, int objtype)
-{
-#if VMS_DEBUG
- vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype);
-#endif
-
- _bfd_vms_output_begin (abfd, objtype, -1);
- _bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1));
- _bfd_vms_output_byte (abfd, 0); /* Completion code. */
- _bfd_vms_output_byte (abfd, 0); /* Fill byte. */
-
- if (bfd_get_start_address (abfd) != (bfd_vma)-1)
- {
- asection *section;
-
- section = bfd_get_section_by_name (abfd, ".link");
- if (section == 0)
- {
- bfd_set_error (bfd_error_nonrepresentable_section);
- return -1;
- }
- _bfd_vms_output_short (abfd, 0);
- _bfd_vms_output_long (abfd, (unsigned long) (section->index));
- _bfd_vms_output_long (abfd,
- (unsigned long) bfd_get_start_address (abfd));
- _bfd_vms_output_long (abfd, 0);
- }
-
- _bfd_vms_output_end (abfd);
- return 0;
-}
-
-/* Read & process IHD/EIHD record.
- Return 0 on success, -1 on error */
-int
-_bfd_vms_slurp_ihd (bfd *abfd, unsigned int *isd_offset,
- unsigned int *ihs_offset)
-{
- unsigned int imgtype, size;
- bfd_vma symvva;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_slurp_ihd\n");
-#endif
-
- size = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
- imgtype = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_IMGTYPE);
-
- if (imgtype == EIHD_S_K_EXE)
- abfd->flags |= EXEC_P;
-
- symvva = bfd_getl64 (PRIV (vms_rec) + EIHD_S_Q_SYMVVA);
- if (symvva != 0)
- {
- PRIV (symvva) = symvva;
- abfd->flags |= DYNAMIC;
- }
-
- *isd_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_ISDOFF);
- *ihs_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SYMDBGOFF);
-
-#if VMS_DEBUG
- vms_debug (4, "EIHD record size %d imgtype %d symvva 0x%llx isd %d ihs %d\n",
- size, imgtype, symvva, *isd_offset, *ihs_offset);
-#endif
-
- return 0;
-}
-
-/* Read & process ISD/EISD record
- return 0 on success, -1 on error */
-
-int
-_bfd_vms_slurp_isd (bfd *abfd, unsigned int offset)
-{
- int section_count = 0;
- unsigned char *p;
- unsigned int rec_size;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_slurp_isd\n");
-#endif
-
- for (p = PRIV (vms_rec) + offset;
- (rec_size = bfd_getl32 (p + EISD_S_L_EISDSIZE)) != 0;
- p += rec_size)
- {
- unsigned long long vaddr = bfd_getl64 (p + EISD_S_Q_VIR_ADDR);
- unsigned int size = bfd_getl32 (p + EISD_S_L_SECSIZE);
- unsigned int flags = bfd_getl32 (p + EISD_S_L_FLAGS);
- unsigned int vbn = bfd_getl32 (p + EISD_S_L_VBN);
- char *name = NULL;
- asection *section;
- flagword bfd_flags;
-
-#if VMS_DEBUG
- vms_debug (4, "EISD record at 0x%x size 0x%x addr 0x%x bfd_flags 0x%x block %d\n",
- p - PRIV (vms_rec), size, vaddr, flags, vbn);
-#endif
-
- /* VMS combines psects from .obj files into isects in the .exe. This
- process doesn't preserve enough information to reliably determine
- what's in each section without examining the data. This is
- especially true of DWARF debug sections. */
- bfd_flags = SEC_ALLOC;
-
- if (flags & EISD_S_M_EXE)
- bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD;
-
- if (flags & EISD_S_M_NONSHRADR)
- bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
-
- if (!(flags & EISD_S_M_WRT))
- bfd_flags |= SEC_READONLY;
-
- if (flags & EISD_S_M_DZRO)
- bfd_flags |= SEC_DATA;
-
- if (flags & EISD_S_M_FIXUPVEC)
- bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
-
- if (flags & EISD_S_M_CRF)
- bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
-
- if (flags & EISD_S_M_GBL)
- {
- name = _bfd_vms_save_counted_string (p + EISD_S_T_GBLNAM);
- bfd_flags |= SEC_COFF_SHARED_LIBRARY;
- bfd_flags &= ~(SEC_ALLOC | SEC_LOAD);
- }
- else
- {
- name = (char*) bfd_alloc (abfd, 32);
- sprintf (name, "$LOCAL_%03d$", section_count++);
- }
-
- section = bfd_make_section (abfd, name);
-
- if (!section)
- return -1;
-
- section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : (unsigned int)-1;
- section->size = size;
- section->vma = vaddr;
-
- if (!bfd_set_section_flags (abfd, section, bfd_flags))
- return -1;
- }
-
- return 0;
-}
-
-/* Read & process IHS/EIHS record
- return 0 on success, -1 on error */
-int
-_bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset)
-{
- unsigned char *p = PRIV (vms_rec) + offset;
- unsigned int gstvbn = bfd_getl32 (p + EIHS_S_L_GSTVBN);
- unsigned int gstsize ATTRIBUTE_UNUSED = bfd_getl32 (p + EIHS_S_L_GSTSIZE);
- unsigned int dstvbn = bfd_getl32 (p + EIHS_S_L_DSTVBN);
- unsigned int dstsize = bfd_getl32 (p + EIHS_S_L_DSTSIZE);
- unsigned int dmtvbn = bfd_getl32 (p + EIHS_S_L_DMTVBN);
- unsigned int dmtbytes = bfd_getl32 (p + EIHS_S_L_DMTBYTES);
- asection *section;
-
-#if VMS_DEBUG
- vms_debug (8, "_bfd_vms_slurp_ihs\n");
- vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n",
- gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes);
-#endif
-
- if (dstvbn)
- {
- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
-
- section = bfd_make_section (abfd, "$DST$");
- if (!section)
- return -1;
-
- section->size = dstsize;
- section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1);
-
- if (!bfd_set_section_flags (abfd, section, bfd_flags))
- return -1;
-
- PRIV (dst_section) = section;
- abfd->flags |= (HAS_DEBUG | HAS_LINENO);
- }
-
- if (dmtvbn)
- {
- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
-
- section = bfd_make_section (abfd, "$DMT$");
- if (!section)
- return -1;
-
- section->size = dmtbytes;
- section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1);
-
- if (!bfd_set_section_flags (abfd, section, bfd_flags))
- return -1;
- }
-
- if (gstvbn)
- {
- flagword bfd_flags = SEC_HAS_CONTENTS;
-
- section = bfd_make_section (abfd, "$GST$");
- if (!section)
- return -1;
-
- if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET))
- {
- bfd_set_error (bfd_error_file_truncated);
- return -1;
- }
-
- if (_bfd_vms_slurp_object_records (abfd) != 0)
- return -1;
-
- section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1);
- section->size = bfd_tell (abfd) - section->filepos;
-
- if (!bfd_set_section_flags (abfd, section, bfd_flags))
- return -1;
-
- abfd->flags |= HAS_SYMS;
- }
-
- return 0;
-}
-
-/* Build a new module for the specified BFD. */
-
-static struct module *
-new_module (bfd *abfd)
-{
- struct module *module
- = (struct module *) bfd_zalloc (abfd, sizeof (struct module));
- module->file_table_count = 16; /* Arbitrary. */
- module->file_table
- = bfd_malloc (module->file_table_count * sizeof (struct fileinfo));
- return module;
-}
-
-/* Parse debug info for a module and internalize it. */
-
-static void
-parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
- unsigned int length)
-{
- unsigned char *maxptr = ptr + length, *src_ptr, *pcl_ptr;
- unsigned int prev_linum = 0, curr_linenum = 0;
- bfd_vma prev_pc = 0, curr_pc = 0;
- struct srecinfo *curr_srec, *srec;
- struct lineinfo *curr_line, *line;
- struct funcinfo *funcinfo;
-
- /* Initialize tables with zero element. */
- curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
- module->srec_table = curr_srec;
-
- curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
- module->line_table = curr_line;
-
- while (ptr < maxptr)
- {
- /* The first byte is not counted in the recorded length. */
- int rec_length = bfd_getl16 (ptr) + 1;
- int rec_type = bfd_getl16 (ptr + 2);
-
-#if VMS_DEBUG
- _bfd_vms_debug (2, "DST record: length %d, type %d\n",
- rec_length, rec_type);
-#endif
-
- switch (rec_type)
- {
- case DST_S_C_MODBEG:
- module->name
- = _bfd_vms_save_counted_string (ptr + DST_S_B_MODBEG_NAME);
-
- curr_pc = 0;
- prev_pc = 0;
- curr_linenum = 0;
- prev_linum = 0;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "module: %s\n", module->name);
-#endif
- break;
-
- case DST_S_C_MODEND:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "end module\n");
-#endif
- break;
-
- case DST_S_C_RTNBEG:
- funcinfo = (struct funcinfo *)
- bfd_zalloc (abfd, sizeof (struct funcinfo));
- funcinfo->name
- = _bfd_vms_save_counted_string (ptr + DST_S_B_RTNBEG_NAME);
- funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS);
- funcinfo->next = module->func_table;
- module->func_table = funcinfo;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "routine: %s at 0x%x\n",
- funcinfo->name, funcinfo->low);
-#endif
- break;
-
- case DST_S_C_RTNEND:
- module->func_table->high = module->func_table->low
- + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1;
-
- if (module->func_table->high > module->high)
- module->high = module->func_table->high;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "end routine\n");
-#endif
- break;
-
- case DST_S_C_PROLOG:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "prologue\n");
-#endif
- break;
-
- case DST_S_C_EPILOG:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "epilog\n");
-#endif
- break;
-
- case DST_S_C_BLKBEG:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "block\n");
-#endif
- break;
-
- case DST_S_C_BLKEND:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "end block\n");
-#endif
- break;
-
- case DST_S_C_SOURCE:
- src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "source info\n");
-#endif
-
- while (src_ptr < ptr + rec_length)
- {
- int cmd = src_ptr[0], cmd_length, data;
-
- switch (cmd)
- {
- case DST_S_C_SRC_DECLFILE:
- {
- unsigned int fileid
- = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID);
- char *filename
- = _bfd_vms_save_counted_string (src_ptr
- + DST_S_B_SRC_DF_FILENAME);
-
- while (fileid >= module->file_table_count)
- {
- module->file_table_count *= 2;
- module->file_table
- = bfd_realloc (module->file_table,
- module->file_table_count
- * sizeof (struct fileinfo));
- }
-
- module->file_table [fileid].name = filename;
- module->file_table [fileid].srec = 1;
- cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_DECLFILE: %d, %s\n",
- fileid,
- module->file_table [fileid].name);
-#endif
- }
- break;
-
- case DST_S_C_SRC_DEFLINES_B:
- /* Perform the association and set the next higher index
- to the limit. */
- data = src_ptr[DST_S_B_SRC_UNSBYTE];
- srec = (struct srecinfo *)
- bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = curr_srec->line + data;
- srec->srec = curr_srec->srec + data;
- srec->sfile = curr_srec->sfile;
- curr_srec->next = srec;
- curr_srec = srec;
- cmd_length = 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_B: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_DEFLINES_W:
- /* Perform the association and set the next higher index
- to the limit. */
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- srec = (struct srecinfo *)
- bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = curr_srec->line + data;
- srec->srec = curr_srec->srec + data,
- srec->sfile = curr_srec->sfile;
- curr_srec->next = srec;
- curr_srec = srec;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_INCRLNUM_B:
- data = src_ptr[DST_S_B_SRC_UNSBYTE];
- curr_srec->line += data;
- cmd_length = 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_SETFILE:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->sfile = data;
- curr_srec->srec = module->file_table[data].srec;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_SETFILE: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_SETLNUM_L:
- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
- curr_srec->line = data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_SETLNUM_W:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->line = data;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_SETREC_L:
- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
- curr_srec->srec = data;
- module->file_table[curr_srec->sfile].srec = data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_SETREC_W:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->srec = data;
- module->file_table[curr_srec->sfile].srec = data;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SRC_FORMFEED:
- cmd_length = 1;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SRC_FORMFEED\n");
-#endif
- break;
-
- default:
- (*_bfd_error_handler) (_("unknown source command %d"),
- cmd);
- cmd_length = 2;
- break;
- }
-
- src_ptr += cmd_length;
- }
- break;
-
- case DST_S_C_LINE_NUM:
- pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "line info\n");
-#endif
-
- while (pcl_ptr < ptr + rec_length)
- {
- /* The command byte is signed so we must sign-extend it. */
- int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data;
-
- switch (cmd)
- {
- case DST_S_C_DELTA_PC_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_pc += data;
- curr_linenum += 1;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_DELTA_PC_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_DELTA_PC_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc += data;
- curr_linenum += 1;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_DELTA_PC_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_INCR_LINUM:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_linenum += data;
- cmd_length = 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_INCR_LINUM: %d\n", data);
-#endif
- break;
-
- case DST_S_C_INCR_LINUM_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_linenum += data;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_INCR_LINUM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_linenum += data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SET_LINUM_INCR:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_LINUM_INCR not implemented"));
- cmd_length = 2;
- break;
-
- case DST_S_C_SET_LINUM_INCR_W:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_LINUM_INCR_W not implemented"));
- cmd_length = 3;
- break;
-
- case DST_S_C_RESET_LINUM_INCR:
- (*_bfd_error_handler)
- (_("DST_S_C_RESET_LINUM_INCR not implemented"));
- cmd_length = 1;
- break;
-
- case DST_S_C_BEG_STMT_MODE:
- (*_bfd_error_handler)
- (_("DST_S_C_BEG_STMT_MODE not implemented"));
- cmd_length = 1;
- break;
-
- case DST_S_C_END_STMT_MODE:
- (*_bfd_error_handler)
- (_("DST_S_C_END_STMT_MODE not implemented"));
- cmd_length = 1;
- break;
-
- case DST_S_C_SET_LINUM_B:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_linenum = data;
- cmd_length = 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SET_LINUM_B: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SET_LINE_NUM:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_linenum = data;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SET_LINE_NUM: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SET_LINUM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_linenum = data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SET_LINUM_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SET_PC:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_PC not implemented"));
- cmd_length = 2;
- break;
-
- case DST_S_C_SET_PC_W:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_PC_W not implemented"));
- cmd_length = 3;
- break;
-
- case DST_S_C_SET_PC_L:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_PC_L not implemented"));
- cmd_length = 5;
- break;
-
- case DST_S_C_SET_STMTNUM:
- (*_bfd_error_handler)
- (_("DST_S_C_SET_STMTNUM not implemented"));
- cmd_length = 2;
- break;
-
- case DST_S_C_TERM:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_pc += data;
- cmd_length = 2;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_TERM: %d\n", data);
-#endif
- break;
-
- case DST_S_C_TERM_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_pc += data;
- cmd_length = 3;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_TERM_W: %d\n", data);
-#endif
- break;
-
- case DST_S_C_TERM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc += data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_TERM_L: %d\n", data);
-#endif
- break;
-
- case DST_S_C_SET_ABS_PC:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc = data;
- cmd_length = 5;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "DST_S_C_SET_ABS_PC: 0x%x\n", data);
-#endif
- break;
-
- default:
- if (cmd <= 0)
- {
- curr_pc -= cmd;
- curr_linenum += 1;
- cmd_length = 1;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "bump pc to 0x%llx and line to %d\n",
- curr_pc, curr_linenum);
-#endif
- }
- else
- {
- (*_bfd_error_handler) (_("unknown line command %d"),
- cmd);
- cmd_length = 2;
- }
- break;
- }
-
- if ((curr_linenum != prev_linum && curr_pc != prev_pc)
- || cmd <= 0
- || cmd == DST_S_C_DELTA_PC_L
- || cmd == DST_S_C_DELTA_PC_W)
- {
- line = (struct lineinfo *)
- bfd_zalloc (abfd, sizeof (struct lineinfo));
- line->address = curr_pc;
- line->line = curr_linenum;
-
- curr_line->next = line;
- curr_line = line;
-
- prev_linum = curr_linenum;
- prev_pc = curr_pc;
-#if VMS_DEBUG
- _bfd_vms_debug (4, "-> correlate pc 0x%llx with line %d\n",
- curr_pc, curr_linenum);
-#endif
- }
-
- pcl_ptr += cmd_length;
- }
- break;
-
- case 0x17: /* Undocumented type used by DEC C to declare equates. */
-#if VMS_DEBUG
- _bfd_vms_debug (3, "undocumented type 0x17\n");
-#endif
- break;
-
- default:
-#if VMS_DEBUG
- _bfd_vms_debug (3, "ignoring record\n");
-#endif
- break;
-
- }
-
- ptr += rec_length;
- }
-
- /* Finalize tables with EOL marker. */
- srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = (unsigned int) -1;
- srec->srec = (unsigned int) -1;
- curr_srec->next = srec;
-
- line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
- line->line = (unsigned int) -1;
- line->address = (bfd_vma) -1;
- curr_line->next = line;
-
- /* Advertise that this module has been parsed. This is needed
- because parsing can be either performed at module creation
- or deferred until debug info is consumed. */
- SET_MODULE_PARSED (module);
-}
-
-/* Build the list of modules for the specified BFD. */
-
-static struct module *
-build_module_list (bfd *abfd)
-{
- struct module *module, *list = NULL;
- asection *dmt;
-
- if ((dmt = bfd_get_section_by_name (abfd, "$DMT$")))
- {
- /* We have a DMT section so this must be an image. Parse the
- section and build the list of modules. This is sufficient
- since we can compute the start address and the end address
- of every module from the section contents. */
- bfd_size_type size = bfd_get_section_size (dmt);
- unsigned char *ptr, *end;
-
- ptr = (unsigned char *) bfd_alloc (abfd, size);
- if (! ptr)
- return NULL;
-
- if (! bfd_get_section_contents (abfd, dmt, ptr, 0, size))
- return NULL;
-
-#if VMS_DEBUG
- _bfd_vms_debug (2, "DMT\n");
-#endif
-
- end = ptr + size;
-
- while (ptr < end)
- {
- /* Each header declares a module with its start offset and size
- of debug info in the DST section, as well as the count of
- program sections (i.e. address spans) it contains. */
- int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG);
- int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE);
- int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT);
- ptr += DBG_S_C_DMT_HEADER_SIZE;
-
-#if VMS_DEBUG
- _bfd_vms_debug (3, "module: modbeg = %d, size = %d, count = %d\n",
- modbeg, msize, count);
-#endif
-
- /* We create a 'module' structure for each program section since
- we only support contiguous addresses in a 'module' structure.
- As a consequence, the actual debug info in the DST section is
- shared and can be parsed multiple times; that doesn't seem to
- cause problems in practice. */
- while (count-- > 0)
- {
- int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START);
- int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH);
- module = new_module (abfd);
- module->modbeg = modbeg;
- module->size = msize;
- module->low = start;
- module->high = start + length;
- module->next = list;
- list = module;
- ptr += DBG_S_C_DMT_PSECT_SIZE;
-
-#if VMS_DEBUG
- _bfd_vms_debug (4, "section: start = 0x%x, length = %d\n",
- start, length);
-#endif
- }
- }
- }
- else
- {
- /* We don't have a DMT section so this must be an object. Parse
- the module right now in order to compute its start address and
- end address. */
- module = new_module (abfd);
- parse_module (abfd, module, PRIV (dst_section)->contents,
- PRIV (dst_ptr_end) - PRIV (dst_section)->contents);
- list = module;
- }
-
- return list;
-}
-
-/* Calculate and return the name of the source file and the line nearest
- to the wanted location in the specified module. */
-
-static bfd_boolean
-module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr,
- const char **file, const char **func,
- unsigned int *line)
-{
- struct funcinfo *funcinfo;
- struct lineinfo *lineinfo;
- struct srecinfo *srecinfo;
- bfd_boolean ret = FALSE;
-
- /* Parse this module if that was not done at module creation. */
- if (! IS_MODULE_PARSED (module))
- {
- unsigned int size = module->size;
- unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg;
- unsigned char *buffer = (unsigned char *) bfd_malloc (module->size);
-
- if (bfd_seek (abfd, modbeg, SEEK_SET) != 0
- || bfd_bread (buffer, size, abfd) != size)
- {
- bfd_set_error (bfd_error_no_debug_section);
- return FALSE;
- }
-
- parse_module (abfd, module, buffer, size);
- free (buffer);
- }
-
- /* Find out the function (if any) that contains the address. */
- for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next)
- if (addr >= funcinfo->low && addr <= funcinfo->high)
- {
- *func = funcinfo->name;
- ret = TRUE;
- break;
- }
-
- /* Find out the source file and the line nearest to the address. */
- for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next)
- if (lineinfo->next && addr < lineinfo->next->address)
- {
- for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next)
- if (srecinfo->next && lineinfo->line < srecinfo->next->line)
- {
- if (srecinfo->sfile > 0)
- {
- *file = module->file_table[srecinfo->sfile].name;
- *line = srecinfo->srec + lineinfo->line - srecinfo->line;
- }
- else
- {
- *file = module->name;
- *line = lineinfo->line;
- }
- return TRUE;
- }
-
- break;
- }
-
- return ret;
-}
-
-/* Provided a BFD, a section and an offset into the section, calculate and
- return the name of the source file and the line nearest to the wanted
- location. */
-
-bfd_boolean
-_bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section,
- asymbol **symbols ATTRIBUTE_UNUSED,
- bfd_vma offset, const char **file,
- const char **func, unsigned int *line)
-{
- struct module *module;
-
- /* What address are we looking for? */
- bfd_vma addr = section->vma + offset;
-
- *file = NULL;
- *func = NULL;
- *line = 0;
-
- if (PRIV (dst_section) == NULL)
- return FALSE;
-
- if (PRIV (modules) == NULL)
- {
- PRIV (modules) = build_module_list (abfd);
- if (PRIV (modules) == NULL)
- return FALSE;
- }
-
- for (module = PRIV (modules); module; module = module->next)
- if (addr >= module->low && addr <= module->high)
- return module_find_nearest_line (abfd, module, addr, file, func, line);
-
- return FALSE;
-}
-
-/* Process EDBG/ETBT record.
- Return 0 on success, -1 on error */
-
-static int
-vms_slurp_debug (bfd *abfd)
-{
- if (PRIV (dst_section) == NULL)
- {
- /* We have no way to find out beforehand how much debug info there
- is in an object file, so pick an initial amount and grow it as
- needed later. */
- flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC;
- asection *section = bfd_make_section (abfd, "$DST$");
- if (!section)
- return -1;
- section->size = 1024;
- if (!bfd_set_section_flags (abfd, section, flags))
- return -1;
- section->contents = ((unsigned char *)
- bfd_zmalloc (section->size));
- if (section->contents == NULL)
- return -1;
- section->filepos = (unsigned int)-1;
- PRIV (dst_section) = section;
- }
-
- PRIV (image_section) = PRIV (dst_section);
- PRIV (image_ptr) = PRIV (dst_section)->contents;
-
- return _bfd_vms_slurp_tir (abfd, EOBJ_S_C_ETIR);
-}
-
-/* Process DBG/EDBG record.
- Return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_dbg (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "DBG/EDBG\n");
-#endif
-
- abfd->flags |= (HAS_DEBUG | HAS_LINENO);
-
- return vms_slurp_debug (abfd);
-}
-
-/* Process TBT/ETBT record.
- Return 0 on success, -1 on error. */
-
-int
-_bfd_vms_slurp_tbt (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "TBT/ETBT\n");
-#endif
-
- abfd->flags |= HAS_LINENO;
-
- return vms_slurp_debug (abfd);
-}
-
-/* Write DBG/EDBG record. */
-
-int
-_bfd_vms_write_dbg (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "vms_write_dbg (%p, %d)\n", abfd, objtype);
-#endif
-
- return 0;
-}
-
-/* Write TBT/ETBT record. */
-
-int
-_bfd_vms_write_tbt (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED)
-{
-#if VMS_DEBUG
- _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype);
-#endif
-
- return 0;
-}