GTIRB  v2.1.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/Export.hpp>
20 #include <gtirb/Node.hpp>
21 #include <gtirb/Observer.hpp>
23 #include <array>
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>
38 #include <cstdint>
39 #include <functional>
40 #include <map>
41 #include <optional>
42 #include <type_traits>
43 #include <variant>
44 #include <vector>
45 
48 
49 namespace gtirb {
50 namespace proto {
51 class ByteInterval;
52 } // namespace proto
53 
54 class Section; // Forward declared for the backpointer.
55 class CodeBlock; // Forward declared so Blocks can store CodeBlocks.
56 class DataBlock; // Forward declared so Blocks can store DataBlocks.
57 class ByteIntervalObserver;
58 
59 template <class T> class ErrorOr;
60 
64 
66 public:
67  virtual ~CodeBlockObserver() = default;
68 
78  virtual ChangeStatus sizeChange(CodeBlock* B, uint64_t OldSize,
79  uint64_t NewSize) = 0;
80 };
81 
85 
87 public:
88  virtual ~DataBlockObserver() = default;
89 
99  virtual ChangeStatus sizeChange(DataBlock* B, uint64_t OldSize,
100  uint64_t NewSize) = 0;
101 };
102 
121  struct Block {
122  uint64_t Offset;
123  gtirb::Node* Node;
124 
125  Block(uint64_t Off, gtirb::Node* N) : Offset(Off), Node(N) {}
126 
129  uint64_t getOffset() const { return Offset; }
130 
137  gtirb::Node* getNode() const { return Node; }
138  };
139 
147  template <Node::Kind K> struct BlockKindEquals {
148  bool operator()(const Block& B) const {
149  return B.getNode()->getKind() == K;
150  }
151  };
152 
156  template <typename NodeType> struct BlockToNode {
157  BlockToNode() {}
158 
160  BlockToNode(const BlockToNode<std::remove_const_t<NodeType>>&) {}
161 
162  BlockToNode& operator=(const BlockToNode<std::remove_const_t<NodeType>>&) {
163  return *this;
164  }
165 
166  NodeType& operator()(const Block& B) const {
167  // We avoid the call to cast() here because we use this function after
168  // BlockKindEquals, which confirms the type of the Node for us
169  // (and more importantly, we avoid having to include Code/DataBlock).
170  return *reinterpret_cast<NodeType*>(B.Node);
171  }
172 
173  NodeType& operator()(const Block* B) const { return *B->Node; }
174  };
175 
176  struct OffsetLess {
177  bool operator()(const Block* b1, const Block* b2) const;
178  };
179 
180  struct by_offset {};
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,
187  &Block::getOffset>>,
188  boost::multi_index::hashed_unique<
189  boost::multi_index::tag<by_pointer>,
190  boost::multi_index::const_mem_fun<Block, Node*,
191  &Block::getNode>>>>;
192  using BlockIntMap =
193  boost::icl::interval_map<uint64_t,
194  std::multiset<const Block*, OffsetLess>>;
195  using SymbolicExpressionMap = std::map<uint64_t, SymbolicExpression>;
196 
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");
203  return *It;
204  }
205 
206  class CodeBlockObserverImpl;
207  class DataBlockObserverImpl;
208 
209  ChangeStatus sizeChange(Node* N, uint64_t OldSize, uint64_t NewSize);
210 
211 public:
215  static ByteInterval* Create(Context& C) { return C.Create<ByteInterval>(C); }
216 
224  static ByteInterval* Create(Context& C, uint64_t Size,
225  std::optional<uint64_t> InitSize = std::nullopt) {
226  return C.Create<ByteInterval>(C, std::nullopt, Size,
227  InitSize.value_or(Size));
228  }
229 
238  static ByteInterval* Create(Context& C, std::optional<Addr> Address,
239  uint64_t Size = 0,
240  std::optional<uint64_t> InitSize = std::nullopt) {
241  return C.Create<ByteInterval>(C, Address, Size, InitSize.value_or(Size));
242  }
243 
258  template <typename InputIterator>
259  static ByteInterval* Create(Context& C, InputIterator Begin,
260  InputIterator End,
261  std::optional<uint64_t> Size = std::nullopt,
262  std::optional<uint64_t> InitSize = std::nullopt) {
263  return C.Create<ByteInterval>(
264  C, std::nullopt, Size ? *Size : std::distance(Begin, End),
265  InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
266  }
267 
283  template <typename InputIterator>
284  static ByteInterval* Create(Context& C, std::optional<Addr> Address,
285  InputIterator Begin, InputIterator End,
286  std::optional<uint64_t> Size = std::nullopt,
287  std::optional<uint64_t> InitSize = std::nullopt) {
288  return C.Create<ByteInterval>(
289  C, Address, Size ? *Size : std::distance(Begin, End),
290  InitSize ? *InitSize : std::distance(Begin, End), Begin, End);
291  }
292 
294  Section* getSection() { return Parent; }
296  const Section* getSection() const { return Parent; }
297 
305  std::optional<Addr> getAddress() const { return Address; }
306 
311  using block_iterator =
312  boost::transform_iterator<BlockToNode<Node>,
313  BlockSet::index<by_offset>::type::iterator>;
318  using block_range = boost::iterator_range<block_iterator>;
323  using block_subrange = boost::iterator_range<boost::transform_iterator<
324  BlockToNode<Node>, BlockIntMap::codomain_type::iterator>>;
329  using const_block_iterator = boost::transform_iterator<
330  BlockToNode<const Node>,
331  BlockSet::index<by_offset>::type::const_iterator>;
336  using const_block_range = boost::iterator_range<const_block_iterator>;
342  using const_block_subrange = boost::iterator_range<boost::transform_iterator<
343  BlockToNode<const Node>, BlockIntMap::codomain_type::const_iterator>>;
344 
346  block_iterator blocks_begin() { return block_iterator(Blocks.begin()); }
349  return const_block_iterator(Blocks.begin());
350  }
352  block_iterator blocks_end() { return block_iterator(Blocks.end()); }
356  return const_block_iterator(Blocks.end());
357  }
360  return boost::make_iterator_range(blocks_begin(), blocks_end());
361  }
364  return boost::make_iterator_range(blocks_begin(), blocks_end());
365  }
366 
374  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
375  return block_subrange(It->second.begin(), It->second.end());
376  }
377  return {};
378  }
379 
387  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
388  return const_block_subrange(It->second.begin(), It->second.end());
389  }
390  return {};
391  }
392 
401  if (Address) {
402  return findBlocksOnOffset(A - *Address);
403  }
404  return {};
405  }
406 
415  if (Address) {
416  return findBlocksOnOffset(A - *Address);
417  }
418  return {};
419  }
420 
428  auto Pair = Blocks.get<by_offset>().equal_range(Off);
429  return boost::make_iterator_range(block_iterator(Pair.first),
430  block_iterator(Pair.second));
431  }
432 
440  block_range findBlocksAtOffset(uint64_t Low, uint64_t High) {
441  auto& Index = Blocks.get<by_offset>();
442  auto LowIt = Index.lower_bound(Low);
443  auto HighIt = Index.lower_bound(std::max(Low, High));
444  return boost::make_iterator_range(block_iterator(LowIt),
445  block_iterator(HighIt));
446  }
447 
455  if (!Address || A < *Address) {
456  // Return an empty range without default-constructing the iterators.
457  return findBlocksAtOffset(0, 0);
458  }
459  return findBlocksAtOffset(A - *Address);
460  }
461 
470  if (!Address) {
471  // Return an empty range without default-constructing the iterators.
472  return findBlocksAtOffset(0, 0);
473  }
474  return findBlocksAtOffset(Low - std::min(*Address, Low),
475  High - std::min(*Address, High));
476  }
477 
484  const_block_range findBlocksAtOffset(uint64_t Off) const {
485  auto Pair = Blocks.get<by_offset>().equal_range(Off);
486  return boost::make_iterator_range(const_block_iterator(Pair.first),
487  const_block_iterator(Pair.second));
488  }
489 
497  const_block_range findBlocksAtOffset(uint64_t Low, uint64_t High) const {
498  auto& Index = Blocks.get<by_offset>();
499  auto LowIt = Index.lower_bound(Low);
500  auto HighIt = Index.lower_bound(std::max(Low, High));
501  return boost::make_iterator_range(const_block_iterator(LowIt),
502  const_block_iterator(HighIt));
503  }
504 
512  if (!Address || A < *Address) {
513  // Return an empty range without default-constructing the iterators.
514  return findBlocksAtOffset(0, 0);
515  }
516  return findBlocksAtOffset(A - *Address);
517  }
518 
527  if (!Address) {
528  // Return an empty range without default-constructing the iterators.
529  return findBlocksAtOffset(0, 0);
530  }
531  return findBlocksAtOffset(Low - std::min(*Address, Low),
532  High - std::min(*Address, High));
533  }
534 
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>>;
547  using code_block_range = boost::iterator_range<code_block_iterator>;
553  using code_block_subrange = boost::iterator_range<boost::transform_iterator<
554  BlockToNode<CodeBlock>,
555  boost::filter_iterator<
556  BlockKindEquals<Node::Kind::CodeBlock>,
557  boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
562  using const_code_block_iterator = boost::transform_iterator<
563  BlockToNode<const CodeBlock>,
564  boost::filter_iterator<BlockKindEquals<Node::Kind::CodeBlock>,
565  BlockSet::index<by_offset>::type::const_iterator>>;
570  using const_code_block_range =
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>>>>;
584 
587  return code_block_iterator(
588  code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
589  }
593  const_code_block_iterator::base_type(Blocks.begin(), Blocks.end()));
594  }
598  return code_block_iterator(
599  code_block_iterator::base_type(Blocks.end(), Blocks.end()));
600  }
605  const_code_block_iterator::base_type(Blocks.end(), Blocks.end()));
606  }
609  return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
610  }
614  return boost::make_iterator_range(code_blocks_begin(), code_blocks_end());
615  }
616 
623  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
624  auto End = boost::make_indirect_iterator(It->second.end());
625  return code_block_subrange(
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));
629  }
630  return {};
631  }
632 
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));
645  }
646  return {};
647  }
648 
656  if (Address) {
657  return findCodeBlocksOnOffset(A - *Address);
658  }
659  return {};
660  }
661 
669  if (Address) {
670  return findCodeBlocksOnOffset(A - *Address);
671  }
672  return {};
673  }
674 
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)));
687  }
688 
695  code_block_range findCodeBlocksAtOffset(uint64_t Low, uint64_t High) {
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(
700  code_block_iterator(code_block_iterator::base_type(LowIt, HighIt)),
701  code_block_iterator(code_block_iterator::base_type(HighIt, HighIt)));
702  }
703 
710  if (!Address || A < *Address) {
711  // Return an empty range without default-constructing the iterators.
712  return findCodeBlocksAtOffset(0, 0);
713  }
714  return findCodeBlocksAtOffset(A - *Address);
715  }
716 
724  if (!Address) {
725  // Return an empty range without default-constructing the iterators.
726  return findCodeBlocksAtOffset(0, 0);
727  }
728  return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
729  High - std::min(*Address, High));
730  }
731 
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)));
744  }
745 
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)));
762  }
763 
770  if (!Address || A < *Address) {
771  // Return an empty range without default-constructing the iterators.
772  return findCodeBlocksAtOffset(0, 0);
773  }
774  return findCodeBlocksAtOffset(A - *Address);
775  }
776 
784  if (!Address) {
785  // Return an empty range without default-constructing the iterators.
786  return findCodeBlocksAtOffset(0, 0);
787  }
788  return findCodeBlocksAtOffset(Low - std::min(*Address, Low),
789  High - std::min(*Address, High));
790  }
791 
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>>;
804  using data_block_range = boost::iterator_range<data_block_iterator>;
810  using data_block_subrange = boost::iterator_range<boost::transform_iterator<
811  BlockToNode<DataBlock>,
812  boost::filter_iterator<
813  BlockKindEquals<Node::Kind::DataBlock>,
814  boost::indirect_iterator<BlockIntMap::codomain_type::iterator>>>>;
819  using const_data_block_iterator = boost::transform_iterator<
820  BlockToNode<const DataBlock>,
821  boost::filter_iterator<BlockKindEquals<Node::Kind::DataBlock>,
822  BlockSet::index<by_offset>::type::const_iterator>>;
827  using const_data_block_range =
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>>>>;
841 
844  return data_block_iterator(
845  data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
846  }
850  const_data_block_iterator::base_type(Blocks.begin(), Blocks.end()));
851  }
855  return data_block_iterator(
856  data_block_iterator::base_type(Blocks.end(), Blocks.end()));
857  }
862  const_data_block_iterator::base_type(Blocks.end(), Blocks.end()));
863  }
866  return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
867  }
871  return boost::make_iterator_range(data_blocks_begin(), data_blocks_end());
872  }
873 
880  if (auto It = BlockOffsets.find(Off); It != BlockOffsets.end()) {
881  auto End = boost::make_indirect_iterator(It->second.end());
882  return data_block_subrange(
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));
886  }
887  return {};
888  }
889 
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));
902  }
903  return {};
904  }
905 
913  if (Address) {
914  return findDataBlocksOnOffset(A - *Address);
915  }
916  return {};
917  }
918 
926  if (Address) {
927  return findDataBlocksOnOffset(A - *Address);
928  }
929  return {};
930  }
931 
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)));
944  }
945 
952  data_block_range findDataBlocksAtOffset(uint64_t Low, uint64_t High) {
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(
957  data_block_iterator(data_block_iterator::base_type(LowIt, HighIt)),
958  data_block_iterator(data_block_iterator::base_type(HighIt, HighIt)));
959  }
960 
967  if (!Address || A < *Address) {
968  // Return an empty range without default-constructing the iterators.
969  return findDataBlocksAtOffset(0, 0);
970  }
971  return findDataBlocksAtOffset(A - *Address);
972  }
973 
981  if (!Address) {
982  // Return an empty range without default-constructing the iterators.
983  return findDataBlocksAtOffset(0, 0);
984  }
985  return findDataBlocksAtOffset(Low - std::min(*Address, Low),
986  High - std::min(*Address, High));
987  }
988 
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)));
1001  }
1002 
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)));
1019  }
1020 
1027  if (!Address || A < *Address) {
1028  // Return an empty range without default-constructing the iterators.
1029  return findDataBlocksAtOffset(0, 0);
1030  }
1031  return findDataBlocksAtOffset(A - *Address);
1032  }
1033 
1041  if (!Address) {
1042  // Return an empty range without default-constructing the iterators.
1043  return findDataBlocksAtOffset(0, 0);
1044  }
1045  return findDataBlocksAtOffset(Low - std::min(*Address, Low),
1046  High - std::min(*Address, High));
1047  }
1048 
1049 private:
1056  template <typename ByteIntervalType> class SymbolicExpressionElementBase {
1057  public:
1063  SymbolicExpressionElementBase(ByteIntervalType* BI_, uint64_t Off_,
1064  const SymbolicExpression& SE_)
1065  : BI{BI_}, Off{Off_}, SE{SE_} {}
1066 
1068  ByteIntervalType* getByteInterval() { return BI; }
1069 
1071  const ByteIntervalType* getByteInterval() const { return BI; }
1072 
1074  uint64_t getOffset() const { return Off; }
1075 
1078  const SymbolicExpression& getSymbolicExpression() const { return SE; }
1079 
1082  operator SymbolicExpressionElementBase<const ByteIntervalType>() const {
1083  return SymbolicExpressionElementBase<const ByteIntervalType>(BI, Off, SE);
1084  }
1085 
1090  struct AddressLess {
1091  using key_type = std::optional<Addr>;
1092  static key_type
1093  key(const SymbolicExpressionElementBase<ByteIntervalType>& SEE) {
1094  if (auto A = SEE.getByteInterval()->getAddress(); A) {
1095  return *A + SEE.getOffset();
1096  }
1097  return std::nullopt;
1098  };
1100  const SymbolicExpressionElementBase<ByteIntervalType>& SEE1,
1101  const SymbolicExpressionElementBase<ByteIntervalType>& SEE2) const {
1102  return key(SEE1) < key(SEE2);
1103  }
1104  };
1105 
1106  private:
1107  ByteIntervalType* BI;
1108  uint64_t Off;
1109  SymbolicExpression SE;
1110  };
1111 
1119  template <typename SymExprElementType> class SymExprPairToElement {
1120  using ByteIntervalType =
1121  decltype(std::declval<SymExprElementType>().getByteInterval());
1122  ByteIntervalType BI;
1123 
1124  public:
1125  explicit SymExprPairToElement(ByteIntervalType BI_) : BI{BI_} {}
1126 
1127  SymExprElementType
1128  operator()(const SymbolicExpressionMap::value_type& Pair) const {
1129  return SymExprElementType(BI, Pair.first, Pair.second);
1130  }
1131  };
1132 
1133 public:
1136  using SymbolicExpressionElement = SymbolicExpressionElementBase<ByteInterval>;
1137 
1141  SymbolicExpressionElementBase<const ByteInterval>;
1142 
1147  boost::transform_iterator<SymExprPairToElement<SymbolicExpressionElement>,
1148  SymbolicExpressionMap::iterator>;
1153  boost::iterator_range<symbolic_expression_iterator>;
1157  using const_symbolic_expression_iterator = boost::transform_iterator<
1158  SymExprPairToElement<ConstSymbolicExpressionElement>,
1159  SymbolicExpressionMap::const_iterator>;
1164  boost::iterator_range<const_symbolic_expression_iterator>;
1165 
1168  return boost::make_transform_iterator(
1169  SymbolicExpressions.begin(),
1170  SymExprPairToElement<SymbolicExpressionElement>(this));
1171  }
1174  return boost::make_transform_iterator(
1175  SymbolicExpressions.begin(),
1176  SymExprPairToElement<ConstSymbolicExpressionElement>(this));
1177  }
1181  return boost::make_transform_iterator(
1182  SymbolicExpressions.end(),
1183  SymExprPairToElement<SymbolicExpressionElement>(this));
1184  }
1188  return boost::make_transform_iterator(
1189  SymbolicExpressions.end(),
1190  SymExprPairToElement<ConstSymbolicExpressionElement>(this));
1191  }
1195  return boost::make_iterator_range(symbolic_expressions_begin(),
1196  symbolic_expressions_end());
1197  }
1201  return boost::make_iterator_range(symbolic_expressions_begin(),
1202  symbolic_expressions_end());
1203  }
1204 
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(
1222  Pair.second,
1223  SymExprPairToElement<SymbolicExpressionElement>(this)));
1224  }
1225 
1235  uint64_t High) {
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)));
1243  }
1244 
1257  if (!Address) {
1258  return boost::make_iterator_range(symbolic_expressions_end(),
1259  symbolic_expressions_end());
1260  }
1261  return findSymbolicExpressionsAtOffset(A - *Address);
1262  }
1263 
1273  if (!Address) {
1274  return boost::make_iterator_range(symbolic_expressions_end(),
1275  symbolic_expressions_end());
1276  }
1277  return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1278  }
1279 
1291  const_symbolic_expression_range
1292  findSymbolicExpressionsAtOffset(uint64_t Off) const {
1293  auto Pair = SymbolicExpressions.equal_range(Off);
1294  return boost::make_iterator_range(
1295  boost::make_transform_iterator(
1296  Pair.first,
1297  SymExprPairToElement<ConstSymbolicExpressionElement>(this)),
1298  boost::make_transform_iterator(
1299  Pair.second,
1300  SymExprPairToElement<ConstSymbolicExpressionElement>(this)));
1301  }
1302 
1311  const_symbolic_expression_range
1312  findSymbolicExpressionsAtOffset(uint64_t Low, uint64_t High) const {
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)));
1320  }
1321 
1334  if (!Address) {
1335  return boost::make_iterator_range(symbolic_expressions_end(),
1336  symbolic_expressions_end());
1337  }
1338  return findSymbolicExpressionsAtOffset(A - *Address);
1339  }
1340 
1350  Addr High) const {
1351  if (!Address) {
1352  return boost::make_iterator_range(symbolic_expressions_end(),
1353  symbolic_expressions_end());
1354  }
1355  return findSymbolicExpressionsAtOffset(Low - *Address, High - *Address);
1356  }
1357 
1365  ChangeStatus removeBlock(CodeBlock* B);
1366 
1374  ChangeStatus removeBlock(DataBlock* B);
1375 
1384  ChangeStatus addBlock(uint64_t Off, CodeBlock* N);
1385 
1394  ChangeStatus addBlock(uint64_t Off, DataBlock* N);
1395 
1404  template <typename BlockType, typename... Args>
1405  BlockType* addBlock(Context& C, uint64_t O, Args&&... A) {
1406  BlockType* B = BlockType::Create(C, std::forward<Args>(A)...);
1407  [[maybe_unused]] ChangeStatus Status = addBlock(O, B);
1408  // addBlock(uint64_t, BlockType*) does not currently reject any insertions
1409  // and the result cannot be NoChange because we just inserted a newly
1410  // created ByteInterval.
1411  assert(Status == ChangeStatus::Accepted &&
1412  "unexpected result when inserting ByteInterval");
1413  return B;
1414  }
1415 
1423  const SymbolicExpression& SymExpr) {
1424  SymbolicExpressions[Off] = SymExpr;
1425  return SymbolicExpressions[Off];
1426  }
1427 
1436  template <class ExprType, class... Args>
1437  SymbolicExpression& addSymbolicExpression(uint64_t Off, Args... A) {
1438  SymbolicExpressions[Off] = ExprType{A...};
1439  return SymbolicExpressions[Off];
1440  }
1441 
1450  bool removeSymbolicExpression(uint64_t Off) {
1451  std::size_t N;
1452  N = SymbolicExpressions.erase(Off);
1453  return N != 0;
1454  }
1455 
1463  if (auto It = SymbolicExpressions.find(Off);
1464  It != SymbolicExpressions.end()) {
1465  return &It->second;
1466  }
1467  return nullptr;
1468  }
1469 
1476  const SymbolicExpression* getSymbolicExpression(uint64_t Off) const {
1477  if (auto It = SymbolicExpressions.find(Off);
1478  It != SymbolicExpressions.end()) {
1479  return &It->second;
1480  }
1481  return nullptr;
1482  }
1483 
1488  void setAddress(std::optional<Addr> A);
1489 
1497  uint64_t getSize() const { return Size; }
1498 
1505  void setSize(uint64_t S);
1506 
1520  uint64_t getInitializedSize() const { return Bytes.size(); }
1521 
1536  void setInitializedSize(uint64_t S) {
1537  Bytes.resize(S);
1538  if (S > getSize()) {
1539  setSize(S);
1540  }
1541  }
1542 
1543 private:
1544  // Wrapper to boost::endian::conditional_reverse which skips the call for
1545  // 1-byte types (char, [un]signed char, [u]int8_t).
1546  // This layer was added to work around a bug in boost 1.67 (fixed as of 1.74)
1547  // which gave wrong results for T=char.
1548  // It also allows BytesReference to work for std::byte.
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);
1553  }
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) {
1557  return From;
1558  }
1559 
1569  template <typename ByteIntervalType, typename T> class BytesReference {
1570  public:
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_) {}
1575 
1581  operator T() const {
1582  assert(I + sizeof(T) <= BI->Size &&
1583  "read into interval's bytes out of bounds!");
1584 
1585  auto S = BI->Bytes.size();
1586 
1587  if (I >= S) {
1588  // anything this far past the end of initialized bytes is composed of
1589  // all zero bytes, so we return what T would have been interpreted as
1590  // if all bytes are zero.
1591  //
1592  // (note that you may be tempted to replace this with "return T{};",
1593  // but beware: T might be a non-scalar type whose default constructor
1594  // differs from the value returned when all bytes are re-interpeted as
1595  // zeroes. A similar argument exists for "return T{0};".)
1596  const std::array<uint8_t, sizeof(T)> Array{};
1597  return *reinterpret_cast<const T*>(Array.data());
1598  }
1599 
1600  if (I + sizeof(T) > S) {
1601  // Here, I < S < I + sizeof(T), so we need to partially fill the
1602  // initialized bytes and combine it with zeroes for the uninitialized
1603  // bytes.
1604  std::array<uint8_t, sizeof(T)> Array{};
1605  // Thanks to math, 0 < S - I < sizeof(T).
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);
1609  }
1610 
1611  return endian_flip(*reinterpret_cast<const T*>(BI->Bytes.data() + I),
1612  InputOrder, OutputOrder);
1613  }
1614 
1621  BytesReference<ByteIntervalType, T>& operator=(const T& rhs) {
1622  assert(I + sizeof(T) <= BI->Size &&
1623  "write into interval's bytes out of bounds!");
1624 
1625  if (I + sizeof(T) > BI->Bytes.size()) {
1626  BI->Bytes.resize(I + sizeof(T));
1627  }
1628 
1629  *reinterpret_cast<T*>(BI->Bytes.data() + I) =
1630  endian_flip(rhs, OutputOrder, InputOrder);
1631  return *this;
1632  }
1633 
1634  ByteIntervalType* BI;
1635  size_t I;
1636  boost::endian::order InputOrder;
1637  boost::endian::order OutputOrder;
1638  };
1639 
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>> {
1651  private:
1652  using self = BytesBaseIterator<ByteIntervalType, T>;
1653 
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_) {}
1658 
1659  public:
1660  using reference = BytesReference<ByteIntervalType, T>;
1661 
1668  BytesBaseIterator() = default;
1669 
1670  // Beginning of functions for iterator facade compatibility.
1671  reference dereference() const {
1672  assert(BI && "attempt to dereference default-constructed byte iterator!");
1673  return reference(BI, I, InputOrder, OutputOrder);
1674  }
1675 
1676  bool equal(const self& other) const {
1677  return BI == other.BI && I == other.I;
1678  }
1679 
1680  void increment() {
1681  assert(BI && "attempt to increment default-constructed byte iterator!");
1682  I += sizeof(T);
1683  }
1684 
1685  void decrement() {
1686  assert(BI && "attempt to decrement default-constructed byte iterator!");
1687  I -= sizeof(T);
1688  }
1689 
1690  void advance(typename self::difference_type n) {
1691  assert(BI && "attempt to advance default-constructed byte iterator!");
1692  I += n * sizeof(T);
1693  }
1694 
1695  typename self::difference_type distance_to(const self& other) const {
1696  return (other.I - I) / sizeof(T);
1697  }
1698  // End of functions for iterator facade compatibility.
1699 
1701  operator BytesBaseIterator<const ByteIntervalType, T>() const {
1702  return BytesBaseIterator<const ByteIntervalType, T>(BI, I, InputOrder,
1703  OutputOrder);
1704  }
1705 
1706  private:
1707  ByteIntervalType* BI{nullptr};
1708  size_t I{0};
1709  boost::endian::order InputOrder{boost::endian::order::native};
1710  boost::endian::order OutputOrder{boost::endian::order::native};
1711 
1712  friend class ByteInterval;
1713  };
1714 
1715 public:
1720  template <typename T>
1721  using bytes_iterator = BytesBaseIterator<ByteInterval, T>;
1726  template <typename T>
1727  using bytes_range = boost::iterator_range<bytes_iterator<T>>;
1732  template <typename T>
1733  using const_bytes_iterator = BytesBaseIterator<const ByteInterval, T>;
1738  template <typename T>
1739  using const_bytes_range = boost::iterator_range<const_bytes_iterator<T>>;
1740 
1745  template <typename T> bytes_iterator<T> bytes_begin() {
1746  return bytes_begin<T>(getBoostEndianOrder());
1747  }
1748 
1756  template <typename T>
1757  bytes_iterator<T>
1758  bytes_begin(boost::endian::order InputOrder,
1759  boost::endian::order OutputOrder = boost::endian::order::native) {
1760  return bytes_iterator<T>(this, 0, InputOrder, OutputOrder);
1761  }
1762 
1767  template <typename T> bytes_iterator<T> bytes_end() {
1768  return bytes_end<T>(getBoostEndianOrder());
1769  }
1770 
1778  template <typename T>
1779  bytes_iterator<T>
1780  bytes_end(boost::endian::order InputOrder,
1781  boost::endian::order OutputOrder = boost::endian::order::native) {
1782  return bytes_iterator<T>(this, Size, InputOrder, OutputOrder);
1783  }
1784 
1789  template <typename T> bytes_range<T> bytes() {
1790  return bytes<T>(getBoostEndianOrder());
1791  }
1792 
1800  template <typename T>
1801  bytes_range<T>
1802  bytes(boost::endian::order InputOrder,
1803  boost::endian::order OutputOrder = boost::endian::order::native) {
1804  return bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
1805  bytes_end<T>(InputOrder, OutputOrder));
1806  }
1807 
1812  template <typename T> const_bytes_iterator<T> bytes_begin() const {
1813  return bytes_begin<T>(getBoostEndianOrder());
1814  }
1815 
1823  template <typename T>
1825  boost::endian::order InputOrder,
1826  boost::endian::order OutputOrder = boost::endian::order::native) const {
1827  return const_bytes_iterator<T>(this, 0, InputOrder, OutputOrder);
1828  }
1829 
1834  template <typename T> const_bytes_iterator<T> bytes_end() const {
1835  return bytes_end<T>(getBoostEndianOrder());
1836  }
1837 
1845  template <typename T>
1847  boost::endian::order InputOrder,
1848  boost::endian::order OutputOrder = boost::endian::order::native) const {
1849  return const_bytes_iterator<T>(this, Size, InputOrder, OutputOrder);
1850  }
1851 
1856  template <typename T> const_bytes_range<T> bytes() const {
1857  return bytes<T>(getBoostEndianOrder());
1858  }
1859 
1867  template <typename T>
1868  const_bytes_range<T>
1869  bytes(boost::endian::order InputOrder,
1870  boost::endian::order OutputOrder = boost::endian::order::native) const {
1871  return const_bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
1872  bytes_end<T>(InputOrder, OutputOrder));
1873  }
1874 
1875 private:
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) {
1897  static_assert(
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>");
1901 
1902  auto N = std::distance(Begin, End) * sizeof(T);
1903  setSize(Size + N);
1904  // If the position to insert is currently outside the initilized bytes,
1905  // we let the iterator's operator= handle resizing the byte vector,
1906  // otherwise we insert zeroes and then overwrite them via said operator=.
1907  if (Pos.I < Bytes.size()) {
1908  Bytes.insert(Bytes.begin() + Pos.I, N, 0);
1909  }
1910  // std::copy calls operator= one time for every element in the input iter.
1911  std::copy(Begin, End,
1912  bytes_iterator<T>(this, Pos.I, VectorOrder, ElementsOrder));
1913  return Pos;
1914  }
1915 
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);
1936  }
1937 
1938 public:
1949  template <typename T>
1951  const T& X) {
1952  return insertBytes<T>(Pos, X, getBoostEndianOrder());
1953  }
1954 
1965  template <typename T>
1967  return insertBytes<T>(Pos, X, getBoostEndianOrder());
1968  }
1969 
1982  template <typename T>
1984  const const_bytes_iterator<T> Pos, const T& X,
1985  boost::endian::order VectorOrder,
1986  boost::endian::order ElementOrder = boost::endian::order::native) {
1987  return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
1988  }
1989 
2002  template <typename T>
2004  bytes_iterator<T> Pos, const T& X, boost::endian::order VectorOrder,
2005  boost::endian::order ElementOrder = boost::endian::order::native) {
2006  return insertSingleByte<T>(Pos, X, VectorOrder, ElementOrder);
2007  }
2008 
2022 
2023  template <typename T, typename InputIterator>
2025  InputIterator Begin, InputIterator End) {
2026  return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2027  }
2041  template <typename T, typename InputIterator>
2043  InputIterator End) {
2044  return insertBytes<T>(Pos, Begin, End, getBoostEndianOrder());
2045  }
2046 
2062  template <typename T, typename InputIterator>
2064  const const_bytes_iterator<T> Pos, InputIterator Begin, InputIterator End,
2065  boost::endian::order VectorOrder,
2066  boost::endian::order ElementsOrder = boost::endian::order::native) {
2067  return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2068  }
2069 
2085  template <typename T, typename InputIterator>
2087  bytes_iterator<T> Pos, InputIterator Begin, InputIterator End,
2088  boost::endian::order VectorOrder,
2089  boost::endian::order ElementsOrder = boost::endian::order::native) {
2090  return insertByteVec<T>(Pos, Begin, End, VectorOrder, ElementsOrder);
2091  }
2092 
2102 
2103  template <typename T>
2105  const const_bytes_iterator<T> End) {
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!");
2109 
2110  // If the beginning iter is outside the init vector, nothing need be done.
2111  if (Begin.I < Bytes.size()) {
2112  if (End.I < Bytes.size()) {
2113  // All positions are within the initilized vector.
2114  Bytes.erase(Bytes.begin() + Begin.I, Bytes.begin() + End.I);
2115  } else {
2116  // The beginning is within vector, the end isn't; clamp to
2117  // Bytes.end().
2118  Bytes.erase(Bytes.begin() + Begin.I, Bytes.end());
2119  }
2120  }
2121 
2122  setSize(Size - (End.I - Begin.I));
2123  return Begin;
2124  }
2125 
2136  template <typename T> T* rawBytes() {
2137  return reinterpret_cast<T*>(Bytes.data());
2138  }
2139 
2150  template <typename T> const T* rawBytes() const {
2151  return reinterpret_cast<const T*>(Bytes.data());
2152  }
2153 
2155  static bool classof(const Node* N) {
2156  return N->getKind() == Kind::ByteInterval;
2157  }
2159 
2162  boost::endian::order getBoostEndianOrder() const;
2163 
2164 private:
2165  ByteInterval(Context& C);
2166 
2167  ByteInterval(Context& C, std::optional<Addr> A, uint64_t S, uint64_t InitSize,
2168  const UUID& U);
2169 
2170  ByteInterval(Context& C, std::optional<Addr> A, uint64_t S,
2171  uint64_t InitSize);
2172 
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);
2179  }
2180 
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);
2187  }
2188 
2189  void setParent(Section* S, ByteIntervalObserver* O) {
2190  Parent = S;
2191  Observer = O;
2192  }
2193 
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);
2202  }
2203 
2205  using MessageType = proto::ByteInterval;
2206 
2212  void toProtobuf(MessageType* Message) const;
2213 
2220  static ErrorOr<ByteInterval*> fromProtobuf(Context& C,
2221  const MessageType& Message);
2222 
2230  bool symbolicExpressionsFromProtobuf(Context& C, const MessageType& Message);
2231 
2232  // Present for testing purposes only.
2233  void save(std::ostream& Out) const;
2234 
2235  // Present for testing purposes only.
2236  static ByteInterval* load(Context& C, std::istream& In);
2237 
2238  // Present for testing purposes only.
2239  bool loadSymbolicExpressions(Context& C, std::istream& In);
2240 
2241  // Shared implementation for adding CodeBlocks and DataBlocks.
2242  template <typename BlockType, typename IterType>
2243  ChangeStatus addBlock(uint64_t Off, BlockType* B);
2244 
2245  // Shared implementation for removing CodeBlocks and DataBlocks.
2246  template <typename BlockType, typename IterType>
2247  ChangeStatus removeBlock(BlockType* B);
2248 
2249  Section* Parent{nullptr};
2250  ByteIntervalObserver* Observer{nullptr};
2251  std::optional<Addr> Address;
2252  uint64_t Size{0};
2253  BlockSet Blocks;
2254  BlockIntMap BlockOffsets;
2255  SymbolicExpressionMap SymbolicExpressions;
2256  std::vector<uint8_t> Bytes;
2257 
2258  std::unique_ptr<CodeBlockObserver> CBO;
2259  std::unique_ptr<DataBlockObserver> DBO;
2260 
2261  friend class Context; // Friend to enable Context::Create.
2262  friend class Section; // Friend to enable Section::(re)moveByteInterval,
2263  // Create, etc.
2264  friend class CodeBlock; // Friend to enable CodeBlock::getAddress.
2265  friend class DataBlock; // Friend to enable DataBlock::getAddress.
2266  friend class Module; // Allow Module::fromProtobuf to deserialize symbolic
2267  // expressions.
2268  friend class SerializationTestHarness; // Testing support.
2269 };
2270 
2274 
2276 public:
2277  virtual ~ByteIntervalObserver() = default;
2278 
2287  virtual ChangeStatus addCodeBlocks(ByteInterval* BI,
2288  ByteInterval::code_block_range Blocks) = 0;
2289 
2298  virtual ChangeStatus
2299  moveCodeBlocks(ByteInterval* BI, ByteInterval::code_block_range Blocks) = 0;
2300 
2309  virtual ChangeStatus
2310  removeCodeBlocks(ByteInterval* BI, ByteInterval::code_block_range Blocks) = 0;
2311 
2320  virtual ChangeStatus addDataBlocks(ByteInterval* BI,
2321  ByteInterval::data_block_range Blocks) = 0;
2322 
2331  virtual ChangeStatus
2332  moveDataBlocks(ByteInterval* BI, ByteInterval::data_block_range Blocks) = 0;
2333 
2342  virtual ChangeStatus
2343  removeDataBlocks(ByteInterval* BI, ByteInterval::data_block_range Blocks) = 0;
2344 
2355  virtual ChangeStatus
2356  changeExtent(ByteInterval* BI,
2357  std::function<void(ByteInterval*)> Callback) = 0;
2358 };
2359 
2360 } // namespace gtirb
2361 
2362 #endif // GTIRB_BYTE_INTERVAL_H
gtirb::ByteInterval::Create
static ByteInterval * Create(Context &C)
Create an unitialized ByteInterval object.
Definition: ByteInterval.hpp:215
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:2104
gtirb::ByteInterval::bytes_iterator
BytesBaseIterator< ByteInterval, T > bytes_iterator
Iterator over bytes.
Definition: ByteInterval.hpp:1721
gtirb::ByteInterval::bytes_begin
const_bytes_iterator< T > bytes_begin() const
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1812
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:284
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:1292
gtirb::ByteInterval::removeSymbolicExpression
bool removeSymbolicExpression(uint64_t Off)
Removes a SymbolicExpression at the given offset, if present.
Definition: ByteInterval.hpp:1450
gtirb::CodeBlock
A basic block.
Definition: CodeBlock.hpp:54
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:668
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:2063
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:966
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:1405
gtirb::ByteInterval::bytes_end
bytes_iterator< T > bytes_end()
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1767
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:613
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:497
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:783
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:583
gtirb::ByteInterval::symbolic_expressions
symbolic_expression_range symbolic_expressions()
Return a range of the SymbolicExpression objects in this interval.
Definition: ByteInterval.hpp:1194
gtirb::ByteInterval::bytes
const_bytes_range< T > bytes() const
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1856
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:1780
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:1312
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:1437
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:565
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:828
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:695
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:346
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:1802
gtirb::ByteInterval::code_blocks_begin
const_code_block_iterator code_blocks_begin() const
Return a const iterator to the first CodeBlock.
Definition: ByteInterval.hpp:591
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:352
gtirb::ByteInterval::data_blocks
data_block_range data_blocks()
Return a range of the DataBlock objects in this interval.
Definition: ByteInterval.hpp:865
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:336
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:586
gtirb::ByteInterval::getAddress
std::optional< Addr > getAddress() const
Get the fixed address of this interval, if present.
Definition: ByteInterval.hpp:305
gtirb::ByteInterval::setInitializedSize
void setInitializedSize(uint64_t S)
Set the number of initialized bytes in this interval.
Definition: ByteInterval.hpp:1536
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:952
gtirb::ByteInterval::data_block_range
boost::iterator_range< data_block_iterator > data_block_range
Range of DataBlock objects.
Definition: ByteInterval.hpp:804
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:895
gtirb::ByteInterval::bytes_range
boost::iterator_range< bytes_iterator< T > > bytes_range
Range over bytes.
Definition: ByteInterval.hpp:1727
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:1009
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:603
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:1758
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:1234
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:2086
gtirb::ByteInterval::rawBytes
T * rawBytes()
Return the raw data underlying this byte vector.
Definition: ByteInterval.hpp:2136
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:1040
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:1272
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:1333
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::key
static key_type key(const SymbolicExpressionElementBase< ByteIntervalType > &SEE)
Definition: ByteInterval.hpp:1093
gtirb::ByteInterval::findDataBlocksAt
const_data_block_range findDataBlocksAt(Addr A) const
Find all the data blocks that start at an address.
Definition: ByteInterval.hpp:1026
gtirb::ByteInterval::data_blocks_begin
const_data_block_iterator data_blocks_begin() const
Return a const iterator to the first DataBlock.
Definition: ByteInterval.hpp:848
gtirb::SymAttribute::S
@ S
gtirb::ByteIntervalObserver
Interface for notifying observers when the ByteInterval is modified.
Definition: ByteInterval.hpp:2275
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:373
gtirb::ByteInterval::symbolic_expressions_end
symbolic_expression_iterator symbolic_expressions_end()
Return an iterator to the element following the last SymbolicExpression.
Definition: ByteInterval.hpp:1180
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:870
gtirb::ByteInterval::code_blocks_end
code_block_iterator code_blocks_end()
Return an iterator to the element following the last CodeBlock.
Definition: ByteInterval.hpp:597
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:400
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:912
gtirb::ByteInterval::getSize
uint64_t getSize() const
Get the size of this interval in bytes.
Definition: ByteInterval.hpp:1497
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:343
gtirb::ByteInterval::findBlocksAt
block_range findBlocksAt(Addr A)
Find all the blocks that start at an address.
Definition: ByteInterval.hpp:454
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:331
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:526
gtirb::ByteInterval::rawBytes
const T * rawBytes() const
Return the raw data underlying this byte vector.
Definition: ByteInterval.hpp:2150
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:2024
gtirb::ByteInterval::bytes_end
const_bytes_iterator< T > bytes_end() const
Get an iterator past the end of this byte vector.
Definition: ByteInterval.hpp:1834
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:1136
gtirb::ByteInterval::findBlocksAtOffset
const_block_range findBlocksAtOffset(uint64_t Off) const
Find all the blocks that start at an offset.
Definition: ByteInterval.hpp:484
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:1824
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:440
gtirb::ByteInterval::const_bytes_iterator
BytesBaseIterator< const ByteInterval, T > const_bytes_iterator
Const iterator over bytes.
Definition: ByteInterval.hpp:1733
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:238
gtirb::ByteInterval::data_blocks_begin
data_block_iterator data_blocks_begin()
Return an iterator to the first DataBlock.
Definition: ByteInterval.hpp:843
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:414
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess
A comparison function object to order symbolic expression elements by the address in which they occur...
Definition: ByteInterval.hpp:1090
gtirb::ByteInterval::bytes_begin
bytes_iterator< T > bytes_begin()
Get an iterator to the beginning of this byte vector.
Definition: ByteInterval.hpp:1745
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:259
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:814
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:1167
gtirb::ByteInterval::findCodeBlocksAt
const_code_block_range findCodeBlocksAt(Addr A) const
Find all the code blocks that start at an address.
Definition: ByteInterval.hpp:769
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:1966
gtirb::ByteInterval::symbolic_expression_iterator
boost::transform_iterator< SymExprPairToElement< SymbolicExpressionElement >, SymbolicExpressionMap::iterator > symbolic_expression_iterator
Iterator over SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1148
gtirb::ByteInterval::findBlocksAt
const_block_range findBlocksAt(Addr A) const
Find all the blocks that start at an address.
Definition: ByteInterval.hpp:511
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:1349
gtirb::ByteInterval::blocks
block_range blocks()
Return a range of the Block objects in this interval.
Definition: ByteInterval.hpp:359
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:571
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:860
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:1159
gtirb::ByteInterval::code_blocks
code_block_range code_blocks()
Return a range of the CodeBlock objects in this interval.
Definition: ByteInterval.hpp:608
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:737
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:980
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:1869
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::key_type
std::optional< Addr > key_type
Definition: ByteInterval.hpp:1091
gtirb::ByteInterval::addSymbolicExpression
SymbolicExpression & addSymbolicExpression(uint64_t Off, const SymbolicExpression &SymExpr)
Adds a new SymbolicExpression to this interval.
Definition: ByteInterval.hpp:1422
gtirb::ByteInterval::findSymbolicExpressionsAt
symbolic_expression_range findSymbolicExpressionsAt(Addr A)
Find all the symbolic expressions that start at an address.
Definition: ByteInterval.hpp:1256
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:925
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:1846
gtirb::ByteInterval::getSection
const Section * getSection() const
Get the Section this byte interval belongs to.
Definition: ByteInterval.hpp:296
gtirb::ByteInterval::code_block_range
boost::iterator_range< code_block_iterator > code_block_range
Range of CodeBlock objects.
Definition: ByteInterval.hpp:547
gtirb::ByteInterval::getSymbolicExpression
SymbolicExpression * getSymbolicExpression(uint64_t Off)
Get the symbolic expression at the given offset, if present.
Definition: ByteInterval.hpp:1462
gtirb::ByteInterval::symbolic_expression_range
boost::iterator_range< symbolic_expression_iterator > symbolic_expression_range
Range of SymbolicExpressionElement objects.
Definition: ByteInterval.hpp:1153
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:1141
gtirb::ByteInterval::getSection
Section * getSection()
Get the Section this byte interval belongs to.
Definition: ByteInterval.hpp:294
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:324
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:799
gtirb::CodeBlockObserver
Interface for notifying observers when a CodeBlock is modified.
Definition: ByteInterval.hpp:65
gtirb::ByteInterval::symbolic_expressions_begin
const_symbolic_expression_iterator symbolic_expressions_begin() const
Return a const iterator to the first SymbolicExpression.
Definition: ByteInterval.hpp:1173
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:638
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:557
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:822
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:994
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:1164
gtirb::ByteInterval::bytes
bytes_range< T > bytes()
Get a range of data in this byte vector.
Definition: ByteInterval.hpp:1789
gtirb::ByteInterval::blocks_begin
const_block_iterator blocks_begin() const
Return a const iterator to the first Block.
Definition: ByteInterval.hpp:348
gtirb::ByteInterval::block_iterator
boost::transform_iterator< BlockToNode< Node >, BlockSet::index< by_offset >::type::iterator > block_iterator
Iterator over Block objects.
Definition: ByteInterval.hpp:313
gtirb::ByteInterval::findCodeBlocksAt
code_block_range findCodeBlocksAt(Addr A)
Find all the code blocks that start at an address.
Definition: ByteInterval.hpp:709
gtirb::ByteInterval::getInitializedSize
uint64_t getInitializedSize() const
Get the number of initialized bytes in this interval.
Definition: ByteInterval.hpp:1520
gtirb::ByteInterval::blocks_end
const_block_iterator blocks_end() const
Return a const iterator to the element following the last Block.
Definition: ByteInterval.hpp:355
gtirb::ByteInterval
A contiguous region of bytes in a binary.
Definition: ByteInterval.hpp:116
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:937
gtirb::ByteInterval::getSymbolicExpression
const SymbolicExpression * getSymbolicExpression(uint64_t Off) const
Get the symbolic expression at the given offset, if present.
Definition: ByteInterval.hpp:1476
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:622
gtirb::ByteInterval::blocks
const_block_range blocks() const
Return a const range of the Block objects in this interval.
Definition: ByteInterval.hpp:363
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:752
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:224
gtirb::ByteInterval::block_range
boost::iterator_range< block_iterator > block_range
Range of Block objects.
Definition: ByteInterval.hpp:318
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:2003
gtirb::ByteInterval::const_bytes_range
boost::iterator_range< const_bytes_iterator< T > > const_bytes_range
Const range over bytes.
Definition: ByteInterval.hpp:1739
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:1983
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:1187
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:386
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:1950
gtirb::ByteInterval::findBlocksAt
block_range findBlocksAt(Addr Low, Addr High)
Find all the blocks that start between a range of addresses.
Definition: ByteInterval.hpp:469
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:1200
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:840
gtirb::ByteInterval::findBlocksAtOffset
block_range findBlocksAtOffset(uint64_t Off)
Find all the blocks that start at an offset.
Definition: ByteInterval.hpp:427
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:542
gtirb::ChangeStatus
ChangeStatus
Definition: Observer.hpp:19
gtirb::ErrorOr
Definition: ByteInterval.hpp:59
gtirb::DataBlockObserver
Interface for notifying observers when a DataBlock is modified.
Definition: ByteInterval.hpp:86
gtirb::ByteInterval::findSymbolicExpressionsAtOffset
symbolic_expression_range findSymbolicExpressionsAtOffset(uint64_t Off)
Find all the symbolic expressions that start at an offset.
Definition: ByteInterval.hpp:1216
gtirb::ByteInterval::insertBytes
bytes_iterator< T > insertBytes(bytes_iterator< T > Pos, InputIterator Begin, InputIterator End)
Insert data into this byte vector.
Definition: ByteInterval.hpp:2042
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:879
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:655
gtirb::ByteInterval::findCodeBlocksAtOffset
code_block_range findCodeBlocksAtOffset(uint64_t Off)
Find all the code blocks that start at an offset.
Definition: ByteInterval.hpp:680
gtirb::ByteInterval::data_blocks_end
data_block_iterator data_blocks_end()
Return an iterator to the element following the last DataBlock.
Definition: ByteInterval.hpp:854
gtirb::ByteInterval::SymbolicExpressionElementBase::AddressLess::operator()
bool operator()(const SymbolicExpressionElementBase< ByteIntervalType > &SEE1, const SymbolicExpressionElementBase< ByteIntervalType > &SEE2) const
Definition: ByteInterval.hpp:1099
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:723