diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp | 160 | 
1 files changed, 102 insertions, 58 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp b/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp index 673bbb4d06f4..a98297cdb35f 100644 --- a/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp +++ b/contrib/llvm-project/llvm/lib/Support/DataExtractor.cpp @@ -7,111 +7,137 @@  //===----------------------------------------------------------------------===//  #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Errc.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/Host.h" -#include "llvm/Support/SwapByteOrder.h"  #include "llvm/Support/LEB128.h" +#include "llvm/Support/SwapByteOrder.h" +  using namespace llvm; +static void unexpectedEndReached(Error *E) { +  if (E) +    *E = createStringError(errc::illegal_byte_sequence, +                           "unexpected end of data"); +} + +static bool isError(Error *E) { return E && *E; } +  template <typename T> -static T getU(uint32_t *offset_ptr, const DataExtractor *de, -              bool isLittleEndian, const char *Data) { +static T getU(uint64_t *offset_ptr, const DataExtractor *de, +              bool isLittleEndian, const char *Data, llvm::Error *Err) { +  ErrorAsOutParameter ErrAsOut(Err);    T val = 0; -  uint32_t offset = *offset_ptr; -  if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) { -    std::memcpy(&val, &Data[offset], sizeof(val)); -    if (sys::IsLittleEndianHost != isLittleEndian) -      sys::swapByteOrder(val); - -    // Advance the offset -    *offset_ptr += sizeof(val); +  if (isError(Err)) +    return val; + +  uint64_t offset = *offset_ptr; +  if (!de->isValidOffsetForDataOfSize(offset, sizeof(T))) { +    unexpectedEndReached(Err); +    return val;    } +  std::memcpy(&val, &Data[offset], sizeof(val)); +  if (sys::IsLittleEndianHost != isLittleEndian) +    sys::swapByteOrder(val); + +  // Advance the offset +  *offset_ptr += sizeof(val);    return val;  }  template <typename T> -static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count, -                const DataExtractor *de, bool isLittleEndian, const char *Data){ -  uint32_t offset = *offset_ptr; - -  if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) { -    for (T *value_ptr = dst, *end = dst + count; value_ptr != end; -        ++value_ptr, offset += sizeof(*dst)) -      *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data); -    // Advance the offset -    *offset_ptr = offset; -    // Return a non-NULL pointer to the converted data as an indicator of -    // success -    return dst; +static T *getUs(uint64_t *offset_ptr, T *dst, uint32_t count, +                const DataExtractor *de, bool isLittleEndian, const char *Data, +                llvm::Error *Err) { +  ErrorAsOutParameter ErrAsOut(Err); +  if (isError(Err)) +    return nullptr; + +  uint64_t offset = *offset_ptr; + +  if (!de->isValidOffsetForDataOfSize(offset, sizeof(*dst) * count)) { +    unexpectedEndReached(Err); +    return nullptr;    } -  return nullptr; +  for (T *value_ptr = dst, *end = dst + count; value_ptr != end; +       ++value_ptr, offset += sizeof(*dst)) +    *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data, Err); +  // Advance the offset +  *offset_ptr = offset; +  // Return a non-NULL pointer to the converted data as an indicator of +  // success +  return dst;  } -uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const { -  return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data()); +uint8_t DataExtractor::getU8(uint64_t *offset_ptr, llvm::Error *Err) const { +  return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);  }  uint8_t * -DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const { +DataExtractor::getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const {    return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian, -                       Data.data()); +                        Data.data(), nullptr);  } +uint8_t *DataExtractor::getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const { +  return getUs<uint8_t>(&C.Offset, Dst, Count, this, IsLittleEndian, +                        Data.data(), &C.Err); +} -uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const { -  return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data()); +uint16_t DataExtractor::getU16(uint64_t *offset_ptr, llvm::Error *Err) const { +  return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);  } -uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst, +uint16_t *DataExtractor::getU16(uint64_t *offset_ptr, uint16_t *dst,                                  uint32_t count) const {    return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian, -                        Data.data()); +                         Data.data(), nullptr);  } -uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const { +uint32_t DataExtractor::getU24(uint64_t *offset_ptr) const {    uint24_t ExtractedVal = -      getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data()); +      getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data(), nullptr);    // The 3 bytes are in the correct byte order for the host.    return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);  } -uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const { -  return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data()); +uint32_t DataExtractor::getU32(uint64_t *offset_ptr, llvm::Error *Err) const { +  return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);  } -uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst, +uint32_t *DataExtractor::getU32(uint64_t *offset_ptr, uint32_t *dst,                                  uint32_t count) const {    return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian, -                        Data.data()); +                         Data.data(), nullptr);  } -uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const { -  return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data()); +uint64_t DataExtractor::getU64(uint64_t *offset_ptr, llvm::Error *Err) const { +  return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);  } -uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst, +uint64_t *DataExtractor::getU64(uint64_t *offset_ptr, uint64_t *dst,                                  uint32_t count) const {    return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian, -                        Data.data()); +                         Data.data(), nullptr);  } -uint64_t -DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const { +uint64_t DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size, +                                    llvm::Error *Err) const {    switch (byte_size) {    case 1: -    return getU8(offset_ptr); +    return getU8(offset_ptr, Err);    case 2: -    return getU16(offset_ptr); +    return getU16(offset_ptr, Err);    case 4: -    return getU32(offset_ptr); +    return getU32(offset_ptr, Err);    case 8: -    return getU64(offset_ptr); +    return getU64(offset_ptr, Err);    }    llvm_unreachable("getUnsigned unhandled case!");  }  int64_t -DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const { +DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {    switch (byte_size) {    case 1:      return (int8_t)getU8(offset_ptr); @@ -125,8 +151,8 @@ DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {    llvm_unreachable("getSigned unhandled case!");  } -const char *DataExtractor::getCStr(uint32_t *offset_ptr) const { -  uint32_t offset = *offset_ptr; +const char *DataExtractor::getCStr(uint64_t *offset_ptr) const { +  uint64_t offset = *offset_ptr;    StringRef::size_type pos = Data.find('\0', offset);    if (pos != StringRef::npos) {      *offset_ptr = pos + 1; @@ -135,31 +161,38 @@ const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {    return nullptr;  } -StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const { -  uint32_t Start = *OffsetPtr; +StringRef DataExtractor::getCStrRef(uint64_t *offset_ptr) const { +  uint64_t Start = *offset_ptr;    StringRef::size_type Pos = Data.find('\0', Start);    if (Pos != StringRef::npos) { -    *OffsetPtr = Pos + 1; +    *offset_ptr = Pos + 1;      return StringRef(Data.data() + Start, Pos - Start);    }    return StringRef();  } -uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const { +uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr, +                                   llvm::Error *Err) const {    assert(*offset_ptr <= Data.size()); +  ErrorAsOutParameter ErrAsOut(Err); +  if (isError(Err)) +    return 0;    const char *error;    unsigned bytes_read;    uint64_t result = decodeULEB128(        reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,        reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error); -  if (error) +  if (error) { +    if (Err) +      *Err = createStringError(errc::illegal_byte_sequence, error);      return 0; +  }    *offset_ptr += bytes_read;    return result;  } -int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const { +int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr) const {    assert(*offset_ptr <= Data.size());    const char *error; @@ -172,3 +205,14 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {    *offset_ptr += bytes_read;    return result;  } + +void DataExtractor::skip(Cursor &C, uint64_t Length) const { +  ErrorAsOutParameter ErrAsOut(&C.Err); +  if (isError(&C.Err)) +    return; + +  if (isValidOffsetForDataOfSize(C.Offset, Length)) +    C.Offset += Length; +  else +    unexpectedEndReached(&C.Err); +}  | 
