This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[arm] Infrastructure for eabi unwinding tables
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>
- Date: Tue, 10 Aug 2004 21:00:32 +0100
- Subject: [arm] Infrastructure for eabi unwinding tables
- Organization: CodeSourcery
The attached patch adds features to binutils which are required for arm eabi
based unwinding tables.
It adds segment relative relocations, a new arm specific section type, and
linker support for the new sections.
Tested with cross to arm-none-elf.
Ok?
Paul
2004-08-10 Paul Brook <paul@codesourcery.com>
bfd/
* elf32-arm.c (elf32_arm_get_roseg_base): New function.
(elf32_arm_get_rwseg_base): New function.
(elf32_arm_final_link_relocate): Handle R_ARM_SBREL32 and
R_ARM_ROSEGREL32.
(elf32_arm_fake_sections, is_unwind_section_name): New functions.
(elf32_arm_section_from_shdr): New function.
(elf_backend_fake_sections, elf_backend_section_from_shdr): Define.
binutils/
* readelf.c (get_arm_section_type_name): New function.
(get_section_type_name): Use it.
gas/
* config/tc-arm.c (arm_elf_change_section): Set elf_linked_to_section.
include/elf/
* arm.h (SHT_ARM_EXIDX): Define.
(ELF_STRING_ARM_unwind*): Define.
ld/
* emulparams/armelf.sh: Define OTHER_READONLY_SECTIONS and
TEXT_START_SYMBOLS.
ld/testsuite/
* ld-arm/arm-app-abs32.d: Disassembler may output __text_start.
* ld-arm/arm-app.d: Disassembler may output __text_start.
* ld-arm/arm-static-app.d: Disassembler may output __text_start.
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.133
diff -u -p -r1.133 elf32-arm.h
--- bfd/elf32-arm.h 24 Jun 2004 04:46:18 -0000 1.133
+++ bfd/elf32-arm.h 10 Aug 2004 12:38:12 -0000
@@ -1239,6 +1239,33 @@ elf32_arm_to_thumb_stub (info, name, inp
return TRUE;
}
+
+/* Get the start of the RO segment (ie. the .text section). */
+/* ??? This is probably wrong for anything with shared libraries. */
+
+static bfd_vma
+elf32_arm_get_roseg_base (bfd * abfd)
+{
+ asection *sec;
+
+ sec = bfd_get_section_by_name (abfd, ".text");
+ return sec->vma;
+}
+
+
+/* Get the start of the RW segment (ie. the .data section). */
+/* ??? This is probably wrong for anything with shared libraries. */
+
+static bfd_vma
+elf32_arm_get_rwseg_base (bfd * abfd)
+{
+ asection *sec;
+
+ sec = bfd_get_section_by_name (abfd, ".data");
+ return sec->vma;
+}
+
+
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
@@ -1324,6 +1351,8 @@ elf32_arm_final_link_relocate (howto, in
case R_ARM_XPC25:
#endif
case R_ARM_PLT32:
+ case R_ARM_ROSEGREL32:
+ case R_ARM_SBREL32:
/* r_symndx will be zero only for relocs against symbols
from removed linkonce sections, or sections discarded by
a linker script. */
@@ -1334,7 +1363,8 @@ elf32_arm_final_link_relocate (howto, in
will use the symbol's value, which may point to a PLT entry, but we
don't need to handle that here. If we created a PLT entry, all
branches in this object should go to it. */
- if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
+ if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
+ && r_type != R_ARM_REL32)
&& h != NULL
&& splt != NULL
&& h->plt.offset != (bfd_vma) -1)
@@ -1362,7 +1392,9 @@ elf32_arm_final_link_relocate (howto, in
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& r_type != R_ARM_PC24
- && r_type != R_ARM_PLT32)
+ && r_type != R_ARM_PLT32
+ && r_type != R_ARM_ROSEGREL32
+ && r_type != R_ARM_SBREL32)
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
@@ -1555,6 +1587,18 @@ elf32_arm_final_link_relocate (howto, in
+ input_section->output_offset + rel->r_offset);
value += addend;
break;
+
+ case R_ARM_ROSEGREL32:
+ value -= elf32_arm_get_roseg_base (output_bfd);
+ value += addend;
+ if (sym_flags == STT_ARM_TFUNC)
+ value |= 1;
+ break;
+
+ case R_ARM_SBREL32:
+ value -= elf32_arm_get_rwseg_base (output_bfd);
+ value += addend;
+ break;
}
bfd_put_32 (input_bfd, value, hit_data);
@@ -1937,9 +1981,6 @@ elf32_arm_final_link_relocate (howto, in
contents, rel->r_offset, value,
(bfd_vma) 0);
- case R_ARM_SBREL32:
- return bfd_reloc_notsupported;
-
case R_ARM_AMP_VCALL9:
return bfd_reloc_notsupported;
@@ -4106,6 +4147,8 @@ elf32_arm_reloc_type_class (rela)
static bfd_boolean elf32_arm_section_flags PARAMS ((flagword *, const Elf_Internal_Shdr *));
static void elf32_arm_final_write_processing PARAMS ((bfd *, bfd_boolean));
+static bfd_boolean elf32_arm_fake_sections (bfd *, Elf_Internal_Shdr *,
+ asection *);
/* Set the right machine number for an Arm ELF file. */
@@ -4129,6 +4172,66 @@ elf32_arm_final_write_processing (abfd,
}
+/* Return TRUE if this is an unwinding table entry. */
+
+static bfd_boolean
+is_unwind_section_name (bfd * abfd ATTRIBUTE_UNUSED, const char * name)
+{
+ size_t len1, len2;
+
+ len1 = sizeof (ELF_STRING_ARM_unwind) - 1;
+ len2 = sizeof (ELF_STRING_ARM_unwind_once) - 1;
+ return (strncmp (name, ELF_STRING_ARM_unwind, len1) == 0
+ || strncmp (name, ELF_STRING_ARM_unwind_once, len2) == 0);
+}
+
+
+/* Set the type and flags for an ARM section. We do this by the
+ section name, which is a hack, but ought to work. */
+
+static bfd_boolean
+elf32_arm_fake_sections (bfd * abfd, Elf_Internal_Shdr * hdr, asection * sec)
+{
+ const char * name;
+
+ name = bfd_get_section_name (abfd, sec);
+
+ if (is_unwind_section_name (abfd, name))
+ {
+ hdr->sh_type = SHT_ARM_EXIDX;
+ hdr->sh_flags |= SHF_LINK_ORDER;
+ }
+ return TRUE;
+}
+
+
+/* Handle an ARM specific section when reading an object file. This
+ is called when elf.c finds a section with an unknown type. */
+
+static bfd_boolean
+elf32_arm_section_from_shdr (bfd *abfd, Elf_Internal_Shdr * hdr,
+ const char *name)
+{
+ /* There ought to be a place to keep ELF backend specific flags, but
+ at the moment there isn't one. We just keep track of the
+ sections by their name, instead. Fortunately, the ABI gives
+ names for all the ARM specific sections, so we will probably get
+ away with this. */
+ switch (hdr->sh_type)
+ {
+ case SHT_ARM_EXIDX:
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ return FALSE;
+
+ return TRUE;
+}
+
/* Called for each symbol. Builds a section map based on mapping symbols.
Does not alter any of the symbols. */
@@ -4303,6 +4406,8 @@ elf32_arm_write_section (bfd *output_bfd
#define elf_backend_reloc_type_class elf32_arm_reloc_type_class
#define elf_backend_object_p elf32_arm_object_p
#define elf_backend_section_flags elf32_arm_section_flags
+#define elf_backend_fake_sections elf32_arm_fake_sections
+#define elf_backend_section_from_shdr elf32_arm_section_from_shdr
#define elf_backend_final_write_processing elf32_arm_final_write_processing
#define elf_backend_copy_indirect_symbol elf32_arm_copy_indirect_symbol
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.249
diff -u -p -r1.249 readelf.c
--- binutils/readelf.c 6 Aug 2004 13:13:30 -0000 1.249
+++ binutils/readelf.c 10 Aug 2004 12:38:14 -0000
@@ -2363,6 +2363,19 @@ get_ia64_section_type_name (unsigned int
}
static const char *
+get_arm_section_type_name (unsigned int sh_type)
+{
+ switch (sh_type)
+ {
+ case SHT_ARM_EXIDX:
+ return "ARM_EXIDX";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static const char *
get_section_type_name (unsigned int sh_type)
{
static char buff[32];
@@ -2412,6 +2425,9 @@ get_section_type_name (unsigned int sh_t
case EM_IA_64:
result = get_ia64_section_type_name (sh_type);
break;
+ case EM_ARM:
+ result = get_arm_section_type_name (sh_type);
+ break;
default:
result = NULL;
break;
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.171
diff -u -p -r1.171 tc-arm.c
--- gas/config/tc-arm.c 6 Aug 2004 16:18:07 -0000 1.171
+++ gas/config/tc-arm.c 10 Aug 2004 12:38:17 -0000
@@ -2901,6 +2958,11 @@ arm_elf_change_section (void)
{
flagword flags;
+ /* Link unlinked unwind index table section to the .text section. */
+ if (elf_section_type (now_seg) == SHT_ARM_EXIDX
+ && elf_linked_to_section (now_seg) == NULL)
+ elf_linked_to_section (now_seg) = text_section;
+
if (!SEG_NORMAL (now_seg))
return;
Index: include/elf/arm.h
===================================================================
RCS file: /cvs/src/src/include/elf/arm.h,v
retrieving revision 1.14
diff -u -p -r1.14 arm.h
--- include/elf/arm.h 6 Aug 2004 16:18:11 -0000 1.14
+++ include/elf/arm.h 10 Aug 2004 12:38:23 -0000
@@ -64,6 +64,9 @@
#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */
#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */
+/* Additional section types. */
+#define SHT_ARM_EXIDX 0x70000001
+
/* ARM-specific values for sh_flags. */
#define SHF_ENTRYSECT 0x10000000 /* Section contains an entry point. */
#define SHF_COMDEF 0x80000000 /* Section may be multiply defined in the input to a link step. */
@@ -152,5 +155,11 @@ END_RELOC_NUMBERS (R_ARM_max)
/* The name of the note section used to identify arm variants. */
#define ARM_NOTE_SECTION ".note.gnu.arm.ident"
-
+
+/* Special section names. */
+#define ELF_STRING_ARM_unwind ".ARM.exidx"
+#define ELF_STRING_ARM_unwind_info ".ARM.extab"
+#define ELF_STRING_ARM_unwind_once ".gnu.linkonce.armexidx."
+#define ELF_STRING_ARM_unwind_info_once ".gnu.linkonce.armextab."
+
#endif /* _ELF_ARM_H */
Index: ld/emulparams/armelf.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/armelf.sh,v
retrieving revision 1.12
diff -u -p -r1.12 armelf.sh
--- ld/emulparams/armelf.sh 9 Feb 2004 18:06:20 -0000 1.12
+++ ld/emulparams/armelf.sh 10 Aug 2004 12:38:23 -0000
@@ -10,8 +10,14 @@ OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue
OTHER_BSS_SYMBOLS='__bss_start__ = .;'
OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;'
OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+OTHER_READONLY_SECTIONS="
+ .ARM.extab ${RELOCATING-0} : { *(.ARM.extab${RELOCATING+* .gnu.linkonce.armextab.*}) }
+ __exidx_start = .;
+ .ARM.exidx ${RELOCATING-0} : { *(.ARM.exidx${RELOCATING+* .gnu.linkonce.armexidx.*}) }
+ __exidx_end = .;"
DATA_START_SYMBOLS='__data_start = . ;';
+TEXT_START_SYMBOLS='__text_start = . ;';
GENERATE_SHLIB_SCRIPT=yes
Index: ld/testsuite/ld-arm/arm-app-abs32.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-app-abs32.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-app-abs32.d
--- ld/testsuite/ld-arm/arm-app-abs32.d 23 Jan 2004 16:51:39 -0000 1.1
+++ ld/testsuite/ld-arm/arm-app-abs32.d 10 Aug 2004 12:38:23 -0000
@@ -17,7 +17,7 @@ Disassembly of section .plt:
.*: e5bcf.* ldr pc, \[ip, #.*\]!
Disassembly of section .text:
-.* <_start>:
+.* <(__text|)_start>:
.*: e1a0c00d mov ip, sp
.*: e92dd800 stmdb sp!, {fp, ip, lr, pc}
.*: e59f0004 ldr r0, \[pc, #4\] ; .* <.text\+0x14>
Index: ld/testsuite/ld-arm/arm-app.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-app.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-app.d
--- ld/testsuite/ld-arm/arm-app.d 6 Jan 2004 21:47:38 -0000 1.1
+++ ld/testsuite/ld-arm/arm-app.d 10 Aug 2004 12:38:23 -0000
@@ -17,7 +17,7 @@ Disassembly of section .plt:
.*: e5bcf.* ldr pc, \[ip, #.*\]!
Disassembly of section .text:
-.* <_start>:
+.* <(__text|)_start>:
.*: e1a0c00d mov ip, sp
.*: e92dd800 stmdb sp!, {fp, ip, lr, pc}
.*: eb000001 bl .* <app_func>
Index: ld/testsuite/ld-arm/arm-static-app.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-static-app.d,v
retrieving revision 1.1
diff -u -p -r1.1 arm-static-app.d
--- ld/testsuite/ld-arm/arm-static-app.d 13 Jan 2004 21:09:18 -0000 1.1
+++ ld/testsuite/ld-arm/arm-static-app.d 10 Aug 2004 12:38:23 -0000
@@ -6,7 +6,7 @@ start address 0x.*
Disassembly of section .text:
-.* <_start>:
+.* <(__text|)_start>:
.*: e1a0c00d mov ip, sp
.*: e92dd800 stmdb sp!, {fp, ip, lr, pc}
.*: eb000001 bl .* <app_func>