DataExtractor.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. #include "llvm/Support/DataExtractor.h"
  10. #include "llvm/Support/ErrorHandling.h"
  11. #include "llvm/Support/Host.h"
  12. #include "llvm/Support/SwapByteOrder.h"
  13. using namespace llvm;
  14. template <typename T>
  15. static T getU(uint32_t *offset_ptr, const DataExtractor *de,
  16. bool isLittleEndian, const char *Data) {
  17. T val = 0;
  18. uint32_t offset = *offset_ptr;
  19. if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
  20. std::memcpy(&val, &Data[offset], sizeof(val));
  21. if (sys::IsLittleEndianHost != isLittleEndian)
  22. sys::swapByteOrder(val);
  23. // Advance the offset
  24. *offset_ptr += sizeof(val);
  25. }
  26. return val;
  27. }
  28. template <typename T>
  29. static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
  30. const DataExtractor *de, bool isLittleEndian, const char *Data){
  31. uint32_t offset = *offset_ptr;
  32. if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
  33. for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
  34. ++value_ptr, offset += sizeof(*dst))
  35. *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
  36. // Advance the offset
  37. *offset_ptr = offset;
  38. // Return a non-NULL pointer to the converted data as an indicator of
  39. // success
  40. return dst;
  41. }
  42. return nullptr;
  43. }
  44. uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
  45. return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
  46. }
  47. uint8_t *
  48. DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
  49. return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
  50. Data.data());
  51. }
  52. uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
  53. return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
  54. }
  55. uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
  56. uint32_t count) const {
  57. return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
  58. Data.data());
  59. }
  60. uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
  61. return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
  62. }
  63. uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
  64. uint32_t count) const {
  65. return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
  66. Data.data());
  67. }
  68. uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
  69. return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
  70. }
  71. uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
  72. uint32_t count) const {
  73. return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
  74. Data.data());
  75. }
  76. uint64_t
  77. DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
  78. switch (byte_size) {
  79. case 1:
  80. return getU8(offset_ptr);
  81. case 2:
  82. return getU16(offset_ptr);
  83. case 4:
  84. return getU32(offset_ptr);
  85. case 8:
  86. return getU64(offset_ptr);
  87. }
  88. llvm_unreachable("getUnsigned unhandled case!");
  89. }
  90. int64_t
  91. DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
  92. switch (byte_size) {
  93. case 1:
  94. return (int8_t)getU8(offset_ptr);
  95. case 2:
  96. return (int16_t)getU16(offset_ptr);
  97. case 4:
  98. return (int32_t)getU32(offset_ptr);
  99. case 8:
  100. return (int64_t)getU64(offset_ptr);
  101. }
  102. llvm_unreachable("getSigned unhandled case!");
  103. }
  104. const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
  105. uint32_t offset = *offset_ptr;
  106. StringRef::size_type pos = Data.find('\0', offset);
  107. if (pos != StringRef::npos) {
  108. *offset_ptr = pos + 1;
  109. return Data.data() + offset;
  110. }
  111. return nullptr;
  112. }
  113. uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
  114. uint64_t result = 0;
  115. if (Data.empty())
  116. return 0;
  117. unsigned shift = 0;
  118. uint32_t offset = *offset_ptr;
  119. uint8_t byte = 0;
  120. while (isValidOffset(offset)) {
  121. byte = Data[offset++];
  122. result |= uint64_t(byte & 0x7f) << shift;
  123. shift += 7;
  124. if ((byte & 0x80) == 0)
  125. break;
  126. }
  127. *offset_ptr = offset;
  128. return result;
  129. }
  130. int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
  131. int64_t result = 0;
  132. if (Data.empty())
  133. return 0;
  134. unsigned shift = 0;
  135. uint32_t offset = *offset_ptr;
  136. uint8_t byte = 0;
  137. while (isValidOffset(offset)) {
  138. byte = Data[offset++];
  139. result |= uint64_t(byte & 0x7f) << shift;
  140. shift += 7;
  141. if ((byte & 0x80) == 0)
  142. break;
  143. }
  144. // Sign bit of byte is 2nd high order bit (0x40)
  145. if (shift < 64 && (byte & 0x40))
  146. result |= -(1ULL << shift);
  147. *offset_ptr = offset;
  148. return result;
  149. }