From c3d8e071bfe11043d6d1398377f6eadc22cf0679 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 18 Jun 1996 19:07:51 +0000 Subject: [PATCH] Tue Jun 18 14:42:58 1996 Klaus Kaempf Added support for Alpha OpenVMS: * evax.h, evax-alpha.c, evax-egsd.c, evax-emh.c: New files. * evax-etir.c, evax-misc.c, hosts/alphavms.h: New files. * config.h-vms, makefile.vms: New files. * config.bfd (alpha-*-*vms*): New target. * configure.in (evax_alpha_vec): New target vector. * configure: Rebuild. * reloc.c (BFD_RELOC_SWREL32, BFD_RELOC_SWREL64): Define. (BFD_RELOC_ALPHA_LINKAGE, BFD_RELOC_ALPHA_BASEREG): Define. * targets.c (bfd_target_evax_flavour): Define. (evax_alpha_vec): Declare. (bfd_target_vector): Add ecoffalpha_little_vec and evax_alpha_vec if BFD64 is defined. * bfd-in2.h, libbfd.h: Rebuild. * Makefile.in: Rebuild dependencies. (BFD64_BACKENDS): Add evax-alpha.o, evax-egsd.o, evax-etir.o, evax-emh.o, and evax-misc.o. (BFD64_BACKENDS_CFILES): Add evax-alpha.c, evax-egsd.c, evax-etir.c, evax-emh.c, and evax-misc.c. (HFILES): Add evax.h. --- bfd/.Sanitize | 8 + bfd/ChangeLog | 23 + bfd/bfd-in2.h | 34 +- bfd/config.h-vms | 59 ++ bfd/evax-alpha.c | 1857 ++++++++++++++++++++++++++++++++++++++++++ bfd/evax-egsd.c | 583 +++++++++++++ bfd/evax-emh.c | 288 +++++++ bfd/evax-etir.c | 1553 +++++++++++++++++++++++++++++++++++ bfd/evax-misc.c | 1065 ++++++++++++++++++++++++ bfd/evax.h | 382 +++++++++ bfd/hosts/.Sanitize | 1 + bfd/hosts/alphavms.h | 65 ++ bfd/makefile.vms | 40 + 13 files changed, 5953 insertions(+), 5 deletions(-) create mode 100644 bfd/config.h-vms create mode 100644 bfd/evax-alpha.c create mode 100644 bfd/evax-egsd.c create mode 100644 bfd/evax-emh.c create mode 100644 bfd/evax-etir.c create mode 100644 bfd/evax-misc.c create mode 100644 bfd/evax.h create mode 100644 bfd/hosts/alphavms.h create mode 100644 bfd/makefile.vms diff --git a/bfd/.Sanitize b/bfd/.Sanitize index 41c481ccd26..8217e3ff338 100644 --- a/bfd/.Sanitize +++ b/bfd/.Sanitize @@ -92,6 +92,7 @@ coffgen.c cofflink.c coffswap.h config.bfd +config.h-vms config.in configure configure.bat @@ -147,6 +148,12 @@ elfcode.h elfcore.h elflink.c elflink.h +evax.h +evax-alpha.c +evax-egsd.c +evax-emh.c +evax-etir.c +evax-misc.c filemode.c format.c freebsd.h @@ -193,6 +200,7 @@ m68klynx.c m68knetbsd.c m88kmach3.c makefile.dos +makefile.vms mipsbsd.c mpw-config.in mpw-make.sed diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e336ca0a4e0..c09c54562f4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +Tue Jun 18 14:42:58 1996 Klaus Kaempf + + Added support for Alpha OpenVMS: + * evax.h, evax-alpha.c, evax-egsd.c, evax-emh.c: New files. + * evax-etir.c, evax-misc.c, hosts/alphavms.h: New files. + * config.h-vms, makefile.vms: New files. + * config.bfd (alpha-*-*vms*): New target. + * configure.in (evax_alpha_vec): New target vector. + * configure: Rebuild. + * reloc.c (BFD_RELOC_SWREL32, BFD_RELOC_SWREL64): Define. + (BFD_RELOC_ALPHA_LINKAGE, BFD_RELOC_ALPHA_BASEREG): Define. + * targets.c (bfd_target_evax_flavour): Define. + (evax_alpha_vec): Declare. + (bfd_target_vector): Add ecoffalpha_little_vec and evax_alpha_vec + if BFD64 is defined. + * bfd-in2.h, libbfd.h: Rebuild. + * Makefile.in: Rebuild dependencies. + (BFD64_BACKENDS): Add evax-alpha.o, evax-egsd.o, evax-etir.o, + evax-emh.o, and evax-misc.o. + (BFD64_BACKENDS_CFILES): Add evax-alpha.c, evax-egsd.c, + evax-etir.c, evax-emh.c, and evax-misc.c. + (HFILES): Add evax.h. + Tue Jun 18 13:54:18 1996 Ian Lance Taylor * coff-h8300.c (h8300_reloc16_extra_cases): Make name a const diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8003d45afb4..a6b59aa6e52 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -125,7 +125,9 @@ typedef long int file_ptr; #else #ifdef __GNUC__ #define BFD_HOST_64_BIT long long -#endif /* defined (__GNUC__) */ +#else /* ! defined (__GNUC__) */ + #error No 64 bit integer type available +#endif /* ! defined (__GNUC__) */ #endif /* ! BFD_HOST_64BIT_LONG */ #endif /* ! defined (BFD_HOST_64_BIT) */ @@ -665,6 +667,18 @@ extern boolean bfd_xcoff_size_dynamic_sections unsigned long, unsigned long, unsigned long, boolean, int, boolean, boolean, struct sec **)); +/* Externally visible COFF routines. */ + +#if defined(__STDC__) || defined(ALMOST_STDC) +struct internal_syment; +union internal_auxent; +#endif + +extern boolean bfd_coff_get_syment + PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *)); +extern boolean bfd_coff_get_auxent + PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *)); + /* And more from the source. */ void bfd_init PARAMS ((void)); @@ -1190,9 +1204,6 @@ enum bfd_architecture bfd_arch_arm, /* Advanced Risc Machines ARM */ bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_w65, /* WDC 65816 */ - /* start-sanitize-rce */ - bfd_arch_rce, /* Motorola RCE */ - /* end-sanitize-rce */ /* start-sanitize-arc */ bfd_arch_arc, /* Argonaut RISC Core */ #define bfd_mach_arc_base 0 @@ -1533,6 +1544,11 @@ decided relatively late. */ BFD_RELOC_GPREL16, BFD_RELOC_GPREL32, +/* For openVMS/Alpha systems, these are displacements for switch +tables. */ + BFD_RELOC_SWREL32, + BFD_RELOC_SWREL64, + /* Reloc types used for i960/b.out. */ BFD_RELOC_I960_CALLJ, @@ -1617,6 +1633,13 @@ The GNU linker currently doesn't do any of this optimizing. */ prediction logic which may be provided on some processors. */ BFD_RELOC_ALPHA_HINT, +/* The LINKAGE relocation outputs a special code in the object file, +the rest is handled by the linker. */ + BFD_RELOC_ALPHA_LINKAGE, + +/* The BASEREG relocation calculates differences to basereg. */ + BFD_RELOC_ALPHA_BASEREG, + /* Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. */ BFD_RELOC_MIPS_JMP, @@ -2270,7 +2293,8 @@ enum bfd_flavour { bfd_target_som_flavour, bfd_target_os9k_flavour, bfd_target_versados_flavour, - bfd_target_msdos_flavour + bfd_target_msdos_flavour, + bfd_target_evax_flavour }; enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; diff --git a/bfd/config.h-vms b/bfd/config.h-vms new file mode 100644 index 00000000000..66c4344973d --- /dev/null +++ b/bfd/config.h-vms @@ -0,0 +1,59 @@ +/* config.h-vms. Generated by hand by Klaus Kämpf, kkaempf@didymus.rmi.de. */ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Whether malloc must be declared even if is included. */ +/* #undef NEED_DECLARATION_MALLOC */ + +/* Whether free must be declared even if is included. */ +/* #undef NEED_DECLARATION_FREE */ + +/* Define if you have a working `mmap' system call. */ +/* #define HAVE_MMAP 1 */ + +/* Do we need to use the b modifier when opening binary files? */ +/* #undef USE_BINARY_FOPEN */ + +/* Name of host specific header file to include in trad-core.c. */ +/* #undef TRAD_HEADER */ + +/* Define only if is available *and* it defines prstatus_t. */ +/* #undef HAVE_SYS_PROCFS_H */ + +/* Do we really want to use mmap if it's available? */ +/* #undef USE_MMAP */ + +/* Define if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the madvise function. */ +#define HAVE_MADVISE 1 + +/* Define if you have the mprotect function. */ +#define HAVE_MPROTECT 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 diff --git a/bfd/evax-alpha.c b/bfd/evax-alpha.c new file mode 100644 index 00000000000..2f430399987 --- /dev/null +++ b/bfd/evax-alpha.c @@ -0,0 +1,1857 @@ +/* evax-alpha.c -- BFD back-end for ALPHA EVAX (openVMS/AXP) files. + Copyright 1996 Free Software Foundation, Inc. + Written by Klaus Kämpf (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" + +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 PARAMS ((bfd *abfd, asymbol *symbol)); +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 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 | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* sect flags */ + 0, /* symbol_leading_char */ + ' ', /* ar_pad_char */ + 15, /* ar_max_namelen */ + bfd_getl64, /* bfd_getx64 */ + bfd_getl_signed_64, /* bfd_getx_signed_64 */ + bfd_putl64, /* bfd_putx64 */ + bfd_getl32, /* bfd_getx32 */ + bfd_getl_signed_32, /* bfd_getx_signed_32 */ + bfd_putl32, /* bfd_putx32 */ + bfd_getl16, /* bfd_getx16 */ + bfd_getl_signed_16, /* bfd_getx_signed_16 */ + bfd_putl16, /* bfd_putx16 */ + bfd_getl64, /* bfd_h_getx64 */ + bfd_getl_signed_64, /* bfd_h_getx_signed_64 */ + bfd_putl64, /* bfd_h_putx64 */ + bfd_getl32, /* bfd_h_getx32 */ + bfd_getl_signed_32, /* bfd_h_getx_signed_32 */ + bfd_putl32, /* bfd_h_putx32 */ + bfd_getl16, /* bfd_h_getx16 */ + bfd_getl_signed_16, /* bfd_h_getx_signed_16 */ + bfd_putl16, /* bfd_h_putx16 */ + + {_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(filename) = NULL; + 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; isection 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; + evax_reloc *er, *er1; + 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(filename) != NULL) + { + free (PRIV(filename)); + PRIV(filename) = NULL; + } + + 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; + + er = PRIV(evax_reloc_table)[i]; + while (er != NULL) + { + er1 = er->next; + free (er); + er = er1; + } + PRIV(evax_reloc_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[bfd_get_symcount(abfd)] = NULL; + + return bfd_get_symcount(abfd); +} + + +/* 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_abs_section (sec)) + ret->type = 'A'; + 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 (abfd, symbol) + bfd *abfd; + asymbol *symbol; +{ +#if EVAX_DEBUG + evax_debug (1, "evax_bfd_is_local_label(%p, %p)\n", abfd, symbol); +#endif + return false; +} + + +/* 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; +{ + evax_reloc *er; + +#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 + + er = (evax_reloc *)malloc (sizeof(evax_reloc)); + if (er == NULL) + { + bfd_set_error (bfd_error_no_memory); + return bfd_reloc_notsupported; /* FIXME */ + } + er->section = sec; + er->reloc = reloc; + er->next = NULL; + if (PRIV(evax_reloc_table)[sec->index] == NULL) + { + PRIV(evax_reloc_table)[sec->index] = er; + } + else + { + er->next = PRIV(evax_reloc_table)[sec->index]; + } + 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 */ + + /* Switch table, 32bit relocation. */ + HOWTO (ALPHA_R_SWREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + reloc_nil, /* special_function */ + "SWREL32", /* name */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Switch table, 64bit relocation. */ + HOWTO (ALPHA_R_SWREL64, /* 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 */ + "SWREL64", /* name */ + false, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* 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 */ + +}; + +/* 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_SWREL32: alpha_type = ALPHA_R_SWREL32; break; + case BFD_RELOC_SWREL64: alpha_type = ALPHA_R_SWREL64; break; +#if 0 + case ???: alpha_type = ALPHA_R_OP_PUSH; break; + case ???: alpha_type = ALPHA_R_OP_STORE; break; + case ???: alpha_type = ALPHA_R_OP_PSUB; break; + case ???: alpha_type = ALPHA_R_OP_PRSHIFT;break; + case ???: alpha_type = ALPHA_R_GPVALUE; break; +#endif + 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 + abfd->arch_info = bfd_scan_arch("alpha"); + + return true; +} + + +/* 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); +#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; +} + + +/* 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 new file mode 100644 index 00000000000..b1394f17532 --- /dev/null +++ b/bfd/evax-egsd.c @@ -0,0 +1,583 @@ +/* evax-egsd.c -- BFD back-end for ALPHA EVAX (openVMS/AXP) files. + Copyright 1996 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ämpf (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 + +#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_READONLY_NAME "$READONLY$" +#define EVAX_LITERAL_NAME "$LITERAL$" + +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 */ +}; + +/* just a dummy flag array since i don't understand it yet */ + +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_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), + (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_READONLY_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), + (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_LITERAL_NAME, + (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), + (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) }, + { 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, 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; /* FIXME: should be cooked size */ + section->contents = (unsigned char *) malloc (section->_raw_size); + if (section->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return -1; + } + memset (section->contents, 0, 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 */ + { +#if EVAX_DEBUG + evax_debug(3, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, evax_rec+9, old_flags, flag2str(gsyflagdesc, old_flags)); +#endif + symbol->name = + _bfd_evax_save_counted_string ((char *)evax_rec+8); + 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 uname[200]; + 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; + } + + _bfd_evax_output_begin (abfd, EGSD_S_C_PSC, -1); + _bfd_evax_output_short (abfd, section->alignment_power & 0xff); + _bfd_evax_output_short (abfd, + evax_esecflag_by_name (sname, + section->_raw_size)); + _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_GLOBAL) == 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 (old_flags & BSF_FUNCTION) + { + new_flags |= EGSY_S_V_NORM; + new_flags |= EGSY_S_V_REL; + } + if (old_flags & BSF_GLOBAL) + { + 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) /* 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, FIXME */ + } + } + if (strlen ((char *)symbol->name) > 198) + { + (*_bfd_error_handler) ("Name '%s' too long\n", symbol->name); + abort (); + } + nptr = (char *)symbol->name; + uptr = uname; + while (*nptr) + { + if (islower (*nptr)) + *uptr = toupper (*nptr); + else + *uptr = *nptr; + uptr++; + nptr++; + } + *uptr = 0; + _bfd_evax_output_counted (abfd, uname); + + _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 new file mode 100644 index 00000000000..71519388d6e --- /dev/null +++ b/bfd/evax-emh.c @@ -0,0 +1,288 @@ +/* evax-emh.c -- BFD back-end for ALPHA EVAX (openVMS/AXP) files. + Copyright 1996 Free Software Foundation, Inc. + + EMH record handling functions + and + EEOM record handling functions + + Written by Klaus Kämpf (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; +} + + +#if 0 + +/* register a file name */ + +int +_bfd_evax_register_filename (abfd, name) + bfd *abfd; + char *name; +{ + if (PRIV(filename) != NULL) + { +#if EVAX_DEBUG + evax_debug(3, "Second filename %s, first was %s\n", name, PRIV(filename)); +#endif + return -1; + } + PRIV(filename) = strdup (name); + return 0; +} + +#endif /* 0 */ + +/* write object header for bfd abfd */ + +int +_bfd_evax_write_emh (abfd) + bfd *abfd; +{ + char *name; + +#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) != NULL) + { + name = strdup (bfd_get_filename (abfd)); + _bfd_evax_output_counted (abfd, _bfd_evax_basename (name)); + } + else + _bfd_evax_output_counted (abfd, "NONAME"); + _bfd_evax_output_counted (abfd, BFD_VERSION); + _bfd_evax_output_dump (abfd, (unsigned char *)_bfd_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); + if (PRIV(filename) != 0) + _bfd_evax_output_dump (abfd, (unsigned char *)PRIV(filename), strlen (PRIV(filename))); + else + _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 new file mode 100644 index 00000000000..b9c53bc5ddf --- /dev/null +++ b/bfd/evax-etir.c @@ -0,0 +1,1553 @@ +/* evax-etir.c -- BFD back-end for ALPHA EVAX (openVMS/AXP) files. + Copyright 1996 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ämpf (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 + +#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: + (*_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; + char uname[200]; + char *nptr, *uptr; + +#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_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); + uptr = uname; + nptr = (char *)sym->name; + while (*nptr) + { + if (islower (*nptr)) + *uptr = toupper (*nptr); + else + *uptr = *nptr; + nptr++; + uptr++; + } + *uptr = 0; + _bfd_evax_output_counted (abfd, uname); + _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); + uptr = uname; + nptr = (char *)sym->name; + while (*nptr) + { + if (islower (*nptr)) + *uptr = toupper (*nptr); + else + *uptr = *nptr; + nptr++; + uptr++; + } + *uptr = 0; + _bfd_evax_output_counted (abfd, uname); + _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); + uptr = uname; + nptr = (char *)(*(*rptr)->sym_ptr_ptr)->name; + while (*nptr) + { + if (islower (*nptr)) + *uptr = toupper (*nptr); + else + *uptr = *nptr; + nptr++; + uptr++; + } + *uptr = 0; + + evax_output_counted(abfd, uname); + evax_output_flush(abfd); +#endif + } + break; +#if 0 + case ALPHA_R_BRADDR: + break; + case ALPHA_R_SREL16: + break; + case ALPHA_R_SREL32: + break; + case ALPHA_R_SREL64: + break; + case ALPHA_R_OP_PUSH: + break; + case ALPHA_R_OP_STORE: + break; + case ALPHA_R_OP_PSUB: + break; + case ALPHA_R_OP_PRSHIFT: + break; +#endif + 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; + uptr = uname; + nptr = (char *)(*(*rptr)->sym_ptr_ptr)->name; + while (*nptr) + { + if (islower (*nptr)) + *uptr = toupper (*nptr); + else + *uptr = *nptr; + nptr++; + uptr++; + } + *uptr = 0; + _bfd_evax_output_counted (abfd, uname); + _bfd_evax_output_byte (abfd, 0); + _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 new file mode 100644 index 00000000000..aade68a88c8 --- /dev/null +++ b/bfd/evax-misc.c @@ -0,0 +1,1065 @@ +/* evax-misc.c -- Miscellaneous functions for ALPHA EVAX (openVMS/AXP) files. + Copyright 1996 Free Software Foundation, Inc. + Written by Klaus Kämpf (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 + +#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; + + newptr = (evax_section *) bfd_zalloc (abfd, sizeof (evax_section)); + if (newptr == (evax_section *)NULL) + { + bfd_set_error (bfd_error_no_memory); + return NULL; + } + sptr = PRIV(evax_section_table)[section->index]; + if (sptr == NULL) + { + PRIV(evax_section_table)[section->index] = (evax_section *)newptr; + } + else + { + while (sptr->next != NULL) + sptr = sptr->next; + sptr->next = 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; + sptr->contents = (unsigned char *) bfd_alloc (abfd, (int)count); + if (sptr->contents == (unsigned char *)NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + memcpy (sptr->contents, data, (int)count); + sptr->offset = (bfd_vma)offset; + sptr->size = count; + +#if EVAX_DEBUG + evax_debug (6, "_bfd_save_evax_section sptr = %08lx\n", sptr); + _bfd_hexdump (6, data, count, (int)offset); +#endif + + 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; +} + +/*-----------------------------------------------------------------------------*/ + +/* Return basename (stripped of directory information) of filename */ + +char * +_bfd_evax_basename (name) + char *name; +{ + char *ptr; + +#if EVAX_DEBUG + evax_debug (6, "_bfd_evax_basename %s -> ", name); +#endif + +#ifndef VMS + /* assume unix host */ + ptr = strrchr (name, '.'); + if (ptr) + *ptr = 0; + ptr = strrchr (name, '/'); + if (ptr) + *ptr++ = 0; + else + ptr = name; +#else + /* assume vms host */ + ptr = strrchr (name, '.'); + if (ptr) + { + *ptr = 0; + ptr = name; + } + else + { + ptr = strrchr (name, ']'); + if (ptr) + *ptr++ = 0; + else + { + ptr = strrchr (name, ':'); + if (ptr) + *ptr++ = 0; + else + ptr = name; + } + } +#endif + +#if EVAX_DEBUG + evax_debug (6, "%s\n", ptr); +#endif + + return ptr; +} + + +/* Manufacure a VMS like time on a unix based system. + stolen from obj-vms.c */ + +char * +_bfd_get_vms_time_string () +{ + static char tbuf[18]; +#ifndef VMS +#include +#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; + 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; +} diff --git a/bfd/evax.h b/bfd/evax.h new file mode 100644 index 00000000000..6717bdc0465 --- /dev/null +++ b/bfd/evax.h @@ -0,0 +1,382 @@ +/* evax.h -- Header file for ALPHA EVAX (openVMS/AXP) support. + Copyright 1996 Free Software Foundation, Inc. + Written by Klaus Kämpf (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_SWREL32 12 +#define ALPHA_R_SWREL64 13 +#define ALPHA_R_REFLONG 14 + +/* 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 /*Maxymum symbol 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 32 + +struct evax_private_data_struct { + char *filename; /* Filename of object file */ + 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]; + evax_reloc *evax_reloc_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; + +}; + +#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_get_vms_time_string PARAMS ((void)); +extern char *_bfd_evax_basename PARAMS ((char *name)); + +#endif /* EVAX_H */ diff --git a/bfd/hosts/.Sanitize b/bfd/hosts/.Sanitize index 7f476716a01..5ce2c15a22b 100644 --- a/bfd/hosts/.Sanitize +++ b/bfd/hosts/.Sanitize @@ -25,6 +25,7 @@ Do-first: Things-to-keep: alphalinux.h +alphavms.h decstation.h delta68.h dpx2.h diff --git a/bfd/hosts/alphavms.h b/bfd/hosts/alphavms.h new file mode 100644 index 00000000000..38f815392f1 --- /dev/null +++ b/bfd/hosts/alphavms.h @@ -0,0 +1,65 @@ +/* alphavms.h -- BFD definitions for an openVMS host + Copyright 1996 Free Software Foundation, Inc. + Written by Klaus Kämpf (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. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bfd.h" + +#ifndef BFD_HOST_64_BIT +/* Make the basic types 64-bit quantities on the host. + Also provide the support macros BFD needs. */ +# ifdef __GNUC__ +# define BFD_HOST_64_BIT long long +# else +# define BFD_HOST_64_BIT long +# endif +typedef unsigned BFD_HOST_64_BIT uint64_type; +typedef BFD_HOST_64_BIT int64_type; + +# define sprintf_vma(s,x) sprintf (s, "%016lx", x) /* BFD_HOST_64_BIT */ +# define fprintf_vma(f,x) fprintf (f, "%016lx", x) /* BFD_HOST_64_BIT */ + +# define BYTES_IN_PRINTF_INT 4 + +/* These must have type unsigned long because they are used as + arguments in printf functions. */ +# define uint64_typeLOW(x) ((unsigned long) (((x) & 0xffffffff))) /* BFD_HOST_64_BIT */ +# define uint64_typeHIGH(x) ((unsigned long) (((x) >> 32) & 0xffffffff)) /* BFD_HOST_64_BIT */ + +#endif /* BFD_HOST_64_BIT */ + +#include "fopen-vms.h" + +#define NO_FCNTL 1 + +extern int getpagesize PARAMS ((void)); diff --git a/bfd/makefile.vms b/bfd/makefile.vms new file mode 100644 index 00000000000..8331dfc0624 --- /dev/null +++ b/bfd/makefile.vms @@ -0,0 +1,40 @@ +# +# Makefile for bfd library under openVMS/AXP +# +# For use with gnu-make for vms +# +# Created by Klaus Kaempf, kkaempf@progis.de +# +# +CC=gcc + +OBJS=archive.obj,archures.obj,bfd.obj,cache.obj,coffgen.obj,corefile.obj,format.obj,\ + init.obj,libbfd.obj,opncls.obj,reloc.obj,section.obj,syms.obj,targets.obj,\ + hash.obj,linker.obj,elf.obj,srec.obj,binary.obj,tekhex.obj,ihex.obj,stab-syms.obj,\ + evax-alpha.obj,evax-emh.obj,evax-egsd.obj,evax-etir.obj,evax-misc.obj,\ + cpu-alpha.obj + +ifeq ($(CC),gcc) +DEFS=/define=(SELECT_VECS="&evax_alpha_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch","unlink=remove") +CFLAGS=/include=([],[-.include])$(DEFS) +else +DEFS=/define=(DEFAULT_VECTOR="evax_alpha_vec",SELECT_VECS="&evax_alpha_vec",\ +SELECT_ARCHITECTURES="&bfd_alpha_arch","unlink=remove",\ +"_bfd_generic_get_section_contents_in_window"="_bfd_generic_get_win_section_cont",\ +"_bfd_elf_section_from_bfd_section"="_bfd_elf_sec_from_bfd_sec") +CFLAGS=/machine/list=cc.s/noopt/debug/include=([],[-.include])$(DEFS) +endif + + +libbfd.olb: sysdep.h bfd.h $(OBJS) + purge + lib/create libbfd $(OBJS) + +sysdep.h: [.hosts]alphavms.h config.h + $(CP) $< $@ + +bfd.h: bfd.h-vms + $(CP) $< $@ + +config.h: config.h-vms + $(CP) $< $@ -- 2.30.2