mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 04:24:37 +03:00
Added indirect branch protection to function abstraction
* Adds a new entry to FuncAttributes * Adds a new API to FuncFrame
This commit is contained in:
@@ -312,6 +312,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) {
|
||||
{ Inst::kIdStr_v, Inst::kIdStp_v }
|
||||
}};
|
||||
|
||||
// Emit: 'bti' (indirect branch protection).
|
||||
if (frame.hasIndirectBranchProtection()) {
|
||||
// TODO: The instruction is not available at the moment (would be ABI break).
|
||||
// ASMJIT_PROPAGATE(emitter->bti());
|
||||
}
|
||||
|
||||
uint32_t adjustInitialOffset = pei.sizeTotal;
|
||||
|
||||
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) {
|
||||
|
||||
@@ -546,7 +546,7 @@ public:
|
||||
uint8_t _reserved1;
|
||||
};
|
||||
|
||||
//! Data that can have different meaning dependning on \ref NodeType.
|
||||
//! Data that can have different meaning depending on \ref NodeType.
|
||||
union {
|
||||
//! Data useful by any node type.
|
||||
AnyData _any;
|
||||
@@ -694,8 +694,9 @@ public:
|
||||
|
||||
//! Returns user data casted to `T*`.
|
||||
//!
|
||||
//! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer
|
||||
//! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`.
|
||||
//! User data is dedicated to be used only by AsmJit users and not touched by the library. The data is of a pointer
|
||||
//! size so you can either store a pointer or `int64_t` value through `setUserDataAsPtr()`, `setUserDataAsInt64()`
|
||||
//! and `setUserDataAsUInt64()`.
|
||||
template<typename T>
|
||||
ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
|
||||
//! Returns user data casted to `int64_t`.
|
||||
|
||||
@@ -717,6 +717,11 @@ enum class FuncAttributes : uint32_t {
|
||||
kHasFuncCalls = 0x00000020u,
|
||||
//! Function has aligned save/restore of vector registers.
|
||||
kAlignedVecSR = 0x00000040u,
|
||||
//! Function must begin with an instruction that marks a start of a branch or function.
|
||||
//!
|
||||
//! * `ENDBR32/ENDBR64` instruction is inserted at the beginning of the function (X86, X86_64).
|
||||
//! * `BTI` instruction is inserted at the beginning of the function (AArch64)
|
||||
kIndirectBranchProtection = 0x00000080u,
|
||||
//! FuncFrame is finalized and can be used by prolog/epilog inserter (PEI).
|
||||
kIsFinalized = 0x00000800u,
|
||||
|
||||
@@ -1072,11 +1077,18 @@ public:
|
||||
|
||||
//! Tests whether the function calls other functions.
|
||||
ASMJIT_INLINE_NODEBUG bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); }
|
||||
//! Sets `kFlagHasCalls` to true.
|
||||
//! Sets `FuncAttributes::kHasFuncCalls` to true.
|
||||
ASMJIT_INLINE_NODEBUG void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
//! Sets `kFlagHasCalls` to false.
|
||||
//! Sets `FuncAttributes::kHasFuncCalls` to false.
|
||||
ASMJIT_INLINE_NODEBUG void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
|
||||
//! Tests whether the function uses indirect branch protection, see \ref FuncAttributes::kIndirectBranchProtection.
|
||||
ASMJIT_INLINE_NODEBUG bool hasIndirectBranchProtection() const noexcept { return hasAttribute(FuncAttributes::kIndirectBranchProtection); }
|
||||
//! Enabled indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to true).
|
||||
ASMJIT_INLINE_NODEBUG void setIndirectBranchProtection() noexcept { addAttributes(FuncAttributes::kIndirectBranchProtection); }
|
||||
//! Disables indirect branch protection (sets `FuncAttributes::kIndirectBranchProtection` attribute to false).
|
||||
ASMJIT_INLINE_NODEBUG void resetIndirectBranchProtection() noexcept { clearAttributes(FuncAttributes::kIndirectBranchProtection); }
|
||||
|
||||
//! Tests whether the function has AVX enabled.
|
||||
ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); }
|
||||
//! Enables AVX use.
|
||||
|
||||
@@ -425,6 +425,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) {
|
||||
Gp gpReg = zsp; // General purpose register (temporary).
|
||||
Gp saReg = zsp; // Stack-arguments base pointer.
|
||||
|
||||
// Emit: 'endbr32' or 'endbr64' (indirect branch protection).
|
||||
if (frame.hasIndirectBranchProtection()) {
|
||||
InstId instId = emitter->is32Bit() ? Inst::kIdEndbr32 : Inst::kIdEndbr64;
|
||||
ASMJIT_PROPAGATE(emitter->emit(instId));
|
||||
}
|
||||
|
||||
// Emit: 'push zbp'
|
||||
// 'mov zbp, zsp'.
|
||||
if (frame.hasPreservedFP()) {
|
||||
|
||||
@@ -238,8 +238,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// x86::Compiler - X86Test_AlignNone
|
||||
// =================================
|
||||
// x86::Compiler - X86Test_NoAlign
|
||||
// ===============================
|
||||
|
||||
class X86Test_NoAlign : public X86TestCase {
|
||||
public:
|
||||
@@ -267,6 +267,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// x86::Compiler - X86Test_IndirectBranchProtection
|
||||
// ================================================
|
||||
|
||||
class X86Test_IndirectBranchProtection : public X86TestCase {
|
||||
public:
|
||||
X86Test_IndirectBranchProtection() : X86TestCase("IndirectBranchProtection") {}
|
||||
|
||||
static void add(TestApp& app) {
|
||||
app.add(new X86Test_IndirectBranchProtection());
|
||||
}
|
||||
|
||||
virtual void compile(x86::Compiler& cc) {
|
||||
FuncNode* func = cc.addFunc(FuncSignatureT<void>(CallConvId::kHost));
|
||||
func->addAttributes(FuncAttributes::kIndirectBranchProtection);
|
||||
cc.endFunc();
|
||||
}
|
||||
|
||||
virtual bool run(void* _func, String& result, String& expect) {
|
||||
DebugUtils::unused(result, expect);
|
||||
|
||||
typedef void (*Func)(void);
|
||||
Func func = ptr_as_func<Func>(_func);
|
||||
|
||||
func();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// x86::Compiler - X86Test_JumpMerge
|
||||
// =================================
|
||||
|
||||
@@ -4362,6 +4391,7 @@ void compiler_add_x86_tests(TestApp& app) {
|
||||
// Base tests.
|
||||
app.addT<X86Test_NoCode>();
|
||||
app.addT<X86Test_NoAlign>();
|
||||
app.addT<X86Test_IndirectBranchProtection>();
|
||||
app.addT<X86Test_AlignBase>();
|
||||
|
||||
// Jump tests.
|
||||
|
||||
Reference in New Issue
Block a user