LCOV - code coverage report
Current view: top level - lib/Support - DataExtractor.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 83 99 83.8 %
Date: 2017-09-14 15:23:50 Functions: 13 19 68.4 %
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    14014709 :   T val = 0;
      20    14014709 :   uint32_t offset = *offset_ptr;
      21    14013676 :   if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
      22    14013676 :     std::memcpy(&val, &Data[offset], sizeof(val));
      23     4529081 :     if (sys::IsLittleEndianHost != isLittleEndian)
      24             :       sys::swapByteOrder(val);
      25             : 
      26             :     // Advance the offset
      27    14013676 :     *offset_ptr += sizeof(val);
      28             :   }
      29             :   return val;
      30             : }
      31             : 
      32             : template <typename T>
      33           2 : static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
      34             :                 const DataExtractor *de, bool isLittleEndian, const char *Data){
      35           2 :   uint32_t offset = *offset_ptr;
      36             : 
      37           4 :   if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
      38           6 :     for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
      39             :         ++value_ptr, offset += sizeof(*dst))
      40           8 :       *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
      41             :     // Advance the offset
      42           2 :     *offset_ptr = offset;
      43             :     // Return a non-NULL pointer to the converted data as an indicator of
      44             :     // success
      45           2 :     return dst;
      46             :   }
      47             :   return nullptr;
      48             : }
      49             : 
      50     9484599 : uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
      51    28453797 :   return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
      52             : }
      53             : 
      54             : uint8_t *
      55           0 : 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           0 :                        Data.data());
      58             : }
      59             : 
      60             : 
      61       33029 : uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
      62       99087 :   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           6 :       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      220039 : uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
      79      660117 :   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           4 :   return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
      85           2 :                         Data.data());
      86             : }
      87             : 
      88     4277036 : uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
      89    12831108 :   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     4233132 : DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     100     4233132 :   switch (byte_size) {
     101           0 :   case 1:
     102           0 :     return getU8(offset_ptr);
     103           0 :   case 2:
     104           0 :     return getU16(offset_ptr);
     105      141270 :   case 4:
     106      141270 :     return getU32(offset_ptr);
     107     4091862 :   case 8:
     108     4091862 :     return getU64(offset_ptr);
     109             :   }
     110           0 :   llvm_unreachable("getUnsigned unhandled case!");
     111             : }
     112             : 
     113             : int64_t
     114          30 : DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
     115          30 :   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          27 :   case 4:
     121          27 :     return (int32_t)getU32(offset_ptr);
     122           1 :   case 8:
     123           1 :     return (int64_t)getU64(offset_ptr);
     124             :   }
     125           0 :   llvm_unreachable("getSigned unhandled case!");
     126             : }
     127             : 
     128      565154 : const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
     129      565154 :   uint32_t offset = *offset_ptr;
     130     1130067 :   StringRef::size_type pos = Data.find('\0', offset);
     131      564913 :   if (pos != StringRef::npos) {
     132      564913 :     *offset_ptr = pos + 1;
     133      564913 :     return Data.data() + offset;
     134             :   }
     135             :   return nullptr;
     136             : }
     137             : 
     138       34052 : StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
     139       34052 :   uint32_t Start = *OffsetPtr;
     140       68104 :   StringRef::size_type Pos = Data.find('\0', Start);
     141       34052 :   if (Pos != StringRef::npos) {
     142       34052 :     *OffsetPtr = Pos + 1;
     143       34052 :     return StringRef(Data.data() + Start, Pos - Start);
     144             :   }
     145           0 :   return StringRef();
     146             : }
     147             : 
     148   144012300 : uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
     149   144012300 :   uint64_t result = 0;
     150   288024600 :   if (Data.empty())
     151             :     return 0;
     152             : 
     153   144012300 :   unsigned shift = 0;
     154   144012300 :   uint32_t offset = *offset_ptr;
     155   144012300 :   uint8_t byte = 0;
     156             : 
     157   151349266 :   while (isValidOffset(offset)) {
     158   302698494 :     byte = Data[offset++];
     159   151349247 :     result |= uint64_t(byte & 0x7f) << shift;
     160   151349247 :     shift += 7;
     161   151349247 :     if ((byte & 0x80) == 0)
     162             :       break;
     163             :   }
     164             : 
     165   144012300 :   *offset_ptr = offset;
     166   144012300 :   return result;
     167             : }
     168             : 
     169      297657 : int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
     170      297657 :   int64_t result = 0;
     171      595314 :   if (Data.empty())
     172             :     return 0;
     173             : 
     174      297657 :   unsigned shift = 0;
     175      297657 :   uint32_t offset = *offset_ptr;
     176      297657 :   uint8_t byte = 0;
     177             : 
     178      529555 :   while (isValidOffset(offset)) {
     179     1059106 :     byte = Data[offset++];
     180      529553 :     result |= uint64_t(byte & 0x7f) << shift;
     181      529553 :     shift += 7;
     182      529553 :     if ((byte & 0x80) == 0)
     183             :       break;
     184             :   }
     185             : 
     186             :   // Sign bit of byte is 2nd high order bit (0x40)
     187      297657 :   if (shift < 64 && (byte & 0x40))
     188      143348 :     result |= -(1ULL << shift);
     189             : 
     190      297657 :   *offset_ptr = offset;
     191      297657 :   return result;
     192             : }

Generated by: LCOV version 1.13