180814287SRaphael Isemann //===-- DataEncoder.cpp ---------------------------------------------------===// 2666cc0b2SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6666cc0b2SZachary Turner // 7666cc0b2SZachary Turner //===----------------------------------------------------------------------===// 8666cc0b2SZachary Turner 9666cc0b2SZachary Turner #include "lldb/Utility/DataEncoder.h" 10666cc0b2SZachary Turner 11*244258e3SGreg Clayton #include "lldb/Utility/DataBufferHeap.h" 12666cc0b2SZachary Turner #include "lldb/Utility/Endian.h" 13666cc0b2SZachary Turner 1464c2760eSDavide Italiano #include "llvm/Support/Endian.h" 15672d2c12SJonas Devlieghere #include "llvm/Support/ErrorHandling.h" 16666cc0b2SZachary Turner 17666cc0b2SZachary Turner #include <cstddef> 18666cc0b2SZachary Turner 1976e47d48SRaphael Isemann #include <cstring> 204479ac15SZachary Turner 21666cc0b2SZachary Turner using namespace lldb; 22666cc0b2SZachary Turner using namespace lldb_private; 2364c2760eSDavide Italiano using namespace llvm::support::endian; 24666cc0b2SZachary Turner 25666cc0b2SZachary Turner DataEncoder::DataEncoder() 26*244258e3SGreg Clayton : m_data_sp(new DataBufferHeap()), m_byte_order(endian::InlHostByteOrder()), 27*244258e3SGreg Clayton m_addr_size(sizeof(void *)) {} 28666cc0b2SZachary Turner 29*244258e3SGreg Clayton DataEncoder::DataEncoder(const void *data, uint32_t length, ByteOrder endian, 30666cc0b2SZachary Turner uint8_t addr_size) 31*244258e3SGreg Clayton : m_data_sp(new DataBufferHeap(data, length)), m_byte_order(endian), 32*244258e3SGreg Clayton m_addr_size(addr_size) {} 33666cc0b2SZachary Turner 34*244258e3SGreg Clayton DataEncoder::DataEncoder(ByteOrder endian, uint8_t addr_size) 35*244258e3SGreg Clayton : m_data_sp(new DataBufferHeap()), m_byte_order(endian), 36*244258e3SGreg Clayton m_addr_size(addr_size) {} 37666cc0b2SZachary Turner 38666cc0b2SZachary Turner DataEncoder::~DataEncoder() = default; 39666cc0b2SZachary Turner 40*244258e3SGreg Clayton llvm::ArrayRef<uint8_t> DataEncoder::GetData() const { 41*244258e3SGreg Clayton return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(), GetByteSize()); 42666cc0b2SZachary Turner } 43666cc0b2SZachary Turner 44*244258e3SGreg Clayton size_t DataEncoder::GetByteSize() const { return m_data_sp->GetByteSize(); } 45666cc0b2SZachary Turner 4605097246SAdrian Prantl // Extract a single unsigned char from the binary data and update the offset 4705097246SAdrian Prantl // pointed to by "offset_ptr". 48666cc0b2SZachary Turner // 49666cc0b2SZachary Turner // RETURNS the byte that was extracted, or zero on failure. 50666cc0b2SZachary Turner uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) { 51666cc0b2SZachary Turner if (ValidOffset(offset)) { 52*244258e3SGreg Clayton m_data_sp->GetBytes()[offset] = value; 53666cc0b2SZachary Turner return offset + 1; 54666cc0b2SZachary Turner } 55666cc0b2SZachary Turner return UINT32_MAX; 56666cc0b2SZachary Turner } 57666cc0b2SZachary Turner 58666cc0b2SZachary Turner uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { 59666cc0b2SZachary Turner if (ValidOffsetForDataOfSize(offset, sizeof(value))) { 60666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) 61*244258e3SGreg Clayton write16be(m_data_sp->GetBytes() + offset, value); 62666cc0b2SZachary Turner else 63*244258e3SGreg Clayton write16le(m_data_sp->GetBytes() + offset, value); 64666cc0b2SZachary Turner 65666cc0b2SZachary Turner return offset + sizeof(value); 66666cc0b2SZachary Turner } 67666cc0b2SZachary Turner return UINT32_MAX; 68666cc0b2SZachary Turner } 69666cc0b2SZachary Turner 70666cc0b2SZachary Turner uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { 71666cc0b2SZachary Turner if (ValidOffsetForDataOfSize(offset, sizeof(value))) { 72666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) 73*244258e3SGreg Clayton write32be(m_data_sp->GetBytes() + offset, value); 74666cc0b2SZachary Turner else 75*244258e3SGreg Clayton write32le(m_data_sp->GetBytes() + offset, value); 76666cc0b2SZachary Turner 77666cc0b2SZachary Turner return offset + sizeof(value); 78666cc0b2SZachary Turner } 79666cc0b2SZachary Turner return UINT32_MAX; 80666cc0b2SZachary Turner } 81666cc0b2SZachary Turner 82666cc0b2SZachary Turner uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) { 83666cc0b2SZachary Turner if (ValidOffsetForDataOfSize(offset, sizeof(value))) { 84666cc0b2SZachary Turner if (m_byte_order != endian::InlHostByteOrder()) 85*244258e3SGreg Clayton write64be(m_data_sp->GetBytes() + offset, value); 86666cc0b2SZachary Turner else 87*244258e3SGreg Clayton write64le(m_data_sp->GetBytes() + offset, value); 88666cc0b2SZachary Turner 89666cc0b2SZachary Turner return offset + sizeof(value); 90666cc0b2SZachary Turner } 91666cc0b2SZachary Turner return UINT32_MAX; 92666cc0b2SZachary Turner } 93666cc0b2SZachary Turner 948ac053eeSJonas Devlieghere uint32_t DataEncoder::PutUnsigned(uint32_t offset, uint32_t byte_size, 95666cc0b2SZachary Turner uint64_t value) { 96666cc0b2SZachary Turner switch (byte_size) { 97666cc0b2SZachary Turner case 1: 98666cc0b2SZachary Turner return PutU8(offset, value); 99666cc0b2SZachary Turner case 2: 100666cc0b2SZachary Turner return PutU16(offset, value); 101666cc0b2SZachary Turner case 4: 102666cc0b2SZachary Turner return PutU32(offset, value); 103666cc0b2SZachary Turner case 8: 104666cc0b2SZachary Turner return PutU64(offset, value); 105666cc0b2SZachary Turner default: 106666cc0b2SZachary Turner llvm_unreachable("GetMax64 unhandled case!"); 107666cc0b2SZachary Turner } 108666cc0b2SZachary Turner return UINT32_MAX; 109666cc0b2SZachary Turner } 110666cc0b2SZachary Turner 111666cc0b2SZachary Turner uint32_t DataEncoder::PutData(uint32_t offset, const void *src, 112666cc0b2SZachary Turner uint32_t src_len) { 113666cc0b2SZachary Turner if (src == nullptr || src_len == 0) 114666cc0b2SZachary Turner return offset; 115666cc0b2SZachary Turner 116666cc0b2SZachary Turner if (ValidOffsetForDataOfSize(offset, src_len)) { 117*244258e3SGreg Clayton memcpy(m_data_sp->GetBytes() + offset, src, src_len); 118666cc0b2SZachary Turner return offset + src_len; 119666cc0b2SZachary Turner } 120666cc0b2SZachary Turner return UINT32_MAX; 121666cc0b2SZachary Turner } 122666cc0b2SZachary Turner 123666cc0b2SZachary Turner uint32_t DataEncoder::PutAddress(uint32_t offset, lldb::addr_t addr) { 1248ac053eeSJonas Devlieghere return PutUnsigned(offset, m_addr_size, addr); 125666cc0b2SZachary Turner } 126666cc0b2SZachary Turner 127666cc0b2SZachary Turner uint32_t DataEncoder::PutCString(uint32_t offset, const char *cstr) { 128666cc0b2SZachary Turner if (cstr != nullptr) 129666cc0b2SZachary Turner return PutData(offset, cstr, strlen(cstr) + 1); 130666cc0b2SZachary Turner return UINT32_MAX; 131666cc0b2SZachary Turner } 132*244258e3SGreg Clayton 133*244258e3SGreg Clayton void DataEncoder::AppendU8(uint8_t value) { 134*244258e3SGreg Clayton m_data_sp->AppendData(&value, sizeof(value)); 135*244258e3SGreg Clayton } 136*244258e3SGreg Clayton 137*244258e3SGreg Clayton void DataEncoder::AppendU16(uint16_t value) { 138*244258e3SGreg Clayton uint32_t offset = m_data_sp->GetByteSize(); 139*244258e3SGreg Clayton m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); 140*244258e3SGreg Clayton PutU16(offset, value); 141*244258e3SGreg Clayton } 142*244258e3SGreg Clayton 143*244258e3SGreg Clayton void DataEncoder::AppendU32(uint32_t value) { 144*244258e3SGreg Clayton uint32_t offset = m_data_sp->GetByteSize(); 145*244258e3SGreg Clayton m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); 146*244258e3SGreg Clayton PutU32(offset, value); 147*244258e3SGreg Clayton } 148*244258e3SGreg Clayton 149*244258e3SGreg Clayton void DataEncoder::AppendU64(uint64_t value) { 150*244258e3SGreg Clayton uint32_t offset = m_data_sp->GetByteSize(); 151*244258e3SGreg Clayton m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); 152*244258e3SGreg Clayton PutU64(offset, value); 153*244258e3SGreg Clayton } 154*244258e3SGreg Clayton 155*244258e3SGreg Clayton void DataEncoder::AppendAddress(lldb::addr_t addr) { 156*244258e3SGreg Clayton switch (m_addr_size) { 157*244258e3SGreg Clayton case 4: 158*244258e3SGreg Clayton AppendU32(addr); 159*244258e3SGreg Clayton break; 160*244258e3SGreg Clayton case 8: 161*244258e3SGreg Clayton AppendU64(addr); 162*244258e3SGreg Clayton break; 163*244258e3SGreg Clayton default: 164*244258e3SGreg Clayton llvm_unreachable("AppendAddress unhandled case!"); 165*244258e3SGreg Clayton } 166*244258e3SGreg Clayton } 167*244258e3SGreg Clayton 168*244258e3SGreg Clayton void DataEncoder::AppendData(llvm::StringRef data) { 169*244258e3SGreg Clayton const char *bytes = data.data(); 170*244258e3SGreg Clayton const size_t length = data.size(); 171*244258e3SGreg Clayton if (bytes && length > 0) 172*244258e3SGreg Clayton m_data_sp->AppendData(bytes, length); 173*244258e3SGreg Clayton } 174*244258e3SGreg Clayton 175*244258e3SGreg Clayton void DataEncoder::AppendCString(llvm::StringRef data) { 176*244258e3SGreg Clayton const char *bytes = data.data(); 177*244258e3SGreg Clayton const size_t length = data.size(); 178*244258e3SGreg Clayton if (bytes) { 179*244258e3SGreg Clayton if (length > 0) 180*244258e3SGreg Clayton m_data_sp->AppendData(bytes, length); 181*244258e3SGreg Clayton if (length == 0 || bytes[length - 1] != '\0') 182*244258e3SGreg Clayton AppendU8(0); 183*244258e3SGreg Clayton } 184*244258e3SGreg Clayton } 185