aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog5
-rw-r--r--ld/emultempl/armelf.em68
-rw-r--r--ld/testsuite/ChangeLog13
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp4
-rw-r--r--ld/testsuite/ld-arm/arm.ld2
-rw-r--r--ld/testsuite/ld-arm/unwind-1.d10
-rw-r--r--ld/testsuite/ld-arm/unwind-1.s19
-rw-r--r--ld/testsuite/ld-arm/unwind-2.d10
-rw-r--r--ld/testsuite/ld-arm/unwind-2.s19
-rw-r--r--ld/testsuite/ld-arm/unwind-3.d11
-rw-r--r--ld/testsuite/ld-arm/unwind-3.s29
-rw-r--r--ld/testsuite/ld-arm/unwind-4.d11
-rw-r--r--ld/testsuite/ld-arm/unwind-4.s49
13 files changed, 250 insertions, 0 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a13b985..2f937b8 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-05 Paul Brook <paul@codesourcery.com>
+
+ * emultempl/armelf.em (compare_output_sec_vma): New function.
+ (gld${EMULATION_NAME}_finish): Add exidx munging code.
+
2009-05-05 Anatoly Sokolov <aesok@post.ru>
* scripttempl/avr.sc (MEMORY): Use DATA_ORIGIN.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 2f0c3af..2d63a63 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -258,10 +258,78 @@ build_section_lists (lang_statement_union_type *statement)
}
}
+static int
+compare_output_sec_vma (const void *a, const void *b)
+{
+ asection *asec = *(asection **) a, *bsec = *(asection **) b;
+ asection *aout = asec->output_section, *bout = bsec->output_section;
+ bfd_vma avma, bvma;
+
+ /* If there's no output section for some reason, compare equal. */
+ if (!aout || !bout)
+ return 0;
+
+ avma = aout->vma + asec->output_offset;
+ bvma = bout->vma + bsec->output_offset;
+
+ if (avma > bvma)
+ return 1;
+ else if (avma < bvma)
+ return -1;
+
+ return 0;
+}
+
static void
gld${EMULATION_NAME}_finish (void)
{
struct bfd_link_hash_entry * h;
+ unsigned int list_size = 10;
+ asection **sec_list = xmalloc (list_size * sizeof (asection *));
+ unsigned int sec_count = 0;
+
+ if (!link_info.relocatable)
+ {
+ /* Build a sorted list of input text sections, then use that to process
+ the unwind table index. */
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
+ {
+ bfd *abfd = is->the_bfd;
+ asection *sec;
+
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+ continue;
+
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ asection *out_sec = sec->output_section;
+
+ if (out_sec
+ && elf_section_type (sec) == SHT_PROGBITS
+ && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
+ && (sec->flags & SEC_EXCLUDE) == 0
+ && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS
+ && out_sec != bfd_abs_section_ptr)
+ {
+ if (sec_count == list_size)
+ {
+ list_size *= 2;
+ sec_list = xrealloc (sec_list,
+ list_size * sizeof (asection *));
+ }
+
+ sec_list[sec_count++] = sec;
+ }
+ }
+ }
+
+ qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
+
+ if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info))
+ need_laying_out = 1;
+
+ free (sec_list);
+ }
/* bfd_elf32_discard_info just plays with debugging sections,
ie. doesn't affect any code, so we can delay resizing the
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 63c51ff..5631ca2 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,16 @@
+2009-05-05 Paul Brook <paul@codesourcery.com>
+
+ * ld-arm/arm.ld: Add .ARM.exidx and .ARM.extab.
+ * ld-arm/arm-elf.exp: Add unwind-[1-4].
+ * ld-arm/unwind-1.d: New test.
+ * ld-arm/unwind-1.s: New test.
+ * ld-arm/unwind-2.d: New test.
+ * ld-arm/unwind-2.s: New test.
+ * ld-arm/unwind-3.d: New test.
+ * ld-arm/unwind-3.s: New test.
+ * ld-arm/unwind-4.d: New test.
+ * ld-arm/unwind-4.s: New test.
+
2009-05-01 Julian Brown <julian@codesourcery.com>
* ld-arm/arm-elf.exp (armeabitests): Add thumb2-bl-blx-interwork test.
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 218bfb5..054a187 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -392,3 +392,7 @@ run_dump_test "attr-merge-unknown-1"
run_dump_test "attr-merge-unknown-2"
run_dump_test "attr-merge-unknown-2r"
run_dump_test "attr-merge-unknown-3"
+run_dump_test "unwind-1"
+run_dump_test "unwind-2"
+run_dump_test "unwind-3"
+run_dump_test "unwind-4"
diff --git a/ld/testsuite/ld-arm/arm.ld b/ld/testsuite/ld-arm/arm.ld
index cb73fb3..8e3fac2 100644
--- a/ld/testsuite/ld-arm/arm.ld
+++ b/ld/testsuite/ld-arm/arm.ld
@@ -10,9 +10,11 @@ SECTIONS
*(.before)
*(.text)
*(.after)
+ *(.ARM.extab*)
*(.glue_7)
*(.v4_bx)
} =0
+ .ARM.exidx : { *(.ARM.exidx*) }
. = 0x9000;
.got : { *(.got) *(.got.plt)}
. = 0x12340000;
diff --git a/ld/testsuite/ld-arm/unwind-1.d b/ld/testsuite/ld-arm/unwind-1.d
new file mode 100644
index 0000000..add5cb7
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-1.d
@@ -0,0 +1,10 @@
+#ld: -T arm.ld
+#objdump: -s
+
+.*: file format.*
+
+#...
+Contents of section .ARM.exidx:
+ 8008 (f8ffff7f b0b0a880 f4ffff7f 01000000|7ffffff8 80a8b0b0 7ffffff4 00000001) .*
+Contents of section .far:
+#...
diff --git a/ld/testsuite/ld-arm/unwind-1.s b/ld/testsuite/ld-arm/unwind-1.s
new file mode 100644
index 0000000..a4eb390
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-1.s
@@ -0,0 +1,19 @@
+ .syntax unified
+ .text
+ .global _start
+ .type _start, %function
+_start:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ @ Section with no unwinding information. Linker should insert a cantunwind entry.
+ .section .after, "xa"
+ .global __aeabi_unwind_cpp_pr0
+ .type __aeabi_unwind_cpp_pr0, %function
+__aeabi_unwind_cpp_pr0:
+ bx lr
+
+ .section .far
+ .word 0
diff --git a/ld/testsuite/ld-arm/unwind-2.d b/ld/testsuite/ld-arm/unwind-2.d
new file mode 100644
index 0000000..a096c9b
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-2.d
@@ -0,0 +1,10 @@
+#ld: -T arm.ld
+#objdump: -s
+
+.*: file format.*
+
+#...
+Contents of section .ARM.exidx:
+ 8004 (fcffff7f b0b0a880 f8ffff7f 01000000|7ffffffc 80a8b0b0 7ffffff8 00000001) .*
+Contents of section .far:
+#...
diff --git a/ld/testsuite/ld-arm/unwind-2.s b/ld/testsuite/ld-arm/unwind-2.s
new file mode 100644
index 0000000..cd5851c
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-2.s
@@ -0,0 +1,19 @@
+ .syntax unified
+ .text
+
+ .global __aeabi_unwind_cpp_pr0
+ .type __aeabi_unwind_cpp_pr0, %function
+__aeabi_unwind_cpp_pr0:
+ .global _start
+ .type _start, %function
+_start:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ @ last text section has unwind information. Linker should append a
+ @ terminating cantunwind entry.
+
+ .section .far
+ .word 0
diff --git a/ld/testsuite/ld-arm/unwind-3.d b/ld/testsuite/ld-arm/unwind-3.d
new file mode 100644
index 0000000..0b8e85e
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-3.d
@@ -0,0 +1,11 @@
+#ld: -T arm.ld
+#objdump: -s
+
+.*: file format.*
+
+#...
+Contents of section .ARM.exidx:
+ 800c (f4ffff7f b0b0a880 f0ffff7f 01000000|7ffffff4 80a8b0b0 7ffffff0 00000001) .*
+ 801c (ecffff7f b0b0a880 e8ffff7f 01000000|7fffffec 80a8b0b0 7fffffe8 00000001) .*
+Contents of section .far:
+#...
diff --git a/ld/testsuite/ld-arm/unwind-3.s b/ld/testsuite/ld-arm/unwind-3.s
new file mode 100644
index 0000000..9cd8514
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-3.s
@@ -0,0 +1,29 @@
+ .syntax unified
+ .text
+ @ section without unwind info
+ .global _start
+ .type _start, %function
+_start:
+ bl _before
+
+ @ Section that will be placed first
+ .section .before, "xa"
+ .type _before, %function
+_before:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ @ section that will be placed last
+ .section .after, "xa"
+ .global __aeabi_unwind_cpp_pr0
+ .type __aeabi_unwind_cpp_pr0, %function
+__aeabi_unwind_cpp_pr0:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ .section .far
+ .word 0
diff --git a/ld/testsuite/ld-arm/unwind-4.d b/ld/testsuite/ld-arm/unwind-4.d
new file mode 100644
index 0000000..0a4427a
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-4.d
@@ -0,0 +1,11 @@
+#ld: -T arm.ld
+#objdump: -s
+
+.*: file format.*
+
+#...
+Contents of section .ARM.exidx:
+ 8020 (e0ffff7f b0b0a880 dcffff7f e8ffff7f|7fffffe0 80a8b0b0 7fffffdc 7fffffe8) .*
+ 8030 (d8ffff7f b0b0a880 d8ffff7f 01000000|7fffffd8 80a8b0b0 7fffffd8 00000001) .*
+Contents of section .far:
+#...
diff --git a/ld/testsuite/ld-arm/unwind-4.s b/ld/testsuite/ld-arm/unwind-4.s
new file mode 100644
index 0000000..015311b
--- /dev/null
+++ b/ld/testsuite/ld-arm/unwind-4.s
@@ -0,0 +1,49 @@
+ .syntax unified
+ .text
+ @ out of line table entry
+ .global _start
+ .type _start, %function
+_start:
+ .fnstart
+ .save {r4, lr}
+ .vsave {d0}
+ .vsave {d4}
+ bl _before
+ .fnend
+
+ @ entry that can be merged
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ @ Section that will be placed first
+ .section .before, "xa"
+ .type _before, %function
+_before:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+
+ @ section that will be placed last
+ .section .after, "xa"
+ .global __aeabi_unwind_cpp_pr0
+ .type __aeabi_unwind_cpp_pr0, %function
+__aeabi_unwind_cpp_pr0:
+ .fnstart
+ .save {r4, lr}
+ bx lr
+ .fnend
+ @ final function is cantunwind, so output table size is smaller
+ @ than sum of input sections
+ .global __aeabi_unwind_cpp_pr1
+ .type __aeabi_unwind_cpp_pr1, %function
+__aeabi_unwind_cpp_pr1:
+ .fnstart
+ .cantunwind
+ bx lr
+ .fnend
+
+ .section .far
+ .word 0