X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fvms-alpha.c;h=4b0b23fd7eedd9ea501eac46fe49c6b67ef522d4;hb=3499769a6a6d3acb48d4d7eef5f656b22fecaeb8;hp=8d1d7cbf0886d044de7f9f641134118f7ba931e9;hpb=bd7b51b4c67b4b655e4783945b2828bec39c6721;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index 8d1d7cbf08..4b0b23fd7e 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -1,6 +1,5 @@ /* vms.c -- BFD back-end for EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1996-2015 Free Software Foundation, Inc. Initial version written by Klaus Kaempf (kkaempf@rmi.de) Major rewrite by Adacore. @@ -21,15 +20,16 @@ MA 02110-1301, USA. */ /* TODO: - o DMT + o overlayed sections o PIC o Generation of shared image - o Generation of GST in image o Relocation optimizations o EISD for the stack o Vectors isect o 64 bits sections o Entry point + o LIB$INITIALIZE + o protected sections (for messages) ... */ @@ -167,11 +167,11 @@ struct vms_symbol_entry unsigned short flags; /* Section and offset/value of the symbol. */ - unsigned int section; unsigned int value; + asection *section; /* Section and offset/value for the entry point (only for subprg). */ - unsigned int code_section; + asection *code_section; unsigned int code_value; /* Symbol vector offset. */ @@ -271,8 +271,14 @@ struct vms_private_data_struct struct hdr_struct hdr_data; /* data from HDR/EMH record */ struct eom_struct eom_data; /* data from EOM/EEOM record */ - unsigned int section_count; /* # of sections in following array */ - asection **sections; /* array of GSD/EGSD sections */ + + /* Transfer addresses (entry points). */ + bfd_vma transfer_address[4]; + + /* Array of GSD sections to get the correspond BFD one. */ + unsigned int section_max; /* Size of the sections array. */ + unsigned int section_count; /* Number of GSD sections. */ + asection **sections; /* Array of raw symbols. */ struct vms_symbol_entry **syms; @@ -297,7 +303,7 @@ struct vms_private_data_struct struct module *modules; /* list of all compilation units */ - struct dst_info *dst_info; + /* The DST section. */ asection *dst_section; unsigned int dst_ptr_offsets_count; /* # of offsets in following array */ @@ -323,11 +329,7 @@ struct vms_private_data_struct struct vms_internal_eisd_map *gbl_eisd_tail; /* linkage index counter used by conditional store commands */ - int vms_linkage_index; - - /* see tc-alpha.c of gas for a description. */ - int flag_hash_long_names; /* -+, hash instead of truncate */ - int flag_show_after_trunc; /* -H, show hashing/truncation */ + unsigned int vms_linkage_index; }; #define PRIV2(abfd, name) \ @@ -362,18 +364,18 @@ struct vms_section_data_struct ((struct vms_section_data_struct *)sec->used_by_bfd) /* To be called from the debugger. */ -struct vms_private_data_struct *bfd_vms_get_data (bfd *abfd); +struct vms_private_data_struct *bfd_vms_get_data (bfd *); -static int vms_get_remaining_object_record (bfd *abfd, int read_so_far); +static int vms_get_remaining_object_record (bfd *, unsigned int); static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd); static void alpha_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *); static void alpha_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *); static void alpha_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *, bfd_vma); -static void alpha_vms_add_lw_reloc (struct bfd_link_info *info); -static void alpha_vms_add_qw_reloc (struct bfd_link_info *info); -static void alpha_vms_add_lw_fixup (struct bfd_link_info *, unsigned int, +static void alpha_vms_add_fixup_lr (struct bfd_link_info *, unsigned int, bfd_vma); +static void alpha_vms_add_lw_reloc (struct bfd_link_info *); +static void alpha_vms_add_qw_reloc (struct bfd_link_info *); struct vector_type { @@ -433,7 +435,7 @@ struct alpha_vms_link_hash_table { struct bfd_link_hash_table root; - /* Vector of shared libaries. */ + /* Vector of shared libraries. */ struct vector_type shrlibs; /* Fixup section. */ @@ -519,9 +521,11 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) asection *section; flagword bfd_flags; + /* PR 17512: file: 3d9e9fe9. */ + if (offset >= PRIV (recrd.rec_size)) + return FALSE; eisd = (struct vms_eisd *)(PRIV (recrd.rec) + offset); rec_size = bfd_getl32 (eisd->eisdsize); - if (rec_size == 0) break; @@ -547,12 +551,14 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) what's in each section without examining the data. This is especially true of DWARF debug sections. */ bfd_flags = SEC_ALLOC; + if (vbn != 0) + bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD; if (flags & EISD__M_EXE) - bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD; + bfd_flags |= SEC_CODE; if (flags & EISD__M_NONSHRADR) - bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD; + bfd_flags |= SEC_DATA; if (!(flags & EISD__M_WRT)) bfd_flags |= SEC_READONLY; @@ -561,10 +567,10 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset) bfd_flags |= SEC_DATA; if (flags & EISD__M_FIXUPVEC) - bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD; + bfd_flags |= SEC_DATA; if (flags & EISD__M_CRF) - bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD; + bfd_flags |= SEC_DATA; if (flags & EISD__M_GBL) { @@ -665,12 +671,6 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) if (gstvbn) { - flagword bfd_flags = SEC_HAS_CONTENTS; - - section = bfd_make_section (abfd, "$GST$"); - if (!section) - return FALSE; - if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET)) { bfd_set_error (bfd_error_file_truncated); @@ -680,12 +680,6 @@ _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset) if (_bfd_vms_slurp_object_records (abfd) != TRUE) return FALSE; - section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1); - section->size = bfd_tell (abfd) - section->filepos; - - if (!bfd_set_section_flags (abfd, section, bfd_flags)) - return FALSE; - abfd->flags |= HAS_SYMS; } @@ -796,7 +790,7 @@ _bfd_vms_get_object_record (bfd *abfd) Return the size of the record or 0 on failure. */ static int -vms_get_remaining_object_record (bfd *abfd, int read_so_far) +vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far) { unsigned int to_read; @@ -805,7 +799,7 @@ vms_get_remaining_object_record (bfd *abfd, int read_so_far) /* Extract record size. */ PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2); - if (PRIV (recrd.rec_size) <= 0) + if (PRIV (recrd.rec_size) == 0) { bfd_set_error (bfd_error_file_truncated); return 0; @@ -832,6 +826,9 @@ vms_get_remaining_object_record (bfd *abfd, int read_so_far) return 0; PRIV (recrd.buf_size) = to_read; } + /* PR 17512: file: 025-1974-0.004. */ + else if (to_read <= read_so_far) + return 0; /* Read the remaining record. */ to_read -= read_so_far; @@ -862,9 +859,12 @@ _bfd_vms_slurp_ehdr (bfd *abfd) { unsigned char *ptr; unsigned char *vms_rec; + unsigned char *end; int subtype; vms_rec = PRIV (recrd.rec); + /* PR 17512: file: 62736583. */ + end = PRIV (recrd.buf) + PRIV (recrd.buf_size); vms_debug2 ((2, "HDR/EMH\n")); @@ -876,28 +876,42 @@ _bfd_vms_slurp_ehdr (bfd *abfd) { case EMH__C_MHD: /* Module header. */ + if (vms_rec + 21 >= end) + goto fail; PRIV (hdr_data).hdr_b_strlvl = vms_rec[6]; PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8); PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12); PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); + if ((vms_rec + 20 + vms_rec[20] + 1) >= end) + goto fail; PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20); ptr = vms_rec + 20 + vms_rec[20] + 1; + if ((ptr + *ptr + 1) >= end) + goto fail; PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr); ptr += *ptr + 1; + if (ptr + 17 >= end) + goto fail; PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17); break; case EMH__C_LNM: + if (vms_rec + PRIV (recrd.rec_size - 6) > end) + goto fail; PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); break; case EMH__C_SRC: + if (vms_rec + PRIV (recrd.rec_size - 6) > end) + goto fail; PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); break; case EMH__C_TTL: + if (vms_rec + PRIV (recrd.rec_size - 6) > end) + goto fail; PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6)); break; @@ -908,6 +922,7 @@ _bfd_vms_slurp_ehdr (bfd *abfd) break; default: + fail: bfd_set_error (bfd_error_wrong_format); return FALSE; } @@ -940,71 +955,70 @@ struct sec_flags_struct /* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */ -static struct sec_flags_struct evax_section_flags[] = +static const struct sec_flags_struct evax_section_flags[] = { { EVAX_ABS_NAME, - (EGPS__V_SHR), - (SEC_DATA), - (EGPS__V_SHR), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, + EGPS__V_SHR, + 0, + EGPS__V_SHR, + 0 }, { EVAX_CODE_NAME, - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE), - (SEC_CODE), - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE), - (SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, + SEC_CODE | SEC_READONLY, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE, + SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_LITERAL_NAME, - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD), - (SEC_DATA | SEC_READONLY), - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, + SEC_DATA | SEC_READONLY, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, + SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_LINK_NAME, - (EGPS__V_REL | EGPS__V_RD), - (SEC_DATA | SEC_READONLY), - (EGPS__V_REL | EGPS__V_RD), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, + EGPS__V_REL | EGPS__V_RD, + SEC_DATA | SEC_READONLY, + EGPS__V_REL | EGPS__V_RD, + SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_DATA_NAME, - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD), - (SEC_DATA), - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, + SEC_DATA, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, + SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_BSS_NAME, - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD), - (SEC_NO_FLAGS), - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD), - (SEC_ALLOC) }, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, + SEC_NO_FLAGS, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD, + SEC_ALLOC }, { EVAX_READONLYADDR_NAME, - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD), - (SEC_DATA | SEC_READONLY), - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, + SEC_DATA | SEC_READONLY, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD, + SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_READONLY_NAME, - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD), - (SEC_DATA | SEC_READONLY), - (EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD, + SEC_DATA | SEC_READONLY, + EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD, + SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_LOCAL_NAME, - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT), - (SEC_DATA), - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, + SEC_DATA, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, + SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { EVAX_LITERALS_NAME, - (EGPS__V_PIC | EGPS__V_OVR), - (SEC_DATA | SEC_READONLY), - (EGPS__V_PIC | EGPS__V_OVR), - (SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, + EGPS__V_PIC | EGPS__V_OVR, + SEC_DATA | SEC_READONLY, + EGPS__V_PIC | EGPS__V_OVR, + SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }, { NULL, - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT), - (SEC_DATA), - (EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT), - (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) } + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, + SEC_DATA, + EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT, + SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD } }; -/* Retrieve bfd section flags by name and size. */ +/* Retrieve BFD section flags by name and size. */ static flagword -vms_secflag_by_name (bfd *abfd ATTRIBUTE_UNUSED, - struct sec_flags_struct *section_flags, - char *name, +vms_secflag_by_name (const struct sec_flags_struct *section_flags, + const char *name, int hassize) { int i = 0; @@ -1025,12 +1039,12 @@ vms_secflag_by_name (bfd *abfd ATTRIBUTE_UNUSED, return section_flags[i].flags_always; } -/* Retrieve vms section flags by name and size. */ +/* Retrieve VMS section flags by name and size. */ static flagword -vms_esecflag_by_name (struct sec_flags_struct *section_flags, - char *name, - int hassize) +vms_esecflag_by_name (const struct sec_flags_struct *section_flags, + const char *name, + int hassize) { int i = 0; @@ -1050,23 +1064,12 @@ vms_esecflag_by_name (struct sec_flags_struct *section_flags, return section_flags[i].vflags_always; } -/* Input routines. */ +/* Add SYM to the symbol table of ABFD. + Return FALSE in case of error. */ -static struct vms_symbol_entry * -add_symbol (bfd *abfd, const unsigned char *ascic) +static bfd_boolean +add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym) { - struct vms_symbol_entry *entry; - int len; - - len = *ascic++; - entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len); - if (entry == NULL) - return NULL; - entry->namelen = len; - memcpy (entry->name, ascic, len); - entry->name[len] = 0; - entry->owner = abfd; - if (PRIV (gsd_sym_count) >= PRIV (max_sym_count)) { if (PRIV (max_sym_count) == 0) @@ -1083,25 +1086,44 @@ add_symbol (bfd *abfd, const unsigned char *ascic) (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *))); } if (PRIV (syms) == NULL) - return NULL; + return FALSE; } - PRIV (syms)[PRIV (gsd_sym_count)++] = entry; + PRIV (syms)[PRIV (gsd_sym_count)++] = sym; + return TRUE; +} + +/* Create a symbol whose name is ASCIC and add it to ABFD. + Return NULL in case of error. */ + +static struct vms_symbol_entry * +add_symbol (bfd *abfd, const unsigned char *ascic) +{ + struct vms_symbol_entry *entry; + int len; + + len = *ascic++; + entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len); + if (entry == NULL) + return NULL; + entry->namelen = len; + memcpy (entry->name, ascic, len); + entry->name[len] = 0; + entry->owner = abfd; + + if (!add_symbol_entry (abfd, entry)) + return NULL; return entry; } /* Read and process EGSD. Return FALSE on failure. */ static bfd_boolean -_bfd_vms_slurp_egsd (bfd * abfd) +_bfd_vms_slurp_egsd (bfd *abfd) { int gsd_type, gsd_size; - asection *section; unsigned char *vms_rec; - flagword new_flags, old_flags; - char *name; unsigned long base_addr; - unsigned long align_addr; vms_debug2 ((2, "EGSD\n")); @@ -1123,41 +1145,82 @@ _bfd_vms_slurp_egsd (bfd * abfd) switch (gsd_type) { case EGSD__C_PSC: + /* Program section definition. */ { - /* Program section definition. */ struct vms_egps *egps = (struct vms_egps *)vms_rec; - name = _bfd_vms_save_counted_string (&egps->namlng); - section = bfd_make_section (abfd, name); - if (!section) - return FALSE; - old_flags = bfd_getl16 (egps->flags); - vms_section_data (section)->flags = old_flags; - vms_section_data (section)->no_flags = 0; - section->size = bfd_getl32 (egps->alloc); - new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, - section->size > 0); - if (!(old_flags & EGPS__V_NOMOD)) + flagword new_flags, vms_flags; + asection *section; + + vms_flags = bfd_getl16 (egps->flags); + + if ((vms_flags & EGPS__V_REL) == 0) { - new_flags |= SEC_HAS_CONTENTS; - if (old_flags & EGPS__V_REL) - new_flags |= SEC_RELOC; + /* Use the global absolute section for all + absolute sections. */ + section = bfd_abs_section_ptr; } - if (!bfd_set_section_flags (abfd, section, new_flags)) - return FALSE; - section->alignment_power = egps->align; - 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->size; - section->filepos = (unsigned int)-1; -#if VMS_DEBUG - vms_debug (4, "EGSD P-section %d (%s, flags %04x) ", - section->index, name, old_flags); - vms_debug (4, "%lu bytes at 0x%08lx (mem %p)\n", - (unsigned long)section->size, - (unsigned long)section->vma, section->contents); -#endif + else + { + char *name; + unsigned long align_addr; + + name = _bfd_vms_save_counted_string (&egps->namlng); + + section = bfd_make_section (abfd, name); + if (!section) + return FALSE; + + section->filepos = 0; + section->size = bfd_getl32 (egps->alloc); + section->alignment_power = egps->align; + + vms_section_data (section)->flags = vms_flags; + vms_section_data (section)->no_flags = 0; + + new_flags = vms_secflag_by_name (evax_section_flags, name, + section->size > 0); + if (section->size > 0) + new_flags |= SEC_LOAD; + if (!(vms_flags & EGPS__V_NOMOD) && section->size > 0) + { + /* Set RELOC and HAS_CONTENTS if the section is not + demand-zero and not empty. */ + new_flags |= SEC_HAS_CONTENTS; + if (vms_flags & EGPS__V_REL) + new_flags |= SEC_RELOC; + } + if (vms_flags & EGPS__V_EXE) + { + /* Set CODE if section is executable. */ + new_flags |= SEC_CODE; + new_flags &= ~SEC_DATA; + } + if (!bfd_set_section_flags (abfd, section, new_flags)) + return FALSE; + + /* Give a non-overlapping vma to non absolute sections. */ + 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->size; + } + + /* Append it to the section array. */ + if (PRIV (section_count) >= PRIV (section_max)) + { + if (PRIV (section_max) == 0) + PRIV (section_max) = 16; + else + PRIV (section_max) *= 2; + PRIV (sections) = bfd_realloc_or_free + (PRIV (sections), PRIV (section_max) * sizeof (asection *)); + if (PRIV (sections) == NULL) + return FALSE; + } + + PRIV (sections)[PRIV (section_count)] = section; + PRIV (section_count)++; } break; @@ -1166,6 +1229,7 @@ _bfd_vms_slurp_egsd (bfd * abfd) int nameoff; struct vms_symbol_entry *entry; struct vms_egsy *egsy = (struct vms_egsy *) vms_rec; + flagword old_flags; old_flags = bfd_getl16 (egsy->flags); if (old_flags & EGSY__V_DEF) @@ -1193,14 +1257,15 @@ _bfd_vms_slurp_egsd (bfd * abfd) struct vms_esdf *esdf = (struct vms_esdf *)vms_rec; entry->value = bfd_getl64 (esdf->value); - entry->section = bfd_getl32 (esdf->psindx); + entry->section = PRIV (sections)[bfd_getl32 (esdf->psindx)]; if (old_flags & EGSY__V_NORM) { PRIV (norm_sym_count)++; entry->code_value = bfd_getl64 (esdf->code_address); - entry->code_section = bfd_getl32 (esdf->ca_psindx); + entry->code_section = + PRIV (sections)[bfd_getl32 (esdf->ca_psindx)]; } } } @@ -1208,15 +1273,11 @@ _bfd_vms_slurp_egsd (bfd * abfd) case EGSD__C_SYMG: { - int nameoff; struct vms_symbol_entry *entry; struct vms_egst *egst = (struct vms_egst *)vms_rec; + flagword old_flags; old_flags = bfd_getl16 (egst->header.flags); - if (old_flags & EGSY__V_DEF) - nameoff = ESDF__B_NAMLNG; - else - nameoff = ESRF__B_NAMLNG; entry = add_symbol (abfd, &egst->namlng); @@ -1229,7 +1290,11 @@ _bfd_vms_slurp_egsd (bfd * abfd) entry->symbol_vector = bfd_getl32 (egst->value); - entry->section = bfd_getl32 (egst->psindx); + if (old_flags & EGSY__V_REL) + entry->section = PRIV (sections)[bfd_getl32 (egst->psindx)]; + else + entry->section = bfd_abs_section_ptr; + entry->value = bfd_getl64 (egst->lp_2); if (old_flags & EGSY__V_NORM) @@ -1237,7 +1302,7 @@ _bfd_vms_slurp_egsd (bfd * abfd) PRIV (norm_sym_count)++; entry->code_value = bfd_getl64 (egst->lp_1); - entry->code_section = 0; + entry->code_section = bfd_abs_section_ptr; } } break; @@ -1602,7 +1667,8 @@ alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h) return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index); else { - /* Can this happen ? I'd like to see an example. */ + /* Can this happen (non-relocatable symg) ? I'd like to see + an example. */ abort (); } } @@ -1617,16 +1683,9 @@ alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h) } static bfd_vma -alpha_vms_get_sym_value (unsigned int sect, bfd_vma addr, - struct alpha_vms_link_hash_entry *h) +alpha_vms_get_sym_value (asection *sect, bfd_vma addr) { - asection *s; - - BFD_ASSERT (h && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak)); - - s = PRIV2 (h->root.u.def.section->owner, sections)[sect]; - return s->output_section->vma + s->output_offset + addr; + return sect->output_section->vma + sect->output_offset + addr; } static bfd_vma @@ -1680,7 +1739,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) #if VMS_DEBUG _bfd_vms_debug (4, "etir: %s(%d)\n", _bfd_vms_etir_name (cmd), cmd); - _bfd_hexdump (8, ptr, cmd_length - 4, (long) ptr); + _bfd_hexdump (8, ptr, cmd_length - 4, 0); #endif switch (cmd) @@ -1770,7 +1829,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) } else if (rel1 & RELC_SHR_BASE) { - alpha_vms_add_lw_fixup (info, rel1 & RELC_MASK, op1); + alpha_vms_add_fixup_lr (info, rel1 & RELC_MASK, op1); rel1 = RELC_NONE; } if (rel1 != RELC_NONE) @@ -1833,7 +1892,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) else { op1 = alpha_vms_get_sym_value (h->sym->section, - h->sym->value, h); + h->sym->value); alpha_vms_add_qw_reloc (info); } } @@ -1857,7 +1916,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) else { op1 = alpha_vms_get_sym_value (h->sym->code_section, - h->sym->code_value, h); + h->sym->code_value); alpha_vms_add_qw_reloc (info); } } @@ -1967,9 +2026,9 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info) else { op1 = alpha_vms_get_sym_value (h->sym->code_section, - h->sym->code_value, h); + h->sym->code_value); op2 = alpha_vms_get_sym_value (h->sym->section, - h->sym->value, h); + h->sym->value); } } else @@ -2396,7 +2455,7 @@ vms_initialize (bfd * abfd) static const struct bfd_target * alpha_vms_object_p (bfd *abfd) { - PTR tdata_save = abfd->tdata.any; + void *tdata_save = abfd->tdata.any; unsigned int test_len; unsigned char *buf; @@ -2438,10 +2497,7 @@ alpha_vms_object_p (bfd *abfd) PRIV (recrd.rec) = buf; if (bfd_bread (buf, test_len, abfd) != test_len) - { - bfd_set_error (bfd_error_file_truncated); - goto error_ret; - } + goto err_wrong_format; /* Is it an image? */ if ((bfd_getl32 (buf) == EIHD__K_MAJORID) @@ -2466,7 +2522,6 @@ alpha_vms_object_p (bfd *abfd) if (buf == NULL) { PRIV (recrd.buf) = NULL; - bfd_set_error (bfd_error_no_memory); goto error_ret; } PRIV (recrd.buf) = buf; @@ -2481,10 +2536,7 @@ alpha_vms_object_p (bfd *abfd) while (remaining > 0) { if (bfd_bread (buf + read_so_far, to_read, abfd) != to_read) - { - bfd_set_error (bfd_error_file_truncated); - goto err_wrong_format; - } + goto err_wrong_format; read_so_far += to_read; remaining -= to_read; @@ -2495,6 +2547,9 @@ alpha_vms_object_p (bfd *abfd) /* Reset the record pointer. */ PRIV (recrd.rec) = buf; + /* PR 17512: file: 7d7c57c2. */ + if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd)) + goto error_ret; vms_debug2 ((2, "file type is image\n")); if (_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset) != TRUE) @@ -2619,7 +2674,7 @@ _bfd_vms_write_eeom (bfd *abfd) _bfd_vms_output_alignment (recwr, 2); _bfd_vms_output_begin (recwr, EOBJ__C_EEOM); - _bfd_vms_output_long (recwr, (unsigned long) (PRIV (vms_linkage_index) >> 1)); + _bfd_vms_output_long (recwr, PRIV (vms_linkage_index + 1) >> 1); _bfd_vms_output_byte (recwr, 0); /* Completion code. */ _bfd_vms_output_byte (recwr, 0); /* Fill byte. */ @@ -2635,7 +2690,7 @@ _bfd_vms_write_eeom (bfd *abfd) return FALSE; } _bfd_vms_output_short (recwr, 0); - _bfd_vms_output_long (recwr, (unsigned long) (section->index)); + _bfd_vms_output_long (recwr, (unsigned long) section->target_index); _bfd_vms_output_long (recwr, (unsigned long) bfd_get_start_address (abfd)); _bfd_vms_output_long (recwr, 0); @@ -2645,88 +2700,6 @@ _bfd_vms_write_eeom (bfd *abfd) return TRUE; } -/* This hash routine borrowed from GNU-EMACS, and strengthened - slightly. ERY. */ - -static int -hash_string (const char *ptr) -{ - const unsigned char *p = (unsigned char *) ptr; - const unsigned char *end = p + strlen (ptr); - unsigned char c; - int hash = 0; - - while (p != end) - { - c = *p++; - hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); - } - return hash; -} - -/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */ - -static char * -_bfd_vms_length_hash_symbol (bfd *abfd, const char *in, int maxlen) -{ - unsigned long result; - int in_len; - char *new_name; - const char *old_name; - int i; - static char outbuf[EOBJ__C_SYMSIZ + 1]; - char *out = outbuf; - -#if VMS_DEBUG - vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in); -#endif - - if (maxlen > EOBJ__C_SYMSIZ) - maxlen = EOBJ__C_SYMSIZ; - - /* Save this for later. */ - new_name = out; - - /* We may need to truncate the symbol, save the hash for later. */ - in_len = strlen (in); - - result = (in_len > maxlen) ? hash_string (in) : 0; - - old_name = in; - - /* Do the length checking. */ - if (in_len <= maxlen) - i = in_len; - else - { - if (PRIV (flag_hash_long_names)) - i = maxlen - 9; - else - i = maxlen; - } - - strncpy (out, in, (size_t) i); - in += i; - out += i; - - if ((in_len > maxlen) - && PRIV (flag_hash_long_names)) - sprintf (out, "_%08lx", result); - else - *out = 0; - -#if VMS_DEBUG - vms_debug (4, "--> [%d]\"%s\"\n", (int)strlen (outbuf), outbuf); -#endif - - if (in_len > maxlen - && PRIV (flag_hash_long_names) - && PRIV (flag_show_after_trunc)) - printf (_("Symbol %s replaced by %s\n"), old_name, new_name); - - return outbuf; -} - static void vector_grow1 (struct vector_type *vec, size_t elsz) { @@ -2875,7 +2848,11 @@ alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec) if (!(sec->flags & SEC_READONLY)) eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; - if (!(sec->flags & SEC_LOAD)) + /* If relocations or fixup will be applied, make this isect writeable. */ + if (sec->flags & SEC_RELOC) + eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF; + + if (!(sec->flags & SEC_HAS_CONTENTS)) { eisd->u.eisd.flags |= EISD__M_DZRO; eisd->u.eisd.flags &= ~EISD__M_CRF; @@ -2912,6 +2889,8 @@ alpha_vms_write_exec (bfd *abfd) struct vms_internal_eisd_map *eisd; asection *dst; asection *dmt; + file_ptr gst_filepos = 0; + unsigned int lnkflags = 0; /* Build the EIHD. */ PRIV (file_pos) = EIHD__C_LENGTH; @@ -2940,7 +2919,6 @@ alpha_vms_write_exec (bfd *abfd) bfd_putl32 ((sizeof (eihd) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE, eihd.hdrblkcnt); - bfd_putl32 (0, eihd.lnkflags); bfd_putl32 (0, eihd.ident); bfd_putl32 (0, eihd.sysver); @@ -2958,11 +2936,10 @@ alpha_vms_write_exec (bfd *abfd) bfd_putl32 (sizeof (struct vms_eiha), eiha->size); bfd_putl32 (0, eiha->spare); - bfd_putl32 (0x00000340, eiha->tfradr1); /* SYS$IMGACT */ - bfd_putl32 (0xffffffff, eiha->tfradr1_h); - bfd_putl64 (bfd_get_start_address (abfd), eiha->tfradr2); - bfd_putl64 (0, eiha->tfradr3); - bfd_putl64 (0, eiha->tfradr4); + bfd_putl64 (PRIV (transfer_address[0]), eiha->tfradr1); + bfd_putl64 (PRIV (transfer_address[1]), eiha->tfradr2); + bfd_putl64 (PRIV (transfer_address[2]), eiha->tfradr3); + bfd_putl64 (PRIV (transfer_address[3]), eiha->tfradr4); bfd_putl64 (0, eiha->inishr); /* Alloc EIHI. */ @@ -2976,6 +2953,7 @@ alpha_vms_write_exec (bfd *abfd) char *module; unsigned int len; + /* Set module name. */ module = vms_get_module_name (bfd_get_filename (abfd), TRUE); len = strlen (module); if (len > sizeof (eihi->imgnam) - 1) @@ -2984,8 +2962,15 @@ alpha_vms_write_exec (bfd *abfd) memcpy (eihi->imgnam + 1, module, len); free (module); } - bfd_putl32 (0, eihi->linktime + 0); - bfd_putl32 (0, eihi->linktime + 4); + { + unsigned int lo; + unsigned int hi; + + /* Set time. */ + vms_get_time (&hi, &lo); + bfd_putl32 (lo, eihi->linktime + 0); + bfd_putl32 (hi, eihi->linktime + 4); + } eihi->imgid[0] = 0; eihi->linkid[0] = 0; eihi->imgbid[0] = 0; @@ -3085,6 +3070,7 @@ alpha_vms_write_exec (bfd *abfd) PRIV (file_pos) += sec->size; } + /* Update EIHS. */ if (eihs != NULL && dst != NULL) { bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn); @@ -3092,9 +3078,17 @@ alpha_vms_write_exec (bfd *abfd) if (dmt != NULL) { + lnkflags |= EIHD__M_DBGDMT; bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn); bfd_putl32 (dmt->size, eihs->dmtsize); } + if (PRIV (gsd_sym_count) != 0) + { + alpha_vms_file_position_block (abfd); + gst_filepos = PRIV (file_pos); + bfd_putl32 ((gst_filepos / VMS_BLOCK_SIZE) + 1, eihs->gstvbn); + bfd_putl32 ((PRIV (gsd_sym_count) + 4) / 5 + 4, eihs->gstsize); + } } /* Write EISD in hdr. */ @@ -3104,6 +3098,7 @@ alpha_vms_write_exec (bfd *abfd) (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos)); /* Write first block. */ + bfd_putl32 (lnkflags, eihd.lnkflags); if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd)) return FALSE; @@ -3155,6 +3150,66 @@ alpha_vms_write_exec (bfd *abfd) } } + /* Write GST. */ + if (gst_filepos != 0) + { + struct vms_rec_wr *recwr = &PRIV (recwr); + unsigned int i; + + _bfd_vms_write_emh (abfd); + _bfd_vms_write_lmn (abfd, "GNU LD"); + + /* PSC for the absolute section. */ + _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); + _bfd_vms_output_long (recwr, 0); + _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); + _bfd_vms_output_short (recwr, 0); + _bfd_vms_output_short (recwr, EGPS__V_PIC | EGPS__V_LIB | EGPS__V_RD); + _bfd_vms_output_long (recwr, 0); + _bfd_vms_output_counted (recwr, ".$$ABS$$."); + _bfd_vms_output_end_subrec (recwr); + _bfd_vms_output_end (abfd, recwr); + + for (i = 0; i < PRIV (gsd_sym_count); i++) + { + struct vms_symbol_entry *sym = PRIV (syms)[i]; + bfd_vma val; + bfd_vma ep; + + if ((i % 5) == 0) + { + _bfd_vms_output_alignment (recwr, 8); + _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); + _bfd_vms_output_long (recwr, 0); + } + _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYMG); + _bfd_vms_output_short (recwr, 0); /* Data type, alignment. */ + _bfd_vms_output_short (recwr, sym->flags); + + if (sym->code_section) + ep = alpha_vms_get_sym_value (sym->code_section, sym->code_value); + else + { + BFD_ASSERT (sym->code_value == 0); + ep = 0; + } + val = alpha_vms_get_sym_value (sym->section, sym->value); + _bfd_vms_output_quad + (recwr, sym->typ == EGSD__C_SYMG ? sym->symbol_vector : val); + _bfd_vms_output_quad (recwr, ep); + _bfd_vms_output_quad (recwr, val); + _bfd_vms_output_long (recwr, 0); + _bfd_vms_output_counted (recwr, sym->name); + _bfd_vms_output_end_subrec (recwr); + if ((i % 5) == 4) + _bfd_vms_output_end (abfd, recwr); + } + if ((i % 5) != 0) + _bfd_vms_output_end (abfd, recwr); + + if (!_bfd_vms_write_eeom (abfd)) + return FALSE; + } return TRUE; } @@ -3168,18 +3223,13 @@ _bfd_vms_write_egsd (bfd *abfd) asection *section; asymbol *symbol; unsigned int symnum; - int last_index = -1; - char dummy_name[10]; - char *sname; + const char *sname; flagword new_flags, old_flags; - int abs_section_index = 0; + int abs_section_index = -1; + unsigned int target_index = 0; struct vms_rec_wr *recwr = &PRIV (recwr); - vms_debug2 ((2, "vms_write_gsd\n")); - - /* Output sections. */ - section = abfd->sections; - vms_debug2 ((3, "%d sections found\n", abfd->section_count)); + vms_debug2 ((2, "vms_write_egsd\n")); /* Egsd is quadword aligned. */ _bfd_vms_output_alignment (recwr, 8); @@ -3187,15 +3237,28 @@ _bfd_vms_write_egsd (bfd *abfd) _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); _bfd_vms_output_long (recwr, 0); - while (section != 0) + /* Number sections. */ + for (section = abfd->sections; section != NULL; section = section->next) + { + if (section->flags & SEC_DEBUGGING) + continue; + if (!strcmp (section->name, ".vmsdebug")) + { + section->flags |= SEC_DEBUGGING; + continue; + } + section->target_index = target_index++; + } + + for (section = abfd->sections; section != NULL; section = section->next) { vms_debug2 ((3, "Section #%d %s, %d bytes\n", - section->index, section->name, (int)section->size)); + section->target_index, section->name, (int)section->size)); /* Don't write out the VMS debug info section since it is in the ETBT and EDBG sections in etir. */ - if (!strcmp (section->name, ".vmsdebug")) - goto done; + if (section->flags & SEC_DEBUGGING) + continue; /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ if (_bfd_vms_output_check (recwr, 64) < 0) @@ -3205,25 +3268,12 @@ _bfd_vms_write_egsd (bfd *abfd) _bfd_vms_output_long (recwr, 0); } - /* Create dummy sections to keep consecutive indices. */ - while (section->index - last_index > 1) - { - vms_debug2 ((3, "index %d, last %d\n", section->index, last_index)); - _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); - _bfd_vms_output_short (recwr, 0); - _bfd_vms_output_short (recwr, 0); - _bfd_vms_output_long (recwr, 0); - sprintf (dummy_name, ".DUMMY%02d", last_index); - _bfd_vms_output_counted (recwr, dummy_name); - _bfd_vms_output_end_subrec (recwr); - last_index++; - } - /* Don't know if this is necessary for the linker but for now it keeps - vms_slurp_gsd happy */ - sname = (char *)section->name; + vms_slurp_gsd happy. */ + sname = section->name; if (*sname == '.') { + /* Remove leading dot. */ sname++; if ((*sname == 't') && (strcmp (sname, "text") == 0)) sname = EVAX_CODE_NAME; @@ -3238,20 +3288,12 @@ _bfd_vms_write_egsd (bfd *abfd) else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) sname = EVAX_LITERAL_NAME; else if ((*sname == 'l') && (strcmp (sname, "literals") == 0)) - { - sname = EVAX_LITERALS_NAME; - abs_section_index = section->index; - } + sname = EVAX_LITERALS_NAME; else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) sname = EVAX_COMMON_NAME; else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) sname = EVAX_LOCAL_NAME; } - else - sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ__C_SECSIZ); - - _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); - _bfd_vms_output_short (recwr, section->alignment_power & 0xff); if (bfd_is_com_section (section)) new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD @@ -3271,14 +3313,17 @@ _bfd_vms_write_egsd (bfd *abfd) vms_debug2 ((3, "new_flags %x, _raw_size %lu\n", new_flags, (unsigned long)section->size)); + _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); + _bfd_vms_output_short (recwr, section->alignment_power & 0xff); _bfd_vms_output_short (recwr, new_flags); _bfd_vms_output_long (recwr, (unsigned long) section->size); _bfd_vms_output_counted (recwr, sname); _bfd_vms_output_end_subrec (recwr); - last_index = section->index; -done: - section = section->next; + /* If the section is an obsolute one, remind its index as it will be + used later for absolute symbols. */ + if ((new_flags & EGPS__V_REL) == 0 && abs_section_index < 0) + abs_section_index = section->target_index; } /* Output symbols. */ @@ -3288,33 +3333,54 @@ done: for (symnum = 0; symnum < abfd->symcount; symnum++) { - char *hash; - 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; + /* Work-around a missing feature: consider __main as the main entry + point. */ + if (symbol->name[0] == '_' && strcmp (symbol->name, "__main") == 0) + bfd_set_start_address (abfd, (bfd_vma)symbol->value); + + /* Only put in the GSD the global and the undefined symbols. */ if (old_flags & BSF_FILE) continue; - if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */ - && !bfd_is_und_section (symbol->section) /* and not xref... */ - && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */ - && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0)) - continue; + if ((old_flags & BSF_GLOBAL) == 0 && !bfd_is_und_section (symbol->section)) + { + /* If the LIB$INITIIALIZE section is present, add a reference to + LIB$INITIALIZE symbol. FIXME: this should be done explicitely + in the assembly file. */ + if (!((old_flags & BSF_SECTION_SYM) != 0 + && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0)) + continue; + } - /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */ - if (_bfd_vms_output_check (recwr, 80) < 0) + /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. Add 16 more + bytes for a possible ABS section. */ + if (_bfd_vms_output_check (recwr, 80 + 16) < 0) { _bfd_vms_output_end (abfd, recwr); _bfd_vms_output_begin (recwr, EOBJ__C_EGSD); _bfd_vms_output_long (recwr, 0); } + if ((old_flags & BSF_GLOBAL) != 0 + && bfd_is_abs_section (symbol->section) + && abs_section_index <= 0) + { + /* Create an absolute section if none was defined. It is highly + unlikely that the name $ABS$ clashes with a user defined + non-absolute section name. */ + _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC); + _bfd_vms_output_short (recwr, 4); + _bfd_vms_output_short (recwr, EGPS__V_SHR); + _bfd_vms_output_long (recwr, 0); + _bfd_vms_output_counted (recwr, "$ABS$"); + _bfd_vms_output_end_subrec (recwr); + + abs_section_index = target_index++; + } + _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM); /* Data type, alignment. */ @@ -3351,25 +3417,24 @@ done: { asymbol *sym; - sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; + sym = + ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; code_address = sym->value; - ca_psindx = sym->section->index; + ca_psindx = sym->section->target_index; } if (bfd_is_abs_section (symbol->section)) psindx = abs_section_index; else - psindx = symbol->section->index; + psindx = symbol->section->target_index; _bfd_vms_output_quad (recwr, symbol->value); _bfd_vms_output_quad (recwr, code_address); _bfd_vms_output_long (recwr, ca_psindx); _bfd_vms_output_long (recwr, psindx); } - hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ__C_SYMSIZ); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, symbol->name); _bfd_vms_output_end_subrec (recwr); - } _bfd_vms_output_alignment (recwr, 8); @@ -3385,8 +3450,6 @@ _bfd_vms_write_ehdr (bfd *abfd) { asymbol *symbol; unsigned int symnum; - int had_case = 0; - int had_file = 0; struct vms_rec_wr *recwr = &PRIV (recwr); vms_debug2 ((2, "vms_write_ehdr (%p)\n", abfd)); @@ -3406,22 +3469,9 @@ _bfd_vms_write_ehdr (bfd *abfd) if (symbol->flags & BSF_FILE) { - if (CONST_STRNEQ ((char *)symbol->name, "name[6] - '0'; - PRIV (flag_show_after_trunc) = symbol->name[7] - '0'; - - if (had_file) - break; - had_case = 1; - continue; - } - _bfd_vms_output_dump (recwr, (unsigned char *) symbol->name, (int) strlen (symbol->name)); - if (had_case) - break; - had_file = 1; + break; } } @@ -3469,8 +3519,7 @@ start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset) { struct vms_rec_wr *recwr = &PRIV (recwr); - if (section->name[0] == '.' && section->name[1] == 'v' - && !strcmp (section->name, ".vmsdebug")) + if (section->flags & SEC_DEBUGGING) { _bfd_vms_output_begin (recwr, EOBJ__C_ETBT); @@ -3494,7 +3543,7 @@ start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset) { /* Push start offset. */ _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); - _bfd_vms_output_long (recwr, (unsigned long) section->index); + _bfd_vms_output_long (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, offset); _bfd_vms_output_end_subrec (recwr); @@ -3594,12 +3643,12 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) _bfd_vms_output_alignment (recwr, 4); - PRIV (vms_linkage_index) = 1; + PRIV (vms_linkage_index) = 0; for (section = abfd->sections; section; section = section->next) { vms_debug2 ((4, "writing %d. section '%s' (%d bytes)\n", - section->index, section->name, (int) (section->size))); + section->target_index, section->name, (int) (section->size))); if (!(section->flags & SEC_HAS_CONTENTS) || bfd_is_com_section (section)) @@ -3622,7 +3671,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) int pass2_in_progress = 0; unsigned int irel; - if (section->reloc_count <= 0) + if (section->reloc_count == 0) (*_bfd_error_handler) (_("SEC_RELOC with no relocs in section %s"), section->name); @@ -3658,7 +3707,6 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) asection *sec = sym->section; bfd_boolean defer = defer_reloc_p (rptr); unsigned int slen; - char *hash; if (pass2_in_progress) { @@ -3697,13 +3745,11 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { bfd_vma addend = rptr->addend; slen = strlen ((char *) sym->name); - hash = _bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ__C_SYMSIZ); etir_output_check (abfd, section, curr_addr, slen); if (addend) { _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_end_subrec (recwr); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW); _bfd_vms_output_long (recwr, (unsigned long) addend); @@ -3717,7 +3763,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL_LW); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_end_subrec (recwr); } } @@ -3734,7 +3780,8 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { etir_output_check (abfd, section, curr_addr, 32); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); - _bfd_vms_output_long (recwr, (unsigned long) sec->index); + _bfd_vms_output_long (recwr, + (unsigned long) sec->target_index); _bfd_vms_output_quad (recwr, rptr->addend + sym->value); _bfd_vms_output_end_subrec (recwr); /* ??? Table B-8 of the OpenVMS Linker Utilily Manual @@ -3751,13 +3798,11 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { bfd_vma addend = rptr->addend; slen = strlen ((char *) sym->name); - hash = _bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ__C_SYMSIZ); etir_output_check (abfd, section, curr_addr, slen); if (addend) { _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_end_subrec (recwr); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW); _bfd_vms_output_quad (recwr, addend); @@ -3770,7 +3815,7 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) else { _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_end_subrec (recwr); } } @@ -3787,7 +3832,8 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { etir_output_check (abfd, section, curr_addr, 32); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ); - _bfd_vms_output_long (recwr, (unsigned long) sec->index); + _bfd_vms_output_long (recwr, + (unsigned long) sec->target_index); _bfd_vms_output_quad (recwr, rptr->addend + sym->value); _bfd_vms_output_end_subrec (recwr); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_OFF); @@ -3803,22 +3849,19 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) etir_output_check (abfd, section, curr_addr, 64); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB); _bfd_vms_output_long - (recwr, (unsigned long) PRIV (vms_linkage_index)); - PRIV (vms_linkage_index) += 2; - hash = _bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ__C_SYMSIZ); - _bfd_vms_output_counted (recwr, hash); + (recwr, (unsigned long) rptr->addend); + if (rptr->addend > PRIV (vms_linkage_index)) + PRIV (vms_linkage_index) = rptr->addend; + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_byte (recwr, 0); _bfd_vms_output_end_subrec (recwr); break; case ALPHA_R_CODEADDR: slen = strlen ((char *) sym->name); - hash = _bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ__C_SYMSIZ); etir_output_check (abfd, section, curr_addr, slen); _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_CA); - _bfd_vms_output_counted (recwr, hash); + _bfd_vms_output_counted (recwr, sym->name); _bfd_vms_output_end_subrec (recwr); break; @@ -3830,15 +3873,13 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_NOP_GBL); _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); _bfd_vms_output_long - (recwr, (unsigned long) udata->enbsym->section->index); + (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, rptr->address); _bfd_vms_output_long (recwr, (unsigned long) 0x47ff041f); _bfd_vms_output_long - (recwr, (unsigned long) udata->enbsym->section->index); + (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, rptr->addend); - _bfd_vms_output_counted - (recwr, _bfd_vms_length_hash_symbol - (abfd, udata->origname, EOBJ__C_SYMSIZ)); + _bfd_vms_output_counted (recwr, udata->origname); _bfd_vms_output_end_subrec (recwr); break; @@ -3855,15 +3896,13 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex + 1); _bfd_vms_output_long - (recwr, (unsigned long) udata->enbsym->section->index); + (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, rptr->address); _bfd_vms_output_long (recwr, (unsigned long) 0x237B0000); _bfd_vms_output_long - (recwr, (unsigned long) udata->bsym->section->index); + (recwr, (unsigned long) udata->bsym->section->target_index); _bfd_vms_output_quad (recwr, rptr->addend); - _bfd_vms_output_counted - (recwr, _bfd_vms_length_hash_symbol - (abfd, udata->origname, EOBJ__C_SYMSIZ)); + _bfd_vms_output_counted (recwr, udata->origname); _bfd_vms_output_end_subrec (recwr); break; @@ -3875,15 +3914,13 @@ _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_BOH_GBL); _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex); _bfd_vms_output_long - (recwr, (unsigned long) udata->enbsym->section->index); + (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, rptr->address); _bfd_vms_output_long (recwr, (unsigned long) 0xD3400000); _bfd_vms_output_long - (recwr, (unsigned long) udata->enbsym->section->index); + (recwr, (unsigned long) section->target_index); _bfd_vms_output_quad (recwr, rptr->addend); - _bfd_vms_output_counted - (recwr, _bfd_vms_length_hash_symbol - (abfd, udata->origname, EOBJ__C_SYMSIZ)); + _bfd_vms_output_counted (recwr, udata->origname); _bfd_vms_output_end_subrec (recwr); break; @@ -4480,6 +4517,11 @@ build_module_list (bfd *abfd) /* We don't have a DMT section so this must be an object. Parse the module right now in order to compute its start address and end address. */ + void *dst = PRIV (dst_section)->contents; + + if (dst == NULL) + return NULL; + module = new_module (abfd); parse_module (abfd, module, PRIV (dst_section)->contents, -1); list = module; @@ -4559,10 +4601,14 @@ module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr, location. */ static bfd_boolean -_bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section, - asymbol **symbols ATTRIBUTE_UNUSED, - bfd_vma offset, const char **file, - const char **func, unsigned int *line) +_bfd_vms_find_nearest_line (bfd *abfd, + asymbol **symbols ATTRIBUTE_UNUSED, + asection *section, + bfd_vma offset, + const char **file, + const char **func, + unsigned int *line, + unsigned int *discriminator) { struct module *module; @@ -4572,10 +4618,14 @@ _bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section, *file = NULL; *func = NULL; *line = 0; + if (discriminator) + *discriminator = 0; - if (PRIV (dst_section) == NULL || !(abfd->flags & (EXEC_P | DYNAMIC))) + /* We can't do anything if there is no DST (debug symbol table). */ + if (PRIV (dst_section) == NULL) return FALSE; + /* Create the module list - if not already done. */ if (PRIV (modules) == NULL) { PRIV (modules) = build_module_list (abfd); @@ -4619,7 +4669,7 @@ alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym) if (e->flags & EGSY__V_NORM) flags |= BSF_FUNCTION; value = e->value; - sec = PRIV (sections)[e->section]; + sec = e->section; } else { @@ -4645,35 +4695,9 @@ alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym) if (e->flags & EGSY__V_NORM) flags |= BSF_FUNCTION; - value = e->symbol_vector; - - /* Adding this offset is necessary in order for GDB to - read the DWARF-2 debug info from shared libraries. */ - if ((abfd->flags & DYNAMIC) && strstr (name, "$DWARF2.DEBUG") != 0) - value += PRIV (symvva); - + value = e->value; + /* sec = e->section; */ sec = bfd_abs_section_ptr; -#if 0 - /* Find containing section. */ - { - bfd_vma sbase = 0; - asection *s; - - for (s = abfd->sections; s; s = s->next) - { - if (value >= s->vma - && s->vma > sbase - && !(s->flags & SEC_COFF_SHARED_LIBRARY) - && (s->size > 0 || !(e->flags & EGSY__V_REL))) - { - sbase = s->vma; - sec = s; - } - } - value -= sbase; - } -#endif - break; default: @@ -4976,7 +5000,14 @@ alpha_vms_slurp_relocs (bfd *abfd) (*_bfd_error_handler) (_("Invalid section index in ETIR")); return FALSE; } + sec = PRIV (sections)[cur_psect]; + if (sec == bfd_abs_section_ptr) + { + (*_bfd_error_handler) (_("Relocation for non-REL psect")); + return FALSE; + } + vms_sec = vms_section_data (sec); /* Allocate a reloc entry. */ @@ -4987,7 +5018,7 @@ alpha_vms_slurp_relocs (bfd *abfd) vms_sec->reloc_max = 64; sec->relocation = bfd_zmalloc (vms_sec->reloc_max * sizeof (arelent)); - } + } else { vms_sec->reloc_max *= 2; @@ -5480,43 +5511,18 @@ alpha_vms_get_synthetic_symtab (bfd *abfd, switch (e->typ) { case EGSD__C_SYM: - if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM)) - { - value = e->code_value; - sec = PRIV (sections)[e->code_section]; - } - else - continue; - break; - case EGSD__C_SYMG: if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM)) { - bfd_vma sbase = 0; - asection *s; - value = e->code_value; - - /* Find containing section. */ - for (s = abfd->sections; s; s = s->next) - { - if (value >= s->vma - && s->vma > sbase - && !(s->flags & SEC_COFF_SHARED_LIBRARY) - && (s->size > 0 || !(e->flags & EGSY__V_REL))) - { - sbase = s->vma; - sec = s; - } - } - value -= sbase; + sec = e->code_section; } else continue; break; default: - abort (); + continue; } l = strlen (name); @@ -5936,7 +5942,7 @@ evax_bfd_print_etir (FILE *file, const char *name, unsigned char *rec, unsigned int rec_len) { unsigned int off = sizeof (struct vms_egsd); - unsigned int sec_len; + unsigned int sec_len = 0; fprintf (file, _(" %s (len=%u+%u):\n"), name, (unsigned)(rec_len - sizeof (struct vms_eobjrec)), @@ -6035,6 +6041,10 @@ evax_bfd_print_etir (FILE *file, const char *name, sec_len += len; } break; + case ETIR__C_STO_GBL_LW: + fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"), + buf[0], buf + 1); + break; case ETIR__C_STO_LP_PSB: fprintf (file, _("STO_OFF (store LP with procedure signature)\n")); break; @@ -7737,7 +7747,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file) } if (lpfixoff != 0) { - fprintf (file, _(" Linkage Pairs Referece Fixups:\n")); + fprintf (file, _(" Linkage Pairs Reference Fixups:\n")); evax_bfd_print_reference_fixups (file, buf + lpfixoff); } if (chgprtoff) @@ -7931,8 +7941,11 @@ alpha_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib) sl->has_fixups = TRUE; VEC_APPEND_EL (sl->lp, bfd_vma, sect->output_section->vma + sect->output_offset + offset); + sect->output_section->flags |= SEC_RELOC; } +/* Add a code address fixup at address SECT + OFFSET to SHLIB. */ + static void alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib) { @@ -7945,8 +7958,11 @@ alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib) sl->has_fixups = TRUE; VEC_APPEND_EL (sl->ca, bfd_vma, sect->output_section->vma + sect->output_offset + offset); + sect->output_section->flags |= SEC_RELOC; } +/* Add a quad word relocation fixup at address SECT + OFFSET to SHLIB. */ + static void alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src, bfd *shlib, bfd_vma vec) @@ -7962,25 +7978,19 @@ alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src, r = VEC_APPEND (sl->qr, struct alpha_vms_vma_ref); r->vma = sect->output_section->vma + sect->output_offset + offset; r->ref = vec; + sect->output_section->flags |= SEC_RELOC; } static void -alpha_vms_add_lw_fixup (struct bfd_link_info *info ATTRIBUTE_UNUSED, +alpha_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED, unsigned int shr ATTRIBUTE_UNUSED, bfd_vma vec ATTRIBUTE_UNUSED) { + /* Not yet supported. */ abort (); } -#if 0 -static void -alpha_vms_add_qw_fixup (struct bfd_link_info *info ATTRIBUTE_UNUSED, - unsigned int shr ATTRIBUTE_UNUSED, - bfd_vma vec ATTRIBUTE_UNUSED) -{ - abort (); -} -#endif +/* Add relocation. FIXME: Not yet emitted. */ static void alpha_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED) @@ -8165,7 +8175,10 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) return FALSE; if (element->archive_pass == -1 || element->archive_pass == pass) - continue; + { + /* Next symbol if this archive is wrong or already handled. */ + continue; + } if (! bfd_check_format (element, bfd_object)) { @@ -8187,10 +8200,10 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) /* Unlike the generic linker, we know that this element provides a definition for an undefined symbol and we know that we want to include it. We don't need to check anything. */ - if (! (*info->callbacks->add_archive_element) (info, element, - h->root.string)) + if (!(*info->callbacks + ->add_archive_element) (info, element, h->root.string, &element)) return FALSE; - if (! alpha_vms_link_add_object_symbols (element, info)) + if (!alpha_vms_link_add_object_symbols (element, info)) return FALSE; orig_element->archive_pass = pass; @@ -8231,6 +8244,8 @@ alpha_vms_build_fixups (struct bfd_link_info *info) unsigned int ca_sz = 0; unsigned int qr_sz = 0; unsigned int shrimg_cnt = 0; + unsigned int chgprt_num = 0; + unsigned int chgprt_sz = 0; struct vms_eiaf *eiaf; unsigned int off; asection *sec; @@ -8278,9 +8293,20 @@ alpha_vms_build_fixups (struct bfd_link_info *info) if (ca_sz + lp_sz + qr_sz == 0) return TRUE; + /* Add an eicp entry for the fixup itself. */ + chgprt_num = 1; + for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) + { + /* This isect could be made RO or EXE after relocations are applied. */ + if ((sec->flags & SEC_RELOC) != 0 + && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) + chgprt_num++; + } + chgprt_sz = 4 + chgprt_num * sizeof (struct vms_eicp); + /* Allocate section content (round-up size) */ sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl) - + ca_sz + lp_sz + qr_sz; + + ca_sz + lp_sz + qr_sz + chgprt_sz; sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1); content = bfd_zalloc (info->output_bfd, sz); if (content == NULL) @@ -8443,13 +8469,122 @@ alpha_vms_build_fixups (struct bfd_link_info *info) bfd_putl32 (0, content + off + 4); off += 8; } + } - /* CA fixups. */ + /* Write the change protection table. */ + bfd_putl32 (off, eiaf->chgprtoff); + bfd_putl32 (chgprt_num, content + off); + off += 4; + + for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next) + { + struct vms_eicp *eicp; + unsigned int prot; + + if ((sec->flags & SEC_LINKER_CREATED) != 0 && + strcmp (sec->name, "$FIXUP$") == 0) + prot = PRT__C_UREW; + else if ((sec->flags & SEC_RELOC) != 0 + && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) + prot = PRT__C_UR; + else + continue; + + eicp = (struct vms_eicp *)(content + off); + bfd_putl64 (sec->vma - t->base_addr, eicp->baseva); + bfd_putl32 ((sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1), + eicp->size); + bfd_putl32 (prot, eicp->newprt); + off += sizeof (struct vms_eicp); } return TRUE; } +/* Called by bfd_hash_traverse to fill the symbol table. + Return FALSE in case of failure. */ + +static bfd_boolean +alpha_vms_link_output_symbol (struct bfd_hash_entry *bh, void *infov) +{ + struct bfd_link_hash_entry *hc = (struct bfd_link_hash_entry *) bh; + struct bfd_link_info *info = (struct bfd_link_info *)infov; + struct alpha_vms_link_hash_entry *h; + struct vms_symbol_entry *sym; + + if (hc->type == bfd_link_hash_warning) + { + hc = hc->u.i.link; + if (hc->type == bfd_link_hash_new) + return TRUE; + } + h = (struct alpha_vms_link_hash_entry *) hc; + + switch (h->root.type) + { + case bfd_link_hash_undefined: + return TRUE; + case bfd_link_hash_new: + case bfd_link_hash_warning: + abort (); + case bfd_link_hash_undefweak: + return TRUE; + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + { + asection *sec = h->root.u.def.section; + + /* FIXME: this is certainly a symbol from a dynamic library. */ + if (bfd_is_abs_section (sec)) + return TRUE; + + if (sec->owner->flags & DYNAMIC) + return TRUE; + } + break; + case bfd_link_hash_common: + break; + case bfd_link_hash_indirect: + return TRUE; + } + + /* Do not write not kept symbols. */ + if (info->strip == strip_some + && bfd_hash_lookup (info->keep_hash, h->root.root.string, + FALSE, FALSE) != NULL) + return TRUE; + + if (h->sym == NULL) + { + /* This symbol doesn't come from a VMS object. So we suppose it is + a data. */ + int len = strlen (h->root.root.string); + + sym = (struct vms_symbol_entry *)bfd_zalloc (info->output_bfd, + sizeof (*sym) + len); + if (sym == NULL) + abort (); + sym->namelen = len; + memcpy (sym->name, h->root.root.string, len); + sym->name[len] = 0; + sym->owner = info->output_bfd; + + sym->typ = EGSD__C_SYMG; + sym->data_type = 0; + sym->flags = EGSY__V_DEF | EGSY__V_REL; + sym->symbol_vector = h->root.u.def.value; + sym->section = h->root.u.def.section; + sym->value = h->root.u.def.value; + } + else + sym = h->sym; + + if (!add_symbol_entry (info->output_bfd, sym)) + return FALSE; + + return TRUE; +} + static bfd_boolean alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) { @@ -8462,6 +8597,14 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) asection *dst; asection *dmt; + if (bfd_link_relocatable (info)) + { + /* FIXME: we do not yet support relocatable link. It is not obvious + how to do it for debug infos. */ + (*info->callbacks->einfo)(_("%P: relocatable link is not supported\n")); + return FALSE; + } + bfd_get_outsymbols (abfd) = NULL; bfd_get_symcount (abfd) = 0; @@ -8504,12 +8647,17 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) } #endif + /* Generate the symbol table. */ + BFD_ASSERT (PRIV (syms) == NULL); + if (info->strip != strip_all) + bfd_hash_traverse (&info->hash->table, alpha_vms_link_output_symbol, info); + /* Find the entry point. */ if (bfd_get_start_address (abfd) == 0) { bfd *startbfd = NULL; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { /* Consider only VMS object files. */ if (sub->xvec != abfd->xvec) @@ -8543,7 +8691,24 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) } } - /* Allocate contents. */ + /* Set transfer addresses. */ + { + int i; + struct bfd_link_hash_entry *h; + + i = 0; + PRIV (transfer_address[i++]) = 0xffffffff00000340ULL; /* SYS$IMGACT */ + h = bfd_link_hash_lookup (info->hash, "LIB$INITIALIZE", FALSE, FALSE, TRUE); + if (h != NULL && h->type == bfd_link_hash_defined) + PRIV (transfer_address[i++]) = + alpha_vms_get_sym_value (h->u.def.section, h->u.def.value); + PRIV (transfer_address[i++]) = bfd_get_start_address (abfd); + while (i < 4) + PRIV (transfer_address[i++]) = 0; + } + + /* Allocate contents. + Also compute the virtual base address. */ base_addr = (bfd_vma)-1; last_addr = 0; for (o = abfd->sections; o != NULL; o = o->next) @@ -8561,6 +8726,9 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) if (o->vma + o->size > last_addr) last_addr = o->vma + o->size; } + /* Clear the RELOC flags. Currently we don't support incremental + linking. We use the RELOC flag for computing the eicp entries. */ + o->flags &= ~SEC_RELOC; } /* Create the fixup section. */ @@ -8576,11 +8744,13 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) alpha_vms_link_hash (info)->base_addr = base_addr; /* Create the DMT section, if necessary. */ - dst = PRIV (dst_section); + BFD_ASSERT (PRIV (dst_section) == NULL); + dst = bfd_get_section_by_name (abfd, "$DST$"); if (dst != NULL && dst->size == 0) dst = NULL; if (dst != NULL) { + PRIV (dst_section) = dst; dmt = bfd_make_section_anyway_with_flags (info->output_bfd, "$DMT$", SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED); @@ -8591,7 +8761,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) dmt = NULL; /* Read all sections from the inputs. */ - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { if (sub->flags & DYNAMIC) { @@ -8642,7 +8812,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info) unsigned int off = 0; /* For each object file (ie for each module). */ - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *sub_dst; struct vms_dmt_header *dmth = NULL; @@ -8732,9 +8902,17 @@ alpha_vms_get_section_contents (bfd *abfd, asection *section, return FALSE; } - /* Alloc in memory and read ETIRs. */ - BFD_ASSERT (section->contents == NULL); + /* If the section is already in memory, just copy it. */ + if (section->flags & SEC_IN_MEMORY) + { + BFD_ASSERT (section->contents != NULL); + memcpy (buf, section->contents + offset, count); + return TRUE; + } + if (section->size == 0) + return TRUE; + /* Alloc in memory and read ETIRs. */ for (sec = abfd->sections; sec; sec = sec->next) { BFD_ASSERT (sec->contents == NULL); @@ -8749,8 +8927,8 @@ alpha_vms_get_section_contents (bfd *abfd, asection *section, if (!alpha_vms_read_sections_content (abfd, NULL)) return FALSE; for (sec = abfd->sections; sec; sec = sec->next) - if (section->contents) - section->flags |= SEC_IN_MEMORY; + if (sec->contents) + sec->flags |= SEC_IN_MEMORY; memcpy (buf, section->contents + offset, count); return TRUE; } @@ -8820,7 +8998,7 @@ vms_close_and_cleanup (bfd * abfd) format. */ if (bfd_cache_close (abfd) != TRUE) return FALSE; - if (vms_convert_to_var_unix_filename (abfd->filename) != TRUE) + if (_bfd_vms_convert_to_var_unix_filename (abfd->filename) != TRUE) return FALSE; } #endif @@ -8835,38 +9013,19 @@ vms_new_section_hook (bfd * abfd, asection *section) { bfd_size_type amt; - /* Count hasn't been incremented yet. */ - unsigned int section_count = abfd->section_count + 1; + vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n", + abfd, section->index, section->name)); - vms_debug2 ((1, "vms_new_section_hook (%p, [%d]%s), count %d\n", - abfd, section->index, section->name, section_count)); - - bfd_set_section_alignment (abfd, section, 0); - - if (section_count > PRIV (section_count)) - { - amt = section_count; - amt *= sizeof (asection *); - PRIV (sections) = bfd_realloc_or_free (PRIV (sections), amt); - if (PRIV (sections) == NULL) - return FALSE; - PRIV (section_count) = section_count; - } - - vms_debug2 ((6, "section_count: %d\n", PRIV (section_count))); - - PRIV (sections)[section->index] = section; + if (! bfd_set_section_alignment (abfd, section, 0)) + return FALSE; - vms_debug2 ((7, "%d: %s\n", section->index, section->name)); + vms_debug2 ((7, "%u: %s\n", section->index, section->name)); amt = sizeof (struct vms_section_data_struct); - section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt); + section->used_by_bfd = bfd_zalloc (abfd, amt); if (section->used_by_bfd == NULL) return FALSE; - if (strcmp (bfd_get_section_name (abfd, section), "$DST$") == 0) - PRIV (dst_section) = section; - /* Create the section symbol. */ return _bfd_generic_new_section_hook (abfd, section); } @@ -8934,7 +9093,7 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, if (ret == NULL) return; - if (sec == 0) + if (sec == NULL) ret->type = 'U'; else if (bfd_is_com_section (sec)) ret->type = 'C'; @@ -8944,14 +9103,15 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, ret->type = 'U'; else if (bfd_is_ind_section (sec)) ret->type = 'I'; - else if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + else if ((symbol->flags & BSF_FUNCTION) + || (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 = '-'; + ret->type = '?'; if (ret->type != 'U') ret->value = symbol->value + symbol->section->vma; @@ -8967,7 +9127,6 @@ static bfd_boolean vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, const char *name) { - vms_debug2 ((1, "vms_bfd_is_local_label_name (%p, %s)\n", abfd, name)); return name[0] == '$'; } @@ -9055,12 +9214,16 @@ bfd_vms_get_data (bfd *abfd) ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) #define alpha_vms_print_symbol vms_print_symbol #define alpha_vms_get_symbol_info vms_get_symbol_info +#define alpha_vms_get_symbol_version_string \ + _bfd_nosymbols_get_symbol_version_string + #define alpha_vms_read_minisymbols _bfd_generic_read_minisymbols #define alpha_vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol #define alpha_vms_get_lineno _bfd_nosymbols_get_lineno #define alpha_vms_find_inliner_info _bfd_nosymbols_find_inliner_info #define alpha_vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol -#define alpha_vms_find_nearest_line _bfd_vms_find_nearest_dst_line +#define alpha_vms_find_nearest_line _bfd_vms_find_nearest_line +#define alpha_vms_find_line _bfd_nosymbols_find_line #define alpha_vms_bfd_is_local_label_name vms_bfd_is_local_label_name /* Generic table. */ @@ -9075,6 +9238,7 @@ bfd_vms_get_data (bfd *abfd) #define alpha_vms_bfd_relax_section bfd_generic_relax_section #define alpha_vms_bfd_gc_sections bfd_generic_gc_sections +#define alpha_vms_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define alpha_vms_bfd_merge_sections bfd_generic_merge_sections #define alpha_vms_bfd_is_group_section bfd_generic_is_group_section #define alpha_vms_bfd_discard_group bfd_generic_discard_group @@ -9082,7 +9246,6 @@ bfd_vms_get_data (bfd *abfd) _bfd_generic_section_already_linked #define alpha_vms_bfd_define_common_symbol bfd_generic_define_common_symbol -#define alpha_vms_bfd_link_hash_table_free _bfd_generic_link_hash_table_free #define alpha_vms_bfd_link_just_syms _bfd_generic_link_just_syms #define alpha_vms_bfd_copy_link_hash_symbol_type \ _bfd_generic_copy_link_hash_symbol_type @@ -9098,7 +9261,7 @@ bfd_vms_get_data (bfd *abfd) #define alpha_vms_canonicalize_dynamic_reloc \ _bfd_nodynamic_canonicalize_dynamic_reloc -const bfd_target vms_alpha_vec = +const bfd_target alpha_vms_vec = { "vms-alpha", /* Name. */ bfd_target_evax_flavour, @@ -9113,6 +9276,7 @@ const bfd_target vms_alpha_vec = 0, /* symbol_leading_char. */ ' ', /* ar_pad_char. */ 15, /* ar_max_namelen. */ + 0, /* match priority. */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, bfd_getl16, bfd_getl_signed_16, bfd_putl16, @@ -9123,7 +9287,7 @@ const bfd_target vms_alpha_vec = {_bfd_dummy_target, alpha_vms_object_p, /* bfd_check_format. */ _bfd_vms_lib_alpha_archive_p, _bfd_dummy_target}, {bfd_false, alpha_vms_mkobject, /* bfd_set_format. */ - _bfd_vms_lib_mkarchive, bfd_false}, + _bfd_vms_lib_alpha_mkarchive, bfd_false}, {bfd_false, alpha_vms_write_object_contents, /* bfd_write_contents. */ _bfd_vms_lib_write_archive_contents, bfd_false}, @@ -9139,5 +9303,5 @@ const bfd_target vms_alpha_vec = NULL, - (PTR) 0 + NULL };