aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorMarcus Shawcroft <marcus.shawcroft@gmail.com>2015-03-22 08:31:18 +0000
committerMarcus Shawcroft <marcus.shawcroft@arm.com>2015-03-25 15:16:04 +0000
commit618655192fca05a9aaebbd395b0960626cbfdebe (patch)
tree2b37bb4f932147c9a22b9bcde4a3df3115dd3161 /bfd
parentd9ced15d6ea875aadd3e7395990eb37319454d71 (diff)
downloadgdb-618655192fca05a9aaebbd395b0960626cbfdebe.zip
gdb-618655192fca05a9aaebbd395b0960626cbfdebe.tar.gz
gdb-618655192fca05a9aaebbd395b0960626cbfdebe.tar.bz2
[AArch64] Implement branch over stub section.
Ensure that injection of a stub section does not break a link where there is an xpectation that flow of control can pass from one input section to another simply by linking the input sections in series. The solution here is to allow stub sections to be inserted after any input section (existing behaviour), but inject an additional branch at the start of each stub section such that control flow falling into the stub section will branch over the stub section.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elfnn-aarch64.c18
2 files changed, 25 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6642b4b..014e30d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,13 @@
2015-03-25 Marcus Shawcroft <marcus.shawcroft@arm.com>
+ * elfnn-aarch64.c (_bfd_aarch64_resize_stubs): Adjust stub section
+ size for initial branch.
+ (elfNN_aarch64_build_stubs): Write initial branch.
+ _bfd_aarch64_decode_(elfNN_aarch64_output_arch_local_syms): Write
+ mapping symbol on initial branch.
+
+2015-03-25 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
* elfnn-aarch64.c (_bfd_aarch64_erratum_835769_scan):
Update erratum count.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4ac4691..9b62a5e 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3117,8 +3117,17 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
}
bfd_hash_traverse (&htab->stub_hash_table, aarch64_size_one_stub, htab);
-}
+ for (section = htab->stub_bfd->sections;
+ section != NULL; section = section->next)
+ {
+ if (!strstr (section->name, STUB_SUFFIX))
+ continue;
+
+ if (section->size)
+ section->size += 4;
+ }
+}
/* Determine and set the size of the stub section for a final link.
@@ -3482,6 +3491,9 @@ elfNN_aarch64_build_stubs (struct bfd_link_info *info)
if (stub_sec->contents == NULL && size != 0)
return FALSE;
stub_sec->size = 0;
+
+ bfd_putl32 (0x14000000 | (size >> 2), stub_sec->contents);
+ stub_sec->size += 4;
}
/* Build the stubs as directed by the stub hash table. */
@@ -6501,6 +6513,10 @@ elfNN_aarch64_output_arch_local_syms (bfd *output_bfd,
osi.sec_shndx = _bfd_elf_section_from_bfd_section
(output_bfd, osi.sec->output_section);
+ /* The first instruction in a stub is always a branch. */
+ if (!elfNN_aarch64_output_map_sym (&osi, AARCH64_MAP_INSN, 0))
+ return FALSE;
+
bfd_hash_traverse (&htab->stub_hash_table, aarch64_map_one_stub,
&osi);
}