/* 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.
+ 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Initial version written by Klaus Kaempf (kkaempf@rmi.de)
Major rewrite by Adacore.
struct module *modules; /* list of all compilation units */
+ /* The DST section. */
asection *dst_section;
unsigned int dst_ptr_offsets_count; /* # of offsets in following array */
struct vms_internal_eisd_map *gbl_eisd_tail;
/* linkage index counter used by conditional store commands */
- int vms_linkage_index;
+ unsigned int vms_linkage_index;
/* see tc-alpha.c of gas for a description. */
int flag_hash_long_names; /* -+, hash instead of truncate */
{
struct bfd_link_hash_table root;
- /* Vector of shared libaries. */
+ /* Vector of shared libraries. */
struct vector_type shrlibs;
/* Fixup section. */
/* 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;
0 },
{ EVAX_CODE_NAME,
EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
- SEC_CODE,
+ SEC_CODE | SEC_READONLY,
EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
- SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
+ 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 },
+ 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 },
+ 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_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 },
+ 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 },
+ 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_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 },
+ 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 }
+ SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }
};
/* Retrieve BFD section flags by name and size. */
/* Program section definition. */
{
struct vms_egps *egps = (struct vms_egps *)vms_rec;
- flagword new_flags, old_flags;
+ flagword new_flags, vms_flags;
asection *section;
- old_flags = bfd_getl16 (egps->flags);
+ vms_flags = bfd_getl16 (egps->flags);
- if ((old_flags & EGPS__V_REL) == 0)
+ if ((vms_flags & EGPS__V_REL) == 0)
{
- /* Use the global absolute section for all absolute sections. */
+ /* Use the global absolute section for all
+ absolute sections. */
section = bfd_abs_section_ptr;
}
else
section->size = bfd_getl32 (egps->alloc);
section->alignment_power = egps->align;
- vms_section_data (section)->flags = old_flags;
+ 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 (!(old_flags & EGPS__V_NOMOD) && 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 (old_flags & EGPS__V_REL)
+ 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;
#if VMS_DEBUG
_bfd_vms_debug (4, "etir: %s(%d)\n",
_bfd_vms_etir_name (cmd), cmd);
- _bfd_hexdump (8, ptr, cmd_length - 4, (intptr_t) ptr);
+ _bfd_hexdump (8, ptr, cmd_length - 4, 0);
#endif
switch (cmd)
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;
_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. */
if (sec->flags & SEC_CODE)
eisd->u.eisd.flags |= EISD__M_EXE;
- else if (!(sec->flags & SEC_READONLY))
+ if (!(sec->flags & SEC_READONLY))
eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
/* 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_LOAD))
+ if (!(sec->flags & SEC_HAS_CONTENTS))
{
eisd->u.eisd.flags |= EISD__M_DZRO;
eisd->u.eisd.flags &= ~EISD__M_CRF;
_bfd_vms_output_alignment (recwr, 4);
- PRIV (vms_linkage_index) = 1;
+ PRIV (vms_linkage_index) = 0;
for (section = abfd->sections; section; section = section->next)
{
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);
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;
+ (recwr, (unsigned long) rptr->addend);
+ if (rptr->addend > PRIV (vms_linkage_index))
+ PRIV (vms_linkage_index) = rptr->addend;
hash = _bfd_vms_length_hash_symbol
(abfd, sym->name, EOBJ__C_SYMSIZ);
_bfd_vms_output_counted (recwr, hash);
_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->target_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->target_index);
+ (recwr, (unsigned long) section->target_index);
_bfd_vms_output_quad (recwr, rptr->addend);
_bfd_vms_output_counted
(recwr, _bfd_vms_length_hash_symbol
_bfd_vms_output_long
(recwr, (unsigned long) udata->lkindex + 1);
_bfd_vms_output_long
- (recwr,
- (unsigned long) udata->enbsym->section->target_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
_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->target_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->target_index);
+ (recwr, (unsigned long) section->target_index);
_bfd_vms_output_quad (recwr, rptr->addend);
_bfd_vms_output_counted
(recwr, _bfd_vms_length_hash_symbol
/* 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;
*func = NULL;
*line = 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);
(*_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. */
vms_sec->reloc_max = 64;
sec->relocation = bfd_zmalloc
(vms_sec->reloc_max * sizeof (arelent));
- }
+ }
else
{
vms_sec->reloc_max *= 2;
}
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)
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))
{
return TRUE;
}
-/* Called by bfd_link_hash_traverse to fill the symbol table.
+/* 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_link_hash_entry *hc, void *infov)
+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 alpha_vms_link_hash_entry *)hc;
+ 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_new:
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_common:
break;
case bfd_link_hash_indirect:
- case bfd_link_hash_warning:
return TRUE;
}
/* Generate the symbol table. */
BFD_ASSERT (PRIV (syms) == NULL);
if (info->strip != strip_all)
- bfd_link_hash_traverse (info->hash, alpha_vms_link_output_symbol, info);
+ bfd_hash_traverse (&info->hash->table, alpha_vms_link_output_symbol, info);
/* Find the entry point. */
if (bfd_get_start_address (abfd) == 0)
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);
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;
}
vms_debug2 ((7, "%d: %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;
#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
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,
NULL,
- (PTR) 0
+ NULL
};