diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2017-01-05 19:35:47 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-02-06 18:40:48 +1100 |
commit | 4ebde139333659b6de4516830a2785b8a89c08a4 (patch) | |
tree | a04a547f3971f98a2bff5f777884daf19e5bf863 /include/elf-abi.h | |
parent | 420d62d8f545204ff615b3062b01babb8b98e11c (diff) | |
download | skiboot-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.h | 67 |
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 */ |