xref: /src/contrib/llvm-project/lldb/source/Utility/DataEncoder.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
1cfca06d7SDimitry Andric //===-- DataEncoder.cpp ---------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
974a628f7SDimitry Andric #include "lldb/Utility/DataEncoder.h"
10f034231aSEd Maste 
1177fc4c14SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1274a628f7SDimitry Andric #include "lldb/Utility/Endian.h"
1374a628f7SDimitry Andric 
14ef5d0b5eSDimitry Andric #include "llvm/Support/Endian.h"
1594994d37SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1674a628f7SDimitry Andric 
17f3fbd1c0SDimitry Andric #include <cstddef>
18f034231aSEd Maste 
19344a3780SDimitry Andric #include <cstring>
20f034231aSEd Maste 
21f034231aSEd Maste using namespace lldb;
22f034231aSEd Maste using namespace lldb_private;
23ef5d0b5eSDimitry Andric using namespace llvm::support::endian;
24f034231aSEd Maste 
DataEncoder()2514f1b3e8SDimitry Andric DataEncoder::DataEncoder()
2677fc4c14SDimitry Andric     : m_data_sp(new DataBufferHeap()), m_byte_order(endian::InlHostByteOrder()),
2777fc4c14SDimitry Andric       m_addr_size(sizeof(void *)) {}
28f034231aSEd Maste 
DataEncoder(const void * data,uint32_t length,ByteOrder endian,uint8_t addr_size)2977fc4c14SDimitry Andric DataEncoder::DataEncoder(const void *data, uint32_t length, ByteOrder endian,
3014f1b3e8SDimitry Andric                          uint8_t addr_size)
3177fc4c14SDimitry Andric     : m_data_sp(new DataBufferHeap(data, length)), m_byte_order(endian),
3277fc4c14SDimitry Andric       m_addr_size(addr_size) {}
33f034231aSEd Maste 
DataEncoder(ByteOrder endian,uint8_t addr_size)3477fc4c14SDimitry Andric DataEncoder::DataEncoder(ByteOrder endian, uint8_t addr_size)
3577fc4c14SDimitry Andric     : m_data_sp(new DataBufferHeap()), m_byte_order(endian),
3677fc4c14SDimitry Andric       m_addr_size(addr_size) {}
37f034231aSEd Maste 
38f3fbd1c0SDimitry Andric DataEncoder::~DataEncoder() = default;
39f034231aSEd Maste 
GetData() const4077fc4c14SDimitry Andric llvm::ArrayRef<uint8_t> DataEncoder::GetData() const {
4177fc4c14SDimitry Andric   return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(), GetByteSize());
42f034231aSEd Maste }
43f034231aSEd Maste 
GetByteSize() const4477fc4c14SDimitry Andric size_t DataEncoder::GetByteSize() const { return m_data_sp->GetByteSize(); }
45f034231aSEd Maste 
46f73363f1SDimitry Andric // Extract a single unsigned char from the binary data and update the offset
47f73363f1SDimitry Andric // pointed to by "offset_ptr".
48f034231aSEd Maste //
49f034231aSEd Maste // RETURNS the byte that was extracted, or zero on failure.
PutU8(uint32_t offset,uint8_t value)5014f1b3e8SDimitry Andric uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) {
5114f1b3e8SDimitry Andric   if (ValidOffset(offset)) {
5277fc4c14SDimitry Andric     m_data_sp->GetBytes()[offset] = value;
53f034231aSEd Maste     return offset + 1;
54f034231aSEd Maste   }
55f034231aSEd Maste   return UINT32_MAX;
56f034231aSEd Maste }
57f034231aSEd Maste 
PutU16(uint32_t offset,uint16_t value)5814f1b3e8SDimitry Andric uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) {
5914f1b3e8SDimitry Andric   if (ValidOffsetForDataOfSize(offset, sizeof(value))) {
60e81d9d49SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder())
6177fc4c14SDimitry Andric       write16be(m_data_sp->GetBytes() + offset, value);
62f034231aSEd Maste     else
6377fc4c14SDimitry Andric       write16le(m_data_sp->GetBytes() + offset, value);
64f034231aSEd Maste 
65f034231aSEd Maste     return offset + sizeof(value);
66f034231aSEd Maste   }
67f034231aSEd Maste   return UINT32_MAX;
68f034231aSEd Maste }
69f034231aSEd Maste 
PutU32(uint32_t offset,uint32_t value)7014f1b3e8SDimitry Andric uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) {
7114f1b3e8SDimitry Andric   if (ValidOffsetForDataOfSize(offset, sizeof(value))) {
72e81d9d49SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder())
7377fc4c14SDimitry Andric       write32be(m_data_sp->GetBytes() + offset, value);
74f034231aSEd Maste     else
7577fc4c14SDimitry Andric       write32le(m_data_sp->GetBytes() + offset, value);
76f034231aSEd Maste 
77f034231aSEd Maste     return offset + sizeof(value);
78f034231aSEd Maste   }
79f034231aSEd Maste   return UINT32_MAX;
80f034231aSEd Maste }
81f034231aSEd Maste 
PutU64(uint32_t offset,uint64_t value)8214f1b3e8SDimitry Andric uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) {
8314f1b3e8SDimitry Andric   if (ValidOffsetForDataOfSize(offset, sizeof(value))) {
84e81d9d49SDimitry Andric     if (m_byte_order != endian::InlHostByteOrder())
8577fc4c14SDimitry Andric       write64be(m_data_sp->GetBytes() + offset, value);
86f034231aSEd Maste     else
8777fc4c14SDimitry Andric       write64le(m_data_sp->GetBytes() + offset, value);
88f034231aSEd Maste 
89f034231aSEd Maste     return offset + sizeof(value);
90f034231aSEd Maste   }
91f034231aSEd Maste   return UINT32_MAX;
92f034231aSEd Maste }
93f034231aSEd Maste 
PutUnsigned(uint32_t offset,uint32_t byte_size,uint64_t value)94706b4fc4SDimitry Andric uint32_t DataEncoder::PutUnsigned(uint32_t offset, uint32_t byte_size,
9514f1b3e8SDimitry Andric                                   uint64_t value) {
9614f1b3e8SDimitry Andric   switch (byte_size) {
9714f1b3e8SDimitry Andric   case 1:
9814f1b3e8SDimitry Andric     return PutU8(offset, value);
9914f1b3e8SDimitry Andric   case 2:
10014f1b3e8SDimitry Andric     return PutU16(offset, value);
10114f1b3e8SDimitry Andric   case 4:
10214f1b3e8SDimitry Andric     return PutU32(offset, value);
10314f1b3e8SDimitry Andric   case 8:
10414f1b3e8SDimitry Andric     return PutU64(offset, value);
105f034231aSEd Maste   default:
106a4092fcbSDimitry Andric     llvm_unreachable("GetMax64 unhandled case!");
107f034231aSEd Maste   }
108f034231aSEd Maste   return UINT32_MAX;
109f034231aSEd Maste }
110f034231aSEd Maste 
PutData(uint32_t offset,const void * src,uint32_t src_len)11114f1b3e8SDimitry Andric uint32_t DataEncoder::PutData(uint32_t offset, const void *src,
11214f1b3e8SDimitry Andric                               uint32_t src_len) {
113f3fbd1c0SDimitry Andric   if (src == nullptr || src_len == 0)
114f034231aSEd Maste     return offset;
115f034231aSEd Maste 
11614f1b3e8SDimitry Andric   if (ValidOffsetForDataOfSize(offset, src_len)) {
11777fc4c14SDimitry Andric     memcpy(m_data_sp->GetBytes() + offset, src, src_len);
118f034231aSEd Maste     return offset + src_len;
119f034231aSEd Maste   }
120f034231aSEd Maste   return UINT32_MAX;
121f034231aSEd Maste }
122f034231aSEd Maste 
PutAddress(uint32_t offset,lldb::addr_t addr)12314f1b3e8SDimitry Andric uint32_t DataEncoder::PutAddress(uint32_t offset, lldb::addr_t addr) {
124706b4fc4SDimitry Andric   return PutUnsigned(offset, m_addr_size, addr);
125f034231aSEd Maste }
126f034231aSEd Maste 
PutCString(uint32_t offset,const char * cstr)12714f1b3e8SDimitry Andric uint32_t DataEncoder::PutCString(uint32_t offset, const char *cstr) {
128f3fbd1c0SDimitry Andric   if (cstr != nullptr)
129f034231aSEd Maste     return PutData(offset, cstr, strlen(cstr) + 1);
130f034231aSEd Maste   return UINT32_MAX;
131f034231aSEd Maste }
13277fc4c14SDimitry Andric 
AppendU8(uint8_t value)13377fc4c14SDimitry Andric void DataEncoder::AppendU8(uint8_t value) {
13477fc4c14SDimitry Andric   m_data_sp->AppendData(&value, sizeof(value));
13577fc4c14SDimitry Andric }
13677fc4c14SDimitry Andric 
AppendU16(uint16_t value)13777fc4c14SDimitry Andric void DataEncoder::AppendU16(uint16_t value) {
13877fc4c14SDimitry Andric   uint32_t offset = m_data_sp->GetByteSize();
13977fc4c14SDimitry Andric   m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value));
14077fc4c14SDimitry Andric   PutU16(offset, value);
14177fc4c14SDimitry Andric }
14277fc4c14SDimitry Andric 
AppendU32(uint32_t value)14377fc4c14SDimitry Andric void DataEncoder::AppendU32(uint32_t value) {
14477fc4c14SDimitry Andric   uint32_t offset = m_data_sp->GetByteSize();
14577fc4c14SDimitry Andric   m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value));
14677fc4c14SDimitry Andric   PutU32(offset, value);
14777fc4c14SDimitry Andric }
14877fc4c14SDimitry Andric 
AppendU64(uint64_t value)14977fc4c14SDimitry Andric void DataEncoder::AppendU64(uint64_t value) {
15077fc4c14SDimitry Andric   uint32_t offset = m_data_sp->GetByteSize();
15177fc4c14SDimitry Andric   m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value));
15277fc4c14SDimitry Andric   PutU64(offset, value);
15377fc4c14SDimitry Andric }
15477fc4c14SDimitry Andric 
AppendAddress(lldb::addr_t addr)15577fc4c14SDimitry Andric void DataEncoder::AppendAddress(lldb::addr_t addr) {
15677fc4c14SDimitry Andric   switch (m_addr_size) {
15777fc4c14SDimitry Andric   case 4:
15877fc4c14SDimitry Andric     AppendU32(addr);
15977fc4c14SDimitry Andric     break;
16077fc4c14SDimitry Andric   case 8:
16177fc4c14SDimitry Andric     AppendU64(addr);
16277fc4c14SDimitry Andric     break;
16377fc4c14SDimitry Andric   default:
16477fc4c14SDimitry Andric     llvm_unreachable("AppendAddress unhandled case!");
16577fc4c14SDimitry Andric   }
16677fc4c14SDimitry Andric }
16777fc4c14SDimitry Andric 
AppendData(llvm::StringRef data)16877fc4c14SDimitry Andric void DataEncoder::AppendData(llvm::StringRef data) {
16977fc4c14SDimitry Andric   const char *bytes = data.data();
17077fc4c14SDimitry Andric   const size_t length = data.size();
17177fc4c14SDimitry Andric   if (bytes && length > 0)
17277fc4c14SDimitry Andric     m_data_sp->AppendData(bytes, length);
17377fc4c14SDimitry Andric }
17477fc4c14SDimitry Andric 
AppendData(llvm::ArrayRef<uint8_t> data)17577fc4c14SDimitry Andric void DataEncoder::AppendData(llvm::ArrayRef<uint8_t> data) {
17677fc4c14SDimitry Andric   const uint8_t *bytes = data.data();
17777fc4c14SDimitry Andric   const size_t length = data.size();
17877fc4c14SDimitry Andric   if (bytes && length > 0)
17977fc4c14SDimitry Andric     m_data_sp->AppendData(bytes, length);
18077fc4c14SDimitry Andric }
18177fc4c14SDimitry Andric 
AppendCString(llvm::StringRef data)18277fc4c14SDimitry Andric void DataEncoder::AppendCString(llvm::StringRef data) {
18377fc4c14SDimitry Andric   const char *bytes = data.data();
18477fc4c14SDimitry Andric   const size_t length = data.size();
18577fc4c14SDimitry Andric   if (bytes) {
18677fc4c14SDimitry Andric     if (length > 0)
18777fc4c14SDimitry Andric       m_data_sp->AppendData(bytes, length);
18877fc4c14SDimitry Andric     if (length == 0 || bytes[length - 1] != '\0')
18977fc4c14SDimitry Andric       AppendU8(0);
19077fc4c14SDimitry Andric   }
19177fc4c14SDimitry Andric }
192