aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-10-29 15:37:43 +1030
committerAlan Modra <amodra@gmail.com>2013-10-30 13:40:21 +1030
commit6911b7dcb8ea17f8b811578dd4ac1ab7bb675e7b (patch)
tree0181671770254c68868ad161b4f207805969ef25 /include
parentee67d69a3ff0eed25d98c5e97ed6c3ede8069edc (diff)
downloadfsf-binutils-gdb-6911b7dcb8ea17f8b811578dd4ac1ab7bb675e7b.zip
fsf-binutils-gdb-6911b7dcb8ea17f8b811578dd4ac1ab7bb675e7b.tar.gz
fsf-binutils-gdb-6911b7dcb8ea17f8b811578dd4ac1ab7bb675e7b.tar.bz2
Add ELFv2 .localentry support.
This defines the ELF symbol st_other field used to encode the number of instructions between a function "global entry" and its "local entry", and adds support related to the local entry offset. include/elf/ * ppc64.h (STO_PPC64_LOCAL_BIT, STO_PPC64_LOCAL_MASK): Define. (ppc64_decode_local_entry, ppc64_encode_local_entry): New functions. (PPC64_LOCAL_ENTRY_OFFSET, PPC64_SET_LOCAL_ENTRY_OFFSET): Define. bfd/ * elf64-ppc.c (struct ppc_stub_hash_entry): Add "other". (stub_hash_newfunc): Init new ppc_stub_hash_entry field, and one we forgot, "plt_ent". (ppc64_elf_add_symbol_hook): Check ELFv1 objects don't have st_other bits only valid in ELFv2. (ppc64_elf_merge_symbol_attribute): New function. (ppc_type_of_stub): Add local_off param to test branch range. (ppc_build_one_stub): Adjust destinations for ELFv2 locals. (ppc_size_one_stub, toc_adjusting_stub_needed): Similarly. (ppc64_elf_size_stubs): Pass local_off to ppc_type_of_stub. Set "other" field. (ppc64_elf_relocate_section): Adjust destination for ELFv2 local calls. gas/ * config/tc-ppc.c (md_pseudo_table): Add .localentry. (ppc_elf_localentry): New function. (ppc_force_relocation): Force relocs on all branches to localenty symbols. (ppc_fix_adjustable): Don't reduce such symbols to section+offset. binutils/ * readelf.c (get_ppc64_symbol_other): New function. (get_symbol_other): Use it for EM_PPC64.
Diffstat (limited to 'include')
-rw-r--r--include/elf/ChangeLog6
-rw-r--r--include/elf/ppc64.h47
2 files changed, 53 insertions, 0 deletions
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index 2999bc8..7e98ddb 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,5 +1,11 @@
2013-10-30 Alan Modra <amodra@gmail.com>
+ * ppc64.h (STO_PPC64_LOCAL_BIT, STO_PPC64_LOCAL_MASK): Define.
+ (ppc64_decode_local_entry, ppc64_encode_local_entry): New functions.
+ (PPC64_LOCAL_ENTRY_OFFSET, PPC64_SET_LOCAL_ENTRY_OFFSET): Define.
+
+2013-10-30 Alan Modra <amodra@gmail.com>
+
* ppc64.h (EF_PPC64_ABI): Define.
2013-10-30 Alan Modra <amodra@gmail.com>
diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h
index 1121649..d3cfdfb 100644
--- a/include/elf/ppc64.h
+++ b/include/elf/ppc64.h
@@ -180,6 +180,53 @@ END_RELOC_NUMBERS (R_PPC64_max)
0 for unspecified or not using any features affected by the differences. */
#define EF_PPC64_ABI 3
+/* The ELFv2 ABI uses three bits in the symbol st_other field of a
+ function definition to specify the number of instructions between a
+ function's global entry point and local entry point.
+ The global entry point is used when it is necessary to set up the
+ toc pointer (r2) for the function. Callers must enter the global
+ entry point with r12 set to the global entry point address. On
+ return from the function, r2 may have a different value to that
+ which it had on entry.
+ The local entry point is used when r2 is known to already be valid
+ for the function. There is no requirement on r12 when using the
+ local entry point, and on return r2 will contain the same value as
+ at entry.
+ A value of zero in these bits means that the function has a single
+ entry point with no requirement on r12 or r2, and that on return r2
+ will contain the same value as at entry.
+ Values of one and seven are reserved. */
+#define STO_PPC64_LOCAL_BIT 5
+#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
+
+// 3 bit other field to bytes.
+static inline unsigned int
+ppc64_decode_local_entry(unsigned int other)
+{
+ return ((1 << other) >> 2) << 2;
+}
+
+// bytes to field value.
+static inline unsigned int
+ppc64_encode_local_entry(unsigned int val)
+{
+ return (val >= 4 * 4
+ ? (val >= 8 * 4
+ ? (val >= 16 * 4 ? 6 : 5)
+ : 4)
+ : (val >= 2 * 4
+ ? 3
+ : (val >= 1 * 4 ? 2 : 0)));
+}
+
+/* st_other to number of bytes. */
+#define PPC64_LOCAL_ENTRY_OFFSET(other) \
+ ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK) \
+ >> STO_PPC64_LOCAL_BIT)
+/* number of bytes to st_other. */
+#define PPC64_SET_LOCAL_ENTRY_OFFSET(val) \
+ ppc64_encode_local_entry (val) << STO_PPC64_LOCAL_BIT
+
/* Specify the start of the .glink section. */
#define DT_PPC64_GLINK DT_LOPROC