Home | History | Annotate | Download | only in Core
      1 //===-- DataEncoder.cpp ---------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Core/DataEncoder.h"
     11 
     12 #include <assert.h>
     13 #include <stddef.h>
     14 
     15 #include "llvm/Support/MathExtras.h"
     16 
     17 #include "lldb/Core/DataBuffer.h"
     18 #include "lldb/Host/Endian.h"
     19 
     20 using namespace lldb;
     21 using namespace lldb_private;
     22 
     23 static inline void
     24 WriteInt16(const unsigned char* ptr, unsigned offset, uint16_t value)
     25 {
     26     *(uint16_t *)(ptr + offset) = value;
     27 }
     28 static inline void
     29 WriteInt32 (const unsigned char* ptr, unsigned offset, uint32_t value)
     30 {
     31     *(uint32_t *)(ptr + offset) = value;
     32 }
     33 
     34 static inline void
     35 WriteInt64(const unsigned char* ptr, unsigned offset, uint64_t value)
     36 {
     37     *(uint64_t *)(ptr + offset) = value;
     38 }
     39 
     40 static inline void
     41 WriteSwappedInt16(const unsigned char* ptr, unsigned offset, uint16_t value)
     42 {
     43     *(uint16_t *)(ptr + offset) = llvm::ByteSwap_16(value);
     44 }
     45 
     46 static inline void
     47 WriteSwappedInt32 (const unsigned char* ptr, unsigned offset, uint32_t value)
     48 {
     49     *(uint32_t *)(ptr + offset) = llvm::ByteSwap_32(value);
     50 }
     51 
     52 static inline void
     53 WriteSwappedInt64(const unsigned char* ptr, unsigned offset, uint64_t value)
     54 {
     55     *(uint64_t *)(ptr + offset) = llvm::ByteSwap_64(value);
     56 }
     57 
     58 //----------------------------------------------------------------------
     59 // Default constructor.
     60 //----------------------------------------------------------------------
     61 DataEncoder::DataEncoder () :
     62     m_start     (NULL),
     63     m_end       (NULL),
     64     m_byte_order(lldb::endian::InlHostByteOrder()),
     65     m_addr_size (sizeof(void*)),
     66     m_data_sp   ()
     67 {
     68 }
     69 
     70 //----------------------------------------------------------------------
     71 // This constructor allows us to use data that is owned by someone else.
     72 // The data must stay around as long as this object is valid.
     73 //----------------------------------------------------------------------
     74 DataEncoder::DataEncoder (void* data, uint32_t length, ByteOrder endian, uint8_t addr_size) :
     75     m_start     ((uint8_t*)data),
     76     m_end       ((uint8_t*)data + length),
     77     m_byte_order(endian),
     78     m_addr_size (addr_size),
     79     m_data_sp   ()
     80 {
     81 }
     82 
     83 //----------------------------------------------------------------------
     84 // Make a shared pointer reference to the shared data in "data_sp" and
     85 // set the endian swapping setting to "swap", and the address size to
     86 // "addr_size". The shared data reference will ensure the data lives
     87 // as long as any DataEncoder objects exist that have a reference to
     88 // this data.
     89 //----------------------------------------------------------------------
     90 DataEncoder::DataEncoder (const DataBufferSP& data_sp, ByteOrder endian, uint8_t addr_size) :
     91     m_start     (NULL),
     92     m_end       (NULL),
     93     m_byte_order(endian),
     94     m_addr_size (addr_size),
     95     m_data_sp   ()
     96 {
     97     SetData (data_sp);
     98 }
     99 
    100 //----------------------------------------------------------------------
    101 // Destructor
    102 //----------------------------------------------------------------------
    103 DataEncoder::~DataEncoder ()
    104 {
    105 }
    106 
    107 //------------------------------------------------------------------
    108 // Clears the object contents back to a default invalid state, and
    109 // release any references to shared data that this object may
    110 // contain.
    111 //------------------------------------------------------------------
    112 void
    113 DataEncoder::Clear ()
    114 {
    115     m_start = NULL;
    116     m_end = NULL;
    117     m_byte_order = lldb::endian::InlHostByteOrder();
    118     m_addr_size = sizeof(void*);
    119     m_data_sp.reset();
    120 }
    121 
    122 //------------------------------------------------------------------
    123 // If this object contains shared data, this function returns the
    124 // offset into that shared data. Else zero is returned.
    125 //------------------------------------------------------------------
    126 size_t
    127 DataEncoder::GetSharedDataOffset () const
    128 {
    129     if (m_start != NULL)
    130     {
    131         const DataBuffer * data = m_data_sp.get();
    132         if (data != NULL)
    133         {
    134             const uint8_t * data_bytes = data->GetBytes();
    135             if (data_bytes != NULL)
    136             {
    137                 assert(m_start >= data_bytes);
    138                 return m_start - data_bytes;
    139             }
    140         }
    141     }
    142     return 0;
    143 }
    144 
    145 //----------------------------------------------------------------------
    146 // Set the data with which this object will extract from to data
    147 // starting at BYTES and set the length of the data to LENGTH bytes
    148 // long. The data is externally owned must be around at least as
    149 // long as this object points to the data. No copy of the data is
    150 // made, this object just refers to this data and can extract from
    151 // it. If this object refers to any shared data upon entry, the
    152 // reference to that data will be released. Is SWAP is set to true,
    153 // any data extracted will be endian swapped.
    154 //----------------------------------------------------------------------
    155 uint32_t
    156 DataEncoder::SetData (const void *bytes, uint32_t length, ByteOrder endian)
    157 {
    158     m_byte_order = endian;
    159     m_data_sp.reset();
    160     if (bytes == NULL || length == 0)
    161     {
    162         m_start = NULL;
    163         m_end = NULL;
    164     }
    165     else
    166     {
    167         m_start = (uint8_t *)bytes;
    168         m_end = m_start + length;
    169     }
    170     return GetByteSize();
    171 }
    172 
    173 //----------------------------------------------------------------------
    174 // Assign the data for this object to be a subrange of the shared
    175 // data in "data_sp" starting "data_offset" bytes into "data_sp"
    176 // and ending "data_length" bytes later. If "data_offset" is not
    177 // a valid offset into "data_sp", then this object will contain no
    178 // bytes. If "data_offset" is within "data_sp" yet "data_length" is
    179 // too large, the length will be capped at the number of bytes
    180 // remaining in "data_sp". A ref counted pointer to the data in
    181 // "data_sp" will be made in this object IF the number of bytes this
    182 // object refers to in greater than zero (if at least one byte was
    183 // available starting at "data_offset") to ensure the data stays
    184 // around as long as it is needed. The address size and endian swap
    185 // settings will remain unchanged from their current settings.
    186 //----------------------------------------------------------------------
    187 uint32_t
    188 DataEncoder::SetData (const DataBufferSP& data_sp, uint32_t data_offset, uint32_t data_length)
    189 {
    190     m_start = m_end = NULL;
    191 
    192     if (data_length > 0)
    193     {
    194         m_data_sp = data_sp;
    195         if (data_sp.get())
    196         {
    197             const size_t data_size = data_sp->GetByteSize();
    198             if (data_offset < data_size)
    199             {
    200                 m_start = data_sp->GetBytes() + data_offset;
    201                 const size_t bytes_left = data_size - data_offset;
    202                 // Cap the length of we asked for too many
    203                 if (data_length <= bytes_left)
    204                     m_end = m_start + data_length;  // We got all the bytes we wanted
    205                 else
    206                     m_end = m_start + bytes_left;   // Not all the bytes requested were available in the shared data
    207             }
    208         }
    209     }
    210 
    211     uint32_t new_size = GetByteSize();
    212 
    213     // Don't hold a shared pointer to the data buffer if we don't share
    214     // any valid bytes in the shared buffer.
    215     if (new_size == 0)
    216         m_data_sp.reset();
    217 
    218     return new_size;
    219 }
    220 
    221 //----------------------------------------------------------------------
    222 // Extract a single unsigned char from the binary data and update
    223 // the offset pointed to by "offset_ptr".
    224 //
    225 // RETURNS the byte that was extracted, or zero on failure.
    226 //----------------------------------------------------------------------
    227 uint32_t
    228 DataEncoder::PutU8 (uint32_t offset, uint8_t value)
    229 {
    230     if (ValidOffset(offset))
    231     {
    232         m_start[offset] = value;
    233         return offset + 1;
    234     }
    235     return UINT32_MAX;
    236 }
    237 
    238 uint32_t
    239 DataEncoder::PutU16 (uint32_t offset, uint16_t value)
    240 {
    241     if (ValidOffsetForDataOfSize(offset, sizeof(value)))
    242     {
    243         if (m_byte_order != lldb::endian::InlHostByteOrder())
    244             WriteSwappedInt16 (m_start, offset, value);
    245         else
    246             WriteInt16 (m_start, offset, value);
    247 
    248         return offset + sizeof (value);
    249     }
    250     return UINT32_MAX;
    251 }
    252 
    253 uint32_t
    254 DataEncoder::PutU32 (uint32_t offset, uint32_t value)
    255 {
    256     if (ValidOffsetForDataOfSize(offset, sizeof(value)))
    257     {
    258         if (m_byte_order != lldb::endian::InlHostByteOrder())
    259             WriteSwappedInt32 (m_start, offset, value);
    260         else
    261             WriteInt32 (m_start, offset, value);
    262 
    263         return offset + sizeof (value);
    264     }
    265     return UINT32_MAX;
    266 }
    267 
    268 uint32_t
    269 DataEncoder::PutU64 (uint32_t offset, uint64_t value)
    270 {
    271     if (ValidOffsetForDataOfSize(offset, sizeof(value)))
    272     {
    273         if (m_byte_order != lldb::endian::InlHostByteOrder())
    274             WriteSwappedInt64 (m_start, offset, value);
    275         else
    276             WriteInt64 (m_start, offset, value);
    277 
    278         return offset + sizeof (value);
    279     }
    280     return UINT32_MAX;
    281 }
    282 
    283 //----------------------------------------------------------------------
    284 // Extract a single integer value from the data and update the offset
    285 // pointed to by "offset_ptr". The size of the extracted integer
    286 // is specified by the "byte_size" argument. "byte_size" should have
    287 // a value >= 1 and <= 8 since the return value is only 64 bits
    288 // wide. Any "byte_size" values less than 1 or greater than 8 will
    289 // result in nothing being extracted, and zero being returned.
    290 //
    291 // RETURNS the integer value that was extracted, or zero on failure.
    292 //----------------------------------------------------------------------
    293 uint32_t
    294 DataEncoder::PutMaxU64 (uint32_t offset, uint32_t byte_size, uint64_t value)
    295 {
    296     switch (byte_size)
    297     {
    298     case 1: return PutU8 (offset, value);
    299     case 2: return PutU16(offset, value);
    300     case 4: return PutU32(offset, value);
    301     case 8: return PutU64(offset, value);
    302     default:
    303         assert(!"GetMax64 unhandled case!");
    304         break;
    305     }
    306     return UINT32_MAX;
    307 }
    308 
    309 uint32_t
    310 DataEncoder::PutData (uint32_t offset, const void *src, uint32_t src_len)
    311 {
    312     if (src == NULL || src_len == 0)
    313         return offset;
    314 
    315     if (ValidOffsetForDataOfSize(offset, src_len))
    316     {
    317         memcpy (m_start + offset, src, src_len);
    318         return offset + src_len;
    319     }
    320     return UINT32_MAX;
    321 }
    322 
    323 uint32_t
    324 DataEncoder::PutAddress (uint32_t offset, lldb::addr_t addr)
    325 {
    326     return PutMaxU64 (offset, GetAddressByteSize(), addr);
    327 }
    328 
    329 uint32_t
    330 DataEncoder::PutCString (uint32_t offset, const char *cstr)
    331 {
    332     if (cstr)
    333         return PutData (offset, cstr, strlen(cstr) + 1);
    334     return UINT32_MAX;
    335 }
    336