forked from OSchip/llvm-project
[Compiler-rt][XRAY][MIPS] Support xray on mips/mipsel/mips64/mips64el
Summary: Adds support for xray on mips/mipsel/mips64/mips64el. Reviewed by sdardis, dberris Differential: D27699 llvm-svn: 295166
This commit is contained in:
parent
ec65792910
commit
ea831e4c46
|
@ -183,7 +183,7 @@ set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
|
|||
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64})
|
||||
set(ALL_ESAN_SUPPORTED_ARCH ${X86_64} ${MIPS64})
|
||||
set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64})
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64})
|
||||
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64})
|
||||
|
||||
if(APPLE)
|
||||
include(CompilerRTDarwinUtils)
|
||||
|
|
|
@ -29,6 +29,26 @@ set(aarch64_SOURCES
|
|||
xray_trampoline_AArch64.S
|
||||
${XRAY_SOURCES})
|
||||
|
||||
set(mips_SOURCES
|
||||
xray_mips.cc
|
||||
xray_trampoline_mips.S
|
||||
${XRAY_SOURCES})
|
||||
|
||||
set(mipsel_SOURCES
|
||||
xray_mips.cc
|
||||
xray_trampoline_mips.S
|
||||
${XRAY_SOURCES})
|
||||
|
||||
set(mips64_SOURCES
|
||||
xray_mips64.cc
|
||||
xray_trampoline_mips64.S
|
||||
${XRAY_SOURCES})
|
||||
|
||||
set(mips64el_SOURCES
|
||||
xray_mips64.cc
|
||||
xray_trampoline_mips64.S
|
||||
${XRAY_SOURCES})
|
||||
|
||||
include_directories(..)
|
||||
include_directories(../../include)
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ macro(add_xray_unittest testname)
|
|||
list(APPEND TEST_DEPS gtest_main xray)
|
||||
endif()
|
||||
if(NOT APPLE)
|
||||
add_compiler_rt_test(XRayUnitTests ${testname}
|
||||
add_compiler_rt_test(XRayUnitTests ${testname}-${arch}
|
||||
OBJECTS ${TEST_OBJECTS}
|
||||
DEPS ${TEST_DEPS}
|
||||
LINK_FLAGS ${TARGET_LINK_FLAGS}
|
||||
|
|
|
@ -35,6 +35,10 @@ static const int16_t cSledLength = 12;
|
|||
static const int16_t cSledLength = 32;
|
||||
#elif defined(__arm__)
|
||||
static const int16_t cSledLength = 28;
|
||||
#elif SANITIZER_MIPS32
|
||||
static const int16_t cSledLength = 48;
|
||||
#elif SANITIZER_MIPS64
|
||||
static const int16_t cSledLength = 64;
|
||||
#else
|
||||
#error "Unsupported CPU Architecture"
|
||||
#endif /* CPU architecture */
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//===-- xray_mips.cc --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
||||
//
|
||||
// Implementation of MIPS-specific routines (32-bit).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "xray_defs.h"
|
||||
#include "xray_interface_internal.h"
|
||||
#include <atomic>
|
||||
|
||||
namespace __xray {
|
||||
|
||||
// The machine codes for some instructions used in runtime patching.
|
||||
enum PatchOpcodes : uint32_t {
|
||||
PO_ADDIU = 0x24000000, // addiu rt, rs, imm
|
||||
PO_SW = 0xAC000000, // sw rt, offset(sp)
|
||||
PO_LUI = 0x3C000000, // lui rs, %hi(address)
|
||||
PO_ORI = 0x34000000, // ori rt, rs, %lo(address)
|
||||
PO_JALR = 0x0000F809, // jalr rs
|
||||
PO_LW = 0x8C000000, // lw rt, offset(address)
|
||||
PO_B44 = 0x1000000b, // b #44
|
||||
PO_NOP = 0x0, // nop
|
||||
};
|
||||
|
||||
enum RegNum : uint32_t {
|
||||
RN_T0 = 0x8,
|
||||
RN_T9 = 0x19,
|
||||
RN_RA = 0x1F,
|
||||
RN_SP = 0x1D,
|
||||
};
|
||||
|
||||
inline static uint32_t encodeInstruction(uint32_t Opcode, uint32_t Rs,
|
||||
uint32_t Rt,
|
||||
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
|
||||
return (Opcode | Rs << 21 | Rt << 16 | Imm);
|
||||
}
|
||||
|
||||
inline static uint32_t
|
||||
encodeSpecialInstruction(uint32_t Opcode, uint32_t Rs, uint32_t Rt, uint32_t Rd,
|
||||
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
|
||||
return (Rs << 21 | Rt << 16 | Rd << 11 | Imm << 6 | Opcode);
|
||||
}
|
||||
|
||||
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):
|
||||
//
|
||||
// xray_sled_n:
|
||||
// B .tmpN
|
||||
// 11 NOPs (44 bytes)
|
||||
// .tmpN
|
||||
// ADDIU T9, T9, 44
|
||||
//
|
||||
// With the following runtime patch:
|
||||
//
|
||||
// xray_sled_n (32-bit):
|
||||
// addiu sp, sp, -8 ;create stack frame
|
||||
// nop
|
||||
// sw ra, 4(sp) ;save return address
|
||||
// sw t9, 0(sp) ;save register t9
|
||||
// lui t9, %hi(__xray_FunctionEntry/Exit)
|
||||
// ori t9, t9, %lo(__xray_FunctionEntry/Exit)
|
||||
// lui t0, %hi(function_id)
|
||||
// jalr t9 ;call Tracing hook
|
||||
// ori t0, t0, %lo(function_id) ;pass function id (delay slot)
|
||||
// lw t9, 0(sp) ;restore register t9
|
||||
// lw ra, 4(sp) ;restore return address
|
||||
// addiu sp, sp, 8 ;delete stack frame
|
||||
//
|
||||
// We add 44 bytes to t9 because we want to adjust the function pointer to
|
||||
// the actual start of function i.e. the address just after the noop sled.
|
||||
// We do this because gp displacement relocation is emitted at the start of
|
||||
// of the function i.e after the nop sled and to correctly calculate the
|
||||
// global offset table address, t9 must hold the address of the instruction
|
||||
// containing the gp displacement relocation.
|
||||
// FIXME: Is this correct for the static relocation model?
|
||||
//
|
||||
// Replacement of the first 4-byte instruction should be the last and atomic
|
||||
// operation, so that the user code which reaches the sled concurrently
|
||||
// either jumps over the whole sled, or executes the whole sled when the
|
||||
// latter is ready.
|
||||
//
|
||||
// When |Enable|==false, we set back the first instruction in the sled to be
|
||||
// B #44
|
||||
|
||||
if (Enable) {
|
||||
uint32_t LoTracingHookAddr = reinterpret_cast<int32_t>(TracingHook) & 0xffff;
|
||||
uint32_t HiTracingHookAddr =
|
||||
(reinterpret_cast<int32_t>(TracingHook) >> 16) & 0xffff;
|
||||
uint32_t LoFunctionID = FuncId & 0xffff;
|
||||
uint32_t HiFunctionID = (FuncId >> 16) & 0xffff;
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 8) = encodeInstruction(
|
||||
PatchOpcodes::PO_SW, RegNum::RN_SP, RegNum::RN_RA, 0x4);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 12) = encodeInstruction(
|
||||
PatchOpcodes::PO_SW, RegNum::RN_SP, RegNum::RN_T9, 0x0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 16) = encodeInstruction(
|
||||
PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T9, HiTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 20) = encodeInstruction(
|
||||
PatchOpcodes::PO_ORI, RegNum::RN_T9, RegNum::RN_T9, LoTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 24) = encodeInstruction(
|
||||
PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T0, HiFunctionID);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 28) = encodeSpecialInstruction(
|
||||
PatchOpcodes::PO_JALR, RegNum::RN_T9, 0x0, RegNum::RN_RA, 0X0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 32) = encodeInstruction(
|
||||
PatchOpcodes::PO_ORI, RegNum::RN_T0, RegNum::RN_T0, LoFunctionID);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 36) = encodeInstruction(
|
||||
PatchOpcodes::PO_LW, RegNum::RN_SP, RegNum::RN_T9, 0x0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 40) = encodeInstruction(
|
||||
PatchOpcodes::PO_LW, RegNum::RN_SP, RegNum::RN_RA, 0x4);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 44) = encodeInstruction(
|
||||
PatchOpcodes::PO_ADDIU, RegNum::RN_SP, RegNum::RN_SP, 0x8);
|
||||
uint32_t CreateStackSpaceInstr = encodeInstruction(
|
||||
PatchOpcodes::PO_ADDIU, RegNum::RN_SP, RegNum::RN_SP, 0xFFF8);
|
||||
std::atomic_store_explicit(
|
||||
reinterpret_cast<std::atomic<uint32_t> *>(Sled.Address),
|
||||
uint32_t(CreateStackSpaceInstr), std::memory_order_release);
|
||||
} else {
|
||||
std::atomic_store_explicit(
|
||||
reinterpret_cast<std::atomic<uint32_t> *>(Sled.Address),
|
||||
uint32_t(PatchOpcodes::PO_B44), std::memory_order_release);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
|
||||
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
|
||||
return patchSled(Enable, FuncId, Sled, __xray_FunctionEntry);
|
||||
}
|
||||
|
||||
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 {
|
||||
// FIXME: In the future we'd need to distinguish between non-tail exits and
|
||||
// tail exits for better information preservation.
|
||||
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
|
||||
}
|
||||
|
||||
} // namespace __xray
|
|
@ -0,0 +1,162 @@
|
|||
//===-- xray_mips64.cc ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
||||
//
|
||||
// Implementation of MIPS64-specific routines.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "xray_defs.h"
|
||||
#include "xray_interface_internal.h"
|
||||
#include <atomic>
|
||||
|
||||
namespace __xray {
|
||||
|
||||
// The machine codes for some instructions used in runtime patching.
|
||||
enum PatchOpcodes : uint32_t {
|
||||
PO_DADDIU = 0x64000000, // daddiu rt, rs, imm
|
||||
PO_SD = 0xFC000000, // sd rt, base(offset)
|
||||
PO_LUI = 0x3C000000, // lui rt, imm
|
||||
PO_ORI = 0x34000000, // ori rt, rs, imm
|
||||
PO_DSLL = 0x00000038, // dsll rd, rt, sa
|
||||
PO_JALR = 0x00000009, // jalr rs
|
||||
PO_LD = 0xDC000000, // ld rt, base(offset)
|
||||
PO_B60 = 0x1000000f, // b #60
|
||||
PO_NOP = 0x0, // nop
|
||||
};
|
||||
|
||||
enum RegNum : uint32_t {
|
||||
RN_T0 = 0xC,
|
||||
RN_T9 = 0x19,
|
||||
RN_RA = 0x1F,
|
||||
RN_SP = 0x1D,
|
||||
};
|
||||
|
||||
inline static uint32_t encodeInstruction(uint32_t Opcode, uint32_t Rs,
|
||||
uint32_t Rt,
|
||||
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
|
||||
return (Opcode | Rs << 21 | Rt << 16 | Imm);
|
||||
}
|
||||
|
||||
inline static uint32_t
|
||||
encodeSpecialInstruction(uint32_t Opcode, uint32_t Rs, uint32_t Rt, uint32_t Rd,
|
||||
uint32_t Imm) XRAY_NEVER_INSTRUMENT {
|
||||
return (Rs << 21 | Rt << 16 | Rd << 11 | Imm << 6 | Opcode);
|
||||
}
|
||||
|
||||
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):
|
||||
//
|
||||
// xray_sled_n:
|
||||
// B .tmpN
|
||||
// 15 NOPs (60 bytes)
|
||||
// .tmpN
|
||||
//
|
||||
// With the following runtime patch:
|
||||
//
|
||||
// xray_sled_n (64-bit):
|
||||
// daddiu sp, sp, -16 ;create stack frame
|
||||
// nop
|
||||
// sd ra, 8(sp) ;save return address
|
||||
// sd t9, 0(sp) ;save register t9
|
||||
// lui t9, %highest(__xray_FunctionEntry/Exit)
|
||||
// ori t9, t9, %higher(__xray_FunctionEntry/Exit)
|
||||
// dsll t9, t9, 16
|
||||
// ori t9, t9, %hi(__xray_FunctionEntry/Exit)
|
||||
// dsll t9, t9, 16
|
||||
// ori t9, t9, %lo(__xray_FunctionEntry/Exit)
|
||||
// lui t0, %hi(function_id)
|
||||
// jalr t9 ;call Tracing hook
|
||||
// ori t0, t0, %lo(function_id) ;pass function id (delay slot)
|
||||
// ld t9, 0(sp) ;restore register t9
|
||||
// ld ra, 8(sp) ;restore return address
|
||||
// daddiu sp, sp, 16 ;delete stack frame
|
||||
//
|
||||
// Replacement of the first 4-byte instruction should be the last and atomic
|
||||
// operation, so that the user code which reaches the sled concurrently
|
||||
// either jumps over the whole sled, or executes the whole sled when the
|
||||
// latter is ready.
|
||||
//
|
||||
// When |Enable|==false, we set back the first instruction in the sled to be
|
||||
// B #60
|
||||
|
||||
if (Enable) {
|
||||
uint32_t LoTracingHookAddr =
|
||||
reinterpret_cast<int64_t>(TracingHook) & 0xffff;
|
||||
uint32_t HiTracingHookAddr = (reinterpret_cast<int64_t>(TracingHook) >> 16) & 0xffff;
|
||||
uint32_t HigherTracingHookAddr =
|
||||
(reinterpret_cast<int64_t>(TracingHook) >> 32) & 0xffff;
|
||||
uint32_t HighestTracingHookAddr =
|
||||
(reinterpret_cast<int64_t>(TracingHook) >> 48) & 0xffff;
|
||||
uint32_t LoFunctionID = FuncId & 0xffff;
|
||||
uint32_t HiFunctionID = (FuncId >> 16) & 0xffff;
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 8) = encodeInstruction(
|
||||
PatchOpcodes::PO_SD, RegNum::RN_SP, RegNum::RN_RA, 0x8);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 12) = encodeInstruction(
|
||||
PatchOpcodes::PO_SD, RegNum::RN_SP, RegNum::RN_T9, 0x0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 16) = encodeInstruction(
|
||||
PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T9, HighestTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 20) =
|
||||
encodeInstruction(PatchOpcodes::PO_ORI, RegNum::RN_T9, RegNum::RN_T9,
|
||||
HigherTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 24) = encodeSpecialInstruction(
|
||||
PatchOpcodes::PO_DSLL, 0x0, RegNum::RN_T9, RegNum::RN_T9, 0x10);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 28) = encodeInstruction(
|
||||
PatchOpcodes::PO_ORI, RegNum::RN_T9, RegNum::RN_T9, HiTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 32) = encodeSpecialInstruction(
|
||||
PatchOpcodes::PO_DSLL, 0x0, RegNum::RN_T9, RegNum::RN_T9, 0x10);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 36) = encodeInstruction(
|
||||
PatchOpcodes::PO_ORI, RegNum::RN_T9, RegNum::RN_T9, LoTracingHookAddr);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 40) = encodeInstruction(
|
||||
PatchOpcodes::PO_LUI, 0x0, RegNum::RN_T0, HiFunctionID);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 44) = encodeSpecialInstruction(
|
||||
PatchOpcodes::PO_JALR, RegNum::RN_T9, 0x0, RegNum::RN_RA, 0X0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 48) = encodeInstruction(
|
||||
PatchOpcodes::PO_ORI, RegNum::RN_T0, RegNum::RN_T0, LoFunctionID);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 52) = encodeInstruction(
|
||||
PatchOpcodes::PO_LD, RegNum::RN_SP, RegNum::RN_T9, 0x0);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 56) = encodeInstruction(
|
||||
PatchOpcodes::PO_LD, RegNum::RN_SP, RegNum::RN_RA, 0x8);
|
||||
*reinterpret_cast<uint32_t *>(Sled.Address + 60) = encodeInstruction(
|
||||
PatchOpcodes::PO_DADDIU, RegNum::RN_SP, RegNum::RN_SP, 0x10);
|
||||
uint32_t CreateStackSpace = encodeInstruction(
|
||||
PatchOpcodes::PO_DADDIU, RegNum::RN_SP, RegNum::RN_SP, 0xfff0);
|
||||
std::atomic_store_explicit(
|
||||
reinterpret_cast<std::atomic<uint32_t> *>(Sled.Address),
|
||||
CreateStackSpace, std::memory_order_release);
|
||||
} else {
|
||||
std::atomic_store_explicit(
|
||||
reinterpret_cast<std::atomic<uint32_t> *>(Sled.Address),
|
||||
uint32_t(PatchOpcodes::PO_B60), std::memory_order_release);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
|
||||
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
|
||||
return patchSled(Enable, FuncId, Sled, __xray_FunctionEntry);
|
||||
}
|
||||
|
||||
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 {
|
||||
// FIXME: In the future we'd need to distinguish between non-tail exits and
|
||||
// tail exits for better information preservation.
|
||||
return patchSled(Enable, FuncId, Sled, __xray_FunctionExit);
|
||||
}
|
||||
|
||||
} // namespace __xray
|
|
@ -0,0 +1,110 @@
|
|||
//===-- xray_trampoline_mips.s ----------------------------------*- ASM -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
||||
//
|
||||
// This implements the MIPS-specific assembler for the trampolines.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
.text
|
||||
.file "xray_trampoline_mips.S"
|
||||
.globl __xray_FunctionEntry
|
||||
.p2align 2
|
||||
.type __xray_FunctionEntry,@function
|
||||
__xray_FunctionEntry:
|
||||
.cfi_startproc
|
||||
.set noreorder
|
||||
.cpload $t9
|
||||
.set reorder
|
||||
// Save argument registers before doing any actual work
|
||||
.cfi_def_cfa_offset 36
|
||||
addiu $sp, $sp, -36
|
||||
sw $ra, 32($sp)
|
||||
.cfi_offset 31, -4
|
||||
sw $a3, 28($sp)
|
||||
sw $a2, 24($sp)
|
||||
sw $a1, 20($sp)
|
||||
sw $a0, 16($sp)
|
||||
sdc1 $f14, 8($sp)
|
||||
sdc1 $f12, 0($sp)
|
||||
|
||||
la $t9, _ZN6__xray19XRayPatchedFunctionE
|
||||
lw $t9, 0($t9)
|
||||
|
||||
beqz $t9, FunctionEntry_restore
|
||||
|
||||
// a1=0 means that we are tracing an entry event
|
||||
move $a1, $zero
|
||||
// Function ID is in t0 (the first parameter).
|
||||
move $a0, $t0
|
||||
jalr $t9
|
||||
|
||||
FunctionEntry_restore:
|
||||
// Restore argument registers
|
||||
ldc1 $f12, 0($sp)
|
||||
ldc1 $f14, 8($sp)
|
||||
lw $a0, 16($sp)
|
||||
lw $a1, 20($sp)
|
||||
lw $a2, 24($sp)
|
||||
lw $a3, 28($sp)
|
||||
lw $ra, 32($sp)
|
||||
addiu $sp, $sp, 36
|
||||
jr $ra
|
||||
FunctionEntry_end:
|
||||
.size __xray_FunctionEntry, FunctionEntry_end-__xray_FunctionEntry
|
||||
.cfi_endproc
|
||||
|
||||
.text
|
||||
.globl __xray_FunctionExit
|
||||
.p2align 2
|
||||
.type __xray_FunctionExit,@function
|
||||
__xray_FunctionExit:
|
||||
.cfi_startproc
|
||||
.set noreorder
|
||||
.cpload $t9
|
||||
.set reorder
|
||||
// Save return registers before doing any actual work.
|
||||
.cfi_def_cfa_offset 36
|
||||
addiu $sp, $sp, -36
|
||||
sw $ra, 32($sp)
|
||||
.cfi_offset 31, -4
|
||||
sw $a1, 28($sp)
|
||||
sw $a0, 24($sp)
|
||||
sw $v1, 20($sp)
|
||||
sw $v0, 16($sp)
|
||||
sdc1 $f2, 8($sp)
|
||||
sdc1 $f0, 0($sp)
|
||||
|
||||
la $t9, _ZN6__xray19XRayPatchedFunctionE
|
||||
lw $t9, 0($t9)
|
||||
|
||||
beqz $t9, FunctionExit_restore
|
||||
|
||||
// a1=1 means that we are tracing an exit event
|
||||
li $a1, 1
|
||||
// Function ID is in t0 (the first parameter).
|
||||
move $a0, $t0
|
||||
jalr $t9
|
||||
|
||||
FunctionExit_restore:
|
||||
// Restore return registers
|
||||
ldc1 $f0, 0($sp)
|
||||
ldc1 $f2, 8($sp)
|
||||
lw $v0, 16($sp)
|
||||
lw $v1, 20($sp)
|
||||
lw $a0, 24($sp)
|
||||
lw $a1, 28($sp)
|
||||
lw $ra, 32($sp)
|
||||
addiu $sp, $sp, 36
|
||||
jr $ra
|
||||
|
||||
FunctionExit_end:
|
||||
.size __xray_FunctionExit, FunctionExit_end-__xray_FunctionExit
|
||||
.cfi_endproc
|
|
@ -0,0 +1,136 @@
|
|||
//===-- xray_trampoline_mips64.s --------------------------------*- ASM -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
||||
//
|
||||
// This implements the MIPS64-specific assembler for the trampolines.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
.text
|
||||
.file "xray_trampoline_mips64.S"
|
||||
.globl __xray_FunctionEntry
|
||||
.p2align 2
|
||||
.type __xray_FunctionEntry,@function
|
||||
__xray_FunctionEntry:
|
||||
.cfi_startproc
|
||||
// Save argument registers before doing any actual work.
|
||||
.cfi_def_cfa_offset 144
|
||||
daddiu $sp, $sp, -144
|
||||
sd $ra, 136($sp)
|
||||
.cfi_offset 31, -8
|
||||
sd $gp, 128($sp)
|
||||
sd $a7, 120($sp)
|
||||
sd $a6, 112($sp)
|
||||
sd $a5, 104($sp)
|
||||
sd $a4, 96($sp)
|
||||
sd $a3, 88($sp)
|
||||
sd $a2, 80($sp)
|
||||
sd $a1, 72($sp)
|
||||
sd $a0, 64($sp)
|
||||
sdc1 $f19, 56($sp)
|
||||
sdc1 $f18, 48($sp)
|
||||
sdc1 $f17, 40($sp)
|
||||
sdc1 $f16, 32($sp)
|
||||
sdc1 $f15, 24($sp)
|
||||
sdc1 $f14, 16($sp)
|
||||
sdc1 $f13, 8($sp)
|
||||
sdc1 $f12, 0($sp)
|
||||
|
||||
lui $gp, %hi(%neg(%gp_rel(__xray_FunctionEntry)))
|
||||
daddu $gp, $gp, $t9
|
||||
daddiu $gp ,$gp, %lo(%neg(%gp_rel(__xray_FunctionEntry)))
|
||||
|
||||
dla $t9, _ZN6__xray19XRayPatchedFunctionE
|
||||
ld $t9, 0($t9)
|
||||
|
||||
beqz $t9, FunctionEntry_restore
|
||||
|
||||
// a1=0 means that we are tracing an entry event
|
||||
move $a1, $zero
|
||||
// Function ID is in t0 (the first parameter).
|
||||
move $a0, $t0
|
||||
jalr $t9
|
||||
|
||||
FunctionEntry_restore:
|
||||
// Restore argument registers
|
||||
ldc1 $f12, 0($sp)
|
||||
ldc1 $f13, 8($sp)
|
||||
ldc1 $f14, 16($sp)
|
||||
ldc1 $f15, 24($sp)
|
||||
ldc1 $f16, 32($sp)
|
||||
ldc1 $f17, 40($sp)
|
||||
ldc1 $f18, 48($sp)
|
||||
ldc1 $f19, 56($sp)
|
||||
ld $a0, 64($sp)
|
||||
ld $a1, 72($sp)
|
||||
ld $a2, 80($sp)
|
||||
ld $a3, 88($sp)
|
||||
ld $a4, 96($sp)
|
||||
ld $a5, 104($sp)
|
||||
ld $a6, 112($sp)
|
||||
ld $a7, 120($sp)
|
||||
ld $gp, 128($sp)
|
||||
ld $ra, 136($sp)
|
||||
daddiu $sp, $sp, 144
|
||||
jr $ra
|
||||
FunctionEntry_end:
|
||||
.size __xray_FunctionEntry, FunctionEntry_end-__xray_FunctionEntry
|
||||
.cfi_endproc
|
||||
|
||||
.text
|
||||
.globl __xray_FunctionExit
|
||||
.p2align 2
|
||||
.type __xray_FunctionExit,@function
|
||||
__xray_FunctionExit:
|
||||
.cfi_startproc
|
||||
// Save return registers before doing any actual work.
|
||||
.cfi_def_cfa_offset 64
|
||||
daddiu $sp, $sp, -64
|
||||
sd $ra, 56($sp)
|
||||
.cfi_offset 31, -8
|
||||
sd $gp, 48($sp)
|
||||
sd $a0, 40($sp)
|
||||
sd $v1, 32($sp)
|
||||
sd $v0, 24($sp)
|
||||
sdc1 $f2, 16($sp)
|
||||
sdc1 $f1, 8($sp)
|
||||
sdc1 $f0, 0($sp)
|
||||
|
||||
lui $gp, %hi(%neg(%gp_rel(__xray_FunctionExit)))
|
||||
daddu $gp, $gp, $t9
|
||||
daddiu $gp ,$gp, %lo(%neg(%gp_rel(__xray_FunctionExit)))
|
||||
|
||||
dla $t9, _ZN6__xray19XRayPatchedFunctionE
|
||||
ld $t9, 0($t9)
|
||||
|
||||
beqz $t9, FunctionExit_restore
|
||||
|
||||
// a1=1 means that we are tracing an exit event
|
||||
li $a1, 1
|
||||
// Function ID is in t0 (the first parameter).
|
||||
move $a0, $t0
|
||||
jalr $t9
|
||||
|
||||
FunctionExit_restore:
|
||||
// Restore return registers
|
||||
ldc1 $f0, 0($sp)
|
||||
ldc1 $f1, 8($sp)
|
||||
ldc1 $f2, 16($sp)
|
||||
ld $v0, 24($sp)
|
||||
ld $v1, 32($sp)
|
||||
ld $a0, 40($sp)
|
||||
ld $gp, 48($sp)
|
||||
ld $ra, 56($sp)
|
||||
daddiu $sp, $sp, 64
|
||||
jr $ra
|
||||
|
||||
FunctionExit_end:
|
||||
.size __xray_FunctionExit, FunctionExit_end-__xray_FunctionExit
|
||||
.cfi_endproc
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#if defined(__x86_64__)
|
||||
#include "xray_x86_64.inc"
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__)
|
||||
// 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
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Test to check if we handle pic code properly.
|
||||
|
||||
// RUN: %clangxx_xray -fxray-instrument -std=c++11 -fpic %s -o %t
|
||||
// RUN: XRAY_OPTIONS="verbosity=1 xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s
|
||||
// After all that, clean up the output xray log.
|
||||
//
|
||||
// RUN: rm pic-test-logging-*
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
[[clang::xray_always_instrument]]
|
||||
unsigned short foo (unsigned b);
|
||||
|
||||
[[clang::xray_always_instrument]]
|
||||
unsigned short bar (unsigned short a)
|
||||
{
|
||||
printf("bar() is always instrumented!\n");
|
||||
return foo(a);
|
||||
}
|
||||
|
||||
unsigned short foo (unsigned b)
|
||||
{
|
||||
printf("foo() is always instrumented!\n");
|
||||
return b + b + 5;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
// CHECK: XRay: Log file in 'pic-test-logging-{{.*}}'
|
||||
bar(10);
|
||||
// CHECK: bar() is always instrumented!
|
||||
// CHECK-NEXT: foo() is always instrumented!
|
||||
}
|
Loading…
Reference in New Issue