* bfd/bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.

* bfd/elf32-arm.h (struct elf32_elf_section_map): New.
	(struct _arm_elf_section_data): New.
	(elf32_arm_section_data): Define.
	(struct elf32_arm_link_hash_table): Add byteswap_code.
	(elf32_arm_link_hash_table_create): Initialize byteswap_code.
	(bfd_elf32_arm_process_before_allocation): Add byteswap_code.
	(elf32_arm_post_process_headers): Set EF_ARM_BE8.
	(elf32_arm_output_symbol_hook, elf32_arm_new_section_hook,
	elf32_arm_compare_mapping, elf32_arm_write_section): New functions.
	(bfd_elf32_new_section_hook, elf_backend_write_section,
	elf_backend_link_output_symbol_hook): Define.
	* ld/emultempl/armelf.em (byteswap_code): Add.
	(arm_elf_before_allocation): Pass extra parameter.
	(PARSE_AND_LIST_PROLOGUE): Add OPTION_BE8.
	(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add be8.
	(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_BE8.
	* ld/emultempl/armelf_oabi.em: Pass extra parameter.
	* ld/ld.texinfo: Document --be8.
This commit is contained in:
Paul Brook 2004-04-01 11:20:04 +00:00
parent 935a41f543
commit e489d0aef7
8 changed files with 232 additions and 7 deletions

View File

@ -1,3 +1,18 @@
2004-04-01 Paul Brook <paul@codesourcery.com>
* bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.
* elf32-arm.h (struct elf32_elf_section_map): New.
(struct _arm_elf_section_data): New.
(elf32_arm_section_data): Define.
(struct elf32_arm_link_hash_table): Add byteswap_code.
(elf32_arm_link_hash_table_create): Initialize byteswap_code.
(bfd_elf32_arm_process_before_allocation): Add byteswap_code.
(elf32_arm_post_process_headers): Set EF_ARM_BE8.
(elf32_arm_output_symbol_hook, elf32_arm_new_section_hook,
elf32_arm_compare_mapping, elf32_arm_write_section): New functions.
(bfd_elf32_new_section_hook, elf_backend_write_section,
elf_backend_link_output_symbol_hook): Define.
2004-04-01 Andy Chittenden <achittenden@bluearc.com> 2004-04-01 Andy Chittenden <achittenden@bluearc.com>
* stabs.c (struct stab_link_includes_totals): Add field 'symb' * stabs.c (struct stab_link_includes_totals): Add field 'symb'

View File

@ -786,7 +786,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
(struct bfd_link_info *); (struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation extern bfd_boolean bfd_elf32_arm_process_before_allocation
(bfd *, struct bfd_link_info *, int); (bfd *, struct bfd_link_info *, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);

View File

@ -793,7 +793,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
(struct bfd_link_info *); (struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation extern bfd_boolean bfd_elf32_arm_process_before_allocation
(bfd *, struct bfd_link_info *, int); (bfd *, struct bfd_link_info *, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);

View File

@ -106,7 +106,7 @@ bfd_boolean bfd_elf32_arm_allocate_interworking_sections
bfd_boolean bfd_elf32_arm_get_bfd_for_interworking bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
PARAMS ((bfd *, struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
bfd_boolean bfd_elf32_arm_process_before_allocation bfd_boolean bfd_elf32_arm_process_before_allocation
PARAMS ((bfd *, struct bfd_link_info *, int)); PARAMS ((bfd *, struct bfd_link_info *, int, int));
#endif #endif
@ -190,6 +190,26 @@ static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] =
#endif #endif
/* Used to build a map of a section. This is required for mixed-endian
code/data. */
typedef struct elf32_elf_section_map
{
bfd_vma vma;
char type;
}
elf32_arm_section_map;
struct _arm_elf_section_data
{
struct bfd_elf_section_data elf;
int mapcount;
elf32_arm_section_map *map;
};
#define elf32_arm_section_data(sec) \
((struct _arm_elf_section_data *) elf_section_data (sec))
/* The ARM linker needs to keep track of the number of relocs that it /* The ARM linker needs to keep track of the number of relocs that it
decides to copy in check_relocs for each symbol. This is so that decides to copy in check_relocs for each symbol. This is so that
it can discard PC relative relocs if it doesn't need them when it can discard PC relative relocs if it doesn't need them when
@ -247,6 +267,9 @@ struct elf32_arm_link_hash_table
length should be applied by the linker. */ length should be applied by the linker. */
int no_pipeline_knowledge; int no_pipeline_knowledge;
/* Nonzero to output a BE8 image. */
int byteswap_code;
/* Short-cuts to get to dynamic linker sections. */ /* Short-cuts to get to dynamic linker sections. */
asection *sgot; asection *sgot;
asection *sgotplt; asection *sgotplt;
@ -430,6 +453,7 @@ elf32_arm_link_hash_table_create (abfd)
ret->arm_glue_size = 0; ret->arm_glue_size = 0;
ret->bfd_of_glue_owner = NULL; ret->bfd_of_glue_owner = NULL;
ret->no_pipeline_knowledge = 0; ret->no_pipeline_knowledge = 0;
ret->byteswap_code = 0;
ret->sym_sec.abfd = NULL; ret->sym_sec.abfd = NULL;
return &ret->root.root; return &ret->root.root;
@ -808,10 +832,13 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
} }
bfd_boolean bfd_boolean
bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) bfd_elf32_arm_process_before_allocation (abfd, link_info,
no_pipeline_knowledge,
byteswap_code)
bfd *abfd; bfd *abfd;
struct bfd_link_info *link_info; struct bfd_link_info *link_info;
int no_pipeline_knowledge; int no_pipeline_knowledge;
int byteswap_code;
{ {
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *internal_relocs = NULL;
@ -834,6 +861,14 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
BFD_ASSERT (globals->bfd_of_glue_owner != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
globals->no_pipeline_knowledge = no_pipeline_knowledge; globals->no_pipeline_knowledge = no_pipeline_knowledge;
if (byteswap_code && !bfd_big_endian (abfd))
{
_bfd_error_handler (
_("%s: BE8 images only valid in big-endian mode."),
bfd_archive_filename (abfd));
return FALSE;
}
globals->byteswap_code = byteswap_code;
/* Rummage around all the relocs and map the glue vectors. */ /* Rummage around all the relocs and map the glue vectors. */
sec = abfd->sections; sec = abfd->sections;
@ -4049,11 +4084,16 @@ elf32_arm_post_process_headers (abfd, link_info)
struct bfd_link_info * link_info ATTRIBUTE_UNUSED; struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
{ {
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
struct elf32_arm_link_hash_table *globals;
i_ehdrp = elf_elfheader (abfd); i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_ABI_VERSION; i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_ABI_VERSION;
i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION; i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
globals = elf32_arm_hash_table (link_info);
if (globals->byteswap_code)
i_ehdrp->e_flags |= EF_ARM_BE8;
} }
static enum elf_reloc_type_class static enum elf_reloc_type_class
@ -4089,7 +4129,7 @@ elf32_arm_section_flags (flags, hdr)
return TRUE; return TRUE;
} }
void static void
elf32_arm_final_write_processing (abfd, linker) elf32_arm_final_write_processing (abfd, linker)
bfd *abfd; bfd *abfd;
bfd_boolean linker ATTRIBUTE_UNUSED; bfd_boolean linker ATTRIBUTE_UNUSED;
@ -4097,6 +4137,148 @@ elf32_arm_final_write_processing (abfd, linker)
bfd_arm_update_notes (abfd, ARM_NOTE_SECTION); bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
} }
/* Called for each symbol. Builds a section map based on mapping symbols.
Does not alter any of the symbols. */
static bfd_boolean
elf32_arm_output_symbol_hook (struct bfd_link_info *info,
const char *name,
Elf_Internal_Sym *elfsym,
asection *input_sec,
struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
{
int mapcount;
elf32_arm_section_map *map;
struct elf32_arm_link_hash_table *globals;
/* Only do this on final link. */
if (info->relocatable)
return TRUE;
/* Only build a map if we need to byteswap code. */
globals = elf32_arm_hash_table (info);
if (!globals->byteswap_code)
return TRUE;
/* We only want mapping symbols. */
if (name == NULL
|| name[0] != '$'
|| (name[1] != 'a'
&& name[1] != 't'
&& name[1] != 'd'))
return TRUE;
mapcount = ++(elf32_arm_section_data (input_sec)->mapcount);
map = elf32_arm_section_data (input_sec)->map;
/* TODO: This may be inefficient, but we probably don't usually have many
mapping symbols per section. */
map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map));
elf32_arm_section_data (input_sec)->map = map;
map[mapcount - 1].vma = elfsym->st_value;
map[mapcount - 1].type = name[1];
return TRUE;
}
/* Allocate target specific section data. */
static bfd_boolean
elf32_arm_new_section_hook (bfd *abfd, asection *sec)
{
struct _arm_elf_section_data *sdata;
bfd_size_type amt = sizeof (*sdata);
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
return FALSE;
sec->used_by_bfd = sdata;
return _bfd_elf_new_section_hook (abfd, sec);
}
/* Used to order a list of mapping symbols by address. */
static int
elf32_arm_compare_mapping (const void * a, const void * b)
{
return ((const elf32_arm_section_map *) a)->vma
> ((const elf32_arm_section_map *) b)->vma;
}
/* Do code byteswapping. Return FALSE afterwards so that the section is
written out as normal. */
static bfd_boolean
elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
bfd_byte *contents)
{
int mapcount;
elf32_arm_section_map *map;
bfd_vma ptr;
bfd_vma end;
bfd_vma offset;
bfd_byte tmp;
int i;
mapcount = elf32_arm_section_data (sec)->mapcount;
map = elf32_arm_section_data (sec)->map;
if (mapcount == 0)
return FALSE;
qsort (map, mapcount, sizeof (elf32_arm_section_map),
elf32_arm_compare_mapping);
offset = sec->output_section->vma + sec->output_offset;
ptr = map[0].vma - offset;
for (i = 0; i < mapcount; i++)
{
if (i == mapcount - 1)
end = bfd_section_size (output_bfd, sec);
else
end = map[i + 1].vma - offset;
switch (map[i].type)
{
case 'a':
/* Byte swap code words. */
while (ptr + 3 < end)
{
tmp = contents[ptr];
contents[ptr] = contents[ptr + 3];
contents[ptr + 3] = tmp;
tmp = contents[ptr + 1];
contents[ptr + 1] = contents[ptr + 2];
contents[ptr + 2] = tmp;
ptr += 4;
}
break;
case 't':
/* Byte swap code halfwords. */
while (ptr + 1 < end)
{
tmp = contents[ptr];
contents[ptr] = contents[ptr + 1];
contents[ptr + 1] = tmp;
ptr += 2;
}
break;
case 'd':
/* Leave data alone. */
break;
}
ptr = end;
}
bfd_free (map);
return FALSE;
}
#define ELF_ARCH bfd_arch_arm #define ELF_ARCH bfd_arch_arm
#define ELF_MACHINE_CODE EM_ARM #define ELF_MACHINE_CODE EM_ARM
#ifdef __QNXTARGET__ #ifdef __QNXTARGET__
@ -4112,16 +4294,19 @@ elf32_arm_final_write_processing (abfd, linker)
#define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
#define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line #define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line
#define bfd_elf32_new_section_hook elf32_arm_new_section_hook
#define elf_backend_get_symbol_type elf32_arm_get_symbol_type #define elf_backend_get_symbol_type elf32_arm_get_symbol_type
#define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook #define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook #define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook
#define elf_backend_check_relocs elf32_arm_check_relocs #define elf_backend_check_relocs elf32_arm_check_relocs
#define elf_backend_relocate_section elf32_arm_relocate_section #define elf_backend_relocate_section elf32_arm_relocate_section
#define elf_backend_write_section elf32_arm_write_section
#define elf_backend_adjust_dynamic_symbol elf32_arm_adjust_dynamic_symbol #define elf_backend_adjust_dynamic_symbol elf32_arm_adjust_dynamic_symbol
#define elf_backend_create_dynamic_sections elf32_arm_create_dynamic_sections #define elf_backend_create_dynamic_sections elf32_arm_create_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol #define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections #define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections
#define elf_backend_link_output_symbol_hook elf32_arm_output_symbol_hook
#define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections #define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections
#define elf_backend_post_process_headers elf32_arm_post_process_headers #define elf_backend_post_process_headers elf32_arm_post_process_headers
#define elf_backend_reloc_type_class elf32_arm_reloc_type_class #define elf_backend_reloc_type_class elf32_arm_reloc_type_class

