LCOV - code coverage report
Current view: top level - lib/Support - DataExtractor.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 119 77.3 %
Date: 2018-10-20 13:21:21 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      109691 :   uint32_t offset = *offset_ptr;
      21             :   if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
      22      378873 :     std::memcpy(&val, &Data[offset], sizeof(val));
      23      269208 :     if (sys::IsLittleEndianHost != isLittleEndian)
      24             :       sys::swapByteOrder(val);
      25             : 
      26             :     // Advance the offset
      27      378873 :     *offset_ptr += sizeof(val);
      28             :   }
      29             :   return val;
      30             : }
      31             : 
      32             : template <typename T>
      33          70 : static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
      34             :                 const DataExtractor *de, bool isLittleEndian, const char *Data){
      35          70 :   uint32_t offset = *offset_ptr;
      36             : 
      37          70 :   if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
      38         389 :     for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
      39             :         ++value_ptr, offset += sizeof(*dst))
      40         344 :       *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
      41             :     // Advance the offset
      42          45 :     *offset_ptr = offset;
      43             :     // Return a non-NULL pointer to the converted data as an indicator of
      44             :     // success
      45          45 :     return dst;
      46             :   }
      47             :   return nullptr;
      48             : }
      49           0 : 
      50             : uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
      51           0 :   return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
      52             : }
      53           0 : 
      54           0 : uint8_t *
      55             : DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
      56           0 :   return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
      57             :                        Data.data());
      58           0 : }
      59             : 
      60             : 
      61           0 : uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
      62             :   return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
      63             : }
      64             : 
      65           2 : uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
      66             :                                 uint32_t count) const {
      67           2 :   return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
      68             :                         Data.data());
      69           2 : }
      70           6 : 
      71             : uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
      72           4 :   uint24_t ExtractedVal =
      73             :       getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
      74           2 :   // The 3 bytes are in the correct byte order for the host.
      75             :   return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
      76             : }
      77           2 : 
      78             : uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
      79             :   return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
      80             : }
      81           0 : 
      82             : uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
      83           0 :                                 uint32_t count) const {
      84             :   return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
      85           0 :                         Data.data());
      86           0 : }
      87             : 
      88           0 : uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
      89             :   return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
      90           0 : }
      91             : 
      92             : uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
      93           0 :                                 uint32_t count) const {
      94             :   return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
      95             :                         Data.data());
      96             : }
      97          68 : 
      98             : uint64_t
      99          68 : DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     100             :   switch (byte_size) {
     101          68 :   case 1:
     102         383 :     return getU8(offset_ptr);
     103             :   case 2:
     104         340 :     return getU16(offset_ptr);
     105             :   case 4:
     106          43 :     return getU32(offset_ptr);
     107             :   case 8:
     108             :     return getU64(offset_ptr);
     109          43 :   }
     110             :   llvm_unreachable("getUnsigned unhandled case!");
     111             : }
     112             : 
     113             : int64_t
     114      109347 : DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     115      109347 :   switch (byte_size) {
     116             :   case 1:
     117             :     return (int8_t)getU8(offset_ptr);
     118             :   case 2:
     119          68 :     return (int16_t)getU16(offset_ptr);
     120          68 :   case 4:
     121          68 :     return (int32_t)getU32(offset_ptr);
     122             :   case 8:
     123             :     return (int64_t)getU64(offset_ptr);
     124             :   }
     125       13527 :   llvm_unreachable("getSigned unhandled case!");
     126       13527 : }
     127             : 
     128             : const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
     129           0 :   uint32_t offset = *offset_ptr;
     130             :   StringRef::size_type pos = Data.find('\0', offset);
     131           0 :   if (pos != StringRef::npos) {
     132           0 :     *offset_ptr = pos + 1;
     133             :     return Data.data() + offset;
     134             :   }
     135           4 :   return nullptr;
     136             : }
     137           4 : 
     138             : StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
     139           4 :   uint32_t Start = *OffsetPtr;
     140             :   StringRef::size_type Pos = Data.find('\0', Start);
     141             :   if (Pos != StringRef::npos) {
     142       93566 :     *OffsetPtr = Pos + 1;
     143       93566 :     return StringRef(Data.data() + Start, Pos - Start);
     144             :   }
     145             :   return StringRef();
     146           2 : }
     147             : 
     148           2 : uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
     149           2 :   uint64_t result = 0;
     150             :   if (Data.empty())
     151             :     return 0;
     152      162604 : 
     153      162604 :   unsigned shift = 0;
     154             :   uint32_t offset = *offset_ptr;
     155             :   uint8_t byte = 0;
     156           0 : 
     157             :   while (isValidOffset(offset)) {
     158           0 :     byte = Data[offset++];
     159           0 :     result |= uint64_t(byte & 0x7f) << shift;
     160             :     shift += 7;
     161             :     if ((byte & 0x80) == 0)
     162             :       break;
     163      214062 :   }
     164      214062 : 
     165           0 :   *offset_ptr = offset;
     166           0 :   return result;
     167           0 : }
     168           0 : 
     169       53128 : int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
     170       53128 :   int64_t result = 0;
     171      160934 :   if (Data.empty())
     172      160934 :     return 0;
     173             : 
     174           0 :   unsigned shift = 0;
     175             :   uint32_t offset = *offset_ptr;
     176             :   uint8_t byte = 0;
     177             : 
     178         363 :   while (isValidOffset(offset)) {
     179         363 :     byte = Data[offset++];
     180           1 :     result |= uint64_t(byte & 0x7f) << shift;
     181           1 :     shift += 7;
     182           1 :     if ((byte & 0x80) == 0)
     183           1 :       break;
     184         356 :   }
     185         356 : 
     186           5 :   // Sign bit of byte is 2nd high order bit (0x40)
     187           5 :   if (shift < 64 && (byte & 0x40))
     188             :     result |= -(1ULL << shift);
     189           0 : 
     190             :   *offset_ptr = offset;
     191             :   return result;
     192       25793 : }

Generated by: LCOV version 1.13