From 54c005754aedbedec44c1c98f135bfbb0de78068 Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Tue, 13 Jul 2021 17:18:39 +0200 Subject: [PATCH] UserpaceEmulator: Handle possibly unaligned IO We also should add some UB warnings for that in the future --- .../DevTools/UserspaceEmulator/MmapRegion.cpp | 56 +++++++++++------- .../UserspaceEmulator/SimpleRegion.cpp | 58 +++++++++++++------ Userland/DevTools/UserspaceEmulator/SoftCPU.h | 12 +++- 3 files changed, 85 insertions(+), 41 deletions(-) diff --git a/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp b/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp index a7056e47f0..eff2431999 100644 --- a/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp +++ b/Userland/DevTools/UserspaceEmulator/MmapRegion.cpp @@ -75,7 +75,7 @@ ValueWithShadow MmapRegion::read8(FlatPtr offset) } VERIFY(offset < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + return { m_data[offset], m_shadow_data[offset] }; } ValueWithShadow MmapRegion::read16(u32 offset) @@ -92,7 +92,11 @@ ValueWithShadow MmapRegion::read16(u32 offset) } VERIFY(offset + 1 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u16 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow MmapRegion::read32(u32 offset) @@ -109,7 +113,11 @@ ValueWithShadow MmapRegion::read32(u32 offset) } VERIFY(offset + 3 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u32 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow MmapRegion::read64(u32 offset) @@ -126,7 +134,11 @@ ValueWithShadow MmapRegion::read64(u32 offset) } VERIFY(offset + 7 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u64 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow MmapRegion::read128(u32 offset) @@ -143,7 +155,10 @@ ValueWithShadow MmapRegion::read128(u32 offset) } VERIFY(offset + 15 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u128 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + return { value, shadow }; } ValueWithShadow MmapRegion::read256(u32 offset) @@ -160,7 +175,10 @@ ValueWithShadow MmapRegion::read256(u32 offset) } VERIFY(offset + 31 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u256 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + return { value, shadow }; } void MmapRegion::write8(u32 offset, ValueWithShadow value) @@ -177,8 +195,8 @@ void MmapRegion::write8(u32 offset, ValueWithShadow value) } VERIFY(offset < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + m_data[offset] = value.value(); + m_shadow_data[offset] = value.shadow(); } void MmapRegion::write16(u32 offset, ValueWithShadow value) @@ -195,8 +213,8 @@ void MmapRegion::write16(u32 offset, ValueWithShadow value) } VERIFY(offset + 1 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void MmapRegion::write32(u32 offset, ValueWithShadow value) @@ -214,8 +232,8 @@ void MmapRegion::write32(u32 offset, ValueWithShadow value) VERIFY(offset + 3 < size()); VERIFY(m_data != m_shadow_data); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void MmapRegion::write64(u32 offset, ValueWithShadow value) @@ -233,8 +251,8 @@ void MmapRegion::write64(u32 offset, ValueWithShadow value) VERIFY(offset + 7 < size()); VERIFY(m_data != m_shadow_data); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void MmapRegion::write128(u32 offset, ValueWithShadow value) @@ -249,11 +267,10 @@ void MmapRegion::write128(u32 offset, ValueWithShadow value) if (auto* tracer = emulator().malloc_tracer()) tracer->audit_write(*this, base() + offset, 16); } - VERIFY(offset + 15 < size()); VERIFY(m_data != m_shadow_data); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void MmapRegion::write256(u32 offset, ValueWithShadow value) @@ -268,11 +285,10 @@ void MmapRegion::write256(u32 offset, ValueWithShadow value) if (auto* tracer = emulator().malloc_tracer()) tracer->audit_write(*this, base() + offset, 32); } - VERIFY(offset + 31 < size()); VERIFY(m_data != m_shadow_data); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } NonnullOwnPtr MmapRegion::split_at(VirtualAddress offset) diff --git a/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp b/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp index 99f035c8c6..e353e94d1f 100644 --- a/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp +++ b/Userland/DevTools/UserspaceEmulator/SimpleRegion.cpp @@ -5,6 +5,7 @@ */ #include "SimpleRegion.h" +#include #include namespace UserspaceEmulator { @@ -26,77 +27,98 @@ SimpleRegion::~SimpleRegion() ValueWithShadow SimpleRegion::read8(FlatPtr offset) { VERIFY(offset < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + return { m_data[offset], m_shadow_data[offset] }; } ValueWithShadow SimpleRegion::read16(u32 offset) { VERIFY(offset + 1 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + + u16 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow SimpleRegion::read32(u32 offset) { VERIFY(offset + 3 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + + u32 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow SimpleRegion::read64(u32 offset) { VERIFY(offset + 7 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + + u64 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + + return { value, shadow }; } ValueWithShadow SimpleRegion::read128(u32 offset) { VERIFY(offset + 15 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u128 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + return { value, shadow }; } ValueWithShadow SimpleRegion::read256(u32 offset) { VERIFY(offset + 31 < size()); - return { *reinterpret_cast(m_data + offset), *reinterpret_cast(m_shadow_data + offset) }; + u256 value, shadow; + ByteReader::load(m_data + offset, value); + ByteReader::load(m_shadow_data + offset, shadow); + return { value, shadow }; } void SimpleRegion::write8(u32 offset, ValueWithShadow value) { VERIFY(offset < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + m_data[offset] = value.value(); + m_shadow_data[offset] = value.shadow(); } void SimpleRegion::write16(u32 offset, ValueWithShadow value) { VERIFY(offset + 1 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void SimpleRegion::write32(u32 offset, ValueWithShadow value) { VERIFY(offset + 3 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void SimpleRegion::write64(u32 offset, ValueWithShadow value) { VERIFY(offset + 7 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void SimpleRegion::write128(u32 offset, ValueWithShadow value) { VERIFY(offset + 15 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } void SimpleRegion::write256(u32 offset, ValueWithShadow value) { VERIFY(offset + 31 < size()); - *reinterpret_cast(m_data + offset) = value.value(); - *reinterpret_cast(m_shadow_data + offset) = value.shadow(); + ByteReader::store(m_data + offset, value.value()); + ByteReader::store(m_shadow_data + offset, value.shadow()); } u8* SimpleRegion::cacheable_ptr(u32 offset) diff --git a/Userland/DevTools/UserspaceEmulator/SoftCPU.h b/Userland/DevTools/UserspaceEmulator/SoftCPU.h index eb8b55d039..c9713cdb3e 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftCPU.h +++ b/Userland/DevTools/UserspaceEmulator/SoftCPU.h @@ -8,6 +8,7 @@ #include "Region.h" #include "ValueWithShadow.h" +#include #include #include @@ -1223,7 +1224,8 @@ ALWAYS_INLINE u16 SoftCPU::read16() if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u16 value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); + u16 value; + ByteReader::load(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()], value); m_eip += 2; return value; } @@ -1233,7 +1235,9 @@ ALWAYS_INLINE u32 SoftCPU::read32() if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - u32 value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); + u32 value; + ByteReader::load(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()], value); + m_eip += 4; return value; } @@ -1243,7 +1247,9 @@ ALWAYS_INLINE u64 SoftCPU::read64() if (!m_cached_code_region || !m_cached_code_region->contains(m_eip)) update_code_cache(); - auto value = *reinterpret_cast(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]); + u64 value; + ByteReader::load(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()], value); + m_eip += 8; return value; }