Skip to content

Commit

Permalink
[xray] add support for hexagon
Browse files Browse the repository at this point in the history
Adds x-ray support for hexagon to llvm codegen, clang driver,
compiler-rt libs.

Differential Revision: https://reviews.llvm.org/D113638
  • Loading branch information
androm3da committed Dec 9, 2021
1 parent bfe0719 commit 543a9ad
Show file tree
Hide file tree
Showing 18 changed files with 448 additions and 3 deletions.
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Hexagon.cpp
Expand Up @@ -226,6 +226,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);

bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);

//----------------------------------------------------------------------------
// Silence warnings for various options
Expand Down Expand Up @@ -297,6 +298,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,

CmdArgs.push_back("-lunwind");
}
if (NeedsXRayDeps)
linkXRayRuntimeDeps(HTC, CmdArgs);

CmdArgs.push_back("-lclang_rt.builtins-hexagon");
CmdArgs.push_back("-lc");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/XRayArgs.cpp
Expand Up @@ -40,6 +40,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
case llvm::Triple::x86_64:
case llvm::Triple::arm:
case llvm::Triple::aarch64:
case llvm::Triple::hexagon:
case llvm::Triple::ppc64le:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Expand Up @@ -73,7 +73,8 @@ set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
if(APPLE)
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
else()
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
powerpc64le ${HEXAGON})
endif()
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})

Expand Down
6 changes: 6 additions & 0 deletions compiler-rt/lib/xray/CMakeLists.txt
Expand Up @@ -73,6 +73,11 @@ set(powerpc64le_SOURCES
xray_trampoline_powerpc64_asm.S
)

set(hexagon_SOURCES
xray_hexagon.cpp
xray_trampoline_hexagon.S
)

