[ubsan][ia32][x64] Assemblers: safely access unaligned memory locations
The Memory<T>(address) helper requires the address to be aligned. Since values embedded into ia32/x64 code can in general be unaligned, we must use ReadUnalignedValue/WriteUnalignedValue to manipulate them. Bug: v8:3770 Change-Id: I12c3fc6aa09062dcc9188b6782ed4a35e1d684bd Reviewed-on: https://chromium-review.googlesource.com/c/1436223 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#59100}
This commit is contained in:
parent
258371bd44
commit
67392e9d22
@ -45,11 +45,11 @@ const char* CodeCommentsIterator::GetComment() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CodeCommentsIterator::GetCommentSize() const {
|
uint32_t CodeCommentsIterator::GetCommentSize() const {
|
||||||
return *reinterpret_cast<uint32_t*>(current_entry_ + kOffsetToCommentSize);
|
return ReadUnalignedValue<uint32_t>(current_entry_ + kOffsetToCommentSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CodeCommentsIterator::GetPCOffset() const {
|
uint32_t CodeCommentsIterator::GetPCOffset() const {
|
||||||
return *reinterpret_cast<uint32_t*>(current_entry_ + kOffsetToPCOffset);
|
return ReadUnalignedValue<uint32_t>(current_entry_ + kOffsetToPCOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeCommentsIterator::Next() {
|
void CodeCommentsIterator::Next() {
|
||||||
|
@ -2642,7 +2642,11 @@ int TranslatedValue::GetChildrenCount() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TranslatedState::GetUInt64Slot(Address fp, int slot_offset) {
|
uint64_t TranslatedState::GetUInt64Slot(Address fp, int slot_offset) {
|
||||||
|
#if V8_TARGET_ARCH_32_BIT
|
||||||
|
return ReadUnalignedValue<uint64_t>(fp + slot_offset);
|
||||||
|
#else
|
||||||
return Memory<uint64_t>(fp + slot_offset);
|
return Memory<uint64_t>(fp + slot_offset);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
|
uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
|
||||||
|
@ -91,19 +91,19 @@ int RelocInfo::target_address_size() {
|
|||||||
|
|
||||||
HeapObject RelocInfo::target_object() {
|
HeapObject RelocInfo::target_object() {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
return HeapObject::cast(Object(Memory<Address>(pc_)));
|
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
|
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
return Handle<HeapObject>::cast(Memory<Handle<Object>>(pc_));
|
return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
|
void RelocInfo::set_target_object(Heap* heap, HeapObject target,
|
||||||
WriteBarrierMode write_barrier_mode,
|
WriteBarrierMode write_barrier_mode,
|
||||||
ICacheFlushMode icache_flush_mode) {
|
ICacheFlushMode icache_flush_mode) {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
Memory<Address>(pc_) = target->ptr();
|
WriteUnalignedValue(pc_, target->ptr());
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc_, sizeof(Address));
|
Assembler::FlushICache(pc_, sizeof(Address));
|
||||||
}
|
}
|
||||||
@ -114,13 +114,13 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target,
|
|||||||
|
|
||||||
Address RelocInfo::target_external_reference() {
|
Address RelocInfo::target_external_reference() {
|
||||||
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
||||||
return Memory<Address>(pc_);
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocInfo::set_target_external_reference(
|
void RelocInfo::set_target_external_reference(
|
||||||
Address target, ICacheFlushMode icache_flush_mode) {
|
Address target, ICacheFlushMode icache_flush_mode) {
|
||||||
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
||||||
Memory<Address>(pc_) = target;
|
WriteUnalignedValue(pc_, target);
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc_, sizeof(Address));
|
Assembler::FlushICache(pc_, sizeof(Address));
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ void RelocInfo::set_target_external_reference(
|
|||||||
|
|
||||||
Address RelocInfo::target_internal_reference() {
|
Address RelocInfo::target_internal_reference() {
|
||||||
DCHECK(rmode_ == INTERNAL_REFERENCE);
|
DCHECK(rmode_ == INTERNAL_REFERENCE);
|
||||||
return Memory<Address>(pc_);
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ Address RelocInfo::target_internal_reference_address() {
|
|||||||
|
|
||||||
Address RelocInfo::target_runtime_entry(Assembler* origin) {
|
Address RelocInfo::target_runtime_entry(Assembler* origin) {
|
||||||
DCHECK(IsRuntimeEntry(rmode_));
|
DCHECK(IsRuntimeEntry(rmode_));
|
||||||
return static_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocInfo::set_target_runtime_entry(Address target,
|
void RelocInfo::set_target_runtime_entry(Address target,
|
||||||
@ -159,7 +159,7 @@ Address RelocInfo::target_off_heap_target() {
|
|||||||
void RelocInfo::WipeOut() {
|
void RelocInfo::WipeOut() {
|
||||||
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
|
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
|
||||||
IsInternalReference(rmode_)) {
|
IsInternalReference(rmode_)) {
|
||||||
Memory<Address>(pc_) = kNullAddress;
|
WriteUnalignedValue(pc_, kNullAddress);
|
||||||
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
|
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
|
||||||
IsOffHeapTarget(rmode_)) {
|
IsOffHeapTarget(rmode_)) {
|
||||||
// Effectively write zero into the relocation.
|
// Effectively write zero into the relocation.
|
||||||
@ -190,13 +190,13 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::emit(uint32_t x) {
|
void Assembler::emit(uint32_t x) {
|
||||||
*reinterpret_cast<uint32_t*>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
pc_ += sizeof(uint32_t);
|
pc_ += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::emit_q(uint64_t x) {
|
void Assembler::emit_q(uint64_t x) {
|
||||||
*reinterpret_cast<uint64_t*>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
pc_ += sizeof(uint64_t);
|
pc_ += sizeof(uint64_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,19 +251,19 @@ void Assembler::emit_b(Immediate x) {
|
|||||||
void Assembler::emit_w(const Immediate& x) {
|
void Assembler::emit_w(const Immediate& x) {
|
||||||
DCHECK(RelocInfo::IsNone(x.rmode_));
|
DCHECK(RelocInfo::IsNone(x.rmode_));
|
||||||
uint16_t value = static_cast<uint16_t>(x.immediate());
|
uint16_t value = static_cast<uint16_t>(x.immediate());
|
||||||
reinterpret_cast<uint16_t*>(pc_)[0] = value;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), value);
|
||||||
pc_ += sizeof(uint16_t);
|
pc_ += sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Address Assembler::target_address_at(Address pc, Address constant_pool) {
|
Address Assembler::target_address_at(Address pc, Address constant_pool) {
|
||||||
return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
|
return pc + sizeof(int32_t) + ReadUnalignedValue<int32_t>(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
||||||
Address target,
|
Address target,
|
||||||
ICacheFlushMode icache_flush_mode) {
|
ICacheFlushMode icache_flush_mode) {
|
||||||
*reinterpret_cast<int32_t*>(pc) = target - (pc + sizeof(int32_t));
|
WriteUnalignedValue(pc, target - (pc + sizeof(int32_t)));
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc, sizeof(int32_t));
|
Assembler::FlushICache(pc, sizeof(int32_t));
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ void Assembler::emit_near_disp(Label* L) {
|
|||||||
|
|
||||||
void Assembler::deserialization_set_target_internal_reference_at(
|
void Assembler::deserialization_set_target_internal_reference_at(
|
||||||
Address pc, Address target, RelocInfo::Mode mode) {
|
Address pc, Address target, RelocInfo::Mode mode) {
|
||||||
Memory<Address>(pc) = target;
|
WriteUnalignedValue(pc, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ bool RelocInfo::IsInConstantPool() {
|
|||||||
|
|
||||||
uint32_t RelocInfo::wasm_call_tag() const {
|
uint32_t RelocInfo::wasm_call_tag() const {
|
||||||
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
|
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
|
||||||
return Memory<uint32_t>(pc_);
|
return ReadUnalignedValue<uint32_t>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -297,7 +297,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
|
||||||
Memory<Handle<Object>>(pc) = object;
|
WriteUnalignedValue(pc, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3199,8 +3199,8 @@ void Assembler::GrowBuffer() {
|
|||||||
|
|
||||||
// Relocate internal references.
|
// Relocate internal references.
|
||||||
for (auto pos : internal_reference_positions_) {
|
for (auto pos : internal_reference_positions_) {
|
||||||
int32_t* p = reinterpret_cast<int32_t*>(buffer_start_ + pos);
|
Address p = reinterpret_cast<Address>(buffer_start_ + pos);
|
||||||
*p += pc_delta;
|
WriteUnalignedValue(p, ReadUnalignedValue<int>(p) + pc_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relocate pc-relative references.
|
// Relocate pc-relative references.
|
||||||
@ -3277,7 +3277,7 @@ void Assembler::emit_operand(int code, Operand adr) {
|
|||||||
pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
|
pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
|
||||||
RecordRelocInfo(adr.rmode_);
|
RecordRelocInfo(adr.rmode_);
|
||||||
if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
|
if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
|
||||||
emit_label(*reinterpret_cast<Label**>(pc_));
|
emit_label(ReadUnalignedValue<Label*>(reinterpret_cast<Address>(pc_)));
|
||||||
} else {
|
} else {
|
||||||
pc_ += sizeof(int32_t);
|
pc_ += sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
@ -275,8 +275,8 @@ class V8_EXPORT_PRIVATE Operand {
|
|||||||
inline void set_disp8(int8_t disp);
|
inline void set_disp8(int8_t disp);
|
||||||
inline void set_dispr(int32_t disp, RelocInfo::Mode rmode) {
|
inline void set_dispr(int32_t disp, RelocInfo::Mode rmode) {
|
||||||
DCHECK(len_ == 1 || len_ == 2);
|
DCHECK(len_ == 1 || len_ == 2);
|
||||||
int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
|
Address p = reinterpret_cast<Address>(&buf_[len_]);
|
||||||
*p = disp;
|
WriteUnalignedValue(p, disp);
|
||||||
len_ += sizeof(int32_t);
|
len_ += sizeof(int32_t);
|
||||||
rmode_ = rmode;
|
rmode_ = rmode;
|
||||||
}
|
}
|
||||||
@ -1650,14 +1650,16 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
|||||||
void emit_sse_operand(Register dst, XMMRegister src);
|
void emit_sse_operand(Register dst, XMMRegister src);
|
||||||
void emit_sse_operand(XMMRegister dst, Register src);
|
void emit_sse_operand(XMMRegister dst, Register src);
|
||||||
|
|
||||||
byte* addr_at(int pos) { return buffer_start_ + pos; }
|
Address addr_at(int pos) {
|
||||||
|
return reinterpret_cast<Address>(buffer_start_ + pos);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t long_at(int pos) {
|
uint32_t long_at(int pos) {
|
||||||
return *reinterpret_cast<uint32_t*>(addr_at(pos));
|
return ReadUnalignedValue<uint32_t>(addr_at(pos));
|
||||||
}
|
}
|
||||||
void long_at_put(int pos, uint32_t x) {
|
void long_at_put(int pos, uint32_t x) {
|
||||||
*reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
|
WriteUnalignedValue(addr_at(pos), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// code emission
|
// code emission
|
||||||
|
@ -16,6 +16,8 @@ namespace internal {
|
|||||||
// proposal (http://wg21.link/p0593r2) to make it defined behaviour though.
|
// proposal (http://wg21.link/p0593r2) to make it defined behaviour though.
|
||||||
template <class T>
|
template <class T>
|
||||||
T& Memory(Address addr) {
|
T& Memory(Address addr) {
|
||||||
|
// {addr} must be aligned.
|
||||||
|
DCHECK_EQ(0, addr & (alignof(T) - 1));
|
||||||
return *reinterpret_cast<T*>(addr);
|
return *reinterpret_cast<T*>(addr);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -26,23 +28,15 @@ T& Memory(byte* addr) {
|
|||||||
template <typename V>
|
template <typename V>
|
||||||
static inline V ReadUnalignedValue(Address p) {
|
static inline V ReadUnalignedValue(Address p) {
|
||||||
ASSERT_TRIVIALLY_COPYABLE(V);
|
ASSERT_TRIVIALLY_COPYABLE(V);
|
||||||
#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM)
|
|
||||||
return *reinterpret_cast<const V*>(p);
|
|
||||||
#else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
|
|
||||||
V r;
|
V r;
|
||||||
memmove(&r, reinterpret_cast<void*>(p), sizeof(V));
|
memcpy(&r, reinterpret_cast<void*>(p), sizeof(V));
|
||||||
return r;
|
return r;
|
||||||
#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
static inline void WriteUnalignedValue(Address p, V value) {
|
static inline void WriteUnalignedValue(Address p, V value) {
|
||||||
ASSERT_TRIVIALLY_COPYABLE(V);
|
ASSERT_TRIVIALLY_COPYABLE(V);
|
||||||
#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM)
|
memcpy(reinterpret_cast<void*>(p), &value, sizeof(V));
|
||||||
*(reinterpret_cast<V*>(p)) = value;
|
|
||||||
#else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
|
|
||||||
memmove(reinterpret_cast<void*>(p), &value, sizeof(V));
|
|
||||||
#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double ReadFloatValue(Address p) {
|
static inline double ReadFloatValue(Address p) {
|
||||||
|
@ -135,12 +135,12 @@ void WriteVersion(Writer* writer) {
|
|||||||
void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
|
void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
|
||||||
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
|
||||||
DCHECK(rinfo->HasTargetAddressAddress());
|
DCHECK(rinfo->HasTargetAddressAddress());
|
||||||
*(reinterpret_cast<uint32_t*>(rinfo->target_address_address())) = tag;
|
WriteUnalignedValue(rinfo->target_address_address(), tag);
|
||||||
#elif V8_TARGET_ARCH_ARM64
|
#elif V8_TARGET_ARCH_ARM64
|
||||||
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
|
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
|
||||||
if (instr->IsLdrLiteralX()) {
|
if (instr->IsLdrLiteralX()) {
|
||||||
Memory<Address>(rinfo->constant_pool_entry_address()) =
|
WriteUnalignedValue(rinfo->constant_pool_entry_address(),
|
||||||
static_cast<Address>(tag);
|
static_cast<Address>(tag));
|
||||||
} else {
|
} else {
|
||||||
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
|
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
|
||||||
instr->SetBranchImmTarget(
|
instr->SetBranchImmTarget(
|
||||||
@ -160,12 +160,11 @@ void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
|
|||||||
|
|
||||||
uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
|
uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
|
||||||
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
|
||||||
return *(reinterpret_cast<uint32_t*>(rinfo->target_address_address()));
|
return ReadUnalignedValue<uint32_t>(rinfo->target_address_address());
|
||||||
#elif V8_TARGET_ARCH_ARM64
|
#elif V8_TARGET_ARCH_ARM64
|
||||||
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
|
Instruction* instr = reinterpret_cast<Instruction*>(rinfo->pc());
|
||||||
if (instr->IsLdrLiteralX()) {
|
if (instr->IsLdrLiteralX()) {
|
||||||
return static_cast<uint32_t>(
|
return ReadUnalignedValue<uint32_t>(rinfo->constant_pool_entry_address());
|
||||||
Memory<Address>(rinfo->constant_pool_entry_address()));
|
|
||||||
} else {
|
} else {
|
||||||
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
|
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
|
||||||
return static_cast<uint32_t>(instr->ImmPCOffset() / kInstrSize);
|
return static_cast<uint32_t>(instr->ImmPCOffset() / kInstrSize);
|
||||||
|
@ -24,12 +24,12 @@ bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(SSE4_1); }
|
|||||||
|
|
||||||
|
|
||||||
void Assembler::emitl(uint32_t x) {
|
void Assembler::emitl(uint32_t x) {
|
||||||
Memory<uint32_t>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
pc_ += sizeof(uint32_t);
|
pc_ += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::emitp(Address x, RelocInfo::Mode rmode) {
|
void Assembler::emitp(Address x, RelocInfo::Mode rmode) {
|
||||||
Memory<uintptr_t>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
if (!RelocInfo::IsNone(rmode)) {
|
if (!RelocInfo::IsNone(rmode)) {
|
||||||
RecordRelocInfo(rmode, x);
|
RecordRelocInfo(rmode, x);
|
||||||
}
|
}
|
||||||
@ -38,13 +38,13 @@ void Assembler::emitp(Address x, RelocInfo::Mode rmode) {
|
|||||||
|
|
||||||
|
|
||||||
void Assembler::emitq(uint64_t x) {
|
void Assembler::emitq(uint64_t x) {
|
||||||
Memory<uint64_t>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
pc_ += sizeof(uint64_t);
|
pc_ += sizeof(uint64_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::emitw(uint16_t x) {
|
void Assembler::emitw(uint16_t x) {
|
||||||
Memory<uint16_t>(pc_) = x;
|
WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
|
||||||
pc_ += sizeof(uint16_t);
|
pc_ += sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,13 +233,13 @@ void Assembler::emit_vex_prefix(Register reg, Register vreg, Operand rm,
|
|||||||
|
|
||||||
|
|
||||||
Address Assembler::target_address_at(Address pc, Address constant_pool) {
|
Address Assembler::target_address_at(Address pc, Address constant_pool) {
|
||||||
return Memory<int32_t>(pc) + pc + 4;
|
return ReadUnalignedValue<int32_t>(pc) + pc + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
||||||
Address target,
|
Address target,
|
||||||
ICacheFlushMode icache_flush_mode) {
|
ICacheFlushMode icache_flush_mode) {
|
||||||
Memory<int32_t>(pc) = static_cast<int32_t>(target - pc - 4);
|
WriteUnalignedValue(pc, static_cast<int32_t>(target - pc - 4));
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc, sizeof(int32_t));
|
Assembler::FlushICache(pc, sizeof(int32_t));
|
||||||
}
|
}
|
||||||
@ -247,7 +247,7 @@ void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
|||||||
|
|
||||||
void Assembler::deserialization_set_target_internal_reference_at(
|
void Assembler::deserialization_set_target_internal_reference_at(
|
||||||
Address pc, Address target, RelocInfo::Mode mode) {
|
Address pc, Address target, RelocInfo::Mode mode) {
|
||||||
Memory<Address>(pc) = target;
|
WriteUnalignedValue(pc, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -268,11 +268,11 @@ int Assembler::deserialization_special_target_size(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
|
Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
|
||||||
return GetCodeTarget(Memory<int32_t>(pc));
|
return GetCodeTarget(ReadUnalignedValue<int32_t>(pc));
|
||||||
}
|
}
|
||||||
|
|
||||||
Address Assembler::runtime_entry_at(Address pc) {
|
Address Assembler::runtime_entry_at(Address pc) {
|
||||||
return Memory<int32_t>(pc) + options().code_range_start;
|
return ReadUnalignedValue<int32_t>(pc) + options().code_range_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -281,10 +281,11 @@ Address Assembler::runtime_entry_at(Address pc) {
|
|||||||
// The modes possibly affected by apply must be in kApplyMask.
|
// The modes possibly affected by apply must be in kApplyMask.
|
||||||
void RelocInfo::apply(intptr_t delta) {
|
void RelocInfo::apply(intptr_t delta) {
|
||||||
if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
|
if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
|
||||||
Memory<int32_t>(pc_) -= static_cast<int32_t>(delta);
|
WriteUnalignedValue(
|
||||||
|
pc_, ReadUnalignedValue<int32_t>(pc_) - static_cast<int32_t>(delta));
|
||||||
} else if (IsInternalReference(rmode_)) {
|
} else if (IsInternalReference(rmode_)) {
|
||||||
// absolute code pointer inside code object moves with the code object.
|
// Absolute code pointer inside code object moves with the code object.
|
||||||
Memory<Address>(pc_) += delta;
|
WriteUnalignedValue(pc_, ReadUnalignedValue<Address>(pc_) + delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,13 +318,13 @@ int RelocInfo::target_address_size() {
|
|||||||
|
|
||||||
HeapObject RelocInfo::target_object() {
|
HeapObject RelocInfo::target_object() {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
return HeapObject::cast(Object(Memory<Address>(pc_)));
|
return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
|
Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
if (rmode_ == EMBEDDED_OBJECT) {
|
if (rmode_ == EMBEDDED_OBJECT) {
|
||||||
return Handle<HeapObject>::cast(Memory<Handle<Object>>(pc_));
|
return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
|
||||||
} else {
|
} else {
|
||||||
return origin->code_target_object_handle_at(pc_);
|
return origin->code_target_object_handle_at(pc_);
|
||||||
}
|
}
|
||||||
@ -331,13 +332,13 @@ Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
|
|||||||
|
|
||||||
Address RelocInfo::target_external_reference() {
|
Address RelocInfo::target_external_reference() {
|
||||||
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
||||||
return Memory<Address>(pc_);
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocInfo::set_target_external_reference(
|
void RelocInfo::set_target_external_reference(
|
||||||
Address target, ICacheFlushMode icache_flush_mode) {
|
Address target, ICacheFlushMode icache_flush_mode) {
|
||||||
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
|
||||||
Memory<Address>(pc_) = target;
|
WriteUnalignedValue(pc_, target);
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc_, sizeof(Address));
|
Assembler::FlushICache(pc_, sizeof(Address));
|
||||||
}
|
}
|
||||||
@ -345,7 +346,7 @@ void RelocInfo::set_target_external_reference(
|
|||||||
|
|
||||||
Address RelocInfo::target_internal_reference() {
|
Address RelocInfo::target_internal_reference() {
|
||||||
DCHECK(rmode_ == INTERNAL_REFERENCE);
|
DCHECK(rmode_ == INTERNAL_REFERENCE);
|
||||||
return Memory<Address>(pc_);
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,7 +359,7 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target,
|
|||||||
WriteBarrierMode write_barrier_mode,
|
WriteBarrierMode write_barrier_mode,
|
||||||
ICacheFlushMode icache_flush_mode) {
|
ICacheFlushMode icache_flush_mode) {
|
||||||
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||||
Memory<Address>(pc_) = target->ptr();
|
WriteUnalignedValue(pc_, target->ptr());
|
||||||
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
|
||||||
Assembler::FlushICache(pc_, sizeof(Address));
|
Assembler::FlushICache(pc_, sizeof(Address));
|
||||||
}
|
}
|
||||||
@ -383,13 +384,13 @@ void RelocInfo::set_target_runtime_entry(Address target,
|
|||||||
|
|
||||||
Address RelocInfo::target_off_heap_target() {
|
Address RelocInfo::target_off_heap_target() {
|
||||||
DCHECK(IsOffHeapTarget(rmode_));
|
DCHECK(IsOffHeapTarget(rmode_));
|
||||||
return Memory<Address>(pc_);
|
return ReadUnalignedValue<Address>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocInfo::WipeOut() {
|
void RelocInfo::WipeOut() {
|
||||||
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
|
if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
|
||||||
IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
|
IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
|
||||||
Memory<Address>(pc_) = kNullAddress;
|
WriteUnalignedValue(pc_, kNullAddress);
|
||||||
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
|
} else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
|
||||||
// Effectively write zero into the relocation.
|
// Effectively write zero into the relocation.
|
||||||
Assembler::set_target_address_at(pc_, constant_pool_,
|
Assembler::set_target_address_at(pc_, constant_pool_,
|
||||||
|
@ -126,7 +126,7 @@ void CpuFeatures::PrintFeatures() {
|
|||||||
|
|
||||||
uint32_t RelocInfo::wasm_call_tag() const {
|
uint32_t RelocInfo::wasm_call_tag() const {
|
||||||
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
|
DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL);
|
||||||
return Memory<uint32_t>(pc_);
|
return ReadUnalignedValue<uint32_t>(pc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -200,7 +200,8 @@ class OperandBuilder {
|
|||||||
int32_t disp_value = 0;
|
int32_t disp_value = 0;
|
||||||
if (mode == 0x80 || is_baseless) {
|
if (mode == 0x80 || is_baseless) {
|
||||||
// Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
|
// Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
|
||||||
disp_value = *bit_cast<const int32_t*>(&operand.data().buf[disp_offset]);
|
disp_value = ReadUnalignedValue<int32_t>(
|
||||||
|
reinterpret_cast<Address>(&operand.data().buf[disp_offset]));
|
||||||
} else if (mode == 0x40) {
|
} else if (mode == 0x40) {
|
||||||
// Mode 1: Byte displacement.
|
// Mode 1: Byte displacement.
|
||||||
disp_value = static_cast<signed char>(operand.data().buf[disp_offset]);
|
disp_value = static_cast<signed char>(operand.data().buf[disp_offset]);
|
||||||
@ -215,8 +216,8 @@ class OperandBuilder {
|
|||||||
// Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
|
// Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
|
||||||
data_.buf[0] = (modrm & 0x3F) | (is_baseless ? 0x00 : 0x80);
|
data_.buf[0] = (modrm & 0x3F) | (is_baseless ? 0x00 : 0x80);
|
||||||
data_.len = disp_offset + 4;
|
data_.len = disp_offset + 4;
|
||||||
Memory<int32_t>(reinterpret_cast<Address>(&data_.buf[disp_offset])) =
|
WriteUnalignedValue(reinterpret_cast<Address>(&data_.buf[disp_offset]),
|
||||||
disp_value;
|
disp_value);
|
||||||
} else if (disp_value != 0 || (base_reg == 0x05)) {
|
} else if (disp_value != 0 || (base_reg == 0x05)) {
|
||||||
// Need 8 bits of displacement.
|
// Need 8 bits of displacement.
|
||||||
data_.buf[0] = (modrm & 0x3F) | 0x40; // Mode 1.
|
data_.buf[0] = (modrm & 0x3F) | 0x40; // Mode 1.
|
||||||
@ -260,15 +261,15 @@ class OperandBuilder {
|
|||||||
|
|
||||||
void set_disp32(int disp) {
|
void set_disp32(int disp) {
|
||||||
DCHECK(data_.len == 1 || data_.len == 2);
|
DCHECK(data_.len == 1 || data_.len == 2);
|
||||||
int32_t* p = reinterpret_cast<int32_t*>(&data_.buf[data_.len]);
|
Address p = reinterpret_cast<Address>(&data_.buf[data_.len]);
|
||||||
*p = disp;
|
WriteUnalignedValue(p, disp);
|
||||||
data_.len += sizeof(int32_t);
|
data_.len += sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_disp64(int64_t disp) {
|
void set_disp64(int64_t disp) {
|
||||||
DCHECK_EQ(1, data_.len);
|
DCHECK_EQ(1, data_.len);
|
||||||
int64_t* p = reinterpret_cast<int64_t*>(&data_.buf[data_.len]);
|
Address p = reinterpret_cast<Address>(&data_.buf[data_.len]);
|
||||||
*p = disp;
|
WriteUnalignedValue(p, disp);
|
||||||
data_.len += sizeof(disp);
|
data_.len += sizeof(disp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,14 +329,14 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
|||||||
case HeapObjectRequest::kHeapNumber: {
|
case HeapObjectRequest::kHeapNumber: {
|
||||||
Handle<HeapNumber> object =
|
Handle<HeapNumber> object =
|
||||||
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
|
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
|
||||||
Memory<Handle<Object>>(pc) = object;
|
WriteUnalignedValue(pc, object);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HeapObjectRequest::kStringConstant: {
|
case HeapObjectRequest::kStringConstant: {
|
||||||
const StringConstantBase* str = request.string();
|
const StringConstantBase* str = request.string();
|
||||||
CHECK_NOT_NULL(str);
|
CHECK_NOT_NULL(str);
|
||||||
Handle<String> allocated = str->AllocateStringConstant(isolate);
|
Handle<String> allocated = str->AllocateStringConstant(isolate);
|
||||||
Memory<Handle<Object>>(pc) = allocated;
|
WriteUnalignedValue(pc, allocated);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,11 +373,9 @@ bool ConstPool::TryRecordEntry(intptr_t data, RelocInfo::Mode mode) {
|
|||||||
return AddSharedEntry(raw_data, offset);
|
return AddSharedEntry(raw_data, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConstPool::IsMoveRipRelative(byte* instr) {
|
bool ConstPool::IsMoveRipRelative(Address instr) {
|
||||||
if ((*reinterpret_cast<uint32_t*>(instr) & kMoveRipRelativeMask) ==
|
return (ReadUnalignedValue<uint32_t>(instr) & kMoveRipRelativeMask) ==
|
||||||
kMoveRipRelativeInstr)
|
kMoveRipRelativeInstr;
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstPool::Clear() { entries_.clear(); }
|
void ConstPool::Clear() { entries_.clear(); }
|
||||||
@ -397,13 +396,13 @@ void ConstPool::PatchEntries() {
|
|||||||
DCHECK_LT(constant_entry_offset, it->second);
|
DCHECK_LT(constant_entry_offset, it->second);
|
||||||
int32_t disp32 =
|
int32_t disp32 =
|
||||||
constant_entry_offset - (it->second + kRipRelativeDispSize);
|
constant_entry_offset - (it->second + kRipRelativeDispSize);
|
||||||
byte* disp_addr = assm_->addr_at(it->second);
|
Address disp_addr = assm_->addr_at(it->second);
|
||||||
|
|
||||||
// Check if the instruction is actually a rip-relative move.
|
// Check if the instruction is actually a rip-relative move.
|
||||||
DCHECK(IsMoveRipRelative(disp_addr - kMoveRipRelativeDispOffset));
|
DCHECK(IsMoveRipRelative(disp_addr - kMoveRipRelativeDispOffset));
|
||||||
// The displacement of the rip-relative move should be 0 before patching.
|
// The displacement of the rip-relative move should be 0 before patching.
|
||||||
DCHECK(*reinterpret_cast<uint32_t*>(disp_addr) == 0);
|
DCHECK(ReadUnalignedValue<uint32_t>(disp_addr) == 0);
|
||||||
*reinterpret_cast<int32_t*>(disp_addr) = disp32;
|
WriteUnalignedValue(disp_addr, disp32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Clear();
|
Clear();
|
||||||
@ -518,7 +517,7 @@ void Assembler::bind_to(Label* L, int pos) {
|
|||||||
if (current >= 4 && long_at(current - 4) == 0) {
|
if (current >= 4 && long_at(current - 4) == 0) {
|
||||||
// Absolute address.
|
// Absolute address.
|
||||||
intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
|
intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
|
||||||
*reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
|
WriteUnalignedValue(addr_at(current - 4), imm64);
|
||||||
internal_reference_positions_.push_back(current - 4);
|
internal_reference_positions_.push_back(current - 4);
|
||||||
} else {
|
} else {
|
||||||
// Relative address, relative to point after address.
|
// Relative address, relative to point after address.
|
||||||
@ -532,7 +531,7 @@ void Assembler::bind_to(Label* L, int pos) {
|
|||||||
if (current >= 4 && long_at(current - 4) == 0) {
|
if (current >= 4 && long_at(current - 4) == 0) {
|
||||||
// Absolute address.
|
// Absolute address.
|
||||||
intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
|
intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
|
||||||
*reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
|
WriteUnalignedValue(addr_at(current - 4), imm64);
|
||||||
internal_reference_positions_.push_back(current - 4);
|
internal_reference_positions_.push_back(current - 4);
|
||||||
} else {
|
} else {
|
||||||
// Relative address, relative to point after address.
|
// Relative address, relative to point after address.
|
||||||
@ -629,8 +628,8 @@ void Assembler::GrowBuffer() {
|
|||||||
|
|
||||||
// Relocate internal references.
|
// Relocate internal references.
|
||||||
for (auto pos : internal_reference_positions_) {
|
for (auto pos : internal_reference_positions_) {
|
||||||
intptr_t* p = reinterpret_cast<intptr_t*>(buffer_start_ + pos);
|
Address p = reinterpret_cast<Address>(buffer_start_ + pos);
|
||||||
*p += pc_delta;
|
WriteUnalignedValue(p, ReadUnalignedValue<intptr_t>(p) + pc_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK(!buffer_overflow());
|
DCHECK(!buffer_overflow());
|
||||||
@ -648,7 +647,8 @@ void Assembler::emit_operand(int code, Operand adr) {
|
|||||||
// Recognize RIP relative addressing.
|
// Recognize RIP relative addressing.
|
||||||
if (adr.data().buf[0] == 5) {
|
if (adr.data().buf[0] == 5) {
|
||||||
DCHECK_EQ(9u, length);
|
DCHECK_EQ(9u, length);
|
||||||
Label* label = *bit_cast<Label* const*>(&adr.data().buf[1]);
|
Label* label = ReadUnalignedValue<Label*>(
|
||||||
|
reinterpret_cast<Address>(&adr.data().buf[1]));
|
||||||
if (label->is_bound()) {
|
if (label->is_bound()) {
|
||||||
int offset =
|
int offset =
|
||||||
label->pos() - pc_offset() - sizeof(int32_t) + adr.data().addend;
|
label->pos() - pc_offset() - sizeof(int32_t) + adr.data().addend;
|
||||||
|
@ -268,7 +268,7 @@ class ConstPool {
|
|||||||
bool AddSharedEntry(uint64_t data, int offset);
|
bool AddSharedEntry(uint64_t data, int offset);
|
||||||
|
|
||||||
// Check if the instruction is a rip-relative move.
|
// Check if the instruction is a rip-relative move.
|
||||||
bool IsMoveRipRelative(byte* instr);
|
bool IsMoveRipRelative(Address instr);
|
||||||
|
|
||||||
Assembler* assm_;
|
Assembler* assm_;
|
||||||
|
|
||||||
@ -1806,12 +1806,14 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
|||||||
void call(Operand operand);
|
void call(Operand operand);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
byte* addr_at(int pos) { return buffer_start_ + pos; }
|
Address addr_at(int pos) {
|
||||||
|
return reinterpret_cast<Address>(buffer_start_ + pos);
|
||||||
|
}
|
||||||
uint32_t long_at(int pos) {
|
uint32_t long_at(int pos) {
|
||||||
return *reinterpret_cast<uint32_t*>(addr_at(pos));
|
return ReadUnalignedValue<uint32_t>(addr_at(pos));
|
||||||
}
|
}
|
||||||
void long_at_put(int pos, uint32_t x) {
|
void long_at_put(int pos, uint32_t x) {
|
||||||
*reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
|
WriteUnalignedValue(addr_at(pos), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// code emission
|
// code emission
|
||||||
|
Loading…
Reference in New Issue
Block a user