16 #ifndef GTIRB_BYTE_INTERVAL_H
17 #define GTIRB_BYTE_INTERVAL_H
26 #include <boost/endian/conversion.hpp>
27 #include <boost/icl/interval_map.hpp>
28 #include <boost/iterator/filter_iterator.hpp>
29 #include <boost/iterator/indirect_iterator.hpp>
30 #include <boost/iterator/iterator_categories.hpp>
31 #include <boost/iterator/iterator_facade.hpp>
32 #include <boost/iterator/iterator_traits.hpp>
33 #include <boost/iterator/transform_iterator.hpp>
34 #include <boost/multi_index/hashed_index.hpp>
35 #include <boost/multi_index/identity.hpp>
36 #include <boost/multi_index/key_extractors.hpp>
37 #include <boost/multi_index/mem_fun.hpp>
38 #include <boost/multi_index/ordered_index.hpp>
39 #include <boost/multi_index_container.hpp>
40 #include <boost/range/iterator_range.hpp>
45 #include <type_traits>
60 class ByteIntervalObserver;
82 uint64_t NewSize) = 0;
108 uint64_t NewSize) = 0;
137 uint64_t getOffset()
const {
return Offset; }
155 template <Node::Kind K>
struct BlockKindEquals {
156 bool operator()(
const Block& B)
const {
157 return B.getNode()->getKind() == K;
164 template <
typename NodeType>
struct BlockToNode {
168 BlockToNode(
const BlockToNode<std::remove_const_t<NodeType>>&) {}
170 BlockToNode& operator=(
const BlockToNode<std::remove_const_t<NodeType>>&) {
174 NodeType& operator()(
const Block& B)
const {
178 return *
reinterpret_cast<NodeType*
>(B.Node);
181 NodeType& operator()(
const Block* B)
const {
return *B->Node; }
190 bool operator()(
const Block* B1,
const Block* B2)
const {
191 return BlockOffsetPairLess()({B1->Offset, B1->Node},
192 {B2->Offset, B2->Node});
194 bool operator()(
const Block& B1,
const Block& B2)
const {
195 return operator()(&B1, &B2);
204 bool operator()(uint64_t
Offset,
const Block& B)
const {
207 bool operator()(
const Block& B, uint64_t
Offset)
const {
213 struct by_pointer {};
214 using BlockSet = boost::multi_index::multi_index_container<
215 Block, boost::multi_index::indexed_by<
216 boost::multi_index::ordered_non_unique<
217 boost::multi_index::tag<by_offset>,
218 boost::multi_index::identity<Block>, BlockOffsetLess>,
219 boost::multi_index::hashed_unique<
220 boost::multi_index::tag<by_pointer>,
221 boost::multi_index::const_mem_fun<Block,
Node*,
224 boost::icl::interval_map<uint64_t,
225 std::multiset<const Block*, BlockOffsetLess>>;
226 using SymbolicExpressionMap = std::map<uint64_t, SymbolicExpression>;
229 const Block& nodeToBlock(
const Node* N)
const {
230 auto& Index = Blocks.get<by_pointer>();
231 auto It = Index.find(
const_cast<Node*
>(N));
232 assert(It != Index.end() &&
233 "ByteInterval::nodeToBlock called with block not in interval");
237 class CodeBlockObserverImpl;
238 class DataBlockObserverImpl;
248 void updateIntervalMap(
Node* N, std::optional<uint64_t> OldSize,
249 std::optional<uint64_t> NewSize);
252 void updateBlockSortOrder(
Node* N);
272 std::optional<uint64_t> InitSize = std::nullopt) {
274 InitSize.value_or(Size));
287 std::optional<uint64_t> InitSize = std::nullopt) {
305 template <
typename InputIterator>
308 std::optional<uint64_t> Size = std::nullopt,
309 std::optional<uint64_t> InitSize = std::nullopt) {
311 C, std::nullopt, Size ? *Size : std::distance(Begin, End),
312 InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
330 template <
typename InputIterator>
332 InputIterator Begin, InputIterator End,
333 std::optional<uint64_t> Size = std::nullopt,
334 std::optional<uint64_t> InitSize = std::nullopt) {
336 C, Address, Size ? *Size : std::distance(Begin, End),
337 InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
360 boost::transform_iterator<BlockToNode<Node>,
361 BlockSet::index<by_offset>::type::iterator>;
371 using block_subrange = boost::iterator_range<boost::transform_iterator<
372 BlockToNode<Node>, BlockIntMap::codomain_type::iterator>>;
378 BlockToNode<const Node>,
379 BlockSet::index<by_offset>::type::const_iterator>;
391 BlockToNode<const Node>, BlockIntMap::codomain_type::const_iterator>>;
408 return boost::make_iterator_range(blocks_begin(), blocks_end());
412 return boost::make_iterator_range(blocks_begin(), blocks_end());
422 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
435 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
450 return findBlocksOnOffset(A - *Address);
464 return findBlocksOnOffset(A - *Address);
476 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
489 auto& Index = Blocks.get<by_offset>();
490 auto LowIt = Index.lower_bound(Low, OffsetCmp());
491 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
503 if (!Address || A < *Address) {
505 return findBlocksAtOffset(0, 0);
507 return findBlocksAtOffset(A - *Address);
520 return findBlocksAtOffset(0, 0);
522 return findBlocksAtOffset(Low - std::min(*Address, Low),
523 High - std::min(*Address, High));
533 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
546 auto& Index = Blocks.get<by_offset>();
547 auto LowIt = Index.lower_bound(Low, OffsetCmp());
548 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
560 if (!Address || A < *Address) {
562 return findBlocksAtOffset(0, 0);
564 return findBlocksAtOffset(A - *Address);
577 return findBlocksAtOffset(0, 0);
579 return findBlocksAtOffset(Low - std::min(*Address, Low),
580 High - std::min(*Address, High));
587 using code_block_iterator = boost::transform_iterator<
588 BlockToNode<CodeBlock>,
589 boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
590 BlockSet::index<by_offset>::type::iterator>>;
602 BlockToNode<CodeBlock>,
603 boost::filter_iterator<
604 BlockKindEquals<Node::Kind::CodeBlock>,
605 boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
611 BlockToNode<const CodeBlock>,
612 boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
613 BlockSet::index<by_offset>::type::const_iterator>>;
619 boost::iterator_range<const_code_block_iterator>;
626 boost::iterator_range<boost::transform_iterator<
627 BlockToNode<const CodeBlock>,
628 boost::filter_iterator<
629 BlockKindEquals<Node::Kind::CodeBlock>,
630 boost::indirect_iterator<
631 BlockIntMap::codomain_type::const_iterator>>>>;
636 code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
641 const_code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
647 code_block_iterator::base_type(Blocks.end(), Blocks.end()));
653 const_code_block_iterator::base_type(Blocks.end(), Blocks.end()));
657 return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
662 return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
671 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
672 auto End = boost::make_indirect_iterator(It->second.end());
674 code_block_subrange::iterator::base_type(
675 boost::make_indirect_iterator(It->second.begin()), End),
676 code_block_subrange::iterator::base_type(End, End));
687 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
688 auto End = boost::make_indirect_iterator(It->second.end());
690 const_code_block_subrange::iterator::base_type(
691 boost::make_indirect_iterator(It->second.begin()), End),
692 const_code_block_subrange::iterator::base_type(End, End));
705 return findCodeBlocksOnOffset(A - *Address);
718 return findCodeBlocksOnOffset(A - *Address);
729 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
730 return boost::make_iterator_range(
732 code_block_iterator::base_type(Pair.first, Pair.second)),
734 code_block_iterator::base_type(Pair.second, Pair.second)));
744 auto& Index = Blocks.get<by_offset>();
745 auto LowIt = Index.lower_bound(Low, OffsetCmp());
746 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
747 return boost::make_iterator_range(
758 if (!Address || A < *Address) {
760 return findCodeBlocksAtOffset(0, 0);
762 return findCodeBlocksAtOffset(A - *Address);
774 return findCodeBlocksAtOffset(0, 0);
776 return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
777 High - std::min(*Address, High));
786 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
787 return boost::make_iterator_range(
789 const_code_block_iterator::base_type(Pair.first, Pair.second)),
791 const_code_block_iterator::base_type(Pair.second, Pair.second)));
801 uint64_t High)
const {
802 auto& Index = Blocks.get<by_offset>();
803 auto LowIt = Index.lower_bound(Low, OffsetCmp());
804 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
805 return boost::make_iterator_range(
807 const_code_block_iterator::base_type(LowIt, HighIt)),
809 const_code_block_iterator::base_type(HighIt, HighIt)));
818 if (!Address || A < *Address) {
820 return findCodeBlocksAtOffset(0, 0);
822 return findCodeBlocksAtOffset(A - *Address);
834 return findCodeBlocksAtOffset(0, 0);
836 return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
837 High - std::min(*Address, High));
844 using data_block_iterator = boost::transform_iterator<
845 BlockToNode<DataBlock>,
846 boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
847 BlockSet::index<by_offset>::type::iterator>>;
859 BlockToNode<DataBlock>,
860 boost::filter_iterator<
861 BlockKindEquals<Node::Kind::DataBlock>,
862 boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
868 BlockToNode<const DataBlock>,
869 boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
870 BlockSet::index<by_offset>::type::const_iterator>>;
876 boost::iterator_range<const_data_block_iterator>;
883 boost::iterator_range<boost::transform_iterator<
884 BlockToNode<const DataBlock>,
885 boost::filter_iterator<
886 BlockKindEquals<Node::Kind::DataBlock>,
887 boost::indirect_iterator<
888 BlockIntMap::codomain_type::const_iterator>>>>;
893 data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
898 const_data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
904 data_block_iterator::base_type(Blocks.end(), Blocks.end()));
910 const_data_block_iterator::base_type(Blocks.end(), Blocks.end()));
914 return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
919 return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
928 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
929 auto End = boost::make_indirect_iterator(It->second.end());
931 data_block_subrange::iterator::base_type(
932 boost::make_indirect_iterator(It->second.begin()), End),
933 data_block_subrange::iterator::base_type(End, End));
944 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
945 auto End = boost::make_indirect_iterator(It->second.end());
947 const_data_block_subrange::iterator::base_type(
948 boost::make_indirect_iterator(It->second.begin()), End),
949 const_data_block_subrange::iterator::base_type(End, End));
962 return findDataBlocksOnOffset(A - *Address);
975 return findDataBlocksOnOffset(A - *Address);
986 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
987 return boost::make_iterator_range(
989 data_block_iterator::base_type(Pair.first, Pair.second)),
991 data_block_iterator::base_type(Pair.second, Pair.second)));
1001 auto& Index = Blocks.get<by_offset>();
1002 auto LowIt = Index.lower_bound(Low, OffsetCmp());
1003 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
1004 return boost::make_iterator_range(
1015 if (!Address || A < *Address) {
1017 return findDataBlocksAtOffset(0, 0);
1019 return findDataBlocksAtOffset(A - *Address);
1031 return findDataBlocksAtOffset(0, 0);
1033 return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1034 High - std::min(*Address, High));
1043 auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
1044 return boost::make_iterator_range(
1046 const_data_block_iterator::base_type(Pair.first, Pair.second)),
1048 const_data_block_iterator::base_type(Pair.second, Pair.second)));
1058 uint64_t High)
const {
1059 auto& Index = Blocks.get<by_offset>();
1060 auto LowIt = Index.lower_bound(Low, OffsetCmp());
1061 auto HighIt = Index.lower_bound(std::max(Low, High), OffsetCmp());
1062 return boost::make_iterator_range(
1064 const_data_block_iterator::base_type(LowIt, HighIt)),
1066 const_data_block_iterator::base_type(HighIt, HighIt)));
1075 if (!Address || A < *Address) {
1077 return findDataBlocksAtOffset(0, 0);
1079 return findDataBlocksAtOffset(A - *Address);
1091 return findDataBlocksAtOffset(0, 0);
1093 return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1094 High - std::min(*Address, High));
1104 template <
typename ByteIntervalType>
class SymbolicExpressionElementBase {
1111 SymbolicExpressionElementBase(ByteIntervalType* BI_, uint64_t Off_,
1113 : BI{BI_}, Off{Off_}, SE{SE_} {}
1116 ByteIntervalType* getByteInterval() {
return BI; }
1119 const ByteIntervalType* getByteInterval()
const {
return BI; }
1122 uint64_t getOffset()
const {
return Off; }
1130 operator SymbolicExpressionElementBase<const ByteIntervalType>()
const {
1131 return SymbolicExpressionElementBase<const ByteIntervalType>(BI, Off, SE);
1141 key(
const SymbolicExpressionElementBase<ByteIntervalType>& SEE) {
1142 if (
auto A = SEE.getByteInterval()->getAddress(); A) {
1143 return *A + SEE.getOffset();
1145 return std::nullopt;
1148 const SymbolicExpressionElementBase<ByteIntervalType>& SEE1,
1149 const SymbolicExpressionElementBase<ByteIntervalType>& SEE2)
const {
1150 return key(SEE1) < key(SEE2);
1155 ByteIntervalType* BI;
1167 template <
typename SymExprElementType>
class SymExprPairToElement {
1168 using ByteIntervalType =
1169 decltype(std::declval<SymExprElementType>().getByteInterval());
1170 ByteIntervalType BI;
1173 explicit SymExprPairToElement(ByteIntervalType BI_) : BI{BI_} {}
1176 operator()(
const SymbolicExpressionMap::value_type& Pair)
const {
1177 return SymExprElementType(BI, Pair.first, Pair.second);
1189 SymbolicExpressionElementBase<const ByteInterval>;
1195 boost::transform_iterator<SymExprPairToElement<SymbolicExpressionElement>,
1196 SymbolicExpressionMap::iterator>;
1201 boost::iterator_range<symbolic_expression_iterator>;
1206 SymExprPairToElement<ConstSymbolicExpressionElement>,
1207 SymbolicExpressionMap::const_iterator>;
1212 boost::iterator_range<const_symbolic_expression_iterator>;
1216 return boost::make_transform_iterator(
1217 SymbolicExpressions.begin(),
1218 SymExprPairToElement<SymbolicExpressionElement>(
this));
1222 return boost::make_transform_iterator(
1223 SymbolicExpressions.begin(),
1224 SymExprPairToElement<ConstSymbolicExpressionElement>(
this));
1229 return boost::make_transform_iterator(
1230 SymbolicExpressions.end(),
1231 SymExprPairToElement<SymbolicExpressionElement>(
this));
1236 return boost::make_transform_iterator(
1237 SymbolicExpressions.end(),
1238 SymExprPairToElement<ConstSymbolicExpressionElement>(
this));
1243 return boost::make_iterator_range(symbolic_expressions_begin(),
1244 symbolic_expressions_end());
1249 return boost::make_iterator_range(symbolic_expressions_begin(),
1250 symbolic_expressions_end());
1265 auto Pair = SymbolicExpressions.equal_range(Off);
1266 return boost::make_iterator_range(
1267 boost::make_transform_iterator(
1268 Pair.first, SymExprPairToElement<SymbolicExpressionElement>(
this)),
1269 boost::make_transform_iterator(
1271 SymExprPairToElement<SymbolicExpressionElement>(
this)));
1284 return boost::make_iterator_range(
1285 boost::make_transform_iterator(
1286 SymbolicExpressions.lower_bound(Low),
1287 SymExprPairToElement<SymbolicExpressionElement>(
this)),
1288 boost::make_transform_iterator(
1289 SymbolicExpressions.lower_bound(High),
1290 SymExprPairToElement<SymbolicExpressionElement>(
this)));
1306 return boost::make_iterator_range(symbolic_expressions_end(),
1307 symbolic_expressions_end());
1309 return findSymbolicExpressionsAtOffset(A - *Address);
1322 return boost::make_iterator_range(symbolic_expressions_end(),
1323 symbolic_expressions_end());
1325 return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1339 const_symbolic_expression_range
1341 auto Pair = SymbolicExpressions.equal_range(Off);
1342 return boost::make_iterator_range(
1343 boost::make_transform_iterator(
1345 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)),
1346 boost::make_transform_iterator(
1348 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)));
1359 const_symbolic_expression_range
1361 return boost::make_iterator_range(
1362 boost::make_transform_iterator(
1363 SymbolicExpressions.lower_bound(Low),
1364 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)),
1365 boost::make_transform_iterator(
1366 SymbolicExpressions.lower_bound(High),
1367 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)));
1383 return boost::make_iterator_range(symbolic_expressions_end(),
1384 symbolic_expressions_end());
1386 return findSymbolicExpressionsAtOffset(A - *Address);
1400 return boost::make_iterator_range(symbolic_expressions_end(),
1401 symbolic_expressions_end());
1403 return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1452 template <
typename BlockType,
typename... Args>
1454 BlockType* B = BlockType::Create(C, std::forward<Args>(A)...);
1460 "unexpected result when inserting ByteInterval");
1472 SymbolicExpressions[Off] = SymExpr;
1473 return SymbolicExpressions[Off];
1484 template <
class ExprType,
class... Args>
1486 SymbolicExpressions[Off] = ExprType{A...};
1487 return SymbolicExpressions[Off];
1500 N = SymbolicExpressions.erase(Off);
1511 if (
auto It = SymbolicExpressions.find(Off);
1512 It != SymbolicExpressions.end()) {
1525 if (
auto It = SymbolicExpressions.find(Off);
1526 It != SymbolicExpressions.end()) {
1536 void setAddress(std::optional<Addr> A);
1553 void setSize(uint64_t S);
1586 if (
S > getSize()) {
1597 template <
typename T>
1598 static inline std::enable_if_t<
sizeof(T) != 1, T>
1599 endian_flip(T From, boost::endian::order In, boost::endian::order Out) {
1600 return boost::endian::conditional_reverse(From, In, Out);
1602 template <
typename T>
1603 static inline std::enable_if_t<
sizeof(T) == 1, T>
1604 endian_flip(T From, boost::endian::order, boost::endian::order) {
1617 template <
typename ByteIntervalType,
typename T>
class BytesReference {
1619 BytesReference(ByteIntervalType* BI_,
size_t I_,
1620 boost::endian::order InputOrder_,
1621 boost::endian::order OutputOrder_)
1622 : BI(BI_), I(I_), InputOrder(InputOrder_), OutputOrder(OutputOrder_) {}
1629 operator T()
const {
1630 assert(I +
sizeof(T) <= BI->Size &&
1631 "read into interval's bytes out of bounds!");
1633 auto S = BI->Bytes.size();
1644 const std::array<uint8_t,
sizeof(T)> Array{};
1645 return *
reinterpret_cast<const T*
>(Array.data());
1648 if (I +
sizeof(T) >
S) {
1652 std::array<uint8_t,
sizeof(T)> Array{};
1654 std::copy_n(BI->Bytes.begin() + I, S - I, Array.begin());
1655 return endian_flip(*
reinterpret_cast<const T*
>(Array.data()),
1656 InputOrder, OutputOrder);
1659 return endian_flip(*
reinterpret_cast<const T*
>(BI->Bytes.data() + I),
1660 InputOrder, OutputOrder);
1669 BytesReference<ByteIntervalType, T>& operator=(
const T& rhs) {
1670 assert(I +
sizeof(T) <= BI->Size &&
1671 "write into interval's bytes out of bounds!");
1673 if (I +
sizeof(T) > BI->Bytes.size()) {
1674 BI->Bytes.resize(I +
sizeof(T));
1677 *
reinterpret_cast<T*
>(BI->Bytes.data() + I) =
1678 endian_flip(rhs, OutputOrder, InputOrder);
1682 ByteIntervalType* BI;
1684 boost::endian::order InputOrder;
1685 boost::endian::order OutputOrder;
1694 template <
typename ByteIntervalType,
typename T>
1695 class BytesBaseIterator
1696 :
public boost::iterator_facade<BytesBaseIterator<ByteIntervalType, T>, T,
1697 boost::random_access_traversal_tag,
1698 BytesReference<ByteIntervalType, T>> {
1700 using self = BytesBaseIterator<ByteIntervalType, T>;
1702 BytesBaseIterator(ByteIntervalType* BI_,
size_t I_,
1703 boost::endian::order InputOrder_,
1704 boost::endian::order OutputOrder_)
1705 : BI(BI_), I(I_), InputOrder(InputOrder_), OutputOrder(OutputOrder_) {}
1708 using reference = BytesReference<ByteIntervalType, T>;
1716 BytesBaseIterator() =
default;
1719 reference dereference()
const {
1720 assert(BI &&
"attempt to dereference default-constructed byte iterator!");
1721 return reference(BI, I, InputOrder, OutputOrder);
1724 bool equal(
const self& other)
const {
1725 return BI == other.BI && I == other.I;
1729 assert(BI &&
"attempt to increment default-constructed byte iterator!");
1734 assert(BI &&
"attempt to decrement default-constructed byte iterator!");
1738 void advance(
typename self::difference_type n) {
1739 assert(BI &&
"attempt to advance default-constructed byte iterator!");
1743 typename self::difference_type distance_to(
const self& other)
const {
1744 return (other.I - I) /
sizeof(T);
1749 operator BytesBaseIterator<const ByteIntervalType, T>()
const {
1750 return BytesBaseIterator<const ByteIntervalType, T>(BI, I, InputOrder,
1755 ByteIntervalType* BI{
nullptr};
1757 boost::endian::order InputOrder{boost::endian::order::native};
1758 boost::endian::order OutputOrder{boost::endian::order::native};
1760 friend class ByteInterval;
1768 template <
typename T>
1774 template <
typename T>
1780 template <
typename T>
1786 template <
typename T>
1794 return bytes_begin<T>(getBoostEndianOrder());
1804 template <
typename T>
1807 boost::endian::order OutputOrder = boost::endian::order::native) {
1816 return bytes_end<T>(getBoostEndianOrder());
1826 template <
typename T>
1829 boost::endian::order OutputOrder = boost::endian::order::native) {
1838 return bytes<T>(getBoostEndianOrder());
1848 template <
typename T>
1851 boost::endian::order OutputOrder = boost::endian::order::native) {
1853 bytes_end<T>(InputOrder, OutputOrder));
1861 return bytes_begin<T>(getBoostEndianOrder());
1871 template <
typename T>
1873 boost::endian::order InputOrder,
1874 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1883 return bytes_end<T>(getBoostEndianOrder());
1893 template <
typename T>
1895 boost::endian::order InputOrder,
1896 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1905 return bytes<T>(getBoostEndianOrder());
1915 template <
typename T>
1916 const_bytes_range<T>
1918 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1920 bytes_end<T>(InputOrder, OutputOrder));
1940 template <
typename T,
typename BytesIterator,
typename InputIterator>
1941 BytesIterator insertByteVec(
1942 BytesIterator Pos, InputIterator Begin, InputIterator End,
1943 boost::endian::order VectorOrder,
1944 boost::endian::order ElementsOrder = boost::endian::order::native) {
1946 std::is_same<BytesIterator, bytes_iterator<T>>::value ||
1947 std::is_same<BytesIterator, const_bytes_iterator<T>>::value,
1948 "Pos must be a byte_iterator<T> or a const_byte_iterator<T>");
1950 auto N = std::distance(Begin, End) *
sizeof(T);
1955 if (Pos.I < Bytes.size()) {
1956 Bytes.insert(Bytes.begin() + Pos.I, N, 0);
1959 std::copy(Begin, End,
1960 bytes_iterator<T>(
this, Pos.I, VectorOrder, ElementsOrder));
1979 template <
typename T,
typename BytesIterator>
1980 BytesIterator insertSingleByte(
1981 BytesIterator Pos,
const T& X, boost::endian::order VectorOrder,
1982 boost::endian::order ElementOrder = boost::endian::order::native) {
1983 return insertByteVec<T>(Pos, &X, &X + 1, VectorOrder, ElementOrder);
1997 template <
typename T>
2000 return insertBytes<T>(Pos, X, getBoostEndianOrder());
2013 template <
typename T>
2015 return insertBytes<T>(Pos, X, getBoostEndianOrder());
2030 template <
typename T>
2033 boost::endian::order VectorOrder,
2034 boost::endian::order ElementOrder = boost::endian::order::native) {
2035 return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2050 template <
typename T>
2053 boost::endian::order ElementOrder = boost::endian::order::native) {
2054 return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2071 template <
typename T,
typename InputIterator>
2073 InputIterator Begin, InputIterator End) {
2074 return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2089 template <
typename T,
typename InputIterator>
2091 InputIterator End) {
2092 return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2110 template <
typename T,
typename InputIterator>
2113 boost::endian::order VectorOrder,
2114 boost::endian::order ElementsOrder = boost::endian::order::native) {
2115 return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2133 template <
typename T,
typename InputIterator>
2136 boost::endian::order VectorOrder,
2137 boost::endian::order ElementsOrder = boost::endian::order::native) {
2138 return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2151 template <
typename T>
2154 assert(Begin.I <= End.I &&
"eraseBytes: Begin > End!");
2155 assert(Begin.I <= Size &&
"eraseBytes: Begin out of range!");
2156 assert(End.I <= Size &&
"eraseBytes: End out of range!");
2159 if (Begin.I < Bytes.size()) {
2160 if (End.I < Bytes.size()) {
2162 Bytes.erase(Bytes.begin() + Begin.I, Bytes.begin() + End.I);
2166 Bytes.erase(Bytes.begin() + Begin.I, Bytes.end());
2170 setSize(Size - (End.I - Begin.I));
2185 return reinterpret_cast<T*
>(Bytes.data());
2199 return reinterpret_cast<const T*
>(Bytes.data());
2203 static bool classof(
const Node* N) {
2204 return N->getKind() == Kind::ByteInterval;
2210 boost::endian::order getBoostEndianOrder()
const;
2213 ByteInterval(Context& C);
2215 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2218 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
2221 template <
typename InputIterator>
2222 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2223 InputIterator Begin, InputIterator End)
2224 : ByteInterval(C, A, S, 0) {
2225 Bytes.insert(Bytes.end(), Begin, End);
2226 Bytes.resize(InitSize);
2229 template <
typename InputIterator>
2230 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2231 InputIterator Begin, InputIterator End,
const UUID& U)
2232 : ByteInterval(C, A,
S, 0, U) {
2233 Bytes.insert(Bytes.end(), Begin, End);
2234 Bytes.resize(InitSize);
2237 void setParent(Section* S, ByteIntervalObserver* O) {
2242 template <
typename InputIterator>
2243 static ByteInterval* Create(Context& C, std::optional<Addr> Address,
2244 InputIterator Begin, InputIterator End,
2245 std::optional<uint64_t> Size,
2246 std::optional<uint64_t> InitSize,
const UUID& U) {
2247 return C.Create<ByteInterval>(
2248 C, Address, Size ? *Size : std::distance(Begin, End),
2249 InitSize ? *InitSize : std::distance(Begin, End), Begin, End, U);
2253 using MessageType = proto::ByteInterval;
2260 void toProtobuf(MessageType* Message)
const;
2268 static ErrorOr<ByteInterval*> fromProtobuf(Context& C,
2269 const MessageType& Message);
2278 bool symbolicExpressionsFromProtobuf(Context& C,
const MessageType& Message);
2281 void save(std::ostream& Out)
const;
2284 static ByteInterval* load(Context& C, std::istream& In);
2287 bool loadSymbolicExpressions(Context& C, std::istream& In);
2290 template <
typename BlockType,
typename IterType>
2294 template <
typename BlockType,
typename IterType>
2297 Section* Parent{
nullptr};
2298 ByteIntervalObserver* Observer{
nullptr};
2299 std::optional<Addr> Address;
2302 BlockIntMap BlockOffsets;
2303 SymbolicExpressionMap SymbolicExpressions;
2304 std::vector<uint8_t> Bytes;
2306 std::unique_ptr<CodeBlockObserver> CBO;
2307 std::unique_ptr<DataBlockObserver> DBO;
2316 friend struct BlockOffsetLess;
2317 friend class SerializationTestHarness;
2411 #endif // GTIRB_BYTE_INTERVAL_H