diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index 64d7aac4c4b261dfc25fa914508e8d7992eb6946..072c8109241d21d041d1d3db2907f1e6b99ffaee 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -391,12 +391,6 @@ private: /// Manage a pipeline of metadata handlers. class MetadataManager MetadataManager; - /// Get the contents of the LSDA section for this binary. - ArrayRef getLSDAData(); - - /// Get the mapped address of the LSDA section for this binary. - uint64_t getLSDAAddress(); - static const char TimerGroupName[]; static const char TimerGroupDesc[]; @@ -540,7 +534,6 @@ private: } /// Exception handling and stack unwinding information in this binary. - ErrorOr LSDASection{std::errc::bad_address}; ErrorOr EHFrameSection{std::errc::bad_address}; /// .note.gnu.build-id section. diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index 31bb8000dda00c3b1e0a9c3badcd08ecd48443fe..6f4d1170dbe2a4aa52bed58f14062f5f998943f2 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -138,10 +138,13 @@ BinaryBasicBlock *LongJmpPass::lookupStubFromGroup( Cand = LeftCand; } int BitsAvail = BC.MIB->getPCRelEncodingSize(Inst) - 1; - uint64_t Mask = ~((1ULL << BitsAvail) - 1); + assert(BitsAvail < 63 && "PCRelEncodingSize is too large to use int64_t to" + "check for out-of-bounds."); + int64_t MaxVal = (1ULL << BitsAvail) - 1; + int64_t MinVal = -(1ULL << BitsAvail); uint64_t PCRelTgtAddress = Cand->first; - PCRelTgtAddress = DotAddress > PCRelTgtAddress ? DotAddress - PCRelTgtAddress - : PCRelTgtAddress - DotAddress; + int64_t PCOffset = (int64_t)(PCRelTgtAddress - DotAddress); + LLVM_DEBUG({ if (Candidates.size() > 1) dbgs() << "Considering stub group with " << Candidates.size() @@ -149,7 +152,7 @@ BinaryBasicBlock *LongJmpPass::lookupStubFromGroup( << ", chosen candidate address is " << Twine::utohexstr(Cand->first) << "\n"; }); - return PCRelTgtAddress & Mask ? nullptr : Cand->second; + return (PCOffset < MinVal || PCOffset > MaxVal) ? nullptr : Cand->second; } BinaryBasicBlock * @@ -512,13 +515,15 @@ bool LongJmpPass::needsStub(const BinaryBasicBlock &BB, const MCInst &Inst, } int BitsAvail = BC.MIB->getPCRelEncodingSize(Inst) - 1; - uint64_t Mask = ~((1ULL << BitsAvail) - 1); + assert(BitsAvail < 63 && "PCRelEncodingSize is too large to use int64_t to" + "check for out-of-bounds."); + int64_t MaxVal = (1ULL << BitsAvail) - 1; + int64_t MinVal = -(1ULL << BitsAvail); uint64_t PCRelTgtAddress = getSymbolAddress(BC, TgtSym, TgtBB); - PCRelTgtAddress = DotAddress > PCRelTgtAddress ? DotAddress - PCRelTgtAddress - : PCRelTgtAddress - DotAddress; + int64_t PCOffset = (int64_t)(PCRelTgtAddress - DotAddress); - return PCRelTgtAddress & Mask; + return PCOffset < MinVal || PCOffset > MaxVal; } bool LongJmpPass::relax(BinaryFunction &Func) { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index fe8c134b8554ead927c636c167edecc15e57baf1..1ade842c4ee0539513d85a20385ddbc5f1793ace 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -1676,13 +1676,6 @@ void RewriteInstance::relocateEHFrameSection() { check_error(std::move(E), "failed to patch EH frame"); } -ArrayRef RewriteInstance::getLSDAData() { - return ArrayRef(LSDASection->getData(), - LSDASection->getContents().size()); -} - -uint64_t RewriteInstance::getLSDAAddress() { return LSDASection->getAddress(); } - Error RewriteInstance::readSpecialSections() { NamedRegionTimer T("readSpecialSections", "read special sections", TimerGroupName, TimerGroupDesc, opts::TimeRewrite); @@ -1721,7 +1714,6 @@ Error RewriteInstance::readSpecialSections() { HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text"); HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab"); - LSDASection = BC->getUniqueSectionByName(".gcc_except_table"); EHFrameSection = BC->getUniqueSectionByName(".eh_frame"); BuildIDSection = BC->getUniqueSectionByName(".note.gnu.build-id"); @@ -3067,8 +3059,14 @@ void RewriteInstance::disassembleFunctions() { // Parse LSDA. if (Function.getLSDAAddress() != 0 && - !BC->getFragmentsToSkip().count(&Function)) - Function.parseLSDA(getLSDAData(), getLSDAAddress()); + !BC->getFragmentsToSkip().count(&Function)) { + ErrorOr LSDASection = + BC->getSectionForAddress(Function.getLSDAAddress()); + check_error(LSDASection.getError(), "failed to get LSDA section"); + ArrayRef LSDAData = ArrayRef( + LSDASection->getData(), LSDASection->getContents().size()); + Function.parseLSDA(LSDAData, LSDASection->getAddress()); + } } } diff --git a/bolt/test/AArch64/Inputs/long-jmp-offset-boundary.ld b/bolt/test/AArch64/Inputs/long-jmp-offset-boundary.ld new file mode 100644 index 0000000000000000000000000000000000000000..94a170ec298508e9bc0a6c3cb1de798317be242f --- /dev/null +++ b/bolt/test/AArch64/Inputs/long-jmp-offset-boundary.ld @@ -0,0 +1,11 @@ +SECTIONS { + . = 0; + . = ALIGN(0x400000); + .text : { + *(foo_section) + . += 0x7BFFFFC; + *(main_section) + ASSERT(foo == 0x400000, "Error: foo address is not 0x400000."); + ASSERT(_start == 0x8000000, "Error: _start address is not 0x8000000."); + } +} diff --git a/bolt/test/AArch64/long-jmp-offset-boundary.s b/bolt/test/AArch64/long-jmp-offset-boundary.s new file mode 100644 index 0000000000000000000000000000000000000000..1aeffd629f6f374f71a7413f5e28c97ced2f9a7e --- /dev/null +++ b/bolt/test/AArch64/long-jmp-offset-boundary.s @@ -0,0 +1,31 @@ +# This test checks long call negative offset boundary(0x8000000) for aarch64. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -nostartfiles -fuse-ld=lld -Wl,-q \ +# RUN: -Wl,--script=%p/Inputs/long-jmp-offset-boundary.ld +# RUN: llvm-bolt %t.exe -o %t.bolt.exe -skip-funcs="foo.*" +# RUN: llvm-objdump -d -j .text --print-imm-hex %t.bolt.exe | FileCheck %s + +# The default alignment of the new program header table and the new text is +# HugePageSize(2MB). +# CHECK: [[#%x,ADDR:]]: [[#]] bl +# CHECK-SAME: 0x[[#ADDR-0x8000000]] + + .text + .section foo_section,"ax",@progbits + .globl foo + .type foo,@function +foo: + ret + .size foo, .-foo + + .section main_section,"ax",@progbits + .globl _start + .type _start,@function +_start: + bl foo + ret + .size _start, .-_start diff --git a/bolt/test/Inputs/lsda.ldscript b/bolt/test/Inputs/lsda.ldscript new file mode 100644 index 0000000000000000000000000000000000000000..aa608ecd97e8c5cdda5fc404eae2a3fa9ddf456c --- /dev/null +++ b/bolt/test/Inputs/lsda.ldscript @@ -0,0 +1,7 @@ +SECTIONS { + .text : { *(.text*) } + .gcc_except_table.main : { *(.gcc_except_table*) } + . = 0x20000; + .eh_frame : { *(.eh_frame) } + . = 0x80000; +} diff --git a/bolt/test/X86/asm-dump.c b/bolt/test/X86/asm-dump.c index 5d85e2a0a151c6c2431aa14e59cbb18e29ba4902..fdd448e0c408ddbca63919906658819387337f30 100644 --- a/bolt/test/X86/asm-dump.c +++ b/bolt/test/X86/asm-dump.c @@ -1,13 +1,14 @@ /** * Test for asm-dump functionality. * - * REQUIRES: system-linux,bolt-runtime + * REQUIRES: x86_64-linux,bolt-runtime * * Compile the source * RUN: %clang -fPIC %s -o %t.exe -Wl,-q * * Profile collection: instrument the binary - * RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata -o %t.instr + * RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata -o \ + * RUN: %t.instr * * Profile collection: run instrumented binary (and capture output) * RUN: %t.instr > %t.result diff --git a/bolt/test/X86/bolt-address-translation-internal-call.test b/bolt/test/X86/bolt-address-translation-internal-call.test index edc32d966b3c92ba5042ea53348298852897d4ba..e24a9e6dc1c2272050f2c7a75d89dac48dcf8014 100644 --- a/bolt/test/X86/bolt-address-translation-internal-call.test +++ b/bolt/test/X86/bolt-address-translation-internal-call.test @@ -4,7 +4,7 @@ # internal calls) might create new blocks without a mapping to an # input block. -# REQUIRES: system-linux,bolt-runtime +# REQUIRES: x86_64-linux,bolt-runtime # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # Delete our BB symbols so BOLT doesn't mark them as entry points diff --git a/bolt/test/X86/internal-call-instrument.s b/bolt/test/X86/internal-call-instrument.s index c13717472be40245d77985571792e65402fbf552..7ddfb4fb812d3528c6f2ca7fe01925ea18dfb664 100644 --- a/bolt/test/X86/internal-call-instrument.s +++ b/bolt/test/X86/internal-call-instrument.s @@ -1,6 +1,6 @@ # This reproduces a bug with instrumentation crashes on internal call -# REQUIRES: system-linux,bolt-runtime +# REQUIRES: x86_64-linux,bolt-runtime # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # Delete our BB symbols so BOLT doesn't mark them as entry points diff --git a/bolt/test/lsda.cpp b/bolt/test/lsda.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7905a58b532daba5926142bf95413a0fee913fd --- /dev/null +++ b/bolt/test/lsda.cpp @@ -0,0 +1,47 @@ +// This test check that LSDA section named by .gcc_except_table.main is +// disassembled by BOLT. + +// RUN: %clang++ %cxxflags -O3 -flto=thin -no-pie -c %s -o %t.o +// RUN: %clang++ %cxxflags -flto=thin -no-pie -fuse-ld=lld %t.o -o %t.exe \ +// RUN: -Wl,-q -Wl,--script=%S/Inputs/lsda.ldscript +// RUN: llvm-readelf -SW %t.exe | FileCheck %s +// RUN: llvm-bolt %t.exe -o %t.bolt + +// CHECK: .gcc_except_table.main + +#include + +class MyException : public std::exception { +public: + const char *what() const throw() { + return "Custom Exception: an error occurred!"; + } +}; + +int divide(int a, int b) { + if (b == 0) { + throw MyException(); + } + return a / b; +} + +int main() { + try { + int result = divide(10, 2); // normal case + std::cout << "Result: " << result << std::endl; + result = divide(5, 0); // will cause exception + std::cout << "Result: " << result << std::endl; + // this line will not execute + } catch (const MyException &e) { + // catch custom exception + std::cerr << "Caught exception: " << e.what() << std::endl; + } catch (const std::exception &e) { + // catch other C++ exceptions + std::cerr << "Caught exception: " << e.what() << std::endl; + } catch (...) { + // catch all other exceptions + std::cerr << "Caught unknown exception" << std::endl; + } + + return 0; +} diff --git a/bolt/test/runtime/AArch64/Inputs/basic-instrumentation.s b/bolt/test/runtime/AArch64/Inputs/basic-instrumentation.s new file mode 100644 index 0000000000000000000000000000000000000000..fa1ac353f7c6bb6d4f24dfe481d07f6e50844b85 --- /dev/null +++ b/bolt/test/runtime/AArch64/Inputs/basic-instrumentation.s @@ -0,0 +1,9 @@ + .globl main + .type main, %function +main: + sub sp, sp, #16 + mov w0, wzr + str wzr, [sp, #12] + add sp, sp, #16 + ret +.size main, .-main diff --git a/bolt/test/runtime/AArch64/basic-instrumentation.test b/bolt/test/runtime/AArch64/basic-instrumentation.test new file mode 100644 index 0000000000000000000000000000000000000000..0f77b0c73c42028d29377987da53a93f1d9b60a9 --- /dev/null +++ b/bolt/test/runtime/AArch64/basic-instrumentation.test @@ -0,0 +1,22 @@ +# Try to instrument a very fast test. Input bin will not execute any code during +# runtime besides returning zero in main, so it is a good trivial case. +REQUIRES: system-linux,bolt-runtime + +RUN: %clang %p/Inputs/basic-instrumentation.s -Wl,-q -o %t.exe +RUN: llvm-bolt %t.exe -o %t --instrument \ +RUN: --instrumentation-file=%t \ +RUN: --instrumentation-file-append-pid + +# Execute program to collect profile +RUN: rm %t.*.fdata || echo Nothing to remove +RUN: %t + +# Profile should be written to %t.PID.fdata, check it +RUN: mv %t.*.fdata %t.fdata +RUN: cat %t.fdata | FileCheck -check-prefix=CHECK %s + +# Check BOLT works with this profile +RUN: llvm-bolt %t.exe --data %t.fdata -o %t.2 --reorder-blocks=cache + +# The instrumented profile should at least say main was called once +CHECK: main 0 0 1{{$}} diff --git a/bolt/test/runtime/AArch64/instrumentation-ind-call.c b/bolt/test/runtime/AArch64/instrumentation-ind-call.c new file mode 100644 index 0000000000000000000000000000000000000000..76ee8c05dd2998dd708bb719f82dda4e1fb8115c --- /dev/null +++ b/bolt/test/runtime/AArch64/instrumentation-ind-call.c @@ -0,0 +1,38 @@ +#include + +typedef int (*func_ptr)(int, int); + +int add(int a, int b) { return a + b; } + +int main() { + func_ptr fun; + fun = add; + int sum = fun(10, 20); // indirect call to 'add' + printf("The sum is: %d\n", sum); + return 0; +} +/* +REQUIRES: system-linux,bolt-runtime + +RUN: %clang %cflags %s -o %t.exe -Wl,-q -nopie -fpie + +RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ +RUN: -o %t.instrumented + +# Instrumented program needs to finish returning zero +RUN: %t.instrumented | FileCheck %s -check-prefix=CHECK-OUTPUT + +# Test that the instrumented data makes sense +RUN: llvm-bolt %t.exe -o %t.bolted --data %t.fdata \ +RUN: --reorder-blocks=ext-tsp --reorder-functions=hfsort+ \ +RUN: --print-only=main --print-finalized | FileCheck %s + +RUN: %t.bolted | FileCheck %s -check-prefix=CHECK-OUTPUT + +CHECK-OUTPUT: The sum is: 30 + +# Check that our indirect call has 1 hit recorded in the fdata file and that +# this was processed correctly by BOLT +CHECK: blr x8 # CallProfile: 1 (0 misses) : +CHECK-NEXT: { add: 1 (0 misses) } +*/ diff --git a/bolt/test/runtime/meta-merge-fdata.test b/bolt/test/runtime/meta-merge-fdata.test index 469d190df05095747ae98c063060e87233e15410..39f34ba3d8ac06d124b945a7ebf3cea8c26ce27d 100644 --- a/bolt/test/runtime/meta-merge-fdata.test +++ b/bolt/test/runtime/meta-merge-fdata.test @@ -1,7 +1,7 @@ # Meta test using merge-fdata binary UNSUPPORTED: asan # Instrumentation currently only works on X86 -REQUIRES: x86_64-linux,bolt-runtime +REQUIRES: bolt-runtime # Instrumentation, should test: # - Direct branches diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index c83a159e3f0530a57b71a666e69ae01443c3fa06..f2f76ffe4809f896f25e6372aaf16f126de572de 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -749,6 +749,8 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { uint64_t secAddr = sec.getOutputSection()->addr; if (auto *s = dyn_cast(&sec)) secAddr += s->outSecOff; + else if (auto *ehIn = dyn_cast(&sec)) + secAddr += ehIn->getParent()->outSecOff; AArch64Relaxer relaxer(sec.relocs()); for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) { const Relocation &rel = sec.relocs()[i]; diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 0b6459f852c0b380ed9bac19f00057258362e934..9d3a92e579c394a0a1690ebfdf98de13662751f8 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -1563,6 +1563,8 @@ void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { uint64_t secAddr = sec.getOutputSection()->addr; if (auto *s = dyn_cast(&sec)) secAddr += s->outSecOff; + else if (auto *ehIn = dyn_cast(&sec)) + secAddr += ehIn->getParent()->outSecOff; uint64_t lastPPCRelaxedRelocOff = -1; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index 349ccd218a579e462c064ee66b6a09ce80599255..9e49f54f6389a6cc2f5e0536f36f80719ce2d45b 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -989,6 +989,8 @@ void X86_64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { uint64_t secAddr = sec.getOutputSection()->addr; if (auto *s = dyn_cast(&sec)) secAddr += s->outSecOff; + else if (auto *ehIn = dyn_cast(&sec)) + secAddr += ehIn->getParent()->outSecOff; for (const Relocation &rel : sec.relocs()) { if (rel.expr == R_NONE) // See deleteFallThruJmpInsn continue; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 33ecccff2a632e29e4d3de5c38b5962d779ef3bf..ddd0e2569518495a0dbe297596fca8a35c14678a 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -583,13 +583,14 @@ static uint64_t readFdeAddr(uint8_t *buf, int size) { uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff, uint8_t enc) const { // The starting address to which this FDE applies is - // stored at FDE + 8 byte. + // stored at FDE + 8 byte. And this offset is within + // the .eh_frame section. size_t off = fdeOff + 8; uint64_t addr = readFdeAddr(buf + off, enc & 0xf); if ((enc & 0x70) == DW_EH_PE_absptr) return addr; if ((enc & 0x70) == DW_EH_PE_pcrel) - return addr + getParent()->addr + off; + return addr + getParent()->addr + off + outSecOff; fatal("unknown FDE size relative encoding"); } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 78f73c432112eb464146bae97913c4f304bfd497..117a05a5966ec868bc7464de404483ce3ae2d785 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -161,6 +161,8 @@ void TargetInfo::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { uint64_t secAddr = sec.getOutputSection()->addr; if (auto *s = dyn_cast(&sec)) secAddr += s->outSecOff; + else if (auto *ehIn = dyn_cast(&sec)) + secAddr += ehIn->getParent()->outSecOff; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; const uint64_t val = SignExtend64( diff --git a/lld/test/ELF/eh-frame-nonzero-offset-aarch64.s b/lld/test/ELF/eh-frame-nonzero-offset-aarch64.s new file mode 100644 index 0000000000000000000000000000000000000000..31e63a9c140985c57fe7168f32e56f3c6975c9aa --- /dev/null +++ b/lld/test/ELF/eh-frame-nonzero-offset-aarch64.s @@ -0,0 +1,53 @@ +// REQUIRES: aarch64 +// RUN: rm -rf %t && split-file %s %t && cd %t + +// RUN: llvm-mc -filetype=obj -triple=aarch64 a.s -o a.o +// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s +// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s + +// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start +// NONZERO-NEXT: {{[0-9]+}}: 00000000000000b4 {{.*}} __eh_frame_end + +// NONZERO: 0x00000088 10000000 00000000 017a5200 017c1e01 +// NONZERO-NEXT: 0x00000098 1b0c1f00 10000000 18000000 5cffffff +// NONZERO-NEXT: 0x000000a8 04000000 00000000 00000000 + +// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start +// ZERO-NEXT: {{[0-9]+}}: 0000000000000034 {{.*}} __eh_frame_end + +// ZERO: 0x00000008 10000000 00000000 017a5200 017c1e01 +// ZERO-NEXT: 0x00000018 1b0c1f00 10000000 18000000 dcffffff +// ZERO-NEXT: 0x00000028 04000000 00000000 00000000 + +//--- eh-frame-non-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + /* Padding within .eh_frame */ + . += 128; + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- eh-frame-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- a.s +.section .text.01, "ax",%progbits +.global f1 +.type f1, %function +f1: +.cfi_startproc +.space 4 +.cfi_endproc diff --git a/lld/test/ELF/eh-frame-nonzero-offset-arm.s b/lld/test/ELF/eh-frame-nonzero-offset-arm.s new file mode 100644 index 0000000000000000000000000000000000000000..eec3943a5554c81463c31a7b1fa6b182a25889bb --- /dev/null +++ b/lld/test/ELF/eh-frame-nonzero-offset-arm.s @@ -0,0 +1,54 @@ +// REQUIRES: arm +// RUN: rm -rf %t && split-file %s %t && cd %t + +// RUN: llvm-mc -filetype=obj -triple=arm a.s -o a.o +// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s +// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s + +// NONZERO: {{[0-9]+}}: 00000084 {{.*}} __eh_frame_start +// NONZERO-NEXT: {{[0-9]+}}: 000000b0 {{.*}} __eh_frame_end + +// NONZERO: 0x00000084 10000000 00000000 017a5200 017c0e01 +// NONZERO-NEXT: 0x00000094 1b0c0d00 10000000 18000000 60ffffff +// NONZERO-NEXT: 0x000000a4 04000000 00000000 00000000 + +// ZERO: {{[0-9]+}}: 00000004 {{.*}} __eh_frame_start +// ZERO-NEXT: {{[0-9]+}}: 00000030 {{.*}} __eh_frame_end + +// ZERO: 0x00000004 10000000 00000000 017a5200 017c0e01 +// ZERO-NEXT: 0x00000014 1b0c0d00 10000000 18000000 e0ffffff +// ZERO-NEXT: 0x00000024 04000000 00000000 00000000 + +//--- eh-frame-non-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + /* Padding within .eh_frame */ + . += 128; + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- eh-frame-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- a.s +.section .text.01, "ax",%progbits +.global f1 +.type f1, %function +f1: +.cfi_startproc +.cfi_sections .eh_frame +.space 4 +.cfi_endproc diff --git a/lld/test/ELF/eh-frame-nonzero-offset-ppc.s b/lld/test/ELF/eh-frame-nonzero-offset-ppc.s new file mode 100644 index 0000000000000000000000000000000000000000..7b147cf34715a25343d87ca081d3fa4338f72abb --- /dev/null +++ b/lld/test/ELF/eh-frame-nonzero-offset-ppc.s @@ -0,0 +1,53 @@ +// REQUIRES: ppc +// RUN: rm -rf %t && split-file %s %t && cd %t + +// RUN: llvm-mc -filetype=obj -triple=ppc64le a.s -o a.o +// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s +// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s + +// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start +// NONZERO-NEXT: {{[0-9]+}}: 00000000000000b4 {{.*}} __eh_frame_end + +// NONZERO: 0x00000088 10000000 00000000 017a5200 04784101 +// NONZERO-NEXT: 0x00000098 1b0c0100 10000000 18000000 5cffffff +// NONZERO-NEXT: 0x000000a8 04000000 00000000 00000000 + +// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start +// ZERO-NEXT: {{[0-9]+}}: 0000000000000034 {{.*}} __eh_frame_end + +// ZERO: 0x00000008 10000000 00000000 017a5200 04784101 +// ZERO-NEXT: 0x00000018 1b0c0100 10000000 18000000 dcffffff +// ZERO-NEXT: 0x00000028 04000000 00000000 00000000 + +//--- eh-frame-non-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + /* Padding within .eh_frame */ + . += 128; + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- eh-frame-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- a.s +.section .text.01, "ax",%progbits +.global f1 +.type f1, %function +f1: +.cfi_startproc +.space 4 +.cfi_endproc diff --git a/lld/test/ELF/eh-frame-nonzero-offset-x86.s b/lld/test/ELF/eh-frame-nonzero-offset-x86.s new file mode 100644 index 0000000000000000000000000000000000000000..e433d45a839397b570b519df63b15bb70c7d134f --- /dev/null +++ b/lld/test/ELF/eh-frame-nonzero-offset-x86.s @@ -0,0 +1,55 @@ +// REQUIRES: x86 +// RUN: rm -rf %t && split-file %s %t && cd %t + +// RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +// RUN: ld.lld a.o -T eh-frame-non-zero-offset.t -o non-zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame non-zero | FileCheck --check-prefix=NONZERO %s +// RUN: ld.lld a.o -T eh-frame-zero-offset.t -o zero +// RUN: llvm-readelf --program-headers --unwind --symbols -x .eh_frame zero | FileCheck --check-prefix=ZERO %s + +// NONZERO: {{[0-9]+}}: 0000000000000088 {{.*}} __eh_frame_start +// NONZERO-NEXT: {{[0-9]+}}: 00000000000000bc {{.*}} __eh_frame_end + +// NONZERO: 0x00000088 14000000 00000000 017a5200 01781001 +// NONZERO-NEXT: 0x00000098 1b0c0708 90010000 14000000 1c000000 +// NONZERO-NEXT: 0x000000a8 58ffffff 04000000 00000000 00000000 +// NONZERO-NEXT: 0x000000b8 00000000 + +// ZERO: {{[0-9]+}}: 0000000000000008 {{.*}} __eh_frame_start +// ZERO-NEXT: {{[0-9]+}}: 000000000000003c {{.*}} __eh_frame_end + +// ZERO: 0x00000008 14000000 00000000 017a5200 01781001 +// ZERO-NEXT: 0x00000018 1b0c0708 90010000 14000000 1c000000 +// ZERO-NEXT: 0x00000028 d8ffffff 04000000 00000000 00000000 +// ZERO-NEXT: 0x00000038 00000000 + +//--- eh-frame-non-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + /* Padding within .eh_frame */ + . += 128; + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- eh-frame-zero-offset.t +SECTIONS { + .text : { *(.text .text.*) } + .eh_frame : { + __eh_frame_start = .; + *(.eh_frame) ; + __eh_frame_end = .; + } +} + +//--- a.s +.section .text.01, "ax",%progbits +.global f1 +.type f1, %function +f1: +.cfi_startproc +.space 4 +.cfi_endproc