Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport ELF/AARCH64 JITLink backend to 14.x #9

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d0d6cfa
Revert "[MC] Always emit relocations for same-section function refere…
vchuravy Oct 1, 2021
0f3a27e
Allow for custom address spaces
vchuravy May 19, 2018
a78d0b0
[clang/CMake] Respect LLVM_TOOLS_INSTALL_DIR
Keno Sep 29, 2021
e68ee3f
Don't sink ptrtoint/inttoptr sequences into non-noop addrspacecasts.
maleadt Sep 29, 2021
b69564a
Don't merge icmps derived from pointers with addressspaces
vchuravy Jan 16, 2021
ca588e8
AArch64: Remove Bad optimization
Keno Mar 1, 2021
503f510
[LV] Handle non-integral types when considering interleave widening l…
preames Apr 4, 2022
02db4d1
Add support for unwinding during prologue/epilogue
Keno Apr 30, 2022
08d2371
[LLD] Respect LLVM_TOOLS_INSTALL_DIR
jpsamaroo Jan 18, 2022
16f0adf
[Sanitizers] Guard FP_XSTATE_MAGIC1 usage by GLIBC version
vchuravy May 2, 2022
3c1151c
[PowerPC] Allow llvm.ppc.cfence to accept pointer types
vchuravy Jun 17, 2022
5482a78
Rename EHFrameSplitter to DWARFRecordSectionSplitter
rastogishubham Mar 11, 2022
cb35459
Move DWARFRecordSectionSplitter code to its own file
rastogishubham Mar 15, 2022
3397070
[JITLink] Fix sorting bug for PC-begin candidate symbols during EH-fr…
lhames Apr 5, 2022
e9468df
[JITLink] Refactor and expand DWARF pointer encoding support.
lhames Apr 15, 2022
2d754c8
[JITLink] Add missing moves from 43acef48d38e.
lhames Apr 15, 2022
b1d39fc
[JITLink] Error instead of asserting on unrecognized edge kinds.
lhames Apr 17, 2022
4b51c03
[JITLink][ELF][AArch64] Lift MachO/arm64 edges into aarch64.h, reuse …
sunho Jun 7, 2022
e230a2a
[JITLink][AArch64] Refactor isLoadStoreImm12 check out of getPageOffs…
sunho Jun 7, 2022
649e779
[JITLink][ELF][AArch64] Implement ADR_PREL_PG_HI21, ADD_ABS_LO12_NC.
sunho Jun 7, 2022
f3d818f
[JITLink][ELF][AArch64] Implement R_AARCH64_LDST*_ABS_LO12_NC relocat…
sunho Jun 8, 2022
152c98d
[JITLink][ELF][AArch64] Implement R_AARCH64_ABS64 relocation type.
lhames Jun 8, 2022
ce401b5
[JITLink][ELF][AArch64] Implement ADR_GOT_PAGE, LD64_GOT_LO12_NC.
sunho Jun 8, 2022
a84660c
[JITLink][ELF][AArch64] Implement R_AARCH64_PREL32 and R_AARCH64_PREL64.
sunho Jun 8, 2022
11aab97
[JITLink][AArch64] Fix overflow range of Page21 fixup edge.
sunho Jun 9, 2022
ce6c028
[JITLink][ELF][AArch64] Implement R_AARCH64_JUMP26
sunho Jun 10, 2022
3bee8c9
[JITLink][ELF][AArch64] Implement Procedure Linkage Table.
sunho Jun 10, 2022
176d088
[JITLink][EHFrameSupport] Remove CodeAlignmentFactor and DataAlignmen…
sunho Jun 10, 2022
cb01a71
[JITLink][ELF][AArch64] Implement eh frame handling.
sunho Jun 10, 2022
c4d7e6c
[JITLink][AArch64] Unify table managers of ELF and MachO.
sunho Jun 14, 2022
a68eeba
[JITLink][AArch64] Lift fixup functions from aarch64.cpp to aarch64.h…
sunho Jun 14, 2022
eee4a9d
[JITLink][AArch64] Implement MoveWide16 generic edge.
sunho Jun 14, 2022
95642af
[JITLink][ELF][AArch64] Implement R_AARCH64_MOVW_UABS_G*_NC.
sunho Jun 14, 2022
fddc9fd
[JITLink][ELF] Log enum name of unsupported relocation type.
sunho Jun 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/cmake/modules/AddClang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ macro(add_clang_tool name)
get_target_export_arg(${name} Clang export_to_clangtargets)
install(TARGETS ${name}
${export_to_clangtargets}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR}
COMPONENT ${name})

