DataExtractor.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. //===-- DataExtractor.cpp -------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Support/DataExtractor.h"
  9. #include "llvm/Support/ErrorHandling.h"
  10. #include "llvm/Support/Host.h"
  11. #include "llvm/Support/SwapByteOrder.h"
  12. #include "llvm/Support/LEB128.h"
  13. using namespace llvm;
  14. template <typename T>
  15. static T getU(uint64_t *offset_ptr, const DataExtractor *de,
  16. bool isLittleEndian, const char *Data) {
  17. T val = 0;
  18. uint64_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(uint64_t *offset_ptr, T *dst, uint32_t count,
  30. const DataExtractor *de, bool isLittleEndian, const char *Data){
  31. uint64_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(uint64_t *offset_ptr) const {
  45. return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
  46. }
  47. uint8_t *
  48. DataExtractor::getU8(uint64_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(uint64_t *offset_ptr) const {
  53. return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
  54. }
  55. uint16_t *DataExtractor::getU16(uint64_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::getU24(uint64_t *offset_ptr) const {
  61. uint24_t ExtractedVal =
  62. getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
  63. // The 3 bytes are in the correct byte order for the host.
  64. return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
  65. }
  66. uint32_t DataExtractor::getU32(uint64_t *offset_ptr) const {
  67. return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
  68. }
  69. uint32_t *DataExtractor::getU32(uint64_t *offset_ptr, uint32_t *dst,
  70. uint32_t count) const {
  71. return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
  72. Data.data());
  73. }
  74. uint64_t DataExtractor::getU64(uint64_t *offset_ptr) const {
  75. return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
  76. }
  77. uint64_t *DataExtractor::getU64(uint64_t *offset_ptr, uint64_t *dst,
  78. uint32_t count) const {
  79. return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
  80. Data.data());
  81. }
  82. uint64_t
  83. DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size) const {
  84. switch (byte_size) {
  85. case 1:
  86. return getU8(offset_ptr);
  87. case 2:
  88. return getU16(offset_ptr);
  89. case 4:
  90. return getU32(offset_ptr);
  91. case 8:
  92. return getU64(offset_ptr);
  93. }
  94. llvm_unreachable("getUnsigned unhandled case!");
  95. }
  96. int64_t
  97. DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {
  98. switch (byte_size) {
  99. case 1:
  100. return (int8_t)getU8(offset_ptr);
  101. case 2:
  102. return (int16_t)getU16(offset_ptr);
  103. case 4:
  104. return (int32_t)getU32(offset_ptr);
  105. case 8:
  106. return (int64_t)getU64(offset_ptr);
  107. }
  108. llvm_unreachable("getSigned unhandled case!");
  109. }
  110. const char *DataExtractor::getCStr(uint64_t *offset_ptr) const {
  111. uint64_t offset = *offset_ptr;
  112. StringRef::size_type pos = Data.find('\0', offset);
  113. if (pos != StringRef::npos) {
  114. *offset_ptr = pos + 1;
  115. return Data.data() + offset;
  116. }
  117. return nullptr;
  118. }
  119. StringRef DataExtractor::getCStrRef(uint64_t *offset_ptr) const {
  120. uint64_t Start = *offset_ptr;
  121. StringRef::size_type Pos = Data.find('\0', Start);
  122. if (Pos != StringRef::npos) {
  123. *offset_ptr = Pos + 1;
  124. return StringRef(Data.data() + Start, Pos - Start);
  125. }
  126. return StringRef();
  127. }
  128. uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr) const {
  129. assert(*offset_ptr <= Data.size());
  130. const char *error;
  131. unsigned bytes_read;
  132. uint64_t result = decodeULEB128(
  133. reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,
  134. reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error);
  135. if (error)
  136. return 0;
  137. *offset_ptr += bytes_read;
  138. return result;
  139. }
  140. int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr) const {
  141. assert(*offset_ptr <= Data.size());
  142. const char *error;
  143. unsigned bytes_read;
  144. int64_t result = decodeSLEB128(
  145. reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,
  146. reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error);
  147. if (error)
  148. return 0;
  149. *offset_ptr += bytes_read;
  150. return result;
  151. }
  152. // The following is temporary code aimed to preserve compatibility with
  153. // existing code which uses 32-bit offsets.
  154. // It will be removed when migration to 64-bit offsets is finished.
  155. namespace {
  156. class WrapOffset {
  157. uint64_t offset64;
  158. uint32_t *offset32_ptr;
  159. public:
  160. WrapOffset(uint32_t *offset_ptr)
  161. : offset64(*offset_ptr), offset32_ptr(offset_ptr) {}
  162. ~WrapOffset() { *offset32_ptr = offset64; }
  163. operator uint64_t *() { return &offset64; }
  164. };
  165. }
  166. uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
  167. return getU8(WrapOffset(offset_ptr));
  168. }
  169. uint8_t *
  170. DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
  171. return getU8(WrapOffset(offset_ptr), dst, count);
  172. }
  173. uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
  174. return getU16(WrapOffset(offset_ptr));
  175. }
  176. uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
  177. uint32_t count) const {
  178. return getU16(WrapOffset(offset_ptr), dst, count);
  179. }
  180. uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
  181. return getU24(WrapOffset(offset_ptr));
  182. }
  183. uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
  184. return getU32(WrapOffset(offset_ptr));
  185. }
  186. uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
  187. uint32_t count) const {
  188. return getU32(WrapOffset(offset_ptr), dst, count);
  189. }
  190. uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
  191. return getU64(WrapOffset(offset_ptr));
  192. }
  193. uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
  194. uint32_t count) const {
  195. return getU64(WrapOffset(offset_ptr), dst, count);
  196. }
  197. uint64_t
  198. DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
  199. return getUnsigned(WrapOffset(offset_ptr), byte_size);
  200. }
  201. int64_t
  202. DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
  203. return getSigned(WrapOffset(offset_ptr), byte_size);
  204. }
  205. const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
  206. return getCStr(WrapOffset(offset_ptr));
  207. }
  208. StringRef DataExtractor::getCStrRef(uint32_t *offset_ptr) const {
  209. return getCStrRef(WrapOffset(offset_ptr));
  210. }
  211. uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
  212. return getULEB128(WrapOffset(offset_ptr));
  213. }
  214. int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
  215. return getSLEB128(WrapOffset(offset_ptr));
  216. }