aboutsummaryrefslogtreecommitdiff
path: root/bfd/vms-alpha.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/vms-alpha.c')
-rw-r--r--bfd/vms-alpha.c176
1 files changed, 127 insertions, 49 deletions
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 294bd90..92d0693 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -89,6 +89,7 @@
#define ALPHA_R_BSR 15
#define ALPHA_R_LDA 16
#define ALPHA_R_BOH 17
+
/* These are used with DST_S_C_LINE_NUM. */
#define DST_S_C_LINE_NUM_HEADER_SIZE 4
@@ -291,7 +292,6 @@ struct vms_private_data_struct
/* Content reading. */
asection *image_section; /* section for image_ptr */
file_ptr image_offset; /* Offset for image_ptr. */
- bfd_boolean image_autoextend; /* Resize section if necessary. */
struct module *modules; /* list of all compilation units */
@@ -1383,30 +1383,6 @@ dst_retrieve_location (bfd *abfd, unsigned int loc)
return PRIV (dst_ptr_offsets)[loc];
}
-/* Check that the DST section is big enough for the specified
- amount of bytes. */
-
-static void
-dst_check_allocation (bfd *abfd, unsigned int size)
-{
- asection *section = PRIV (image_section);
-
- section->size += size;
-
- /* Grow the section as necessary */
- if (section->size <= section->rawsize)
- return;
- do
- {
- if (section->rawsize == 0)
- section->rawsize = 1024;
- else
- section->rawsize *= 2;
- }
- while (section->size > section->rawsize);
- section->contents = bfd_realloc (section->contents, section->rawsize);
-}
-
/* Write multiple bytes to section image. */
static bfd_boolean
@@ -1418,9 +1394,6 @@ image_write (bfd *abfd, unsigned char *ptr, int size)
_bfd_hexdump (9, ptr, size, 0);
#endif
- if (PRIV (image_autoextend))
- dst_check_allocation (abfd, size);
-
if (PRIV (image_section)->contents != NULL)
{
asection *sec = PRIV (image_section);
@@ -1667,6 +1640,10 @@ alpha_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info,
return vma + sec->vma;
}
+/* Read an ETIR record from ABFD. If INFO is not null, put the content into
+ the output section (used during linking).
+ Return FALSE in case of error. */
+
static bfd_boolean
_bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
{
@@ -2263,11 +2240,11 @@ vms_slurp_debug (bfd *abfd)
PRIV (image_section) = section;
PRIV (image_offset) = section->size;
- PRIV (image_autoextend) = FALSE;
if (!_bfd_vms_slurp_etir (abfd, NULL))
return FALSE;
+ section->size = PRIV (image_offset);
return TRUE;
}
@@ -2279,7 +2256,7 @@ _bfd_vms_slurp_edbg (bfd *abfd)
{
vms_debug2 ((2, "EDBG\n"));
- abfd->flags |= (HAS_DEBUG | HAS_LINENO);
+ abfd->flags |= HAS_DEBUG | HAS_LINENO;
return vms_slurp_debug (abfd);
}
@@ -2334,21 +2311,20 @@ _bfd_vms_slurp_eeom (bfd *abfd)
static bfd_boolean
_bfd_vms_slurp_object_records (bfd * abfd)
{
- int err, new_type, type = -1;
+ bfd_boolean err;
+ int type;
do
{
vms_debug2 ((7, "reading at %08lx\n", (unsigned long)bfd_tell (abfd)));
- new_type = _bfd_vms_get_object_record (abfd);
- if (new_type < 0)
+ type = _bfd_vms_get_object_record (abfd);
+ if (type < 0)
{
vms_debug2 ((2, "next_record failed\n"));
return FALSE;
}
- type = new_type;
-
switch (type)
{
case EOBJ__C_EMH:
@@ -2598,6 +2574,8 @@ alpha_vms_file_position_block (bfd *abfd)
PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE);
}
+/* Convert from internal structure SRC to external structure DST. */
+
static void
alpha_vms_swap_eisd_out (struct vms_internal_eisd_map *src,
struct vms_eisd *dst)
@@ -2636,6 +2614,9 @@ alpha_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd)
PRIV (gbl_eisd_tail) = eisd;
}
+/* Create an EISD for shared image SHRIMG.
+ Return FALSE in case of error. */
+
static bfd_boolean
alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
{
@@ -2677,6 +2658,9 @@ alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
return TRUE;
}
+/* Create an EISD for section SEC.
+ Return FALSE in case of failure. */
+
static bfd_boolean
alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
{
@@ -2732,6 +2716,9 @@ alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
return TRUE;
}
+/* Layout executable ABFD and write it to the disk.
+ Return FALSE in case of failure. */
+
static bfd_boolean
alpha_vms_write_exec (bfd *abfd)
{
@@ -2743,7 +2730,9 @@ alpha_vms_write_exec (bfd *abfd)
struct vms_internal_eisd_map *first_eisd;
struct vms_internal_eisd_map *eisd;
asection *dst;
+ asection *dmt;
+ /* Build the EIHD. */
PRIV (file_pos) = EIHD__C_LENGTH;
memset (&eihd, 0, sizeof (eihd));
@@ -2821,9 +2810,8 @@ alpha_vms_write_exec (bfd *abfd)
eihi->imgbid[0] = 0;
/* Alloc EIHS. */
- dst = bfd_get_section_by_name (abfd, "$DST$");
- if (dst == NULL || dst->size == 0)
- dst = bfd_get_section_by_name (abfd, "$TBT$");
+ dst = PRIV (dst_section);
+ dmt = bfd_get_section_by_name (abfd, "$DMT$");
if (dst != NULL && dst->size != 0)
{
eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos));
@@ -2840,7 +2828,7 @@ alpha_vms_write_exec (bfd *abfd)
bfd_putl32 (0, eihs->dmtsize);
}
- /* One per section. */
+ /* One EISD per section. */
for (sec = abfd->sections; sec; sec = sec->next)
{
if (!alpha_vms_create_eisd_for_section (abfd, sec))
@@ -2920,6 +2908,12 @@ alpha_vms_write_exec (bfd *abfd)
{
bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn);
bfd_putl32 (dst->size, eihs->dstsize);
+
+ if (dmt != NULL)
+ {
+ bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn);
+ bfd_putl32 (dmt->size, eihs->dmtsize);
+ }
}
/* Write EISD in hdr. */
@@ -7362,8 +7356,8 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
(unsigned)bfd_getl32 (eihs.minorid));
dst_vbn = bfd_getl32 (eihs.dstvbn);
dst_size = bfd_getl32 (eihs.dstsize);
- fprintf (file, _(" debug symbol table : vbn: %u, size: %u\n"),
- dst_vbn, dst_size);
+ fprintf (file, _(" debug symbol table : vbn: %u, size: %u (0x%x)\n"),
+ dst_vbn, dst_size, dst_size);
gst_vbn = bfd_getl32 (eihs.gstvbn);
gst_size = bfd_getl32 (eihs.gstsize);
fprintf (file, _(" global symbol table: vbn: %u, records: %u\n"),
@@ -7499,7 +7493,7 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
}
count = bfd_getl16 (dmth.psect_count);
fprintf (file,
- _(" module address: 0x%08x, size: 0x%08x, (%u psect)\n"),
+ _(" module address: 0x%08x, size: 0x%08x, (%u psects)\n"),
(unsigned)bfd_getl32 (dmth.modbeg),
(unsigned)bfd_getl32 (dmth.size), count);
dmt_size -= sizeof (dmth);
@@ -7745,7 +7739,7 @@ vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr)
/* Linking. */
-/* Slurp an ordered set of VMS object records. */
+/* Slurp ETIR/EDBG/ETBT VMS object records. */
static bfd_boolean
alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
@@ -7758,8 +7752,6 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
if (bfd_seek (abfd, 0, SEEK_SET) != 0)
return FALSE;
- PRIV (image_autoextend) = FALSE;
-
cur_section = NULL;
cur_offset = 0;
@@ -7769,6 +7761,7 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
{
if (info->strip == strip_all || info->strip == strip_debugger)
{
+ /* Discard the DST section. */
dst_offset = 0;
dst_section = NULL;
}
@@ -7805,9 +7798,7 @@ alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
continue;
PRIV (image_section) = dst_section;
PRIV (image_offset) = dst_offset;
- PRIV (image_autoextend) = TRUE;
res = _bfd_vms_slurp_etir (abfd, info);
- PRIV (image_autoextend) = FALSE;
dst_offset = PRIV (image_offset);
break;
case EOBJ__C_EEOM:
@@ -8372,6 +8363,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
asection *fixupsec;
bfd_vma base_addr;
bfd_vma last_addr;
+ asection *dst;
bfd_get_outsymbols (abfd) = NULL;
bfd_get_symcount (abfd) = 0;
@@ -8415,7 +8407,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
}
#endif
- /* Find entry point. */
+ /* Find the entry point. */
if (bfd_get_start_address (abfd) == 0)
{
bfd *startbfd = NULL;
@@ -8454,7 +8446,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
}
}
- /* Allocate content. */
+ /* Allocate contents. */
base_addr = (bfd_vma)-1;
last_addr = 0;
for (o = abfd->sections; o != NULL; o = o->next)
@@ -8474,6 +8466,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
}
}
+ /* Create the fixup section. */
fixupsec = bfd_make_section_anyway_with_flags
(info->output_bfd, "$FIXUP$",
SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
@@ -8524,6 +8517,91 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
if (!alpha_vms_build_fixups (info))
return FALSE;
+ /* Compute the DMT. */
+ dst = PRIV (dst_section);
+ if (dst != NULL && dst->size == 0)
+ dst = NULL;
+ if (dst != NULL)
+ {
+ asection *dmt;
+ int pass;
+ unsigned char *contents = NULL;
+
+ dmt = bfd_make_section_anyway_with_flags
+ (info->output_bfd, "$DMT$",
+ SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
+ if (dmt == NULL)
+ return FALSE;
+
+ /* In pass 1, compute the size. In pass 2, write the DMT contents. */
+ for (pass = 0; pass < 2; pass++)
+ {
+ unsigned int off = 0;
+
+ /* For each object file (ie for each module). */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *sub_dst;
+ struct vms_dmt_header *dmth = NULL;
+ unsigned int psect_count;
+
+ /* Skip this module if it has no DST. */
+ sub_dst = PRIV2 (sub, dst_section);
+ if (sub_dst == NULL || sub_dst->size == 0)
+ continue;
+
+ if (pass == 1)
+ {
+ /* Write the header. */
+ dmth = (struct vms_dmt_header *)(contents + off);
+ bfd_putl32 (sub_dst->output_offset, dmth->modbeg);
+ bfd_putl32 (sub_dst->size, dmth->size);
+ }
+
+ off += sizeof (struct vms_dmt_header);
+ psect_count = 0;
+
+ /* For each section (ie for each psect). */
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ /* Only consider interesting sections. */
+ if (!(o->flags & SEC_ALLOC))
+ continue;
+ if (o->flags & SEC_LINKER_CREATED)
+ continue;
+
+ if (pass == 1)
+ {
+ /* Write an entry. */
+ struct vms_dmt_psect *dmtp;
+
+ dmtp = (struct vms_dmt_psect *)(contents + off);
+ bfd_putl32 (o->output_offset + o->output_section->vma,
+ dmtp->start);
+ bfd_putl32 (o->size, dmtp->length);
+ psect_count++;
+ }
+ off += sizeof (struct vms_dmt_psect);
+ }
+ if (pass == 1)
+ bfd_putl32 (psect_count, dmth->psect_count);
+ }
+
+ if (pass == 0)
+ {
+ contents = bfd_zalloc (info->output_bfd, off);
+ if (contents == NULL)
+ return FALSE;
+ dmt->contents = contents;
+ dmt->size = off;
+ }
+ else
+ {
+ BFD_ASSERT (off == dmt->size);
+ }
+ }
+ }
+
return TRUE;
}