if(NOT LLVM_ENABLE_IDE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ namespace __sanitizer {
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);

unsigned ucontext_t_sz(void *ctx) {
# if SANITIZER_GLIBC && SANITIZER_X64
# if SANITIZER_GLIBC && SANITIZER_X64 && __GLIBC_PREREQ (2, 27)
// See kernel arch/x86/kernel/fpu/signal.c for details.
const auto *fpregs = static_cast<ucontext_t *>(ctx)->uc_mcontext.fpregs;
// The member names differ across header versions, but the actual layout
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/msan/Linux/signal_mcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

void handler(int sig, siginfo_t *info, void *uctx) {
__msan_check_mem_is_initialized(uctx, sizeof(ucontext_t));
#if defined(__GLIBC__) && defined(__x86_64__)
#if defined(__GLIBC__) && defined(__x86_64__) && __GLIBC_PREREQ(2, 27)
auto *mctx = &static_cast<ucontext_t *>(uctx)->uc_mcontext;
if (auto *fpregs = mctx->fpregs) {
// The member names differ across header versions, but the actual layout
Expand Down
156 changes: 156 additions & 0 deletions libunwind/src/CompactUnwinder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,50 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
uint32_t savedRegistersLocations =
EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);

// If we have not stored EBP yet
if (functionStart == registers.getIP()) {
uint64_t rsp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rsp+8);
// pop return address into eip
registers.setIP(addressSpace.get64(rsp));

return UNW_STEP_SUCCESS;
} else if (functionStart + 1 == registers.getIP()) {
uint64_t rsp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rsp + 16);
// pop return address into eip
registers.setIP(addressSpace.get64(rsp + 8));

return UNW_STEP_SUCCESS;
}

// If we're about to return, we've already popped the base pointer
uint8_t b = addressSpace.get8(registers.getIP());

// This is a hack to detect VZEROUPPER but in between popq rbp and ret
// It's not pretty but it works
if (b == 0xC5) {
if ((b = addressSpace.get8(registers.getIP() + 1)) == 0xF8 &&
(b = addressSpace.get8(registers.getIP() + 2)) == 0x77)
b = addressSpace.get8(registers.getIP() + 3);
else
goto skip_ret;
}

if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) {
uint64_t rbp = registers.getSP();
// old esp is ebp less return address
registers.setSP(rbp + 16);
// pop return address into eip
registers.setIP(addressSpace.get64(rbp + 8));

return UNW_STEP_SUCCESS;
}

skip_ret:

uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset;
for (int i = 0; i < 5; ++i) {
switch (savedRegistersLocations & 0x7) {
Expand Down Expand Up @@ -430,6 +474,118 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
}
}
}

// Note that the order of these registers is so that
// registersSaved[0] is the one that will be pushed onto the stack last.
// Thus, if we want to walk this from the top, we need to go in reverse.
assert(regCount <= 6);

// check whether we are still in the prologue
uint64_t curAddr = functionStart;
if (regCount > 0) {
for (int8_t i = (int8_t)(regCount) - 1; i >= 0; --i) {
if (registers.getIP() == curAddr) {
// None of the registers have been modified yet, so we don't need to reload them
framelessUnwind(addressSpace, registers.getSP() + 8 * (regCount - (uint64_t)(i + 1)), registers);
return UNW_STEP_SUCCESS;
} else {
assert(curAddr < registers.getIP());
}


// pushq %rbp and pushq %rbx is 1 byte. Everything else 2
if ((UNWIND_X86_64_REG_RBP == registersSaved[i]) ||
(UNWIND_X86_64_REG_RBX == registersSaved[i]))
curAddr += 1;
else
curAddr += 2;
}
}
if (registers.getIP() == curAddr) {
// None of the registers have been modified yet, so we don't need to reload them
framelessUnwind(addressSpace, registers.getSP() + 8*regCount, registers);
return UNW_STEP_SUCCESS;
} else {
assert(curAddr < registers.getIP());
}