set(XRAY_IMPL_HEADERS
xray_allocator.h
xray_basic_flags.h
Expand Down Expand Up @@ -111,6 +116,7 @@ set(XRAY_ALL_SOURCE_FILES
${x86_64_SOURCES}
${arm_SOURCES}
${armhf_SOURCES}
${hexagon_SOURCES}
${mips_SOURCES}
${mipsel_SOURCES}
${mips64_SOURCES}
Expand Down
168 changes: 168 additions & 0 deletions compiler-rt/lib/xray/xray_hexagon.cpp
@@ -0,0 +1,168 @@
//===-- xray_hexagon.cpp --------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file is a part of XRay, a dynamic runtime instrumentation system.
//
// Implementation of hexagon-specific routines (32-bit).
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_common.h"
#include "xray_defs.h"
#include "xray_interface_internal.h"
#include <assert.h>
#include <atomic>

namespace __xray {

// The machine codes for some instructions used in runtime patching.
enum PatchOpcodes : uint32_t {
PO_JUMPI_14 = 0x5800c00a, // jump #0x014 (PC + 0x014)
PO_CALLR_R6 = 0x50a6c000, // indirect call: callr r6
PO_TFR_IMM = 0x78000000, // transfer immed
// ICLASS 0x7 - S2-type A-type
PO_IMMEXT = 0x00000000, // constant extender
};

enum PacketWordParseBits : uint32_t {
PP_DUPLEX = 0x00 << 14,
PP_NOT_END = 0x01 << 14,
PP_PACKET_END = 0x03 << 14,
};

enum RegNum : uint32_t {
RN_R6 = 0x6,
RN_R7 = 0x7,
};

inline static uint32_t
encodeExtendedTransferImmediate(uint32_t Imm, RegNum DestReg,
bool PacketEnd = false) XRAY_NEVER_INSTRUMENT {
static const uint32_t REG_MASK = 0x1f;
assert((DestReg & (~REG_MASK)) == 0);
// The constant-extended register transfer encodes the 6 least
// significant bits of the effective constant:
Imm = Imm & 0x03f;
const PacketWordParseBits ParseBits = PacketEnd ? PP_PACKET_END : PP_NOT_END;

return PO_TFR_IMM | ParseBits | (Imm << 5) | (DestReg & REG_MASK);
}

inline static uint32_t
encodeConstantExtender(uint32_t Imm) XRAY_NEVER_INSTRUMENT {
// Bits Name Description
// ----- ------- ------------------------------------------
// 31:28 ICLASS Instruction class = 0000
// 27:16 high High 12 bits of 26-bit constant extension
// 15:14 Parse Parse bits
// 13:0 low Low 14 bits of 26-bit constant extension
static const uint32_t IMM_MASK_LOW = 0x03fff;
static const uint32_t IMM_MASK_HIGH = 0x00fff << 14;

// The extender encodes the 26 most significant bits of the effective
// constant:
Imm = Imm >> 6;

const uint32_t high = (Imm & IMM_MASK_HIGH) << 16;
const uint32_t low = Imm & IMM_MASK_LOW;

return PO_IMMEXT | high | PP_NOT_END | low;
}

static void WriteInstFlushCache(void *Addr, uint32_t NewInstruction) {
asm volatile("icinva(%[inst_addr])\n\t"
"isync\n\t"
"memw(%[inst_addr]) = %[new_inst]\n\t"
"dccleaninva(%[inst_addr])\n\t"
"syncht\n\t"
:
: [ inst_addr ] "r"(Addr), [ new_inst ] "r"(NewInstruction)
: "memory");
}

inline static bool patchSled(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled,
void (*TracingHook)()) XRAY_NEVER_INSTRUMENT {
// When |Enable| == true,
// We replace the following compile-time stub (sled):
//
// .L_xray_sled_N:
// <xray_sled_base>:
// { jump .Ltmp0 }
// { nop
// nop
// nop
// nop }
// .Ltmp0:

// With the following runtime patch:
//
// xray_sled_n (32-bit):
//
// <xray_sled_n>:
// { immext(#...) // upper 26-bits of func id
// r7 = ##... // lower 6-bits of func id
// immext(#...) // upper 26-bits of trampoline
// r6 = ##... } // lower 6 bits of trampoline
// { callr r6 }
//
// When |Enable|==false, we set back the first instruction in the sled to be
// { jump .Ltmp0 }

uint32_t *FirstAddress = reinterpret_cast<uint32_t *>(Sled.address());
if (Enable) {
uint32_t *CurAddress = FirstAddress + 1;
*CurAddress = encodeExtendedTransferImmediate(FuncId, RN_R7);
CurAddress++;
*CurAddress = encodeConstantExtender(reinterpret_cast<uint32_t>(TracingHook));
CurAddress++;
*CurAddress =
encodeExtendedTransferImmediate(reinterpret_cast<uint32_t>(TracingHook), RN_R6, true);
CurAddress++;

*CurAddress = uint32_t(PO_CALLR_R6);

WriteInstFlushCache(FirstAddress, uint32_t(encodeConstantExtender(FuncId)));
} else {
WriteInstFlushCache(FirstAddress, uint32_t(PatchOpcodes::PO_JUMPI_14));
}
return true;
}

bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled,
void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
return patchSled(Enable, FuncId, Sled, Trampoline);
}

bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
}

bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
}

bool patchCustomEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
// FIXME: Implement in hexagon?
return false;
}

bool patchTypedEvent(const bool Enable, const uint32_t FuncId,
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
// FIXME: Implement in hexagon?
return false;
}

} // namespace __xray

extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
// FIXME: this will have to be implemented in the trampoline assembly file
}
2 changes: 2 additions & 0 deletions compiler-rt/lib/xray/xray_interface.cpp
Expand Up @@ -52,6 +52,8 @@ static const int16_t cSledLength = 48;
static const int16_t cSledLength = 64;
#elif defined(__powerpc64__)
static const int16_t cSledLength = 8;
#elif defined(__hexagon__)
static const int16_t cSledLength = 20;
#else
#error "Unsupported CPU Architecture"
#endif /* CPU architecture */
Expand Down
99 changes: 99 additions & 0 deletions compiler-rt/lib/xray/xray_trampoline_hexagon.S
@@ -0,0 +1,99 @@
//===-- xray_trampoline_hexagon.s -------------------------------*- ASM -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file is a part of XRay, a dynamic runtime instrumentation system.
//
// This implements the hexagon-specific assembler for the trampolines.
//
//===----------------------------------------------------------------------===//

