From: Ian Lance Taylor Date: Thu, 2 Jul 1998 18:41:08 +0000 (+0000) Subject: Thu Jul 2 14:59:42 1998 Klaus Kaempf X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0dc4c667aceab372c5500045bd76a4c93af315ca;p=binutils-gdb.git Thu Jul 2 14:59:42 1998 Klaus Kaempf Merge of vax/vms (read-only) support * configure.com: Support Vax target. * makefile.vms: Support Vax target. * vms.h: Renamed from evax.h, merged vax/vms (read-only) support. * vms.c: Renamed from evax-alpha.c, merged vax/vms (read-only) support. * vms-hdr.c: Renamed from evax-emh.c, merged vax/vms (read-only) support. * vms-gsd.c: Renamed from evax-egsd.c, merged vax/vms (read-only) support. * vms-tir.c: Renamed from evax-etir.c, merged vax/vms (read-only) support. * vms-misc.c: Renamed from evax-misc.c, merged vax/vms (read-only) support. * libbfd.c (real_read): Use unbuffered read on VMS/Vax. * targets.c (bfd_target_ovax_flavour): New flavour. (vms_alpha_vec): Renamed from evax_alpha_vec. (vms_vax_vec): New. (target_vector): Update accordingly. * config.bfd (alpha*-*-*vms*): Use vms_alpha_vec, not evax_alpha_vec. (vax*-*-*vms*): New target. * Makefile.am: Update for renamed files. Rebuild dependencies. * bfd-in2.h: Rebuild. * configure.in, Makefile.in, aclocal.m4: Rebuild. --- diff --git a/bfd/.Sanitize b/bfd/.Sanitize index 4abfe9de760..d8c7c33b48d 100644 --- a/bfd/.Sanitize +++ b/bfd/.Sanitize @@ -179,12 +179,6 @@ elfcore.h elflink.c elflink.h elfxx-target.h -evax-alpha.c -evax-egsd.c -evax-emh.c -evax-etir.c -evax-misc.c -evax.h format.c freebsd.h gen-aout.c @@ -287,6 +281,12 @@ tekhex.c trad-core.c vaxnetbsd.c versados.c +vms.c +vms.h +vms-gsd.c +vms-hdr.c +vms-misc.c +vms-tir.c xcofflink.c Things-to-lose: diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2287a35db41..7d180e6b77e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,38 @@ +Thu Jul 2 14:59:42 1998 Klaus Kaempf + + Merge of vax/vms (read-only) support + * configure.com: Support Vax target. + * makefile.vms: Support Vax target. + * vms.h: Renamed from evax.h, merged vax/vms (read-only) support. + * vms.c: Renamed from evax-alpha.c, merged vax/vms (read-only) + support. + * vms-hdr.c: Renamed from evax-emh.c, merged vax/vms (read-only) + support. + * vms-gsd.c: Renamed from evax-egsd.c, merged vax/vms (read-only) + support. + * vms-tir.c: Renamed from evax-etir.c, merged vax/vms (read-only) + support. + * vms-misc.c: Renamed from evax-misc.c, merged vax/vms (read-only) + support. + * libbfd.c (real_read): Use unbuffered read on VMS/Vax. + * targets.c (bfd_target_ovax_flavour): New flavour. + (vms_alpha_vec): Renamed from evax_alpha_vec. + (vms_vax_vec): New. + (target_vector): Update accordingly. + * config.bfd (alpha*-*-*vms*): Use vms_alpha_vec, not + evax_alpha_vec. + (vax*-*-*vms*): New target. + * Makefile.am: Update for renamed files. Rebuild dependencies. + * bfd-in2.h: Rebuild. + * configure.in, Makefile.in, aclocal.m4: Rebuild. + +Thu Jul 2 13:31:55 1998 Ian Lance Taylor + + Based on patch from Matt Semersky : + * linker.c (_bfd_generic_final_link): Force a trailing NULL + pointer on abfd->outsymbols. + (generic_add_output_symbol): Handle NULL sym parameter. + Wed Jul 1 17:05:53 1998 Nick Clifton * elf.c (copy_private_bfd_data): Add support for changing VMA or diff --git a/bfd/config.bfd b/bfd/config.bfd index 05ef334902e..3155cdf8b47 100755 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -76,7 +76,7 @@ case "${targ}" in targ_selvecs=ecoffalpha_little_vec ;; alpha*-*-*vms*) - targ_defvec=evax_alpha_vec + targ_defvec=vms_alpha_vec ;; alpha*-*-*) targ_defvec=ecoffalpha_little_vec @@ -610,6 +610,10 @@ case "${targ}" in ;; #endif + vax*-*-*vms*) + targ_defvec=vms_vax_vec + ;; + we32k-*-*) targ_defvec=we32kcoff_vec ;; @@ -648,3 +652,16 @@ case "${targ}" in exit 1 ;; esac + +# If we support any ELF target, then automatically add support for the +# generic ELF targets. This permits an objdump with some ELF support +# to be used on an arbitrary ELF file for anything other than +# relocation information. +case "${targ_defvec} ${targ_selvecs}" in + *bfd_elf64*) + targ_selvecs="${targ_selvecs} bfd_elf64_little_generic_vec bfd_elf64_big_generic_vec bfd_elf32_little_generic_vec bfd_elf32_big_generic_vec" + ;; + *bfd_elf32*) + targ_selvecs="${targ_selvecs} bfd_elf32_little_generic_vec bfd_elf32_big_generic_vec" + ;; +esac diff --git a/bfd/evax-alpha.c b/bfd/evax-alpha.c deleted file mode 100644 index 48bde0c19f6..00000000000 --- a/bfd/evax-alpha.c +++ /dev/null @@ -1,1795 +0,0 @@ -/* evax-alpha.c -- BFD back-end for ALPHA EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998 Free Software Foundation, Inc. - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" -#include "libbfd.h" - -#include "evax.h" - -static boolean evax_initialize PARAMS ((bfd *)); -static boolean fill_section_ptr PARAMS ((struct bfd_hash_entry *, PTR)); -static boolean evax_fixup_sections PARAMS ((bfd *)); -static boolean copy_symbols PARAMS ((struct bfd_hash_entry *, PTR)); -static bfd_reloc_status_type reloc_nil - PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static const struct bfd_target *evax_object_p PARAMS ((bfd *abfd)); -static const struct bfd_target *evax_archive_p PARAMS ((bfd *abfd)); -static boolean evax_mkobject PARAMS ((bfd *abfd)); -static boolean evax_write_object_contents PARAMS ((bfd *abfd)); -static boolean evax_close_and_cleanup PARAMS ((bfd *abfd)); -static boolean evax_bfd_free_cached_info PARAMS ((bfd *abfd)); -static boolean evax_new_section_hook PARAMS ((bfd *abfd, asection *section)); -static boolean evax_get_section_contents - PARAMS ((bfd *abfd, asection *section, PTR x1, file_ptr x2, - bfd_size_type x3)); -static boolean evax_get_section_contents_in_window - PARAMS ((bfd *abfd, asection *section, bfd_window *w, file_ptr offset, - bfd_size_type count)); -static boolean evax_bfd_copy_private_bfd_data PARAMS ((bfd *src, bfd *dest)); -static boolean evax_bfd_copy_private_section_data - PARAMS ((bfd *srcbfd, asection *srcsec, bfd *dstbfd, asection *dstsec)); -static boolean evax_bfd_copy_private_symbol_data - PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym)); -static boolean evax_bfd_print_private_bfd_data - PARAMS ((bfd *abfd, void *file)); -static char *evax_core_file_failing_command PARAMS ((bfd *abfd)); -static int evax_core_file_failing_signal PARAMS ((bfd *abfd)); -static boolean evax_core_file_matches_executable_p - PARAMS ((bfd *abfd, bfd *bbfd)); -static boolean evax_slurp_armap PARAMS ((bfd *abfd)); -static boolean evax_slurp_extended_name_table PARAMS ((bfd *abfd)); -static boolean evax_construct_extended_name_table - PARAMS ((bfd *abfd, char **tabloc, bfd_size_type *tablen, - const char **name)); -static void evax_truncate_arname - PARAMS ((bfd *abfd, CONST char *pathname, char *arhdr)); -static boolean evax_write_armap - PARAMS ((bfd *arch, unsigned int elength, struct orl *map, - unsigned int orl_count, int stridx)); -static PTR evax_read_ar_hdr PARAMS ((bfd *abfd)); -static bfd *evax_get_elt_at_index PARAMS ((bfd *abfd, symindex index)); -static bfd *evax_openr_next_archived_file PARAMS ((bfd *arch, bfd *prev)); -static boolean evax_update_armap_timestamp PARAMS ((bfd *abfd)); -static int evax_generic_stat_arch_elt PARAMS ((bfd *abfd, struct stat *stat)); -static long evax_get_symtab_upper_bound PARAMS ((bfd *abfd)); -static long evax_get_symtab PARAMS ((bfd *abfd, asymbol **symbols)); -static void evax_print_symbol - PARAMS ((bfd *abfd, PTR file, asymbol *symbol, bfd_print_symbol_type how)); -static void evax_get_symbol_info - PARAMS ((bfd *abfd, asymbol *symbol, symbol_info *ret)); -static boolean evax_bfd_is_local_label_name PARAMS ((bfd *abfd, const char *)); -static alent *evax_get_lineno PARAMS ((bfd *abfd, asymbol *symbol)); -static boolean evax_find_nearest_line - PARAMS ((bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, - const char **file, const char **func, unsigned int *line)); -static asymbol *evax_bfd_make_debug_symbol - PARAMS ((bfd *abfd, void *ptr, unsigned long size)); -static long evax_read_minisymbols - PARAMS ((bfd *abfd, boolean dynamic, PTR *minisymsp, unsigned int *sizep)); -static asymbol *evax_minisymbol_to_symbol - PARAMS ((bfd *abfd, boolean dynamic, const PTR minisym, asymbol *sym)); -static long evax_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect)); -static long evax_canonicalize_reloc - PARAMS ((bfd *abfd, asection *srcsec, arelent **location, - asymbol **symbols)); -static const struct reloc_howto_struct *evax_bfd_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -static boolean evax_set_arch_mach - PARAMS ((bfd *abfd, enum bfd_architecture arch, unsigned long mach)); -static boolean evax_set_section_contents - PARAMS ((bfd *abfd, asection *section, PTR location, file_ptr offset, - bfd_size_type count)); -static int evax_sizeof_headers PARAMS ((bfd *abfd, boolean reloc)); -static bfd_byte *evax_bfd_get_relocated_section_contents - PARAMS ((bfd *abfd, struct bfd_link_info *link_info, - struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable, asymbol **symbols)); -static boolean evax_bfd_relax_section - PARAMS ((bfd *abfd, asection *section, struct bfd_link_info *link_info, - boolean *again)); -static boolean evax_bfd_gc_sections - PARAMS ((bfd *abfd, struct bfd_link_info *link_info)); -static struct bfd_link_hash_table *evax_bfd_link_hash_table_create - PARAMS ((bfd *abfd)); -static boolean evax_bfd_link_add_symbols - PARAMS ((bfd *abfd, struct bfd_link_info *link_info)); -static boolean evax_bfd_final_link - PARAMS ((bfd *abfd, struct bfd_link_info *link_info)); -static boolean evax_bfd_link_split_section - PARAMS ((bfd *abfd, asection *section)); -static long evax_get_dynamic_symtab_upper_bound PARAMS ((bfd *abfd)); -static long evax_canonicalize_dynamic_symtab - PARAMS ((bfd *abfd, asymbol **symbols)); -static long evax_get_dynamic_reloc_upper_bound PARAMS ((bfd *abfd)); -static long evax_canonicalize_dynamic_reloc - PARAMS ((bfd *abfd, arelent **arel, asymbol **symbols)); -static boolean evax_bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)); -static boolean evax_bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags)); - -#define evax_make_empty_symbol _bfd_evax_make_empty_symbol - -/*===========================================================================*/ - -const bfd_target evax_alpha_vec = -{ - - "evax-alpha", /* name */ - bfd_target_evax_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ - - (HAS_RELOC | HAS_SYMS - | WP_TEXT | D_PAGED), /* object flags */ - (SEC_ALLOC | SEC_LOAD | SEC_RELOC - | SEC_READONLY | SEC_CODE | SEC_DATA - | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* sect flags */ - 0, /* symbol_leading_char */ - ' ', /* ar_pad_char */ - 15, /* ar_max_namelen */ - bfd_getl64, bfd_getl_signed_64, bfd_putl64, - bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, - bfd_getl64, bfd_getl_signed_64, bfd_putl64, - bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, - - {_bfd_dummy_target, evax_object_p, /* bfd_check_format */ - evax_archive_p, _bfd_dummy_target}, - {bfd_false, evax_mkobject, /* bfd_set_format */ - _bfd_generic_mkarchive, bfd_false}, - {bfd_false, evax_write_object_contents, /* bfd_write_contents */ - _bfd_write_archive_contents, bfd_false}, - - BFD_JUMP_TABLE_GENERIC (evax), - BFD_JUMP_TABLE_COPY (evax), - BFD_JUMP_TABLE_CORE (evax), - BFD_JUMP_TABLE_ARCHIVE (evax), - BFD_JUMP_TABLE_SYMBOLS (evax), - BFD_JUMP_TABLE_RELOCS (evax), - BFD_JUMP_TABLE_WRITE (evax), - BFD_JUMP_TABLE_LINK (evax), - BFD_JUMP_TABLE_DYNAMIC (evax), - - (PTR) 0 -}; - - -/*===========================================================================*/ - -/* Initialize private data */ - -static boolean -evax_initialize (abfd) - bfd *abfd; -{ - int i; - - if (abfd->tdata.any != 0) - return true; - - bfd_set_start_address (abfd, (bfd_vma)-1); - - abfd->tdata.any = ((struct evax_private_data_struct*) - bfd_malloc (sizeof (struct evax_private_data_struct))); - if (abfd->tdata.any == 0) - return false; - PRIV(evax_buf) = 0; - PRIV(buf_size) = 0; - PRIV(rec_length) = 0; - PRIV(file_format) = FF_UNKNOWN; - PRIV(fixup_done) = false; - PRIV(sections) = NULL; - - PRIV(stack) = ((struct stack_struct *) - bfd_malloc (sizeof (struct stack_struct) * STACKSIZE)); - if (PRIV(stack) == 0) - { - evax_init_no_mem1: - free (abfd->tdata.any); - abfd->tdata.any = 0; - return false; - } - PRIV(stackptr) = 0; - - PRIV(evax_symbol_table) = ((struct bfd_hash_table *) - bfd_malloc (sizeof (struct bfd_hash_table))); - if (PRIV(evax_symbol_table) == 0) - { - evax_init_no_mem2: - free (PRIV(stack)); - PRIV(stack) = 0; - goto evax_init_no_mem1; - } - - if (!bfd_hash_table_init (PRIV(evax_symbol_table), _bfd_evax_hash_newfunc)) - return false; - - PRIV(location_stack) = ((struct location_struct *) - bfd_malloc (sizeof (struct location_struct) - * LOCATION_SAVE_SIZE)); - if (PRIV(location_stack) == 0) - { - evax_init_no_mem3: - free (PRIV(evax_symbol_table)); - PRIV(evax_symbol_table) = 0; - goto evax_init_no_mem2; - } - - for (i = 0; i < EVAX_SECTION_COUNT; i++) - PRIV(evax_section_table)[i] = NULL; - - PRIV(output_buf) = (unsigned char *) malloc (MAX_OUTREC_SIZE); - if (PRIV(output_buf) == 0) - { - free (PRIV(location_stack)); - PRIV(location_stack) = 0; - goto evax_init_no_mem3; - } - PRIV(push_level) = 0; - PRIV(pushed_size) = 0; - PRIV(length_pos) = 2; - PRIV(output_size) = 0; - PRIV(output_alignment) = 1; - - return true; -} - - -/* Fill symbol->section with section ptr - symbol->section is filled with the section index for defined symbols - during reading the EGSD section. But we need the pointer to the - bfd section later. - - It has the correct value for referenced (undefined section) symbols - - called from bfd_hash_traverse in evax_fixup_sections */ - -static boolean -fill_section_ptr (entry, sections) - struct bfd_hash_entry *entry; - PTR sections; -{ - asection *sec; - asymbol *sym; - - sym = ((evax_symbol_entry *)entry)->symbol; - sec = sym->section; - - if (!bfd_is_und_section (sec)) - { - sec = ((evax_symbol_entry *)entry)->symbol->section = - ((asection **)sections)[(int)sec]; - } - - if (strcmp (sym->name, sec->name) == 0) - sym->flags |= BSF_SECTION_SYM; - - return true; -} - - -/* Fixup sections - set up all pointers and arrays, counters and sizes are fixed now - - we build a private sections vector for easy access since sections - are always referenced by an index number. - - alloc PRIV(sections) according to abfd->section_count - copy abfd->sections to PRIV(sections) */ - -static boolean -evax_fixup_sections (abfd) - bfd *abfd; -{ - asection *s; - - if (PRIV(fixup_done)) - return true; - - PRIV(sections) = ((asection **) - bfd_malloc (abfd->section_count * sizeof (asection *))); - if (PRIV(sections) == 0) - return false; - PRIV(egsd_sec_count) = abfd->section_count; - s = abfd->sections; - while (s) - { - PRIV(sections)[s->index] = s; - s = s->next; - } - - /* - * traverse symbol table and fill in all section pointers - */ - - bfd_hash_traverse (PRIV(evax_symbol_table), fill_section_ptr, - (PTR)(PRIV(sections))); - - PRIV(fixup_done) = true; - - return true; -} - -/*===========================================================================*/ - -/* Check the format for a file being read. - Return a (bfd_target *) if it's an object file or zero if not. */ - -static const struct bfd_target * -evax_object_p (abfd) - bfd *abfd; -{ - int err = 0; - int prev_type; -#if EVAX_DEBUG - evax_debug (1, "evax_object_p(%p)\n", abfd); -#endif - if (bfd_seek (abfd, 0L, SEEK_SET)) - { - bfd_set_error (bfd_error_file_truncated); - return 0; - } - - prev_type = -1; - - do - { -#if EVAX_DEBUG - evax_debug (3, "reading at %08lx\n", bfd_tell(abfd)); -#endif - if (_bfd_evax_next_record (abfd) < 0) - { -#if EVAX_DEBUG - evax_debug (2, "next_record failed\n"); -#endif - bfd_set_error (bfd_error_wrong_format); - return 0; - } - - if ((prev_type == EOBJ_S_C_EGSD) && (PRIV(rec_type) != EOBJ_S_C_EGSD)) - { - if (evax_fixup_sections (abfd) == false) - { -#if EVAX_DEBUG - evax_debug (2, "evax_fixup_sections failed\n"); -#endif - bfd_set_error (bfd_error_wrong_format); - return 0; - } - } - - prev_type = PRIV(rec_type); - - switch (PRIV(rec_type)) - { - case EOBJ_S_C_EMH: - err = _bfd_evax_slurp_emh (abfd); - break; - case EOBJ_S_C_EEOM: - err = _bfd_evax_slurp_eeom (abfd); - break; - case EOBJ_S_C_EGSD: - err = _bfd_evax_slurp_egsd (abfd); - break; - case EOBJ_S_C_ETIR: - err = _bfd_evax_slurp_etir (abfd); - break; - case EOBJ_S_C_EDBG: - err = _bfd_evax_slurp_edbg (abfd); - break; - case EOBJ_S_C_ETBT: - err = _bfd_evax_slurp_etbt (abfd); - break; - default: - err = -1; - } - if (err != 0) - { -#if EVAX_DEBUG - evax_debug (2, "slurp type %d failed with %d\n", PRIV(rec_type), err); -#endif - bfd_set_error (bfd_error_wrong_format); - return 0; - } - } - while (prev_type != EOBJ_S_C_EEOM); - - /* set arch_info to alpha */ - - { - const bfd_arch_info_type *arch = bfd_scan_arch ("alpha"); - if (arch == 0) - { -#if EVAX_DEBUG - evax_debug (2, "arch not found\n"); -#endif - bfd_set_error (bfd_error_wrong_format); - return 0; - } - abfd->arch_info = arch; - } - - return &evax_alpha_vec; -} - - -/* Check the format for a file being read. - Return a (bfd_target *) if it's an archive file or zero. */ - -static const struct bfd_target * -evax_archive_p (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_archive_p(%p)\n", abfd); -#endif - - if (!evax_initialize (abfd)) - return 0; - - return 0; -} - - -/* Set the format of a file being written. */ - -static boolean -evax_mkobject (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_mkobject(%p)\n", abfd); -#endif - - if (!evax_initialize (abfd)) - return 0; - - { - const bfd_arch_info_type *arch = bfd_scan_arch ("alpha"); - if (arch == 0) - { - bfd_set_error(bfd_error_wrong_format); - return 0; - } - abfd->arch_info = arch; - } - - return true; -} - - -/* Write cached information into a file being written, at bfd_close. */ - -static boolean -evax_write_object_contents (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_write_object_contents(%p)\n", abfd); -#endif - - if (abfd->section_count > 0) /* we have sections */ - { - if (_bfd_evax_write_emh (abfd) != 0) - return false; - if (_bfd_evax_write_egsd (abfd) != 0) - return false; - if (_bfd_evax_write_etir (abfd) != 0) - return false; - if (_bfd_evax_write_etbt (abfd) != 0) - return false; - if (_bfd_evax_write_eeom (abfd) != 0) - return false; - } - return true; -} - -/*-- 4.1, generic -----------------------------------------------------------*/ - -/* Called when the BFD is being closed to do any necessary cleanup. */ - -static boolean -evax_close_and_cleanup (abfd) - bfd *abfd; -{ - asection *sec; - evax_section *es, *es1; - int i; - -#if EVAX_DEBUG - evax_debug (1, "evax_close_and_cleanup(%p)\n", abfd); -#endif - if (abfd == 0) - return true; - - if (PRIV(evax_buf) != NULL) - { - free (PRIV(evax_buf)); - PRIV(evax_buf) = NULL; - } - PRIV(buf_size) = 0; - - if (PRIV(output_buf) != 0) - { - free (PRIV(output_buf)); - PRIV(output_buf) = 0; - } - - sec = abfd->sections; - while (sec != NULL) - { - if (sec->contents) - free (sec->contents); - sec = sec->next; - } - - if (PRIV(sections) != NULL) - { - free (PRIV(sections)); - PRIV(sections) = NULL; - } - - if (PRIV(evax_symbol_table)) - { - bfd_hash_table_free (PRIV(evax_symbol_table)); - PRIV(evax_symbol_table) = 0; - } - - if (PRIV(stack)) - { - free (PRIV(stack)); - PRIV(stack) = 0; - } - - if (PRIV(location_stack)) - { - free (PRIV(location_stack)); - PRIV(location_stack) = 0; - } - - for (i = 0; i < EVAX_SECTION_COUNT; i++) - { - es = PRIV(evax_section_table)[i]; - while (es != NULL) - { - es1 = es->next; - free (es); - es = es1; - } - PRIV(evax_section_table)[i] = NULL; - } - - free (abfd->tdata.any); - abfd->tdata.any = NULL; - - return true; -} - - -/* Ask the BFD to free all cached information. */ -static boolean -evax_bfd_free_cached_info (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_free_cached_info(%p)\n", abfd); -#endif - return true; -} - - -/* Called when a new section is created. */ - -static boolean -evax_new_section_hook (abfd, section) - bfd *abfd; - asection *section; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_new_section_hook(%p, %s)\n", abfd, section->name); -#endif - bfd_set_section_alignment(abfd, section, 4); - return true; -} - - -/* Read the contents of a section. - buf points to a buffer of buf_size bytes to be filled with - section data (starting at offset into section) */ - -static boolean -evax_get_section_contents (abfd, section, buf, offset, buf_size) - bfd *abfd; - asection *section; - PTR buf; - file_ptr offset; - bfd_size_type buf_size; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_section_contents(%p, %s, %p, off %ld, size %d)\n", - abfd, section->name, buf, offset, (int)buf_size); -#endif - - /* shouldn't be called, since all sections are IN_MEMORY */ - - return false; -} - -/* Read the contents of a section. - buf points to a buffer of buf_size bytes to be filled with - section data (starting at offset into section) */ - -static boolean -evax_get_section_contents_in_window (abfd, section, w, offset, count) - bfd *abfd; - asection *section; - bfd_window *w; - file_ptr offset; - bfd_size_type count; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_section_contents_in_window(%p, %s, %p, off %ld, count %d)\n", - abfd, section->name, w, offset, (int)count); -#endif - - /* shouldn't be called, since all sections are IN_MEMORY */ - - return false; -} - -/*-- Part 4.2, copy private data --------------------------------------------*/ - -/* Called to copy BFD general private data from one object file - to another. */ - -static boolean -evax_bfd_copy_private_bfd_data (src, dest) - bfd *src; - bfd *dest; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_copy_private_bfd_data(%p, %p)\n", src, dest); -#endif - return true; -} - - -/* Merge private BFD information from the BFD @var{ibfd} to the - the output file BFD @var{obfd} when linking. Return <> - on success, <> on error. Possible error returns are: - - o <> - - Not enough memory exists to create private data for @var{obfd}. */ - -static boolean -evax_bfd_merge_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; -{ -#if EVAX_DEBUG - evax_debug (1,"evax_bfd_merge_private_bfd_data(%p, %p)\n", ibfd, obfd); -#endif - return true; -} - - -/* Set private BFD flag information in the BFD @var{abfd}. - Return <> on success, <> on error. Possible error - returns are: - - o <> - - Not enough memory exists to create private data for @var{obfd}. */ - -static boolean -evax_bfd_set_private_flags (abfd, flags) - bfd *abfd; - flagword flags; -{ -#if EVAX_DEBUG - evax_debug (1,"evax_bfd_set_private_flags(%p, %lx)\n", abfd, (long)flags); -#endif - return true; -} - - -/* Called to copy BFD private section data from one object file - to another. */ - -static boolean -evax_bfd_copy_private_section_data (srcbfd, srcsec, dstbfd, dstsec) - bfd *srcbfd; - asection *srcsec; - bfd *dstbfd; - asection *dstsec; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_copy_private_section_data(%p, %s, %p, %s)\n", - srcbfd, srcsec->name, dstbfd, dstsec->name); -#endif - return true; -} - -/* Called to copy BFD private symbol data from one object file - to another. */ - -static boolean -evax_bfd_copy_private_symbol_data (ibfd, isym, obfd, osym) - bfd *ibfd; - asymbol *isym; - bfd *obfd; - asymbol *osym; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_copy_private_symbol_data(%p, %s, %p, %s)\n", - ibfd, isym->name, obfd, osym->name); -#endif - return true; -} - -/*-- Part 4.3, core file ----------------------------------------------------*/ - -/* Return a read-only string explaining which program was running - when it failed and produced the core file abfd. */ - -static char * -evax_core_file_failing_command (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_core_file_failing_command(%p)\n", abfd); -#endif - return 0; -} - - -/* Returns the signal number which caused the core dump which - generated the file the BFD abfd is attached to. */ - -static int -evax_core_file_failing_signal (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_core_file_failing_signal(%p)\n", abfd); -#endif - return 0; -} - - -/* Return true if the core file attached to core_bfd was generated - by a run of the executable file attached to exec_bfd, false otherwise. */ - -static boolean -evax_core_file_matches_executable_p (abfd, bbfd) - bfd *abfd; - bfd *bbfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_core_file_matches_executable_p(%p, %p)\n", abfd, bbfd); -#endif - return false; -} - -/*-- Part 4.4, archive ------------------------------------------------------*/ - -/* ??? do something with an archive map. - Return false on error, true otherwise. */ - -static boolean -evax_slurp_armap (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_slurp_armap(%p)\n", abfd); -#endif - return false; -} - - -/* ??? do something with an extended name table. - Return false on error, true otherwise. */ - -static boolean -evax_slurp_extended_name_table (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_slurp_extended_name_table(%p)\n", abfd); -#endif - return false; -} - - -/* ??? do something with an extended name table. - Return false on error, true otherwise. */ - -static boolean -evax_construct_extended_name_table (abfd, tabloc, tablen, name) - bfd *abfd; - char **tabloc; - bfd_size_type *tablen; - const char **name; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_construct_extended_name_table(%p)\n", abfd); -#endif - return false; -} - - -/* Truncate the name of an archive to match system-dependent restrictions */ - -static void -evax_truncate_arname (abfd, pathname, arhdr) - bfd *abfd; - CONST char *pathname; - char *arhdr; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_truncate_arname(%p, %s, %s)\n", abfd, pathname, arhdr); -#endif - return; -} - - -/* ??? write archive map */ - -static boolean -evax_write_armap (arch, elength, map, orl_count, stridx) - bfd *arch; - unsigned int elength; - struct orl *map; - unsigned int orl_count; - int stridx; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_write_armap(%p, %d, %p, %d %d)\n", - arch, elength, map, orl_count, stridx); -#endif - return true; -} - -/* Read archive header ??? */ - -static PTR -evax_read_ar_hdr (abfd) - bfd * abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_read_ar_hdr(%p)\n", abfd); -#endif - return (PTR)0; -} - - -/* Provided a BFD, @var{archive}, containing an archive and NULL, open - an input BFD on the first contained element and returns that. - Subsequent calls should pass the archive and the previous return value - to return a created BFD to the next contained element. - NULL is returned when there are no more. */ - -static bfd * -evax_openr_next_archived_file (arch, prev) - bfd *arch; - bfd *prev; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_openr_next_archived_file(%p, %p)\n", arch, prev); -#endif - return false; -} - - -/* Return the BFD which is referenced by the symbol in ABFD indexed by - INDEX. INDEX should have been returned by bfd_get_next_mapent. */ - -static bfd * -evax_get_elt_at_index (abfd, index) - bfd *abfd; - symindex index; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_elt_at_index(%p, %p)\n", abfd, index); -#endif - return _bfd_generic_get_elt_at_index(abfd, index); -} - - -/* ??? - -> bfd_generic_stat_arch_elt */ - -static int -evax_generic_stat_arch_elt (abfd, stat) - bfd *abfd; - struct stat *stat; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_generic_stat_arch_elt(%p, %p)\n", abfd, stat); -#endif - return bfd_generic_stat_arch_elt(abfd, stat); -} - - -/* This is a new function in bfd 2.5 */ - -static boolean -evax_update_armap_timestamp (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_update_armap_timestamp(%p)\n", abfd); -#endif - return true; -} - -/*-- Part 4.5, symbols --------------------------------------------------------*/ - -/* Return the number of bytes required to store a vector of pointers - to asymbols for all the symbols in the BFD abfd, including a - terminal NULL pointer. If there are no symbols in the BFD, - then return 0. If an error occurs, return -1. */ - -static long -evax_get_symtab_upper_bound (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_symtab_upper_bound(%p), %d symbols\n", abfd, PRIV(egsd_sym_count)); -#endif - return (PRIV(egsd_sym_count)+1) * sizeof(asymbol *); -} - - -/* Copy symbols from hash table to symbol vector - - called from bfd_hash_traverse in evax_get_symtab - init counter to 0 if entry == 0 */ - -static boolean -copy_symbols (entry, arg) - struct bfd_hash_entry *entry; - PTR arg; -{ - bfd *abfd = (bfd *) arg; - - if (entry == NULL) /* init counter */ - PRIV(symnum) = 0; - else /* fill vector, inc counter */ - PRIV(symcache)[PRIV(symnum)++] = ((evax_symbol_entry *)entry)->symbol; - - return true; -} - - -/* Read the symbols from the BFD abfd, and fills in the vector - location with pointers to the symbols and a trailing NULL. - - return # of symbols read */ - -static long -evax_get_symtab (abfd, symbols) - bfd *abfd; - asymbol **symbols; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_symtab(%p, )\n", abfd); -#endif - - /* init counter */ - (void)copy_symbols((struct bfd_hash_entry *)0, abfd); - - /* traverse table and fill symbols vector */ - - PRIV(symcache) = symbols; - bfd_hash_traverse(PRIV(evax_symbol_table), copy_symbols, (PTR)abfd); - - symbols[PRIV(egsd_sym_count)] = NULL; - - return PRIV(egsd_sym_count); -} - - -/* Create a new asymbol structure for the BFD abfd and return a pointer - to it. - This routine is necessary because each back end has private information - surrounding the asymbol. Building your own asymbol and pointing to it - will not create the private information, and will cause problems later on. */ - -asymbol * -_bfd_evax_make_empty_symbol (abfd) - bfd *abfd; -{ - asymbol *symbol = (asymbol *)bfd_zalloc(abfd, sizeof(asymbol)); - -#if EVAX_DEBUG - evax_debug (1, "_bfd_evax_make_empty_symbol(%p)\n", abfd); -#endif - - if (symbol == 0) - { - bfd_set_error (bfd_error_no_memory); - return 0; - } - symbol->the_bfd = abfd; - - return symbol; -} - - -/* Print symbol to file according to how. how is one of - bfd_print_symbol_name just print the name - bfd_print_symbol_more print more (???) - bfd_print_symbol_all print all we know, which is not much right now :-) */ - -static void -evax_print_symbol (abfd, file, symbol, how) - bfd *abfd; - PTR file; - asymbol *symbol; - bfd_print_symbol_type how; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_print_symbol(%p, %p, %p, %d)\n", abfd, file, symbol, how); -#endif - - switch (how) - { - case bfd_print_symbol_name: - case bfd_print_symbol_more: - fprintf((FILE *)file," %s", symbol->name); - break; - - break; - - case bfd_print_symbol_all: - { - CONST char *section_name = symbol->section->name; - - bfd_print_symbol_vandf((PTR)file,symbol); - - fprintf((FILE *)file," %-8s %s", section_name, symbol->name); - } - break; - } - return; -} - - -/* Return information about symbol in ret. - - fill type, value and name - type: - A absolute - B bss segment symbol - C common symbol - D data segment symbol - f filename - t a static function symbol - T text segment symbol - U undefined - - debug */ - -static void -evax_get_symbol_info (abfd, symbol, ret) - bfd *abfd; - asymbol *symbol; - symbol_info *ret; -{ - asection *sec; - -#if EVAX_DEBUG - evax_debug (1, "evax_get_symbol_info(%p, %p, )\n", abfd, symbol); -#endif - - sec = symbol->section; - - if (bfd_is_com_section (sec)) - ret->type = 'C'; - else if (bfd_is_abs_section (sec)) - ret->type = 'A'; - else if (bfd_is_und_section (sec)) - ret->type = 'U'; - else if (bfd_is_ind_section (sec)) - ret->type = 'I'; - else if (bfd_get_section_flags (abfd, sec) & SEC_CODE) - ret->type = 'T'; - else if (bfd_get_section_flags (abfd, sec) & SEC_DATA) - ret->type = 'D'; - else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC) - ret->type = 'B'; - else - ret->type = '-'; - - if (ret->type != 'U') - ret->value = symbol->value + symbol->section->vma; - else - ret->value = 0; - ret->name = symbol->name; - - return; -} - - -/* Return true if the given symbol sym in the BFD abfd is - a compiler generated local label, else return false. */ - -static boolean -evax_bfd_is_local_label_name (abfd, name) - bfd *abfd; - const char *name; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_is_local_label_name(%p, %s)\n", abfd, name); -#endif - return name[0] == '$'; -} - - -/* Get source line number for symbol */ - -static alent * -evax_get_lineno (abfd, symbol) - bfd *abfd; - asymbol *symbol; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_lineno(%p, %p)\n", abfd, symbol); -#endif - return 0; -} - - -/* 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. */ - -static boolean -evax_find_nearest_line (abfd, section, symbols, offset, file, func, line) - bfd *abfd; - asection *section; - asymbol **symbols; - bfd_vma offset; - CONST char **file; - CONST char **func; - unsigned int *line; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_find_nearest_line(%p, %s, %p, %ld, , , )\n", - abfd, section->name, symbols, (long int)offset); -#endif - return false; -} - - -/* Back-door to allow format-aware applications to create debug symbols - while using BFD for everything else. Currently used by the assembler - when creating COFF files. */ - -static asymbol * -evax_bfd_make_debug_symbol (abfd, ptr, size) - bfd *abfd; - void *ptr; - unsigned long size; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_make_debug_symbol(%p, %p, %ld)\n", abfd, ptr, size); -#endif - return 0; -} - - -/* Read minisymbols. For minisymbols, we use the unmodified a.out - symbols. The minisymbol_to_symbol function translates these into - BFD asymbol structures. */ - -static long -evax_read_minisymbols (abfd, dynamic, minisymsp, sizep) - bfd *abfd; - boolean dynamic; - PTR *minisymsp; - unsigned int *sizep; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_read_minisymbols(%p, %d, %p, %d)\n", abfd, dynamic, minisymsp, *sizep); -#endif - return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep); -} - -/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an - unmodified a.out symbol. The SYM argument is a structure returned - by bfd_make_empty_symbol, which we fill in here. */ - -static asymbol * -evax_minisymbol_to_symbol (abfd, dynamic, minisym, sym) - bfd *abfd; - boolean dynamic; - const PTR minisym; - asymbol *sym; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_minisymbol_to_symbol(%p, %d, %p, %p)\n", abfd, dynamic, minisym, sym); -#endif - return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym); -} - -/*-- Part 4.6, relocations --------------------------------------------------*/ - -/* Return the number of bytes required to store the relocation information - associated with section sect attached to bfd abfd. - If an error occurs, return -1. */ - -static long -evax_get_reloc_upper_bound (abfd, section) - bfd *abfd; - asection *section; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_reloc_upper_bound(%p, %s)\n", abfd, section->name); -#endif - return -1L; -} - - -/* Call the back end associated with the open BFD abfd and translate the - external form of the relocation information attached to sec into the - internal canonical form. Place the table into memory at loc, which has - been preallocated, usually by a call to bfd_get_reloc_upper_bound. - Returns the number of relocs, or -1 on error. */ - -static long -evax_canonicalize_reloc (abfd, section, location, symbols) - bfd *abfd; - asection *section; - arelent **location; - asymbol **symbols; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_canonicalize_reloc(%p, %s, , )\n", abfd, section->name); -#endif - return false; -} - -/*---------------------------------------------------------------------------*/ -/* this is just copied from ecoff-alpha, needs to be fixed probably */ - -/* How to process the various reloc types. */ - -static bfd_reloc_status_type -reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) - bfd *abfd; - arelent *reloc; - asymbol *sym; - PTR data; - asection *sec; - bfd *output_bfd; - char **error_message; -{ -#if EVAX_DEBUG - evax_debug (1, "reloc_nil(abfd %p, output_bfd %p)\n", abfd, output_bfd); - evax_debug (2, "In section %s, symbol %s\n", - sec->name, sym->name); - evax_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n", - reloc->sym_ptr_ptr[0]->name, - (unsigned long)reloc->address, - (unsigned long)reloc->addend, reloc->howto->name); - evax_debug (2, "data at %p\n", data); -/* _bfd_hexdump (2, data, bfd_get_reloc_size(reloc->howto),0); */ -#endif - - return bfd_reloc_ok; -} - -/* In case we're on a 32-bit machine, construct a 64-bit "-1" value - from smaller values. Start with zero, widen, *then* decrement. */ -#define MINUS_ONE (((bfd_vma)0) - 1) - -static reloc_howto_type alpha_howto_table[] = -{ - HOWTO (ALPHA_R_IGNORE, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "IGNORE", /* name */ - true, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - true), /* pcrel_offset */ - - /* A 64 bit reference to a symbol. */ - HOWTO (ALPHA_R_REFQUAD, /* type */ - 0, /* rightshift */ - 4, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "REFQUAD", /* name */ - true, /* partial_inplace */ - MINUS_ONE, /* src_mask */ - MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ - - /* A 21 bit branch. The native assembler generates these for - branches within the text segment, and also fills in the PC - relative offset in the instruction. */ - HOWTO (ALPHA_R_BRADDR, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 21, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "BRADDR", /* name */ - true, /* partial_inplace */ - 0x1fffff, /* src_mask */ - 0x1fffff, /* dst_mask */ - false), /* pcrel_offset */ - - /* A hint for a jump to a register. */ - HOWTO (ALPHA_R_HINT, /* type */ - 2, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 14, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "HINT", /* name */ - true, /* partial_inplace */ - 0x3fff, /* src_mask */ - 0x3fff, /* dst_mask */ - false), /* pcrel_offset */ - - /* 16 bit PC relative offset. */ - HOWTO (ALPHA_R_SREL16, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "SREL16", /* name */ - true, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - false), /* pcrel_offset */ - - /* 32 bit PC relative offset. */ - HOWTO (ALPHA_R_SREL32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "SREL32", /* name */ - true, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - /* A 64 bit PC relative offset. */ - HOWTO (ALPHA_R_SREL64, /* type */ - 0, /* rightshift */ - 4, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ - true, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "SREL64", /* name */ - true, /* partial_inplace */ - MINUS_ONE, /* src_mask */ - MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ - - /* Push a value on the reloc evaluation stack. */ - HOWTO (ALPHA_R_OP_PUSH, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "OP_PUSH", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ - - /* Store the value from the stack at the given address. Store it in - a bitfield of size r_size starting at bit position r_offset. */ - HOWTO (ALPHA_R_OP_STORE, /* type */ - 0, /* rightshift */ - 4, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "OP_STORE", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ - - /* Subtract the reloc address from the value on the top of the - relocation stack. */ - HOWTO (ALPHA_R_OP_PSUB, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "OP_PSUB", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ - - /* Shift the value on the top of the relocation stack right by the - given value. */ - HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "OP_PRSHIFT", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ - - /* Hack. Linkage is done by linker. */ - HOWTO (ALPHA_R_LINKAGE, /* type */ - 0, /* rightshift */ - 8, /* size (0 = byte, 1 = short, 2 = long) */ - 256, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "LINKAGE", /* name */ - false, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - false), /* pcrel_offset */ - - /* A 32 bit reference to a symbol. */ - HOWTO (ALPHA_R_REFLONG, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - reloc_nil, /* special_function */ - "REFLONG", /* name */ - true, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - - /* A 64 bit reference to a procedure, written as 32 bit value. */ - HOWTO (ALPHA_R_CODEADDR, /* type */ - 0, /* rightshift */ - 4, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed,/* complain_on_overflow */ - reloc_nil, /* special_function */ - "CODEADDR", /* name */ - false, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - -}; - -/* Return a pointer to a howto structure which, when invoked, will perform - the relocation code on data from the architecture noted. */ - -static const struct reloc_howto_struct * -evax_bfd_reloc_type_lookup (abfd, code) - bfd *abfd; - bfd_reloc_code_real_type code; -{ - int alpha_type; - -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_reloc_type_lookup(%p, %d)\t", abfd, code); -#endif - - switch (code) - { - case BFD_RELOC_16: alpha_type = ALPHA_R_SREL16; break; - case BFD_RELOC_32: alpha_type = ALPHA_R_REFLONG; break; - case BFD_RELOC_64: alpha_type = ALPHA_R_REFQUAD; break; - case BFD_RELOC_CTOR: alpha_type = ALPHA_R_REFQUAD; break; - case BFD_RELOC_23_PCREL_S2: alpha_type = ALPHA_R_BRADDR; break; - case BFD_RELOC_ALPHA_HINT: alpha_type = ALPHA_R_HINT; break; - case BFD_RELOC_16_PCREL: alpha_type = ALPHA_R_SREL16; break; - case BFD_RELOC_32_PCREL: alpha_type = ALPHA_R_SREL32; break; - case BFD_RELOC_64_PCREL: alpha_type = ALPHA_R_SREL64; break; - case BFD_RELOC_ALPHA_LINKAGE: alpha_type = ALPHA_R_LINKAGE; break; - case BFD_RELOC_ALPHA_CODEADDR: alpha_type = ALPHA_R_CODEADDR; break; - default: - (*_bfd_error_handler) ("reloc (%d) is *UNKNOWN*", code); - return (const struct reloc_howto_struct *) NULL; - } -#if EVAX_DEBUG - evax_debug (2, "reloc is %s\n", alpha_howto_table[alpha_type].name); -#endif - return &alpha_howto_table[alpha_type]; -} - - -/*-- Part 4.7, writing an object file ---------------------------------------*/ - -/* Set the architecture and machine type in BFD abfd to arch and mach. - Find the correct pointer to a structure and insert it into the arch_info - pointer. */ - -static boolean -evax_set_arch_mach (abfd, arch, mach) - bfd *abfd; - enum bfd_architecture arch; - unsigned long mach; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_set_arch_mach(%p, %d, %ld)\n", abfd, arch, mach); -#endif - if (arch != bfd_arch_alpha - && arch != bfd_arch_unknown) - return false; - - return bfd_default_set_arch_mach (abfd, arch, mach); -} - - -/* Sets the contents of the section section in BFD abfd to the data starting - in memory at data. The data is written to the output section starting at - offset offset for count bytes. - - Normally true is returned, else false. Possible error returns are: - o bfd_error_no_contents - The output section does not have the - SEC_HAS_CONTENTS attribute, so nothing can be written to it. - o and some more too */ - -static boolean -evax_set_section_contents (abfd, section, location, offset, count) - bfd *abfd; - asection *section; - PTR location; - file_ptr offset; - bfd_size_type count; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_set_section_contents(%p, sec %s, loc %p, off %ld, count %d)\n", - abfd, section->name, location, (long int)offset, (int)count); - evax_debug (2, "secraw %d, seccooked %d\n", (int)section->_raw_size, (int)section->_cooked_size); -#endif - return _bfd_save_evax_section(abfd, section, location, offset, count); -} - - -/*-- Part 4.8, linker -------------------------------------------------------*/ - -/* Get the size of the section headers. */ - -static int -evax_sizeof_headers (abfd, reloc) - bfd *abfd; - boolean reloc; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_sizeof_headers(%p, %s)\n", abfd, (reloc)?"True":"False"); -#endif - return 0; -} - - -/* Provides default handling of relocation effort for back ends - which can't be bothered to do it efficiently. */ - -static bfd_byte * -evax_bfd_get_relocated_section_contents (abfd, link_info, link_order, data, - relocateable, symbols) - bfd *abfd; - struct bfd_link_info *link_info; - struct bfd_link_order *link_order; - bfd_byte *data; - boolean relocateable; - asymbol **symbols; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_get_relocated_section_contents(%p, %p, %p, %p, %s, %p)\n", - abfd, link_info, link_order, data, (relocateable)?"True":"False", symbols); -#endif - return 0; -} - - -/* ??? */ - -static boolean -evax_bfd_relax_section (abfd, section, link_info, again) - bfd *abfd; - asection *section; - struct bfd_link_info *link_info; - boolean *again; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_relax_section(%p, %s, %p, )\n", - abfd, section->name, link_info); -#endif - return true; -} - -static boolean -evax_bfd_gc_sections (abfd, link_info) - bfd *abfd; - struct bfd_link_info *link_info; - const char *entry; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_gc_sections(%p, %p)\n", abfd, link_info); -#endif - return true; -} - - -/* Create a hash table for the linker. Different backends store - different information in this table. */ - -static struct bfd_link_hash_table * -evax_bfd_link_hash_table_create (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_link_hash_table_create(%p)\n", abfd); -#endif - return 0; -} - - -/* Add symbols from this object file into the hash table. */ - -static boolean -evax_bfd_link_add_symbols (abfd, link_info) - bfd *abfd; - struct bfd_link_info *link_info; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_link_add_symbols(%p, %p)\n", abfd, link_info); -#endif - return false; -} - - -/* Do a link based on the link_order structures attached to each - section of the BFD. */ - -static boolean -evax_bfd_final_link (abfd, link_info) - bfd *abfd; - struct bfd_link_info *link_info; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_final_link(%p, %p)\n", abfd, link_info); -#endif - return true; -} - -/* Should this section be split up into smaller pieces during linking. */ - -static boolean -evax_bfd_link_split_section (abfd, section) - bfd *abfd; - asection *section; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_link_split_section(%p, %s)\n", abfd, section->name); -#endif - return false; -} - -/*-- Part 4.9, dynamic symbols and relocations ------------------------------*/ - -/* Get the amount of memory required to hold the dynamic symbols. */ - -static long -evax_get_dynamic_symtab_upper_bound (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_dynamic_symtab_upper_bound(%p)\n", abfd); -#endif - return 0; -} - -static boolean -evax_bfd_print_private_bfd_data (abfd, file) - bfd *abfd; - void *file; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_bfd_print_private_bfd_data(%p)\n", abfd); -#endif - return 0; -} - - -/* Read in the dynamic symbols. */ - -static long -evax_canonicalize_dynamic_symtab (abfd, symbols) - bfd *abfd; - asymbol **symbols; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_canonicalize_dynamic_symtab(%p, )\n", abfd); -#endif - return 0L; -} - - -/* Get the amount of memory required to hold the dynamic relocs. */ - -static long -evax_get_dynamic_reloc_upper_bound (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_get_dynamic_reloc_upper_bound(%p)\n", abfd); -#endif - return 0L; -} - - -/* Read in the dynamic relocs. */ - -static long -evax_canonicalize_dynamic_reloc (abfd, arel, symbols) - bfd *abfd; - arelent **arel; - asymbol **symbols; -{ -#if EVAX_DEBUG - evax_debug (1, "evax_canonicalize_dynamic_reloc(%p)\n", abfd); -#endif - return 0L; -} diff --git a/bfd/evax-egsd.c b/bfd/evax-egsd.c deleted file mode 100644 index 567fe46e144..00000000000 --- a/bfd/evax-egsd.c +++ /dev/null @@ -1,596 +0,0 @@ -/* evax-egsd.c -- BFD back-end for ALPHA EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998 Free Software Foundation Inc. - - go and read the openVMS linker manual (esp. appendix B) - if you don't know what's going on here :-) - - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#include - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" -#include "libbfd.h" - -#include "evax.h" - -/*-----------------------------------------------------------------------------*/ - -/* sections every evax object file has */ - -#define EVAX_ABS_NAME "$ABS$" -#define EVAX_CODE_NAME "$CODE$" -#define EVAX_LINK_NAME "$LINK$" -#define EVAX_DATA_NAME "$DATA$" -#define EVAX_BSS_NAME "$BSS$" -#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" -#define EVAX_READONLY_NAME "$READONLY$" -#define EVAX_LITERAL_NAME "$LITERAL$" -#define EVAX_COMMON_NAME "$COMMON$" -#define EVAX_LOCAL_NAME "$LOCAL$" - -struct sec_flags_struct { - char *name; /* name of section */ - int eflags_always; - flagword flags_always; /* flags we set always */ - int eflags_hassize; - flagword flags_hassize; /* flags we set if the section has a size > 0 */ -}; - -/* These flags are deccrtl/vaxcrtl (openVMS 6.2) compatible */ - -static struct sec_flags_struct evax_section_flags[] = { - { EVAX_ABS_NAME, - (EGPS_S_V_SHR), - (SEC_DATA), - (EGPS_S_V_SHR), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, - { EVAX_CODE_NAME, - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), - (SEC_CODE), - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), - (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, - { EVAX_LITERAL_NAME, - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), - (SEC_DATA|SEC_READONLY), - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, - { EVAX_LINK_NAME, - (EGPS_S_V_REL|EGPS_S_V_RD), - (SEC_DATA|SEC_READONLY), - (EGPS_S_V_REL|EGPS_S_V_RD), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, - { EVAX_DATA_NAME, - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), - (SEC_DATA), - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, - { EVAX_BSS_NAME, - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), - (SEC_NO_FLAGS), - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), - (SEC_IN_MEMORY|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, - { EVAX_READONLYADDR_NAME, - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), - (SEC_DATA|SEC_READONLY), - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, - { EVAX_READONLY_NAME, - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), - (SEC_DATA|SEC_READONLY), - (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, - { EVAX_LOCAL_NAME, - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), - (SEC_DATA), - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, - { NULL, - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), - (SEC_DATA), - (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), - (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } -}; - -/* Retrieve bfd section flags by name and size */ - -static flagword -evax_secflag_by_name(name, size) - char *name; - int size; -{ - int i = 0; - - while (evax_section_flags[i].name != NULL) - { - if (strcmp (name, evax_section_flags[i].name) == 0) - { - if (size > 0) - return evax_section_flags[i].flags_hassize; - else - return evax_section_flags[i].flags_always; - } - i++; - } - if (size > 0) - return evax_section_flags[i].flags_hassize; - return evax_section_flags[i].flags_always; -} - - -/* Retrieve evax section flags by name and size */ - -static flagword -evax_esecflag_by_name(name, size) - char *name; - int size; -{ - int i = 0; - - while (evax_section_flags[i].name != NULL) - { - if (strcmp (name, evax_section_flags[i].name) == 0) - { - if (size > 0) - return evax_section_flags[i].eflags_hassize; - else - return evax_section_flags[i].eflags_always; - } - i++; - } - if (size > 0) - return evax_section_flags[i].eflags_hassize; - return evax_section_flags[i].eflags_always; -} - -/*-----------------------------------------------------------------------------*/ -#if EVAX_DEBUG -/* debug */ - -struct flagdescstruct { char *name; flagword value; }; - -/* Convert flag to printable string */ - -static char * -flag2str(flagdesc, flags) - struct flagdescstruct *flagdesc; - flagword flags; -{ - - static char res[64]; - int next = 0; - - res[0] = 0; - while (flagdesc->name != NULL) - { - if ((flags & flagdesc->value) != 0) - { - if (next) - strcat(res, ","); - else - next = 1; - strcat (res, flagdesc->name); - } - flagdesc++; - } - return res; -} -#endif - -/*-----------------------------------------------------------------------------*/ -/* input routines */ - -/* Process EGSD record - return 0 on success, -1 on error */ - -int -_bfd_evax_slurp_egsd (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - static struct flagdescstruct gpsflagdesc[] = - { - { "PIC", 0x0001 }, - { "LIB", 0x0002 }, - { "OVR", 0x0004 }, - { "REL", 0x0008 }, - { "GBL", 0x0010 }, - { "SHR", 0x0020 }, - { "EXE", 0x0040 }, - { "RD", 0x0080 }, - { "WRT", 0x0100 }, - { "VEC", 0x0200 }, - { "NOMOD", 0x0400 }, - { "COM", 0x0800 }, - { NULL, 0 } - }; - - static struct flagdescstruct gsyflagdesc[] = - { - { "WEAK", 0x0001 }, - { "DEF", 0x0002 }, - { "UNI", 0x0004 }, - { "REL", 0x0008 }, - { "COMM", 0x0010 }, - { "VECEP", 0x0020 }, - { "NORM", 0x0040 }, - { NULL, 0 } - }; -#endif - - int gsd_type, gsd_size; - asection *section; - unsigned char *evax_rec; - flagword new_flags, old_flags; - char *name; - asymbol *symbol; - evax_symbol_entry *entry; - unsigned long base_addr; - unsigned long align_addr; - -#if EVAX_DEBUG - evax_debug (2, "EGSD\n"); -#endif - - PRIV(evax_rec) += 8; /* skip type, size, l_temp */ - PRIV(rec_size) -= 8; - - /* calculate base address for each section */ - base_addr = 0L; - - abfd->symcount = 0; - - while (PRIV(rec_size) > 0) - { - evax_rec = PRIV(evax_rec); - _bfd_evax_get_header_values (abfd, evax_rec, &gsd_type, &gsd_size); - switch (gsd_type) - { - case EGSD_S_C_PSC: - { - /* program section definition */ - - name = _bfd_evax_save_counted_string ((char *)evax_rec+12); - section = bfd_make_section (abfd, name); - if (!section) - return -1; - old_flags = bfd_getl16 (evax_rec + 6); - section->_raw_size = bfd_getl32 (evax_rec + 8); /* allocation */ - new_flags = evax_secflag_by_name (name, (int) section->_raw_size); - if (old_flags & EGPS_S_V_REL) - new_flags |= SEC_RELOC; - if (!bfd_set_section_flags (abfd, section, new_flags)) - return -1; - section->alignment_power = evax_rec[4]; - align_addr = (1 << section->alignment_power); - if ((base_addr % align_addr) != 0) - base_addr += (align_addr - (base_addr % align_addr)); - section->vma = (bfd_vma)base_addr; - base_addr += section->_raw_size; - section->contents = ((unsigned char *) - bfd_malloc (section->_raw_size)); - if (section->contents == NULL) - return -1; - memset (section->contents, 0, (size_t) section->_raw_size); - section->_cooked_size = section->_raw_size; -#if EVAX_DEBUG - evax_debug(3, "egsd psc %d (%s, flags %04x=%s) ", - section->index, name, old_flags, flag2str(gpsflagdesc, old_flags)); - evax_debug(3, "%d bytes at 0x%08lx (mem %p)\n", - section->_raw_size, section->vma, section->contents); -#endif - } - break; - - case EGSD_S_C_SYM: - { - /* symbol specification (definition or reference) */ - - symbol = _bfd_evax_make_empty_symbol (abfd); - if (symbol == 0) - return -1; - - old_flags = bfd_getl16 (evax_rec + 6); - new_flags = BSF_NO_FLAGS; - - if (old_flags & EGSY_S_V_WEAK) - new_flags |= BSF_WEAK; - - if (evax_rec[6] & EGSY_S_V_DEF) /* symbol definition */ - { - symbol->name = - _bfd_evax_save_counted_string ((char *)evax_rec+32); - if (old_flags & EGSY_S_V_NORM) - { /* proc def */ - new_flags |= BSF_FUNCTION; - } - symbol->value = bfd_getl64 (evax_rec+8); - symbol->section = (asection *)((unsigned long) bfd_getl32 (evax_rec+28)); -#if EVAX_DEBUG - evax_debug(3, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, - symbol->name, (int)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); -#endif - } - else /* symbol reference */ - { - symbol->name = - _bfd_evax_save_counted_string ((char *)evax_rec+8); -#if EVAX_DEBUG - evax_debug(3, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, - symbol->name, old_flags, flag2str(gsyflagdesc, old_flags)); -#endif - symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); - } - - symbol->flags = new_flags; - - /* save symbol in evax_symbol_table */ - - entry = (evax_symbol_entry *) bfd_hash_lookup (PRIV(evax_symbol_table), symbol->name, true, false); - if (entry == (evax_symbol_entry *)NULL) - { - bfd_set_error (bfd_error_no_memory); - return -1; - } - if (entry->symbol != (asymbol *)NULL) - { /* FIXME ?, DEC C generates this */ -#if EVAX_DEBUG - evax_debug(3, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); -#endif - } - else - { - entry->symbol = symbol; - PRIV(egsd_sym_count)++; - abfd->symcount++; - } - } - break; - - case EGSD_S_C_IDC: - break; - - default: - (*_bfd_error_handler) (_("unknown egsd subtype %d"), gsd_type); - bfd_set_error (bfd_error_bad_value); - return -1; - - } /* switch */ - - PRIV(rec_size) -= gsd_size; - PRIV(evax_rec) += gsd_size; - - } /* while (recsize > 0) */ - - if (abfd->symcount > 0) - abfd->flags |= HAS_SYMS; - - return 0; -} - -/*-----------------------------------------------------------------------------*/ -/* output routines */ - -/* Write section and symbol directory of bfd abfd */ - -int -_bfd_evax_write_egsd (abfd) - bfd *abfd; -{ - asection *section; - asymbol *symbol; - int symnum; - int last_index = -1; - char dummy_name[10]; - char *sname; - flagword new_flags, old_flags; - char *nptr, *uptr; - -#if EVAX_DEBUG - evax_debug (2, "evax_write_egsd(%p)\n", abfd); -#endif - - /* output sections */ - - section = abfd->sections; -#if EVAX_DEBUG - evax_debug (3, "%d sections found\n", abfd->section_count); -#endif - - /* egsd is quadword aligned */ - - _bfd_evax_output_alignment (abfd, 8); - - _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); - _bfd_evax_output_long (abfd, 0); - _bfd_evax_output_push (abfd); /* prepare output for subrecords */ - - while (section != 0) - { -#if EVAX_DEBUG - evax_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->_raw_size); -#endif - - /* 13 bytes egsd, max 31 chars name -> should be 44 bytes */ - if (_bfd_evax_output_check (abfd, 64) < 0) - { - _bfd_evax_output_pop (abfd); - _bfd_evax_output_end (abfd); - _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); - _bfd_evax_output_long (abfd, 0); - _bfd_evax_output_push (abfd); /* prepare output for subrecords */ - } - - /* Create dummy sections to keep consecutive indices */ - - while (section->index - last_index > 1) - { -#if EVAX_DEBUG - evax_debug (3, "index %d, last %d\n", section->index, last_index); -#endif - _bfd_evax_output_begin (abfd, EGSD_S_C_PSC, -1); - _bfd_evax_output_short (abfd, 0); - _bfd_evax_output_short (abfd, 0); - _bfd_evax_output_long (abfd, 0); - sprintf (dummy_name, ".DUMMY%02d", last_index); - _bfd_evax_output_counted (abfd, dummy_name); - _bfd_evax_output_flush (abfd); - last_index++; - } - - /* Don't know if this is neccesary for the linker but for now it keeps - evax_slurp_egsd happy */ - - sname = (char *)section->name; - if (*sname == '.') - { - sname++; - if ((*sname == 't') && (strcmp (sname, "text") == 0)) - sname = EVAX_CODE_NAME; - else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) - sname = EVAX_DATA_NAME; - else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) - sname = EVAX_BSS_NAME; - else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) - sname = EVAX_LINK_NAME; - else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) - sname = EVAX_READONLY_NAME; - else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) - sname = EVAX_LITERAL_NAME; - else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) - sname = EVAX_COMMON_NAME; - else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) - sname = EVAX_LOCAL_NAME; - } - else - sname = _bfd_evax_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); - - _bfd_evax_output_begin (abfd, EGSD_S_C_PSC, -1); - _bfd_evax_output_short (abfd, section->alignment_power & 0xff); - if (bfd_is_com_section (section)) - { - new_flags = (EGPS_S_V_OVR|EGPS_S_V_REL|EGPS_S_V_GBL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD|EGPS_S_V_COM); - } - else - { - new_flags = evax_esecflag_by_name (sname, section->_raw_size); - } - _bfd_evax_output_short (abfd, new_flags); - _bfd_evax_output_long (abfd, section->_raw_size); - _bfd_evax_output_counted (abfd, sname); - _bfd_evax_output_flush (abfd); - - last_index = section->index; - section = section->next; - } - - /* output symbols */ - -#if EVAX_DEBUG - evax_debug (3, "%d symbols found\n", abfd->symcount); -#endif - - bfd_set_start_address (abfd, (bfd_vma)-1); - - for (symnum = 0; symnum < abfd->symcount; symnum++) - { - - symbol = abfd->outsymbols[symnum]; - if (*(symbol->name) == '_') - { - if (strcmp (symbol->name, "__main") == 0) - bfd_set_start_address (abfd, (bfd_vma)symbol->value); - } - old_flags = symbol->flags; - - if (old_flags & BSF_FILE) - continue; - - if (((old_flags & (BSF_GLOBAL|BSF_WEAK)) == 0) /* not xdef */ - && (!bfd_is_und_section (symbol->section))) /* and not xref */ - continue; /* dont output */ - - /* 13 bytes egsd, max 64 chars name -> should be 77 bytes */ - - if (_bfd_evax_output_check (abfd, 80) < 0) - { - _bfd_evax_output_pop (abfd); - _bfd_evax_output_end (abfd); - _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); - _bfd_evax_output_long (abfd, 0); - _bfd_evax_output_push (abfd); /* prepare output for subrecords */ - } - - _bfd_evax_output_begin (abfd, EGSD_S_C_SYM, -1); - - _bfd_evax_output_short (abfd, 0); /* data type, alignment */ - - new_flags = 0; - - if (old_flags & BSF_WEAK) - new_flags |= EGSY_S_V_WEAK; - if (bfd_is_com_section (symbol->section)) /* .comm */ - new_flags |= (EGSY_S_V_WEAK|EGSY_S_V_COMM); - - if (old_flags & BSF_FUNCTION) - { - new_flags |= EGSY_S_V_NORM; - new_flags |= EGSY_S_V_REL; - } - if (old_flags & (BSF_GLOBAL|BSF_WEAK)) - { - new_flags |= EGSY_S_V_DEF; - if (!bfd_is_abs_section (symbol->section)) - new_flags |= EGSY_S_V_REL; - } - _bfd_evax_output_short (abfd, new_flags); - - if (old_flags & (BSF_GLOBAL|BSF_WEAK)) /* symbol definition */ - { - if (old_flags & BSF_FUNCTION) - { - _bfd_evax_output_quad (abfd, symbol->value); - _bfd_evax_output_quad (abfd, - ((asymbol *)(symbol->udata.p))->value); - _bfd_evax_output_long (abfd, - (((asymbol *)(symbol->udata.p)) - ->section->index)); - _bfd_evax_output_long (abfd, symbol->section->index); - } - else - { - _bfd_evax_output_quad (abfd, symbol->value); /* L_VALUE */ - _bfd_evax_output_quad (abfd, 0); /* L_CODE_ADDRESS */ - _bfd_evax_output_long (abfd, 0); /* L_CA_PSINDX */ - _bfd_evax_output_long (abfd, symbol->section->index);/* L_PSINDX */ - } - } - _bfd_evax_output_counted (abfd, _bfd_evax_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ)); - - _bfd_evax_output_flush (abfd); - - } - - _bfd_evax_output_alignment (abfd, 8); - _bfd_evax_output_pop (abfd); - _bfd_evax_output_end (abfd); - - return 0; -} diff --git a/bfd/evax-emh.c b/bfd/evax-emh.c deleted file mode 100644 index 79a63d2adbb..00000000000 --- a/bfd/evax-emh.c +++ /dev/null @@ -1,372 +0,0 @@ -/* evax-emh.c -- BFD back-end for ALPHA EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998 Free Software Foundation, Inc. - - EMH record handling functions - and - EEOM record handling functions - - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" -#include "libbfd.h" - -#include "evax.h" - -/*---------------------------------------------------------------------------*/ - - -/* Read & process emh record - return 0 on success, -1 on error */ - -int -_bfd_evax_slurp_emh (abfd) - bfd *abfd; -{ - unsigned char *ptr; - unsigned char *evax_rec; - - evax_rec = PRIV(evax_rec); - -#if EVAX_DEBUG - evax_debug(2, "EMH\n"); -#endif - - switch (bfd_getl16 (evax_rec + 4)) - { - - case EMH_S_C_MHD: - /* - * module header - */ - PRIV(emh_data).emh_b_strlvl = evax_rec[6]; - PRIV(emh_data).emh_l_arch1 = bfd_getl32 (evax_rec + 8); - PRIV(emh_data).emh_l_arch2 = bfd_getl32 (evax_rec + 12); - PRIV(emh_data).emh_l_recsiz = bfd_getl32 (evax_rec + 16); - PRIV(emh_data).emh_t_name = - _bfd_evax_save_counted_string ((char *)evax_rec + 20); - ptr = evax_rec + 20 + evax_rec[20] + 1; - PRIV(emh_data).emh_t_version = - _bfd_evax_save_counted_string ((char *)ptr); - ptr += *ptr + 1; - PRIV(emh_data).emh_t_date = - _bfd_evax_save_sized_string ((char *)ptr, 17); - - break; - - case EMH_S_C_LNM: - /* - * - */ - PRIV(emh_data).emh_c_lnm = - _bfd_evax_save_sized_string ((char *)evax_rec, PRIV(rec_length-6)); - break; - - case EMH_S_C_SRC: - /* - * - */ - PRIV(emh_data).emh_c_src = - _bfd_evax_save_sized_string ((char *)evax_rec, PRIV(rec_length-6)); - break; - - case EMH_S_C_TTL: - /* - * - */ - PRIV(emh_data).emh_c_ttl = - _bfd_evax_save_sized_string ((char *)evax_rec, PRIV(rec_length-6)); - break; - - case EMH_S_C_CPR: - /* - * - */ - break; - - case EMH_S_C_MTC: - /* - * - */ - break; - - case EMH_S_C_GTX: - /* - * - */ - break; - - default: - bfd_set_error (bfd_error_wrong_format); - return -1; - - } /* switch */ - - return 0; -} - - -/*-----------------------------------------------------------------------------*/ -/* Output routines. */ - - -/* Manufacure a VMS like time on a unix based system. - stolen from obj-vms.c */ - -static unsigned char * -get_vms_time_string () -{ - static unsigned char tbuf[18]; -#ifndef VMS -#include - - 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 (tbuf, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11); -#else -#include - struct - { - int Size; - unsigned char *Ptr; - } Descriptor; - Descriptor.Size = 17; - Descriptor.Ptr = tbuf; - SYS$ASCTIM (0, &Descriptor, 0, 0); -#endif /* not VMS */ - -#if EVAX_DEBUG - evax_debug (6, "vmstimestring:'%s'\n", tbuf); -#endif - - return tbuf; -} - - -/* write object header for bfd abfd */ - -int -_bfd_evax_write_emh (abfd) - bfd *abfd; -{ - asymbol *symbol; - int symnum; - int had_case = 0; - int had_file = 0; - - -#if EVAX_DEBUG - evax_debug (2, "evax_write_emh(%p)\n", abfd); -#endif - - _bfd_evax_output_alignment (abfd, 2); - - /* MHD */ - - _bfd_evax_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD); - _bfd_evax_output_short (abfd, EOBJ_S_C_STRLVL); - _bfd_evax_output_long (abfd, 0); - _bfd_evax_output_long (abfd, 0); - _bfd_evax_output_long (abfd, MAX_OUTREC_SIZE); - - if (bfd_get_filename (abfd) != 0) - { - /* strip path and suffix information */ - - char *fname, *fout, *fptr; - - fptr = bfd_get_filename (abfd); - fname = (char *) alloca (strlen (fptr) + 1); - strcpy (fname, fptr); - fout = strrchr (fname, ']'); - if (fout == 0) - fout = strchr (fname, ':'); - if (fout != 0) - fout++; - else - fout = fname; - - /* strip .obj suffix */ - - fptr = strrchr (fname, '.'); - if ((fptr != 0) - && (strcasecmp (fptr, ".OBJ") == 0)) - *fptr = 0; - - fptr = fout; - while (*fptr != 0) - { - if (islower (*fptr)) - *fptr = toupper (*fptr); - fptr++; - if ((*fptr == ';') - || ((fptr - fout) > 31)) - *fptr = 0; - } - _bfd_evax_output_counted (abfd, fout); - } - else - _bfd_evax_output_counted (abfd, "NONAME"); - - _bfd_evax_output_counted (abfd, BFD_VERSION); - _bfd_evax_output_dump (abfd, get_vms_time_string (), 17); - _bfd_evax_output_fill (abfd, 0, 17); - _bfd_evax_output_flush (abfd); - - /* LMN */ - - _bfd_evax_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM); - _bfd_evax_output_dump (abfd, (unsigned char *)"GAS proGIS", 10); - _bfd_evax_output_flush (abfd); - - /* SRC */ - - _bfd_evax_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) - { - char *s; - - if (strncmp ((char *)symbol->name, "name[6] - '0'; - PRIV(flag_show_after_trunc) = symbol->name[7] - '0'; - - if (had_file) - break; - had_case = 1; - continue; - } - - _bfd_evax_output_dump (abfd, (unsigned char *)symbol->name, strlen (symbol->name)); - if (had_case) - break; - had_file = 1; - } - } - - if (symnum == abfd->symcount) - _bfd_evax_output_dump (abfd, (unsigned char *)"noname", 6); - - _bfd_evax_output_flush (abfd); - - /* TTL */ - - _bfd_evax_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL); - _bfd_evax_output_dump (abfd, (unsigned char *)"TTL", 3); - _bfd_evax_output_flush (abfd); - - /* CPR */ - - _bfd_evax_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR); - _bfd_evax_output_dump (abfd, - (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996", - 39); - _bfd_evax_output_flush (abfd); - - return 0; -} - -/*-----------------------------------------------------------------------------*/ - -/* Process EEOM record - return 0 on success, -1 on error */ - -int -_bfd_evax_slurp_eeom (abfd) - bfd *abfd; -{ - unsigned char *evax_rec; - -#if EVAX_DEBUG - evax_debug(2, "EEOM\n"); -#endif - - evax_rec = PRIV(evax_rec); - - PRIV(eeom_data).eeom_l_total_lps = bfd_getl32 (evax_rec + 4); - PRIV(eeom_data).eeom_b_comcod = *(evax_rec + 8); - if (PRIV(eeom_data).eeom_b_comcod > 1) - { - (*_bfd_error_handler) (_("Object module NOT error-free !\n")); - bfd_set_error (bfd_error_bad_value); - return -1; - } - PRIV(eeom_data).eeom_has_transfer = false; - if (PRIV(rec_size) > 10) - { - PRIV(eeom_data).eeom_has_transfer = true; - PRIV(eeom_data).eeom_b_tfrflg = *(evax_rec + 9); - PRIV(eeom_data).eeom_l_psindx = bfd_getl32 (evax_rec + 12); - PRIV(eeom_data).eeom_l_tfradr = bfd_getl32 (evax_rec + 16); - - abfd->start_address = PRIV(eeom_data).eeom_l_tfradr; - } - return 0; -} - - -/* Write eom record for bfd abfd */ - -int -_bfd_evax_write_eeom (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (2, "evax_write_eeom(%p)\n", abfd); -#endif - - _bfd_evax_output_begin (abfd,EOBJ_S_C_EEOM, -1); - _bfd_evax_output_long (abfd, (unsigned long)(PRIV(evax_linkage_index) >> 1)); - _bfd_evax_output_byte (abfd, 0); /* completion code */ - _bfd_evax_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_evax_output_short (abfd, 0); - _bfd_evax_output_long (abfd, (unsigned long)(section->index)); - _bfd_evax_output_long (abfd, - (unsigned long) bfd_get_start_address (abfd)); - _bfd_evax_output_long (abfd, 0); - } - - _bfd_evax_output_end (abfd); - return 0; -} diff --git a/bfd/evax-etir.c b/bfd/evax-etir.c deleted file mode 100644 index 3f7339b8fbd..00000000000 --- a/bfd/evax-etir.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* evax-etir.c -- BFD back-end for ALPHA EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998 Free Software Foundation, Inc. - ETIR record handling functions - - go and read the openVMS linker manual (esp. appendix B) - if you don't know what's going on here :-) - - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -/* The following type abbreviations are used: - - cs counted string (ascii string with length byte) - by byte (1 byte) - sh short (2 byte, 16 bit) - lw longword (4 byte, 32 bit) - qw quadword (8 byte, 64 bit) - da data stream */ - -#include - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" -#include "libbfd.h" - -#include "evax.h" - -#if 0 -static void location_save - PARAMS ((bfd *abfd, unsigned long index, unsigned long loc, int section)); -static unsigned long location_restore - PARAMS ((bfd *abfd, unsigned long index, int *section)); -#endif /* 0 */ - -static void image_set_ptr PARAMS ((bfd *abfd, int psect, uquad offset)); -static void image_inc_ptr PARAMS ((bfd *abfd, uquad offset)); -static void image_dump PARAMS ((bfd *abfd, unsigned char *ptr, int size, int offset)); -static void image_write_b PARAMS ((bfd *abfd, unsigned int value)); -static void image_write_w PARAMS ((bfd *abfd, unsigned int value)); -static void image_write_l PARAMS ((bfd *abfd, unsigned long value)); -static void image_write_q PARAMS ((bfd *abfd, uquad value)); - -/*-----------------------------------------------------------------------------*/ - -#if 0 - -/* Save location counter at index */ - -static void -location_save (abfd, index, loc, section) - bfd *abfd; - unsigned long index; - unsigned long loc; - int section; -{ - PRIV(location_stack)[index].value = loc; - PRIV(location_stack)[index].psect = section; - - return; -} - -/* Restore location counter from index */ - -static unsigned long -location_restore (abfd, index, section) - bfd *abfd; - unsigned long index; - int *section; -{ - if (section != NULL) - *section = PRIV(location_stack)[index].psect; - return PRIV(location_stack)[index].value; -} - -#endif /* 0 */ - -/* routines to fill sections contents during etir read */ - -/* Initialize image buffer pointer to be filled */ - -static void -image_set_ptr (abfd, psect, offset) - bfd *abfd; - int psect; - uquad offset; -{ -#if EVAX_DEBUG - evax_debug (4, "image_set_ptr(%d=%s, %d)\n", - psect, PRIV(sections)[psect]->name, offset); -#endif - - PRIV(image_ptr) = PRIV(sections)[psect]->contents + offset; - return; -} - - -/* Increment image buffer pointer by offset */ - -static void -image_inc_ptr (abfd, offset) - bfd *abfd; - uquad offset; -{ -#if EVAX_DEBUG - evax_debug (4, "image_inc_ptr(%d)\n", offset); -#endif - - PRIV(image_ptr) += offset; - - return; -} - - -/* Dump multiple bytes to section image */ - -static void -image_dump (abfd, ptr, size, offset) - bfd *abfd; - unsigned char *ptr; - int size; - int offset; -{ -#if EVAX_DEBUG - evax_debug (6, "image_dump from (%p, %d) to (%p)\n", ptr, size, PRIV(image_ptr)); - _bfd_hexdump (7, ptr, size, offset); -#endif - - while (size-- > 0) - *PRIV(image_ptr)++ = *ptr++; - return; -} - - -/* Write byte to section image */ - -static void -image_write_b (abfd, value) - bfd *abfd; - unsigned int value; -{ -#if EVAX_DEBUG - evax_debug (6, "image_write_b(%02x)\n", (int)value); -#endif - - *PRIV(image_ptr)++ = (value & 0xff); - return; -} - - -/* Write 2-byte word to image */ - -static void -image_write_w (abfd, value) - bfd *abfd; - unsigned int value; -{ -#if EVAX_DEBUG - evax_debug (6, "image_write_w(%04x)\n", (int)value); -#endif - - bfd_putl16 (value, PRIV(image_ptr)); - PRIV(image_ptr) += 2; - - return; -} - - -/* Write 4-byte long to image */ - -static void -image_write_l (abfd, value) - bfd *abfd; - unsigned long value; -{ -#if EVAX_DEBUG - evax_debug (6, "image_write_l(%08lx)\n", value); -#endif - - bfd_putl32 (value, PRIV(image_ptr)); - PRIV(image_ptr) += 4; - - return; -} - - -/* Write 4-byte long to image */ - -static void -image_write_q (abfd, value) - bfd *abfd; - uquad value; -{ -#if EVAX_DEBUG - evax_debug (6, "image_write_q(%016lx)\n", value); -#endif - - bfd_putl64 (value, PRIV(image_ptr)); - PRIV(image_ptr) += 8; - - return; -} - - -#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L) - -/* etir_sta - - evax stack commands - - handle sta_xxx commands in etir section - ptr points to data area in record - - see table B-8 of the openVMS linker manual */ - -static boolean -etir_sta (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - - switch (cmd) - { - /* stack */ - - /* stack global - arg: cs symbol name - - stack 32 bit value of symbol (high bits set to 0) */ - - case ETIR_S_C_STA_GBL: - { - char *name; - evax_symbol_entry *entry; - - name = _bfd_evax_save_counted_string ((char *)ptr); - entry = (evax_symbol_entry *) - bfd_hash_lookup (PRIV(evax_symbol_table), name, false, false); - if (entry == (evax_symbol_entry *)NULL) - { -#if EVAX_DEBUG - evax_debug (3, "ETIR_S_C_STA_GBL: no symbol \"%s\"\n", name); -#endif - return false; - } - else - { - _bfd_evax_push (abfd, (uquad)(entry->symbol->value), -1); - } - } - break; - - /* stack longword - arg: lw value - - stack 32 bit value, sign extend to 64 bit */ - - case ETIR_S_C_STA_LW: - _bfd_evax_push (abfd, (uquad)bfd_getl32 (ptr), -1); - break; - - /* stack global - arg: qw value - - stack 64 bit value of symbol */ - - case ETIR_S_C_STA_QW: - _bfd_evax_push (abfd, (uquad)bfd_getl64(ptr), -1); - break; - - /* stack psect base plus quadword offset - arg: lw section index - qw signed quadword offset (low 32 bits) - - stack qw argument and section index - (see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB) */ - - case ETIR_S_C_STA_PQ: - { - uquad dummy; - int psect; - - psect = bfd_getl32 (ptr); - if (psect >= PRIV(egsd_sec_count)) - { - (*_bfd_error_handler) (_("Bad section index in ETIR_S_C_STA_PQ")); - bfd_set_error (bfd_error_bad_value); - return false; - } - dummy = bfd_getl64 (ptr+4); - _bfd_evax_push (abfd, dummy, psect); - } - break; - - /* all not supported */ - - case ETIR_S_C_STA_LI: - case ETIR_S_C_STA_MOD: - case ETIR_S_C_STA_CKARG: - - (*_bfd_error_handler) (_("Unsupported STA cmd %d"), cmd); - return false; - break; - - default: - (*_bfd_error_handler) (_("Reserved STA cmd %d"), cmd); - return false; - break; - } - return true; -} - - -/* - etir_sto - - evax store commands - - handle sto_xxx commands in etir section - ptr points to data area in record - - see table B-9 of the openVMS linker manual */ - -static boolean -etir_sto (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - uquad dummy; - int psect; - - switch (cmd) - { - - /* store byte: pop stack, write byte - arg: - */ - - case ETIR_S_C_STO_B: - dummy = _bfd_evax_pop (abfd, &psect); -#if 0 - if (is_share) /* FIXME */ - (*_bfd_error_handler) ("ETIR_S_C_STO_B: byte fixups not supported"); -#endif - image_write_b (abfd, dummy & 0xff); /* FIXME: check top bits */ - break; - - /* store word: pop stack, write word - arg: - */ - - case ETIR_S_C_STO_W: - dummy = _bfd_evax_pop (abfd, &psect); -#if 0 - if (is_share) /* FIXME */ - (*_bfd_error_handler) ("ETIR_S_C_STO_B: word fixups not supported"); -#endif - image_write_w (abfd, dummy & 0xffff); /* FIXME: check top bits */ - break; - - /* store longword: pop stack, write longword - arg: - */ - - case ETIR_S_C_STO_LW: - dummy = _bfd_evax_pop (abfd, &psect); - dummy += (PRIV(sections)[psect])->vma; - image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */ -#if 0 /* FIXME */ - if (is_rel) - evax_debug (3, "ETIR_S_C_STO_LW: Relocation !\n"); - if (is_share) - evax_debug (3, "ETIR_S_C_STO_LW: Fix-up share !\n"); -#endif - break; - - /* store quadword: pop stack, write quadword - arg: - */ - - case ETIR_S_C_STO_QW: - dummy = _bfd_evax_pop (abfd, &psect); - dummy += (PRIV(sections)[psect])->vma; - image_write_q(abfd, dummy); /* FIXME: check top bits */ -#if 0 /* FIXME */ - if (is_rel) - evax_debug (3, "ETIR_S_C_STO_LW: Relocation !\n"); - if (is_share) - evax_debug (3, "ETIR_S_C_STO_LW: Fix-up share !\n"); -#endif - break; - - /* store immediate repeated: pop stack for repeat count - arg: lw byte count - da data */ - - case ETIR_S_C_STO_IMMR: - { - unsigned long size; - - size = bfd_getl32 (ptr); - dummy = (unsigned long)_bfd_evax_pop (abfd, NULL); - while (dummy-- > 0L) - image_dump (abfd, ptr+4, size, 0); - } - break; - - /* store global: write symbol value - arg: cs global symbol name */ - - case ETIR_S_C_STO_GBL: - { - evax_symbol_entry *entry; - char *name; - - name = _bfd_evax_save_counted_string ((char *)ptr); - entry = (evax_symbol_entry *)bfd_hash_lookup (PRIV(evax_symbol_table), name, false, false); - if (entry == (evax_symbol_entry *)NULL) - { - (*_bfd_error_handler) (_("ETIR_S_C_STO_GBL: no symbol \"%s\""), - name); - return false; - } - else - image_write_q (abfd, (uquad)(entry->symbol->value)); /* FIXME, reloc */ - } - break; - - /* store code address: write address of entry point - arg: cs global symbol name (procedure) */ - - case ETIR_S_C_STO_CA: - { - evax_symbol_entry *entry; - char *name; - - name = _bfd_evax_save_counted_string ((char *)ptr); - entry = (evax_symbol_entry *) bfd_hash_lookup (PRIV(evax_symbol_table), name, false, false); - if (entry == (evax_symbol_entry *)NULL) - { - (*_bfd_error_handler) (_("ETIR_S_C_STO_CA: no symbol \"%s\""), - name); - return false; - } - else - image_write_q (abfd, (uquad)(entry->symbol->value)); /* FIXME, reloc */ - } - break; - - /* not supported */ - - case ETIR_S_C_STO_RB: - case ETIR_S_C_STO_AB: - (*_bfd_error_handler) (_("ETIR_S_C_STO_RB/AB: Not supported")); - break; - - /* store offset to psect: pop stack, add low 32 bits to base of psect - arg: - */ - - case ETIR_S_C_STO_OFF: - { - uquad q; - int psect; - - q = _bfd_evax_pop (abfd, &psect); - q += (PRIV(sections)[psect])->vma; - image_write_q (abfd, q); - } - break; - - /* store immediate - arg: lw count of bytes - da data */ - - case ETIR_S_C_STO_IMM: - { - int size; - - size = bfd_getl32 (ptr); - image_dump (abfd, ptr+4, size, 0); - } - break; - - /* this code is 'reserved to digital' according to the openVMS linker manual, - however it is generated by the DEC C compiler and defined in the include file. - FIXME, since the following is just a guess - store global longword: store 32bit value of symbol - arg: cs symbol name */ - - case ETIR_S_C_STO_GBL_LW: - { - evax_symbol_entry *entry; - char *name; - - name = _bfd_evax_save_counted_string ((char *)ptr); - entry = (evax_symbol_entry *)bfd_hash_lookup (PRIV(evax_symbol_table), name, false, false); - if (entry == (evax_symbol_entry *)NULL) - { -#if EVAX_DEBUG - evax_debug (3, "ETIR_S_C_STO_GBL_LW: no symbol \"%s\"\n", name); -#endif - return false; - } - else - image_write_l (abfd, (unsigned long)(entry->symbol->value)); /* FIXME, reloc */ - } - break; - - /* not supported */ - - case ETIR_S_C_STO_LP_PSB: - (*_bfd_error_handler) (_("ETIR_S_C_STO_LP_PSB: Not supported")); - break; - - /* */ - - case ETIR_S_C_STO_HINT_GBL: - (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_GBL: not implemented")); - break; - - /* */ - - case ETIR_S_C_STO_HINT_PS: - (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_PS: not implemented")); - break; - - default: - (*_bfd_error_handler) (_("Reserved STO cmd %d"), cmd); - break; - } - - return true; -} - -/* stack operator commands - all 32 bit signed arithmetic - all word just like a stack calculator - arguments are popped from stack, results are pushed on stack - - see table B-10 of the openVMS linker manual */ - -static boolean -etir_opr (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - long op1, op2; - - switch (cmd) - { - /* operation */ - - /* no-op */ - - case ETIR_S_C_OPR_NOP: - break; - - /* add */ - - case ETIR_S_C_OPR_ADD: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 + op2), -1); - break; - - /* subtract */ - - case ETIR_S_C_OPR_SUB: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op2 - op1), -1); - break; - - /* multiply */ - - case ETIR_S_C_OPR_MUL: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 * op2), -1); - break; - - /* divide */ - - case ETIR_S_C_OPR_DIV: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - if (op2 == 0) - _bfd_evax_push (abfd, (uquad)0L, -1); - else - _bfd_evax_push (abfd, (uquad)(op2 / op1), -1); - break; - - /* logical and */ - - case ETIR_S_C_OPR_AND: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 & op2), -1); - break; - - /* logical inclusive or */ - - case ETIR_S_C_OPR_IOR: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 | op2), -1); - break; - - /* logical exclusive or */ - - case ETIR_S_C_OPR_EOR: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 ^ op2), -1); - break; - - /* negate */ - - case ETIR_S_C_OPR_NEG: - op1 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(-op1), -1); - break; - - /* complement */ - - case ETIR_S_C_OPR_COM: - op1 = (long)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)(op1 ^ -1L), -1); - break; - - /* insert field */ - - case ETIR_S_C_OPR_INSV: - (void)_bfd_evax_pop (abfd, NULL); - (*_bfd_error_handler) (_("ETIR_S_C_OPR_INSV: Not supported")); - break; - - /* arithmetic shift */ - - case ETIR_S_C_OPR_ASH: - op1 = (long)_bfd_evax_pop (abfd, NULL); - op2 = (long)_bfd_evax_pop (abfd, NULL); - if (op2 < 0) /* shift right */ - op1 >>= -op2; - else /* shift left */ - op1 <<= op2; - _bfd_evax_push (abfd, (uquad)op1, -1); - break; - - /* unsigned shift */ - - case ETIR_S_C_OPR_USH: - (*_bfd_error_handler) (_("ETIR_S_C_OPR_USH: Not supported")); - break; - - /* rotate */ - - case ETIR_S_C_OPR_ROT: - (*_bfd_error_handler) (_("ETIR_S_C_OPR_ROT: Not supported")); - break; - - /* select */ - - case ETIR_S_C_OPR_SEL: - if ((long)_bfd_evax_pop (abfd, NULL) & 0x01L) - (void)_bfd_evax_pop (abfd, NULL); - else - { - op1 = (long)_bfd_evax_pop (abfd, NULL); - (void)_bfd_evax_pop (abfd, NULL); - _bfd_evax_push (abfd, (uquad)op1, -1); - } - break; - - /* redefine symbol to current location */ - - case ETIR_S_C_OPR_REDEF: - (*_bfd_error_handler) (_("ETIR_S_C_OPR_REDEF: Not supported")); - break; - - /* define a literal */ - - case ETIR_S_C_OPR_DFLIT: - (*_bfd_error_handler) (_("ETIR_S_C_OPR_DFLIT: Not supported")); - break; - - default: - (*_bfd_error_handler) (_("Reserved OPR cmd %d"), cmd); - break; - } - - return true; -} - - -/* control commands - - see table B-11 of the openVMS linker manual */ - -static boolean -etir_ctl (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - uquad dummy; - int psect; - - switch (cmd) - { - /* set relocation base: pop stack, set image location counter - arg: - */ - - case ETIR_S_C_CTL_SETRB: - dummy = _bfd_evax_pop (abfd, &psect); - image_set_ptr (abfd, psect, dummy); - break; - - /* augment relocation base: increment image location counter by offset - arg: lw offset value */ - - case ETIR_S_C_CTL_AUGRB: - dummy = bfd_getl32 (ptr); - image_inc_ptr (abfd, dummy); - break; - - /* define location: pop index, save location counter under index - arg: - */ - - case ETIR_S_C_CTL_DFLOC: - dummy = _bfd_evax_pop (abfd, NULL); - /* FIXME */ - break; - - /* set location: pop index, restore location counter from index - arg: - */ - - case ETIR_S_C_CTL_STLOC: - dummy = _bfd_evax_pop (abfd, &psect); - /* FIXME */ - break; - - /* stack defined location: pop index, push location counter from index - arg: - */ - - case ETIR_S_C_CTL_STKDL: - dummy = _bfd_evax_pop (abfd, &psect); - /* FIXME */ - break; - - default: - (*_bfd_error_handler) (_("Reserved CTL cmd %d"), cmd); - break; - } - return true; -} - - -/* store conditional commands - - see table B-12 and B-13 of the openVMS linker manual */ - -static boolean -etir_stc (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - - switch (cmd) - { - /* 200 Store-conditional Linkage Pair - arg: */ - - case ETIR_S_C_STC_LP: - (*_bfd_error_handler) (_("ETIR_S_C_STC_LP: not supported")); - break; - - /* 201 Store-conditional Linkage Pair with Procedure Signature - arg: lw linkage index - cs procedure name - by signature length - da signature */ - - case ETIR_S_C_STC_LP_PSB: - image_inc_ptr (abfd, 16); /* skip entry,procval */ - break; - - /* 202 Store-conditional Address at global address - arg: lw linkage index - cs global name */ - - case ETIR_S_C_STC_GBL: - (*_bfd_error_handler) (_("ETIR_S_C_STC_GBL: not supported")); - break; - - /* 203 Store-conditional Code Address at global address - arg: lw linkage index - cs procedure name */ - - case ETIR_S_C_STC_GCA: - (*_bfd_error_handler) (_("ETIR_S_C_STC_GCA: not supported")); - break; - - /* 204 Store-conditional Address at psect + offset - arg: lw linkage index - lw psect index - qw offset */ - - case ETIR_S_C_STC_PS: - (*_bfd_error_handler) (_("ETIR_S_C_STC_PS: not supported")); - break; - - /* 205 Store-conditional NOP at address of global - arg: */ - - case ETIR_S_C_STC_NOP_GBL: - - /* 206 Store-conditional NOP at pect + offset - arg: */ - - case ETIR_S_C_STC_NOP_PS: - - /* 207 Store-conditional BSR at global address - arg: */ - - case ETIR_S_C_STC_BSR_GBL: - - /* 208 Store-conditional BSR at pect + offset - arg: */ - - case ETIR_S_C_STC_BSR_PS: - - /* 209 Store-conditional LDA at global address - arg: */ - - case ETIR_S_C_STC_LDA_GBL: - - /* 210 Store-conditional LDA at psect + offset - arg: */ - - case ETIR_S_C_STC_LDA_PS: - - /* 211 Store-conditional BSR or Hint at global address - arg: */ - - case ETIR_S_C_STC_BOH_GBL: - - /* 212 Store-conditional BSR or Hint at pect + offset - arg: */ - - case ETIR_S_C_STC_BOH_PS: - - /* 213 Store-conditional NOP,BSR or HINT at global address - arg: */ - - case ETIR_S_C_STC_NBH_GBL: - - /* 214 Store-conditional NOP,BSR or HINT at psect + offset - arg: */ - - case ETIR_S_C_STC_NBH_PS: -/* FIXME (*_bfd_error_handler) ("ETIR_S_C_STC_xx: (%d) not supported", cmd); */ - break; - - default: -#if EVAX_DEBUG - evax_debug (3, "Reserved STC cmd %d", cmd); -#endif - break; - } - return true; -} - - -/* handle command from ETIR section */ - -static boolean -tir_cmd (abfd, cmd, ptr) - bfd *abfd; - int cmd; - unsigned char *ptr; -{ - static struct { - int mincod; - int maxcod; - boolean (*explain) PARAMS((bfd *, int, unsigned char *)); - } tir_table[] = { - { ETIR_S_C_MINSTACOD, ETIR_S_C_MAXSTACOD, etir_sta }, - { ETIR_S_C_MINSTOCOD, ETIR_S_C_MAXSTOCOD, etir_sto }, - { ETIR_S_C_MINOPRCOD, ETIR_S_C_MAXOPRCOD, etir_opr }, - { ETIR_S_C_MINCTLCOD, ETIR_S_C_MAXCTLCOD, etir_ctl }, - { ETIR_S_C_MINSTCCOD, ETIR_S_C_MAXSTCCOD, etir_stc }, - { -1, -1, NULL } - }; - - int i = 0; - boolean res = true; - - while (tir_table[i].mincod >= 0) - { - if ( (tir_table[i].mincod <= cmd) - && (cmd <= tir_table[i].maxcod)) - { - res = tir_table[i].explain (abfd, cmd, ptr); - break; - } - i++; - } - - return res; -} - - -/* Text Information and Relocation Records (OBJ$C_TIR) - handle etir record */ - -static boolean -analyze_etir (abfd, ptr, length) - bfd *abfd; - unsigned char *ptr; - unsigned int length; -{ - int cmd; - unsigned char *maxptr; - boolean res = true; - - maxptr = ptr + length; - - while (ptr < maxptr) - { - cmd = bfd_getl16 (ptr); - length = bfd_getl16 (ptr + 2); - res = tir_cmd (abfd, cmd, ptr+4); - if (!res) - break; - ptr += length; - } - return res; -} - - -/* process ETIR record - - return 0 on success, -1 on error */ - -int -_bfd_evax_slurp_etir (abfd) - bfd *abfd; -{ - -#if EVAX_DEBUG - evax_debug (2, "ETIR\n"); -#endif - - PRIV(evax_rec) += 4; /* skip type, size */ - PRIV(rec_size) -= 4; - if (analyze_etir (abfd, PRIV(evax_rec), PRIV(rec_size))) - return 0; - - return -1; -} - - -/* process EDBG record - return 0 on success, -1 on error - - not implemented yet */ - -int -_bfd_evax_slurp_edbg (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (2, "EDBG\n"); -#endif - - abfd->flags |= (HAS_DEBUG | HAS_LINENO); - return 0; -} - - -/* process ETBT record - return 0 on success, -1 on error - - not implemented yet */ - -int -_bfd_evax_slurp_etbt (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (2, "ETBT\n"); -#endif - - return 0; -} - -/*----------------------------------------------------------------------*/ -/* */ -/* WRITE ETIR SECTION */ -/* */ -/* this is still under construction and therefore not documented */ -/* */ -/*----------------------------------------------------------------------*/ - -static void start_etir_record PARAMS ((bfd *abfd, int index, uquad offset, boolean justoffset)); -static void sto_imm PARAMS ((bfd *abfd, evax_section *sptr, bfd_vma vaddr, int index)); -static void end_etir_record PARAMS ((bfd *abfd)); - -static void -sto_imm (abfd, sptr, vaddr, index) - bfd *abfd; - evax_section *sptr; - bfd_vma vaddr; - int index; -{ - int size; - int ssize; - unsigned char *cptr; - -#if EVAX_DEBUG - evax_debug (8, "sto_imm %d bytes\n", sptr->size); - _bfd_hexdump (9, sptr->contents, (int)sptr->size, (int)vaddr); -#endif - - ssize = sptr->size; - cptr = sptr->contents; - - while (ssize > 0) - { - - size = ssize; /* try all the rest */ - - if (_bfd_evax_output_check (abfd, size) < 0) - { /* doesn't fit, split ! */ - end_etir_record (abfd); - start_etir_record (abfd, index, vaddr, false); - size = _bfd_evax_output_check (abfd, 0); /* get max size */ - if (size > ssize) /* more than what's left ? */ - size = ssize; - } - - _bfd_evax_output_begin (abfd, ETIR_S_C_STO_IMM, -1); - _bfd_evax_output_long (abfd, (unsigned long)(size)); - _bfd_evax_output_dump (abfd, cptr, size); - _bfd_evax_output_flush (abfd); - -#if EVAX_DEBUG - evax_debug (10, "dumped %d bytes\n", size); - _bfd_hexdump (10, cptr, (int)size, (int)vaddr); -#endif - - vaddr += size; - ssize -= size; - cptr += size; - } - - return; -} - -/*-------------------------------------------------------------------*/ - -/* start ETIR record for section #index at virtual addr offset. */ - -static void -start_etir_record (abfd, index, offset, justoffset) - bfd *abfd; - int index; - uquad offset; - boolean justoffset; -{ - if (!justoffset) - { - _bfd_evax_output_begin (abfd, EOBJ_S_C_ETIR, -1); /* one ETIR per section */ - _bfd_evax_output_push (abfd); - } - - _bfd_evax_output_begin (abfd, ETIR_S_C_STA_PQ, -1); /* push start offset */ - _bfd_evax_output_long (abfd, (unsigned long)index); - _bfd_evax_output_quad (abfd, (uquad)offset); - _bfd_evax_output_flush (abfd); - - _bfd_evax_output_begin (abfd, ETIR_S_C_CTL_SETRB, -1); /* start = pop() */ - _bfd_evax_output_flush (abfd); - - return; -} - - -/* end etir record */ -static void -end_etir_record (abfd) - bfd *abfd; -{ - _bfd_evax_output_pop (abfd); - _bfd_evax_output_end (abfd); -} - -/* write section contents for bfd abfd */ - -int -_bfd_evax_write_etir (abfd) - bfd *abfd; -{ - asection *section; - evax_section *sptr; - int nextoffset; - -#if EVAX_DEBUG - evax_debug (2, "evax_write_etir(%p)\n", abfd); -#endif - - _bfd_evax_output_alignment (abfd, 4); - - nextoffset = 0; - PRIV(evax_linkage_index) = 1; - - /* dump all other sections */ - - section = abfd->sections; - - while (section != NULL) - { - -#if EVAX_DEBUG - evax_debug (4, "writing %d. section '%s' (%d bytes)\n", section->index, section->name, (int)(section->_raw_size)); -#endif - - if (section->flags & SEC_RELOC) - { - int i; - - if ((i = section->reloc_count) <= 0) - { - (*_bfd_error_handler) (_("SEC_RELOC with no relocs in section %s"), - section->name); - } -#if EVAX_DEBUG - else - { - arelent **rptr; - evax_debug (4, "%d relocations:\n", i); - rptr = section->orelocation; - while (i-- > 0) - { - evax_debug (4, "sym %s in sec %s, value %08lx, addr %08lx, off %08lx, len %d: %s\n", - (*(*rptr)->sym_ptr_ptr)->name, - (*(*rptr)->sym_ptr_ptr)->section->name, - (long)(*(*rptr)->sym_ptr_ptr)->value, - (*rptr)->address, (*rptr)->addend, - bfd_get_reloc_size((*rptr)->howto), - (*rptr)->howto->name); - rptr++; - } - } -#endif - } - - if ((section->flags & SEC_HAS_CONTENTS) - && (! bfd_is_com_section (section))) - { - bfd_vma vaddr; /* virtual addr in section */ - - sptr = _bfd_get_evax_section (abfd, section->index); - if (sptr == NULL) - { - bfd_set_error (bfd_error_no_contents); - return -1; - } - - vaddr = (bfd_vma)(sptr->offset); - - start_etir_record (abfd, section->index, (uquad) sptr->offset, - false); - - while (sptr != NULL) /* one STA_PQ, CTL_SETRB per evax_section */ - { - - if (section->flags & SEC_RELOC) /* check for relocs */ - { - arelent **rptr = section->orelocation; - int i = section->reloc_count; - for (;;) - { - bfd_size_type addr = (*rptr)->address; - int len = bfd_get_reloc_size ((*rptr)->howto); - if (sptr->offset < addr) /* sptr starts before reloc */ - { - int before = addr - sptr->offset; - if (sptr->size <= before) /* complete before */ - { - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - break; - } - else /* partly before */ - { - int after = sptr->size - before; - sptr->size = before; - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - sptr->contents += before; - sptr->offset += before; - sptr->size = after; - } - } - else if (sptr->offset == addr) /* sptr starts at reloc */ - { - asymbol *sym = *(*rptr)->sym_ptr_ptr; - asection *sec = sym->section; - - switch ((*rptr)->howto->type) - { - case ALPHA_R_IGNORE: - break; - - case ALPHA_R_REFLONG: - { - if (bfd_is_und_section (sym->section)) - { - if (_bfd_evax_output_check (abfd, - strlen((char *)sym->name)) - < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_GBL_LW, - -1); - _bfd_evax_output_counted (abfd, - _bfd_evax_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_evax_output_flush (abfd); - } - else if (bfd_is_abs_section (sym->section)) - { - if (_bfd_evax_output_check (abfd, 16) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STA_LW, - -1); - _bfd_evax_output_quad (abfd, - (uquad)sym->value); - _bfd_evax_output_flush (abfd); - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_LW, - -1); - _bfd_evax_output_flush (abfd); - } - else - { - if (_bfd_evax_output_check (abfd, 32) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STA_PQ, - -1); - _bfd_evax_output_long (abfd, - (unsigned long)(sec->index)); - _bfd_evax_output_quad (abfd, - ((uquad)(*rptr)->addend - + (uquad)sym->value)); - _bfd_evax_output_flush (abfd); - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_LW, - -1); - _bfd_evax_output_flush (abfd); - } - } - break; - - case ALPHA_R_REFQUAD: - { - if (bfd_is_und_section (sym->section)) - { - if (_bfd_evax_output_check (abfd, - strlen((char *)sym->name)) - < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_GBL, - -1); - _bfd_evax_output_counted (abfd, - _bfd_evax_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_evax_output_flush (abfd); - } - else if (bfd_is_abs_section (sym->section)) - { - if (_bfd_evax_output_check (abfd, 16) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STA_QW, - -1); - _bfd_evax_output_quad (abfd, - (uquad)sym->value); - _bfd_evax_output_flush (abfd); - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_QW, - -1); - _bfd_evax_output_flush (abfd); - } - else - { - if (_bfd_evax_output_check (abfd, 32) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STA_PQ, - -1); - _bfd_evax_output_long (abfd, - (unsigned long)(sec->index)); - _bfd_evax_output_quad (abfd, - ((uquad)(*rptr)->addend - + (uquad)sym->value)); - _bfd_evax_output_flush (abfd); - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_OFF, - -1); - _bfd_evax_output_flush (abfd); - } - } - break; - - case ALPHA_R_HINT: - { - int hint_size; - - hint_size = sptr->size; - sptr->size = len; - sto_imm (abfd, sptr, vaddr, section->index); - sptr->size = hint_size; -#if 0 - evax_output_begin(abfd, ETIR_S_C_STO_HINT_GBL, -1); - evax_output_long(abfd, (unsigned long)(sec->index)); - evax_output_quad(abfd, (uquad)addr); - - evax_output_counted(abfd, _bfd_evax_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - evax_output_flush(abfd); -#endif - } - break; - case ALPHA_R_LINKAGE: - { - if (_bfd_evax_output_check (abfd, 64) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STC_LP_PSB, - -1); - _bfd_evax_output_long (abfd, - (unsigned long)PRIV(evax_linkage_index)); - PRIV(evax_linkage_index) += 2; - _bfd_evax_output_counted (abfd, - _bfd_evax_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_evax_output_byte (abfd, 0); - _bfd_evax_output_flush (abfd); - } - break; - - case ALPHA_R_CODEADDR: - { - if (_bfd_evax_output_check (abfd, - strlen((char *)sym->name)) - < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, false); - } - _bfd_evax_output_begin (abfd, - ETIR_S_C_STO_CA, - -1); - _bfd_evax_output_counted (abfd, - _bfd_evax_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_evax_output_flush (abfd); - } - break; - - default: - (*_bfd_error_handler) (_("Unhandled relocation %s"), - (*rptr)->howto->name); - break; - } - - vaddr += len; - - if (len == sptr->size) - { - break; - } - else - { - sptr->contents += len; - sptr->offset += len; - sptr->size -= len; - i--; - rptr++; - } - } - else /* sptr starts after reloc */ - { - i--; /* check next reloc */ - rptr++; - } - - if (i==0) /* all reloc checked */ - { - if (sptr->size > 0) - { - sto_imm (abfd, sptr, vaddr, section->index); /* dump rest */ - vaddr += sptr->size; - } - break; - } - } /* for (;;) */ - } /* if SEC_RELOC */ - else /* no relocs, just dump */ - { - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - } - - sptr = sptr->next; - - } /* while (sptr != 0) */ - - end_etir_record (abfd); - - } /* has_contents */ - - section = section->next; - } - - _bfd_evax_output_alignment(abfd, 2); - return 0; -} - - -/* write traceback data for bfd abfd */ - -int -_bfd_evax_write_etbt (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (2, "evax_write_etbt(%p)\n", abfd); -#endif - - return 0; -} - - -/* write debug info for bfd abfd */ - -int -_bfd_evax_write_edbg (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (2, "evax_write_edbg(%p)\n", abfd); -#endif - - return 0; -} diff --git a/bfd/evax-misc.c b/bfd/evax-misc.c deleted file mode 100644 index 4dc74ed8825..00000000000 --- a/bfd/evax-misc.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* evax-misc.c -- Miscellaneous functions for ALPHA EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998 Free Software Foundation, Inc. - - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#if __STDC__ -#include -#endif - -#include "bfd.h" -#include "sysdep.h" -#include "bfdlink.h" -#include "libbfd.h" - -#include "evax.h" - -/*-----------------------------------------------------------------------------*/ -#if EVAX_DEBUG -/* debug functions */ - -/* debug function for all evax extensions - evaluates environment variable EVAX_DEBUG for a - numerical value on the first call - all error levels below this value are printed - - levels: - 1 toplevel bfd calls (functions from the bfd vector) - 2 functions called by bfd calls - ... - 9 almost everything - - level is also identation level. Indentation is performed - if level > 0 - */ - -#if __STDC__ -void -_bfd_evax_debug (int level, char *format, ...) -{ - static int min_level = -1; - static FILE *output = NULL; - char *eptr; - va_list args; - int abslvl = (level > 0)?level:-level; - - if (min_level == -1) - { - if ((eptr = getenv("EVAX_DEBUG")) != NULL) - { - min_level = atoi(eptr); - output = stderr; - } - else - min_level = 0; - } - if (output == NULL) - return; - if (abslvl > min_level) - return; - - while(--level>0) - fprintf(output, " "); - va_start(args, format); - vfprintf(output, format, args); - fflush(output); - va_end(args); - - return; -} - -#else /* not __STDC__ */ - -void -_bfd_evax_debug (level, format, a1, a2, a3, a4, a5, a6) - int level; - char *format; - long a1; long a2; long a3; - long a4; long a5; long a6; -{ - static int min_level = -1; - static FILE *output = NULL; - char *eptr; - - if (min_level == -1) - { - if ((eptr = getenv("EVAX_DEBUG")) != NULL) - { - min_level = atoi(eptr); - output = stderr; - } - else - min_level = 0; - } - if (output == NULL) - return; - if (level > min_level) - return; - - while(--level>0) - fprintf(output, " "); - fprintf(output, format, a1, a2, a3, a4, a5, a6); - fflush(output); - - return; -} -#endif /* __STDC__ */ - - -/* a debug function - hex dump 'size' bytes starting at 'ptr' */ - -void -_bfd_hexdump (level, ptr, size, offset) - int level; - unsigned char *ptr; - int size; - int offset; -{ - unsigned char *lptr = ptr; - int count = 0; - long start = offset; - - while (size-- > 0) - { - if ((count%16) == 0) - evax_debug (level, "%08lx:", start); - evax_debug (-level, " %02x", *ptr++); - count++; - start++; - if (size == 0) - { - while ((count%16) != 0) - { - evax_debug (-level, " "); - count++; - } - } - if ((count%16) == 0) - { - evax_debug (-level, " "); - while (lptr < ptr) - { - evax_debug (-level, "%c", (*lptr < 32)?'.':*lptr); - lptr++; - } - evax_debug (-level, "\n"); - } - } - if ((count%16) != 0) - evax_debug (-level, "\n"); - - return; -} -#endif - - -/* hash functions - - These are needed when reading an object file. */ - -/* allocate new evax_hash_entry - keep the symbol name and a pointer to the bfd symbol in the table */ - -struct bfd_hash_entry * -_bfd_evax_hash_newfunc (entry, table, string) - struct bfd_hash_entry *entry; - struct bfd_hash_table *table; - const char *string; -{ - evax_symbol_entry *ret = (evax_symbol_entry *)entry; - -#if EVAX_DEBUG - evax_debug (5, "_bfd_evax_hash_newfunc(%p, %p, %s)\n", entry, table, string); -#endif - - if (ret == (evax_symbol_entry *)NULL) - ret = ((evax_symbol_entry *) bfd_hash_allocate (table, sizeof (evax_symbol_entry))); - if (ret == (evax_symbol_entry *)NULL) - { - bfd_set_error (bfd_error_no_memory); - return (struct bfd_hash_entry *)NULL; - } - ret = (evax_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string); - - ret->symbol = (asymbol *)NULL; - - return (struct bfd_hash_entry *)ret; -} - - -/* object file input functions */ - -/* Return type and length from record header (buf) */ - -void -_bfd_evax_get_header_values (abfd, buf, type, length) - bfd *abfd; - unsigned char *buf; - int *type; - int *length; -{ - if (type != 0) - *type = bfd_getl16 (buf); - buf += 2; - if (length != 0) - *length = bfd_getl16 (buf); - - return; -} - - -/* Get next record from object file to evax_buf - set PRIV(buf_size) and return it - - this is a little tricky since it should be portable. - - the openVMS/AXP object file has 'variable length' which means that - read() returns data in chunks of (hopefully) correct and expected - size. The linker (and other tools on vms) depend on that. Unix doesn't - know about 'formatted' files, so reading and writing such an object - file in a unix environment is not trivial. - - With the tool 'file' (available on all vms ftp sites), one - can view and change the attributes of a file. Changing from - 'variable length' to 'fixed length, 512 bytes' reveals the - record length at the first 2 bytes of every record. The same - happens during the transfer of object files from vms to unix, - at least with ucx, dec's implementation of tcp/ip. - - The EVAX format repeats the length at bytes 2 & 3 of every record. - - On the first call (file_format == FF_UNKNOWN) we check if - the first and the third byte pair (!) of the record match. - If they do it's an object file in an unix environment or with - wrong attributes (FF_FOREIGN), else we should be in a vms - environment where read() returns the record size (FF_NATIVE). - - reading is always done in 2 steps. - first just the record header is read and the length extracted - by get_header_values - then the read buffer is adjusted and the remaining bytes are - read in. - - all file i/o is always done on even file positions */ - -int -_bfd_evax_get_record (abfd) - bfd *abfd; -{ - int test_len, test_start, remaining; - unsigned char *evax_buf; - -#if EVAX_DEBUG - evax_debug (8, "_bfd_evax_get_record\n"); -#endif - - /* minimum is 6 bytes - (2 bytes length, 2 bytes record id, 2 bytes length repeated) */ - - if (PRIV(buf_size) == 0) - { - PRIV(evax_buf) = (unsigned char *) malloc (6); -#if EVAX_DEBUG - evax_debug (9, "PRIV(evax_buf) %p\n", PRIV(evax_buf)); -#endif - } - - evax_buf = PRIV(evax_buf); - - if (evax_buf == 0) - { -#if EVAX_DEBUG - evax_debug (9, "can't alloc evax_buf\n"); -#endif - bfd_set_error (bfd_error_no_memory); - return -1; - } - - switch (PRIV(file_format)) - { - case FF_UNKNOWN: - case FF_FOREIGN: - test_len = 6; /* probe 6 bytes */ - test_start = 2; /* where the record starts */ - break; - - case FF_NATIVE: - test_len = 4; - test_start = 0; - break; - } - - /* skip odd alignment byte */ -#if 0 - if (PRIV(file_format) == FF_FOREIGN) - { -#endif - if (bfd_tell (abfd) & 1) - { -#if EVAX_DEBUG - evax_debug (10, "skip odd\n"); -#endif - if (bfd_read (PRIV(evax_buf), 1, 1, abfd) != 1) - { -#if EVAX_DEBUG - evax_debug (9, "skip odd failed\n"); -#endif - bfd_set_error (bfd_error_file_truncated); - return 0; - } - } -#if 0 - } -#endif - /* read the record header */ - - if (bfd_read (PRIV(evax_buf), 1, test_len, abfd) != test_len) - { -#if EVAX_DEBUG - evax_debug (9, "can't bfd_read test %d bytes\n", test_len); -#endif - bfd_set_error (bfd_error_file_truncated); - return 0; - } - - /* check file format on first call */ - - if (PRIV(file_format) == FF_UNKNOWN) - { /* record length repeats ? */ - if ( (evax_buf[0] == evax_buf[4]) - && (evax_buf[1] == evax_buf[5])) - { - PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */ - test_start = 2; - } - else - { - PRIV(file_format) = FF_NATIVE; /* N: native environment */ - test_start = 0; - } -#if EVAX_DEBUG - evax_debug (10, "File format is %s\n", (PRIV(file_format) == FF_FOREIGN)?"foreign":"native"); -#endif - } - - /* extract evax record length */ - - _bfd_evax_get_header_values (abfd, evax_buf+test_start, NULL, - &PRIV(rec_length)); - - if (PRIV(rec_length) <= 0) - { - bfd_set_error (bfd_error_file_truncated); - return 0; - } - - /* that's what the linker manual says */ - - if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ) - { - bfd_set_error (bfd_error_file_truncated); - return 0; - } - - /* adjust the buffer */ - - if (PRIV(rec_length) > PRIV(buf_size)) - { - PRIV(evax_buf) = (unsigned char *) realloc (evax_buf, PRIV(rec_length)); -#if EVAX_DEBUG - evax_debug (3, "adjusted the buffer (%p) from %d to %d\n", PRIV(evax_buf), PRIV(buf_size), PRIV(rec_length)); -#endif - evax_buf = PRIV(evax_buf); - if (evax_buf == 0) - { -#if EVAX_DEBUG - evax_debug (9, "can't realloc evax_buf to %d bytes\n", PRIV(rec_length)); -#endif - bfd_set_error (bfd_error_no_memory); - return -1; - } - PRIV(buf_size) = PRIV(rec_length); - } - - /* read the remaining record */ - - remaining = PRIV(rec_length) - test_len + test_start; - - if (bfd_read (evax_buf + test_len, 1, remaining, abfd) != remaining) - { -#if EVAX_DEBUG - evax_debug (9, "can't bfd_read remaining %d bytes\n", remaining); -#endif - bfd_set_error (bfd_error_file_truncated); - return 0; - } - - PRIV(evax_rec) = evax_buf + test_start; - - return PRIV(rec_length); -} - - -/* get next EVAX record from file - update evax_rec and rec_length to new (remaining) values */ - -int -_bfd_evax_next_record (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (8, "_bfd_evax_next_record (len %d, size %d)\n", - PRIV(rec_length), PRIV(rec_size)); -#endif - - if (PRIV(rec_length) > 0) - { - PRIV(evax_rec) += PRIV(rec_size); - } - else - { - if (_bfd_evax_get_record (abfd) <= 0) - return -1; - } - _bfd_evax_get_header_values (abfd, PRIV(evax_rec), &PRIV(rec_type), - &PRIV(rec_size)); - PRIV(rec_length) -= PRIV(rec_size); - -#if EVAX_DEBUG - evax_debug (8, "_bfd_evax_next_record: rec %p, size %d, length %d, type %d\n", - PRIV(evax_rec), PRIV(rec_size), PRIV(rec_length), - PRIV(rec_type)); -#endif - - return PRIV(rec_type); -} - - - -/* Copy sized string (string with fixed length) to new allocated area - size is string length (size of record) */ - -char * -_bfd_evax_save_sized_string (str, size) - char *str; - int size; -{ - char *newstr = bfd_malloc (size + 1); - - if (newstr == NULL) - return 0; - strncpy (newstr, str, size); - newstr[size] = 0; - - return newstr; -} - -/* Copy counted string (string with length at first byte) to new allocated area - ptr points to length byte on entry */ - -char * -_bfd_evax_save_counted_string (ptr) - char *ptr; -{ - int len = *ptr++; - - return _bfd_evax_save_sized_string (ptr, len); -} - - -/* stack routines for EVAX ETIR commands */ - -/* Push value and section index */ - -void -_bfd_evax_push (abfd, val, psect) - bfd *abfd; - uquad val; - int psect; -{ - static int last_psect; - -#if EVAX_DEBUG - evax_debug (4, "\n", val, psect, PRIV(stackptr)); -#endif - - if (psect >= 0) - last_psect = psect; - - PRIV(stack[PRIV(stackptr)]).value = val; - PRIV(stack[PRIV(stackptr)]).psect = last_psect; - PRIV(stackptr)++; - if (PRIV(stackptr) >= STACKSIZE) - { - bfd_set_error (bfd_error_bad_value); - exit(1); - } - return; -} - - -/* Pop value and section index */ - -uquad -_bfd_evax_pop (abfd, psect) - bfd *abfd; - int *psect; -{ - uquad value; - - if (PRIV(stackptr) == 0) - { - bfd_set_error (bfd_error_bad_value); - exit(1); - } - PRIV(stackptr)--; - value = PRIV(stack[PRIV(stackptr)]).value; - if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0)) - *psect = PRIV(stack[PRIV(stackptr)]).psect; - -#if EVAX_DEBUG - evax_debug (4, "\n", value, PRIV(stack[PRIV(stackptr)]).psect); -#endif - - return value; -} - - -/* object file output functions */ - -/* GAS tends to write sections in little chunks (bfd_set_section_contents) - which we can't use directly. So we save the little chunks in linked - lists (one per section) and write them later. */ - -/* Add a new evax_section structure to evax_section_table - - forward chaining - */ - -static evax_section * -add_new_contents (abfd, section) - bfd *abfd; - sec_ptr section; -{ - evax_section *sptr, *newptr; - - sptr = PRIV(evax_section_table)[section->index]; - if (sptr != NULL) - return sptr; - - newptr = (evax_section *) bfd_malloc (sizeof (evax_section)); - if (newptr == (evax_section *) NULL) - return NULL; - newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size); - if (newptr->contents == (unsigned char *)NULL) - return NULL; - newptr->offset = 0; - newptr->size = section->_raw_size; - newptr->next = 0; - PRIV(evax_section_table)[section->index] = newptr; - return newptr; -} - - -/* Save section data & offset to an evax_section structure - evax_section_table[] holds the evax_section chain */ - -boolean -_bfd_save_evax_section (abfd, section, data, offset, count) - bfd *abfd; - sec_ptr section; - PTR data; - file_ptr offset; - bfd_size_type count; -{ - evax_section *sptr; - - if (section->index >= EVAX_SECTION_COUNT) - { - bfd_set_error (bfd_error_nonrepresentable_section); - return false; - } - if (count == (bfd_size_type)0) - return true; - sptr = add_new_contents (abfd, section); - if (sptr == NULL) - return false; - memcpy (sptr->contents + offset, data, (size_t) count); - - return true; -} - - -/* Get evax_section pointer to saved contents for section # index */ - -evax_section * -_bfd_get_evax_section (abfd, index) - bfd *abfd; - int index; -{ - if (index >= EVAX_SECTION_COUNT) - { - bfd_set_error (bfd_error_nonrepresentable_section); - return NULL; - } - return PRIV(evax_section_table)[index]; -} - - -/* Object output routines */ - -/* Begin new record or record header - write 2 bytes rectype - write 2 bytes record length (filled in at flush) - write 2 bytes header type (ommitted if rechead == -1) */ - -void -_bfd_evax_output_begin (abfd, rectype, rechead) - bfd *abfd; - int rectype; - int rechead; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_begin(type %d, head %d)\n", rectype, - rechead); -#endif - - _bfd_evax_output_short (abfd,rectype); - - /* save current output position to fill in lenght later */ - - if (PRIV(push_level) > 0) - PRIV(length_pos) = PRIV(output_size); - -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_begin: length_pos = %d\n", - PRIV(length_pos)); -#endif - - _bfd_evax_output_short (abfd,0); /* placeholder for length */ - - if (rechead != -1) - _bfd_evax_output_short (abfd,rechead); - - return; -} - - -/* Set record/subrecord alignment */ - -void -_bfd_evax_output_alignment (abfd, alignto) - bfd *abfd; - int alignto; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_alignment(%d)\n", alignto); -#endif - - PRIV(output_alignment) = alignto; - return; -} - - -/* Prepare for subrecord fields */ - -void -_bfd_evax_output_push (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (6, "evax_output_push(pushed_size = %d)\n", PRIV(output_size)); -#endif - - PRIV(push_level)++; - PRIV(pushed_size) = PRIV(output_size); - return; -} - - -/* End of subrecord fields */ - -void -_bfd_evax_output_pop (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (6, "evax_output_pop(pushed_size = %d)\n", PRIV(pushed_size)); -#endif - - _bfd_evax_output_flush (abfd); - PRIV(length_pos) = 2; - -#if EVAX_DEBUG - evax_debug (6, "evax_output_pop: length_pos = %d\n", PRIV(length_pos)); -#endif - - PRIV(pushed_size) = 0; - PRIV(push_level)--; - return; -} - - -/* Flush unwritten output, ends current record */ - -void -_bfd_evax_output_flush (abfd) - bfd *abfd; -{ - int real_size = PRIV(output_size); - int aligncount; - int length; - -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n", - real_size, PRIV(pushed_size), PRIV(length_pos)); -#endif - - if (PRIV(push_level) > 0) - length = real_size - PRIV(pushed_size); - else - length = real_size; - - if (length == 0) - return; - aligncount = (PRIV(output_alignment) - - (length % PRIV(output_alignment))) % PRIV(output_alignment); - -#if EVAX_DEBUG - evax_debug (6, "align: adding %d bytes\n", aligncount); -#endif - - while(aligncount-- > 0) - { - PRIV(output_buf)[real_size++] = 0; -#if 0 - /* this is why I *love* vms: inconsistency :-} - alignment is added to the subrecord length - but not to the record length */ - if (PRIV(push_level) > 0) -#endif - length++; - } - - /* put length to buffer */ - PRIV(output_size) = PRIV(length_pos); - _bfd_evax_output_short (abfd, (unsigned int)length); - - if (PRIV(push_level) == 0) - { -#ifndef VMS - /* write length first, see FF_FOREIGN in the input routines */ - fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream); -#endif - fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream); - - PRIV(output_size) = 0; - } - else - { - PRIV(output_size) = real_size; - PRIV(pushed_size) = PRIV(output_size); - } - - return; -} - - -/* End record output */ - -void -_bfd_evax_output_end (abfd) - bfd *abfd; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_end\n"); -#endif - - _bfd_evax_output_flush (abfd); - - return; -} - - -/* check remaining buffer size - - return what's left. */ - -int -_bfd_evax_output_check (abfd, size) - bfd *abfd; - int size; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_check(%d)\n", size); -#endif - - return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT)); -} - - -/* Output byte (8 bit) value */ - -void -_bfd_evax_output_byte (abfd, value) - bfd *abfd; - unsigned int value; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_byte(%02x)\n", value); -#endif - - bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size)); - PRIV(output_size) += 1; - return; -} - - -/* Output short (16 bit) value */ - -void -_bfd_evax_output_short (abfd, value) - bfd *abfd; - unsigned int value; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_short (%04x)\n", value); -#endif - - bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size)); - PRIV(output_size) += 2; - return; -} - - -/* Output long (32 bit) value */ - -void -_bfd_evax_output_long (abfd, value) - bfd *abfd; - unsigned long value; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_long (%08lx)\n", value); -#endif - - bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size)); - PRIV(output_size) += 4; - return; -} - - -/* Output quad (64 bit) value */ - -void -_bfd_evax_output_quad (abfd, value) - bfd *abfd; - uquad value; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_quad(%016lx)\n", value); -#endif - - bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size)); - PRIV(output_size) += 8; - return; -} - - -/* Output c-string as counted string */ - -void -_bfd_evax_output_counted (abfd, value) - bfd *abfd; - char *value; -{ -int len; - -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_counted(%s)\n", value); -#endif - - len = strlen (value); - if (len == 0) - { - (*_bfd_error_handler) (_("_bfd_evax_output_counted called with zero bytes")); - return; - } - if (len > 255) - { - (*_bfd_error_handler) (_("_bfd_evax_output_counted called with too many bytes")); - return; - } - _bfd_evax_output_byte (abfd, len & 0xff); - _bfd_evax_output_dump (abfd, (unsigned char *)value, len); -} - - -/* Output character area */ - -void -_bfd_evax_output_dump (abfd, data, length) - bfd *abfd; - unsigned char *data; - int length; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_dump(%d)\n", length); -#endif - - if (length == 0) - return; - - memcpy (PRIV(output_buf) + PRIV(output_size), data, length); - PRIV(output_size) += length; - - return; -} - - -/* Output count bytes of value */ - -void -_bfd_evax_output_fill (abfd, value, count) - bfd *abfd; - int value; - int count; -{ -#if EVAX_DEBUG - evax_debug (6, "_bfd_evax_output_fill(val %02x times %d)\n", value, count); -#endif - - if (count == 0) - return; - memset (PRIV(output_buf) + PRIV(output_size), value, count); - PRIV(output_size) += count; - - return; -} - -/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/ - -static int -hash_string (ptr) - const char *ptr; -{ - register const unsigned char *p = (unsigned char *) ptr; - register const unsigned char *end = p + strlen (ptr); - register unsigned char c; - register int hash = 0; - - while (p != end) - { - c = *p++; - hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); - } - return hash; -} - -/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */ - -char * -_bfd_evax_length_hash_symbol (abfd, in, maxlen) - bfd *abfd; - const char *in; - int maxlen; -{ - long int init; - long int result; - int in_len; - char *pnt = 0; - char *new_name; - const char *old_name; - int i; - static char outbuf[EOBJ_S_C_SYMSIZ+1]; - char *out = outbuf; - -#if EVAX_DEBUG - evax_debug(4, "_bfd_evax_length_hash_symbol \"%s\"\n", in); -#endif - - if (maxlen > EOBJ_S_C_SYMSIZ) - maxlen = EOBJ_S_C_SYMSIZ; - - new_name = out; /* save this for later. */ - - /* We may need to truncate the symbol, save the hash for later. */ - - in_len = strlen (in); - - result = (in_len > maxlen) ? hash_string (in) : 0; - - old_name = in; - - /* Do the length checking. */ - - if (in_len <= maxlen) - { - i = in_len; - } - else - { - if (PRIV(flag_hash_long_names)) - i = maxlen-9; - else - i = maxlen; - } - - strncpy (out, in, i); - in += i; - out += i; - - if ((in_len > maxlen) - && PRIV(flag_hash_long_names)) - sprintf (out, "_%08x", result); - else - *out = 0; - -#if EVAX_DEBUG - evax_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf); -#endif - - if (in_len > maxlen - && PRIV(flag_hash_long_names) - && PRIV(flag_show_after_trunc)) - printf (_("Symbol %s replaced by %s\n"), old_name, new_name); - - return outbuf; -} - diff --git a/bfd/evax.h b/bfd/evax.h deleted file mode 100644 index 945989899f6..00000000000 --- a/bfd/evax.h +++ /dev/null @@ -1,383 +0,0 @@ -/* evax.h -- Header file for ALPHA EVAX (openVMS/Alpha) support. - Copyright 1996, 1997 Free Software Foundation, Inc. - - Written by Klaus K"ampf (kkaempf@progis.de) - of proGIS Softwareentwicklung, Aachen, Germany - -This file is part of BFD, the Binary File Descriptor library. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#ifndef EVAX_H -#define EVAX_H - -/* EVAX Text, information and relocation record (ETIR) definitions. */ - -#define ETIR_S_C_MINSTACOD 0 /* Minimum store code */ -#define ETIR_S_C_STA_GBL 0 /* Stack global symbol value */ -#define ETIR_S_C_STA_LW 1 /* Stack longword */ -#define ETIR_S_C_STA_QW 2 /* Stack quadword */ -#define ETIR_S_C_STA_PQ 3 /* Stack psect base plus quadword offset */ -#define ETIR_S_C_STA_LI 4 /* Stack literal */ -#define ETIR_S_C_STA_MOD 5 /* Stack module */ -#define ETIR_S_C_STA_CKARG 6 /* Check Arguments */ -#define ETIR_S_C_MAXSTACOD 6 /* Maximum stack code */ -#define ETIR_S_C_MINSTOCOD 50 /* Minimum store code */ -#define ETIR_S_C_STO_B 50 /* Store byte */ -#define ETIR_S_C_STO_W 51 /* Store word */ -#define ETIR_S_C_STO_LW 52 /* Store longword */ -#define ETIR_S_C_STO_QW 53 /* Store quadword */ -#define ETIR_S_C_STO_IMMR 54 /* Store immediate Repeated */ -#define ETIR_S_C_STO_GBL 55 /* Store global */ -#define ETIR_S_C_STO_CA 56 /* Store code address */ -#define ETIR_S_C_STO_RB 57 /* Store relative branch */ -#define ETIR_S_C_STO_AB 58 /* Store absolute branch */ -#define ETIR_S_C_STO_OFF 59 /* Store offset within psect */ -#define ETIR_S_C_STO_IMM 61 /* Store immediate */ -#define ETIR_S_C_STO_GBL_LW 62 /* Store global Longword */ -#define ETIR_S_C_STO_LP_PSB 63 /* STO_LP_PSB not valid in level 2 use STC_LP_PSB */ -#define ETIR_S_C_STO_HINT_GBL 64 /* Store 14 bit HINT at global address */ -#define ETIR_S_C_STO_HINT_PS 65 /* Store 14 bit HINT at psect + offset */ -#define ETIR_S_C_MAXSTOCOD 65 /* Maximum store code */ -#define ETIR_S_C_MINOPRCOD 100 /* Minimum operate code */ -#define ETIR_S_C_OPR_NOP 100 /* No-op */ -#define ETIR_S_C_OPR_ADD 101 /* Add */ -#define ETIR_S_C_OPR_SUB 102 /* Subtract */ -#define ETIR_S_C_OPR_MUL 103 /* Multiply */ -#define ETIR_S_C_OPR_DIV 104 /* Divide */ -#define ETIR_S_C_OPR_AND 105 /* Logical AND */ -#define ETIR_S_C_OPR_IOR 106 /* Logical inclusive OR */ -#define ETIR_S_C_OPR_EOR 107 /* Logical exclusive OR */ -#define ETIR_S_C_OPR_NEG 108 /* Negate */ -#define ETIR_S_C_OPR_COM 109 /* Complement */ -#define ETIR_S_C_OPR_INSV 110 /* Insert bit field */ -#define ETIR_S_C_OPR_ASH 111 /* Arithmetic shift */ -#define ETIR_S_C_OPR_USH 112 /* Unsigned shift */ -#define ETIR_S_C_OPR_ROT 113 /* Rotate */ -#define ETIR_S_C_OPR_SEL 114 /* Select one of three longwords on top of stack */ -#define ETIR_S_C_OPR_REDEF 115 /* Redefine this symbol after pass 2 */ -#define ETIR_S_C_OPR_DFLIT 116 /* Define a literal */ -#define ETIR_S_C_MAXOPRCOD 116 /* Maximum operate code */ -#define ETIR_S_C_MINCTLCOD 150 /* Minimum control code */ -#define ETIR_S_C_CTL_SETRB 150 /* Set relocation base */ -#define ETIR_S_C_CTL_AUGRB 151 /* Augment relocation base */ -#define ETIR_S_C_CTL_DFLOC 152 /* Define debug location */ -#define ETIR_S_C_CTL_STLOC 153 /* Set debug location */ -#define ETIR_S_C_CTL_STKDL 154 /* Stack debug location */ -#define ETIR_S_C_MAXCTLCOD 154 /* Maximum control code */ -#define ETIR_S_C_MINSTCCOD 200 /* Minimum store-conditional code */ -#define ETIR_S_C_STC_LP 200 /* Store-conditional Linkage Pair */ -#define ETIR_S_C_STC_LP_PSB 201 /* Store-conditional Linkage Pair with Procedure Signature */ -#define ETIR_S_C_STC_GBL 202 /* Store-conditional Address at global address */ -#define ETIR_S_C_STC_GCA 203 /* Store-conditional Code Address at global address */ -#define ETIR_S_C_STC_PS 204 /* Store-conditional Address at psect + offset */ -#define ETIR_S_C_STC_NOP_GBL 205 /* Store-conditional NOP at address of global */ -#define ETIR_S_C_STC_NOP_PS 206 /* Store-conditional NOP at pect + offset */ -#define ETIR_S_C_STC_BSR_GBL 207 /* Store-conditional BSR at global address */ -#define ETIR_S_C_STC_BSR_PS 208 /* Store-conditional BSR at pect + offset */ -#define ETIR_S_C_STC_LDA_GBL 209 /* Store-conditional LDA at global address */ -#define ETIR_S_C_STC_LDA_PS 210 /* Store-conditional LDA at psect + offset */ -#define ETIR_S_C_STC_BOH_GBL 211 /* Store-conditional BSR or Hint at global address */ -#define ETIR_S_C_STC_BOH_PS 212 /* Store-conditional BSR or Hint at pect + offset */ -#define ETIR_S_C_STC_NBH_GBL 213 /* Store-conditional NOP,BSR or HINT at global address */ -#define ETIR_S_C_STC_NBH_PS 214 /* Store-conditional NOP,BSR or HINT at psect + offset */ -#define ETIR_S_C_MAXSTCCOD 214 /* Maximum store-conditional code */ - -/* EVAX Global symbol definition record (EGSD). */ - -#define EGSD_S_K_ENTRIES 2 /* Offset to first entry in record */ -#define EGSD_S_C_ENTRIES 2 /* Offset to first entry in record */ -#define EGSD_S_C_PSC 0 /* Psect definition */ -#define EGSD_S_C_SYM 1 /* Symbol specification */ -#define EGSD_S_C_IDC 2 /* Random entity check */ -#define EGSD_S_C_SPSC 5 /* Shareable image psect definition */ -#define EGSD_S_C_SYMV 6 /* Vectored (dual-valued) versions of SYM, */ -#define EGSD_S_C_SYMM 7 /* Masked versions of SYM, */ -#define EGSD_S_C_SYMG 8 /* EGST - gst version of SYM */ -#define EGSD_S_C_MAXRECTYP 8 /* Maximum entry type defined */ - -#define EGPS_S_V_PIC 0x0001 -#define EGPS_S_V_LIB 0x0002 -#define EGPS_S_V_OVR 0x0004 -#define EGPS_S_V_REL 0x0008 -#define EGPS_S_V_GBL 0x0010 -#define EGPS_S_V_SHR 0x0020 -#define EGPS_S_V_EXE 0x0040 -#define EGPS_S_V_RD 0x0080 -#define EGPS_S_V_WRT 0x0100 -#define EGPS_S_V_VEC 0x0200 -#define EGPS_S_V_NOMOD 0x0400 -#define EGPS_S_V_COM 0x0800 - -#define EGSY_S_V_WEAK 0x0001 -#define EGSY_S_V_DEF 0x0002 -#define EGSY_S_V_UNI 0x0004 -#define EGSY_S_V_REL 0x0008 -#define EGSY_S_V_COMM 0x0010 -#define EGSY_S_V_VECEP 0x0020 -#define EGSY_S_V_NORM 0x0040 - -/* EVAX Module header record (EMH) definitions. */ - -#define EMH_S_C_MHD 0 /* Main header record */ -#define EMH_S_C_LNM 1 /* Language name and version */ -#define EMH_S_C_SRC 2 /* Source file specification */ -#define EMH_S_C_TTL 3 /* Title text of module */ -#define EMH_S_C_CPR 4 /* Copyright notice */ -#define EMH_S_C_MTC 5 /* Maintenance status */ -#define EMH_S_C_GTX 6 /* General text */ -#define EMH_S_C_MAXHDRTYP 6 /* Maximum allowable type */ - -/* evax-alpha.c. */ - -extern asymbol *_bfd_evax_make_empty_symbol PARAMS ((bfd *abfd)); - -/* evax-egsd.c. */ - -extern int _bfd_evax_slurp_egsd PARAMS ((bfd *abfd)); -extern int _bfd_evax_write_egsd PARAMS ((bfd *abfd)); - -/* evax-emh.c. */ - -extern int _bfd_evax_slurp_emh PARAMS ((bfd *abfd)); -extern int _bfd_evax_write_emh PARAMS ((bfd *abfd)); -extern int _bfd_evax_slurp_eeom PARAMS ((bfd *abfd)); -extern int _bfd_evax_write_eeom PARAMS ((bfd *abfd)); - -/* evax-etir.c. */ - -extern int _bfd_evax_slurp_etir PARAMS ((bfd *abfd)); -extern int _bfd_evax_slurp_edbg PARAMS ((bfd *abfd)); -extern int _bfd_evax_slurp_etbt PARAMS ((bfd *abfd)); - -extern int _bfd_evax_write_etir PARAMS ((bfd *abfd)); -extern int _bfd_evax_write_etbt PARAMS ((bfd *abfd)); -extern int _bfd_evax_write_edbg PARAMS ((bfd *abfd)); - -/* The r_type field in a reloc is one of the following values. */ -#define ALPHA_R_IGNORE 0 -#define ALPHA_R_REFQUAD 1 -#define ALPHA_R_BRADDR 2 -#define ALPHA_R_HINT 3 -#define ALPHA_R_SREL16 4 -#define ALPHA_R_SREL32 5 -#define ALPHA_R_SREL64 6 -#define ALPHA_R_OP_PUSH 7 -#define ALPHA_R_OP_STORE 8 -#define ALPHA_R_OP_PSUB 9 -#define ALPHA_R_OP_PRSHIFT 10 -#define ALPHA_R_LINKAGE 11 -#define ALPHA_R_REFLONG 12 -#define ALPHA_R_CODEADDR 13 - -/* Object language definitions. */ - -#define EOBJ_S_C_EMH 8 /*EVAX module header record */ -#define EOBJ_S_C_EEOM 9 /*EVAX end of module record */ -#define EOBJ_S_C_EGSD 10 /*EVAX global symbol definition record */ -#define EOBJ_S_C_ETIR 11 /*EVAX text information record */ -#define EOBJ_S_C_EDBG 12 /*EVAX Debugger information record */ -#define EOBJ_S_C_ETBT 13 /*EVAX Traceback information record */ -#define EOBJ_S_C_MAXRECTYP 13 /*Last assigned record type */ -#define EOBJ_S_K_SUBTYP 4 -#define EOBJ_S_C_SUBTYP 4 -#define EOBJ_S_C_MAXRECSIZ 8192 /*Maximum legal record size */ -#define EOBJ_S_C_STRLVL 2 /*Structure level */ -#define EOBJ_S_C_SYMSIZ 64 /*Maximum symbol length */ -#define EOBJ_S_C_SECSIZ 31 /*Maximum section name length */ -#define EOBJ_S_C_STOREPLIM -1 /*Maximum repeat count on store commands */ -#define EOBJ_S_C_PSCALILIM 16 /*Maximum p-sect alignment */ - -/* Miscellaneous definitions. */ - -#if __GNUC__ -typedef unsigned long long uquad; -#else -typedef unsigned long uquad; -#endif - -#define MAX_OUTREC_SIZE 4096 -#define MIN_OUTREC_LUFT 64 - -typedef struct _evax_section { - unsigned char *contents; - bfd_vma offset; - bfd_size_type size; - struct _evax_section *next; -} evax_section; - -extern boolean _bfd_save_evax_section - PARAMS ((bfd *abfd, asection *section, PTR data, file_ptr offset, - bfd_size_type count)); -extern evax_section *_bfd_get_evax_section PARAMS ((bfd *abfd, int index)); - -typedef struct _evax_reloc { - struct _evax_reloc *next; - arelent *reloc; - asection *section; -} evax_reloc; - -/* evax module header */ - -struct emh_struc { - int emh_b_strlvl; - long emh_l_arch1; - long emh_l_arch2; - long emh_l_recsiz; - char *emh_t_name; - char *emh_t_version; - char *emh_t_date; - char *emh_c_lnm; - char *emh_c_src; - char *emh_c_ttl; -}; - - -/* evax end of module */ - -struct eeom_struc { - long eeom_l_total_lps; - unsigned char eeom_b_comcod; - boolean eeom_has_transfer; - unsigned char eeom_b_tfrflg; - long eeom_l_psindx; - long eeom_l_tfradr; -}; - -enum file_format_enum { FF_UNKNOWN, FF_FOREIGN, FF_NATIVE }; - -typedef struct evax_symbol_struct { - struct bfd_hash_entry bfd_hash; - asymbol *symbol; -} evax_symbol_entry; - -/* stack value for push/pop commands */ - -struct stack_struct { - uquad value; - int psect; -}; -#define STACKSIZE 50 - -/* location stack definitions for CTL_DFLOC, CTL_STLOC, and CTL_STKDL */ - -struct location_struct { - unsigned long value; - int psect; -}; -#define LOCATION_SAVE_SIZE 32 - -#define EVAX_SECTION_COUNT 1024 - -struct evax_private_data_struct { - boolean fixup_done; /* Flag to indicate if all - section pointers and PRIV(sections) - are set up correctly */ - unsigned char *evax_buf; /* buffer to record */ - int buf_size; /* max size of buffer */ - unsigned char *evax_rec; /* actual record ptr */ - int rec_length; /* remaining record length */ - int rec_size; /* actual record size */ - int rec_type; /* actual record type */ - enum file_format_enum file_format; - - struct emh_struc emh_data; /* data from EMH record */ - struct eeom_struc eeom_data; /* data from EEOM record */ - int egsd_sec_count; /* # of EGSD sections */ - asection **sections; /* vector of EGSD sections */ - int egsd_sym_count; /* # of EGSD symbols */ - asymbol **symbols; /* vector of EGSD symbols */ - struct proc_value *procedure; - - struct stack_struct *stack; - int stackptr; - - evax_section *evax_section_table[EVAX_SECTION_COUNT]; - - struct bfd_hash_table *evax_symbol_table; - struct symbol_cache_entry **symcache; - int symnum; - - struct location_struct *location_stack; - - unsigned char *image_ptr; /* a pointer to section->contents */ - - unsigned char pdsc[8]; /* procedure descriptor */ - - /* Output routine storage */ - - unsigned char *output_buf; /* output data */ - int push_level; - int pushed_size; - int length_pos; - int output_size; - int output_alignment; - - /* linkage index counter - used by conditional store commands (ETIR_S_C_STC_) */ - - int evax_linkage_index; - - /* see tc-alpha.c of gas for a description. */ - int flag_hash_long_names; /* -+, hash instead of truncate */ - int flag_show_after_trunc; /* -H, show hashing/truncation */ -}; - -#define PRIV(name) ((struct evax_private_data_struct *)abfd->tdata.any)->name - -#if EVAX_DEBUG -extern void _bfd_evax_debug PARAMS((int level, char *format, ...)); -extern void _bfd_hexdump - PARAMS ((int level, unsigned char *ptr, int size, int offset)); - -#define evax_debug _bfd_evax_debug - -#endif - -extern struct bfd_hash_entry *_bfd_evax_hash_newfunc - PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table, - const char *string)); -extern void _bfd_evax_get_header_values - PARAMS ((bfd *abfd, unsigned char *buf, int *type, int *length)); -extern int _bfd_evax_get_record PARAMS ((bfd *abfd)); -extern int _bfd_evax_next_record PARAMS ((bfd *abfd)); - -extern char *_bfd_evax_save_sized_string PARAMS ((char *str, int size)); -extern char *_bfd_evax_save_counted_string PARAMS ((char *ptr)); -extern void _bfd_evax_push PARAMS ((bfd *abfd, uquad val, int psect)); -extern uquad _bfd_evax_pop PARAMS ((bfd *abfd, int *psect)); - -extern boolean _bfd_save_evax_section - PARAMS ((bfd *abfd, asection *section, PTR data, file_ptr offset, - bfd_size_type count)); -extern void _bfd_evax_output_begin - PARAMS ((bfd *abfd, int rectype, int rechead)); -extern void _bfd_evax_output_alignment PARAMS ((bfd *abfd, int alignto)); -extern void _bfd_evax_output_push PARAMS ((bfd *abfd)); -extern void _bfd_evax_output_pop PARAMS ((bfd *abfd)); -extern void _bfd_evax_output_flush PARAMS ((bfd *abfd)); -extern void _bfd_evax_output_end PARAMS ((bfd *abfd)); -extern int _bfd_evax_output_check PARAMS ((bfd *abfd, int size)); -extern void _bfd_evax_output_byte PARAMS ((bfd *abfd, unsigned int value)); -extern void _bfd_evax_output_short PARAMS ((bfd *abfd, unsigned int value)); -extern void _bfd_evax_output_long PARAMS ((bfd *abfd, unsigned long value)); -extern void _bfd_evax_output_quad PARAMS ((bfd *abfd, uquad value)); -extern void _bfd_evax_output_counted PARAMS ((bfd *abfd, char *value)); -extern void _bfd_evax_output_dump PARAMS ((bfd *abfd, unsigned char *data, - int length)); -extern void _bfd_evax_output_fill PARAMS ((bfd *abfd, int value, int length)); -extern char *_bfd_evax_length_hash_symbol PARAMS ((bfd *abfd, const char *in, int maxlen)); - -#endif /* EVAX_H */ diff --git a/bfd/po/POTFILES.in b/bfd/po/POTFILES.in index f16781a19e3..a582f28d305 100644 --- a/bfd/po/POTFILES.in +++ b/bfd/po/POTFILES.in @@ -109,12 +109,6 @@ elf64-sparc.c elf64.c elfcode.h elflink.c -evax-alpha.c -evax-egsd.c -evax-emh.c -evax-etir.c -evax-misc.c -evax.h format.c genlink.h go32stub.h @@ -197,4 +191,10 @@ tekhex.c trad-core.c vaxnetbsd.c versados.c +vms-gsd.c +vms-hdr.c +vms-misc.c +vms-tir.c +vms.c +vms.h xcofflink.c diff --git a/bfd/vms-gsd.c b/bfd/vms-gsd.c new file mode 100644 index 00000000000..6a52462a06d --- /dev/null +++ b/bfd/vms-gsd.c @@ -0,0 +1,920 @@ +/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and + EVAX (openVMS/Alpha) files. + Copyright 1996, 1997, 1998 Free Software Foundation Inc. + + go and read the openVMS linker manual (esp. appendix B) + if you don't know what's going on here :-) + + 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 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" + +#include "vms.h" + +/*-----------------------------------------------------------------------------*/ + +/* typical sections for vax object files */ + +#define VAX_CODE_NAME "$CODE" +#define VAX_DATA_NAME "$DATA" +#define VAX_ADDRESS_DATA_NAME "$ADDRESS_DATA" + +/* typical sections for evax object files */ + +#define EVAX_ABS_NAME "$ABS$" +#define EVAX_CODE_NAME "$CODE$" +#define EVAX_LINK_NAME "$LINK$" +#define EVAX_DATA_NAME "$DATA$" +#define EVAX_BSS_NAME "$BSS$" +#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" +#define EVAX_READONLY_NAME "$READONLY$" +#define EVAX_LITERAL_NAME "$LITERAL$" +#define EVAX_COMMON_NAME "$COMMON$" +#define EVAX_LOCAL_NAME "$LOCAL$" + +struct sec_flags_struct { + char *name; /* name of section */ + int vflags_always; + flagword flags_always; /* flags we set always */ + int vflags_hassize; + flagword flags_hassize; /* flags we set if the section has a size > 0 */ +}; + +/* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible */ + +static struct sec_flags_struct vax_section_flags[] = { + { VAX_CODE_NAME, + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE|GPS_S_M_RD), + (SEC_CODE), + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE|GPS_S_M_RD), + (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { VAX_DATA_NAME, + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT), + (SEC_DATA), + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { VAX_ADDRESS_DATA_NAME, + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD), + (SEC_DATA|SEC_READONLY), + (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, + { NULL, + (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD|GPS_S_M_WRT), + (SEC_DATA), + (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD|GPS_S_M_WRT), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } +}; + + +/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible */ + +static struct sec_flags_struct evax_section_flags[] = { + { EVAX_ABS_NAME, + (EGPS_S_V_SHR), + (SEC_DATA), + (EGPS_S_V_SHR), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { EVAX_CODE_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), + (SEC_CODE), + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), + (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { EVAX_LITERAL_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), + (SEC_DATA|SEC_READONLY), + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, + { EVAX_LINK_NAME, + (EGPS_S_V_REL|EGPS_S_V_RD), + (SEC_DATA|SEC_READONLY), + (EGPS_S_V_REL|EGPS_S_V_RD), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, + { EVAX_DATA_NAME, + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), + (SEC_DATA), + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { EVAX_BSS_NAME, + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), + (SEC_NO_FLAGS), + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), + (SEC_IN_MEMORY|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { EVAX_READONLYADDR_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), + (SEC_DATA|SEC_READONLY), + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, + { EVAX_READONLY_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), + (SEC_DATA|SEC_READONLY), + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, + { EVAX_LOCAL_NAME, + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), + (SEC_DATA), + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, + { NULL, + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), + (SEC_DATA), + (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), + (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } +}; + +/* Retrieve bfd section flags by name and size */ + +static flagword +vms_secflag_by_name (abfd, section_flags, name, size) + bfd *abfd; + struct sec_flags_struct *section_flags; + char *name; + int size; +{ + int i = 0; + + while (section_flags[i].name != NULL) + { + if ((PRIV(is_vax)? + strcasecmp (name, section_flags[i].name): + strcmp (name, section_flags[i].name)) == 0) + { + if (size > 0) + return section_flags[i].flags_hassize; + else + return section_flags[i].flags_always; + } + i++; + } + if (size > 0) + return section_flags[i].flags_hassize; + return section_flags[i].flags_always; +} + + +/* Retrieve vms section flags by name and size */ + +static flagword +vms_esecflag_by_name (section_flags, name, size) + struct sec_flags_struct *section_flags; + char *name; + int size; +{ + int i = 0; + + while (section_flags[i].name != NULL) + { + if (strcmp (name, section_flags[i].name) == 0) + { + if (size > 0) + return section_flags[i].vflags_hassize; + else + return section_flags[i].vflags_always; + } + i++; + } + if (size > 0) + return section_flags[i].vflags_hassize; + return section_flags[i].vflags_always; +} + +/*-----------------------------------------------------------------------------*/ +#if VMS_DEBUG +/* debug */ + +struct flagdescstruct { char *name; flagword value; }; + +/* Convert flag to printable string */ + +static char * +flag2str(flagdesc, flags) + struct flagdescstruct *flagdesc; + flagword flags; +{ + + static char res[64]; + int next = 0; + + res[0] = 0; + while (flagdesc->name != NULL) + { + if ((flags & flagdesc->value) != 0) + { + if (next) + strcat(res, ","); + else + next = 1; + strcat (res, flagdesc->name); + } + flagdesc++; + } + return res; +} +#endif + +/*-----------------------------------------------------------------------------*/ +/* input routines */ + +/* Process GSD/EGSD record + return 0 on success, -1 on error */ + +int +_bfd_vms_slurp_gsd (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + static struct flagdescstruct gpsflagdesc[] = + { + { "PIC", 0x0001 }, + { "LIB", 0x0002 }, + { "OVR", 0x0004 }, + { "REL", 0x0008 }, + { "GBL", 0x0010 }, + { "SHR", 0x0020 }, + { "EXE", 0x0040 }, + { "RD", 0x0080 }, + { "WRT", 0x0100 }, + { "VEC", 0x0200 }, + { "NOMOD", 0x0400 }, + { "COM", 0x0800 }, + { NULL, 0 } + }; + + static struct flagdescstruct gsyflagdesc[] = + { + { "WEAK", 0x0001 }, + { "DEF", 0x0002 }, + { "UNI", 0x0004 }, + { "REL", 0x0008 }, + { "COMM", 0x0010 }, + { "VECEP", 0x0020 }, + { "NORM", 0x0040 }, + { NULL, 0 } + }; +#endif + + int gsd_type, gsd_size; + asection *section; + unsigned char *vms_rec; + flagword new_flags, old_flags; + char *name; + asymbol *symbol; + vms_symbol_entry *entry; + unsigned long base_addr; + unsigned long align_addr; + static int psect_idx = 0; + +#if VMS_DEBUG + vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype); +#endif + + switch (objtype) + { + case EOBJ_S_C_EGSD: + PRIV(vms_rec) += 8; /* skip type, size, l_temp */ + PRIV(rec_size) -= 8; + break; + case OBJ_S_C_GSD: + PRIV(vms_rec) += 1; + PRIV(rec_size) -= 1; + break; + default: + return -1; + } + + /* calculate base address for each section */ + base_addr = 0L; + + abfd->symcount = 0; + + while (PRIV(rec_size) > 0) + { + vms_rec = PRIV(vms_rec); + + if (objtype == OBJ_S_C_GSD) + { + gsd_type = *vms_rec; + } + else + { + _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size); + gsd_type += EVAX_OFFSET; + } + +#if VMS_DEBUG + vms_debug (3, "gsd_type %d\n", gsd_type); +#endif + + switch (gsd_type) + { + case GSD_S_C_PSC: + { + /* + * program section definition + */ + + asection *old_section = 0; + +#if VMS_DEBUG + vms_debug (4, "GSD_S_C_PSC\n"); +#endif + /* If this section isn't a bfd section. */ + + if (PRIV(is_vax) && (psect_idx < (abfd->section_count-1))) + { + /* check for temporary section from TIR record. */ + + if (psect_idx < PRIV(section_count)) + old_section = PRIV(sections)[psect_idx]; + else + old_section = 0; + } + + name = _bfd_vms_save_counted_string (vms_rec + 8); + section = bfd_make_section (abfd, name); + if (!section) + { + fprintf (stderr, "bfd_make_section (%s) failed\n", name); + return -1; + } + old_flags = bfd_getl16 (vms_rec + 2); + section->_raw_size = bfd_getl32(vms_rec + 4); /* allocation */ + new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->_raw_size); + if (old_flags & EGPS_S_V_REL) + new_flags |= SEC_RELOC; + if (old_flags & GPS_S_M_OVR) + new_flags |= SEC_IS_COMMON; + if (!bfd_set_section_flags (abfd, section, new_flags)) + { + fprintf (stderr, "bfd_set_section_flags (%s, %x) failed\n", name, new_flags); + return -1; + } + section->alignment_power = vms_rec[1]; + align_addr = (1 << section->alignment_power); + if ((base_addr % align_addr) != 0) + base_addr += (align_addr - (base_addr % align_addr)); + section->vma = (bfd_vma)base_addr; + base_addr += section->_raw_size; + + /* global section is common symbol */ + + if (old_flags & GPS_S_M_GBL) + { + entry = _bfd_vms_enter_symbol (abfd, name); + if (entry == (vms_symbol_entry *)NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + symbol = entry->symbol; + + symbol->value = 0; + symbol->section = section; + symbol->flags = (BSF_GLOBAL|BSF_SECTION_SYM|BSF_OLD_COMMON); + } + + /* copy saved contents if old_section set */ + + if (old_section != 0) + { + section->contents = old_section->contents; + if (section->_raw_size < old_section->_raw_size) + { + fprintf (stderr, "Size mismatch section %s=%d, %s=%d\n", old_section->name, old_section->_raw_size, section->name, section->_raw_size); + return -1; + } + else if (section->_raw_size > old_section->_raw_size) + { + section->contents = ((unsigned char *) + bfd_realloc (old_section->contents, section->_raw_size)); + if (section->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + } + } + else + { + section->contents = ((unsigned char *) + bfd_malloc (section->_raw_size)); + if (section->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + memset (section->contents, 0, (size_t)section->_raw_size); + } + section->_cooked_size = section->_raw_size; +#if VMS_DEBUG + vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ", + section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); + vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", + section->_raw_size, section->vma, section->contents); +#endif + + gsd_size = vms_rec[8] + 9; + + psect_idx++; + } + break; + + case GSD_S_C_EPM: + case GSD_S_C_EPMW: +#if VMS_DEBUG + vms_debug(4, "gsd epm\n"); +#endif + /*FALLTHRU*/ + case GSD_S_C_SYM: + case GSD_S_C_SYMW: + { + int name_offset, value_offset; + + /* + * symbol specification (definition or reference) + */ + +#if VMS_DEBUG + vms_debug (4, "GSD_S_C_SYM(W)\n"); +#endif + old_flags = bfd_getl16 (vms_rec + 2); + new_flags = BSF_NO_FLAGS; + + if (old_flags & GSY_S_M_WEAK) + new_flags |= BSF_WEAK; + + switch (gsd_type) + { + case GSD_S_C_EPM: + name_offset = 11; + value_offset = 5; + new_flags |= BSF_FUNCTION; + break; + case GSD_S_C_EPMW: + name_offset = 12; + value_offset = 6; + new_flags |= BSF_FUNCTION; + break; + case GSD_S_C_SYM: + if (old_flags & GSY_S_M_DEF) /* symbol definition */ + name_offset = 9; + else + name_offset = 4; + value_offset = 5; + break; + case GSD_S_C_SYMW: + if (old_flags & GSY_S_M_DEF) /* symbol definition */ + name_offset = 10; + else + name_offset = 5; + value_offset = 6; + break; + } + + /* save symbol in vms_symbol_table */ + + entry = _bfd_vms_enter_symbol (abfd, + _bfd_vms_save_counted_string (vms_rec + name_offset)); + if (entry == (vms_symbol_entry *)NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + symbol = entry->symbol; + + if (old_flags & GSY_S_M_DEF) /* symbol definition */ + { + int psect; + + symbol->value = bfd_getl32 (vms_rec+value_offset); + if ((gsd_type == GSD_S_C_SYMW) + || (gsd_type == GSD_S_C_EPMW)) + psect = bfd_getl16 (vms_rec + value_offset - 2); + else + psect = vms_rec[value_offset-1]; + + symbol->section = (asection *)psect; +#if VMS_DEBUG + vms_debug(4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount, + symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); +#endif + } + else /* symbol reference */ + { + symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); +#if VMS_DEBUG + vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n", abfd->symcount, + symbol->name, symbol->section->name, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); +#endif + } + + gsd_size = vms_rec[name_offset] + name_offset + 1; + symbol->flags = new_flags; + } + + break; + + case GSD_S_C_PRO: + case GSD_S_C_PROW: +#if VMS_DEBUG + vms_debug(4, "gsd pro\n"); +#endif + break; + case GSD_S_C_IDC: +#if VMS_DEBUG + vms_debug(4, "gsd idc\n"); +#endif + break; + case GSD_S_C_ENV: +#if VMS_DEBUG + vms_debug(4, "gsd env\n"); +#endif + break; + case GSD_S_C_LSY: +#if VMS_DEBUG + vms_debug(4, "gsd lsy\n"); +#endif + break; + case GSD_S_C_LEPM: +#if VMS_DEBUG + vms_debug(4, "gsd lepm\n"); +#endif + break; + case GSD_S_C_LPRO: +#if VMS_DEBUG + vms_debug(4, "gsd lpro\n"); +#endif + break; + case GSD_S_C_SPSC: +#if VMS_DEBUG + vms_debug(4, "gsd spsc\n"); +#endif + break; + case GSD_S_C_SYMV: +#if VMS_DEBUG + vms_debug(4, "gsd symv\n"); +#endif + break; + case GSD_S_C_EPMV: +#if VMS_DEBUG + vms_debug(4, "gsd epmv\n"); +#endif + break; + case GSD_S_C_PROV: +#if VMS_DEBUG + vms_debug(4, "gsd prov\n"); +#endif + break; + + case EGSD_S_C_PSC + EVAX_OFFSET: + { + /* program section definition */ + + name = _bfd_vms_save_counted_string (vms_rec+12); + section = bfd_make_section (abfd, name); + if (!section) + return -1; + old_flags = bfd_getl16 (vms_rec + 6); + section->_raw_size = bfd_getl32 (vms_rec + 8); /* allocation */ + new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, (int) section->_raw_size); + if (old_flags & EGPS_S_V_REL) + new_flags |= SEC_RELOC; + if (!bfd_set_section_flags (abfd, section, new_flags)) + return -1; + section->alignment_power = vms_rec[4]; + align_addr = (1 << section->alignment_power); + if ((base_addr % align_addr) != 0) + base_addr += (align_addr - (base_addr % align_addr)); + section->vma = (bfd_vma)base_addr; + base_addr += section->_raw_size; + section->contents = ((unsigned char *) + bfd_malloc (section->_raw_size)); + if (section->contents == NULL) + return -1; + memset (section->contents, 0, (size_t) section->_raw_size); + section->_cooked_size = section->_raw_size; +#if VMS_DEBUG + vms_debug(4, "egsd psc %d (%s, flags %04x=%s) ", + section->index, name, old_flags, flag2str(gpsflagdesc, old_flags)); + vms_debug(4, "%d bytes at 0x%08lx (mem %p)\n", + section->_raw_size, section->vma, section->contents); +#endif + } + break; + + case EGSD_S_C_SYM + EVAX_OFFSET: + { + /* symbol specification (definition or reference) */ + + symbol = _bfd_vms_make_empty_symbol (abfd); + if (symbol == 0) + return -1; + + old_flags = bfd_getl16 (vms_rec + 6); + new_flags = BSF_NO_FLAGS; + + if (old_flags & EGSY_S_V_WEAK) + new_flags |= BSF_WEAK; + + if (vms_rec[6] & EGSY_S_V_DEF) /* symbol definition */ + { + symbol->name = + _bfd_vms_save_counted_string (vms_rec+32); + if (old_flags & EGSY_S_V_NORM) + { /* proc def */ + new_flags |= BSF_FUNCTION; + } + symbol->value = bfd_getl64 (vms_rec+8); + symbol->section = (asection *)((unsigned long) bfd_getl32 (vms_rec+28)); +#if VMS_DEBUG + vms_debug(4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, + symbol->name, (int)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); +#endif + } + else /* symbol reference */ + { + symbol->name = + _bfd_vms_save_counted_string (vms_rec+8); +#if VMS_DEBUG + vms_debug(4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, + symbol->name, old_flags, flag2str(gsyflagdesc, old_flags)); +#endif + symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); + } + + symbol->flags = new_flags; + + /* save symbol in vms_symbol_table */ + + entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV(vms_symbol_table), symbol->name, true, false); + if (entry == (vms_symbol_entry *)NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + if (entry->symbol != (asymbol *)NULL) + { /* FIXME ?, DEC C generates this */ +#if VMS_DEBUG + vms_debug(4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); +#endif + } + else + { + entry->symbol = symbol; + PRIV(gsd_sym_count)++; + abfd->symcount++; + } + } + break; + + case EGSD_S_C_IDC + EVAX_OFFSET: + break; + + default: + (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type); + bfd_set_error (bfd_error_bad_value); + return -1; + + } /* switch */ + + PRIV(rec_size) -= gsd_size; + PRIV(vms_rec) += gsd_size; + + } /* while (recsize > 0) */ + + if (abfd->symcount > 0) + abfd->flags |= HAS_SYMS; + + return 0; +} + +/*-----------------------------------------------------------------------------*/ +/* output routines */ + +/* Write section and symbol directory of bfd abfd */ + +int +_bfd_vms_write_gsd (abfd, objtype) + bfd *abfd; + int objtype; +{ + asection *section; + asymbol *symbol; + int symnum; + int last_index = -1; + char dummy_name[10]; + char *sname; + flagword new_flags, old_flags; + char *nptr, *uptr; + +#if VMS_DEBUG + vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); +#endif + + /* output sections */ + + section = abfd->sections; +#if VMS_DEBUG + vms_debug (3, "%d sections found\n", abfd->section_count); +#endif + + /* egsd is quadword aligned */ + + _bfd_vms_output_alignment (abfd, 8); + + _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); + _bfd_vms_output_long (abfd, 0); + _bfd_vms_output_push (abfd); /* prepare output for subrecords */ + + while (section != 0) + { +#if VMS_DEBUG + vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->_raw_size); +#endif + + /* 13 bytes egsd, max 31 chars name -> should be 44 bytes */ + if (_bfd_vms_output_check (abfd, 64) < 0) + { + _bfd_vms_output_pop (abfd); + _bfd_vms_output_end (abfd); + _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); + _bfd_vms_output_long (abfd, 0); + _bfd_vms_output_push (abfd); /* prepare output for subrecords */ + } + + /* Create dummy sections to keep consecutive indices */ + + while (section->index - last_index > 1) + { +#if VMS_DEBUG + vms_debug (3, "index %d, last %d\n", section->index, last_index); +#endif + _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); + _bfd_vms_output_short (abfd, 0); + _bfd_vms_output_short (abfd, 0); + _bfd_vms_output_long (abfd, 0); + sprintf (dummy_name, ".DUMMY%02d", last_index); + _bfd_vms_output_counted (abfd, dummy_name); + _bfd_vms_output_flush (abfd); + last_index++; + } + + /* Don't know if this is neccesary for the linker but for now it keeps + vms_slurp_gsd happy */ + + sname = (char *)section->name; + if (*sname == '.') + { + sname++; + if ((*sname == 't') && (strcmp (sname, "text") == 0)) + sname = PRIV(is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME; + else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) + sname = PRIV(is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME; + else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) + sname = EVAX_BSS_NAME; + else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) + sname = EVAX_LINK_NAME; + else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) + sname = EVAX_READONLY_NAME; + else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) + sname = EVAX_LITERAL_NAME; + else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) + sname = EVAX_COMMON_NAME; + else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) + sname = EVAX_LOCAL_NAME; + } + else + sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); + + _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); + _bfd_vms_output_short (abfd, section->alignment_power & 0xff); + if (bfd_is_com_section (section)) + { + new_flags = (EGPS_S_V_OVR|EGPS_S_V_REL|EGPS_S_V_GBL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD|EGPS_S_V_COM); + } + else + { + new_flags = vms_esecflag_by_name (evax_section_flags, sname, section->_raw_size); + } + _bfd_vms_output_short (abfd, new_flags); + _bfd_vms_output_long (abfd, section->_raw_size); + _bfd_vms_output_counted (abfd, sname); + _bfd_vms_output_flush (abfd); + + last_index = section->index; + section = section->next; + } + + /* output symbols */ + +#if VMS_DEBUG + vms_debug (3, "%d symbols found\n", abfd->symcount); +#endif + + bfd_set_start_address (abfd, (bfd_vma)-1); + + for (symnum = 0; symnum < abfd->symcount; symnum++) + { + + symbol = abfd->outsymbols[symnum]; + if (*(symbol->name) == '_') + { + if (strcmp (symbol->name, "__main") == 0) + bfd_set_start_address (abfd, (bfd_vma)symbol->value); + } + old_flags = symbol->flags; + + if (old_flags & BSF_FILE) + continue; + + if (((old_flags & (BSF_GLOBAL|BSF_WEAK)) == 0) /* not xdef */ + && (!bfd_is_und_section (symbol->section))) /* and not xref */ + continue; /* dont output */ + + /* 13 bytes egsd, max 64 chars name -> should be 77 bytes */ + + if (_bfd_vms_output_check (abfd, 80) < 0) + { + _bfd_vms_output_pop (abfd); + _bfd_vms_output_end (abfd); + _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); + _bfd_vms_output_long (abfd, 0); + _bfd_vms_output_push (abfd); /* prepare output for subrecords */ + } + + _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1); + + _bfd_vms_output_short (abfd, 0); /* data type, alignment */ + + new_flags = 0; + + if (old_flags & BSF_WEAK) + new_flags |= EGSY_S_V_WEAK; + if (bfd_is_com_section (symbol->section)) /* .comm */ + new_flags |= (EGSY_S_V_WEAK|EGSY_S_V_COMM); + + if (old_flags & BSF_FUNCTION) + { + new_flags |= EGSY_S_V_NORM; + new_flags |= EGSY_S_V_REL; + } + if (old_flags & (BSF_GLOBAL|BSF_WEAK)) + { + new_flags |= EGSY_S_V_DEF; + if (!bfd_is_abs_section (symbol->section)) + new_flags |= EGSY_S_V_REL; + } + _bfd_vms_output_short (abfd, new_flags); + + if (old_flags & (BSF_GLOBAL|BSF_WEAK)) /* symbol definition */ + { + if (old_flags & BSF_FUNCTION) + { + _bfd_vms_output_quad (abfd, symbol->value); + _bfd_vms_output_quad (abfd, + ((asymbol *)(symbol->udata.p))->value); + _bfd_vms_output_long (abfd, + (((asymbol *)(symbol->udata.p)) + ->section->index)); + _bfd_vms_output_long (abfd, symbol->section->index); + } + else + { + _bfd_vms_output_quad (abfd, symbol->value); /* L_VALUE */ + _bfd_vms_output_quad (abfd, 0); /* L_CODE_ADDRESS */ + _bfd_vms_output_long (abfd, 0); /* L_CA_PSINDX */ + _bfd_vms_output_long (abfd, symbol->section->index);/* L_PSINDX */ + } + } + _bfd_vms_output_counted (abfd, _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ)); + + _bfd_vms_output_flush (abfd); + + } + + _bfd_vms_output_alignment (abfd, 8); + _bfd_vms_output_pop (abfd); + _bfd_vms_output_end (abfd); + + return 0; +} diff --git a/bfd/vms-hdr.c b/bfd/vms-hdr.c new file mode 100644 index 00000000000..01d20aabefa --- /dev/null +++ b/bfd/vms-hdr.c @@ -0,0 +1,461 @@ +/* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and + EVAX (openVMS/Alpha) files. + Copyright 1996, 1997, 1998 Free Software Foundation, Inc. + + HDR record handling functions + EMH record handling functions + and + EOM record handling functions + EEOM record 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 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" + +#include "vms.h" + +/*---------------------------------------------------------------------------*/ + + +/* Read & process emh record + return 0 on success, -1 on error */ + +int +_bfd_vms_slurp_hdr (abfd, objtype) + 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_length-2)); + break; + + case MHD_S_C_SRC: + /* + * + */ + PRIV(hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-2)); + break; + + case MHD_S_C_TTL: + /* + * + */ + PRIV(hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-2)); + break; + + case MHD_S_C_CPR: + /* + * + */ + break; + + case MHD_S_C_MTC: + /* + * + */ + break; + + case MHD_S_C_GTX: + /* + * + */ + 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_length-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)); + 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)); + break; + + case EMH_S_C_CPR + EVAX_OFFSET: + /* + * + */ + break; + + case EMH_S_C_MTC + EVAX_OFFSET: + /* + * + */ + break; + + case EMH_S_C_GTX + EVAX_OFFSET: + /* + * + */ + break; + + default: + bfd_set_error (bfd_error_wrong_format); + return -1; + + } /* switch */ + + return 0; +} + + +/*-----------------------------------------------------------------------------*/ +/* Output routines. */ + + +/* Manufacure a VMS like time on a unix based system. + stolen from obj-vms.c */ + +static unsigned char * +get_vms_time_string () +{ + static unsigned char tbuf[18]; +#ifndef VMS +#include + + 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 (tbuf, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11); +#else +#include + 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 (abfd, objtype) + bfd *abfd; + int objtype; +{ + asymbol *symbol; + int symnum; + int had_case = 0; + int had_file = 0; + + +#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) + { + } + else + { + _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); + } + + if (bfd_get_filename (abfd) != 0) + { + /* strip path and suffix information */ + + char *fname, *fout, *fptr; + + fptr = bfd_get_filename (abfd); + fname = (char *) alloca (strlen (fptr) + 1); + strcpy (fname, fptr); + fout = strrchr (fname, ']'); + if (fout == 0) + fout = strchr (fname, ':'); + if (fout != 0) + fout++; + else + fout = fname; + + /* strip .obj suffix */ + + fptr = strrchr (fname, '.'); + if ((fptr != 0) + && (strcasecmp (fptr, ".OBJ") == 0)) + *fptr = 0; + + fptr = fout; + while (*fptr != 0) + { + if (islower (*fptr)) + *fptr = toupper (*fptr); + fptr++; + if ((*fptr == ';') + || ((fptr - fout) > 31)) + *fptr = 0; + } + _bfd_vms_output_counted (abfd, fout); + } + else + _bfd_vms_output_counted (abfd, "NONAME"); + + _bfd_vms_output_counted (abfd, BFD_VERSION); + _bfd_vms_output_dump (abfd, get_vms_time_string (), 17); + _bfd_vms_output_fill (abfd, 0, 17); + _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 *)"GAS proGIS", 10); + _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) + { + char *s; + + if (strncmp ((char *)symbol->name, "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, strlen (symbol->name)); + if (had_case) + break; + had_file = 1; + } + } + + if (symnum == abfd->symcount) + _bfd_vms_output_dump (abfd, (unsigned char *)"noname", 6); + + _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 *)"TTL", 3); + _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 (abfd, objtype) + 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 + 4); + PRIV(eom_data).eom_b_comcod = *(vms_rec + 8); + if (PRIV(eom_data).eom_b_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 + 9); + PRIV(eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12); + PRIV(eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16); + + abfd->start_address = PRIV(eom_data).eom_l_tfradr; + } + } + return 0; +} + + +/* Write eom record for bfd abfd */ + +int +_bfd_vms_write_eom (abfd, objtype) + 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; +} diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c new file mode 100644 index 00000000000..a5fdae4cc28 --- /dev/null +++ b/bfd/vms-misc.c @@ -0,0 +1,1145 @@ +/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and + EVAX (openVMS/Alpha) files. + Copyright 1996, 1997, 1998 Free Software Foundation, Inc. + + 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 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#if __STDC__ +#include +#endif + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" + +#include "vms.h" + +/*-----------------------------------------------------------------------------*/ +#if VMS_DEBUG +/* debug functions */ + +/* debug function for all vms extensions + evaluates environment variable VMS_DEBUG for a + numerical value on the first call + all error levels below this value are printed + + levels: + 1 toplevel bfd calls (functions from the bfd vector) + 2 functions called by bfd calls + ... + 9 almost everything + + level is also identation level. Indentation is performed + if level > 0 + */ + +#if __STDC__ +void +_bfd_vms_debug (int level, char *format, ...) +{ + static int min_level = -1; + static FILE *output = NULL; + char *eptr; + va_list args; + int abslvl = (level > 0)?level:-level; + + if (min_level == -1) + { + if ((eptr = getenv("VMS_DEBUG")) != NULL) + { + min_level = atoi(eptr); + output = stderr; + } + else + min_level = 0; + } + if (output == NULL) + return; + if (abslvl > min_level) + return; + + while(--level>0) + fprintf(output, " "); + va_start(args, format); + vfprintf(output, format, args); + fflush(output); + va_end(args); + + return; +} + +#else /* not __STDC__ */ + +void +_bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6) + int level; + char *format; + long a1; long a2; long a3; + long a4; long a5; long a6; +{ + static int min_level = -1; + static FILE *output = NULL; + char *eptr; + + if (min_level == -1) + { + if ((eptr = getenv("VMS_DEBUG")) != NULL) + { + min_level = atoi(eptr); + output = stderr; + } + else + min_level = 0; + } + if (output == NULL) + return; + if (level > min_level) + return; + + while(--level>0) + fprintf(output, " "); + fprintf(output, format, a1, a2, a3, a4, a5, a6); + fflush(output); + + return; +} +#endif /* __STDC__ */ + + +/* a debug function + hex dump 'size' bytes starting at 'ptr' */ + +void +_bfd_hexdump (level, ptr, size, offset) + int level; + unsigned char *ptr; + int size; + int offset; +{ + unsigned char *lptr = ptr; + int count = 0; + long start = offset; + + while (size-- > 0) + { + if ((count%16) == 0) + vms_debug (level, "%08lx:", start); + vms_debug (-level, " %02x", *ptr++); + count++; + start++; + if (size == 0) + { + while ((count%16) != 0) + { + vms_debug (-level, " "); + count++; + } + } + if ((count%16) == 0) + { + vms_debug (-level, " "); + while (lptr < ptr) + { + vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr); + lptr++; + } + vms_debug (-level, "\n"); + } + } + if ((count%16) != 0) + vms_debug (-level, "\n"); + + return; +} +#endif + + +/* hash functions + + These are needed when reading an object file. */ + +/* allocate new vms_hash_entry + keep the symbol name and a pointer to the bfd symbol in the table */ + +struct bfd_hash_entry * +_bfd_vms_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + vms_symbol_entry *ret; + +#if VMS_DEBUG + vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string); +#endif + + if (entry == (struct bfd_hash_entry *)NULL) + { + ret = (vms_symbol_entry *) + bfd_hash_allocate (table, sizeof (vms_symbol_entry)); + if (ret == (vms_symbol_entry *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return (struct bfd_hash_entry *)NULL; + } + } + + /* Call the allocation method of the base class. */ + + ret = (vms_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string); +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret); +#endif + + ret->symbol = (asymbol *)NULL; + + return (struct bfd_hash_entry *)ret; +} + + +/* object file input functions */ + +/* Return type and length from record header (buf) on Alpha. */ + +void +_bfd_vms_get_header_values (abfd, buf, type, length) + bfd *abfd; + unsigned char *buf; + int *type; + int *length; +{ + if (type != 0) + *type = bfd_getl16 (buf); + buf += 2; + if (length != 0) + *length = bfd_getl16 (buf); + +#if VMS_DEBUG + vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0)); +#endif + + + return; +} + + +/* Get next record from object file to vms_buf + set PRIV(buf_size) and return it + + this is a little tricky since it should be portable. + + the openVMS object file has 'variable length' which means that + read() returns data in chunks of (hopefully) correct and expected + size. The linker (and other tools on vms) depend on that. Unix doesn't + know about 'formatted' files, so reading and writing such an object + file in a unix environment is not trivial. + + With the tool 'file' (available on all vms ftp sites), one + can view and change the attributes of a file. Changing from + 'variable length' to 'fixed length, 512 bytes' reveals the + record length at the first 2 bytes of every record. The same + happens during the transfer of object files from vms to unix, + at least with ucx, dec's implementation of tcp/ip. + + The vms format repeats the length at bytes 2 & 3 of every record. + + On the first call (file_format == FF_UNKNOWN) we check if + the first and the third byte pair (!) of the record match. + If they do it's an object file in an unix environment or with + wrong attributes (FF_FOREIGN), else we should be in a vms + environment where read() returns the record size (FF_NATIVE). + + reading is always done in 2 steps. + first just the record header is read and the length extracted + by get_header_values + then the read buffer is adjusted and the remaining bytes are + read in. + + all file i/o is always done on even file positions */ + +int +_bfd_vms_get_record (abfd) + bfd *abfd; +{ + int test_len, test_start, remaining; + unsigned char *vms_buf; + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_get_record\n"); +#endif + + /* minimum is 6 bytes on Alpha + (2 bytes length, 2 bytes record id, 2 bytes length repeated) + + on VAX there's no length information in the record + so start with OBJ_S_C_MAXRECSIZ */ + + if (PRIV(buf_size) == 0) + { + if (PRIV(is_vax)) + { + PRIV(vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ); + PRIV(buf_size) = OBJ_S_C_MAXRECSIZ; + PRIV(file_format) = FF_VAX; + } + else + PRIV(vms_buf) = (unsigned char *) malloc (6); + } + + vms_buf = PRIV(vms_buf); + + if (vms_buf == 0) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + + switch (PRIV(file_format)) + { + case FF_UNKNOWN: + case FF_FOREIGN: + test_len = 6; /* probe 6 bytes */ + test_start = 2; /* where the record starts */ + break; + + case FF_NATIVE: + test_len = 4; + test_start = 0; + break; + + case FF_VAX: + test_len = 0; + test_start = 0; + break; + } + + /* skip odd alignment byte */ + + if (bfd_tell (abfd) & 1) + { + if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + } + + /* read the record header on Alpha. */ + + if ((test_len != 0) + && (bfd_read (PRIV(vms_buf), 1, test_len, abfd) != test_len)) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + + /* check file format on first call */ + + if (PRIV(file_format) == FF_UNKNOWN) + { /* record length repeats ? */ + if ( (vms_buf[0] == vms_buf[4]) + && (vms_buf[1] == vms_buf[5])) + { + PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */ + test_start = 2; + } + else + { + PRIV(file_format) = FF_NATIVE; /* N: native environment */ + test_start = 0; + } + } + + if (PRIV(is_vax)) + { + PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), abfd); + if (PRIV(rec_length) <= 0) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + PRIV(vms_rec) = vms_buf; + } + else /* Alpha */ + { + /* extract vms record length */ + + _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL, + &PRIV(rec_length)); + + if (PRIV(rec_length) <= 0) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + + /* that's what the linker manual says */ + + if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + + /* adjust the buffer */ + + if (PRIV(rec_length) > PRIV(buf_size)) + { + PRIV(vms_buf) = (unsigned char *) realloc (vms_buf, PRIV(rec_length)); + vms_buf = PRIV(vms_buf); + if (vms_buf == 0) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + PRIV(buf_size) = PRIV(rec_length); + } + + /* read the remaining record */ + + remaining = PRIV(rec_length) - test_len + test_start; + +#if VMS_DEBUG + vms_debug (10, "bfd_read remaining %d\n", remaining); +#endif + if (bfd_read (vms_buf + test_len, 1, remaining, abfd) != remaining) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } + PRIV(vms_rec) = vms_buf + test_start; + } + +#if VMS_DEBUG + vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length)); +#endif + + return PRIV(rec_length); +} + + +/* get next vms record from file + update vms_rec and rec_length to new (remaining) values */ + +int +_bfd_vms_next_record (abfd) + bfd *abfd; +{ +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n", + PRIV(rec_length), PRIV(rec_size)); +#endif + + if (PRIV(rec_length) > 0) + { + PRIV(vms_rec) += PRIV(rec_size); + } + else + { + if (_bfd_vms_get_record (abfd) <= 0) + return -1; + } + + if (PRIV(is_vax)) + { + PRIV(rec_type) = *(PRIV(vms_rec)); + PRIV(rec_size) = PRIV(rec_length); + } + else + { + _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type), + &PRIV(rec_size)); + } + PRIV(rec_length) -= PRIV(rec_size); + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n", + PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length), + PRIV(rec_type)); +#endif + + return PRIV(rec_type); +} + + + +/* Copy sized string (string with fixed length) to new allocated area + size is string length (size of record) */ + +char * +_bfd_vms_save_sized_string (str, size) + unsigned char *str; + int size; +{ + char *newstr = bfd_malloc (size + 1); + + if (newstr == NULL) + return 0; + strncpy (newstr, (char *)str, size); + newstr[size] = 0; + + return newstr; +} + +/* Copy counted string (string with length at first byte) to new allocated area + ptr points to length byte on entry */ + +char * +_bfd_vms_save_counted_string (ptr) + unsigned char *ptr; +{ + int len = *ptr++; + + return _bfd_vms_save_sized_string (ptr, len); +} + + +/* stack routines for vms ETIR commands */ + +/* Push value and section index */ + +void +_bfd_vms_push (abfd, val, psect) + bfd *abfd; + uquad val; + int psect; +{ + static int last_psect; + +#if VMS_DEBUG + vms_debug (4, "\n", val, psect, PRIV(stackptr)); +#endif + + if (psect >= 0) + last_psect = psect; + + PRIV(stack[PRIV(stackptr)]).value = val; + PRIV(stack[PRIV(stackptr)]).psect = last_psect; + PRIV(stackptr)++; + if (PRIV(stackptr) >= STACKSIZE) + { + bfd_set_error (bfd_error_bad_value); + (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr)); + exit (1); + } + return; +} + + +/* Pop value and section index */ + +uquad +_bfd_vms_pop (abfd, psect) + bfd *abfd; + int *psect; +{ + uquad value; + + if (PRIV(stackptr) == 0) + { + bfd_set_error (bfd_error_bad_value); + (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop")); + exit (1); + } + PRIV(stackptr)--; + value = PRIV(stack[PRIV(stackptr)]).value; + if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0)) + *psect = PRIV(stack[PRIV(stackptr)]).psect; + +#if VMS_DEBUG + vms_debug (4, "\n", value, PRIV(stack[PRIV(stackptr)]).psect); +#endif + + return value; +} + + +/* object file output functions */ + +/* GAS tends to write sections in little chunks (bfd_set_section_contents) + which we can't use directly. So we save the little chunks in linked + lists (one per section) and write them later. */ + +/* Add a new vms_section structure to vms_section_table + - forward chaining - */ + +static vms_section * +add_new_contents (abfd, section) + bfd *abfd; + sec_ptr section; +{ + vms_section *sptr, *newptr; + + sptr = PRIV(vms_section_table)[section->index]; + if (sptr != NULL) + return sptr; + + newptr = (vms_section *) bfd_malloc (sizeof (vms_section)); + if (newptr == (vms_section *) NULL) + return NULL; + newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size); + if (newptr->contents == (unsigned char *)NULL) + return NULL; + newptr->offset = 0; + newptr->size = section->_raw_size; + newptr->next = 0; + PRIV(vms_section_table)[section->index] = newptr; + return newptr; +} + + +/* Save section data & offset to an vms_section structure + vms_section_table[] holds the vms_section chain */ + +boolean +_bfd_save_vms_section (abfd, section, data, offset, count) + bfd *abfd; + sec_ptr section; + PTR data; + file_ptr offset; + bfd_size_type count; +{ + vms_section *sptr; + + if (section->index >= VMS_SECTION_COUNT) + { + bfd_set_error (bfd_error_nonrepresentable_section); + return false; + } + if (count == (bfd_size_type)0) + return true; + sptr = add_new_contents (abfd, section); + if (sptr == NULL) + return false; + memcpy (sptr->contents + offset, data, (size_t) count); + + return true; +} + + +/* Get vms_section pointer to saved contents for section # index */ + +vms_section * +_bfd_get_vms_section (abfd, index) + bfd *abfd; + int index; +{ + if (index >= VMS_SECTION_COUNT) + { + bfd_set_error (bfd_error_nonrepresentable_section); + return NULL; + } + return PRIV(vms_section_table)[index]; +} + + +/* Object output routines */ + +/* Begin new record or record header + write 2 bytes rectype + write 2 bytes record length (filled in at flush) + write 2 bytes header type (ommitted if rechead == -1) */ + +void +_bfd_vms_output_begin (abfd, rectype, rechead) + bfd *abfd; + int rectype; + int rechead; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype, + rechead); +#endif + + _bfd_vms_output_short (abfd,rectype); + + /* save current output position to fill in lenght later */ + + if (PRIV(push_level) > 0) + PRIV(length_pos) = PRIV(output_size); + +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n", + PRIV(length_pos)); +#endif + + _bfd_vms_output_short (abfd,0); /* placeholder for length */ + + if (rechead != -1) + _bfd_vms_output_short (abfd,rechead); + + return; +} + + +/* Set record/subrecord alignment */ + +void +_bfd_vms_output_alignment (abfd, alignto) + bfd *abfd; + int alignto; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto); +#endif + + PRIV(output_alignment) = alignto; + return; +} + + +/* Prepare for subrecord fields */ + +void +_bfd_vms_output_push (abfd) + bfd *abfd; +{ +#if VMS_DEBUG + vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size)); +#endif + + PRIV(push_level)++; + PRIV(pushed_size) = PRIV(output_size); + return; +} + + +/* End of subrecord fields */ + +void +_bfd_vms_output_pop (abfd) + bfd *abfd; +{ +#if VMS_DEBUG + vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size)); +#endif + + _bfd_vms_output_flush (abfd); + PRIV(length_pos) = 2; + +#if VMS_DEBUG + vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos)); +#endif + + PRIV(pushed_size) = 0; + PRIV(push_level)--; + return; +} + + +/* Flush unwritten output, ends current record */ + +void +_bfd_vms_output_flush (abfd) + bfd *abfd; +{ + int real_size = PRIV(output_size); + int aligncount; + int length; + +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n", + real_size, PRIV(pushed_size), PRIV(length_pos)); +#endif + + if (PRIV(push_level) > 0) + length = real_size - PRIV(pushed_size); + else + length = real_size; + + if (length == 0) + return; + aligncount = (PRIV(output_alignment) + - (length % PRIV(output_alignment))) % PRIV(output_alignment); + +#if VMS_DEBUG + vms_debug (6, "align: adding %d bytes\n", aligncount); +#endif + + while(aligncount-- > 0) + { + PRIV(output_buf)[real_size++] = 0; +#if 0 + /* this is why I *love* vms: inconsistency :-} + alignment is added to the subrecord length + but not to the record length */ + if (PRIV(push_level) > 0) +#endif + length++; + } + + /* put length to buffer */ + PRIV(output_size) = PRIV(length_pos); + _bfd_vms_output_short (abfd, (unsigned int)length); + + if (PRIV(push_level) == 0) + { +#ifndef VMS + /* write length first, see FF_FOREIGN in the input routines */ + fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream); +#endif + fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream); + + PRIV(output_size) = 0; + } + else + { + PRIV(output_size) = real_size; + PRIV(pushed_size) = PRIV(output_size); + } + + return; +} + + +/* End record output */ + +void +_bfd_vms_output_end (abfd) + bfd *abfd; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_end\n"); +#endif + + _bfd_vms_output_flush (abfd); + + return; +} + + +/* check remaining buffer size + + return what's left. */ + +int +_bfd_vms_output_check (abfd, size) + bfd *abfd; + int size; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_check(%d)\n", size); +#endif + + return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT)); +} + + +/* Output byte (8 bit) value */ + +void +_bfd_vms_output_byte (abfd, value) + bfd *abfd; + unsigned int value; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value); +#endif + + bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size)); + PRIV(output_size) += 1; + return; +} + + +/* Output short (16 bit) value */ + +void +_bfd_vms_output_short (abfd, value) + bfd *abfd; + unsigned int value; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_short (%04x)\n", value); +#endif + + bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size)); + PRIV(output_size) += 2; + return; +} + + +/* Output long (32 bit) value */ + +void +_bfd_vms_output_long (abfd, value) + bfd *abfd; + unsigned long value; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value); +#endif + + bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size)); + PRIV(output_size) += 4; + return; +} + + +/* Output quad (64 bit) value */ + +void +_bfd_vms_output_quad (abfd, value) + bfd *abfd; + uquad value; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value); +#endif + + bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size)); + PRIV(output_size) += 8; + return; +} + + +/* Output c-string as counted string */ + +void +_bfd_vms_output_counted (abfd, value) + bfd *abfd; + char *value; +{ +int len; + +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_counted(%s)\n", value); +#endif + + len = strlen (value); + if (len == 0) + { + (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes")); + return; + } + if (len > 255) + { + (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes")); + return; + } + _bfd_vms_output_byte (abfd, len & 0xff); + _bfd_vms_output_dump (abfd, (unsigned char *)value, len); +} + + +/* Output character area */ + +void +_bfd_vms_output_dump (abfd, data, length) + bfd *abfd; + unsigned char *data; + int length; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_dump(%d)\n", length); +#endif + + if (length == 0) + return; + + memcpy (PRIV(output_buf) + PRIV(output_size), data, length); + PRIV(output_size) += length; + + return; +} + + +/* Output count bytes of value */ + +void +_bfd_vms_output_fill (abfd, value, count) + bfd *abfd; + int value; + int count; +{ +#if VMS_DEBUG + vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count); +#endif + + if (count == 0) + return; + memset (PRIV(output_buf) + PRIV(output_size), value, count); + PRIV(output_size) += count; + + return; +} + +/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/ + +static int +hash_string (ptr) + const char *ptr; +{ + register const unsigned char *p = (unsigned char *) ptr; + register const unsigned char *end = p + strlen (ptr); + register unsigned char c; + register int hash = 0; + + while (p != end) + { + c = *p++; + hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); + } + return hash; +} + +/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */ + +char * +_bfd_vms_length_hash_symbol (abfd, in, maxlen) + bfd *abfd; + const char *in; + int maxlen; +{ + long int init; + long int result; + int in_len; + char *pnt = 0; + char *new_name; + const char *old_name; + int i; + static char outbuf[EOBJ_S_C_SYMSIZ+1]; + char *out = outbuf; + +#if VMS_DEBUG + vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in); +#endif + + if (maxlen > EOBJ_S_C_SYMSIZ) + maxlen = EOBJ_S_C_SYMSIZ; + + new_name = out; /* save this for later. */ + + /* We may need to truncate the symbol, save the hash for later. */ + + in_len = strlen (in); + + result = (in_len > maxlen) ? hash_string (in) : 0; + + old_name = in; + + /* Do the length checking. */ + + if (in_len <= maxlen) + { + i = in_len; + } + else + { + if (PRIV(flag_hash_long_names)) + i = maxlen-9; + else + i = maxlen; + } + + strncpy (out, in, i); + in += i; + out += i; + + if ((in_len > maxlen) + && PRIV(flag_hash_long_names)) + sprintf (out, "_%08x", result); + else + *out = 0; + +#if VMS_DEBUG + vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf); +#endif + + if (in_len > maxlen + && PRIV(flag_hash_long_names) + && PRIV(flag_show_after_trunc)) + printf (_("Symbol %s replaced by %s\n"), old_name, new_name); + + return outbuf; +} + + +/* Allocate and initialize a new symbol. */ + +static asymbol * +new_symbol (abfd, name) + bfd *abfd; + char *name; +{ + asymbol *symbol; + +#if VMS_DEBUG + _bfd_vms_debug (7, "new_symbol %s\n", name); +#endif + + symbol = _bfd_vms_make_empty_symbol (abfd); + if (symbol == 0) + return symbol; + symbol->name = name; + symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); + + return symbol; +} + + +/* Allocate and enter a new private symbol. */ + +vms_symbol_entry * +_bfd_vms_enter_symbol (abfd, name) + bfd *abfd; + char *name; +{ + vms_symbol_entry *entry; + +#if VMS_DEBUG + _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name); +#endif + + entry = (vms_symbol_entry *) + bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false); + if (entry == 0) + { +#if VMS_DEBUG + _bfd_vms_debug (8, "creating hash entry for %s\n", name); +#endif + entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false); + if (entry != 0) + { + asymbol *symbol; + symbol = new_symbol (abfd, name); + if (symbol != 0) + { + entry->symbol = symbol; + PRIV(gsd_sym_count)++; + abfd->symcount++; + } + else + entry = 0; + } + else + (*_bfd_error_handler) (_("failed to enter %s"), name); + } + else + { +#if VMS_DEBUG + _bfd_vms_debug (8, "found hash entry for %s\n", name); +#endif + } + +#if VMS_DEBUG + _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol); +#endif + return entry; +} diff --git a/bfd/vms-tir.c b/bfd/vms-tir.c new file mode 100644 index 00000000000..782f52bfc04 --- /dev/null +++ b/bfd/vms-tir.c @@ -0,0 +1,2489 @@ +/* vms-tir.c -- BFD back-end for VAX (openVMS/VAX) and + EVAX (openVMS/Alpha) files. + Copyright 1996, 1997, 1998 Free Software Foundation, Inc. + + TIR record handling functions + ETIR record handling functions + + go and read the openVMS linker manual (esp. appendix B) + if you don't know what's going on here :-) + + 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 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* The following type abbreviations are used: + + cs counted string (ascii string with length byte) + by byte (1 byte) + sh short (2 byte, 16 bit) + lw longword (4 byte, 32 bit) + qw quadword (8 byte, 64 bit) + da data stream */ + +#include + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" + +#include "vms.h" + +static void image_set_ptr PARAMS ((bfd *abfd, int psect, uquad offset)); +static void image_inc_ptr PARAMS ((bfd *abfd, uquad offset)); +static void image_dump PARAMS ((bfd *abfd, unsigned char *ptr, int size, int offset)); +static void image_write_b PARAMS ((bfd *abfd, unsigned int value)); +static void image_write_w PARAMS ((bfd *abfd, unsigned int value)); +static void image_write_l PARAMS ((bfd *abfd, unsigned long value)); +static void image_write_q PARAMS ((bfd *abfd, uquad value)); + +/*-----------------------------------------------------------------------------*/ + +static int +check_section (abfd, size) + bfd *abfd; + int size; +{ + int offset; + + offset = PRIV(image_ptr) - PRIV(image_section)->contents; + if ((offset + size) > PRIV(image_section)->_raw_size) + { + PRIV(image_section)->contents = bfd_realloc (PRIV(image_section)->contents, offset + size); + if (PRIV(image_section)->contents == 0) + { + (*_bfd_error_handler) (_("No Mem !")); + return -1; + } + PRIV(image_section)->_raw_size = offset + size; + PRIV(image_ptr) = PRIV(image_section)->contents + offset; + } + + return 0; +} + +/* routines to fill sections contents during tir/etir read */ + +/* Initialize image buffer pointer to be filled */ + +static void +image_set_ptr (abfd, psect, offset) + bfd *abfd; + int psect; + uquad offset; +{ +#if VMS_DEBUG + _bfd_vms_debug (4, "image_set_ptr (%d=%s, %d)\n", + psect, PRIV(sections)[psect]->name, offset); +#endif + + PRIV(image_ptr) = PRIV(sections)[psect]->contents + offset; + PRIV(image_section) = PRIV(sections)[psect]; + return; +} + + +/* Increment image buffer pointer by offset */ + +static void +image_inc_ptr (abfd, offset) + bfd *abfd; + uquad offset; +{ +#if VMS_DEBUG + _bfd_vms_debug (4, "image_inc_ptr (%d)\n", offset); +#endif + + PRIV(image_ptr) += offset; + + return; +} + + +/* Dump multiple bytes to section image */ + +static void +image_dump (abfd, ptr, size, offset) + bfd *abfd; + unsigned char *ptr; + int size; + int offset; +{ +#if VMS_DEBUG + _bfd_vms_debug (8, "image_dump from (%p, %d) to (%p)\n", ptr, size, PRIV(image_ptr)); + _bfd_hexdump (9, ptr, size, offset); +#endif + + if (PRIV(is_vax) && check_section (abfd, size)) + return; + + while (size-- > 0) + *PRIV(image_ptr)++ = *ptr++; + return; +} + + +/* Write byte to section image */ + +static void +image_write_b (abfd, value) + bfd *abfd; + unsigned int value; +{ +#if VMS_DEBUG + _bfd_vms_debug (6, "image_write_b(%02x)\n", (int)value); +#endif + + if (PRIV(is_vax) && check_section (abfd, 1)) + return; + + *PRIV(image_ptr)++ = (value & 0xff); + return; +} + + +/* Write 2-byte word to image */ + +static void +image_write_w (abfd, value) + bfd *abfd; + unsigned int value; +{ +#if VMS_DEBUG + _bfd_vms_debug (6, "image_write_w(%04x)\n", (int)value); +#endif + + if (PRIV(is_vax) && check_section (abfd, 2)) + return; + + bfd_putl16 (value, PRIV(image_ptr)); + PRIV(image_ptr) += 2; + + return; +} + + +/* Write 4-byte long to image */ + +static void +image_write_l (abfd, value) + bfd *abfd; + unsigned long value; +{ +#if VMS_DEBUG + _bfd_vms_debug (6, "image_write_l (%08lx)\n", value); +#endif + + if (PRIV(is_vax) && check_section (abfd, 4)) + return; + + bfd_putl32 (value, PRIV(image_ptr)); + PRIV(image_ptr) += 4; + + return; +} + + +/* Write 8-byte quad to image */ + +static void +image_write_q (abfd, value) + bfd *abfd; + uquad value; +{ +#if VMS_DEBUG + _bfd_vms_debug (6, "image_write_q (%016lx)\n", value); +#endif + + if (PRIV(is_vax) && check_section (abfd, 8)) + return; + + bfd_putl64 (value, PRIV(image_ptr)); + PRIV(image_ptr) += 8; + + return; +} + + +#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L) + +/* etir_sta + + vms stack commands + + handle sta_xxx commands in etir section + ptr points to data area in record + + see table B-8 of the openVMS linker manual */ + +static boolean +etir_sta (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + switch (cmd) + { + /* stack */ + + /* stack global + arg: cs symbol name + + stack 32 bit value of symbol (high bits set to 0) */ + + case ETIR_S_C_STA_GBL: + { + char *name; + vms_symbol_entry *entry; + + name = _bfd_vms_save_counted_string (ptr); + entry = (vms_symbol_entry *) + bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false); + if (entry == (vms_symbol_entry *)NULL) + { +#if VMS_DEBUG + _bfd_vms_debug (3, "ETIR_S_C_STA_GBL: no symbol \"%s\"\n", name); +#endif + _bfd_vms_push (abfd, (uquad)0, -1); + } + else + { + _bfd_vms_push (abfd, (uquad)(entry->symbol->value), -1); + } + } + break; + + /* stack longword + arg: lw value + + stack 32 bit value, sign extend to 64 bit */ + + case ETIR_S_C_STA_LW: + _bfd_vms_push (abfd, (uquad)bfd_getl32 (ptr), -1); + break; + + /* stack global + arg: qw value + + stack 64 bit value of symbol */ + + case ETIR_S_C_STA_QW: + _bfd_vms_push (abfd, (uquad)bfd_getl64(ptr), -1); + break; + + /* stack psect base plus quadword offset + arg: lw section index + qw signed quadword offset (low 32 bits) + + stack qw argument and section index + (see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB) */ + + case ETIR_S_C_STA_PQ: + { + uquad dummy; + int psect; + + psect = bfd_getl32 (ptr); + if (psect >= PRIV(section_count)) + { + (*_bfd_error_handler) (_("Bad section index in ETIR_S_C_STA_PQ")); + bfd_set_error (bfd_error_bad_value); + return false; + } + dummy = bfd_getl64 (ptr+4); + _bfd_vms_push (abfd, dummy, psect); + } + break; + + /* all not supported */ + + case ETIR_S_C_STA_LI: + case ETIR_S_C_STA_MOD: + case ETIR_S_C_STA_CKARG: + + (*_bfd_error_handler) (_("Unsupported STA cmd %d"), cmd); + return false; + break; + + default: + (*_bfd_error_handler) (_("Reserved STA cmd %d"), cmd); + return false; + break; + } +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_sta true\n"); +#endif + return true; +} + + +/* + etir_sto + + vms store commands + + handle sto_xxx commands in etir section + ptr points to data area in record + + see table B-9 of the openVMS linker manual */ + +static boolean +etir_sto (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + uquad dummy; + int psect; + +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_sto %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + switch (cmd) + { + + /* store byte: pop stack, write byte + arg: - */ + + case ETIR_S_C_STO_B: + dummy = _bfd_vms_pop (abfd, &psect); +#if 0 + if (is_share) /* FIXME */ + (*_bfd_error_handler) ("ETIR_S_C_STO_B: byte fixups not supported"); +#endif + image_write_b (abfd, dummy & 0xff); /* FIXME: check top bits */ + break; + + /* store word: pop stack, write word + arg: - */ + + case ETIR_S_C_STO_W: + dummy = _bfd_vms_pop (abfd, &psect); +#if 0 + if (is_share) /* FIXME */ + (*_bfd_error_handler) ("ETIR_S_C_STO_B: word fixups not supported"); +#endif + image_write_w (abfd, dummy & 0xffff); /* FIXME: check top bits */ + break; + + /* store longword: pop stack, write longword + arg: - */ + + case ETIR_S_C_STO_LW: + dummy = _bfd_vms_pop (abfd, &psect); + dummy += (PRIV(sections)[psect])->vma; + image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */ + break; + + /* store quadword: pop stack, write quadword + arg: - */ + + case ETIR_S_C_STO_QW: + dummy = _bfd_vms_pop (abfd, &psect); + dummy += (PRIV(sections)[psect])->vma; + image_write_q (abfd, dummy); /* FIXME: check top bits */ + break; + + /* store immediate repeated: pop stack for repeat count + arg: lw byte count + da data */ + + case ETIR_S_C_STO_IMMR: + { + unsigned long size; + + size = bfd_getl32 (ptr); + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + while (dummy-- > 0L) + image_dump (abfd, ptr+4, size, 0); + } + break; + + /* store global: write symbol value + arg: cs global symbol name */ + + case ETIR_S_C_STO_GBL: + { + vms_symbol_entry *entry; + char *name; + + name = _bfd_vms_save_counted_string (ptr); + entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false); + if (entry == (vms_symbol_entry *)NULL) + { + (*_bfd_error_handler) (_("ETIR_S_C_STO_GBL: no symbol \"%s\""), + name); + return false; + } + else + image_write_q (abfd, (uquad)(entry->symbol->value)); /* FIXME, reloc */ + } + break; + + /* store code address: write address of entry point + arg: cs global symbol name (procedure) */ + + case ETIR_S_C_STO_CA: + { + vms_symbol_entry *entry; + char *name; + + name = _bfd_vms_save_counted_string (ptr); + entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false); + if (entry == (vms_symbol_entry *)NULL) + { + (*_bfd_error_handler) (_("ETIR_S_C_STO_CA: no symbol \"%s\""), + name); + return false; + } + else + image_write_q (abfd, (uquad)(entry->symbol->value)); /* FIXME, reloc */ + } + break; + + /* not supported */ + + case ETIR_S_C_STO_RB: + case ETIR_S_C_STO_AB: + (*_bfd_error_handler) (_("ETIR_S_C_STO_RB/AB: Not supported")); + break; + + /* store offset to psect: pop stack, add low 32 bits to base of psect + arg: - */ + + case ETIR_S_C_STO_OFF: + { + uquad q; + int psect; + + q = _bfd_vms_pop (abfd, &psect); + q += (PRIV(sections)[psect])->vma; + image_write_q (abfd, q); + } + break; + + /* store immediate + arg: lw count of bytes + da data */ + + case ETIR_S_C_STO_IMM: + { + int size; + + size = bfd_getl32 (ptr); + image_dump (abfd, ptr+4, size, 0); + } + break; + + /* this code is 'reserved to digital' according to the openVMS linker manual, + however it is generated by the DEC C compiler and defined in the include file. + FIXME, since the following is just a guess + store global longword: store 32bit value of symbol + arg: cs symbol name */ + + case ETIR_S_C_STO_GBL_LW: + { + vms_symbol_entry *entry; + char *name; + + name = _bfd_vms_save_counted_string (ptr); + entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false); + if (entry == (vms_symbol_entry *)NULL) + { +#if VMS_DEBUG + _bfd_vms_debug (3, "ETIR_S_C_STO_GBL_LW: no symbol \"%s\"\n", name); +#endif + image_write_l (abfd, (unsigned long)0); /* FIXME, reloc */ + } + else + image_write_l (abfd, (unsigned long)(entry->symbol->value)); /* FIXME, reloc */ + } + break; + + /* not supported */ + + case ETIR_S_C_STO_LP_PSB: + (*_bfd_error_handler) (_("ETIR_S_C_STO_LP_PSB: Not supported")); + break; + + /* */ + + case ETIR_S_C_STO_HINT_GBL: + (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_GBL: not implemented")); + break; + + /* */ + + case ETIR_S_C_STO_HINT_PS: + (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_PS: not implemented")); + break; + + default: + (*_bfd_error_handler) (_("Reserved STO cmd %d"), cmd); + break; + } + + return true; +} + +/* stack operator commands + all 32 bit signed arithmetic + all word just like a stack calculator + arguments are popped from stack, results are pushed on stack + + see table B-10 of the openVMS linker manual */ + +static boolean +etir_opr (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + long op1, op2; + +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + switch (cmd) + { + /* operation */ + + /* no-op */ + + case ETIR_S_C_OPR_NOP: + break; + + /* add */ + + case ETIR_S_C_OPR_ADD: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 + op2), -1); + break; + + /* subtract */ + + case ETIR_S_C_OPR_SUB: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op2 - op1), -1); + break; + + /* multiply */ + + case ETIR_S_C_OPR_MUL: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 * op2), -1); + break; + + /* divide */ + + case ETIR_S_C_OPR_DIV: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (op2 == 0) + _bfd_vms_push (abfd, (uquad)0L, -1); + else + _bfd_vms_push (abfd, (uquad)(op2 / op1), -1); + break; + + /* logical and */ + + case ETIR_S_C_OPR_AND: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 & op2), -1); + break; + + /* logical inclusive or */ + + case ETIR_S_C_OPR_IOR: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 | op2), -1); + break; + + /* logical exclusive or */ + + case ETIR_S_C_OPR_EOR: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 ^ op2), -1); + break; + + /* negate */ + + case ETIR_S_C_OPR_NEG: + op1 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(-op1), -1); + break; + + /* complement */ + + case ETIR_S_C_OPR_COM: + op1 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)(op1 ^ -1L), -1); + break; + + /* insert field */ + + case ETIR_S_C_OPR_INSV: + (void)_bfd_vms_pop (abfd, NULL); + (*_bfd_error_handler) (_("ETIR_S_C_OPR_INSV: Not supported")); + break; + + /* arithmetic shift */ + + case ETIR_S_C_OPR_ASH: + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (op2 < 0) /* shift right */ + op1 >>= -op2; + else /* shift left */ + op1 <<= op2; + _bfd_vms_push (abfd, (uquad)op1, -1); + break; + + /* unsigned shift */ + + case ETIR_S_C_OPR_USH: + (*_bfd_error_handler) (_("ETIR_S_C_OPR_USH: Not supported")); + break; + + /* rotate */ + + case ETIR_S_C_OPR_ROT: + (*_bfd_error_handler) (_("ETIR_S_C_OPR_ROT: Not supported")); + break; + + /* select */ + + case ETIR_S_C_OPR_SEL: + if ((long)_bfd_vms_pop (abfd, NULL) & 0x01L) + (void)_bfd_vms_pop (abfd, NULL); + else + { + op1 = (long)_bfd_vms_pop (abfd, NULL); + (void)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (uquad)op1, -1); + } + break; + + /* redefine symbol to current location */ + + case ETIR_S_C_OPR_REDEF: + (*_bfd_error_handler) (_("ETIR_S_C_OPR_REDEF: Not supported")); + break; + + /* define a literal */ + + case ETIR_S_C_OPR_DFLIT: + (*_bfd_error_handler) (_("ETIR_S_C_OPR_DFLIT: Not supported")); + break; + + default: + (*_bfd_error_handler) (_("Reserved OPR cmd %d"), cmd); + break; + } + + return true; +} + + +/* control commands + + see table B-11 of the openVMS linker manual */ + +static boolean +etir_ctl (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + uquad dummy; + int psect; + +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_ctl %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + switch (cmd) + { + /* set relocation base: pop stack, set image location counter + arg: - */ + + case ETIR_S_C_CTL_SETRB: + dummy = _bfd_vms_pop (abfd, &psect); + image_set_ptr (abfd, psect, dummy); + break; + + /* augment relocation base: increment image location counter by offset + arg: lw offset value */ + + case ETIR_S_C_CTL_AUGRB: + dummy = bfd_getl32 (ptr); + image_inc_ptr (abfd, dummy); + break; + + /* define location: pop index, save location counter under index + arg: - */ + + case ETIR_S_C_CTL_DFLOC: + dummy = _bfd_vms_pop (abfd, NULL); + /* FIXME */ + break; + + /* set location: pop index, restore location counter from index + arg: - */ + + case ETIR_S_C_CTL_STLOC: + dummy = _bfd_vms_pop (abfd, &psect); + /* FIXME */ + break; + + /* stack defined location: pop index, push location counter from index + arg: - */ + + case ETIR_S_C_CTL_STKDL: + dummy = _bfd_vms_pop (abfd, &psect); + /* FIXME */ + break; + + default: + (*_bfd_error_handler) (_("Reserved CTL cmd %d"), cmd); + break; + } + return true; +} + + +/* store conditional commands + + see table B-12 and B-13 of the openVMS linker manual */ + +static boolean +etir_stc (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + +#if VMS_DEBUG + _bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + switch (cmd) + { + /* 200 Store-conditional Linkage Pair + arg: */ + + case ETIR_S_C_STC_LP: + (*_bfd_error_handler) (_("ETIR_S_C_STC_LP: not supported")); + break; + + /* 201 Store-conditional Linkage Pair with Procedure Signature + arg: lw linkage index + cs procedure name + by signature length + da signature */ + + case ETIR_S_C_STC_LP_PSB: + image_inc_ptr (abfd, 16); /* skip entry,procval */ + break; + + /* 202 Store-conditional Address at global address + arg: lw linkage index + cs global name */ + + case ETIR_S_C_STC_GBL: + (*_bfd_error_handler) (_("ETIR_S_C_STC_GBL: not supported")); + break; + + /* 203 Store-conditional Code Address at global address + arg: lw linkage index + cs procedure name */ + + case ETIR_S_C_STC_GCA: + (*_bfd_error_handler) (_("ETIR_S_C_STC_GCA: not supported")); + break; + + /* 204 Store-conditional Address at psect + offset + arg: lw linkage index + lw psect index + qw offset */ + + case ETIR_S_C_STC_PS: + (*_bfd_error_handler) (_("ETIR_S_C_STC_PS: not supported")); + break; + + /* 205 Store-conditional NOP at address of global + arg: */ + + case ETIR_S_C_STC_NOP_GBL: + + /* 206 Store-conditional NOP at pect + offset + arg: */ + + case ETIR_S_C_STC_NOP_PS: + + /* 207 Store-conditional BSR at global address + arg: */ + + case ETIR_S_C_STC_BSR_GBL: + + /* 208 Store-conditional BSR at pect + offset + arg: */ + + case ETIR_S_C_STC_BSR_PS: + + /* 209 Store-conditional LDA at global address + arg: */ + + case ETIR_S_C_STC_LDA_GBL: + + /* 210 Store-conditional LDA at psect + offset + arg: */ + + case ETIR_S_C_STC_LDA_PS: + + /* 211 Store-conditional BSR or Hint at global address + arg: */ + + case ETIR_S_C_STC_BOH_GBL: + + /* 212 Store-conditional BSR or Hint at pect + offset + arg: */ + + case ETIR_S_C_STC_BOH_PS: + + /* 213 Store-conditional NOP,BSR or HINT at global address + arg: */ + + case ETIR_S_C_STC_NBH_GBL: + + /* 214 Store-conditional NOP,BSR or HINT at psect + offset + arg: */ + + case ETIR_S_C_STC_NBH_PS: +/* FIXME (*_bfd_error_handler) ("ETIR_S_C_STC_xx: (%d) not supported", cmd); */ + break; + + default: +#if VMS_DEBUG + _bfd_vms_debug (3, "Reserved STC cmd %d", cmd); +#endif + break; + } + return true; +} + + +static asection * +new_section (abfd, idx) + bfd *abfd; + int idx; +{ + asection *section; + char sname[16]; + char *name; + +#if VMS_DEBUG + _bfd_vms_debug (5, "new_section %d\n", idx); +#endif + sprintf (sname, SECTION_NAME_TEMPLATE, idx); + + name = bfd_malloc (strlen (sname) + 1); + if (name == 0) + return 0; + strcpy (name, sname); + + section = bfd_malloc (sizeof (asection)); + if (section == 0) + { +#if VMS_DEBUG + _bfd_vms_debug (6, "bfd_make_section (%s) failed", name); +#endif + return 0; + } + + section->_raw_size = 0; + section->vma = 0; + section->contents = 0; + section->_cooked_size = 0; + section->name = name; + section->index = idx; + + return section; +} + + +static int +alloc_section (abfd, idx) + bfd *abfd; + int idx; +{ + asection *section; + +#if VMS_DEBUG + _bfd_vms_debug (4, "alloc_section %d\n", idx); +#endif + + PRIV(sections) = ((asection **) + bfd_realloc (PRIV(sections), (idx+1) * sizeof (asection *))); + if (PRIV(sections) == 0) + return -1; + + while (PRIV(section_count) <= idx) + { + PRIV(sections)[PRIV(section_count)] = new_section (abfd, PRIV(section_count)); + if (PRIV(sections)[PRIV(section_count)] == 0) + return -1; + PRIV(section_count)++; + } + + return 0; +} + + +/* + * tir_sta + * + * vax stack commands + * + * handle sta_xxx commands in tir section + * ptr points to data area in record + * + * see table 7-3 of the VAX/VMS linker manual + */ + +static unsigned char * +tir_sta (bfd *abfd, unsigned char *ptr) +{ + int cmd = *ptr++; + +#if VMS_DEBUG + _bfd_vms_debug (5, "tir_sta %d\n", cmd); +#endif + + switch (cmd) + { + /* stack */ + case TIR_S_C_STA_GBL: + /* + * stack global + * arg: cs symbol name + * + * stack 32 bit value of symbol (high bits set to 0) + */ + { + char *name; + vms_symbol_entry *entry; + + name = _bfd_vms_save_counted_string (ptr); + + entry = _bfd_vms_enter_symbol (abfd, name); + if (entry == (vms_symbol_entry *)NULL) + return 0; + + _bfd_vms_push (abfd, (unsigned long)(entry->symbol->value), -1); + ptr += *ptr + 1; + } + break; + + case TIR_S_C_STA_SB: + /* + * stack signed byte + * arg: by value + * + * stack byte value, sign extend to 32 bit + */ + _bfd_vms_push (abfd, (long)*ptr++, -1); + break; + + case TIR_S_C_STA_SW: + /* + * stack signed short word + * arg: sh value + * + * stack 16 bit value, sign extend to 32 bit + */ + _bfd_vms_push (abfd, (long)bfd_getl16(ptr), -1); + ptr += 2; + break; + + case TIR_S_C_STA_LW: + /* + * stack signed longword + * arg: lw value + * + * stack 32 bit value + */ + _bfd_vms_push (abfd, (long)bfd_getl32 (ptr), -1); + ptr += 4; + break; + + case TIR_S_C_STA_PB: + case TIR_S_C_STA_WPB: + /* + * stack psect base plus byte offset (word index) + * arg: by section index + * (sh section index) + * by signed byte offset + * + */ + { + unsigned long dummy; + int psect; + + if (cmd == TIR_S_C_STA_PB) + psect = *ptr++; + else + { + psect = bfd_getl16(ptr); + ptr += 2; + } + + if (psect >= PRIV(section_count)) + { + alloc_section (abfd, psect); + } + + dummy = (long)*ptr++; + dummy += (PRIV(sections)[psect])->vma; + _bfd_vms_push (abfd, dummy, psect); + } + break; + + case TIR_S_C_STA_PW: + case TIR_S_C_STA_WPW: + /* + * stack psect base plus word offset (word index) + * arg: by section index + * (sh section index) + * sh signed short offset + * + */ + { + unsigned long dummy; + int psect; + + if (cmd == TIR_S_C_STA_PW) + psect = *ptr++; + else + { + psect = bfd_getl16(ptr); + ptr += 2; + } + + if (psect >= PRIV(section_count)) + { + alloc_section (abfd, psect); + } + + dummy = bfd_getl16(ptr); ptr+=2; + dummy += (PRIV(sections)[psect])->vma; + _bfd_vms_push (abfd, dummy, psect); + } + break; + + case TIR_S_C_STA_PL: + case TIR_S_C_STA_WPL: + /* + * stack psect base plus long offset (word index) + * arg: by section index + * (sh section index) + * lw signed longword offset + * + */ + { + unsigned long dummy; + int psect; + + if (cmd == TIR_S_C_STA_PL) + psect = *ptr++; + else + { + psect = bfd_getl16(ptr); + ptr += 2; + } + + if (psect >= PRIV(section_count)) + { + alloc_section (abfd, psect); + } + + dummy = bfd_getl32 (ptr); ptr += 4; + dummy += (PRIV(sections)[psect])->vma; + _bfd_vms_push (abfd, dummy, psect); + } + break; + + case TIR_S_C_STA_UB: + /* + * stack unsigned byte + * arg: by value + * + * stack byte value + */ + _bfd_vms_push (abfd, (unsigned long)*ptr++, -1); + break; + + case TIR_S_C_STA_UW: + /* + * stack unsigned short word + * arg: sh value + * + * stack 16 bit value + */ + _bfd_vms_push (abfd, (unsigned long)bfd_getl16(ptr), -1); + ptr += 2; + break; + + case TIR_S_C_STA_BFI: + /* + * stack byte from image + * arg: - + * + */ + /*FALLTHRU*/ + case TIR_S_C_STA_WFI: + /* + * stack byte from image + * arg: - + * + */ + /*FALLTHRU*/ + case TIR_S_C_STA_LFI: + /* + * stack byte from image + * arg: - + * + */ + (*_bfd_error_handler) (_("Stack-from-image not implemented")); + return NULL; + + case TIR_S_C_STA_EPM: + /* + * stack entry point mask + * arg: cs symbol name + * + * stack (unsigned) entry point mask of symbol + * err if symbol is no entry point + */ + { + char *name; + vms_symbol_entry *entry; + + name = _bfd_vms_save_counted_string (ptr); + entry = _bfd_vms_enter_symbol (abfd, name); + if (entry == (vms_symbol_entry *)NULL) + return 0; + + (*_bfd_error_handler) (_("Stack-entry-mask not fully implemented")); + _bfd_vms_push (abfd, 0L, -1); + ptr += *ptr + 1; + } + break; + + case TIR_S_C_STA_CKARG: + /* + * compare procedure argument + * arg: cs symbol name + * by argument index + * da argument descriptor + * + * compare argument descriptor with symbol argument (ARG$V_PASSMECH) + * and stack TRUE (args match) or FALSE (args dont match) value + */ + (*_bfd_error_handler) (_("PASSMECH not fully implemented")); + _bfd_vms_push (abfd, 1L, -1); + break; + + case TIR_S_C_STA_LSY: + /* + * stack local symbol value + * arg: sh environment index + * cs symbol name + */ + { + int envidx; + char *name; + vms_symbol_entry *entry; + + envidx = bfd_getl16(ptr); ptr += 2; + name = _bfd_vms_save_counted_string (ptr); + entry = _bfd_vms_enter_symbol (abfd, name); + if (entry == (vms_symbol_entry *)NULL) + return 0; + (*_bfd_error_handler) (_("Stack-local-symbol not fully implemented")); + _bfd_vms_push (abfd, 0L, -1); + ptr += *ptr + 1; + } + break; + + case TIR_S_C_STA_LIT: + /* + * stack literal + * arg: by literal index + * + * stack literal + */ + ptr++; + _bfd_vms_push (abfd, 0L, -1); + (*_bfd_error_handler) (_("Stack-literal not fully implemented")); + break; + + case TIR_S_C_STA_LEPM: + /* + * stack local symbol entry point mask + * arg: sh environment index + * cs symbol name + * + * stack (unsigned) entry point mask of symbol + * err if symbol is no entry point + */ + { + int envidx; + char *name; + vms_symbol_entry *entry; + + envidx = bfd_getl16(ptr); ptr += 2; + name = _bfd_vms_save_counted_string (ptr); + entry = _bfd_vms_enter_symbol (abfd, name); + if (entry == (vms_symbol_entry *)NULL) + return 0; + (*_bfd_error_handler) (_("Stack-local-symbol-entry-point-mask not fully implemented")); + _bfd_vms_push (abfd, 0L, -1); + ptr += *ptr + 1; + } + break; + + default: + (*_bfd_error_handler) (_("Reserved STA cmd %d"), ptr[-1]); + return NULL; + break; + } + + return ptr; +} + + +/* + * tir_sto + * + * vax store commands + * + * handle sto_xxx commands in tir section + * ptr points to data area in record + * + * see table 7-4 of the VAX/VMS linker manual + */ + +static unsigned char * +tir_sto (bfd *abfd, unsigned char *ptr) +{ + unsigned long dummy; + int size; + int psect; + +#if VMS_DEBUG + _bfd_vms_debug (5, "tir_sto %d\n", *ptr); +#endif + + switch (*ptr++) + { + case TIR_S_C_STO_SB: + /* + * store signed byte: pop stack, write byte + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_b (abfd, dummy & 0xff); /* FIXME: check top bits */ + break; + + case TIR_S_C_STO_SW: + /* + * store signed word: pop stack, write word + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_w (abfd, dummy & 0xffff); /* FIXME: check top bits */ + break; + + case TIR_S_C_STO_LW: + /* + * store longword: pop stack, write longword + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */ + break; + + case TIR_S_C_STO_BD: + /* + * store byte displaced: pop stack, sub lc+1, write byte + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + dummy -= ((PRIV(sections)[psect])->vma + 1); + image_write_b (abfd, dummy & 0xff);/* FIXME: check top bits */ + break; + + case TIR_S_C_STO_WD: + /* + * store word displaced: pop stack, sub lc+2, write word + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + dummy -= ((PRIV(sections)[psect])->vma + 2); + image_write_w (abfd, dummy & 0xffff);/* FIXME: check top bits */ + break; + case TIR_S_C_STO_LD: + /* + * store long displaced: pop stack, sub lc+4, write long + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + dummy -= ((PRIV(sections)[psect])->vma + 4); + image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */ + break; + case TIR_S_C_STO_LI: + /* + * store short literal: pop stack, write byte + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_b (abfd, dummy & 0xff);/* FIXME: check top bits */ + break; + case TIR_S_C_STO_PIDR: + /* + * store position independent data reference: pop stack, write longword + * arg: - + * FIXME: incomplete ! + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_l (abfd, dummy & 0xffffffff); + break; + case TIR_S_C_STO_PICR: + /* + * store position independent code reference: pop stack, write longword + * arg: - + * FIXME: incomplete ! + */ + dummy = _bfd_vms_pop (abfd, &psect); + image_write_b (abfd, 0x9f); + image_write_l (abfd, dummy & 0xffffffff); + break; + case TIR_S_C_STO_RIVB: + /* + * store repeated immediate variable bytes + * 1-byte count n field followed by n bytes of data + * pop stack, write n bytes times + */ + size = *ptr++; + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + while (dummy-- > 0L) + image_dump (abfd, ptr, size, 0); + ptr += size; + break; + case TIR_S_C_STO_B: + /* + * store byte from top longword + */ + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + image_write_b (abfd, dummy & 0xff); + break; + case TIR_S_C_STO_W: + /* + * store word from top longword + */ + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + image_write_w (abfd, dummy & 0xffff); + break; + case TIR_S_C_STO_RB: + /* + * store repeated byte from top longword + */ + size = (unsigned long)_bfd_vms_pop (abfd, NULL); + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + while (size-- > 0) + image_write_b (abfd, dummy & 0xff); + break; + case TIR_S_C_STO_RW: + /* + * store repeated word from top longword + */ + size = (unsigned long)_bfd_vms_pop (abfd, NULL); + dummy = (unsigned long)_bfd_vms_pop (abfd, NULL); + while (size-- > 0) + image_write_w (abfd, dummy & 0xffff); + break; + + case TIR_S_C_STO_RSB: + case TIR_S_C_STO_RSW: + case TIR_S_C_STO_RL: + case TIR_S_C_STO_VPS: + case TIR_S_C_STO_USB: + case TIR_S_C_STO_USW: + case TIR_S_C_STO_RUB: + case TIR_S_C_STO_RUW: + case TIR_S_C_STO_PIRR: + (*_bfd_error_handler) (_("Unimplemented STO cmd %d"), ptr[-1]); + break; + + default: + (*_bfd_error_handler) (_("Reserved STO cmd %d"), ptr[-1]); + break; + } + + return ptr; +} + + +/* + * stack operator commands + * all 32 bit signed arithmetic + * all word just like a stack calculator + * arguments are popped from stack, results are pushed on stack + * + * see table 7-5 of the VAX/VMS linker manual + */ + +static unsigned char * +tir_opr (bfd *abfd, unsigned char *ptr) +{ + long op1, op2; + +#if VMS_DEBUG + _bfd_vms_debug (5, "tir_opr %d\n", *ptr); +#endif + + switch (*ptr++) + { + /* operation */ + case TIR_S_C_OPR_NOP: + /* + * no-op + */ + break; + + case TIR_S_C_OPR_ADD: + /* + * add + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 + op2), -1); + break; + + case TIR_S_C_OPR_SUB: + /* + * subtract + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op2 - op1), -1); + break; + + case TIR_S_C_OPR_MUL: + /* + * multiply + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 * op2), -1); + break; + + case TIR_S_C_OPR_DIV: + /* + * divide + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (op2 == 0) + _bfd_vms_push (abfd, (unsigned long)0L, -1); + else + _bfd_vms_push (abfd, (unsigned long)(op2 / op1), -1); + break; + + case TIR_S_C_OPR_AND: + /* + * logical and + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 & op2), -1); + break; + + case TIR_S_C_OPR_IOR: + op1 = (long)_bfd_vms_pop (abfd, NULL); + /* + * logical inclusive or + */ + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 | op2), -1); + break; + + case TIR_S_C_OPR_EOR: + /* + * logical exclusive or + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 ^ op2), -1); + break; + + case TIR_S_C_OPR_NEG: + /* + * negate + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(-op1), -1); + break; + + case TIR_S_C_OPR_COM: + /* + * complement + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)(op1 ^ -1L), -1); + break; + + case TIR_S_C_OPR_INSV: + /* + * insert field + */ + (void)_bfd_vms_pop (abfd, NULL); + (*_bfd_error_handler) ("TIR_S_C_OPR_INSV incomplete"); + break; + + case TIR_S_C_OPR_ASH: + /* + * arithmetic shift + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (HIGHBIT(op1)) /* shift right */ + op2 >>= op1; + else /* shift left */ + op2 <<= op1; + _bfd_vms_push (abfd, (unsigned long)op2, -1); + (*_bfd_error_handler) (_("TIR_S_C_OPR_ASH incomplete")); + break; + + case TIR_S_C_OPR_USH: + /* + * unsigned shift + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (HIGHBIT(op1)) /* shift right */ + op2 >>= op1; + else /* shift left */ + op2 <<= op1; + _bfd_vms_push (abfd, (unsigned long)op2, -1); + (*_bfd_error_handler) (_("TIR_S_C_OPR_USH incomplete")); + break; + + case TIR_S_C_OPR_ROT: + /* + * rotate + */ + op1 = (long)_bfd_vms_pop (abfd, NULL); + op2 = (long)_bfd_vms_pop (abfd, NULL); + if (HIGHBIT(0)) /* shift right */ + op2 >>= op1; + else /* shift left */ + op2 <<= op1; + _bfd_vms_push (abfd, (unsigned long)op2, -1); + (*_bfd_error_handler) (_("TIR_S_C_OPR_ROT incomplete")); + break; + + case TIR_S_C_OPR_SEL: + /* + * select + */ + if ((long)_bfd_vms_pop (abfd, NULL) & 0x01L) + (void)_bfd_vms_pop (abfd, NULL); + else + { + op1 = (long)_bfd_vms_pop (abfd, NULL); + (void)_bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, (unsigned long)op1, -1); + } + break; + + case TIR_S_C_OPR_REDEF: + /* + * redefine symbol to current location + */ + (*_bfd_error_handler) (_("TIR_S_C_OPR_REDEF not supported")); + break; + + case TIR_S_C_OPR_DFLIT: + /* + * define a literal + */ + (*_bfd_error_handler) (_("TIR_S_C_OPR_DFLIT not supported")); + break; + + default: + (*_bfd_error_handler) (_("Reserved OPR cmd %d"), ptr[-1]); + break; + } + + return ptr; +} + + +static unsigned char * +tir_ctl (bfd *abfd, unsigned char *ptr) +/* + * control commands + * + * see table 7-6 of the VAX/VMS linker manual + */ +{ + unsigned long dummy; + int psect; + +#if VMS_DEBUG + _bfd_vms_debug (5, "tir_ctl %d\n", *ptr); +#endif + + switch (*ptr++) + { + case TIR_S_C_CTL_SETRB: + /* + * set relocation base: pop stack, set image location counter + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + if (psect >= PRIV(section_count)) + { + alloc_section (abfd, psect); + } + image_set_ptr (abfd, psect, dummy); + break; + case TIR_S_C_CTL_AUGRB: + /* + * augment relocation base: increment image location counter by offset + * arg: lw offset value + */ + dummy = bfd_getl32 (ptr); + image_inc_ptr (abfd, dummy); + break; + case TIR_S_C_CTL_DFLOC: + /* + * define location: pop index, save location counter under index + * arg: - + */ + dummy = _bfd_vms_pop (abfd, NULL); + (*_bfd_error_handler) (_("TIR_S_C_CTL_DFLOC not fully implemented")); + break; + case TIR_S_C_CTL_STLOC: + /* + * set location: pop index, restore location counter from index + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + (*_bfd_error_handler) (_("TIR_S_C_CTL_STLOC not fully implemented")); + break; + case TIR_S_C_CTL_STKDL: + /* + * stack defined location: pop index, push location counter from index + * arg: - + */ + dummy = _bfd_vms_pop (abfd, &psect); + (*_bfd_error_handler) (_("TIR_S_C_CTL_STKDL not fully implemented")); + break; + default: + (*_bfd_error_handler) (_("Reserved CTL cmd %d"), ptr[-1]); + break; + } + return ptr; +} + + +/* + * handle command from TIR section + */ + +static unsigned char * +tir_cmd (bfd *abfd, unsigned char *ptr) +{ + struct { + int mincod; + int maxcod; + unsigned char * (*explain)(bfd *, unsigned char *); + } tir_table[] = { + { 0, TIR_S_C_MAXSTACOD, tir_sta } + ,{ TIR_S_C_MINSTOCOD, TIR_S_C_MAXSTOCOD, tir_sto } + ,{ TIR_S_C_MINOPRCOD, TIR_S_C_MAXOPRCOD, tir_opr } + ,{ TIR_S_C_MINCTLCOD, TIR_S_C_MAXCTLCOD, tir_ctl } + ,{ -1, -1, NULL } + }; + int i = 0; + +#if VMS_DEBUG + _bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + if (*ptr & 0x80) /* store immediate */ + { + i = 128 - (*ptr++ & 0x7f); + image_dump (abfd, ptr, i, 0); + ptr += i; + } + else + { + while (tir_table[i].mincod >= 0) + { + if ( (tir_table[i].mincod <= *ptr) + && (*ptr <= tir_table[i].maxcod)) + { + ptr = tir_table[i].explain (abfd, ptr); + break; + } + i++; + } + if (tir_table[i].mincod < 0) + { + (*_bfd_error_handler) (_("Obj code %d not found"), *ptr); + ptr = 0; + } + } + + return ptr; +} + + +/* handle command from ETIR section */ + +static int +etir_cmd (abfd, cmd, ptr) + bfd *abfd; + int cmd; + unsigned char *ptr; +{ + static struct { + int mincod; + int maxcod; + boolean (*explain) PARAMS((bfd *, int, unsigned char *)); + } etir_table[] = { + { ETIR_S_C_MINSTACOD, ETIR_S_C_MAXSTACOD, etir_sta }, + { ETIR_S_C_MINSTOCOD, ETIR_S_C_MAXSTOCOD, etir_sto }, + { ETIR_S_C_MINOPRCOD, ETIR_S_C_MAXOPRCOD, etir_opr }, + { ETIR_S_C_MINCTLCOD, ETIR_S_C_MAXCTLCOD, etir_ctl }, + { ETIR_S_C_MINSTCCOD, ETIR_S_C_MAXSTCCOD, etir_stc }, + { -1, -1, NULL } + }; + + int i = 0; + +#if VMS_DEBUG + _bfd_vms_debug (4, "etir_cmd %d/%x\n", cmd, cmd); + _bfd_hexdump (8, ptr, 16, (int)ptr); +#endif + + while (etir_table[i].mincod >= 0) + { + if ( (etir_table[i].mincod <= cmd) + && (cmd <= etir_table[i].maxcod)) + { + if (!etir_table[i].explain (abfd, cmd, ptr)) + return -1; + break; + } + i++; + } + +#if VMS_DEBUG + _bfd_vms_debug (4, "etir_cmd: = 0\n"); +#endif + return 0; +} + + +/* Text Information and Relocation Records (OBJ$C_TIR) + handle tir record */ + +static int +analyze_tir (abfd, ptr, length) + bfd *abfd; + unsigned char *ptr; + unsigned int length; +{ + unsigned char *maxptr; + +#if VMS_DEBUG + _bfd_vms_debug (3, "analyze_tir: %d bytes\n", length); +#endif + + maxptr = ptr + length; + + while (ptr < maxptr) + { + ptr = tir_cmd (abfd, ptr); + if (ptr == 0) + return -1; + } + + return 0; +} + + +/* Text Information and Relocation Records (EOBJ$C_ETIR) + handle etir record */ + +static int +analyze_etir (abfd, ptr, length) + bfd *abfd; + unsigned char *ptr; + unsigned int length; +{ + int cmd; + unsigned char *maxptr; + int result = 0; + +#if VMS_DEBUG + _bfd_vms_debug (3, "analyze_etir: %d bytes\n", length); +#endif + + maxptr = ptr + length; + + while (ptr < maxptr) + { + cmd = bfd_getl16 (ptr); + length = bfd_getl16 (ptr + 2); + result = etir_cmd (abfd, cmd, ptr+4); + if (result != 0) + break; + ptr += length; + } + +#if VMS_DEBUG + _bfd_vms_debug (3, "analyze_etir: = %d\n", result); +#endif + + return result; +} + + +/* process ETIR record + + return 0 on success, -1 on error */ + +int +_bfd_vms_slurp_tir (abfd, objtype) + bfd *abfd; + int objtype; +{ + int result; + +#if VMS_DEBUG + _bfd_vms_debug (2, "TIR/ETIR\n"); +#endif + + switch (objtype) + { + case EOBJ_S_C_ETIR: + PRIV(vms_rec) += 4; /* skip type, size */ + PRIV(rec_size) -= 4; + result = analyze_etir (abfd, PRIV(vms_rec), PRIV(rec_size)); + break; + case OBJ_S_C_TIR: + PRIV(vms_rec) += 1; /* skip type */ + PRIV(rec_size) -= 1; + result = analyze_tir (abfd, PRIV(vms_rec), PRIV(rec_size)); + break; + default: + result = -1; + break; + } + + return result; +} + + +/* process EDBG record + return 0 on success, -1 on error + + not implemented yet */ + +int +_bfd_vms_slurp_dbg (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "DBG/EDBG\n"); +#endif + + abfd->flags |= (HAS_DEBUG | HAS_LINENO); + return 0; +} + + +/* process ETBT record + return 0 on success, -1 on error + + not implemented yet */ + +int +_bfd_vms_slurp_tbt (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "TBT/ETBT\n"); +#endif + + return 0; +} + + +/* process LNK record + return 0 on success, -1 on error + + not implemented yet */ + +int +_bfd_vms_slurp_lnk (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "LNK\n"); +#endif + + return 0; +} + +/*----------------------------------------------------------------------*/ +/* */ +/* WRITE ETIR SECTION */ +/* */ +/* this is still under construction and therefore not documented */ +/* */ +/*----------------------------------------------------------------------*/ + +static void start_etir_record PARAMS ((bfd *abfd, int index, uquad offset, boolean justoffset)); +static void sto_imm PARAMS ((bfd *abfd, vms_section *sptr, bfd_vma vaddr, int index)); +static void end_etir_record PARAMS ((bfd *abfd)); + +static void +sto_imm (abfd, sptr, vaddr, index) + bfd *abfd; + vms_section *sptr; + bfd_vma vaddr; + int index; +{ + int size; + int ssize; + unsigned char *cptr; + +#if VMS_DEBUG + _bfd_vms_debug (8, "sto_imm %d bytes\n", sptr->size); + _bfd_hexdump (9, sptr->contents, (int)sptr->size, (int)vaddr); +#endif + + ssize = sptr->size; + cptr = sptr->contents; + + while (ssize > 0) + { + + size = ssize; /* try all the rest */ + + if (_bfd_vms_output_check (abfd, size) < 0) + { /* doesn't fit, split ! */ + end_etir_record (abfd); + start_etir_record (abfd, index, vaddr, false); + size = _bfd_vms_output_check (abfd, 0); /* get max size */ + if (size > ssize) /* more than what's left ? */ + size = ssize; + } + + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_IMM, -1); + _bfd_vms_output_long (abfd, (unsigned long)(size)); + _bfd_vms_output_dump (abfd, cptr, size); + _bfd_vms_output_flush (abfd); + +#if VMS_DEBUG + _bfd_vms_debug (10, "dumped %d bytes\n", size); + _bfd_hexdump (10, cptr, (int)size, (int)vaddr); +#endif + + vaddr += size; + ssize -= size; + cptr += size; + } + + return; +} + +/*-------------------------------------------------------------------*/ + +/* start ETIR record for section #index at virtual addr offset. */ + +static void +start_etir_record (abfd, index, offset, justoffset) + bfd *abfd; + int index; + uquad offset; + boolean justoffset; +{ + if (!justoffset) + { + _bfd_vms_output_begin (abfd, EOBJ_S_C_ETIR, -1); /* one ETIR per section */ + _bfd_vms_output_push (abfd); + } + + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1); /* push start offset */ + _bfd_vms_output_long (abfd, (unsigned long)index); + _bfd_vms_output_quad (abfd, (uquad)offset); + _bfd_vms_output_flush (abfd); + + _bfd_vms_output_begin (abfd, ETIR_S_C_CTL_SETRB, -1); /* start = pop () */ + _bfd_vms_output_flush (abfd); + + return; +} + + +/* end etir record */ +static void +end_etir_record (abfd) + bfd *abfd; +{ + _bfd_vms_output_pop (abfd); + _bfd_vms_output_end (abfd); +} + +/* write section contents for bfd abfd */ + +int +_bfd_vms_write_tir (abfd, objtype) + bfd *abfd; + int objtype; +{ + asection *section; + vms_section *sptr; + int nextoffset; + +#if VMS_DEBUG + _bfd_vms_debug (2, "vms_write_tir (%p, %d)\n", abfd, objtype); +#endif + + _bfd_vms_output_alignment (abfd, 4); + + nextoffset = 0; + PRIV(vms_linkage_index) = 1; + + /* dump all other sections */ + + section = abfd->sections; + + while (section != NULL) + { + +#if VMS_DEBUG + _bfd_vms_debug (4, "writing %d. section '%s' (%d bytes)\n", section->index, section->name, (int)(section->_raw_size)); +#endif + + if (section->flags & SEC_RELOC) + { + int i; + + if ((i = section->reloc_count) <= 0) + { + (*_bfd_error_handler) (_("SEC_RELOC with no relocs in section %s"), + section->name); + } +#if VMS_DEBUG + else + { + arelent **rptr; + _bfd_vms_debug (4, "%d relocations:\n", i); + rptr = section->orelocation; + while (i-- > 0) + { + _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, addr %08lx, off %08lx, len %d: %s\n", + (*(*rptr)->sym_ptr_ptr)->name, + (*(*rptr)->sym_ptr_ptr)->section->name, + (long)(*(*rptr)->sym_ptr_ptr)->value, + (*rptr)->address, (*rptr)->addend, + bfd_get_reloc_size((*rptr)->howto), + (*rptr)->howto->name); + rptr++; + } + } +#endif + } + + if ((section->flags & SEC_HAS_CONTENTS) + && (! bfd_is_com_section (section))) + { + bfd_vma vaddr; /* virtual addr in section */ + + sptr = _bfd_get_vms_section (abfd, section->index); + if (sptr == NULL) + { + bfd_set_error (bfd_error_no_contents); + return -1; + } + + vaddr = (bfd_vma)(sptr->offset); + + start_etir_record (abfd, section->index, (uquad) sptr->offset, + false); + + while (sptr != NULL) /* one STA_PQ, CTL_SETRB per vms_section */ + { + + if (section->flags & SEC_RELOC) /* check for relocs */ + { + arelent **rptr = section->orelocation; + int i = section->reloc_count; + for (;;) + { + bfd_size_type addr = (*rptr)->address; + int len = bfd_get_reloc_size ((*rptr)->howto); + if (sptr->offset < addr) /* sptr starts before reloc */ + { + int before = addr - sptr->offset; + if (sptr->size <= before) /* complete before */ + { + sto_imm (abfd, sptr, vaddr, section->index); + vaddr += sptr->size; + break; + } + else /* partly before */ + { + int after = sptr->size - before; + sptr->size = before; + sto_imm (abfd, sptr, vaddr, section->index); + vaddr += sptr->size; + sptr->contents += before; + sptr->offset += before; + sptr->size = after; + } + } + else if (sptr->offset == addr) /* sptr starts at reloc */ + { + asymbol *sym = *(*rptr)->sym_ptr_ptr; + asection *sec = sym->section; + + switch ((*rptr)->howto->type) + { + case ALPHA_R_IGNORE: + break; + + case ALPHA_R_REFLONG: + { + if (bfd_is_und_section (sym->section)) + { + if (_bfd_vms_output_check (abfd, + strlen((char *)sym->name)) + < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_GBL_LW, + -1); + _bfd_vms_output_counted (abfd, + _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + } + else if (bfd_is_abs_section (sym->section)) + { + if (_bfd_vms_output_check (abfd, 16) < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STA_LW, + -1); + _bfd_vms_output_quad (abfd, + (uquad)sym->value); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_LW, + -1); + _bfd_vms_output_flush (abfd); + } + else + { + if (_bfd_vms_output_check (abfd, 32) < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STA_PQ, + -1); + _bfd_vms_output_long (abfd, + (unsigned long)(sec->index)); + _bfd_vms_output_quad (abfd, + ((uquad)(*rptr)->addend + + (uquad)sym->value)); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_LW, + -1); + _bfd_vms_output_flush (abfd); + } + } + break; + + case ALPHA_R_REFQUAD: + { + if (bfd_is_und_section (sym->section)) + { + if (_bfd_vms_output_check (abfd, + strlen((char *)sym->name)) + < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_GBL, + -1); + _bfd_vms_output_counted (abfd, + _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + } + else if (bfd_is_abs_section (sym->section)) + { + if (_bfd_vms_output_check (abfd, 16) < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STA_QW, + -1); + _bfd_vms_output_quad (abfd, + (uquad)sym->value); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_QW, + -1); + _bfd_vms_output_flush (abfd); + } + else + { + if (_bfd_vms_output_check (abfd, 32) < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STA_PQ, + -1); + _bfd_vms_output_long (abfd, + (unsigned long)(sec->index)); + _bfd_vms_output_quad (abfd, + ((uquad)(*rptr)->addend + + (uquad)sym->value)); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_OFF, + -1); + _bfd_vms_output_flush (abfd); + } + } + break; + + case ALPHA_R_HINT: + { + int hint_size; + + hint_size = sptr->size; + sptr->size = len; + sto_imm (abfd, sptr, vaddr, section->index); + sptr->size = hint_size; +#if 0 + vms_output_begin(abfd, ETIR_S_C_STO_HINT_GBL, -1); + vms_output_long(abfd, (unsigned long)(sec->index)); + vms_output_quad(abfd, (uquad)addr); + + vms_output_counted(abfd, _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); + vms_output_flush(abfd); +#endif + } + break; + case ALPHA_R_LINKAGE: + { + if (_bfd_vms_output_check (abfd, 64) < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STC_LP_PSB, + -1); + _bfd_vms_output_long (abfd, + (unsigned long)PRIV(vms_linkage_index)); + PRIV(vms_linkage_index) += 2; + _bfd_vms_output_counted (abfd, + _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_byte (abfd, 0); + _bfd_vms_output_flush (abfd); + } + break; + + case ALPHA_R_CODEADDR: + { + if (_bfd_vms_output_check (abfd, + strlen((char *)sym->name)) + < 0) + { + end_etir_record (abfd); + start_etir_record (abfd, + section->index, + vaddr, false); + } + _bfd_vms_output_begin (abfd, + ETIR_S_C_STO_CA, + -1); + _bfd_vms_output_counted (abfd, + _bfd_vms_length_hash_symbol (abfd, sym->name, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + } + break; + + default: + (*_bfd_error_handler) (_("Unhandled relocation %s"), + (*rptr)->howto->name); + break; + } + + vaddr += len; + + if (len == sptr->size) + { + break; + } + else + { + sptr->contents += len; + sptr->offset += len; + sptr->size -= len; + i--; + rptr++; + } + } + else /* sptr starts after reloc */ + { + i--; /* check next reloc */ + rptr++; + } + + if (i==0) /* all reloc checked */ + { + if (sptr->size > 0) + { + sto_imm (abfd, sptr, vaddr, section->index); /* dump rest */ + vaddr += sptr->size; + } + break; + } + } /* for (;;) */ + } /* if SEC_RELOC */ + else /* no relocs, just dump */ + { + sto_imm (abfd, sptr, vaddr, section->index); + vaddr += sptr->size; + } + + sptr = sptr->next; + + } /* while (sptr != 0) */ + + end_etir_record (abfd); + + } /* has_contents */ + + section = section->next; + } + + _bfd_vms_output_alignment(abfd, 2); + return 0; +} + + +/* write traceback data for bfd abfd */ + +int +_bfd_vms_write_tbt (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype); +#endif + + return 0; +} + + +/* write debug info for bfd abfd */ + +int +_bfd_vms_write_dbg (abfd, objtype) + bfd *abfd; + int objtype; +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "vms_write_dbg (%p, objtype)\n", abfd, objtype); +#endif + + return 0; +} diff --git a/bfd/vms.h b/bfd/vms.h new file mode 100644 index 00000000000..d6bdd02a720 --- /dev/null +++ b/bfd/vms.h @@ -0,0 +1,675 @@ +#undef vms +/* vms.h -- Header file for VMS (Alpha and Vax) support. + Copyright 1996, 1997 Free Software Foundation, Inc. + + Written by Klaus K"ampf (kkaempf@rmi.de) + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef VMS_H +#define VMS_H + + +/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object language) */ + +/* VMS Text, information and relocation record (TIR/ETIR) definitions. */ + +#define TIR_S_C_STA_GBL 0 +#define TIR_S_C_STA_SB 1 +#define TIR_S_C_STA_SW 2 +#define TIR_S_C_STA_LW 3 +#define TIR_S_C_STA_PB 4 +#define TIR_S_C_STA_PW 5 +#define TIR_S_C_STA_PL 6 +#define TIR_S_C_STA_UB 7 +#define TIR_S_C_STA_UW 8 +#define TIR_S_C_STA_BFI 9 +#define TIR_S_C_STA_WFI 10 +#define TIR_S_C_STA_LFI 11 +#define TIR_S_C_STA_EPM 12 +#define TIR_S_C_STA_CKARG 13 +#define TIR_S_C_STA_WPB 14 +#define TIR_S_C_STA_WPW 15 +#define TIR_S_C_STA_WPL 16 +#define TIR_S_C_STA_LSY 17 +#define TIR_S_C_STA_LIT 18 +#define TIR_S_C_STA_LEPM 19 +#define TIR_S_C_MAXSTACOD 19 +#define TIR_S_C_MINSTOCOD 20 +#define TIR_S_C_STO_SB 20 +#define TIR_S_C_STO_SW 21 +#define TIR_S_C_STO_L 22 +#define TIR_S_C_STO_LW 22 +#define TIR_S_C_STO_BD 23 +#define TIR_S_C_STO_WD 24 +#define TIR_S_C_STO_LD 25 +#define TIR_S_C_STO_LI 26 +#define TIR_S_C_STO_PIDR 27 +#define TIR_S_C_STO_PICR 28 +#define TIR_S_C_STO_RSB 29 +#define TIR_S_C_STO_RSW 30 +#define TIR_S_C_STO_RL 31 +#define TIR_S_C_STO_VPS 32 +#define TIR_S_C_STO_USB 33 +#define TIR_S_C_STO_USW 34 +#define TIR_S_C_STO_RUB 35 +#define TIR_S_C_STO_RUW 36 +#define TIR_S_C_STO_B 37 +#define TIR_S_C_STO_W 38 +#define TIR_S_C_STO_RB 39 +#define TIR_S_C_STO_RW 40 +#define TIR_S_C_STO_RIVB 41 +#define TIR_S_C_STO_PIRR 42 +#define TIR_S_C_MAXSTOCOD 42 +#define TIR_S_C_MINOPRCOD 50 +#define TIR_S_C_OPR_NOP 50 +#define TIR_S_C_OPR_ADD 51 +#define TIR_S_C_OPR_SUB 52 +#define TIR_S_C_OPR_MUL 53 +#define TIR_S_C_OPR_DIV 54 +#define TIR_S_C_OPR_AND 55 +#define TIR_S_C_OPR_IOR 56 +#define TIR_S_C_OPR_EOR 57 +#define TIR_S_C_OPR_NEG 58 +#define TIR_S_C_OPR_COM 59 +#define TIR_S_C_OPR_INSV 60 +#define TIR_S_C_OPR_ASH 61 +#define TIR_S_C_OPR_USH 62 +#define TIR_S_C_OPR_ROT 63 +#define TIR_S_C_OPR_SEL 64 +#define TIR_S_C_OPR_REDEF 65 +#define TIR_S_C_OPR_DFLIT 66 +#define TIR_S_C_MAXOPRCOD 66 +#define TIR_S_C_MINCTLCOD 80 +#define TIR_S_C_CTL_SETRB 80 +#define TIR_S_C_CTL_AUGRB 81 +#define TIR_S_C_CTL_DFLOC 82 +#define TIR_S_C_CTL_STLOC 83 +#define TIR_S_C_CTL_STKDL 84 +#define TIR_S_C_MAXCTLCOD 84 + +#define ETIR_S_C_MINSTACOD 0 /* Minimum store code */ +#define ETIR_S_C_STA_GBL 0 /* Stack global symbol value */ +#define ETIR_S_C_STA_LW 1 /* Stack longword */ +#define ETIR_S_C_STA_QW 2 /* Stack quadword */ +#define ETIR_S_C_STA_PQ 3 /* Stack psect base plus quadword offset */ +#define ETIR_S_C_STA_LI 4 /* Stack literal */ +#define ETIR_S_C_STA_MOD 5 /* Stack module */ +#define ETIR_S_C_STA_CKARG 6 /* Check Arguments */ +#define ETIR_S_C_MAXSTACOD 6 /* Maximum stack code */ +#define ETIR_S_C_MINSTOCOD 50 /* Minimum store code */ +#define ETIR_S_C_STO_B 50 /* Store byte */ +#define ETIR_S_C_STO_W 51 /* Store word */ +#define ETIR_S_C_STO_LW 52 /* Store longword */ +#define ETIR_S_C_STO_QW 53 /* Store quadword */ +#define ETIR_S_C_STO_IMMR 54 /* Store immediate Repeated */ +#define ETIR_S_C_STO_GBL 55 /* Store global */ +#define ETIR_S_C_STO_CA 56 /* Store code address */ +#define ETIR_S_C_STO_RB 57 /* Store relative branch */ +#define ETIR_S_C_STO_AB 58 /* Store absolute branch */ +#define ETIR_S_C_STO_OFF 59 /* Store offset within psect */ +#define ETIR_S_C_STO_IMM 61 /* Store immediate */ +#define ETIR_S_C_STO_GBL_LW 62 /* Store global Longword */ +#define ETIR_S_C_STO_LP_PSB 63 /* STO_LP_PSB not valid in level 2 use STC_LP_PSB */ +#define ETIR_S_C_STO_HINT_GBL 64 /* Store 14 bit HINT at global address */ +#define ETIR_S_C_STO_HINT_PS 65 /* Store 14 bit HINT at psect + offset */ +#define ETIR_S_C_MAXSTOCOD 65 /* Maximum store code */ +#define ETIR_S_C_MINOPRCOD 100 /* Minimum operate code */ +#define ETIR_S_C_OPR_NOP 100 /* No-op */ +#define ETIR_S_C_OPR_ADD 101 /* Add */ +#define ETIR_S_C_OPR_SUB 102 /* Subtract */ +#define ETIR_S_C_OPR_MUL 103 /* Multiply */ +#define ETIR_S_C_OPR_DIV 104 /* Divide */ +#define ETIR_S_C_OPR_AND 105 /* Logical AND */ +#define ETIR_S_C_OPR_IOR 106 /* Logical inclusive OR */ +#define ETIR_S_C_OPR_EOR 107 /* Logical exclusive OR */ +#define ETIR_S_C_OPR_NEG 108 /* Negate */ +#define ETIR_S_C_OPR_COM 109 /* Complement */ +#define ETIR_S_C_OPR_INSV 110 /* Insert bit field */ +#define ETIR_S_C_OPR_ASH 111 /* Arithmetic shift */ +#define ETIR_S_C_OPR_USH 112 /* Unsigned shift */ +#define ETIR_S_C_OPR_ROT 113 /* Rotate */ +#define ETIR_S_C_OPR_SEL 114 /* Select one of three longwords on top of stack */ +#define ETIR_S_C_OPR_REDEF 115 /* Redefine this symbol after pass 2 */ +#define ETIR_S_C_OPR_DFLIT 116 /* Define a literal */ +#define ETIR_S_C_MAXOPRCOD 116 /* Maximum operate code */ +#define ETIR_S_C_MINCTLCOD 150 /* Minimum control code */ +#define ETIR_S_C_CTL_SETRB 150 /* Set relocation base */ +#define ETIR_S_C_CTL_AUGRB 151 /* Augment relocation base */ +#define ETIR_S_C_CTL_DFLOC 152 /* Define debug location */ +#define ETIR_S_C_CTL_STLOC 153 /* Set debug location */ +#define ETIR_S_C_CTL_STKDL 154 /* Stack debug location */ +#define ETIR_S_C_MAXCTLCOD 154 /* Maximum control code */ +#define ETIR_S_C_MINSTCCOD 200 /* Minimum store-conditional code */ +#define ETIR_S_C_STC_LP 200 /* Store-conditional Linkage Pair */ +#define ETIR_S_C_STC_LP_PSB 201 /* Store-conditional Linkage Pair with Procedure Signature */ +#define ETIR_S_C_STC_GBL 202 /* Store-conditional Address at global address */ +#define ETIR_S_C_STC_GCA 203 /* Store-conditional Code Address at global address */ +#define ETIR_S_C_STC_PS 204 /* Store-conditional Address at psect + offset */ +#define ETIR_S_C_STC_NOP_GBL 205 /* Store-conditional NOP at address of global */ +#define ETIR_S_C_STC_NOP_PS 206 /* Store-conditional NOP at pect + offset */ +#define ETIR_S_C_STC_BSR_GBL 207 /* Store-conditional BSR at global address */ +#define ETIR_S_C_STC_BSR_PS 208 /* Store-conditional BSR at pect + offset */ +#define ETIR_S_C_STC_LDA_GBL 209 /* Store-conditional LDA at global address */ +#define ETIR_S_C_STC_LDA_PS 210 /* Store-conditional LDA at psect + offset */ +#define ETIR_S_C_STC_BOH_GBL 211 /* Store-conditional BSR or Hint at global address */ +#define ETIR_S_C_STC_BOH_PS 212 /* Store-conditional BSR or Hint at pect + offset */ +#define ETIR_S_C_STC_NBH_GBL 213 /* Store-conditional NOP,BSR or HINT at global address */ +#define ETIR_S_C_STC_NBH_PS 214 /* Store-conditional NOP,BSR or HINT at psect + offset */ +#define ETIR_S_C_MAXSTCCOD 214 /* Maximum store-conditional code */ + +/* VMS Global symbol definition record (GSD/EGSD). */ + +#define GSD_S_K_ENTRIES 1 +#define GSD_S_C_ENTRIES 1 +#define GSD_S_C_PSC 0 +#define GSD_S_C_SYM 1 +#define GSD_S_C_EPM 2 +#define GSD_S_C_PRO 3 +#define GSD_S_C_SYMW 4 +#define GSD_S_C_EPMW 5 +#define GSD_S_C_PROW 6 +#define GSD_S_C_IDC 7 +#define GSD_S_C_ENV 8 +#define GSD_S_C_LSY 9 +#define GSD_S_C_LEPM 10 +#define GSD_S_C_LPRO 11 +#define GSD_S_C_SPSC 12 +#define GSD_S_C_SYMV 13 +#define GSD_S_C_EPMV 14 +#define GSD_S_C_PROV 15 +#define GSD_S_C_MAXRECTYP 15 + +#define EGSD_S_K_ENTRIES 2 /* Offset to first entry in record */ +#define EGSD_S_C_ENTRIES 2 /* Offset to first entry in record */ +#define EGSD_S_C_PSC 0 /* Psect definition */ +#define EGSD_S_C_SYM 1 /* Symbol specification */ +#define EGSD_S_C_IDC 2 /* Random entity check */ +#define EGSD_S_C_SPSC 5 /* Shareable image psect definition */ +#define EGSD_S_C_SYMV 6 /* Vectored (dual-valued) versions of SYM, */ +#define EGSD_S_C_SYMM 7 /* Masked versions of SYM, */ +#define EGSD_S_C_SYMG 8 /* EGST - gst version of SYM */ +#define EGSD_S_C_MAXRECTYP 8 /* Maximum entry type defined */ + +#define GPS_S_M_PIC 1 +#define GPS_S_M_LIB 2 +#define GPS_S_M_OVR 4 +#define GPS_S_M_REL 8 +#define GPS_S_M_GBL 16 +#define GPS_S_M_SHR 32 +#define GPS_S_M_EXE 64 +#define GPS_S_M_RD 128 +#define GPS_S_M_WRT 256 +#define GPS_S_M_VEC 512 +#define GPS_S_K_NAME 9 +#define GPS_S_C_NAME 9 + +#define EGPS_S_V_PIC 0x0001 +#define EGPS_S_V_LIB 0x0002 +#define EGPS_S_V_OVR 0x0004 +#define EGPS_S_V_REL 0x0008 +#define EGPS_S_V_GBL 0x0010 +#define EGPS_S_V_SHR 0x0020 +#define EGPS_S_V_EXE 0x0040 +#define EGPS_S_V_RD 0x0080 +#define EGPS_S_V_WRT 0x0100 +#define EGPS_S_V_VEC 0x0200 +#define EGPS_S_V_NOMOD 0x0400 +#define EGPS_S_V_COM 0x0800 + +#define GSY_S_M_WEAK 1 +#define GSY_S_M_DEF 2 +#define GSY_S_M_UNI 4 +#define GSY_S_M_REL 8 + +#define EGSY_S_V_WEAK 0x0001 +#define EGSY_S_V_DEF 0x0002 +#define EGSY_S_V_UNI 0x0004 +#define EGSY_S_V_REL 0x0008 +#define EGSY_S_V_COMM 0x0010 +#define EGSY_S_V_VECEP 0x0020 +#define EGSY_S_V_NORM 0x0040 + +#define LSY_S_M_DEF 2 +#define LSY_S_M_REL 8 + +#define ENV_S_M_DEF 1 +#define ENV_S_M_NESTED 2 + +/* + * Debugger symbol definitions: These are done by hand, as no + * machine-readable version seems + * to be available. + */ +#define DST_S_C_C 7 /* Language == "C" */ +#define DST_S_C_CXX 15 /* Language == "C++" */ +#define DST_S_C_VERSION 153 +#define DST_S_C_SOURCE 155 /* Source file */ +#define DST_S_C_PROLOG 162 +#define DST_S_C_BLKBEG 176 /* Beginning of block */ +#define DST_S_C_BLKEND 177 /* End of block */ +#define DST_S_C_ENTRY 181 +#define DST_S_C_PSECT 184 +#define DST_S_C_LINE_NUM 185 /* Line Number */ +#define DST_S_C_LBLORLIT 186 +#define DST_S_C_LABEL 187 +#define DST_S_C_MODBEG 188 /* Beginning of module */ +#define DST_S_C_MODEND 189 /* End of module */ +#define DST_S_C_RTNBEG 190 /* Beginning of routine */ +#define DST_S_C_RTNEND 191 /* End of routine */ +#define DST_S_C_DELTA_PC_W 1 /* Incr PC */ +#define DST_S_C_INCR_LINUM 2 /* Incr Line # */ +#define DST_S_C_INCR_LINUM_W 3 /* Incr Line # */ +#define DST_S_C_SET_LINUM_INCR 4 +#define DST_S_C_SET_LINUM_INCR_W 5 +#define DST_S_C_RESET_LINUM_INCR 6 +#define DST_S_C_BEG_STMT_MODE 7 +#define DST_S_C_END_STMT_MODE 8 +#define DST_S_C_SET_LINE_NUM 9 /* Set Line # */ +#define DST_S_C_SET_PC 10 +#define DST_S_C_SET_PC_W 11 +#define DST_S_C_SET_PC_L 12 +#define DST_S_C_SET_STMTNUM 13 +#define DST_S_C_TERM 14 /* End of lines */ +#define DST_S_C_TERM_W 15 /* End of lines */ +#define DST_S_C_SET_ABS_PC 16 /* Set PC */ +#define DST_S_C_DELTA_PC_L 17 /* Incr PC */ +#define DST_S_C_INCR_LINUM_L 18 /* Incr Line # */ +#define DST_S_C_SET_LINUM_B 19 /* Set Line # */ +#define DST_S_C_SET_LINUM_L 20 /* Set Line # */ +#define DST_S_C_TERM_L 21 /* End of lines */ +/* these are used with DST_S_C_SOURCE */ +#define DST_S_C_SRC_DECLFILE 1 /* Declare source file */ +#define DST_S_C_SRC_SETFILE 2 /* Set source file */ +#define DST_S_C_SRC_SETREC_L 3 /* Set record, longword value */ +#define DST_S_C_SRC_SETREC_W 4 /* Set record, word value */ +#define DST_S_C_SRC_DEFLINES_W 10 /* # of line, word counter */ +#define DST_S_C_SRC_DEFLINES_B 11 /* # of line, byte counter */ +#define DST_S_C_SRC_FORMFEED 16 /* ^L counts as a record */ +/* the following are the codes for the various data types. Anything not on + * the list is included under 'advanced_type' + */ +#define DBG_S_C_UCHAR 0x02 +#define DBG_S_C_USINT 0x03 +#define DBG_S_C_ULINT 0x04 +#define DBG_S_C_UQUAD 0x05 +#define DBG_S_C_SCHAR 0x06 +#define DBG_S_C_SSINT 0x07 +#define DBG_S_C_SLINT 0x08 +#define DBG_S_C_SQUAD 0x09 +#define DBG_S_C_REAL4 0x0a +#define DBG_S_C_REAL8 0x0b /* D_float double */ +#define DBG_S_C_COMPLX4 0x0c /* 2xF_float complex float */ +#define DBG_S_C_COMPLX8 0x0d /* 2xD_float complex double */ +#define DBG_S_C_REAL8_G 0x1b /* G_float double */ +#define DBG_S_C_COMPLX8_G 0x1d /* 2xG_float complex double */ +#define DBG_S_C_FUNCTION_ADDR 0x17 +#define DBG_S_C_ADVANCED_TYPE 0xa3 +/* Some of these are just for future reference. [pr] + */ +#define DBG_S_C_UBITA 0x01 /* unsigned, aligned bit field */ +#define DBG_S_C_UBITU 0x22 /* unsigned, unaligned bit field */ +#define DBG_S_C_SBITA 0x29 /* signed, aligned bit field */ +#define DBG_S_C_SBITU 0x2a /* signed, unaligned bit field */ +#define DBG_S_C_CSTRING 0x2e /* asciz ('\0' terminated) string */ +#define DBG_S_C_WCHAR 0x38 /* wchar_t */ +/* These are descriptor class codes. + */ +#define DSC_K_CLASS_S 0x01 /* static (fixed length) */ +#define DSC_K_CLASS_D 0x02 /* dynamic string (not via malloc!) */ +#define DSC_K_CLASS_A 0x04 /* array */ +#define DSC_K_CLASS_UBS 0x0d /* unaligned bit string */ +/* These are the codes that are used to generate the definitions of struct + * union and enum records + */ +#define DBG_S_C_ENUM_ITEM 0xa4 +#define DBG_S_C_ENUM_START 0xa5 +#define DBG_S_C_ENUM_END 0xa6 +#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */ +#define DBG_S_C_STRUCT_START 0xab +#define DBG_S_C_STRUCT_END 0xac +#define DST_K_TYPSPEC 0xaf /* type specification */ +/* These codes are used in the generation of the symbol definition records + */ +#define DST_K_VFLAGS_NOVAL 0x80 /* struct definition only */ +#define DST_K_VFLAGS_DSC 0xfa /* descriptor used */ +#define DST_K_VFLAGS_TVS 0xfb /* trailing value specified */ +#define DST_K_VS_FOLLOWS 0xfd /* value spec follows */ +#define DST_K_VFLAGS_BITOFFS 0xff /* value contains bit offset */ +#define DST_K_VALKIND_LITERAL 0 +#define DST_K_VALKIND_ADDR 1 +#define DST_K_VALKIND_DESC 2 +#define DST_K_VALKIND_REG 3 +#define DST_K_REG_VAX_AP 0x0c /* R12 */ +#define DST_K_REG_VAX_FP 0x0d /* R13 */ +#define DST_K_REG_VAX_SP 0x0e /* R14 */ +#define DST_V_VALKIND 0 /* offset of valkind field */ +#define DST_V_INDIRECT 2 /* offset to indirect bit */ +#define DST_V_DISP 3 /* offset to displacement bit */ +#define DST_V_REGNUM 4 /* offset to register number */ +#define DST_M_INDIRECT (1<contents */ + + unsigned char pdsc[8]; /* procedure descriptor */ + + /* Output routine storage */ + + unsigned char *output_buf; /* output data */ + int push_level; + int pushed_size; + int length_pos; + int output_size; + int output_alignment; + + /* linkage index counter + used by conditional store commands (ETIR_S_C_STC_) */ + + int vms_linkage_index; + + /* see tc-alpha.c of gas for a description. */ + int flag_hash_long_names; /* -+, hash instead of truncate */ + int flag_show_after_trunc; /* -H, show hashing/truncation */ +}; + +#define PRIV(name) ((struct vms_private_data_struct *)abfd->tdata.any)->name + +#define SECTION_NAME_TEMPLATE "__SEC__%d" + +#if VMS_DEBUG +extern void _bfd_vms_debug PARAMS((int level, char *format, ...)); +extern void _bfd_hexdump + PARAMS ((int level, unsigned char *ptr, int size, int offset)); + +#define vms_debug _bfd_vms_debug +#endif + +extern struct bfd_hash_entry *_bfd_vms_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table, + const char *string)); +extern void _bfd_vms_get_header_values + PARAMS ((bfd *abfd, unsigned char *buf, int *type, int *length)); +extern int _bfd_vms_get_record PARAMS ((bfd *abfd)); +extern int _bfd_vms_next_record PARAMS ((bfd *abfd)); + +extern char *_bfd_vms_save_sized_string PARAMS ((unsigned char *str, int size)); +extern char *_bfd_vms_save_counted_string PARAMS ((unsigned char *ptr)); +extern void _bfd_vms_push PARAMS ((bfd *abfd, uquad val, int psect)); +extern uquad _bfd_vms_pop PARAMS ((bfd *abfd, int *psect)); + +extern boolean _bfd_save_vms_section + PARAMS ((bfd *abfd, asection *section, PTR data, file_ptr offset, + bfd_size_type count)); +extern void _bfd_vms_output_begin + PARAMS ((bfd *abfd, int rectype, int rechead)); +extern void _bfd_vms_output_alignment PARAMS ((bfd *abfd, int alignto)); +extern void _bfd_vms_output_push PARAMS ((bfd *abfd)); +extern void _bfd_vms_output_pop PARAMS ((bfd *abfd)); +extern void _bfd_vms_output_flush PARAMS ((bfd *abfd)); +extern void _bfd_vms_output_end PARAMS ((bfd *abfd)); +extern int _bfd_vms_output_check PARAMS ((bfd *abfd, int size)); +extern void _bfd_vms_output_byte PARAMS ((bfd *abfd, unsigned int value)); +extern void _bfd_vms_output_short PARAMS ((bfd *abfd, unsigned int value)); +extern void _bfd_vms_output_long PARAMS ((bfd *abfd, unsigned long value)); +extern void _bfd_vms_output_quad PARAMS ((bfd *abfd, uquad value)); +extern void _bfd_vms_output_counted PARAMS ((bfd *abfd, char *value)); +extern void _bfd_vms_output_dump PARAMS ((bfd *abfd, unsigned char *data, + int length)); +extern void _bfd_vms_output_fill PARAMS ((bfd *abfd, int value, int length)); +extern char *_bfd_vms_length_hash_symbol PARAMS ((bfd *abfd, const char *in, int maxlen)); + +extern vms_symbol_entry *_bfd_vms_enter_symbol PARAMS ((bfd *abfd, char *name)); + +#endif /* VMS_H */