diff options
Diffstat (limited to 'bfd/vms-hdr.c')
-rw-r--r-- | bfd/vms-hdr.c | 1382 |
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; -} |