summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asmjit/src/asmjit/core/codeholder.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asmjit/src/asmjit/core/codeholder.cpp')
-rw-r--r--3rdparty/asmjit/src/asmjit/core/codeholder.cpp381
1 files changed, 211 insertions, 170 deletions
diff --git a/3rdparty/asmjit/src/asmjit/core/codeholder.cpp b/3rdparty/asmjit/src/asmjit/core/codeholder.cpp
index 8711e382ce4..cf763cfff12 100644
--- a/3rdparty/asmjit/src/asmjit/core/codeholder.cpp
+++ b/3rdparty/asmjit/src/asmjit/core/codeholder.cpp
@@ -1,36 +1,21 @@
-// AsmJit - Machine code generation for C++
+// This file is part of AsmJit project <https://asmjit.com>
//
-// * Official AsmJit Home Page: https://asmjit.com
-// * Official Github Repository: https://github.com/asmjit/asmjit
-//
-// Copyright (c) 2008-2020 The AsmJit Authors
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
+// See asmjit.h or LICENSE.md for license and copyright information
+// SPDX-License-Identifier: Zlib
#include "../core/api-build_p.h"
#include "../core/assembler.h"
+#include "../core/codewriter_p.h"
#include "../core/logger.h"
#include "../core/support.h"
+#include <algorithm>
+#include <tuple>
+
ASMJIT_BEGIN_NAMESPACE
-// ============================================================================
-// [Globals]
-// ============================================================================
+// Globals
+// =======
static const char CodeHolder_addrTabName[] = ".addrtab";
@@ -39,31 +24,30 @@ static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcep
return (m << 6) | (o << 3) | rm;
}
-// ============================================================================
-// [asmjit::LabelLinkIterator]
-// ============================================================================
+// LabelLinkIterator
+// =================
class LabelLinkIterator {
public:
- ASMJIT_INLINE LabelLinkIterator(LabelEntry* le) noexcept { reset(le); }
+ inline LabelLinkIterator(LabelEntry* le) noexcept { reset(le); }
- ASMJIT_INLINE explicit operator bool() const noexcept { return isValid(); }
- ASMJIT_INLINE bool isValid() const noexcept { return _link != nullptr; }
+ inline explicit operator bool() const noexcept { return isValid(); }
+ inline bool isValid() const noexcept { return _link != nullptr; }
- ASMJIT_INLINE LabelLink* link() const noexcept { return _link; }
- ASMJIT_INLINE LabelLink* operator->() const noexcept { return _link; }
+ inline LabelLink* link() const noexcept { return _link; }
+ inline LabelLink* operator->() const noexcept { return _link; }
- ASMJIT_INLINE void reset(LabelEntry* le) noexcept {
+ inline void reset(LabelEntry* le) noexcept {
_pPrev = &le->_links;
_link = *_pPrev;
}
- ASMJIT_INLINE void next() noexcept {
+ inline void next() noexcept {
_pPrev = &_link->next;
_link = *_pPrev;
}
- ASMJIT_INLINE void resolveAndNext(CodeHolder* code) noexcept {
+ inline void resolveAndNext(CodeHolder* code) noexcept {
LabelLink* linkToDelete = _link;
_link = _link->next;
@@ -77,11 +61,10 @@ public:
LabelLink* _link;
};
-// ============================================================================
-// [asmjit::CodeHolder - Utilities]
-// ============================================================================
+// CodeHolder - Utilities
+// ======================
-static void CodeHolder_resetInternal(CodeHolder* self, uint32_t resetPolicy) noexcept {
+static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) noexcept {
uint32_t i;
const ZoneVector<BaseEmitter*>& emitters = self->emitters();
@@ -113,6 +96,7 @@ static void CodeHolder_resetInternal(CodeHolder* self, uint32_t resetPolicy) noe
self->_relocations.reset();
self->_labelEntries.reset();
self->_sections.reset();
+ self->_sectionsByOrder.reset();
self->_unresolvedLinkCount = 0;
self->_addressTableSection = nullptr;
@@ -129,27 +113,25 @@ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept {
}
}
-// ============================================================================
-// [asmjit::CodeHolder - Construction / Destruction]
-// ============================================================================
+// CodeHolder - Construction & Destruction
+// =======================================
-CodeHolder::CodeHolder() noexcept
+CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept
: _environment(),
_baseAddress(Globals::kNoBaseAddress),
_logger(nullptr),
_errorHandler(nullptr),
- _zone(16384 - Zone::kBlockOverhead),
+ _zone(16384 - Zone::kBlockOverhead, 1, temporary),
_allocator(&_zone),
_unresolvedLinkCount(0),
_addressTableSection(nullptr) {}
CodeHolder::~CodeHolder() noexcept {
- CodeHolder_resetInternal(this, Globals::kResetHard);
+ CodeHolder_resetInternal(this, ResetPolicy::kHard);
}
-// ============================================================================
-// [asmjit::CodeHolder - Init / Reset]
-// ============================================================================
+// CodeHolder - Init & Reset
+// =========================
inline void CodeHolder_setSectionDefaultName(
Section* section,
@@ -169,13 +151,15 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe
ASMJIT_ASSERT(_emitters.empty());
// Create a default section and insert it to the `_sections` array.
- Error err = _sections.willGrow(&_allocator);
+ Error err = _sections.willGrow(&_allocator) |
+ _sectionsByOrder.willGrow(&_allocator);
if (err == kErrorOk) {
Section* section = _allocator.allocZeroedT<Section>();
if (ASMJIT_LIKELY(section)) {
- section->_flags = Section::kFlagExec | Section::kFlagConst;
+ section->_flags = SectionFlags::kExecutable | SectionFlags::kReadOnly;
CodeHolder_setSectionDefaultName(section, '.', 't', 'e', 'x', 't');
_sections.appendUnsafe(section);
+ _sectionsByOrder.appendUnsafe(section);
}
else {
err = DebugUtils::errored(kErrorOutOfMemory);
@@ -193,13 +177,12 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe
}
}
-void CodeHolder::reset(uint32_t resetPolicy) noexcept {
+void CodeHolder::reset(ResetPolicy resetPolicy) noexcept {
CodeHolder_resetInternal(this, resetPolicy);
}
-// ============================================================================
-// [asmjit::CodeHolder - Attach / Detach]
-// ============================================================================
+// CodeHolder - Attach / Detach
+// ============================
Error CodeHolder::attach(BaseEmitter* emitter) noexcept {
// Catch a possible misuse of the API.
@@ -207,10 +190,14 @@ Error CodeHolder::attach(BaseEmitter* emitter) noexcept {
return DebugUtils::errored(kErrorInvalidArgument);
// Invalid emitter, this should not be possible.
- uint32_t type = emitter->emitterType();
- if (ASMJIT_UNLIKELY(type == BaseEmitter::kTypeNone || type >= BaseEmitter::kTypeCount))
+ EmitterType type = emitter->emitterType();
+ if (ASMJIT_UNLIKELY(type == EmitterType::kNone || uint32_t(type) > uint32_t(EmitterType::kMaxValue)))
return DebugUtils::errored(kErrorInvalidState);
+ uint64_t archMask = emitter->_archMask;
+ if (ASMJIT_UNLIKELY(!(archMask & (uint64_t(1) << uint32_t(arch())))))
+ return DebugUtils::errored(kErrorInvalidArch);
+
// This is suspicious, but don't fail if `emitter` is already attached
// to this code holder. This is not error, but it's not recommended.
if (emitter->_code != nullptr) {
@@ -254,9 +241,8 @@ Error CodeHolder::detach(BaseEmitter* emitter) noexcept {
return err;
}
-// ============================================================================
-// [asmjit::CodeHolder - Logging]
-// ============================================================================
+// CodeHolder - Logging
+// ====================
void CodeHolder::setLogger(Logger* logger) noexcept {
#ifndef ASMJIT_NO_LOGGING
@@ -267,18 +253,16 @@ void CodeHolder::setLogger(Logger* logger) noexcept {
#endif
}
-// ============================================================================
-// [asmjit::CodeHolder - Error Handling]
-// ============================================================================
+// CodeHolder - Error Handling
+// ===========================
void CodeHolder::setErrorHandler(ErrorHandler* errorHandler) noexcept {
_errorHandler = errorHandler;
CodeHolder_onSettingsUpdated(this);
}
-// ============================================================================
-// [asmjit::CodeHolder - Code Buffer]
-// ============================================================================
+// CodeHolder - Code Buffer
+// ========================
static Error CodeHolder_reserveInternal(CodeHolder* self, CodeBuffer* cb, size_t n) noexcept {
uint8_t* oldData = cb->_data;
@@ -351,7 +335,9 @@ Error CodeHolder::growBuffer(CodeBuffer* cb, size_t n) noexcept {
Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept {
size_t capacity = cb->capacity();
- if (n <= capacity) return kErrorOk;
+
+ if (n <= capacity)
+ return kErrorOk;
if (cb->isFixed())
return DebugUtils::errored(kErrorTooLarge);
@@ -359,11 +345,10 @@ Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept {
return CodeHolder_reserveInternal(this, cb, n);
}
-// ============================================================================
-// [asmjit::CodeHolder - Sections]
-// ============================================================================
+// CodeHolder - Sections
+// =====================
-Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, uint32_t flags, uint32_t alignment) noexcept {
+Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, SectionFlags flags, uint32_t alignment, int32_t order) noexcept {
*sectionOut = nullptr;
if (nameSize == SIZE_MAX)
@@ -383,16 +368,24 @@ Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t name
return DebugUtils::errored(kErrorTooManySections);
ASMJIT_PROPAGATE(_sections.willGrow(&_allocator));
- Section* section = _allocator.allocZeroedT<Section>();
+ ASMJIT_PROPAGATE(_sectionsByOrder.willGrow(&_allocator));
+ Section* section = _allocator.allocZeroedT<Section>();
if (ASMJIT_UNLIKELY(!section))
return DebugUtils::errored(kErrorOutOfMemory);
section->_id = sectionId;
section->_flags = flags;
section->_alignment = alignment;
+ section->_order = order;
memcpy(section->_name.str, name, nameSize);
+
+ Section** insertPosition = std::lower_bound(_sectionsByOrder.begin(), _sectionsByOrder.end(), section, [](const Section* a, const Section* b) {
+ return std::make_tuple(a->order(), a->id()) < std::make_tuple(b->order(), b->id());
+ });
+
_sections.appendUnsafe(section);
+ _sectionsByOrder.insertUnsafe((size_t)(insertPosition - _sectionsByOrder.data()), section);
*sectionOut = section;
return kErrorOk;
@@ -405,7 +398,7 @@ Section* CodeHolder::sectionByName(const char* name, size_t nameSize) const noex
// This could be also put in a hash-table similarly like we do with labels,
// however it's questionable as the number of sections should be pretty low
// in general. Create an issue if this becomes a problem.
- if (ASMJIT_UNLIKELY(nameSize <= Globals::kMaxSectionNameSize)) {
+ if (nameSize <= Globals::kMaxSectionNameSize) {
for (Section* section : _sections)
if (memcmp(section->_name.str, name, nameSize) == 0 && section->_name.str[nameSize] == '\0')
return section;
@@ -418,7 +411,12 @@ Section* CodeHolder::ensureAddressTableSection() noexcept {
if (_addressTableSection)
return _addressTableSection;
- newSection(&_addressTableSection, CodeHolder_addrTabName, sizeof(CodeHolder_addrTabName) - 1, 0, _environment.registerSize());
+ newSection(&_addressTableSection,
+ CodeHolder_addrTabName,
+ sizeof(CodeHolder_addrTabName) - 1,
+ SectionFlags::kNone,
+ _environment.registerSize(),
+ std::numeric_limits<int32_t>::max());
return _addressTableSection;
}
@@ -441,9 +439,8 @@ Error CodeHolder::addAddressToAddressTable(uint64_t address) noexcept {
return kErrorOk;
}
-// ============================================================================
-// [asmjit::CodeHolder - Labels / Symbols]
-// ============================================================================
+// CodeHolder - Labels & Symbols
+// =============================
//! Only used to lookup a label from `_namedLabels`.
class LabelByName {
@@ -491,20 +488,7 @@ static uint32_t CodeHolder_hashNameAndGetSize(const char* name, size_t& nameSize
return hashCode;
}
-static bool CodeHolder_writeDisplacement(void* dst, int64_t displacement, uint32_t displacementSize) {
- if (displacementSize == 4 && Support::isInt32(displacement)) {
- Support::writeI32uLE(dst, int32_t(displacement));
- return true;
- }
- else if (displacementSize == 1 && Support::isInt8(displacement)) {
- Support::writeI8(dst, int8_t(displacement));
- return true;
- }
-
- return false;
-}
-
-LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel) noexcept {
+LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel, const OffsetFormat& format) noexcept {
LabelLink* link = _allocator.allocT<LabelLink>();
if (ASMJIT_UNLIKELY(!link)) return nullptr;
@@ -515,6 +499,7 @@ LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t o
link->relocId = Globals::kInvalidId;
link->offset = offset;
link->rel = rel;
+ link->format = format;
_unresolvedLinkCount++;
return link;
@@ -542,32 +527,66 @@ Error CodeHolder::newLabelEntry(LabelEntry** entryOut) noexcept {
return kErrorOk;
}
-Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId) noexcept {
+Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, LabelType type, uint32_t parentId) noexcept {
*entryOut = nullptr;
uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize);
- if (ASMJIT_UNLIKELY(nameSize == 0))
- return DebugUtils::errored(kErrorInvalidLabelName);
+ if (ASMJIT_UNLIKELY(nameSize == 0)) {
+ if (type == LabelType::kAnonymous)
+ return newLabelEntry(entryOut);
+ else
+ return DebugUtils::errored(kErrorInvalidLabelName);
+ }
if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxLabelNameSize))
return DebugUtils::errored(kErrorLabelNameTooLong);
switch (type) {
- case Label::kTypeLocal:
+ case LabelType::kAnonymous: {
+ // Anonymous labels cannot have a parent (or more specifically, parent is useless here).
+ if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId))
+ return DebugUtils::errored(kErrorInvalidParentLabel);
+
+ uint32_t labelId = _labelEntries.size();
+ if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId))
+ return DebugUtils::errored(kErrorTooManyLabels);
+
+ ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator));
+ LabelEntry* le = _allocator.allocZeroedT<LabelEntry>();
+
+ if (ASMJIT_UNLIKELY(!le))
+ return DebugUtils::errored(kErrorOutOfMemory);
+
+ // NOTE: This LabelEntry has a name, but we leave its hashCode as zero as it's anonymous.
+ le->_setId(labelId);
+ le->_parentId = Globals::kInvalidId;
+ le->_offset = 0;
+ ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize));
+
+ _labelEntries.appendUnsafe(le);
+
+ *entryOut = le;
+ return kErrorOk;
+ }
+
+ case LabelType::kLocal: {
if (ASMJIT_UNLIKELY(parentId >= _labelEntries.size()))
return DebugUtils::errored(kErrorInvalidParentLabel);
hashCode ^= parentId;
break;
+ }
- case Label::kTypeGlobal:
+ case LabelType::kGlobal:
+ case LabelType::kExternal: {
if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId))
- return DebugUtils::errored(kErrorNonLocalLabelCannotHaveParent);
-
+ return DebugUtils::errored(kErrorInvalidParentLabel);
break;
+ }
- default:
+ default: {
return DebugUtils::errored(kErrorInvalidArgument);
+ }
}
// Don't allow to insert duplicates. Local labels allow duplicates that have
@@ -591,7 +610,7 @@ Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, si
le->_hashCode = hashCode;
le->_setId(labelId);
- le->_type = uint8_t(type);
+ le->_type = type;
le->_parentId = parentId;
le->_offset = 0;
ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize));
@@ -640,18 +659,16 @@ ASMJIT_API Error CodeHolder::resolveUnresolvedLinks() noexcept {
ASMJIT_ASSERT(linkOffset < buf.size());
// Calculate the offset relative to the start of the virtual base.
- uint64_t fromOffset = Support::addOverflow<uint64_t>(fromSection->offset(), linkOffset, &of);
+ Support::FastUInt8 localOF = of;
+ uint64_t fromOffset = Support::addOverflow<uint64_t>(fromSection->offset(), linkOffset, &localOF);
int64_t displacement = int64_t(toOffset - fromOffset + uint64_t(int64_t(link->rel)));
- if (!of) {
+ if (!localOF) {
ASMJIT_ASSERT(size_t(linkOffset) < buf.size());
-
- // Size of the value we are going to patch. Only BYTE/DWORD is allowed.
- uint32_t displacementSize = buf._data[linkOffset];
- ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= displacementSize);
+ ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.valueSize());
// Overwrite a real displacement in the CodeBuffer.
- if (CodeHolder_writeDisplacement(buf._data + linkOffset, displacement, displacementSize)) {
+ if (CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) {
link.resolveAndNext(this);
continue;
}
@@ -714,11 +731,10 @@ ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId,
int64_t displacement = int64_t(toOffset - uint64_t(linkOffset) + uint64_t(int64_t(link->rel)));
// Size of the value we are going to patch. Only BYTE/DWORD is allowed.
- uint32_t displacementSize = buf._data[linkOffset];
- ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= displacementSize);
+ ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.regionSize());
// Overwrite a real displacement in the CodeBuffer.
- if (!CodeHolder_writeDisplacement(buf._data + linkOffset, displacement, displacementSize)) {
+ if (!CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) {
err = DebugUtils::errored(kErrorInvalidDisplacement);
link.next();
continue;
@@ -731,11 +747,10 @@ ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId,
return err;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Relocations]
-// ============================================================================
+// CodeHolder - Relocations
+// ========================
-Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType, uint32_t valueSize) noexcept {
+Error CodeHolder::newRelocEntry(RelocEntry** dst, RelocType relocType) noexcept {
ASMJIT_PROPAGATE(_relocations.willGrow(&_allocator));
uint32_t relocId = _relocations.size();
@@ -747,8 +762,7 @@ Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType, uint32_t v
return DebugUtils::errored(kErrorOutOfMemory);
re->_id = relocId;
- re->_relocType = uint8_t(relocType);
- re->_valueSize = uint8_t(valueSize);
+ re->_relocType = relocType;
re->_sourceSectionId = Globals::kInvalidId;
re->_targetSectionId = Globals::kInvalidId;
_relocations.appendUnsafe(re);
@@ -757,26 +771,25 @@ Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType, uint32_t v
return kErrorOk;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Expression Evaluation]
-// ============================================================================
+// CodeHolder - Expression Evaluation
+// ==================================
static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, uint64_t* out) noexcept {
uint64_t value[2];
for (size_t i = 0; i < 2; i++) {
uint64_t v;
switch (exp->valueType[i]) {
- case Expression::kValueNone: {
+ case ExpressionValueType::kNone: {
v = 0;
break;
}
- case Expression::kValueConstant: {
+ case ExpressionValueType::kConstant: {
v = exp->value[i].constant;
break;
}
- case Expression::kValueLabel: {
+ case ExpressionValueType::kLabel: {
LabelEntry* le = exp->value[i].label;
if (!le->isBound())
return DebugUtils::errored(kErrorExpressionLabelNotBound);
@@ -784,7 +797,7 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui
break;
}
- case Expression::kValueExpression: {
+ case ExpressionValueType::kExpression: {
Expression* nested = exp->value[i].expression;
ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(self, nested, &v));
break;
@@ -802,27 +815,27 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui
uint64_t& b = value[1];
switch (exp->opType) {
- case Expression::kOpAdd:
+ case ExpressionOpType::kAdd:
result = a + b;
break;
- case Expression::kOpSub:
+ case ExpressionOpType::kSub:
result = a - b;
break;
- case Expression::kOpMul:
+ case ExpressionOpType::kMul:
result = a * b;
break;
- case Expression::kOpSll:
+ case ExpressionOpType::kSll:
result = (b > 63) ? uint64_t(0) : uint64_t(a << b);
break;
- case Expression::kOpSrl:
+ case ExpressionOpType::kSrl:
result = (b > 63) ? uint64_t(0) : uint64_t(a >> b);
break;
- case Expression::kOpSra:
+ case ExpressionOpType::kSra:
result = Support::sar(a, Support::min<uint64_t>(b, 63));
break;
@@ -834,13 +847,12 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui
return kErrorOk;
}
-// ============================================================================
-// [asmjit::BaseEmitter - Utilities]
-// ============================================================================
+// CodeHolder - Utilities
+// ======================
Error CodeHolder::flatten() noexcept {
uint64_t offset = 0;
- for (Section* section : _sections) {
+ for (Section* section : _sectionsByOrder) {
uint64_t realSize = section->realSize();
if (realSize) {
uint64_t alignedOffset = Support::alignUp(offset, section->alignment());
@@ -858,7 +870,7 @@ Error CodeHolder::flatten() noexcept {
// Now we know that we can assign offsets of all sections properly.
Section* prev = nullptr;
offset = 0;
- for (Section* section : _sections) {
+ for (Section* section : _sectionsByOrder) {
uint64_t realSize = section->realSize();
if (realSize)
offset = Support::alignUp(offset, section->alignment());
@@ -879,7 +891,7 @@ size_t CodeHolder::codeSize() const noexcept {
Support::FastUInt8 of = 0;
uint64_t offset = 0;
- for (Section* section : _sections) {
+ for (Section* section : _sectionsByOrder) {
uint64_t realSize = section->realSize();
if (realSize) {
@@ -916,7 +928,7 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
// Relocate all recorded locations.
for (const RelocEntry* re : _relocations) {
// Possibly deleted or optimized-out entry.
- if (re->relocType() == RelocEntry::kTypeNone)
+ if (re->relocType() == RelocType::kNone)
continue;
Section* sourceSection = sectionById(re->sourceSectionId());
@@ -930,26 +942,25 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
uint64_t sourceOffset = re->sourceOffset();
// Make sure that the `RelocEntry` doesn't go out of bounds.
- size_t regionSize = re->leadingSize() + re->valueSize() + re->trailingSize();
+ size_t regionSize = re->format().regionSize();
if (ASMJIT_UNLIKELY(re->sourceOffset() >= sourceSection->bufferSize() ||
sourceSection->bufferSize() - size_t(re->sourceOffset()) < regionSize))
return DebugUtils::errored(kErrorInvalidRelocEntry);
uint8_t* buffer = sourceSection->data();
- size_t valueOffset = size_t(re->sourceOffset()) + re->leadingSize();
switch (re->relocType()) {
- case RelocEntry::kTypeExpression: {
+ case RelocType::kExpression: {
Expression* expression = (Expression*)(uintptr_t(value));
ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(this, expression, &value));
break;
}
- case RelocEntry::kTypeAbsToAbs: {
+ case RelocType::kAbsToAbs: {
break;
}
- case RelocEntry::kTypeRelToAbs: {
+ case RelocType::kRelToAbs: {
// Value is currently a relative offset from the start of its section.
// We have to convert it to an absolute offset (including base address).
if (ASMJIT_UNLIKELY(!targetSection))
@@ -960,15 +971,21 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
break;
}
- case RelocEntry::kTypeAbsToRel: {
+ case RelocType::kAbsToRel: {
value -= baseAddress + sectionOffset + sourceOffset + regionSize;
- if (addressSize > 4 && !Support::isInt32(int64_t(value)))
+
+ // Sign extend as we are not interested in the high 32-bit word in a 32-bit address space.
+ if (addressSize <= 4)
+ value = uint64_t(int64_t(int32_t(value & 0xFFFFFFFFu)));
+ else if (!Support::isInt32(int64_t(value)))
return DebugUtils::errored(kErrorRelocOffsetOutOfRange);
+
break;
}
- case RelocEntry::kTypeX64AddressEntry: {
- if (re->valueSize() != 4 || re->leadingSize() < 2)
+ case RelocType::kX64AddressEntry: {
+ size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset();
+ if (re->format().valueSize() != 4 || valueOffset < 2)
return DebugUtils::errored(kErrorInvalidRelocEntry);
// First try whether a relative 32-bit displacement would work.
@@ -1022,30 +1039,15 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
return DebugUtils::errored(kErrorInvalidRelocEntry);
}
- switch (re->valueSize()) {
- case 1:
- Support::writeU8(buffer + valueOffset, uint32_t(value & 0xFFu));
- break;
-
- case 2:
- Support::writeU16uLE(buffer + valueOffset, uint32_t(value & 0xFFFFu));
- break;
-
- case 4:
- Support::writeU32uLE(buffer + valueOffset, uint32_t(value & 0xFFFFFFFFu));
- break;
-
- case 8:
- Support::writeU64uLE(buffer + valueOffset, value);
- break;
-
- default:
- return DebugUtils::errored(kErrorInvalidRelocEntry);
+ if (!CodeWriterUtils::writeOffset(buffer + re->sourceOffset(), int64_t(value), re->format())) {
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
}
}
// Fixup the virtual size of the address table if it's the last section.
- if (_sections.last() == addressTableSection) {
+ if (_sectionsByOrder.last() == addressTableSection) {
+ ASMJIT_ASSERT(addressTableSection != nullptr);
+
size_t addressTableSize = addressTableEntryCount * addressSize;
addressTableSection->_buffer._size = addressTableSize;
addressTableSection->_virtualSize = addressTableSize;
@@ -1054,7 +1056,7 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
return kErrorOk;
}
-Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions) noexcept {
+Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, CopySectionFlags copyFlags) noexcept {
if (ASMJIT_UNLIKELY(!isSectionValid(sectionId)))
return DebugUtils::errored(kErrorInvalidSection);
@@ -1066,7 +1068,7 @@ Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId,
memcpy(dst, section->data(), bufferSize);
- if (bufferSize < dstSize && (copyOptions & kCopyPadSectionBuffer)) {
+ if (bufferSize < dstSize && Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer)) {
size_t paddingSize = dstSize - bufferSize;
memset(static_cast<uint8_t*>(dst) + bufferSize, 0, paddingSize);
}
@@ -1074,9 +1076,9 @@ Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId,
return kErrorOk;
}
-Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions) noexcept {
+Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, CopySectionFlags copyFlags) noexcept {
size_t end = 0;
- for (Section* section : _sections) {
+ for (Section* section : _sectionsByOrder) {
if (section->offset() > dstSize)
return DebugUtils::errored(kErrorInvalidArgument);
@@ -1090,7 +1092,7 @@ Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOpti
size_t paddingSize = 0;
memcpy(dstTarget, section->data(), bufferSize);
- if ((copyOptions & kCopyPadSectionBuffer) && bufferSize < section->virtualSize()) {
+ if (Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer) && bufferSize < section->virtualSize()) {
paddingSize = Support::min<size_t>(dstSize - offset, size_t(section->virtualSize())) - bufferSize;
memset(dstTarget + bufferSize, 0, paddingSize);
}
@@ -1098,11 +1100,50 @@ Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOpti
end = Support::max(end, offset + bufferSize + paddingSize);
}
- if (end < dstSize && (copyOptions & kCopyPadTargetBuffer)) {
+ if (end < dstSize && Support::test(copyFlags, CopySectionFlags::kPadTargetBuffer)) {
memset(static_cast<uint8_t*>(dst) + end, 0, dstSize - end);
}
return kErrorOk;
}
+// CodeHolder - Tests
+// ==================
+
+#if defined(ASMJIT_TEST)
+UNIT(code_holder) {
+ CodeHolder code;
+
+ INFO("Verifying CodeHolder::init()");
+ Environment env;
+ env.init(Arch::kX86);
+
+ code.init(env);
+ EXPECT(code.arch() == Arch::kX86);
+
+ INFO("Verifying named labels");
+ LabelEntry* le;
+ EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, LabelType::kGlobal) == kErrorOk);
+ EXPECT(strcmp(le->name(), "NamedLabel") == 0);
+ EXPECT(code.labelIdByName("NamedLabel") == le->id());
+
+ INFO("Verifying section ordering");
+ Section* section1;
+ EXPECT(code.newSection(&section1, "high-priority", SIZE_MAX, SectionFlags::kNone, 1, -1) == kErrorOk);
+ EXPECT(code.sections()[1] == section1);
+ EXPECT(code.sectionsByOrder()[0] == section1);
+
+ Section* section0;
+ EXPECT(code.newSection(&section0, "higher-priority", SIZE_MAX, SectionFlags::kNone, 1, -2) == kErrorOk);
+ EXPECT(code.sections()[2] == section0);
+ EXPECT(code.sectionsByOrder()[0] == section0);
+ EXPECT(code.sectionsByOrder()[1] == section1);
+
+ Section* section3;
+ EXPECT(code.newSection(&section3, "low-priority", SIZE_MAX, SectionFlags::kNone, 1, 2) == kErrorOk);
+ EXPECT(code.sections()[3] == section3);
+ EXPECT(code.sectionsByOrder()[3] == section3);
+}
+#endif
+
ASMJIT_END_NAMESPACE