// And now for the epilogue
{
uint8_t i = 0;
uint64_t p = registers.getIP();
uint8_t b = 0;

while (true) {
b = addressSpace.get8(p++);
// This is a hack to detect VZEROUPPER but in between the popq's and ret
// It's not pretty but it works
if (b == 0xC5) {
if ((b = addressSpace.get8(p++)) == 0xF8 && (b = addressSpace.get8(p++)) == 0x77)
b = addressSpace.get8(p++);
else
break;
}
// popq %rbx popq %rbp
if (b == 0x5B || b == 0x5D) {
i++;
} else if (b == 0x41) {
b = addressSpace.get8(p++);
if (b == 0x5C || b == 0x5D || b == 0x5E || b == 0x5F)
i++;
else
break;
} else if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) {
// i pop's haven't happened yet
uint64_t savedRegisters = registers.getSP() + 8 * i;
if (regCount > 0) {
for (int8_t j = (int8_t)(regCount) - 1; j >= (int8_t)(regCount) - i; --j) {
uint64_t addr = savedRegisters - 8 * (regCount - (uint64_t)(j));
switch (registersSaved[j]) {
case UNWIND_X86_64_REG_RBX:
registers.setRBX(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R12:
registers.setR12(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R13:
registers.setR13(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R14:
registers.setR14(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_R15:
registers.setR15(addressSpace.get64(addr));
break;
case UNWIND_X86_64_REG_RBP:
registers.setRBP(addressSpace.get64(addr));
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
"function starting at 0x%llX",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
}
}
framelessUnwind(addressSpace, savedRegisters, registers);
return UNW_STEP_SUCCESS;
} else {
break;
}
}
}

/*
0x10fe2733a: 5b popq %rbx
0x10fe2733b: 41 5c popq %r12
0x10fe2733d: 41 5d popq %r13
0x10fe2733f: 41 5e popq %r14
0x10fe27341: 41 5f popq %r15
0x10fe27343: 5d popq %rbp
*/


uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount;
for (uint32_t i = 0; i < regCount; ++i) {
switch (registersSaved[i]) {
Expand Down
4 changes: 2 additions & 2 deletions lld/cmake/modules/AddLLD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ macro(add_lld_library name)
${export_to_lldtargets}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR})

if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES)
add_llvm_install_targets(install-${name}
Expand All @@ -47,7 +47,7 @@ macro(add_lld_tool name)
get_target_export_arg(${name} LLD export_to_lldtargets)
install(TARGETS ${name}
${export_to_lldtargets}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
RUNTIME DESTINATION ${LLVM_TOOLS_INSTALL_DIR}
COMPONENT ${name})

if(NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===--------- DWARFRecordSectionSplitter.h - JITLink -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_JITLINK_DWARFRECORDSECTIONSPLITTER_H
#define LLVM_EXECUTIONENGINE_JITLINK_DWARFRECORDSECTIONSPLITTER_H

#include "llvm/ExecutionEngine/JITLink/JITLink.h"

namespace llvm {
namespace jitlink {

/// A LinkGraph pass that splits blocks in a section that follows the DWARF
/// Record format into sub-blocks where each header gets its own block.
/// When splitting EHFrames, DWARFRecordSectionSplitter should not be run
/// without EHFrameEdgeFixer, which is responsible for adding FDE-to-CIE edges.
class DWARFRecordSectionSplitter {
public:
DWARFRecordSectionSplitter(StringRef SectionName);
Error operator()(LinkGraph &G);

private:
Error processBlock(LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache);

StringRef SectionName;
};

} // namespace jitlink
} // namespace llvm

#endif // LLVM_EXECUTIONENGINE_JITLINK_DWARFRECORDSECTIONSPLITTER_H
27 changes: 0 additions & 27 deletions llvm/include/llvm/ExecutionEngine/JITLink/MachO_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,6 @@
namespace llvm {
namespace jitlink {

namespace MachO_arm64_Edges {

enum MachOARM64RelocationKind : Edge::Kind {
Branch26 = Edge::FirstRelocation,
Pointer32,
Pointer64,
Pointer64Anon,
Page21,
PageOffset12,
GOTPage21,
GOTPageOffset12,
TLVPage21,
TLVPageOffset12,
PointerToGOT,
PairedAddend,
LDRLiteral19,
Delta32,
Delta64,
NegDelta32,
NegDelta64,
};

} // namespace MachO_arm64_Edges

/// Create a LinkGraph from a MachO/arm64 relocatable object.
///
/// Note: The graph does not take ownership of the underlying buffer, nor copy
Expand All @@ -62,9 +38,6 @@ createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer);
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx);

/// Return the string name of the given MachO arm64 edge kind.
const char *getMachOARM64RelocationKindName(Edge::Kind R);

} // end namespace jitlink
} // end namespace llvm

Expand Down
Loading