GTIRB  v2.2.0
GrammaTech Intermediate Representation for Binaries: C++ API
ByteInterval.hpp
Go to the documentation of this file.
1 //===- ByteInterval.hpp -----------------------------------------*- C++ -*-===//
2 //
3 // Copyright (C) 2020 GrammaTech, Inc.
4 //
5 // This code is licensed under the MIT license. See the LICENSE file in the
6 // project root for license terms.
7 //
8 // This project is sponsored by the Office of Naval Research, One Liberty
9 // Center, 875 N. Randolph Street, Arlington, VA 22203 under contract #
10 // N68335-17-C-0700. The content of the information does not necessarily
11 // reflect the position or policy of the Government and no official
12 // endorsement should be inferred.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef GTIRB_BYTE_INTERVAL_H
17 #define GTIRB_BYTE_INTERVAL_H
18 
19 #include <gtirb/DecodeMode.hpp>
20 #include <gtirb/Export.hpp>
21 #include <gtirb/Node.hpp>
22 #include <gtirb/Observer.hpp>
24 #include <gtirb/Utility.hpp>
25 #include <array>
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>
41 #include <cstdint>
42 #include <functional>
43 #include <map>
44 #include <optional>
45 #include <type_traits>
46 #include <variant>
47 #include <vector>
48 
51 
52 namespace gtirb {
53 namespace proto {
54 class ByteInterval;
55 } // namespace proto
56 
57 class Section; // Forward declared for the backpointer.
58 class CodeBlock; // Forward declared so Blocks can store CodeBlocks.
59 class DataBlock; // Forward declared so Blocks can store DataBlocks.
60 class ByteIntervalObserver;
61 
62 template <class T> class ErrorOr;
63 
67 
69 public:
70  virtual ~CodeBlockObserver() = default;
71 
81  virtual ChangeStatus sizeChange(CodeBlock* B, uint64_t OldSize,
82  uint64_t NewSize) = 0;
86  virtual ChangeStatus decodeModeChange(CodeBlock* B, DecodeMode OldMode,
87  DecodeMode NewMode) = 0;
88 };
89 
93 
95 public:
96  virtual ~DataBlockObserver() = default;
97 
107  virtual ChangeStatus sizeChange(DataBlock* B, uint64_t OldSize,
108  uint64_t NewSize) = 0;
109 };
110 
129  struct Block {
130  uint64_t Offset;
131  gtirb::Node* Node;
132 
133  Block(uint64_t Off, gtirb::Node* N) : Offset(Off), Node(N) {}
134 
137  uint64_t getOffset() const { return Offset; }
138 
145  gtirb::Node* getNode() const { return Node; }
146  };
147 
155  template <Node::Kind K> struct BlockKindEquals {
156  bool operator()(const Block& B) const {
157  return B.getNode()->getKind() == K;
158  }
159  };
160 
164  template <typename NodeType> struct BlockToNode {
165  BlockToNode() {}
166 
168  BlockToNode(const BlockToNode<std::remove_const_t<NodeType>>&) {}
169 
170  BlockToNode& operator=(const BlockToNode<std::remove_const_t<NodeType>>&) {
171  return *this;
172  }
173 
174  NodeType& operator()(const Block& B) const {
175  // We avoid the call to cast() here because we use this function after
176  // BlockKindEquals, which confirms the type of the Node for us
177  // (and more importantly, we avoid having to include Code/DataBlock).
178  return *reinterpret_cast<NodeType*>(B.Node);
179  }
180 
181  NodeType& operator()(const Block* B) const { return *B->Node; }
182  };
183 
189  struct GTIRB_EXPORT_API BlockOffsetLess {
190  bool operator()(const Block* B1, const Block* B2) const {
191  return BlockOffsetPairLess()({B1->Offset, B1->Node},
192  {B2->Offset, B2->Node});
193  }
194  bool operator()(const Block& B1, const Block& B2) const {
195  return operator()(&B1, &B2);
196  }
197  };
198 
203  struct GTIRB_EXPORT_API OffsetCmp {
204  bool operator()(uint64_t Offset, const Block& B) const {
205  return Offset < B.Offset;
206  }
207  bool operator()(const Block& B, uint64_t Offset) const {
208  return B.Offset < Offset;
209  }
210  };
211 
212  struct by_offset {};
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*,
222  &Block::getNode>>>>;
223  using BlockIntMap =
224  boost::icl::interval_map<uint64_t,
225  std::multiset<const Block*, BlockOffsetLess>>;
226  using SymbolicExpressionMap = std::map<uint64_t, SymbolicExpression>;
227 
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");
234  return *It;
235  }
236 
237  class CodeBlockObserverImpl;
238  class DataBlockObserverImpl;
239 
248  void updateIntervalMap(Node* N, std::optional<uint64_t> OldSize,
249  std::optional<uint64_t> NewSize);
252  void updateBlockSortOrder(Node* N);
253 
254  ChangeStatus sizeChange(Node* N, uint64_t OldSize, uint64_t NewSize);
255  ChangeStatus decodeModeChange(CodeBlock* B, DecodeMode OldMode,
256  DecodeMode NewMode);
257 
258 public:
262  static ByteInterval* Create(Context& C) { return C.Create<ByteInterval>(C); }
263 
271  static ByteInterval* Create(Context& C, uint64_t Size,
272  std::optional<uint64_t> InitSize = std::nullopt) {
273  return C.Create<ByteInterval>(C, std::nullopt, Size,
274  InitSize.value_or(Size));
275  }
276 
285  static ByteInterval* Create(Context& C, std::optional<Addr> Address,
286  uint64_t Size = 0,
287  std::optional<uint64_t> InitSize = std::nullopt) {
288  return C.Create<ByteInterval>(C, Address, Size, InitSize.value_or(Size));
289  }
290 
305  template <typename InputIterator>
306  static ByteInterval* Create(Context& C, InputIterator Begin,
307  InputIterator End,
308  std::optional<uint64_t> Size = std::nullopt,
309  std::optional<uint64_t> InitSize = std::nullopt) {
310  return C.Create<ByteInterval>(
311  C, std::nullopt, Size ? *Size : std::distance(Begin, End),
312  InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
313  }
314 
330  template <typename InputIterator>
331  static ByteInterval* Create(Context& C, std::optional<Addr> Address,
332  InputIterator Begin, InputIterator End,
333  std::optional<uint64_t> Size = std::nullopt,
334  std::optional<uint64_t> InitSize = std::nullopt) {
335  return C.Create<ByteInterval>(
336  C, Address, Size ? *Size : std::distance(Begin, End),
337  InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
338  }
339 
341  Section* getSection() { return Parent; }
343  const Section* getSection() const { return Parent; }
344 
352  std::optional<Addr> getAddress() const { return Address; }
353 
358 
359  using block_iterator =
360  boost::transform_iterator<BlockToNode<Node>,
361  BlockSet::index<by_offset>::type::iterator>;
366  using block_range = boost::iterator_range<block_iterator>;
371  using block_subrange = boost::iterator_range<boost::transform_iterator<
372  BlockToNode<Node>, BlockIntMap::codomain_type::iterator>>;
377  using const_block_iterator = boost::transform_iterator<
378  BlockToNode<const Node>,
379  BlockSet::index<by_offset>::type::const_iterator>;
384  using const_block_range = boost::iterator_range<const_block_iterator>;
390  using const_block_subrange = boost::iterator_range<boost::transform_iterator<
391  BlockToNode<const Node>, BlockIntMap::codomain_type::const_iterator>>;
392 
394  block_iterator blocks_begin() { return block_iterator(Blocks.begin()); }
397  return const_block_iterator(Blocks.begin());
398  }
400  block_iterator blocks_end() { return block_iterator(Blocks.end()); }
404  return const_block_iterator(Blocks.end());
405  }
408  return boost::make_iterator_range(blocks_begin(), blocks_end());
409  }
412  return boost::make_iterator_range(blocks_begin(), blocks_end());
413  }
414 
422  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
423  return block_subrange(It->second.begin(), It->second.end());
424  }
425  return {};
426  }
427 
435  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
436  return const_block_subrange(It->second.begin(), It->second.end());
437  }
438  return {};
439  }
440 
449  if (Address) {
450  return findBlocksOnOffset(A - *Address);
451  }
452  return {};
453  }
454 
463  if (Address) {
464  return findBlocksOnOffset(A - *Address);
465  }
466  return {};
467  }
468 
476  auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
477  return boost::make_iterator_range(block_iterator(Pair.first),
478  block_iterator(Pair.second));
479  }
480 
488  block_range findBlocksAtOffset(uint64_t Low, uint64_t High) {
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());
492  return boost::make_iterator_range(block_iterator(LowIt),
493  block_iterator(HighIt));
494  }
495 
503  if (!Address || A < *Address) {
504  // Return an empty range without default-constructing the iterators.
505  return findBlocksAtOffset(0, 0);
506  }
507  return findBlocksAtOffset(A - *Address);
508  }
509 
518  if (!Address) {
519  // Return an empty range without default-constructing the iterators.
520  return findBlocksAtOffset(0, 0);
521  }
522  return findBlocksAtOffset(Low - std::min(*Address, Low),
523  High - std::min(*Address, High));
524  }
525 
532  const_block_range findBlocksAtOffset(uint64_t Off) const {
533  auto Pair = Blocks.get<by_offset>().equal_range(Off, OffsetCmp());
534  return boost::make_iterator_range(const_block_iterator(Pair.first),
535  const_block_iterator(Pair.second));
536  }
537 
545  const_block_range findBlocksAtOffset(uint64_t Low, uint64_t High) const {
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());
549  return boost::make_iterator_range(const_block_iterator(LowIt),
550  const_block_iterator(HighIt));
551  }
552 
560  if (!Address || A < *Address) {
561  // Return an empty range without default-constructing the iterators.
562  return findBlocksAtOffset(0, 0);
563  }
564  return findBlocksAtOffset(A - *Address);
565  }
566 
575  if (!Address) {
576  // Return an empty range without default-constructing the iterators.
577  return findBlocksAtOffset(0, 0);
578  }
579  return findBlocksAtOffset(Low - std::min(*Address, Low),
580  High - std::min(*Address, High));
581  }
582 
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>>;
595  using code_block_range = boost::iterator_range<code_block_iterator>;
601  using code_block_subrange = boost::iterator_range<boost::transform_iterator<
602  BlockToNode<CodeBlock>,
603  boost::filter_iterator<
604  BlockKindEquals<Node::Kind::CodeBlock>,
605  boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
610  using const_code_block_iterator = boost::transform_iterator<
611  BlockToNode<const CodeBlock>,
612  boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
613  BlockSet::index<by_offset>::type::const_iterator>>;
618  using const_code_block_range =
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>>>>;
632 
635  return code_block_iterator(
636  code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
637  }
641  const_code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
642  }
646  return code_block_iterator(
647  code_block_iterator::base_type(Blocks.end(), Blocks.end()));
648  }
653  const_code_block_iterator::base_type(Blocks.end(), Blocks.end()));
654  }
657  return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
658  }
662  return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
663  }
664 
671  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
672  auto End = boost::make_indirect_iterator(It->second.end());
673  return code_block_subrange(
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));
677  }
678  return {};
679  }
680 
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));
693  }
694  return {};
695  }
696 
704  if (Address) {
705  return findCodeBlocksOnOffset(A - *Address);
706  }
707  return {};
708  }
709 
717  if (Address) {
718  return findCodeBlocksOnOffset(A - *Address);
719  }
720  return {};
721  }
722 
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)));
735  }
736 
743  code_block_range findCodeBlocksAtOffset(uint64_t Low, uint64_t High) {
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(
748  code_block_iterator(code_block_iterator::base_type(LowIt, HighIt)),
749  code_block_iterator(code_block_iterator::base_type(HighIt, HighIt)));
750  }
751 
758  if (!Address || A < *Address) {
759  // Return an empty range without default-constructing the iterators.
760  return findCodeBlocksAtOffset(0, 0);
761  }
762  return findCodeBlocksAtOffset(A - *Address);
763  }
764 
772  if (!Address) {
773  // Return an empty range without default-constructing the iterators.
774  return findCodeBlocksAtOffset(0, 0);
775  }
776  return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
777  High - std::min(*Address, High));
778  }
779 
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)));
792  }
793 
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)));
810  }
811 
818  if (!Address || A < *Address) {
819  // Return an empty range without default-constructing the iterators.
820  return findCodeBlocksAtOffset(0, 0);
821  }
822  return findCodeBlocksAtOffset(A - *Address);
823  }
824 
832  if (!Address) {
833  // Return an empty range without default-constructing the iterators.
834  return findCodeBlocksAtOffset(0, 0);
835  }
836  return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
837  High - std::min(*Address, High));
838  }
839 
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>>;
852  using data_block_range = boost::iterator_range<data_block_iterator>;
858  using data_block_subrange = boost::iterator_range<boost::transform_iterator<
859  BlockToNode<DataBlock>,
860  boost::filter_iterator<
861  BlockKindEquals<Node::Kind::DataBlock>,
862  boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
867  using const_data_block_iterator = boost::transform_iterator<
868  BlockToNode<const DataBlock>,
869  boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
870  BlockSet::index<by_offset>::type::const_iterator>>;
875  using const_data_block_range =
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>>>>;
889 
892  return data_block_iterator(
893  data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
894  }
898  const_data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
899  }
903  return data_block_iterator(
904  data_block_iterator::base_type(Blocks.end(), Blocks.end()));
905  }
910  const_data_block_iterator::base_type(Blocks.end(), Blocks.end()));
911  }
914  return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
915  }
919  return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
920  }
921 
928  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
929  auto End = boost::make_indirect_iterator(It->second.end());
930  return data_block_subrange(
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));
934  }
935  return {};
936  }
937 
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));
950  }
951  return {};
952  }
953 
961  if (Address) {
962  return findDataBlocksOnOffset(A - *Address);
963  }
964  return {};
965  }
966 
974  if (Address) {
975  return findDataBlocksOnOffset(A - *Address);
976  }
977  return {};
978  }
979 
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)));
992  }
993 
1000  data_block_range findDataBlocksAtOffset(uint64_t Low, uint64_t High) {
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(
1005  data_block_iterator(data_block_iterator::base_type(LowIt, HighIt)),
1006  data_block_iterator(data_block_iterator::base_type(HighIt, HighIt)));
1007  }
1008 
1015  if (!Address || A < *Address) {
1016  // Return an empty range without default-constructing the iterators.
1017  return findDataBlocksAtOffset(0, 0);
1018  }
1019  return findDataBlocksAtOffset(A - *Address);
1020  }
1021 
1029  if (!Address) {
1030  // Return an empty range without default-constructing the iterators.
1031  return findDataBlocksAtOffset(0, 0);
1032  }
1033  return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1034  High - std::min(*Address, High));
1035  }
1036 
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)));
1049  }
1050 
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)));
1067  }
1068 
1075  if (!Address || A < *Address) {
1076  // Return an empty range without default-constructing the iterators.
1077  return findDataBlocksAtOffset(0, 0);
1078  }
1079  return findDataBlocksAtOffset(A - *Address);
1080  }
1081 
1089  if (!Address) {
1090  // Return an empty range without default-constructing the iterators.
1091  return findDataBlocksAtOffset(0, 0);
1092  }
1093  return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1094  High - std::min(*Address, High));
1095  }
1096 
1097 private:
1104  template <typename ByteIntervalType> class SymbolicExpressionElementBase {
1105  public:
1111  SymbolicExpressionElementBase(ByteIntervalType* BI_, uint64_t Off_,
1112  const SymbolicExpression& SE_)
1113  : BI{BI_}, Off{Off_}, SE{SE_} {}
1114 
1116  ByteIntervalType* getByteInterval() { return BI; }
1117 
1119  const ByteIntervalType* getByteInterval() const { return BI; }
1120 
1122  uint64_t getOffset() const { return Off; }
1123 
1126  const SymbolicExpression& getSymbolicExpression() const { return SE; }
1127 
1130  operator SymbolicExpressionElementBase<const ByteIntervalType>() const {
1131  return SymbolicExpressionElementBase<const ByteIntervalType>(BI, Off, SE);
1132  }
1133 
1138  struct AddressLess {
1139  using key_type = std::optional<Addr>;
1140  static key_type
1141  key(const SymbolicExpressionElementBase<ByteIntervalType>& SEE) {
1142  if (auto A = SEE.getByteInterval()->getAddress(); A) {
1143  return *A + SEE.getOffset();
1144  }
1145  return std::nullopt;
1146  };
1148  const SymbolicExpressionElementBase<ByteIntervalType>& SEE1,
1149  const SymbolicExpressionElementBase<ByteIntervalType>& SEE2) const {
1150  return key(SEE1) < key(SEE2);
1151  }
1152  };
1153 
1154  private:
1155  ByteIntervalType* BI;
1156  uint64_t Off;
1157  SymbolicExpression SE;
1158  };
1159 
1167  template <typename SymExprElementType> class SymExprPairToElement {
1168  using ByteIntervalType =
1169  decltype(std::declval<SymExprElementType>().getByteInterval());
1170  ByteIntervalType BI;
1171 
1172  public:
1173  explicit SymExprPairToElement(ByteIntervalType BI_) : BI{BI_} {}
1174 
1175  SymExprElementType
1176  operator()(const SymbolicExpressionMap::value_type& Pair) const {
1177  return SymExprElementType(BI, Pair.first, Pair.second);
1178  }
1179  };
1180 
1181 public:
1184  using SymbolicExpressionElement = SymbolicExpressionElementBase<ByteInterval>;
1185 
1189  SymbolicExpressionElementBase<const ByteInterval>;
1190 
1195  boost::transform_iterator<SymExprPairToElement<SymbolicExpressionElement>,
1196  SymbolicExpressionMap::iterator>;
1201  boost::iterator_range<symbolic_expression_iterator>;
1205  using const_symbolic_expression_iterator = boost::transform_iterator<
1206  SymExprPairToElement<ConstSymbolicExpressionElement>,
1207  SymbolicExpressionMap::const_iterator>;
1212  boost::iterator_range<const_symbolic_expression_iterator>;
1213 
1216  return boost::make_transform_iterator(
1217  SymbolicExpressions.begin(),
1218  SymExprPairToElement<SymbolicExpressionElement>(this));
1219  }
1222  return boost::make_transform_iterator(
1223  SymbolicExpressions.begin(),
1224  SymExprPairToElement<ConstSymbolicExpressionElement>(this));
1225  }
1229  return boost::make_transform_iterator(
1230  SymbolicExpressions.end(),
1231  SymExprPairToElement<SymbolicExpressionElement>(this));
1232  }
1236  return boost::make_transform_iterator(
1237  SymbolicExpressions.end(),
1238  SymExprPairToElement<ConstSymbolicExpressionElement>(this));
1239  }
1243  return boost::make_iterator_range(symbolic_expressions_begin(),
1244  symbolic_expressions_end());
1245  }
1249  return boost::make_iterator_range(symbolic_expressions_begin(),
1250  symbolic_expressions_end());
1251  }
1252 
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(
1270  Pair.second,
1271  SymExprPairToElement<SymbolicExpressionElement>(this)));
1272  }
1273 
1283  uint64_t High) {
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)));
1291  }
1292 
1305  if (!Address) {
1306  return boost::make_iterator_range(symbolic_expressions_end(),
1307  symbolic_expressions_end());
1308  }
1309  return findSymbolicExpressionsAtOffset(A - *Address);
1310  }
1311 
1321  if (!Address) {
1322  return boost::make_iterator_range(symbolic_expressions_end(),
1323  symbolic_expressions_end());
1324  }
1325  return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1326  }
1327 
1339  const_symbolic_expression_range
1340  findSymbolicExpressionsAtOffset(uint64_t Off) const {
1341  auto Pair = SymbolicExpressions.equal_range(Off);
1342  return boost::make_iterator_range(
1343  boost::make_transform_iterator(
1344  Pair.first,
1345  SymExprPairToElement<ConstSymbolicExpressionElement>(this)),
1346  boost::make_transform_iterator(
1347  Pair.second,
1348  SymExprPairToElement<ConstSymbolicExpressionElement>(this)));
1349  }
1350 
1359  const_symbolic_expression_range
1360  findSymbolicExpressionsAtOffset(uint64_t Low, uint64_t High) const {
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)));
1368  }
1369 
1382  if (!Address) {
1383  return boost::make_iterator_range(symbolic_expressions_end(),
1384  symbolic_expressions_end());
1385  }
1386  return findSymbolicExpressionsAtOffset(A - *Address);
1387  }
1388 
1398  Addr High) const {
1399  if (!Address) {
1400  return boost::make_iterator_range(symbolic_expressions_end(),
1401  symbolic_expressions_end());
1402  }
1403  return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1404  }
1405 
1413  ChangeStatus removeBlock(CodeBlock* B);
1414 
1422  ChangeStatus removeBlock(DataBlock* B);
1423 
1432  ChangeStatus addBlock(uint64_t Off, CodeBlock* N);
1433 
1442  ChangeStatus addBlock(uint64_t Off, DataBlock* N);
1443 
1452  template <typename BlockType, typename... Args>
1453  BlockType* addBlock(Context& C, uint64_t O, Args&&... A) {
1454  BlockType* B = BlockType::Create(C, std::forward<Args>(A)...);
1455  [[maybe_unused]] ChangeStatus Status = addBlock(O, B);
1456  // addBlock(uint64_t, BlockType*) does not currently reject any insertions
1457  // and the result cannot be NoChange because we just inserted a newly
1458  // created ByteInterval.
1459  assert(Status == ChangeStatus::Accepted &&
1460  "unexpected result when inserting ByteInterval");
1461  return B;
1462  }
1463 
1471  const SymbolicExpression& SymExpr) {
1472  SymbolicExpressions[Off] = SymExpr;
1473  return SymbolicExpressions[Off];
1474  }
1475 
1484  template <class ExprType, class... Args>
1485  SymbolicExpression& addSymbolicExpression(uint64_t Off, Args... A) {
1486  SymbolicExpressions[Off] = ExprType{A...};
1487  return SymbolicExpressions[Off];
1488  }
1489 
1498  bool removeSymbolicExpression(uint64_t Off) {
1499  std::size_t N;
1500  N = SymbolicExpressions.erase(Off);
1501  return N != 0;
1502  }
1503 
1511  if (auto It = SymbolicExpressions.find(Off);
1512  It != SymbolicExpressions.end()) {
1513  return &It->second;
1514  }
1515  return nullptr;
1516  }
1517 
1524  const SymbolicExpression* getSymbolicExpression(uint64_t Off) const {
1525  if (auto It = SymbolicExpressions.find(Off);
1526  It != SymbolicExpressions.end()) {
1527  return &It->second;
1528  }
1529  return nullptr;
1530  }
1531 
1536  void setAddress(std::optional<Addr> A);
1537 
1545  uint64_t getSize() const { return Size; }
1546 
1553  void setSize(uint64_t S);
1554 
1568  uint64_t getInitializedSize() const { return Bytes.size(); }
1569 
1584  void setInitializedSize(uint64_t S) {
1585  Bytes.resize(S);
1586  if (S > getSize()) {
1587  setSize(S);
1588  }
1589  }
1590 
1591 private:
1592  // Wrapper to boost::endian::conditional_reverse which skips the call for
1593  // 1-byte types (char, [un]signed char, [u]int8_t).
1594  // This layer was added to work around a bug in boost 1.67 (fixed as of 1.74)
1595  // which gave wrong results for T=char.
1596  // It also allows BytesReference to work for std::byte.
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);
1601  }
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) {
1605  return From;
1606  }
1607 
1617  template <typename ByteIntervalType, typename T> class BytesReference {
1618  public:
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_) {}
1623 
1629  operator T() const {
1630  assert(I + sizeof(T) <= BI->Size &&
1631  "read into interval's bytes out of bounds!");
1632 
1633  auto S = BI->Bytes.size();
1634 
1635  if (I >= S) {
1636  // anything this far past the end of initialized bytes is composed of
1637  // all zero bytes, so we return what T would have been interpreted as
1638  // if all bytes are zero.
1639  //
1640  // (note that you may be tempted to replace this with "return T{};",
1641  // but beware: T might be a non-scalar type whose default constructor
1642  // differs from the value returned when all bytes are re-interpeted as
1643  // zeroes. A similar argument exists for "return T{0};".)
1644  const std::array<uint8_t, sizeof(T)> Array{};
1645  return *reinterpret_cast<const T*>(Array.data());
1646  }
1647 
1648  if (I + sizeof(T) > S) {
1649  // Here, I < S < I + sizeof(T), so we need to partially fill the
1650  // initialized bytes and combine it with zeroes for the uninitialized
1651  // bytes.
1652  std::array<uint8_t, sizeof(T)> Array{};
1653  // Thanks to math, 0 < S - I < sizeof(T).
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);
1657  }
1658 
1659  return endian_flip(*reinterpret_cast<const T*>(BI->Bytes.data() + I),
1660  InputOrder, OutputOrder);
1661  }
1662 
1669  BytesReference<ByteIntervalType, T>& operator=(const T& rhs) {
1670  assert(I + sizeof(T) <= BI->Size &&
1671  "write into interval's bytes out of bounds!");
1672 
1673  if (I + sizeof(T) > BI->Bytes.size()) {
1674  BI->Bytes.resize(I + sizeof(T));
1675  }
1676 
1677  *reinterpret_cast<T*>(BI->Bytes.data() + I) =
1678  endian_flip(rhs, OutputOrder, InputOrder);
1679  return *this;
1680  }
1681 
1682  ByteIntervalType* BI;
1683  size_t I;
1684  boost::endian::order InputOrder;
1685  boost::endian::order OutputOrder;
1686  };
1687 
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>> {
1699  private:
1700  using self = BytesBaseIterator<ByteIntervalType, T>;
1701 
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_) {}
1706 
1707  public:
1708  using reference = BytesReference<ByteIntervalType, T>;
1709 
1716  BytesBaseIterator() = default;
1717 
1718  // Beginning of functions for iterator facade compatibility.
1719  reference dereference() const {
1720  assert(BI && "attempt to dereference default-constructed byte iterator!");
1721  return reference(BI, I, InputOrder, OutputOrder);
1722  }
1723 
1724  bool equal(const self& other) const {
1725  return BI == other.BI && I == other.I;
1726  }
1727 
1728  void increment() {
1729  assert(BI && "attempt to increment default-constructed byte iterator!");
1730  I += sizeof(T);
1731  }
1732 
1733  void decrement() {
1734  assert(BI && "attempt to decrement default-constructed byte iterator!");
1735  I -= sizeof(T);
1736  }
1737 
1738  void advance(typename self::difference_type n) {
1739  assert(BI && "attempt to advance default-constructed byte iterator!");
1740  I += n * sizeof(T);
1741  }
1742 
1743  typename self::difference_type distance_to(const self& other) const {
1744  return (other.I - I) / sizeof(T);
1745  }
1746  // End of functions for iterator facade compatibility.
1747 
1749  operator BytesBaseIterator<const ByteIntervalType, T>() const {
1750  return BytesBaseIterator<const ByteIntervalType, T>(BI, I, InputOrder,
1751  OutputOrder);
1752  }
1753 
1754  private:
1755  ByteIntervalType* BI{nullptr};
1756  size_t I{0};
1757  boost::endian::order InputOrder{boost::endian::order::native};
1758  boost::endian::order OutputOrder{boost::endian::order::native};
1759 
1760  friend class ByteInterval;
1761  };
1762 
1763 public:
1768  template <typename T>
1769  using bytes_iterator = BytesBaseIterator<ByteInterval, T>;
1774  template <typename T>
1775  using bytes_range = boost::iterator_range<bytes_iterator<T>>;
1780  template <typename T>
1781  using const_bytes_iterator = BytesBaseIterator<const ByteInterval, T>;
1786  template <typename T>
1787  using const_bytes_range = boost::iterator_range<const_bytes_iterator<T>>;
1788 
1793  template <typename T> bytes_iterator<T> bytes_begin() {
1794  return bytes_begin<T>(getBoostEndianOrder());
1795  }
1796 
1804  template <typename T>
1805  bytes_iterator<T>
1806  bytes_begin(boost::endian::order InputOrder,
1807  boost::endian::order OutputOrder = boost::endian::order::native) {
1808  return bytes_iterator<T>(this, 0, InputOrder, OutputOrder);
1809  }
1810 
1815  template <typename T> bytes_iterator<T> bytes_end() {
1816  return bytes_end<T>(getBoostEndianOrder());
1817  }
1818 
1826  template <typename T>
1827  bytes_iterator<T>
1828  bytes_end(boost::endian::order InputOrder,
1829  boost::endian::order OutputOrder = boost::endian::order::native) {
1830  return bytes_iterator<T>(this, Size, InputOrder, OutputOrder);
1831  }
1832 
1837  template <typename T> bytes_range<T> bytes() {
1838  return bytes<T>(getBoostEndianOrder());
1839  }
1840 
1848  template <typename T>
1849  bytes_range<T>
1850  bytes(boost::endian::order InputOrder,
1851  boost::endian::order OutputOrder = boost::endian::order::native) {
1852  return bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
1853  bytes_end<T>(InputOrder, OutputOrder));
1854  }
1855 
1860  template <typename T> const_bytes_iterator<T> bytes_begin() const {
1861  return bytes_begin<T>(getBoostEndianOrder());
1862  }
1863 
1871  template <typename T>
1873  boost::endian::order InputOrder,
1874  boost::endian::order OutputOrder = boost::endian::order::native) const {
1875  return const_bytes_iterator<T>(this, 0, InputOrder, OutputOrder);
1876  }
1877 
1882  template <typename T> const_bytes_iterator<T> bytes_end() const {
1883  return bytes_end<T>(getBoostEndianOrder());
1884  }
1885 
1893  template <typename T>
1895  boost::endian::order InputOrder,
1896  boost::endian::order OutputOrder = boost::endian::order::native) const {
1897  return const_bytes_iterator<T>(this, Size, InputOrder, OutputOrder);
1898  }
1899 
1904  template <typename T> const_bytes_range<T> bytes() const {
1905  return bytes<T>(getBoostEndianOrder());
1906  }
1907 
1915  template <typename T>
1916  const_bytes_range<T>
1917  bytes(boost::endian::order InputOrder,
1918  boost::endian::order OutputOrder = boost::endian::order::native) const {
1919  return const_bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
1920  bytes_end<T>(InputOrder, OutputOrder));
1921  }
1922 
1923 private:
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) {
1945  static_assert(
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>");
1949 
1950  auto N = std::distance(Begin, End) * sizeof(T);
1951  setSize(Size + N);
1952  // If the position to insert is currently outside the initilized bytes,
1953  // we let the iterator's operator= handle resizing the byte vector,
1954  // otherwise we insert zeroes and then overwrite them via said operator=.
1955  if (Pos.I < Bytes.size()) {
1956  Bytes.insert(Bytes.begin() + Pos.I, N, 0);
1957  }
1958  // std::copy calls operator= one time for every element in the input iter.
1959  std::copy(Begin, End,
1960  bytes_iterator<T>(this, Pos.I, VectorOrder, ElementsOrder));
1961  return Pos;
1962  }
1963 
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);
1984  }
1985 
1986 public:
1997  template <typename T>
1999  const T& X) {
2000  return insertBytes<T>(Pos, X, getBoostEndianOrder());
2001  }
2002 
2013  template <typename T>
2015  return insertBytes<T>(Pos, X, getBoostEndianOrder());
2016  }
2017 
2030  template <typename T>
2032  const const_bytes_iterator<T> Pos, const T& X,
2033  boost::endian::order VectorOrder,
2034  boost::endian::order ElementOrder = boost::endian::order::native) {
2035  return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2036  }
2037 
2050  template <typename T>
2052  bytes_iterator<T> Pos, const T& X, boost::endian::order VectorOrder,
2053  boost::endian::order ElementOrder = boost::endian::order::native) {
2054  return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2055  }
2056 
2070 
2071  template <typename T, typename InputIterator>
2073  InputIterator Begin, InputIterator End) {
2074  return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2075  }
2089  template <typename T, typename InputIterator>
2091  InputIterator End) {
2092  return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2093  }
2094 
2110  template <typename T, typename InputIterator>
2112  const const_bytes_iterator<T> Pos, InputIterator Begin, InputIterator End,
2113  boost::endian::order VectorOrder,
2114  boost::endian::order ElementsOrder = boost::endian::order::native) {
2115  return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2116  }
2117 
2133  template <typename T, typename InputIterator>
2135  bytes_iterator<T> Pos, InputIterator Begin, InputIterator End,
2136  boost::endian::order VectorOrder,
2137  boost::endian::order ElementsOrder = boost::endian::order::native) {
2138  return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2139  }
2140 
2150 
2151  template <typename T>
2153  const const_bytes_iterator<T> End) {
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!");
2157 
2158  // If the beginning iter is outside the init vector, nothing need be done.
2159  if (Begin.I < Bytes.size()) {
2160  if (End.I < Bytes.size()) {
2161  // All positions are within the initilized vector.
2162  Bytes.erase(Bytes.begin() + Begin.I, Bytes.begin() + End.I);
2163  } else {
2164  // The beginning is within vector, the end isn't; clamp to
2165  // Bytes.end().
2166  Bytes.erase(Bytes.begin() + Begin.I, Bytes.end());
2167  }
2168  }
2169 
2170  setSize(Size - (End.I - Begin.I));
2171  return Begin;
2172  }
2173 
2184  template <typename T> T* rawBytes() {
2185  return reinterpret_cast<T*>(Bytes.data());
2186  }
2187 
2198  template <typename T> const T* rawBytes() const {
2199  return reinterpret_cast<const T*>(Bytes.data());
2200  }
2201 
2203  static bool classof(const Node* N) {
2204  return N->getKind() == Kind::ByteInterval;
2205  }
2207 
2210  boost::endian::order getBoostEndianOrder() const;
2211 
2212 private:
2213  ByteInterval(Context& C);
2214 
2215  ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2216  const UUID& U);
2217 
2218  ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
2219  uint64_t InitSize);
2220 
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);
2227  }
2228 
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);
2235  }
2236 
2237  void setParent(Section* S, ByteIntervalObserver* O) {
2238  Parent = S;
2239  Observer = O;
2240  }
2241 
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);
2250  }
2251 
2253  using MessageType = proto::ByteInterval;
2254 
2260  void toProtobuf(MessageType* Message) const;
2261 
2268  static ErrorOr<ByteInterval*> fromProtobuf(Context& C,
2269  const MessageType& Message);
2270 
2278  bool symbolicExpressionsFromProtobuf(Context& C, const MessageType& Message);
2279 
2280  // Present for testing purposes only.
2281  void save(std::ostream& Out) const;
2282 
2283  // Present for testing purposes only.
2284  static ByteInterval* load(Context& C, std::istream& In);
2285 
2286  // Present for testing purposes only.
2287  bool loadSymbolicExpressions(Context& C, std::istream& In);
2288 
2289  // Shared implementation for adding CodeBlocks and DataBlocks.
2290  template <typename BlockType, typename IterType>
2291  ChangeStatus addBlock(uint64_t Off, BlockType* B);
2292 
2293  // Shared implementation for removing CodeBlocks and DataBlocks.
2294  template <typename BlockType, typename IterType>
2295  ChangeStatus removeBlock(BlockType* B);
2296 
2297  Section* Parent{nullptr};
2298  ByteIntervalObserver* Observer{nullptr};
2299  std::optional<Addr> Address;
2300  uint64_t Size{0};
2301  BlockSet Blocks;
2302  BlockIntMap BlockOffsets;
2303  SymbolicExpressionMap SymbolicExpressions;
2304  std::vector<uint8_t> Bytes;
2305 
2306  std::unique_ptr<CodeBlockObserver> CBO;
2307  std::unique_ptr<DataBlockObserver> DBO;
2308 
2309  friend class Context; // Friend to enable Context::Create.
2310  friend class Section; // Friend to enable Section::(re)moveByteInterval,
2311  // Create, etc.
2312  friend class CodeBlock; // Friend to enable CodeBlock::getAddress.
2313  friend class DataBlock; // Friend to enable DataBlock::getAddress.
2314  friend class Module; // Allow Module::fromProtobuf to deserialize symbolic
2315  // expressions.
2316  friend struct BlockOffsetLess;
2317  friend class SerializationTestHarness; // Testing support.
2318 };
2319 
2323 
2325 public:
2326  virtual ~ByteIntervalObserver() = default;
2327 
2336  virtual ChangeStatus addCodeBlocks(ByteInterval* BI,
2337  ByteInterval::code_block_range Blocks) = 0;
2338 
2347  virtual ChangeStatus
2348  moveCodeBlocks(ByteInterval* BI, ByteInterval::code_block_range Blocks) = 0;
2349 
2358  virtual ChangeStatus
2359  removeCodeBlocks(ByteInterval* BI, ByteInterval::code_block_range Blocks) = 0;
2360 
2369  virtual ChangeStatus addDataBlocks(ByteInterval* BI,
2370  ByteInterval::data_block_range Blocks) = 0;
2371 
2380  virtual ChangeStatus
2381  moveDataBlocks(ByteInterval* BI, ByteInterval::data_block_range Blocks) = 0;
2382 
2391  virtual ChangeStatus
2392  removeDataBlocks(ByteInterval* BI, ByteInterval::data_block_range Blocks) = 0;
2393 
2404  virtual ChangeStatus
2405  changeExtent(ByteInterval* BI,
2406  std::function<void(ByteInterval*)> Callback) = 0;
2407 };
2408 
2409 } // namespace gtirb
2410 
2411 #endif // GTIRB_BYTE_INTERVAL_H
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C)
Create an unitialized ByteInterval object.
Definition: ByteInterval.hpp:262
gtirb::ByteInterval::eraseBytes
const_bytes_iterator< T > eraseBytes(const const_bytes_iterator< T > Begin, const const_bytes_iterator< T > End)
Erase data from this byte vector.
Definition: ByteInterval.hpp:2152
gtirb::ByteInterval::bytes_iterator
BytesBaseIterator< ByteInterval, T > bytes_iterator
Iterator over bytes.
Definition: ByteInterval.hpp:1769
gtirb::ByteInterval::bytes_begin
const_bytes_iterator< T > bytes_begin() const
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1860
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C, std::optional< Addr > Address, InputIterator Begin, InputIterator End, std::optional< uint64_t > Size=std::nullopt, std::optional< uint64_t > InitSize=std::nullopt)
Create a ByteInterval object.
Definition: ByteInterval.hpp:331
gtirb::ByteInterval::findSymbolicExpressionsAtOffset
const_symbolic_expression_range findSymbolicExpressionsAtOffset(uint64_t Off) const
Find all the symbolic expressions that start at an offset.
Definition: ByteInterval.hpp:1340
gtirb::ByteInterval::removeSymbolicExpression
bool removeSymbolicExpression(uint64_t Off)
Removes a SymbolicExpression at the given offset, if present.
Definition: ByteInterval.hpp:1498
gtirb::CodeBlock
A basic block.
Definition: CodeBlock.hpp:47
gtirb::Context::Create
NodeTy * Create(Args &&... TheArgs)
Create an object of type T.
Definition: Context.hpp:126
gtirb::ByteInterval::findCodeBlocksOn
const_code_block_subrange findCodeBlocksOn(Addr A) const
Find all the code blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:716
gtirb::ByteInterval::insertBytes
const_bytes_iterator< T > insertBytes(const const_bytes_iterator< T > Pos, InputIterator Begin, InputIterator End, boost::endian::order VectorOrder, boost::endian::order ElementsOrder=boost::endian::order::native)
Insert data into this byte vector.
Definition: ByteInterval.hpp:2111
gtirb::Node
Represents the base of the Node class hierarchy.
Definition: Node.hpp:39
gtirb::ByteInterval::findDataBlocksAt
data_block_range findDataBlocksAt(Addr A)
Find all the data blocks that start at an address.
Definition: ByteInterval.hpp:1014
gtirb::ByteInterval::addBlock
BlockType * addBlock(Context &C, uint64_t O, Args &&... A)
Creates a new Block of the given type at a given offset.
Definition: ByteInterval.hpp:1453
gtirb::ByteInterval::bytes_end
bytes_iterator< T > bytes_end()
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1815
gtirb::ByteInterval::code_blocks
const_code_block_range code_blocks() const
Return a const range of the CodeBlock objects in this interval.
Definition: ByteInterval.hpp:661
gtirb::ByteInterval::findBlocksAtOffset
const_block_range findBlocksAtOffset(uint64_t Low, uint64_t High) const
Find all the blocks that start between a range of offsets.
Definition: ByteInterval.hpp:545
gtirb::ByteInterval::findCodeBlocksAt
const_code_block_range findCodeBlocksAt(Addr Low, Addr High) const
Find all the code blocks that start between a range of addresses.
Definition: ByteInterval.hpp:831
gtirb::ByteInterval::const_code_block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< const CodeBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::CodeBlock >, boost::indirect_iterator< BlockIntMap::codomain_type::const_iterator > >> > const_code_block_subrange
Const sub-range of code blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:631
gtirb::ByteInterval::symbolic_expressions
symbolic_expression_range symbolic_expressions()
Return a range of the SymbolicExpression objects in this interval.
Definition: ByteInterval.hpp:1242
gtirb::ByteInterval::bytes
const_bytes_range< T > bytes() const
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1904
gtirb::ByteInterval::bytes_end
bytes_iterator< T > bytes_end(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1828
gtirb::ByteInterval::findSymbolicExpressionsAtOffset
const_symbolic_expression_range findSymbolicExpressionsAtOffset(uint64_t Low, uint64_t High) const
Find all the symbolic expressions that start between a range of offsets.
Definition: ByteInterval.hpp:1360
gtirb::UUID
boost::uuids::uuid UUID
Represents a universally unique identifier used to identify Node objects across serialization boundar...
Definition: Context.hpp:36
gtirb::Addr
A special class to store an Effective Address.
Definition: Addr.hpp:37
gtirb::ByteInterval::addSymbolicExpression
SymbolicExpression & addSymbolicExpression(uint64_t Off, Args... A)
Adds a new SymbolicExpression to this interval.
Definition: ByteInterval.hpp:1485
gtirb::ByteInterval::const_code_block_iterator
boost::transform_iterator< BlockToNode< const CodeBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::CodeBlock >, BlockSet::index< by_offset >::type::const_iterator > > const_code_block_iterator
Const iterator over CodeBlock objects.
Definition: ByteInterval.hpp:613
gtirb::ByteInterval::const_data_block_range
boost::iterator_range< const_data_block_iterator > const_data_block_range
Const range of DataBlock objects.
Definition: ByteInterval.hpp:876
gtirb::ByteInterval::findCodeBlocksAtOffset
code_block_range findCodeBlocksAtOffset(uint64_t Low, uint64_t High)
Find all the code blocks that start between a range of offsets.
Definition: ByteInterval.hpp:743
gtirb::const_block_iterator
cfg_node_cast_iter< const CodeBlock > const_block_iterator
Constant iterator over blocks (Block).
Definition: CFG.hpp:198
gtirb::ByteInterval::blocks_begin
block_iterator blocks_begin()
Return an iterator to the first Block.
Definition: ByteInterval.hpp:394
gtirb::ByteInterval::bytes
bytes_range< T > bytes(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1850
gtirb::ByteInterval::code_blocks_begin
const_code_block_iterator code_blocks_begin() const
Return a const iterator to the first CodeBlock.
Definition: ByteInterval.hpp:639
gtirb::DataBlock
Represents a data object, possibly symbolic.
Definition: DataBlock.hpp:44
gtirb::ByteInterval::blocks_end
block_iterator blocks_end()
Return an iterator to the element following the last Block.
Definition: ByteInterval.hpp:400
gtirb::ByteInterval::data_blocks
data_block_range data_blocks()
Return a range of the DataBlock objects in this interval.
Definition: ByteInterval.hpp:913
gtirb::Context
The context under which GTIRB operations occur.
Definition: Context.hpp:63
gtirb::ByteInterval::const_block_range
boost::iterator_range< const_block_iterator > const_block_range
Const range of Block objects.
Definition: ByteInterval.hpp:384
Node.hpp
Class gtirb::Node.
gtirb::ByteInterval::code_blocks_begin
code_block_iterator code_blocks_begin()
Return an iterator to the first CodeBlock.
Definition: ByteInterval.hpp:634
gtirb::ByteInterval::getAddress
std::optional< Addr > getAddress() const
Get the fixed address of this interval, if present.
Definition: ByteInterval.hpp:352
gtirb::ByteInterval::setInitializedSize
void setInitializedSize(uint64_t S)
Set the number of initialized bytes in this interval.
Definition: ByteInterval.hpp:1584
gtirb::ByteInterval::findDataBlocksAtOffset
data_block_range findDataBlocksAtOffset(uint64_t Low, uint64_t High)
Find all the data blocks that start between a range of offsets.
Definition: ByteInterval.hpp:1000
gtirb::ByteInterval::data_block_range
boost::iterator_range< data_block_iterator > data_block_range
Range of DataBlock objects.
Definition: ByteInterval.hpp:852
gtirb::ByteInterval::findDataBlocksOnOffset
const_data_block_subrange findDataBlocksOnOffset(uint64_t Off) const
Find all the data blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:943
gtirb::ByteInterval::bytes_range
boost::iterator_range< bytes_iterator< T > > bytes_range
Range over bytes.
Definition: ByteInterval.hpp:1775
gtirb::ByteInterval::findDataBlocksAtOffset
const_data_block_range findDataBlocksAtOffset(uint64_t Low, uint64_t High) const
Find all the data blocks that start between a range of offsets.
Definition: ByteInterval.hpp:1057
gtirb::ByteInterval::code_blocks_end
const_code_block_iterator code_blocks_end() const
Return a const iterator to the element following the last CodeBlock.
Definition: ByteInterval.hpp:651
gtirb::ByteInterval::bytes_begin
bytes_iterator< T > bytes_begin(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1806
gtirb::ByteInterval::findSymbolicExpressionsAtOffset
symbolic_expression_range findSymbolicExpressionsAtOffset(uint64_t Low, uint64_t High)
Find all the symbolic expressions that start between a range of offsets.
Definition: ByteInterval.hpp:1282
gtirb::Section
Represents a named section of the binary.
Definition: Section.hpp:66
gtirb::ByteInterval::insertBytes
bytes_iterator< T > insertBytes(bytes_iterator< T > Pos, InputIterator Begin, InputIterator End, boost::endian::order VectorOrder, boost::endian::order ElementsOrder=boost::endian::order::native)
Insert data into this byte vector.
Definition: ByteInterval.hpp:2134
gtirb::ByteInterval::rawBytes
T * rawBytes()
Return the raw data underlying this byte vector.
Definition: ByteInterval.hpp:2184
gtirb::ByteInterval::findDataBlocksAt
const_data_block_range findDataBlocksAt(Addr Low, Addr High) const
Find all the data blocks that start between a range of addresses.
Definition: ByteInterval.hpp:1088
gtirb::ByteInterval::findSymbolicExpressionsAt
symbolic_expression_range findSymbolicExpressionsAt(Addr Low, Addr High)
Find all the symbolic expressions that start between a range of addresses.
Definition: ByteInterval.hpp:1320
gtirb::Offset
Describes a location inside a node (byte interval, block, etc).
Definition: Offset.hpp:32
gtirb::ByteInterval::findSymbolicExpressionsAt
const_symbolic_expression_range findSymbolicExpressionsAt(Addr A) const
Find all the symbolic expressions that start at an address.
Definition: ByteInterval.hpp:1381
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::key
static key_type key(const SymbolicExpressionElementBase< ByteIntervalType > &SEE)
Definition: ByteInterval.hpp:1141
gtirb::ByteInterval::findDataBlocksAt
const_data_block_range findDataBlocksAt(Addr A) const
Find all the data blocks that start at an address.
Definition: ByteInterval.hpp:1074
gtirb::ByteInterval::data_blocks_begin
const_data_block_iterator data_blocks_begin() const
Return a const iterator to the first DataBlock.
Definition: ByteInterval.hpp:896
gtirb::SymAttribute::S
@ S
gtirb::ByteIntervalObserver
Interface for notifying observers when the ByteInterval is modified.
Definition: ByteInterval.hpp:2324
GTIRB_EXPORT_API
#define GTIRB_EXPORT_API
This macro controls the visibility of exported symbols (i.e. classes) in shared libraries....
Definition: Export.hpp:52
gtirb::ByteInterval::findBlocksOnOffset
block_subrange findBlocksOnOffset(uint64_t Off)
Find all the blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:421
gtirb::ByteInterval::symbolic_expressions_end
symbolic_expression_iterator symbolic_expressions_end()
Return an iterator to the element following the last SymbolicExpression.
Definition: ByteInterval.hpp:1228
gtirb::ByteInterval::data_blocks
const_data_block_range data_blocks() const
Return a const range of the DataBlock objects in this interval.
Definition: ByteInterval.hpp:918
gtirb::ByteInterval::code_blocks_end
code_block_iterator code_blocks_end()
Return an iterator to the element following the last CodeBlock.
Definition: ByteInterval.hpp:645
gtirb
Main namespace for the GTIRB API.
Definition: Addr.hpp:28
gtirb::ByteInterval::findBlocksOn
block_subrange findBlocksOn(Addr A)
Find all the blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:448
gtirb::ByteInterval::findDataBlocksOn
data_block_subrange findDataBlocksOn(Addr A)
Find all the data blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:960
gtirb::ByteInterval::getSize
uint64_t getSize() const
Get the size of this interval in bytes.
Definition: ByteInterval.hpp:1545
Export.hpp
gtirb::ByteInterval::const_block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< const Node >, BlockIntMap::codomain_type::const_iterator > > const_block_subrange
Const sub-range of blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:391
gtirb::ByteInterval::findBlocksAt
block_range findBlocksAt(Addr A)
Find all the blocks that start at an address.
Definition: ByteInterval.hpp:502
gtirb::ByteInterval::const_block_iterator
boost::transform_iterator< BlockToNode< const Node >, BlockSet::index< by_offset >::type::const_iterator > const_block_iterator
Const iterator over Block objects.
Definition: ByteInterval.hpp:379
gtirb::ByteInterval::findBlocksAt
const_block_range findBlocksAt(Addr Low, Addr High) const
Find all the blocks that start between a range of addresses.
Definition: ByteInterval.hpp:574
gtirb::ByteInterval::rawBytes
const T * rawBytes() const
Return the raw data underlying this byte vector.
Definition: ByteInterval.hpp:2198
gtirb::block_iterator
cfg_node_cast_iter< CodeBlock > block_iterator
Iterator over blocks (Block).
Definition: CFG.hpp:194
gtirb::ByteInterval::insertBytes
const_bytes_iterator< T > insertBytes(const const_bytes_iterator< T > Pos, InputIterator Begin, InputIterator End)
Insert data into this byte vector.
Definition: ByteInterval.hpp:2072
gtirb::ByteInterval::bytes_end
const_bytes_iterator< T > bytes_end() const
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1882
gtirb::ByteInterval::SymbolicExpressionElement
SymbolicExpressionElementBase< ByteInterval > SymbolicExpressionElement
A symbolic expression paired with the information needed to look up or alter the symbolic expression ...
Definition: ByteInterval.hpp:1184
gtirb::ByteInterval::findBlocksAtOffset
const_block_range findBlocksAtOffset(uint64_t Off) const
Find all the blocks that start at an offset.
Definition: ByteInterval.hpp:532
gtirb::ByteInterval::bytes_begin
const_bytes_iterator< T > bytes_begin(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native) const
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1872
gtirb::ByteInterval::findBlocksAtOffset
block_range findBlocksAtOffset(uint64_t Low, uint64_t High)
Find all the blocks that start between a range of offsets.
Definition: ByteInterval.hpp:488
gtirb::ByteInterval::const_bytes_iterator
BytesBaseIterator< const ByteInterval, T > const_bytes_iterator
Const iterator over bytes.
Definition: ByteInterval.hpp:1781
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C, std::optional< Addr > Address, uint64_t Size=0, std::optional< uint64_t > InitSize=std::nullopt)
Create a ByteInterval object.
Definition: ByteInterval.hpp:285
gtirb::ByteInterval::data_blocks_begin
data_block_iterator data_blocks_begin()
Return an iterator to the first DataBlock.
Definition: ByteInterval.hpp:891
gtirb::ByteInterval::findBlocksOn
const_block_subrange findBlocksOn(Addr A) const
Find all the blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:462
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess
A comparison function object to order symbolic expression elements by the address in which they occur...
Definition: ByteInterval.hpp:1138
gtirb::ByteInterval::bytes_begin
bytes_iterator< T > bytes_begin()
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1793
gtirb::DecodeMode
DecodeMode
Variations on decoding a particular ISA.
Definition: DecodeMode.hpp:26
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C, InputIterator Begin, InputIterator End, std::optional< uint64_t > Size=std::nullopt, std::optional< uint64_t > InitSize=std::nullopt)
Create a ByteInterval object.
Definition: ByteInterval.hpp:306
gtirb::ByteInterval::data_block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< DataBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::DataBlock >, boost::indirect_iterator< BlockIntMap::codomain_type::iterator > >> > data_block_subrange
Sub-range of data blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:862
gtirb::ChangeStatus::Accepted
@ Accepted
gtirb::ByteInterval::symbolic_expressions_begin
symbolic_expression_iterator symbolic_expressions_begin()
Return an iterator to the first SymbolicExpression.
Definition: ByteInterval.hpp:1215
gtirb::ByteInterval::findCodeBlocksAt
const_code_block_range findCodeBlocksAt(Addr A) const
Find all the code blocks that start at an address.
Definition: ByteInterval.hpp:817
gtirb::ByteInterval::insertBytes
bytes_iterator< T > insertBytes(bytes_iterator< T > Pos, const T &X)
Insert a single datum into this byte vector.
Definition: ByteInterval.hpp:2014
gtirb::ByteInterval::symbolic_expression_iterator
boost::transform_iterator< SymExprPairToElement< SymbolicExpressionElement >, SymbolicExpressionMap::iterator > symbolic_expression_iterator
Iterator over SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1196
gtirb::ByteInterval::findBlocksAt
const_block_range findBlocksAt(Addr A) const
Find all the blocks that start at an address.
Definition: ByteInterval.hpp:559
gtirb::ByteInterval::findSymbolicExpressionsAt
const_symbolic_expression_range findSymbolicExpressionsAt(Addr Low, Addr High) const
Find all the symbolic expressions that start between a range of addresses.
Definition: ByteInterval.hpp:1397
gtirb::ByteInterval::blocks
block_range blocks()
Return a range of the Block objects in this interval.
Definition: ByteInterval.hpp:407
gtirb::ByteInterval::const_code_block_range
boost::iterator_range< const_code_block_iterator > const_code_block_range
Const range of CodeBlock objects.
Definition: ByteInterval.hpp:619
gtirb::ByteInterval::data_blocks_end
const_data_block_iterator data_blocks_end() const
Return a const iterator to the element following the last DataBlock.
Definition: ByteInterval.hpp:908
gtirb::ByteInterval::const_symbolic_expression_iterator
boost::transform_iterator< SymExprPairToElement< ConstSymbolicExpressionElement >, SymbolicExpressionMap::const_iterator > const_symbolic_expression_iterator
Const iterator over SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1207
gtirb::ByteInterval::code_blocks
code_block_range code_blocks()
Return a range of the CodeBlock objects in this interval.
Definition: ByteInterval.hpp:656
gtirb::ByteInterval::findCodeBlocksAtOffset
const_code_block_range findCodeBlocksAtOffset(uint64_t Off) const
Find all the code blocks that start at an offset.
Definition: ByteInterval.hpp:785
DecodeMode.hpp
gtirb::ByteInterval::findDataBlocksAt
data_block_range findDataBlocksAt(Addr Low, Addr High)
Find all the data blocks that start between a range of addresses.
Definition: ByteInterval.hpp:1028
gtirb::ByteInterval::bytes
const_bytes_range< T > bytes(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native) const
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1917
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::key_type
std::optional< Addr > key_type
Definition: ByteInterval.hpp:1139
gtirb::ByteInterval::addSymbolicExpression
SymbolicExpression & addSymbolicExpression(uint64_t Off, const SymbolicExpression &SymExpr)
Adds a new SymbolicExpression to this interval.
Definition: ByteInterval.hpp:1470
gtirb::ByteInterval::findSymbolicExpressionsAt
symbolic_expression_range findSymbolicExpressionsAt(Addr A)
Find all the symbolic expressions that start at an address.
Definition: ByteInterval.hpp:1304
gtirb::ByteInterval::findDataBlocksOn
const_data_block_subrange findDataBlocksOn(Addr A) const
Find all the data blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:973
gtirb::ByteInterval::bytes_end
const_bytes_iterator< T > bytes_end(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native) const
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1894
gtirb::ByteInterval::getSection
const Section * getSection() const
Get the Section this byte interval belongs to.
Definition: ByteInterval.hpp:343
gtirb::ByteInterval::code_block_range
boost::iterator_range< code_block_iterator > code_block_range
Range of CodeBlock objects.
Definition: ByteInterval.hpp:595
gtirb::ByteInterval::getSymbolicExpression
SymbolicExpression * getSymbolicExpression(uint64_t Off)
Get the symbolic expression at the given offset, if present.
Definition: ByteInterval.hpp:1510
gtirb::ByteInterval::symbolic_expression_range
boost::iterator_range< symbolic_expression_iterator > symbolic_expression_range
Range of SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1201
gtirb::ByteInterval::ConstSymbolicExpressionElement
SymbolicExpressionElementBase< const ByteInterval > ConstSymbolicExpressionElement
A symbolic expression paired with the information needed to look up or alter the symbolic expression ...
Definition: ByteInterval.hpp:1189
gtirb::ByteInterval::getSection
Section * getSection()
Get the Section this byte interval belongs to.
Definition: ByteInterval.hpp:341
gtirb::ByteInterval::block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< Node >, BlockIntMap::codomain_type::iterator > > block_subrange
Sub-range of blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:372
gtirb::ByteInterval::data_block_iterator
boost::transform_iterator< BlockToNode< DataBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::DataBlock >, BlockSet::index< by_offset >::type::iterator > > data_block_iterator
Iterator over DataBlock objects.
Definition: ByteInterval.hpp:847
gtirb::CodeBlockObserver
Interface for notifying observers when a CodeBlock is modified.
Definition: ByteInterval.hpp:68
gtirb::ByteInterval::symbolic_expressions_begin
const_symbolic_expression_iterator symbolic_expressions_begin() const
Return a const iterator to the first SymbolicExpression.
Definition: ByteInterval.hpp:1221
gtirb::ByteInterval::findCodeBlocksOnOffset
const_code_block_subrange findCodeBlocksOnOffset(uint64_t Off) const
Find all the code blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:686
gtirb::ByteInterval::code_block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< CodeBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::CodeBlock >, boost::indirect_iterator< BlockIntMap::codomain_type::iterator > >> > code_block_subrange
Sub-range of code blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:605
gtirb::ByteInterval::const_data_block_iterator
boost::transform_iterator< BlockToNode< const DataBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::DataBlock >, BlockSet::index< by_offset >::type::const_iterator > > const_data_block_iterator
Const iterator over DataBlock objects.
Definition: ByteInterval.hpp:870
gtirb::Module
Represents a single binary (library or executable).
Definition: Module.hpp:107
gtirb::ByteInterval::findDataBlocksAtOffset
const_data_block_range findDataBlocksAtOffset(uint64_t Off) const
Find all the data blocks that start at an offset.
Definition: ByteInterval.hpp:1042
gtirb::ByteInterval::const_symbolic_expression_range
boost::iterator_range< const_symbolic_expression_iterator > const_symbolic_expression_range
Const range of SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1212
gtirb::ByteInterval::bytes
bytes_range< T > bytes()
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1837
gtirb::ByteInterval::blocks_begin
const_block_iterator blocks_begin() const
Return a const iterator to the first Block.
Definition: ByteInterval.hpp:396
gtirb::ByteInterval::block_iterator
boost::transform_iterator< BlockToNode< Node >, BlockSet::index< by_offset >::type::iterator > block_iterator
Iterator over Block objects.
Definition: ByteInterval.hpp:361
gtirb::ByteInterval::findCodeBlocksAt
code_block_range findCodeBlocksAt(Addr A)
Find all the code blocks that start at an address.
Definition: ByteInterval.hpp:757
gtirb::ByteInterval::getInitializedSize
uint64_t getInitializedSize() const
Get the number of initialized bytes in this interval.
Definition: ByteInterval.hpp:1568
gtirb::ByteInterval::blocks_end
const_block_iterator blocks_end() const
Return a const iterator to the element following the last Block.
Definition: ByteInterval.hpp:403
gtirb::ByteInterval
A contiguous region of bytes in a binary.
Definition: ByteInterval.hpp:124
Observer.hpp
gtirb::ByteInterval::findDataBlocksAtOffset
data_block_range findDataBlocksAtOffset(uint64_t Off)
Find all the data blocks that start at an offset.
Definition: ByteInterval.hpp:985
gtirb::ByteInterval::getSymbolicExpression
const SymbolicExpression * getSymbolicExpression(uint64_t Off) const
Get the symbolic expression at the given offset, if present.
Definition: ByteInterval.hpp:1524
gtirb::ByteInterval::findCodeBlocksOnOffset
code_block_subrange findCodeBlocksOnOffset(uint64_t Off)
Find all the code blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:670
gtirb::ByteInterval::blocks
const_block_range blocks() const
Return a const range of the Block objects in this interval.
Definition: ByteInterval.hpp:411
gtirb::ByteInterval::findCodeBlocksAtOffset
const_code_block_range findCodeBlocksAtOffset(uint64_t Low, uint64_t High) const
Find all the code blocks that start between a range of offsets.
Definition: ByteInterval.hpp:800
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C, uint64_t Size, std::optional< uint64_t > InitSize=std::nullopt)
Create a ByteInterval object.
Definition: ByteInterval.hpp:271
gtirb::ByteInterval::block_range
boost::iterator_range< block_iterator > block_range
Range of Block objects.
Definition: ByteInterval.hpp:366
gtirb::ByteInterval::insertBytes
bytes_iterator< T > insertBytes(bytes_iterator< T > Pos, const T &X, boost::endian::order VectorOrder, boost::endian::order ElementOrder=boost::endian::order::native)
Insert a single datum into this byte vector.
Definition: ByteInterval.hpp:2051
gtirb::ByteInterval::const_bytes_range
boost::iterator_range< const_bytes_iterator< T > > const_bytes_range
Const range over bytes.
Definition: ByteInterval.hpp:1787
gtirb::ByteInterval::insertBytes
const_bytes_iterator< T > insertBytes(const const_bytes_iterator< T > Pos, const T &X, boost::endian::order VectorOrder, boost::endian::order ElementOrder=boost::endian::order::native)
Insert a single datum into this byte vector.
Definition: ByteInterval.hpp:2031
gtirb::ByteInterval::symbolic_expressions_end
const_symbolic_expression_iterator symbolic_expressions_end() const
Return a const iterator to the element following the last SymbolicExpression.
Definition: ByteInterval.hpp:1235
gtirb::ByteInterval::findBlocksOnOffset
const_block_subrange findBlocksOnOffset(uint64_t Off) const
Find all the blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:434
gtirb::ByteInterval::insertBytes
const_bytes_iterator< T > insertBytes(const const_bytes_iterator< T > Pos, const T &X)
Insert a single datum into this byte vector.
Definition: ByteInterval.hpp:1998
gtirb::ByteInterval::findBlocksAt
block_range findBlocksAt(Addr Low, Addr High)
Find all the blocks that start between a range of addresses.
Definition: ByteInterval.hpp:517
SymbolicExpression.hpp
Types and operations for symbolic expressions.
gtirb::ByteInterval::symbolic_expressions
const_symbolic_expression_range symbolic_expressions() const
Return a const range of the SymbolicExpression objects in this interval.
Definition: ByteInterval.hpp:1248
gtirb::ByteInterval::const_data_block_subrange
boost::iterator_range< boost::transform_iterator< BlockToNode< const DataBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::DataBlock >, boost::indirect_iterator< BlockIntMap::codomain_type::const_iterator > >> > const_data_block_subrange
Const sub-range of data blocks overlapping an address or range of addreses.
Definition: ByteInterval.hpp:888
gtirb::ByteInterval::findBlocksAtOffset
block_range findBlocksAtOffset(uint64_t Off)
Find all the blocks that start at an offset.
Definition: ByteInterval.hpp:475
gtirb::ByteInterval::code_block_iterator
boost::transform_iterator< BlockToNode< CodeBlock >, boost::filter_iterator< BlockKindEquals< Node::Kind::CodeBlock >, BlockSet::index< by_offset >::type::iterator > > code_block_iterator
Iterator over CodeBlock objects.
Definition: ByteInterval.hpp:590
gtirb::ChangeStatus
ChangeStatus
Definition: Observer.hpp:19
gtirb::ErrorOr
Definition: ByteInterval.hpp:62
gtirb::DataBlockObserver
Interface for notifying observers when a DataBlock is modified.
Definition: ByteInterval.hpp:94
gtirb::ByteInterval::findSymbolicExpressionsAtOffset
symbolic_expression_range findSymbolicExpressionsAtOffset(uint64_t Off)
Find all the symbolic expressions that start at an offset.
Definition: ByteInterval.hpp:1264
gtirb::ByteInterval::insertBytes
bytes_iterator< T > insertBytes(bytes_iterator< T > Pos, InputIterator Begin, InputIterator End)
Insert data into this byte vector.
Definition: ByteInterval.hpp:2090
gtirb::ByteInterval::findDataBlocksOnOffset
data_block_subrange findDataBlocksOnOffset(uint64_t Off)
Find all the data blocks that have a byte at the specified offset.
Definition: ByteInterval.hpp:927
gtirb::ByteInterval::findCodeBlocksOn
code_block_subrange findCodeBlocksOn(Addr A)
Find all the code blocks that have bytes that lie within the address specified.
Definition: ByteInterval.hpp:703
Utility.hpp
gtirb::ByteInterval::findCodeBlocksAtOffset
code_block_range findCodeBlocksAtOffset(uint64_t Off)
Find all the code blocks that start at an offset.
Definition: ByteInterval.hpp:728
gtirb::ByteInterval::data_blocks_end
data_block_iterator data_blocks_end()
Return an iterator to the element following the last DataBlock.
Definition: ByteInterval.hpp:902
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::operator()
bool operator()(const SymbolicExpressionElementBase< ByteIntervalType > &SEE1, const SymbolicExpressionElementBase< ByteIntervalType > &SEE2) const
Definition: ByteInterval.hpp:1147
gtirb::SymbolicExpression
std::variant< SymAddrConst, SymAddrAddr > SymbolicExpression
A symbolic expression.
Definition: SymbolicExpression.hpp:166
gtirb::ByteInterval::findCodeBlocksAt
code_block_range findCodeBlocksAt(Addr Low, Addr High)
Find all the code blocks that start between a range of addresses.
Definition: ByteInterval.hpp:771