From 046e23fa4adaf4cdee23f4f3416d7d57009f19d5 Mon Sep 17 00:00:00 2001 From: Roy Shi Date: Wed, 1 Apr 2026 08:59:02 -0700 Subject: [PATCH] [llvm lib] Fix endian bug in #189098 (#189778) The bug was added in #189098. Both functions that I added/changed assumed little-endian host memory layout when reading/writing non-power-of-two byte sizes (3, 5, 6, 7). On big-endian hosts (SPARC, s390x), memcpy copies bytes into the MSB end of a uint64_t, leaving the value in the wrong bit position. Fix by offsetting the memcpy/write pointer to always target the LSB bytes. --- llvm/lib/DebugInfo/GSYM/FileWriter.cpp | 14 ++++++-------- llvm/lib/Support/DataExtractor.cpp | 13 ++++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/llvm/lib/DebugInfo/GSYM/FileWriter.cpp b/llvm/lib/DebugInfo/GSYM/FileWriter.cpp index 7c55ae03b6f0..5d6d81dfbc3b 100644 --- a/llvm/lib/DebugInfo/GSYM/FileWriter.cpp +++ b/llvm/lib/DebugInfo/GSYM/FileWriter.cpp @@ -55,15 +55,13 @@ void FileWriter::writeUnsigned(uint64_t Value, size_t ByteSize) { assert((ByteSize == 8 || (Value & (uint64_t)-1 << (8 * ByteSize)) == 0) && "potential data loss: higher bits are non-zero"); // Swap and shift bytes if endianness doesn't match. - if (ByteOrder != llvm::endianness::native) { - // Say ByteSize is 3. - // high low - // Input bytes: 00 00 00 00 00 AA BB CC - // Swapped bytes: CC BB AA 00 00 00 00 00 - // Shifted bytes: 00 00 00 00 00 CC BB AA + if (ByteOrder != llvm::endianness::native) Value = sys::getSwappedBytes(Value) >> (8 * (8 - ByteSize)); - } - OS.write(reinterpret_cast(&Value), ByteSize); + // Write from the least significant bytes of Value regardless of host + // endianness. + OS.write(reinterpret_cast(&Value) + + (sys::IsLittleEndianHost ? 0 : 8 - ByteSize), + ByteSize); } void FileWriter::fixup32(uint32_t U, uint64_t Offset) { diff --git a/llvm/lib/Support/DataExtractor.cpp b/llvm/lib/Support/DataExtractor.cpp index 071093504e59..6b58b492002f 100644 --- a/llvm/lib/Support/DataExtractor.cpp +++ b/llvm/lib/Support/DataExtractor.cpp @@ -144,16 +144,15 @@ uint64_t DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size, uint64_t offset = *offset_ptr; if (!prepareRead(offset, byte_size, Err)) return val; - std::memcpy(&val, &Data.data()[offset], byte_size); + // Copy into the least significant bytes of val regardless of host + // endianness. + std::memcpy(reinterpret_cast(&val) + + (sys::IsLittleEndianHost ? 0 : 8 - byte_size), + &Data.data()[offset], byte_size); + // Swap the least significant bytes of val if endianness doesn't match. if (sys::IsLittleEndianHost != IsLittleEndian) - // Say byte_size is 3. - // high low - // Read bytes: 00 00 00 00 00 AA BB CC - // Swapped bytes: CC BB AA 00 00 00 00 00 - // Shifted bytes: 00 00 00 00 00 CC BB AA val = sys::getSwappedBytes(val) >> (8 * (8 - byte_size)); - // Advance the offset *offset_ptr += byte_size; return val; }