aboutsummaryrefslogtreecommitdiff
path: root/include/elf-abi.h
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-01-05 19:35:47 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-02-06 18:40:48 +1100
commit4ebde139333659b6de4516830a2785b8a89c08a4 (patch)
treea04a547f3971f98a2bff5f777884daf19e5bf863 /include/elf-abi.h
parent420d62d8f545204ff615b3062b01babb8b98e11c (diff)
downloadskiboot-4ebde139333659b6de4516830a2785b8a89c08a4.zip
skiboot-4ebde139333659b6de4516830a2785b8a89c08a4.tar.gz
skiboot-4ebde139333659b6de4516830a2785b8a89c08a4.tar.bz2
Initial support for the ELFv2 ABI
Provide an experimental option to compile using ELFv2 ABI even on big endian builds. ELFv2 + BE is not officially supported by the toolchain, but it works quite well. It may be useful as a small step toward a little-endian build. This saves about 200kB of text/data. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'include/elf-abi.h')
-rw-r--r--include/elf-abi.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/include/elf-abi.h b/include/elf-abi.h
new file mode 100644
index 0000000..e8397f7
--- /dev/null
+++ b/include/elf-abi.h
@@ -0,0 +1,67 @@
+/* Copyright 2017 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ELF_ABI_H
+#define __ELF_ABI_H
+
+#ifndef __ASSEMBLY__
+
+#if defined (_CALL_ELF) && _CALL_ELF == 2
+#define ELF_ABI_v2
+#else
+#define ELF_ABI_v1
+#endif
+
+/* From linux/arch/powerpc/include/asm/code-patching.h */
+#define OP_RT_RA_MASK 0xffff0000UL
+#define LIS_R2 0x3c020000UL
+#define ADDIS_R2_R12 0x3c4c0000UL
+#define ADDI_R2_R2 0x38420000UL
+
+static inline uint64_t function_entry_address(void *func)
+{
+#ifdef ELF_ABI_v2
+ u32 *insn = func;
+ /*
+ * A PPC64 ABIv2 function may have a local and a global entry
+ * point. We use the local entry point for branch tables called
+ * from asm, only a single TOC is used, so identify and step over
+ * the global entry point sequence.
+ *
+ * The global entry point sequence is always of the form:
+ *
+ * addis r2,r12,XXXX
+ * addi r2,r2,XXXX
+ *
+ * A linker optimisation may convert the addis to lis:
+ *
+ * lis r2,XXXX
+ * addi r2,r2,XXXX
+ */
+ if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
+ ((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
+ ((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2))
+ return (uint64_t)(insn + 2);
+ else
+ return (uint64_t)func;
+#else
+ return *(uint64_t *)func;
+#endif
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __COMPILER_H */