16 #ifndef GTIRB_BYTE_INTERVAL_H
17 #define GTIRB_BYTE_INTERVAL_H
24 #include <boost/endian/conversion.hpp>
25 #include <boost/icl/interval_map.hpp>
26 #include <boost/iterator/filter_iterator.hpp>
27 #include <boost/iterator/indirect_iterator.hpp>
28 #include <boost/iterator/iterator_categories.hpp>
29 #include <boost/iterator/iterator_facade.hpp>
30 #include <boost/iterator/iterator_traits.hpp>
31 #include <boost/iterator/transform_iterator.hpp>
32 #include <boost/multi_index/hashed_index.hpp>
33 #include <boost/multi_index/key_extractors.hpp>
34 #include <boost/multi_index/mem_fun.hpp>
35 #include <boost/multi_index/ordered_index.hpp>
36 #include <boost/multi_index_container.hpp>
37 #include <boost/range/iterator_range.hpp>
42 #include <type_traits>
57 class ByteIntervalObserver;
79 uint64_t NewSize) = 0;
100 uint64_t NewSize) = 0;
129 uint64_t getOffset()
const {
return Offset; }
147 template <Node::Kind K>
struct BlockKindEquals {
148 bool operator()(
const Block& B)
const {
149 return B.getNode()->getKind() == K;
156 template <
typename NodeType>
struct BlockToNode {
160 BlockToNode(
const BlockToNode<std::remove_const_t<NodeType>>&) {}
162 BlockToNode& operator=(
const BlockToNode<std::remove_const_t<NodeType>>&) {
166 NodeType& operator()(
const Block& B)
const {
170 return *
reinterpret_cast<NodeType*
>(B.Node);
173 NodeType& operator()(
const Block* B)
const {
return *B->Node; }
177 bool operator()(
const Block* b1,
const Block* b2)
const;
181 struct by_pointer {};
182 using BlockSet = boost::multi_index::multi_index_container<
183 Block, boost::multi_index::indexed_by<
184 boost::multi_index::ordered_non_unique<
185 boost::multi_index::tag<by_offset>,
186 boost::multi_index::const_mem_fun<Block, uint64_t,
188 boost::multi_index::hashed_unique<
189 boost::multi_index::tag<by_pointer>,
190 boost::multi_index::const_mem_fun<Block,
Node*,
193 boost::icl::interval_map<uint64_t,
194 std::multiset<const Block*, OffsetLess>>;
195 using SymbolicExpressionMap = std::map<uint64_t, SymbolicExpression>;
198 const Block& nodeToBlock(
const Node* N)
const {
199 auto& Index = Blocks.get<by_pointer>();
200 auto It = Index.find(
const_cast<Node*
>(N));
201 assert(It != Index.end() &&
202 "ByteInterval::nodeToBlock called with block not in interval");
206 class CodeBlockObserverImpl;
207 class DataBlockObserverImpl;
225 std::optional<uint64_t> InitSize = std::nullopt) {
227 InitSize.value_or(Size));
240 std::optional<uint64_t> InitSize = std::nullopt) {
258 template <
typename InputIterator>
261 std::optional<uint64_t> Size = std::nullopt,
262 std::optional<uint64_t> InitSize = std::nullopt) {
264 C, std::nullopt, Size ? *Size : std::distance(Begin, End),
265 InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
283 template <
typename InputIterator>
285 InputIterator Begin, InputIterator End,
286 std::optional<uint64_t> Size = std::nullopt,
287 std::optional<uint64_t> InitSize = std::nullopt) {
289 C, Address, Size ? *Size : std::distance(Begin, End),
290 InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
312 boost::transform_iterator<BlockToNode<Node>,
313 BlockSet::index<by_offset>::type::iterator>;
323 using block_subrange = boost::iterator_range<boost::transform_iterator<
324 BlockToNode<Node>, BlockIntMap::codomain_type::iterator>>;
330 BlockToNode<const Node>,
331 BlockSet::index<by_offset>::type::const_iterator>;
343 BlockToNode<const Node>, BlockIntMap::codomain_type::const_iterator>>;
360 return boost::make_iterator_range(blocks_begin(), blocks_end());
364 return boost::make_iterator_range(blocks_begin(), blocks_end());
374 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
387 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
402 return findBlocksOnOffset(A - *Address);
416 return findBlocksOnOffset(A - *Address);
428 auto Pair = Blocks.get<by_offset>().equal_range(Off);
441 auto& Index = Blocks.get<by_offset>();
442 auto LowIt = Index.lower_bound(Low);
443 auto HighIt = Index.lower_bound(std::max(Low, High));
455 if (!Address || A < *Address) {
457 return findBlocksAtOffset(0, 0);
459 return findBlocksAtOffset(A - *Address);
472 return findBlocksAtOffset(0, 0);
474 return findBlocksAtOffset(Low - std::min(*Address, Low),
475 High - std::min(*Address, High));
485 auto Pair = Blocks.get<by_offset>().equal_range(Off);
498 auto& Index = Blocks.get<by_offset>();
499 auto LowIt = Index.lower_bound(Low);
500 auto HighIt = Index.lower_bound(std::max(Low, High));
512 if (!Address || A < *Address) {
514 return findBlocksAtOffset(0, 0);
516 return findBlocksAtOffset(A - *Address);
529 return findBlocksAtOffset(0, 0);
531 return findBlocksAtOffset(Low - std::min(*Address, Low),
532 High - std::min(*Address, High));
539 using code_block_iterator = boost::transform_iterator<
540 BlockToNode<CodeBlock>,
541 boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
542 BlockSet::index<by_offset>::type::iterator>>;
554 BlockToNode<CodeBlock>,
555 boost::filter_iterator<
556 BlockKindEquals<Node::Kind::CodeBlock>,
557 boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
563 BlockToNode<const CodeBlock>,
564 boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
565 BlockSet::index<by_offset>::type::const_iterator>>;
571 boost::iterator_range<const_code_block_iterator>;
578 boost::iterator_range<boost::transform_iterator<
579 BlockToNode<const CodeBlock>,
580 boost::filter_iterator<
581 BlockKindEquals<Node::Kind::CodeBlock>,
582 boost::indirect_iterator<
583 BlockIntMap::codomain_type::const_iterator>>>>;
588 code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
593 const_code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
599 code_block_iterator::base_type(Blocks.end(), Blocks.end()));
605 const_code_block_iterator::base_type(Blocks.end(), Blocks.end()));
609 return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
614 return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
623 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
624 auto End = boost::make_indirect_iterator(It->second.end());
626 code_block_subrange::iterator::base_type(
627 boost::make_indirect_iterator(It->second.begin()), End),
628 code_block_subrange::iterator::base_type(End, End));
639 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
640 auto End = boost::make_indirect_iterator(It->second.end());
642 const_code_block_subrange::iterator::base_type(
643 boost::make_indirect_iterator(It->second.begin()), End),
644 const_code_block_subrange::iterator::base_type(End, End));
657 return findCodeBlocksOnOffset(A - *Address);
670 return findCodeBlocksOnOffset(A - *Address);
681 auto Pair = Blocks.get<by_offset>().equal_range(Off);
682 return boost::make_iterator_range(
684 code_block_iterator::base_type(Pair.first, Pair.second)),
686 code_block_iterator::base_type(Pair.second, Pair.second)));
696 auto& Index = Blocks.get<by_offset>();
697 auto LowIt = Index.lower_bound(Low);
698 auto HighIt = Index.lower_bound(std::max(Low, High));
699 return boost::make_iterator_range(
710 if (!Address || A < *Address) {
712 return findCodeBlocksAtOffset(0, 0);
714 return findCodeBlocksAtOffset(A - *Address);
726 return findCodeBlocksAtOffset(0, 0);
728 return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
729 High - std::min(*Address, High));
738 auto Pair = Blocks.get<by_offset>().equal_range(Off);
739 return boost::make_iterator_range(
741 const_code_block_iterator::base_type(Pair.first, Pair.second)),
743 const_code_block_iterator::base_type(Pair.second, Pair.second)));
753 uint64_t High)
const {
754 auto& Index = Blocks.get<by_offset>();
755 auto LowIt = Index.lower_bound(Low);
756 auto HighIt = Index.lower_bound(std::max(Low, High));
757 return boost::make_iterator_range(
759 const_code_block_iterator::base_type(LowIt, HighIt)),
761 const_code_block_iterator::base_type(HighIt, HighIt)));
770 if (!Address || A < *Address) {
772 return findCodeBlocksAtOffset(0, 0);
774 return findCodeBlocksAtOffset(A - *Address);
786 return findCodeBlocksAtOffset(0, 0);
788 return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
789 High - std::min(*Address, High));
796 using data_block_iterator = boost::transform_iterator<
797 BlockToNode<DataBlock>,
798 boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
799 BlockSet::index<by_offset>::type::iterator>>;
811 BlockToNode<DataBlock>,
812 boost::filter_iterator<
813 BlockKindEquals<Node::Kind::DataBlock>,
814 boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
820 BlockToNode<const DataBlock>,
821 boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
822 BlockSet::index<by_offset>::type::const_iterator>>;
828 boost::iterator_range<const_data_block_iterator>;
835 boost::iterator_range<boost::transform_iterator<
836 BlockToNode<const DataBlock>,
837 boost::filter_iterator<
838 BlockKindEquals<Node::Kind::DataBlock>,
839 boost::indirect_iterator<
840 BlockIntMap::codomain_type::const_iterator>>>>;
845 data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
850 const_data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
856 data_block_iterator::base_type(Blocks.end(), Blocks.end()));
862 const_data_block_iterator::base_type(Blocks.end(), Blocks.end()));
866 return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
871 return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
880 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
881 auto End = boost::make_indirect_iterator(It->second.end());
883 data_block_subrange::iterator::base_type(
884 boost::make_indirect_iterator(It->second.begin()), End),
885 data_block_subrange::iterator::base_type(End, End));
896 if (
auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
897 auto End = boost::make_indirect_iterator(It->second.end());
899 const_data_block_subrange::iterator::base_type(
900 boost::make_indirect_iterator(It->second.begin()), End),
901 const_data_block_subrange::iterator::base_type(End, End));
914 return findDataBlocksOnOffset(A - *Address);
927 return findDataBlocksOnOffset(A - *Address);
938 auto Pair = Blocks.get<by_offset>().equal_range(Off);
939 return boost::make_iterator_range(
941 data_block_iterator::base_type(Pair.first, Pair.second)),
943 data_block_iterator::base_type(Pair.second, Pair.second)));
953 auto& Index = Blocks.get<by_offset>();
954 auto LowIt = Index.lower_bound(Low);
955 auto HighIt = Index.lower_bound(std::max(Low, High));
956 return boost::make_iterator_range(
967 if (!Address || A < *Address) {
969 return findDataBlocksAtOffset(0, 0);
971 return findDataBlocksAtOffset(A - *Address);
983 return findDataBlocksAtOffset(0, 0);
985 return findDataBlocksAtOffset(Low - std::min(*Address, Low),
986 High - std::min(*Address, High));
995 auto Pair = Blocks.get<by_offset>().equal_range(Off);
996 return boost::make_iterator_range(
998 const_data_block_iterator::base_type(Pair.first, Pair.second)),
1000 const_data_block_iterator::base_type(Pair.second, Pair.second)));
1010 uint64_t High)
const {
1011 auto& Index = Blocks.get<by_offset>();
1012 auto LowIt = Index.lower_bound(Low);
1013 auto HighIt = Index.lower_bound(std::max(Low, High));
1014 return boost::make_iterator_range(
1016 const_data_block_iterator::base_type(LowIt, HighIt)),
1018 const_data_block_iterator::base_type(HighIt, HighIt)));
1027 if (!Address || A < *Address) {
1029 return findDataBlocksAtOffset(0, 0);
1031 return findDataBlocksAtOffset(A - *Address);
1043 return findDataBlocksAtOffset(0, 0);
1045 return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1046 High - std::min(*Address, High));
1056 template <
typename ByteIntervalType>
class SymbolicExpressionElementBase {
1063 SymbolicExpressionElementBase(ByteIntervalType* BI_, uint64_t Off_,
1065 : BI{BI_}, Off{Off_}, SE{SE_} {}
1068 ByteIntervalType* getByteInterval() {
return BI; }
1071 const ByteIntervalType* getByteInterval()
const {
return BI; }
1074 uint64_t getOffset()
const {
return Off; }
1082 operator SymbolicExpressionElementBase<const ByteIntervalType>()
const {
1083 return SymbolicExpressionElementBase<const ByteIntervalType>(BI, Off, SE);
1093 key(
const SymbolicExpressionElementBase<ByteIntervalType>& SEE) {
1094 if (
auto A = SEE.getByteInterval()->getAddress(); A) {
1095 return *A + SEE.getOffset();
1097 return std::nullopt;
1100 const SymbolicExpressionElementBase<ByteIntervalType>& SEE1,
1101 const SymbolicExpressionElementBase<ByteIntervalType>& SEE2)
const {
1102 return key(SEE1) < key(SEE2);
1107 ByteIntervalType* BI;
1119 template <
typename SymExprElementType>
class SymExprPairToElement {
1120 using ByteIntervalType =
1121 decltype(std::declval<SymExprElementType>().getByteInterval());
1122 ByteIntervalType BI;
1125 explicit SymExprPairToElement(ByteIntervalType BI_) : BI{BI_} {}
1128 operator()(
const SymbolicExpressionMap::value_type& Pair)
const {
1129 return SymExprElementType(BI, Pair.first, Pair.second);
1141 SymbolicExpressionElementBase<const ByteInterval>;
1147 boost::transform_iterator<SymExprPairToElement<SymbolicExpressionElement>,
1148 SymbolicExpressionMap::iterator>;
1153 boost::iterator_range<symbolic_expression_iterator>;
1158 SymExprPairToElement<ConstSymbolicExpressionElement>,
1159 SymbolicExpressionMap::const_iterator>;
1164 boost::iterator_range<const_symbolic_expression_iterator>;
1168 return boost::make_transform_iterator(
1169 SymbolicExpressions.begin(),
1170 SymExprPairToElement<SymbolicExpressionElement>(
this));
1174 return boost::make_transform_iterator(
1175 SymbolicExpressions.begin(),
1176 SymExprPairToElement<ConstSymbolicExpressionElement>(
this));
1181 return boost::make_transform_iterator(
1182 SymbolicExpressions.end(),
1183 SymExprPairToElement<SymbolicExpressionElement>(
this));
1188 return boost::make_transform_iterator(
1189 SymbolicExpressions.end(),
1190 SymExprPairToElement<ConstSymbolicExpressionElement>(
this));
1195 return boost::make_iterator_range(symbolic_expressions_begin(),
1196 symbolic_expressions_end());
1201 return boost::make_iterator_range(symbolic_expressions_begin(),
1202 symbolic_expressions_end());
1217 auto Pair = SymbolicExpressions.equal_range(Off);
1218 return boost::make_iterator_range(
1219 boost::make_transform_iterator(
1220 Pair.first, SymExprPairToElement<SymbolicExpressionElement>(
this)),
1221 boost::make_transform_iterator(
1223 SymExprPairToElement<SymbolicExpressionElement>(
this)));
1236 return boost::make_iterator_range(
1237 boost::make_transform_iterator(
1238 SymbolicExpressions.lower_bound(Low),
1239 SymExprPairToElement<SymbolicExpressionElement>(
this)),
1240 boost::make_transform_iterator(
1241 SymbolicExpressions.lower_bound(High),
1242 SymExprPairToElement<SymbolicExpressionElement>(
this)));
1258 return boost::make_iterator_range(symbolic_expressions_end(),
1259 symbolic_expressions_end());
1261 return findSymbolicExpressionsAtOffset(A - *Address);
1274 return boost::make_iterator_range(symbolic_expressions_end(),
1275 symbolic_expressions_end());
1277 return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1291 const_symbolic_expression_range
1293 auto Pair = SymbolicExpressions.equal_range(Off);
1294 return boost::make_iterator_range(
1295 boost::make_transform_iterator(
1297 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)),
1298 boost::make_transform_iterator(
1300 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)));
1311 const_symbolic_expression_range
1313 return boost::make_iterator_range(
1314 boost::make_transform_iterator(
1315 SymbolicExpressions.lower_bound(Low),
1316 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)),
1317 boost::make_transform_iterator(
1318 SymbolicExpressions.lower_bound(High),
1319 SymExprPairToElement<ConstSymbolicExpressionElement>(
this)));
1335 return boost::make_iterator_range(symbolic_expressions_end(),
1336 symbolic_expressions_end());
1338 return findSymbolicExpressionsAtOffset(A - *Address);
1352 return boost::make_iterator_range(symbolic_expressions_end(),
1353 symbolic_expressions_end());
1355 return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1404 template <
typename BlockType,
typename... Args>
1406 BlockType* B = BlockType::Create(C, std::forward<Args>(A)...);
1412 "unexpected result when inserting ByteInterval");
1424 SymbolicExpressions[Off] = SymExpr;
1425 return SymbolicExpressions[Off];
1436 template <
class ExprType,
class... Args>
1438 SymbolicExpressions[Off] = ExprType{A...};
1439 return SymbolicExpressions[Off];
1452 N = SymbolicExpressions.erase(Off);
1463 if (
auto It = SymbolicExpressions.find(Off);
1464 It != SymbolicExpressions.end()) {
1477 if (
auto It = SymbolicExpressions.find(Off);
1478 It != SymbolicExpressions.end()) {
1488 void setAddress(std::optional<Addr> A);
1505 void setSize(uint64_t S);
1538 if (
S > getSize()) {
1549 template <
typename T>
1550 static inline std::enable_if_t<
sizeof(T) != 1, T>
1551 endian_flip(T From, boost::endian::order In, boost::endian::order Out) {
1552 return boost::endian::conditional_reverse(From, In, Out);
1554 template <
typename T>
1555 static inline std::enable_if_t<
sizeof(T) == 1, T>
1556 endian_flip(T From, boost::endian::order, boost::endian::order) {
1569 template <
typename ByteIntervalType,
typename T>
class BytesReference {
1571 BytesReference(ByteIntervalType* BI_,
size_t I_,
1572 boost::endian::order InputOrder_,
1573 boost::endian::order OutputOrder_)
1574 : BI(BI_), I(I_), InputOrder(InputOrder_), OutputOrder(OutputOrder_) {}
1581 operator T()
const {
1582 assert(I +
sizeof(T) <= BI->Size &&
1583 "read into interval's bytes out of bounds!");
1585 auto S = BI->Bytes.size();
1596 const std::array<uint8_t,
sizeof(T)> Array{};
1597 return *
reinterpret_cast<const T*
>(Array.data());
1600 if (I +
sizeof(T) >
S) {
1604 std::array<uint8_t,
sizeof(T)> Array{};
1606 std::copy_n(BI->Bytes.begin() + I, S - I, Array.begin());
1607 return endian_flip(*
reinterpret_cast<const T*
>(Array.data()),
1608 InputOrder, OutputOrder);
1611 return endian_flip(*
reinterpret_cast<const T*
>(BI->Bytes.data() + I),
1612 InputOrder, OutputOrder);
1621 BytesReference<ByteIntervalType, T>& operator=(
const T& rhs) {
1622 assert(I +
sizeof(T) <= BI->Size &&
1623 "write into interval's bytes out of bounds!");
1625 if (I +
sizeof(T) > BI->Bytes.size()) {
1626 BI->Bytes.resize(I +
sizeof(T));
1629 *
reinterpret_cast<T*
>(BI->Bytes.data() + I) =
1630 endian_flip(rhs, OutputOrder, InputOrder);
1634 ByteIntervalType* BI;
1636 boost::endian::order InputOrder;
1637 boost::endian::order OutputOrder;
1646 template <
typename ByteIntervalType,
typename T>
1647 class BytesBaseIterator
1648 :
public boost::iterator_facade<BytesBaseIterator<ByteIntervalType, T>, T,
1649 boost::random_access_traversal_tag,
1650 BytesReference<ByteIntervalType, T>> {
1652 using self = BytesBaseIterator<ByteIntervalType, T>;
1654 BytesBaseIterator(ByteIntervalType* BI_,
size_t I_,
1655 boost::endian::order InputOrder_,
1656 boost::endian::order OutputOrder_)
1657 : BI(BI_), I(I_), InputOrder(InputOrder_), OutputOrder(OutputOrder_) {}
1660 using reference = BytesReference<ByteIntervalType, T>;
1668 BytesBaseIterator() =
default;
1671 reference dereference()
const {
1672 assert(BI &&
"attempt to dereference default-constructed byte iterator!");
1673 return reference(BI, I, InputOrder, OutputOrder);
1676 bool equal(
const self& other)
const {
1677 return BI == other.BI && I == other.I;
1681 assert(BI &&
"attempt to increment default-constructed byte iterator!");
1686 assert(BI &&
"attempt to decrement default-constructed byte iterator!");
1690 void advance(
typename self::difference_type n) {
1691 assert(BI &&
"attempt to advance default-constructed byte iterator!");
1695 typename self::difference_type distance_to(
const self& other)
const {
1696 return (other.I - I) /
sizeof(T);
1701 operator BytesBaseIterator<const ByteIntervalType, T>()
const {
1702 return BytesBaseIterator<const ByteIntervalType, T>(BI, I, InputOrder,
1707 ByteIntervalType* BI{
nullptr};
1709 boost::endian::order InputOrder{boost::endian::order::native};
1710 boost::endian::order OutputOrder{boost::endian::order::native};
1712 friend class ByteInterval;
1720 template <
typename T>
1726 template <
typename T>
1732 template <
typename T>
1738 template <
typename T>
1746 return bytes_begin<T>(getBoostEndianOrder());
1756 template <
typename T>
1759 boost::endian::order OutputOrder = boost::endian::order::native) {
1768 return bytes_end<T>(getBoostEndianOrder());
1778 template <
typename T>
1781 boost::endian::order OutputOrder = boost::endian::order::native) {
1790 return bytes<T>(getBoostEndianOrder());
1800 template <
typename T>
1803 boost::endian::order OutputOrder = boost::endian::order::native) {
1805 bytes_end<T>(InputOrder, OutputOrder));
1813 return bytes_begin<T>(getBoostEndianOrder());
1823 template <
typename T>
1825 boost::endian::order InputOrder,
1826 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1835 return bytes_end<T>(getBoostEndianOrder());
1845 template <
typename T>
1847 boost::endian::order InputOrder,
1848 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1857 return bytes<T>(getBoostEndianOrder());
1867 template <
typename T>
1868 const_bytes_range<T>
1870 boost::endian::order OutputOrder = boost::endian::order::native)
const {
1872 bytes_end<T>(InputOrder, OutputOrder));
1892 template <
typename T,
typename BytesIterator,
typename InputIterator>
1893 BytesIterator insertByteVec(
1894 BytesIterator Pos, InputIterator Begin, InputIterator End,
1895 boost::endian::order VectorOrder,
1896 boost::endian::order ElementsOrder = boost::endian::order::native) {
1898 std::is_same<BytesIterator, bytes_iterator<T>>::value ||
1899 std::is_same<BytesIterator, const_bytes_iterator<T>>::value,
1900 "Pos must be a byte_iterator<T> or a const_byte_iterator<T>");
1902 auto N = std::distance(Begin, End) *
sizeof(T);
1907 if (Pos.I < Bytes.size()) {
1908 Bytes.insert(Bytes.begin() + Pos.I, N, 0);
1911 std::copy(Begin, End,
1912 bytes_iterator<T>(
this, Pos.I, VectorOrder, ElementsOrder));
1931 template <
typename T,
typename BytesIterator>
1932 BytesIterator insertSingleByte(
1933 BytesIterator Pos,
const T& X, boost::endian::order VectorOrder,
1934 boost::endian::order ElementOrder = boost::endian::order::native) {
1935 return insertByteVec<T>(Pos, &X, &X + 1, VectorOrder, ElementOrder);
1949 template <
typename T>
1952 return insertBytes<T>(Pos, X, getBoostEndianOrder());
1965 template <
typename T>
1967 return insertBytes<T>(Pos, X, getBoostEndianOrder());
1982 template <
typename T>
1985 boost::endian::order VectorOrder,
1986 boost::endian::order ElementOrder = boost::endian::order::native) {
1987 return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2002 template <
typename T>
2005 boost::endian::order ElementOrder = boost::endian::order::native) {
2006 return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2023 template <
typename T,
typename InputIterator>
2025 InputIterator Begin, InputIterator End) {
2026 return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2041 template <
typename T,
typename InputIterator>
2043 InputIterator End) {
2044 return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2062 template <
typename T,
typename InputIterator>
2065 boost::endian::order VectorOrder,
2066 boost::endian::order ElementsOrder = boost::endian::order::native) {
2067 return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2085 template <
typename T,
typename InputIterator>
2088 boost::endian::order VectorOrder,
2089 boost::endian::order ElementsOrder = boost::endian::order::native) {
2090 return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2103 template <
typename T>
2106 assert(Begin.I <= End.I &&
"eraseBytes: Begin > End!");
2107 assert(Begin.I <= Size &&
"eraseBytes: Begin out of range!");
2108 assert(End.I <= Size &&
"eraseBytes: End out of range!");
2111 if (Begin.I < Bytes.size()) {
2112 if (End.I < Bytes.size()) {
2114 Bytes.erase(Bytes.begin() + Begin.I, Bytes.begin() + End.I);
2118 Bytes.erase(Bytes.begin() + Begin.I, Bytes.end());
2122 setSize(Size - (End.I - Begin.I));
2137 return reinterpret_cast<T*
>(Bytes.data());
2151 return reinterpret_cast<const T*
>(Bytes.data());
2155 static bool classof(
const Node* N) {
2156 return N->getKind() == Kind::ByteInterval;
2162 boost::endian::order getBoostEndianOrder()
const;
2165 ByteInterval(Context& C);
2167 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2170 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
2173 template <
typename InputIterator>
2174 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2175 InputIterator Begin, InputIterator End)
2176 : ByteInterval(C, A, S, 0) {
2177 Bytes.insert(Bytes.end(), Begin, End);
2178 Bytes.resize(InitSize);
2181 template <
typename InputIterator>
2182 ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2183 InputIterator Begin, InputIterator End,
const UUID& U)
2184 : ByteInterval(C, A,
S, 0, U) {
2185 Bytes.insert(Bytes.end(), Begin, End);
2186 Bytes.resize(InitSize);
2189 void setParent(Section* S, ByteIntervalObserver* O) {
2194 template <
typename InputIterator>
2195 static ByteInterval* Create(Context& C, std::optional<Addr> Address,
2196 InputIterator Begin, InputIterator End,
2197 std::optional<uint64_t> Size,
2198 std::optional<uint64_t> InitSize,
const UUID& U) {
2199 return C.Create<ByteInterval>(
2200 C, Address, Size ? *Size : std::distance(Begin, End),
2201 InitSize ? *InitSize : std::distance(Begin, End), Begin, End, U);
2205 using MessageType = proto::ByteInterval;
2212 void toProtobuf(MessageType* Message)
const;
2220 static ErrorOr<ByteInterval*> fromProtobuf(Context& C,
2221 const MessageType& Message);
2230 bool symbolicExpressionsFromProtobuf(Context& C,
const MessageType& Message);
2233 void save(std::ostream& Out)
const;
2236 static ByteInterval* load(Context& C, std::istream& In);
2239 bool loadSymbolicExpressions(Context& C, std::istream& In);
2242 template <
typename BlockType,
typename IterType>
2246 template <
typename BlockType,
typename IterType>
2249 Section* Parent{
nullptr};
2250 ByteIntervalObserver* Observer{
nullptr};
2251 std::optional<Addr> Address;
2254 BlockIntMap BlockOffsets;
2255 SymbolicExpressionMap SymbolicExpressions;
2256 std::vector<uint8_t> Bytes;
2258 std::unique_ptr<CodeBlockObserver> CBO;
2259 std::unique_ptr<DataBlockObserver> DBO;
2268 friend class SerializationTestHarness;
2362 #endif // GTIRB_BYTE_INTERVAL_H