From e489d0aef709443ce63e0bb21e7eb18c9575d35c Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Thu, 1 Apr 2004 11:20:04 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 15 ++++ bfd/bfd-in.h | 2 +- bfd/bfd-in2.h | 2 +- bfd/elf32-arm.h | 191 +++++++++++++++++++++++++++++++++++++++++++- ld/ChangeLog | 10 +++ ld/emultempl/armelf.em | 11 ++- ld/emultempl/armelf_oabi.em | 2 +- ld/ld.texinfo | 6 ++ 8 files changed, 232 insertions(+), 7 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f1ab28c..6f6b14c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2004-04-01 Paul Brook + + * 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 * stabs.c (struct stab_link_includes_totals): Add field 'symb' diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 1a5d1ea..9ad727e 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -786,7 +786,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info *); 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 (bfd *, struct bfd_link_info *); diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e6048c3..c2e1819 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -793,7 +793,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info *); 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 (bfd *, struct bfd_link_info *); diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index bc6904a..b9e3deb 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -106,7 +106,7 @@ bfd_boolean bfd_elf32_arm_allocate_interworking_sections bfd_boolean bfd_elf32_arm_get_bfd_for_interworking PARAMS ((bfd *, struct bfd_link_info *)); bfd_boolean bfd_elf32_arm_process_before_allocation - PARAMS ((bfd *, struct bfd_link_info *, int)); + PARAMS ((bfd *, struct bfd_link_info *, int, int)); #endif @@ -190,6 +190,26 @@ static const bfd_vma elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] = #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 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 @@ -247,6 +267,9 @@ struct elf32_arm_link_hash_table length should be applied by the linker. */ int no_pipeline_knowledge; + /* Nonzero to output a BE8 image. */ + int byteswap_code; + /* Short-cuts to get to dynamic linker sections. */ asection *sgot; asection *sgotplt; @@ -430,6 +453,7 @@ elf32_arm_link_hash_table_create (abfd) ret->arm_glue_size = 0; ret->bfd_of_glue_owner = NULL; ret->no_pipeline_knowledge = 0; + ret->byteswap_code = 0; ret->sym_sec.abfd = NULL; return &ret->root.root; @@ -808,10 +832,13 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info) } 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; struct bfd_link_info *link_info; int no_pipeline_knowledge; + int byteswap_code; { Elf_Internal_Shdr *symtab_hdr; 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); 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. */ sec = abfd->sections; @@ -4049,11 +4084,16 @@ elf32_arm_post_process_headers (abfd, link_info) struct bfd_link_info * link_info ATTRIBUTE_UNUSED; { Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ + struct elf32_arm_link_hash_table *globals; i_ehdrp = elf_elfheader (abfd); i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_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 @@ -4089,7 +4129,7 @@ elf32_arm_section_flags (flags, hdr) return TRUE; } -void +static void elf32_arm_final_write_processing (abfd, linker) bfd *abfd; bfd_boolean linker ATTRIBUTE_UNUSED; @@ -4097,6 +4137,148 @@ elf32_arm_final_write_processing (abfd, linker) 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_MACHINE_CODE EM_ARM #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_reloc_type_lookup elf32_arm_reloc_type_lookup #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_gc_mark_hook elf32_arm_gc_mark_hook #define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook #define elf_backend_check_relocs elf32_arm_check_relocs #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_create_dynamic_sections elf32_arm_create_dynamic_sections #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_link_output_symbol_hook elf32_arm_output_symbol_hook #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_reloc_type_class elf32_arm_reloc_type_class diff --git a/ld/ChangeLog b/ld/ChangeLog index 6ff7498..0afd3f6 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2004-04-01 Paul Brook + + * 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 Remove long-obsolete MPW support. diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 0c051ad..beeb40c 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -27,6 +27,7 @@ cat >>e${EMULATION_NAME}.c <the_bfd, & link_info, - no_pipeline_knowledge)) + no_pipeline_knowledge, + byteswap_code)) { /* xgettext:c-format */ einfo (_("Errors encountered processing file %s"), is->filename); @@ -184,6 +186,7 @@ EOF # PARSE_AND_LIST_PROLOGUE=' #define OPTION_THUMB_ENTRY 301 +#define OPTION_BE8 302 ' PARSE_AND_LIST_SHORTOPTS=p @@ -191,11 +194,13 @@ PARSE_AND_LIST_SHORTOPTS=p PARSE_AND_LIST_LONGOPTS=' { "no-pipeline-knowledge", no_argument, NULL, '\'p\''}, { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY}, + { "be8", no_argument, NULL, OPTION_BE8}, ' PARSE_AND_LIST_OPTIONS=' fprintf (file, _(" -p --no-pipeline-knowledge Stop the linker knowing about the pipeline length\n")); fprintf (file, _(" --thumb-entry= Set the entry point to be Thumb symbol \n")); + fprintf (file, _(" --be8 Oputput BE8 format image\n")); ' PARSE_AND_LIST_ARGS_CASES=' @@ -206,6 +211,10 @@ PARSE_AND_LIST_ARGS_CASES=' case OPTION_THUMB_ENTRY: thumb_entry_symbol = optarg; break; + + case OPTION_BE8: + byteswap_code = 1; + break; ' # We have our own after_open and before_allocation functions, but they call diff --git a/ld/emultempl/armelf_oabi.em b/ld/emultempl/armelf_oabi.em index d75c658..8ff2ad1 100644 --- a/ld/emultempl/armelf_oabi.em +++ b/ld/emultempl/armelf_oabi.em @@ -68,7 +68,7 @@ gld${EMULATION_NAME}_before_allocation (void) { 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 */ einfo (_("Errors encountered processing file %s"), is->filename); diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 4310c12..f6bd9ff 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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 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 @lowersections @end ifclear -- 2.7.4