LLVM API Documentation

DataExtractor.cpp
Go to the documentation of this file.
00001 //===-- DataExtractor.cpp -------------------------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/Support/DataExtractor.h"
00011 #include "llvm/Support/ErrorHandling.h"
00012 #include "llvm/Support/Host.h"
00013 #include "llvm/Support/SwapByteOrder.h"
00014 using namespace llvm;
00015 
00016 template <typename T>
00017 static T getU(uint32_t *offset_ptr, const DataExtractor *de,
00018               bool isLittleEndian, const char *Data) {
00019   T val = 0;
00020   uint32_t offset = *offset_ptr;
00021   if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
00022     std::memcpy(&val, &Data[offset], sizeof(val));
00023     if (sys::IsLittleEndianHost != isLittleEndian)
00024       sys::swapByteOrder(val);
00025 
00026     // Advance the offset
00027     *offset_ptr += sizeof(val);
00028   }
00029   return val;
00030 }
00031 
00032 template <typename T>
00033 static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
00034                 const DataExtractor *de, bool isLittleEndian, const char *Data){
00035   uint32_t offset = *offset_ptr;
00036 
00037   if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
00038     for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
00039         ++value_ptr, offset += sizeof(*dst))
00040       *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
00041     // Advance the offset
00042     *offset_ptr = offset;
00043     // Return a non-NULL pointer to the converted data as an indicator of
00044     // success
00045     return dst;
00046   }
00047   return nullptr;
00048 }
00049 
00050 uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
00051   return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
00052 }
00053 
00054 uint8_t *
00055 DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
00056   return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
00057                        Data.data());
00058 }
00059 
00060 
00061 uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
00062   return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
00063 }
00064 
00065 uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
00066                                 uint32_t count) const {
00067   return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
00068                         Data.data());
00069 }
00070 
00071 uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
00072   return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
00073 }
00074 
00075 uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
00076                                 uint32_t count) const {
00077   return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
00078                         Data.data());
00079 }
00080 
00081 uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
00082   return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
00083 }
00084 
00085 uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
00086                                 uint32_t count) const {
00087   return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
00088                         Data.data());
00089 }
00090 
00091 uint64_t
00092 DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
00093   switch (byte_size) {
00094   case 1:
00095     return getU8(offset_ptr);
00096   case 2:
00097     return getU16(offset_ptr);
00098   case 4:
00099     return getU32(offset_ptr);
00100   case 8:
00101     return getU64(offset_ptr);
00102   }
00103   llvm_unreachable("getUnsigned unhandled case!");
00104 }
00105 
00106 int64_t
00107 DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
00108   switch (byte_size) {
00109   case 1:
00110     return (int8_t)getU8(offset_ptr);
00111   case 2:
00112     return (int16_t)getU16(offset_ptr);
00113   case 4:
00114     return (int32_t)getU32(offset_ptr);
00115   case 8:
00116     return (int64_t)getU64(offset_ptr);
00117   }
00118   llvm_unreachable("getSigned unhandled case!");
00119 }
00120 
00121 const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
00122   uint32_t offset = *offset_ptr;
00123   StringRef::size_type pos = Data.find('\0', offset);
00124   if (pos != StringRef::npos) {
00125     *offset_ptr = pos + 1;
00126     return Data.data() + offset;
00127   }
00128   return nullptr;
00129 }
00130 
00131 uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
00132   uint64_t result = 0;
00133   if (Data.empty())
00134     return 0;
00135 
00136   unsigned shift = 0;
00137   uint32_t offset = *offset_ptr;
00138   uint8_t byte = 0;
00139 
00140   while (isValidOffset(offset)) {
00141     byte = Data[offset++];
00142     result |= uint64_t(byte & 0x7f) << shift;
00143     shift += 7;
00144     if ((byte & 0x80) == 0)
00145       break;
00146   }
00147 
00148   *offset_ptr = offset;
00149   return result;
00150 }
00151 
00152 int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
00153   int64_t result = 0;
00154   if (Data.empty())
00155     return 0;
00156 
00157   unsigned shift = 0;
00158   uint32_t offset = *offset_ptr;
00159   uint8_t byte = 0;
00160 
00161   while (isValidOffset(offset)) {
00162     byte = Data[offset++];
00163     result |= uint64_t(byte & 0x7f) << shift;
00164     shift += 7;
00165     if ((byte & 0x80) == 0)
00166       break;
00167   }
00168 
00169   // Sign bit of byte is 2nd high order bit (0x40)
00170   if (shift < 64 && (byte & 0x40))
00171     result |= -(1ULL << shift);
00172 
00173   *offset_ptr = offset;
00174   return result;
00175 }