mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +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 }
|
{ 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;
|
uint32_t adjustInitialOffset = pei.sizeTotal;
|
||||||
|
|
||||||
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) {
|
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) {
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ public:
|
|||||||
uint8_t _reserved1;
|
uint8_t _reserved1;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Data that can have different meaning dependning on \ref NodeType.
|
//! Data that can have different meaning depending on \ref NodeType.
|
||||||
union {
|
union {
|
||||||
//! Data useful by any node type.
|
//! Data useful by any node type.
|
||||||
AnyData _any;
|
AnyData _any;
|
||||||
@@ -694,8 +694,9 @@ public:
|
|||||||
|
|
||||||
//! Returns user data casted to `T*`.
|
//! 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
|
//! 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 `intptr_t` value through `setUserDataAsIntPtr()`.
|
//! size so you can either store a pointer or `int64_t` value through `setUserDataAsPtr()`, `setUserDataAsInt64()`
|
||||||
|
//! and `setUserDataAsUInt64()`.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
|
ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
|
||||||
//! Returns user data casted to `int64_t`.
|
//! Returns user data casted to `int64_t`.
|
||||||
|
|||||||
@@ -717,6 +717,11 @@ enum class FuncAttributes : uint32_t {
|
|||||||
kHasFuncCalls = 0x00000020u,
|
kHasFuncCalls = 0x00000020u,
|
||||||
//! Function has aligned save/restore of vector registers.
|
//! Function has aligned save/restore of vector registers.
|
||||||
kAlignedVecSR = 0x00000040u,
|
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).
|
//! FuncFrame is finalized and can be used by prolog/epilog inserter (PEI).
|
||||||
kIsFinalized = 0x00000800u,
|
kIsFinalized = 0x00000800u,
|
||||||
|
|
||||||
@@ -1072,11 +1077,18 @@ public:
|
|||||||
|
|
||||||
//! Tests whether the function calls other functions.
|
//! Tests whether the function calls other functions.
|
||||||
ASMJIT_INLINE_NODEBUG bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); }
|
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); }
|
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); }
|
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.
|
//! Tests whether the function has AVX enabled.
|
||||||
ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); }
|
ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); }
|
||||||
//! Enables AVX use.
|
//! Enables AVX use.
|
||||||
|
|||||||
@@ -425,6 +425,12 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) {
|
|||||||
Gp gpReg = zsp; // General purpose register (temporary).
|
Gp gpReg = zsp; // General purpose register (temporary).
|
||||||
Gp saReg = zsp; // Stack-arguments base pointer.
|
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'
|
// Emit: 'push zbp'
|
||||||
// 'mov zbp, zsp'.
|
// 'mov zbp, zsp'.
|
||||||
if (frame.hasPreservedFP()) {
|
if (frame.hasPreservedFP()) {
|
||||||
|
|||||||
@@ -238,8 +238,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// x86::Compiler - X86Test_AlignNone
|
// x86::Compiler - X86Test_NoAlign
|
||||||
// =================================
|
// ===============================
|
||||||
|
|
||||||
class X86Test_NoAlign : public X86TestCase {
|
class X86Test_NoAlign : public X86TestCase {
|
||||||
public:
|
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
|
// x86::Compiler - X86Test_JumpMerge
|
||||||
// =================================
|
// =================================
|
||||||
|
|
||||||
@@ -4362,6 +4391,7 @@ void compiler_add_x86_tests(TestApp& app) {
|
|||||||
// Base tests.
|
// Base tests.
|
||||||
app.addT<X86Test_NoCode>();
|
app.addT<X86Test_NoCode>();
|
||||||
app.addT<X86Test_NoAlign>();
|
app.addT<X86Test_NoAlign>();
|
||||||
|
app.addT<X86Test_IndirectBranchProtection>();
|
||||||
app.addT<X86Test_AlignBase>();
|
app.addT<X86Test_AlignBase>();
|
||||||
|
|
||||||
// Jump tests.
|
// Jump tests.
|
||||||
|
|||||||
Reference in New Issue
Block a user