View File

@ -1,3 +1,13 @@
2004-04-01 Paul Brook <paul@codesourcery.com>
* emultempl/armelf.em (byteswap_code): Add.
(arm_elf_before_allocation): Pass extra parameter.
(PARSE_AND_LIST_PROLOGUE): Add OPTION_BE8.
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add be8.
(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_BE8.
* emultempl/armelf_oabi.em: Pass extra parameter.
* ld.texinfo: Document --be8.
2004-03-30 Stan Shebs <shebs@apple.com> 2004-03-30 Stan Shebs <shebs@apple.com>
Remove long-obsolete MPW support. Remove long-obsolete MPW support.

View File

@ -27,6 +27,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
static int no_pipeline_knowledge = 0; static int no_pipeline_knowledge = 0;
static char *thumb_entry_symbol = NULL; static char *thumb_entry_symbol = NULL;
static bfd *bfd_for_interwork; static bfd *bfd_for_interwork;
static int byteswap_code = 0;
static void static void
gld${EMULATION_NAME}_before_parse (void) gld${EMULATION_NAME}_before_parse (void)
@ -117,7 +118,8 @@ arm_elf_before_allocation (void)
LANG_FOR_EACH_INPUT_STATEMENT (is) LANG_FOR_EACH_INPUT_STATEMENT (is)
{ {
if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, & link_info, if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, & link_info,
no_pipeline_knowledge)) no_pipeline_knowledge,
byteswap_code))
{ {
/* xgettext:c-format */ /* xgettext:c-format */
einfo (_("Errors encountered processing file %s"), is->filename); einfo (_("Errors encountered processing file %s"), is->filename);
@ -184,6 +186,7 @@ EOF
# #
PARSE_AND_LIST_PROLOGUE=' PARSE_AND_LIST_PROLOGUE='
#define OPTION_THUMB_ENTRY 301 #define OPTION_THUMB_ENTRY 301
#define OPTION_BE8 302
' '
PARSE_AND_LIST_SHORTOPTS=p PARSE_AND_LIST_SHORTOPTS=p
@ -191,11 +194,13 @@ PARSE_AND_LIST_SHORTOPTS=p
PARSE_AND_LIST_LONGOPTS=' PARSE_AND_LIST_LONGOPTS='
{ "no-pipeline-knowledge", no_argument, NULL, '\'p\''}, { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
{ "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY}, { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
{ "be8", no_argument, NULL, OPTION_BE8},
' '
PARSE_AND_LIST_OPTIONS=' PARSE_AND_LIST_OPTIONS='
fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n")); fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n"));
fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n")); fprintf (file, _(" --thumb-entry=<sym> Set the entry point to be Thumb symbol <sym>\n"));
fprintf (file, _(" --be8 Oputput BE8 format image\n"));
' '
PARSE_AND_LIST_ARGS_CASES=' PARSE_AND_LIST_ARGS_CASES='
@ -206,6 +211,10 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_THUMB_ENTRY: case OPTION_THUMB_ENTRY:
thumb_entry_symbol = optarg; thumb_entry_symbol = optarg;
break; break;
case OPTION_BE8:
byteswap_code = 1;
break;
' '
# We have our own after_open and before_allocation functions, but they call # We have our own after_open and before_allocation functions, but they call

View File

@ -68,7 +68,7 @@ gld${EMULATION_NAME}_before_allocation (void)
{ {
LANG_FOR_EACH_INPUT_STATEMENT (is) LANG_FOR_EACH_INPUT_STATEMENT (is)
{ {
if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info, 0)) if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info, 0, 0))
{ {
/* xgettext:c-format */ /* xgettext:c-format */
einfo (_("Errors encountered processing file %s"), is->filename); einfo (_("Errors encountered processing file %s"), is->filename);

View File

@ -4762,6 +4762,12 @@ But it also sets the bottom bit of the address, so that it can be
branched to using a BX instruction, and the program will start branched to using a BX instruction, and the program will start
executing in Thumb mode straight away. executing in Thumb mode straight away.
@cindex BE8
@kindex --be8
The @samp{--be8} switch instructs @command{ld} to generate BE8 format
executables. This option is only valid when linking big-endian objects.
The resulting image will contain big-endian data and little-endian code.
@ifclear GENERIC @ifclear GENERIC
@lowersections @lowersections
@end ifclear @end ifclear