diff options
author | Tristan Gingold <gingold@adacore.com> | 2009-02-23 09:28:43 +0000 |
---|---|---|
committer | Tristan Gingold <gingold@adacore.com> | 2009-02-23 09:28:43 +0000 |
commit | 0c37646508ccd3222db567f20d0ed44a9c3ba1d2 (patch) | |
tree | 494165a5852e9256b4ffc7b97d8a2ae557f26c59 /bfd/vms-hdr.c | |
parent | 6f43c46f4b7ae3ae4506773de7d41c61bd2be4fe (diff) | |
download | gdb-0c37646508ccd3222db567f20d0ed44a9c3ba1d2.zip gdb-0c37646508ccd3222db567f20d0ed44a9c3ba1d2.tar.gz gdb-0c37646508ccd3222db567f20d0ed44a9c3ba1d2.tar.bz2 |
2009-02-23 Tristan Gingold <gingold@adacore.com>
* vms.h: Update copyright year, fix comments, reorder declarations.
(_bfd_save_vms_section): Remove the prototype.
(EGPS_S_V_NO_SHIFT): New constant.
(bfd_vms_set_section_flags): New prototype.
(EGPS_S_B_ALIGN, EGPS_S_W_FLAGS, EGPS_S_L_ALLOC, EGPS_S_B_NAMLNG): New
constants.
(EGSY_S_W_FLAGS): Ditto.
(EGSY_S_V_QUAD_VAL): Ditto.
(ESDF_S_L_VALUE, ESDF_S_L_PSINDX, ESDF_S_B_NAMLNG): Ditto.
(EGST_S_W_FLAGS, EGST_S_Q_LP_1, EGST_S_Q_LP_2, EGST_S_L_PSINDX,
EGST_S_B_NAMLNG): Ditto.
(ESRF_S_B_NAMLNG): Ditto.
(ETIR_S_C_HEADER_SIZE): Ditto.
(EGPS_S_V_ALLOC_64BIT): Ditto.
(DST_S_C_EPILOG): Ditto.
(DST_S_C_SRC_SETLNUM_L, DST_S_C_SRC_SETLNUM_W) : Ditto.
(DST_S_C_SRC_INCRLNUM_B): Ditto.
(DST_S_B_PCLINE_UNSBYTE, DST_S_W_PCLINE_UNSWORD): Ditto.
(DST_S_L_PCLINE_UNSLONG): Ditto.
(DST_S_B_MODBEG_NAME, DST_S_L_RTNBEG_ADDRESS) : Ditto
(DST_S_B_RTNBEG_NAME, DST_S_L_RTNEND_SIZE): Ditto
(DST_S_C_SOURCE_HEADER_SIZE): Ditto.
(DST_S_B_SRC_DF_LENGTH, DST_S_W_SRC_DF_FILEID): Ditto.
(DST_S_B_SRC_DF_FILENAME, DST_S_B_SRC_UNSBYTE): Ditto.
(DST_S_B_SRC_UNSBYTE): Ditto.
(DST_S_W_SRC_UNSWORD, DST_S_L_SRC_UNSLONG): Ditto.
Add prototypes.
(vms_section, vms_reloc): Remove types.
(hdr_struc): Replaced by ...
(hdr_struct): ... new type.
(EMH_S_W_HDRTYP, EMH_S_B_STRLVL, EMH_S_L_ARCH1): New constants.
(EMH_S_L_ARCH2, EMH_S_L_RECSIZ, EMH_S_B_NAMLNG): Ditto.
(EMH_DATE_LENGTH): Ditto.
(eom_struc): Replaced by ...
(eom_struct): ... new type.
(EEOM_S_L_TOTAL_LPS, EEOM_S_W_COMCOD, EEOM_S_B_TFRFLG): New constants.
(EEOM_S_L_PSINDX, EEOM_S_L_TFRADR): Ditto.
(EIHD_S_K_MAJORID, EIHD_S_K_MINORID, EIHD_S_K_EXE): Ditto.
(EIHD_S_L_SIZE, EIHD_S_L_ISDOFF, EIHD_S_L_SYMDBGOFF): Ditto.
(EIHD_S_Q_SYMVVA, EIHD_S_L_IMGTYPE): Ditto.
(EISD_S_L_EISDSIZE, EISD_S_L_SECSIZE, EISD_S_Q_VIR_ADDR): Ditto.
(EISD_S_L_FLAGS, EISD_S_L_VBN, EISD_S_R_CONTROL): Ditto.
(EISD_S_L_IDENT, EISD_S_T_GBLNAM): Ditto.
(EISD_S_M_GBL, EISD_S_M_CRF, EISD_S_M_DZRO, EISD_S_M_WRT): Ditto.
(EISD_S_M_INITALCODE, EISD_S_M_BASED, EISD_S_M_FIXUPVEC): Ditto.
(EISD_S_M_RESIDENT, EISD_S_M_VECTOR, EISD_S_M_PROTECT): Ditto.
(EISD_S_M_LASTCLU, EISD_S_M_EXE, EISD_S_M_NONSHRADR): Ditto.
(EISD_S_M_QUAD_LENGTH, EISD_S_M_ALLOC_64BIT): Ditto.
(EIHS_S_L_DSTVBN, EIHS_S_L_DSTSIZE, EIHS_S_L_GSTVBN): Ditto.
(EIHS_S_L_GSTSIZE, EIHS_S_L_DMTVBN, EIHS_S_L_DMTBYTES): Ditto.
(DBG_S_L_DMT_MODBEG, DBG_S_L_DST_SIZE): Ditto.
(DBG_S_W_DMT_PSECT_COUNT, DBG_S_C_DMT_HEADER_SIZE): Ditto.
(DBG_S_L_DMT_PSECT_START, DBG_S_L_DMT_PSECT_LENGTH)
(DBG_S_C_DMT_PSECT_SIZE): Ditto.
(enum file_type_enum): New type.
(struct location_struct): Removed.
(struct fileinfo, struct srecinfo, struct lineinfo): New types.
(struct funcinfo, struct module): Ditto.
(struct vms_private_data_struct): Update fields.
(struct vms_section_data_struct): New type.
* vms.c: Update copyright year, fix comments,
Fix includes for DECC, add prototypes.
(vms_initialize): Use bfd_alloc instead of bfd_zalloc and remove
some initializers.
Use flavour to set is_vax, location_stack is removed.
(struct pair): Declare.
(fill_section_ptr): Initialize variables at declaration.
Add guard to set SECTION_SYM flag, handlde und section.
(vms_fixup_sections): Use struct pair for fill_section_ptr argument.
(_bfd_vms_slurp_object_records): New function, replaces previous
vms_object_p.
(vms_slurp_module): New function.
(vms_slurp_image): Ditto.
(vms_object_p): Complete rewrite.
(vms_mkobject): Use is_vax field to slect architecture.
(free_reloc_stream): New function.
(vms_convert_to_var): Ditto.
(vms_convert_to_var_1): Ditto.
(vms_convert_to_var_unix_filename): Ditto.
(vms_close_and_cleanup): Call free_reloc_stream, convert file to
VAR format on VMS.
(vms_new_section_hook): Set alignment to 0, allocate private data.
(vms_get_section_contents): Load content.
(vms_get_symbol_info): Handle undefined section.
(vms_find_nearest_line): Handle.
(alloc_reloc_stream): New function.
(vms_slurp_reloc_table): Ditto.
(vms_get_reloc_upper_bound): Make it real.
(vms_canonicalize_reloc): Do the real work.
(alpha_howto_table): Add ALPHA_R_NOP, ALPHA_R_BSR, ALPHA_R_LDA,
ALPHA_R_BOH.
(vms_bfd_reloc_type_lookup): Handle NOP, BSR, LDA and BOH.
(vms_set_arch_mach): Check arch.
(vms_set_section_contents): Copy the content after allocation.
(vms_alpha_vec): Update object flags.
* vms-tir.c: Update copyright year, fix comments,
add prototypes for new functions.
(dst_define_location): New function.
(dst_restore_location): New function.
(dst_retrieve_location): New function.
(dst_check_allocation): New function.
(image_dump): Call dst_check_allocation.
(image_write_b): Ditto.
(image_write_w): Ditto.
(image_write_l): Ditto.
(image_write_q): Ditto.
(cmd_name): Handle STA_LW, STA_QW, STO_OFF, STO_IMM, STO_IMMR, STO_LW,
STO_QW, OPR_ADD, CTL_SETRB, STC_LP_PSB, CTL_DFLOC, CTL_STLOC,
CTL_STKDL.
Call error handler instead of abort if name is not known.
(etir_sta): Add quarter_relocs argument and set it.
Fix cast.
(etir_sto): Ditto.
(etir_opr): Ditto, return FALSE in case of error.
(etir_ctl): Add quarter_relocs argument and set it, fix cast.
Fix CTL_DFLOC, CTL_STLOC, CTL_STKDL.
(etir_stc): Add quarter_relocs argument and set it, fix cast.
Fix STC_LP, STC_LP_PSB, STC_GBL and STC_CGA.
Handle STC_LP_PSB, STC_BSR_GBL, STC_LDA_GBL, STC_BOH_GBL.
Move STC_NOP_PS, STC_BSR_PS, STC_LDA_PS, STC_BOH_PS, STC_NBH_PS.
Return FALSE in case of error.
(tir_sta): Change sign of psect.
(tir_ctl): Ditto.
(tir_cmd): Fix cast. Makes tir_table static const.
(etir_cmd): Add quarter_relocs argument, makes etir_table const,
add argument to explain.
(analyze_etir): Initialize maxptr, add quarter_relocs
declaration, move some declarations into inner scopes.
Handle quarter_relocs and STO_IMM.
(_bfd_vms_slurp_tir): Use constant instead of hard-coded values.
(_bfd_vms_slurp_relocs): New function.
(_bfd_vms_decode_relocs): New function.
(sto_imm): Rewritten.
(start_first_etbt_record): New function.
(start_another_etbt_record): Ditto.
(etir_output_check): Ditto.
(defer_reloc_p): Ditto.
(_bfd_vms_write_tir): Remove nextoffset, convert a while-loop to
a for-loop. Correctly deals with contents, deals with .vmsdebug,
rewritte relocations handling.
(_bfd_vms_write_tbt): Removed.
(_bfd_vms_write_dbg): Ditto.
* vms-misc.c: Update copyright year, Fix comments.
(_bfd_vms_get_header_values): Use 'size' instead of 'length'.
(maybe_adjust_record_pointer_for_object): New function.
(_bfd_vms_get_first_record): New function, replaces ...
(_bfd_vms_get_record): .. removed.
(_bfd_vms_get_object_record): New function.
(_bfd_vms_get_object_record): New function.
(vms_get_remaining_object_record): New function, replaces ...
(_bfd_vms_get_next_record): ... removed.
(add_new_contents): Removed.
(_bfd_save_vms_section): Removed.
(_bfd_get_vms_section): Removed.
(_bfd_vms_output_flush): Write in VAR format.
(new_symbol): Don't make UND section.
* vms-hdr.c: Update copyright year, update list of record handled.
(_bfd_vms_slurp_hdr): rec_length renamed to rec_size.
(_bfd_vms_write_hdr): Strip vms and unix patches,
add comments, truncate module name at 31 characters,
use constants instead of hard-coded value,
write BFD version instead of a fixed string.
(_bfd_vms_slurp_ihd): New function.
(_bfd_vms_slurp_isd): Ditto.
(_bfd_vms_slurp_ihs): Ditto.
(new_module): Ditto.
(parse_module): Ditto
(build_module_list): Ditto.
(module_find_nearest_line): Ditto.
(_bfd_vms_find_nearest_dst_line): Ditto.
(vms_slurp_debug): Ditto.
(_bfd_vms_slurp_dbg): Ditto.
(_bfd_vms_slurp_tbt): Ditto.
(_bfd_vms_write_dbg): Ditto.
(_bfd_vms_write_tbt): Ditto.
* vms-gsd.c: Update copyright year, update list of records handled.
(EVAX_LITERALS_NAME): New macro.
(evax_section_flags): Add an entry for EVAX_LITERALS_NAME.
(gpsflagdesc, gsyflagdesc): Moved out of _bfd_vms_slurp_gsd.
(register_universal_symbol): New function and prototype.
(_bfd_vms_slurp_gsd): Fix indentations and casts,
improve debug messages,
use constants instead of hard-coded value,
fix missing endianness conversion,
handle global symbol (SYMG).
(bfd_vms_set_section_flags): New function.
(_bfd_vms_write_gsd): Don't write .vmsdebug section,
handle section literals,
fix indentation,
handle section bfd and vms flags,
don't output LIB$INITIALIZE symbol,
fix handling of weak symbols,
fix evax vs vax procedure descriptor,
handle absolute symbols.
* reloc.c (BFD_RELOC_ALPHA_NOP, BFD_RELOC_ALPHA_BSR,
BFD_RELOC_ALPHA_LDA, BFD_RELOC_ALPHA_BOH): New relocations.
* makefile.vms (DEFS): Fix flags for VMS.
* bfdio.c (real_fopen): Handle multiple VMS fopen attributes.
* bfd-in2.h: Regenerated.
* libbfd.h: Regenerated.
Diffstat (limited to 'bfd/vms-hdr.c')
-rw-r--r-- | bfd/vms-hdr.c | 1090 |
1 files changed, 1065 insertions, 25 deletions
diff --git a/bfd/vms-hdr.c b/bfd/vms-hdr.c index 11e1af6..6ad84dd 100644 --- a/bfd/vms-hdr.c +++ b/bfd/vms-hdr.c @@ -1,14 +1,31 @@ /* 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 Free Software Foundation, Inc. + 2007, 2008, 2009 Free Software Foundation, Inc. HDR record handling functions EMH record handling functions - and + 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 @@ -39,6 +56,20 @@ #include <alloca.h> #endif +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. */ @@ -85,15 +116,15 @@ _bfd_vms_slurp_hdr (bfd *abfd, int objtype) break; case MHD_S_C_LNM: - PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); + 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_length - 2)); + 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_length - 2)); + 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: @@ -110,15 +141,15 @@ _bfd_vms_slurp_hdr (bfd *abfd, int objtype) break; case EMH_S_C_LNM + EVAX_OFFSET: - PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); + 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_length - 6)); + 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_length - 6)); + PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6)); break; case MHD_S_C_CPR: @@ -189,6 +220,7 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) 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); @@ -213,27 +245,34 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) fptr = bfd_get_filename (abfd); fname = strdup (fptr); + + /* Strip VMS path. */ fout = strrchr (fname, ']'); - if (fout == 0) + if (fout == NULL) fout = strchr (fname, ':'); - if (fout != 0) + if (fout != NULL) fout++; else fout = fname; + /* Strip UNIX path. */ + fptr = strrchr (fout, '/'); + if (fptr != NULL) + fout = fptr + 1; + /* Strip .obj suffix. */ - fptr = strrchr (fname, '.'); - if ((fptr != 0) - && (strcasecmp (fptr, ".OBJ") == 0)) + fptr = strrchr (fout, '.'); + if (fptr != 0 && strcasecmp (fptr, ".OBJ") == 0) *fptr = 0; + /* Convert to upper case and truncate at 31 characters. + (VMS object file format restricts module name length to 31). */ fptr = fout; while (*fptr != 0) { *fptr = TOUPPER (*fptr); fptr++; - if ((*fptr == ';') - || ((fptr - fout) > 31)) + if (*fptr == ';' || (fptr - fout) >= 31) *fptr = 0; } _bfd_vms_output_counted (abfd, fout); @@ -243,13 +282,14 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) _bfd_vms_output_counted (abfd, "NONAME"); _bfd_vms_output_counted (abfd, BFD_VERSION_STRING); - _bfd_vms_output_dump (abfd, get_vms_time_string (), 17); - _bfd_vms_output_fill (abfd, 0, 17); + _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); - _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("GAS proGIS")); + 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. */ @@ -320,10 +360,10 @@ _bfd_vms_slurp_eom (bfd *abfd, int objtype) } else { - PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4); - PRIV (eom_data).eom_b_comcod = *(vms_rec + 8); - - if (PRIV (eom_data).eom_b_comcod > 1) + 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); @@ -333,9 +373,11 @@ _bfd_vms_slurp_eom (bfd *abfd, int objtype) if (PRIV (rec_size) > 10) { PRIV (eom_data).eom_has_transfer = TRUE; - PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9); - PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12); - PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16); + 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; } @@ -377,3 +419,1001 @@ _bfd_vms_write_eom (bfd *abfd, int objtype) _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 size = 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, size, 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 = size; + 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, objtype)\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; +} |