bfd: use default coff_write_object_contents for XCOFF64

There is no need for XCOFF64 to have is own write_object_contents.

	* coff64-rs6000.c (xcoff64_write_object_contents): Remove.
	* coffcode.h (coff_write_object_contents): Add bfd_mach_ppc_620
	support for o_cputype field.  Avoid creating an empty a.out header
	for XCOFF64.
This commit is contained in:
Clément Chigot 2021-03-11 11:08:18 +01:00 committed by Alan Modra
parent 8aa2d0236a
commit 6d4d932867
3 changed files with 14 additions and 351 deletions

View File

@ -1,3 +1,10 @@
2021-03-12 Clément Chigot <clement.chigot@atos.net>
* coff64-rs6000.c (xcoff64_write_object_contents): Remove.
* coffcode.h (coff_write_object_contents): Add bfd_mach_ppc_620
support for o_cputype field. Avoid creating an empty a.out header
for XCOFF64.
2021-03-12 Clément Chigot <clement.chigot@atos.net>
* coff64-rs6000.c (xcoff64_create_csect_from_smclas): Add

View File

@ -147,8 +147,6 @@ static void xcoff64_swap_ldrel_in
(bfd *, const void *, struct internal_ldrel *);
static void xcoff64_swap_ldrel_out
(bfd *, const struct internal_ldrel *, void *d);
static bfd_boolean xcoff64_write_object_contents
(bfd *);
static bfd_boolean xcoff64_ppc_relocate_section
(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
struct internal_reloc *, struct internal_syment *,
@ -711,352 +709,6 @@ xcoff64_swap_ldrel_out (bfd *abfd, const struct internal_ldrel *src, void *d)
bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
}
static bfd_boolean
xcoff64_write_object_contents (bfd *abfd)
{
asection *current;
bfd_boolean hasrelocs = FALSE;
bfd_boolean haslinno = FALSE;
file_ptr scn_base;
file_ptr reloc_base;
file_ptr lineno_base;
file_ptr sym_base;
unsigned long reloc_size = 0;
unsigned long lnno_size = 0;
asection *text_sec = NULL;
asection *data_sec = NULL;
asection *bss_sec = NULL;
struct internal_filehdr internal_f;
struct internal_aouthdr internal_a;
bfd_set_error (bfd_error_system_call);
if (! abfd->output_has_begun)
{
if (! bfd_coff_compute_section_file_positions (abfd))
return FALSE;
}
/* Work out the size of the reloc and linno areas. */
reloc_base = obj_relocbase (abfd);
for (current = abfd->sections; current != NULL; current = current->next)
reloc_size += current->reloc_count * bfd_coff_relsz (abfd);
lineno_base = reloc_base + reloc_size;
/* Make a pass through the symbol table to count line number entries and
put them into the correct asections. */
lnno_size = coff_count_linenumbers (abfd) * bfd_coff_linesz (abfd);
sym_base = lineno_base + lnno_size;
/* Indicate in each section->line_filepos its actual file address. */
for (current = abfd->sections; current != NULL; current = current->next)
{
if (current->lineno_count)
{
current->line_filepos = lineno_base;
current->moving_line_filepos = lineno_base;
lineno_base += current->lineno_count * bfd_coff_linesz (abfd);
}
else
{
current->line_filepos = 0;
}
if (current->reloc_count)
{
current->rel_filepos = reloc_base;
reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
}
else
{
current->rel_filepos = 0;
}
}
if ((abfd->flags & EXEC_P) != 0)
{
scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
internal_f.f_opthdr = bfd_coff_aoutsz (abfd);
}
else
{
scn_base = bfd_coff_filhsz (abfd);
internal_f.f_opthdr = 0;
}
internal_f.f_nscns = 0;
if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
return FALSE;
for (current = abfd->sections; current != NULL; current = current->next)
{
struct internal_scnhdr section;
struct external_scnhdr buff;
bfd_size_type amount;
internal_f.f_nscns++;
strncpy (section.s_name, current->name, SCNNMLEN);
section.s_vaddr = current->vma;
section.s_paddr = current->lma;
section.s_size = current->size;
/* If this section has no size or is unloadable then the scnptr
will be 0 too. */
if (current->size == 0
|| (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
{
section.s_scnptr = 0;
}
else
{
section.s_scnptr = current->filepos;
}
section.s_relptr = current->rel_filepos;
section.s_lnnoptr = current->line_filepos;
section.s_nreloc = current->reloc_count;
section.s_nlnno = current->lineno_count;
if (current->reloc_count != 0)
hasrelocs = TRUE;
if (current->lineno_count != 0)
haslinno = TRUE;
section.s_flags = sec_to_styp_flags (current->name, current->flags);
if (!strcmp (current->name, _TEXT))
{
text_sec = current;
}
else if (!strcmp (current->name, _DATA))
{
data_sec = current;
}
else if (!strcmp (current->name, _BSS))
{
bss_sec = current;
}
amount = bfd_coff_scnhsz (abfd);
if (bfd_coff_swap_scnhdr_out (abfd, &section, &buff) == 0
|| bfd_bwrite (&buff, amount, abfd) != amount)
return FALSE;
}
internal_f.f_timdat = 0;
internal_f.f_flags = 0;
if (!hasrelocs)
internal_f.f_flags |= F_RELFLG;
if (!haslinno)
internal_f.f_flags |= F_LNNO;
if (abfd->flags & EXEC_P)
internal_f.f_flags |= F_EXEC;
/* FIXME: this is wrong for PPC_PE! */
if (bfd_little_endian (abfd))
internal_f.f_flags |= F_AR32WR;
else
internal_f.f_flags |= F_AR32W;
if ((abfd->flags & DYNAMIC) != 0)
internal_f.f_flags |= F_SHROBJ;
if (bfd_get_section_by_name (abfd, _LOADER) != NULL)
internal_f.f_flags |= F_DYNLOAD;
memset (&internal_a, 0, sizeof internal_a);
internal_f.f_magic = bfd_xcoff_magic_number (abfd);
internal_a.magic = (abfd->flags & D_PAGED
? RS6K_AOUTHDR_ZMAGIC
: (abfd->flags & WP_TEXT
? RS6K_AOUTHDR_NMAGIC
: RS6K_AOUTHDR_OMAGIC));
/* FIXME: Does anybody ever set this to another value? */
internal_a.vstamp = 0;
/* Now should write relocs, strings, syms. */
obj_sym_filepos (abfd) = sym_base;
internal_f.f_symptr = 0;
internal_f.f_nsyms = 0;
/* If bfd_get_symcount (abfd) != 0, then we are not using the COFF
backend linker, and obj_raw_syment_count is not valid until after
coff_write_symbols is called. */
if (bfd_get_symcount (abfd) != 0)
{
int firstundef;
if (!coff_renumber_symbols (abfd, &firstundef))
return FALSE;
coff_mangle_symbols (abfd);
if (! coff_write_symbols (abfd))
return FALSE;
if (! coff_write_linenumbers (abfd))
return FALSE;
if (! coff_write_relocs (abfd, firstundef))
return FALSE;
internal_f.f_symptr = sym_base;
internal_f.f_nsyms = bfd_get_symcount (abfd);
}
else if (obj_raw_syment_count (abfd) != 0)
{
internal_f.f_symptr = sym_base;
/* AIX appears to require that F_RELFLG not be set if there are
local symbols but no relocations. */
internal_f.f_flags &=~ F_RELFLG;
}
else
{
internal_f.f_flags |= F_LSYMS;
}
if (text_sec)
{
internal_a.tsize = text_sec->size;
internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
}
if (data_sec)
{
internal_a.dsize = data_sec->size;
internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
}
if (bss_sec)
{
internal_a.bsize = bss_sec->size;
if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
internal_a.data_start = bss_sec->vma;
}
internal_a.entry = bfd_get_start_address (abfd);
internal_f.f_nsyms = obj_raw_syment_count (abfd);
if (xcoff_data (abfd)->full_aouthdr)
{
bfd_vma toc;
asection *loader_sec;
internal_a.vstamp = 1;
internal_a.o_snentry = xcoff_data (abfd)->snentry;
if (internal_a.o_snentry == 0)
internal_a.entry = (bfd_vma) -1;
if (text_sec != NULL)
{
internal_a.o_sntext = text_sec->target_index;
internal_a.o_algntext = bfd_section_alignment (text_sec);
}
else
{
internal_a.o_sntext = 0;
internal_a.o_algntext = 0;
}
if (data_sec != NULL)
{
internal_a.o_sndata = data_sec->target_index;
internal_a.o_algndata = bfd_section_alignment (data_sec);
}
else
{
internal_a.o_sndata = 0;
internal_a.o_algndata = 0;
}
loader_sec = bfd_get_section_by_name (abfd, ".loader");
if (loader_sec != NULL)
internal_a.o_snloader = loader_sec->target_index;
else
internal_a.o_snloader = 0;
if (bss_sec != NULL)
internal_a.o_snbss = bss_sec->target_index;
else
internal_a.o_snbss = 0;
toc = xcoff_data (abfd)->toc;
internal_a.o_toc = toc;
internal_a.o_sntoc = xcoff_data (abfd)->sntoc;
internal_a.o_modtype = xcoff_data (abfd)->modtype;
if (xcoff_data (abfd)->cputype != -1)
internal_a.o_cputype = xcoff_data (abfd)->cputype;
else
{
switch (bfd_get_arch (abfd))
{
case bfd_arch_rs6000:
internal_a.o_cputype = 4;
break;
case bfd_arch_powerpc:
if (bfd_get_mach (abfd) == bfd_mach_ppc)
internal_a.o_cputype = 3;
else if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
internal_a.o_cputype = 2;
else
internal_a.o_cputype = 1;
break;
default:
abort ();
}
}
internal_a.o_maxstack = xcoff_data (abfd)->maxstack;
internal_a.o_maxdata = xcoff_data (abfd)->maxdata;
}
if (bfd_seek (abfd, (file_ptr) 0, 0) != 0)
return FALSE;
{
char * buff;
bfd_size_type amount = bfd_coff_filhsz (abfd);
buff = bfd_malloc (amount);
if (buff == NULL)
return FALSE;
bfd_coff_swap_filehdr_out (abfd, &internal_f, buff);
amount = bfd_bwrite (buff, amount, abfd);
free (buff);
if (amount != bfd_coff_filhsz (abfd))
return FALSE;
}
if (abfd->flags & EXEC_P)
{
char * buff;
bfd_size_type amount = bfd_coff_aoutsz (abfd);
buff = bfd_malloc (amount);
if (buff == NULL)
return FALSE;
bfd_coff_swap_aouthdr_out (abfd, &internal_a, buff);
amount = bfd_bwrite (buff, amount, abfd);
free (buff);
if (amount != bfd_coff_aoutsz (abfd))
return FALSE;
}
return TRUE;
}
static bfd_boolean
xcoff64_reloc_type_br (bfd *input_bfd,
@ -2702,7 +2354,7 @@ const bfd_target rs6000_xcoff64_vec =
{/* bfd_write_contents */
_bfd_bool_bfd_false_error,
xcoff64_write_object_contents,
coff_write_object_contents,
_bfd_xcoff_write_archive_contents,
_bfd_bool_bfd_false_error
},
@ -2966,7 +2618,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
{/* bfd_write_contents */
_bfd_bool_bfd_false_error,
xcoff64_write_object_contents,
coff_write_object_contents,
_bfd_xcoff_write_archive_contents,
_bfd_bool_bfd_false_error
},

View File

@ -4058,6 +4058,8 @@ coff_write_object_contents (bfd * abfd)
case bfd_arch_powerpc:
if (bfd_get_mach (abfd) == bfd_mach_ppc)
internal_a.o_cputype = 3;
else if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
internal_a.o_cputype = 2;
else
internal_a.o_cputype = 1;
break;
@ -4127,12 +4129,13 @@ coff_write_object_contents (bfd * abfd)
#endif
}
#ifdef RS6000COFF_C
#ifndef XCOFF64
else
{
AOUTHDR buff;
size_t size;
/* XCOFF seems to always write at least a small a.out header. */
/* XCOFF32 seems to always write at least a small a.out header. */
coff_swap_aouthdr_out (abfd, & internal_a, & buff);
if (xcoff_data (abfd)->full_aouthdr)
size = bfd_coff_aoutsz (abfd);
@ -4141,6 +4144,7 @@ coff_write_object_contents (bfd * abfd)
if (bfd_bwrite (& buff, (bfd_size_type) size, abfd) != size)
return FALSE;
}
#endif
#endif
return TRUE;