LCOV - code coverage report
Current view: top level - lib/Support - DataExtractor.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 78 91 85.7 %
Date: 2018-06-17 00:07:59 Functions: 15 19 78.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DataExtractor.cpp -------------------------------------------------===//
       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 "llvm/Support/DataExtractor.h"
      11             : #include "llvm/Support/ErrorHandling.h"
      12             : #include "llvm/Support/Host.h"
      13             : #include "llvm/Support/SwapByteOrder.h"
      14             : using namespace llvm;
      15             : 
      16             : template <typename T>
      17             : static T getU(uint32_t *offset_ptr, const DataExtractor *de,
      18             :               bool isLittleEndian, const char *Data) {
      19             :   T val = 0;
      20      355088 :   uint32_t offset = *offset_ptr;
      21             :   if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
      22      354586 :     std::memcpy(&val, &Data[offset], sizeof(val));
      23      250575 :     if (sys::IsLittleEndianHost != isLittleEndian)
      24             :       sys::swapByteOrder(val);
      25             : 
      26             :     // Advance the offset
      27      354586 :     *offset_ptr += sizeof(val);
      28             :   }
      29             :   return val;
      30             : }
      31             : 
      32             : template <typename T>
      33          77 : static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
      34             :                 const DataExtractor *de, bool isLittleEndian, const char *Data){
      35          77 :   uint32_t offset = *offset_ptr;
      36             : 
      37          77 :   if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
      38         456 :     for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
      39             :         ++value_ptr, offset += sizeof(*dst))
      40         404 :       *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
      41             :     // Advance the offset
      42          52 :     *offset_ptr = offset;
      43             :     // Return a non-NULL pointer to the converted data as an indicator of
      44             :     // success
      45          52 :     return dst;
      46             :   }
      47             :   return nullptr;
      48             : }
      49             : 
      50      103629 : uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
      51      103629 :   return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
      52             : }
      53             : 
      54             : uint8_t *
      55          75 : DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
      56          75 :   return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
      57          75 :                        Data.data());
      58             : }
      59             : 
      60             : 
      61       13027 : uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
      62       26054 :   return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
      63             : }
      64             : 
      65           0 : uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
      66             :                                 uint32_t count) const {
      67           0 :   return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
      68           0 :                         Data.data());
      69             : }
      70             : 
      71           2 : uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
      72             :   uint24_t ExtractedVal =
      73           2 :       getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
      74             :   // The 3 bytes are in the correct byte order for the host.
      75           2 :   return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
      76             : }
      77             : 
      78       90679 : uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
      79      181358 :   return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
      80             : }
      81             : 
      82           2 : uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
      83             :                                 uint32_t count) const {
      84           2 :   return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
      85           2 :                         Data.data());
      86             : }
      87             : 
      88      147347 : uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
      89      294694 :   return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
      90             : }
      91             : 
      92           0 : uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
      93             :                                 uint32_t count) const {
      94           0 :   return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
      95           0 :                         Data.data());
      96             : }
      97             : 
      98             : uint64_t
      99      196738 : DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     100      196738 :   switch (byte_size) {
     101           0 :   case 1:
     102           0 :     return getU8(offset_ptr);
     103           0 :   case 2:
     104           0 :     return getU16(offset_ptr);
     105       50859 :   case 4:
     106       50859 :     return getU32(offset_ptr);
     107      145879 :   case 8:
     108      145879 :     return getU64(offset_ptr);
     109             :   }
     110           0 :   llvm_unreachable("getUnsigned unhandled case!");
     111             : }
     112             : 
     113             : int64_t
     114         312 : DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     115         312 :   switch (byte_size) {
     116           1 :   case 1:
     117           1 :     return (int8_t)getU8(offset_ptr);
     118           1 :   case 2:
     119           1 :     return (int16_t)getU16(offset_ptr);
     120         305 :   case 4:
     121         305 :     return (int32_t)getU32(offset_ptr);
     122           5 :   case 8:
     123           5 :     return (int64_t)getU64(offset_ptr);
     124             :   }
     125           0 :   llvm_unreachable("getSigned unhandled case!");
     126             : }
     127             : 
     128       25385 : const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
     129       25385 :   uint32_t offset = *offset_ptr;
     130       25385 :   StringRef::size_type pos = Data.find('\0', offset);
     131       25118 :   if (pos != StringRef::npos) {
     132       25118 :     *offset_ptr = pos + 1;
     133       25118 :     return Data.data() + offset;
     134             :   }
     135             :   return nullptr;
     136             : }
     137             : 
     138        4838 : StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
     139        4838 :   uint32_t Start = *OffsetPtr;
     140        4838 :   StringRef::size_type Pos = Data.find('\0', Start);
     141        4838 :   if (Pos != StringRef::npos) {
     142        4838 :     *OffsetPtr = Pos + 1;
     143        4838 :     return StringRef(Data.data() + Start, Pos - Start);
     144             :   }
     145           0 :   return StringRef();
     146             : }
     147             : 
     148      449452 : uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
     149             :   uint64_t result = 0;
     150      449452 :   if (Data.empty())
     151             :     return 0;
     152             : 
     153             :   unsigned shift = 0;
     154      449452 :   uint32_t offset = *offset_ptr;
     155             :   uint8_t byte = 0;
     156             : 
     157      464207 :   while (isValidOffset(offset)) {
     158      928310 :     byte = Data[offset++];
     159      464155 :     result |= uint64_t(byte & 0x7f) << shift;
     160      464155 :     shift += 7;
     161      464155 :     if ((byte & 0x80) == 0)
     162             :       break;
     163             :   }
     164             : 
     165      449452 :   *offset_ptr = offset;
     166      449452 :   return result;
     167             : }
     168             : 
     169        2769 : int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
     170             :   int64_t result = 0;
     171        2769 :   if (Data.empty())
     172             :     return 0;
     173             : 
     174             :   unsigned shift = 0;
     175        2769 :   uint32_t offset = *offset_ptr;
     176             :   uint8_t byte = 0;
     177             : 
     178        3980 :   while (isValidOffset(offset)) {
     179        7936 :     byte = Data[offset++];
     180        3968 :     result |= uint64_t(byte & 0x7f) << shift;
     181        3968 :     shift += 7;
     182        3968 :     if ((byte & 0x80) == 0)
     183             :       break;
     184             :   }
     185             : 
     186             :   // Sign bit of byte is 2nd high order bit (0x40)
     187        2769 :   if (shift < 64 && (byte & 0x40))
     188         963 :     result |= -(1ULL << shift);
     189             : 
     190        2769 :   *offset_ptr = offset;
     191        2769 :   return result;
     192             : }

Generated by: LCOV version 1.13