#include "../builtins/assembly.h"
#include "../sanitizer_common/sanitizer_asm.h"

.macro SAVE_REGISTERS
memw(sp+#0)=r0
memw(sp+#4)=r1
memw(sp+#8)=r2
memw(sp+#12)=r3
memw(sp+#16)=r4
.endm
.macro RESTORE_REGISTERS
r0=memw(sp+#0)
r1=memw(sp+#4)
r2=memw(sp+#8)
r3=memw(sp+#12)
r4=memw(sp+#16)
.endm

.macro CALL_PATCHED_FUNC entry_type
// if (xray::XRayPatchedFunctionE != NULL)
// xray::XRayPatchedFunctionE(FuncType);

r8 = #ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)

// The patched sled puts the function type
// into r6. Move it into r0 to pass it to
// the patched function.
{ r0 = r6
r1 = \entry_type
p0 = !cmp.eq(r8, #0)
if (p0) callr r8 }
.endm

.text
.globl ASM_SYMBOL(__xray_FunctionEntry)
ASM_HIDDEN(__xray_FunctionEntry)
ASM_TYPE_FUNCTION(__xray_FunctionEntry)
# LLVM-MCA-BEGIN __xray_FunctionEntry
ASM_SYMBOL(__xray_FunctionEntry):
CFI_STARTPROC
SAVE_REGISTERS

CALL_PATCHED_FUNC #0 // XRayEntryType::ENTRY
.Ltmp0:
RESTORE_REGISTERS
// return
# LLVM-MCA-END
ASM_SIZE(__xray_FunctionEntry)
CFI_ENDPROC


.globl ASM_SYMBOL(__xray_FunctionExit)
ASM_HIDDEN(__xray_FunctionExit)
ASM_TYPE_FUNCTION(__xray_FunctionExit)
# LLVM-MCA-BEGIN __xray_FunctionExit
ASM_SYMBOL(__xray_FunctionExit):
CFI_STARTPROC
SAVE_REGISTERS

CALL_PATCHED_FUNC #1 // XRayEntryType::EXIT
.Ltmp1:
RESTORE_REGISTERS
// return
jumpr r31
# LLVM-MCA-END
ASM_SIZE(__xray_FunctionExit)
CFI_ENDPROC


.globl ASM_SYMBOL(__xray_FunctionTailExit)
ASM_HIDDEN(__xray_FunctionTailExit)
ASM_TYPE_FUNCTION(__xray_FunctionTailExit)
# LLVM-MCA-BEGIN __xray_FunctionTailExit
ASM_SYMBOL(__xray_FunctionTailExit):
CFI_STARTPROC
SAVE_REGISTERS

CALL_PATCHED_FUNC #2 // XRayEntryType::TAIL
.Ltmp2:
RESTORE_REGISTERS
// return
jumpr r31
# LLVM-MCA-END
ASM_SIZE(__xray_FunctionTailExit)
CFI_ENDPROC
3 changes: 2 additions & 1 deletion compiler-rt/lib/xray/xray_tsc.h
Expand Up @@ -42,7 +42,8 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
#include "xray_x86_64.inc"
#elif defined(__powerpc64__)
#include "xray_powerpc64.inc"
#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__)
#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
defined(__hexagon__)
// Emulated TSC.
// There is no instruction like RDTSCP in user mode on ARM. ARM's CP15 does
// not have a constant frequency like TSC on x86(_64), it may go faster
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/XRayInstrumentation.cpp
Expand Up @@ -226,6 +226,7 @@ bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {
case Triple::ArchType::arm:
case Triple::ArchType::thumb:
case Triple::ArchType::aarch64:
case Triple::ArchType::hexagon:
case Triple::ArchType::mips:
case Triple::ArchType::mipsel:
case Triple::ArchType::mips64:
Expand Down

0 comments on commit 543a9ad

Please sign in to comment.