GTIRB  v2.2.0
GrammaTech Intermediate Representation for Binaries: C++ API
CodeBlock.hpp
Go to the documentation of this file.
1 //===- CodeBlock.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 #ifndef GTIRB_BLOCK_H
16 #define GTIRB_BLOCK_H
17 
18 #include <gtirb/Addr.hpp>
19 #include <gtirb/ByteInterval.hpp>
20 #include <gtirb/CfgNode.hpp>
21 #include <gtirb/DecodeMode.hpp>
22 #include <gtirb/Export.hpp>
23 #include <gtirb/Node.hpp>
24 #include <gtirb/proto/CodeBlock.pb.h>
25 #include <boost/range/iterator_range.hpp>
26 #include <cstdint>
27 #include <functional>
28 #include <optional>
29 #include <vector>
30 
35 
36 namespace gtirb {
37 template <class T> class ErrorOr;
38 
39 namespace proto {
40 class CodeBlock;
41 } // namespace proto
42 
48 public:
52  static CodeBlock* Create(Context& C) { return C.Create<CodeBlock>(C); }
53 
61  static CodeBlock* Create(Context& C, uint64_t Size,
63  return C.Create<CodeBlock>(C, Size, DMode);
64  }
65 
67  ByteInterval* getByteInterval() { return Parent; }
69  const ByteInterval* getByteInterval() const { return Parent; }
70 
77  uint64_t getSize() const { return Size; }
78 
85  gtirb::DecodeMode getDecodeMode() const { return this->DecodeMode; }
86 
89  uint64_t getOffset() const;
90 
94  std::optional<Addr> getAddress() const;
95 
101  void setSize(uint64_t S) {
102  if (Observer) {
103  std::swap(Size, S);
104  [[maybe_unused]] ChangeStatus Status =
105  Observer->sizeChange(this, S, Size);
106  assert(Status != ChangeStatus::Rejected &&
107  "recovering from rejected size change is not implemented yet");
108  } else {
109  Size = S;
110  }
111  }
112 
118  if (Observer) {
119  std::swap(DecodeMode, DM);
120  [[maybe_unused]] ChangeStatus Status =
121  Observer->decodeModeChange(this, DM, DecodeMode);
122  assert(
123  Status != ChangeStatus::Rejected &&
124  "recovering from rejected decode mode change is not implemented yet");
125  } else {
126  DecodeMode = DM;
127  }
128  }
129 
134  template <typename T> using bytes_iterator = ByteInterval::bytes_iterator<T>;
139  template <typename T> using bytes_range = ByteInterval::bytes_range<T>;
144  template <typename T>
150  template <typename T>
152 
160  template <typename T> bytes_iterator<T> bytes_begin() {
161  assert(Parent && "Block has no byte interval!");
162  return bytes_begin<T>(Parent->getBoostEndianOrder());
163  }
164 
175  template <typename T>
176  bytes_iterator<T>
177  bytes_begin(boost::endian::order InputOrder,
178  boost::endian::order OutputOrder = boost::endian::order::native) {
179  assert(Parent && "Block has no byte interval!");
180  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
181  }
182 
190  template <typename T> bytes_iterator<T> bytes_end() {
191  assert(Parent && "Block has no byte interval!");
192  return bytes_end<T>(Parent->getBoostEndianOrder());
193  }
194 
205  template <typename T>
206  bytes_iterator<T>
207  bytes_end(boost::endian::order InputOrder,
208  boost::endian::order OutputOrder = boost::endian::order::native) {
209  assert(Parent && "Block has no byte interval!");
210  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
211  }
212 
220  template <typename T> bytes_range<T> bytes() {
221  assert(Parent && "Block has no byte interval!");
222  return bytes<T>(Parent->getBoostEndianOrder());
223  }
224 
235  template <typename T>
236  bytes_range<T>
237  bytes(boost::endian::order InputOrder,
238  boost::endian::order OutputOrder = boost::endian::order::native) {
239  assert(Parent && "Block has no byte interval!");
240  return bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
241  bytes_end<T>(InputOrder, OutputOrder));
242  }
243 
251  template <typename T> const_bytes_iterator<T> bytes_begin() const {
252  assert(Parent && "Block has no byte interval!");
253  return bytes_begin<T>(Parent->getBoostEndianOrder());
254  }
255 
266  template <typename T>
268  boost::endian::order InputOrder,
269  boost::endian::order OutputOrder = boost::endian::order::native) const {
270  assert(Parent && "Block has no byte interval!");
271  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
272  }
273 
281  template <typename T> const_bytes_iterator<T> bytes_end() const {
282  assert(Parent && "Block has no byte interval!");
283  return bytes_end<T>(Parent->getBoostEndianOrder());
284  }
285 
296  template <typename T>
298  boost::endian::order InputOrder,
299  boost::endian::order OutputOrder = boost::endian::order::native) const {
300  assert(Parent && "Block has no byte interval!");
301  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
302  }
303 
311  template <typename T> const_bytes_range<T> bytes() const {
312  assert(Parent && "Block has no byte interval!");
313  return bytes<T>(Parent->getBoostEndianOrder());
314  }
315 
326  template <typename T>
327  const_bytes_range<T>
328  bytes(boost::endian::order InputOrder,
329  boost::endian::order OutputOrder = boost::endian::order::native) const {
330  assert(Parent && "Block has no byte interval!");
331  return const_bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
332  bytes_end<T>(InputOrder, OutputOrder));
333  }
334 
350  template <typename T> T* rawBytes() {
351  assert(Parent && "Block has no byte interval!");
352  return reinterpret_cast<T*>(Parent->rawBytes<uint8_t>() + getOffset());
353  }
354 
370  template <typename T> const T* rawBytes() const {
371  assert(Parent && "Block has no byte interval!");
372  return reinterpret_cast<const T*>(Parent->rawBytes<uint8_t>() +
373  getOffset());
374  }
375 
377  static bool classof(const Node* N) { return N->getKind() == Kind::CodeBlock; }
379 
380 private:
381  CodeBlock(Context& C) : CfgNode(C, Kind::CodeBlock) {}
382  CodeBlock(Context& C, uint64_t S, gtirb::DecodeMode DMode)
383  : CfgNode(C, Kind::CodeBlock), Size(S), DecodeMode(DMode) {}
384  CodeBlock(Context& C, uint64_t S, gtirb::DecodeMode DMode, const UUID& U)
385  : CfgNode(C, Kind::CodeBlock, U), Size(S), DecodeMode(DMode) {}
386 
387  void setParent(ByteInterval* BI, CodeBlockObserver* O) {
388  Parent = BI;
389  Observer = O;
390  }
391 
392  static CodeBlock* Create(Context& C, uint64_t Size, gtirb::DecodeMode DMode,
393  const UUID& U) {
394  return C.Create<CodeBlock>(C, Size, DMode, U);
395  }
396 
398  using MessageType = proto::CodeBlock;
399 
405  void toProtobuf(MessageType* Message) const;
406 
413  static ErrorOr<CodeBlock*> fromProtobuf(Context& C,
414  const MessageType& Message);
415 
416  // Present for testing purposes only.
417  void save(std::ostream& Out) const;
418 
419  // Present for testing purposes only.
420  static CodeBlock* load(Context& C, std::istream& In);
421 
422  ByteInterval* Parent{nullptr};
423  CodeBlockObserver* Observer{nullptr};
424  uint64_t Size{0};
426 
427  friend class Context; // Enables Context::Create
428  friend class ByteInterval; // Enables to/fromProtobuf, setByteInterval
429  friend class SerializationTestHarness; // Testing support.
430 };
431 
432 } // namespace gtirb
433 
434 #endif // GTIRB_BLOCK_H
gtirb::CodeBlock::const_bytes_iterator
ByteInterval::const_bytes_iterator< T > const_bytes_iterator
Const iterator over bytes in this block.
Definition: CodeBlock.hpp:145
gtirb::ByteInterval::bytes_iterator
BytesBaseIterator< ByteInterval, T > bytes_iterator
Iterator over bytes.
Definition: ByteInterval.hpp:1769
gtirb::CodeBlock
A basic block.
Definition: CodeBlock.hpp:47
gtirb::CodeBlock::bytes_begin
bytes_iterator< T > bytes_begin()
Get an iterator to the first byte in this block.
Definition: CodeBlock.hpp:160
gtirb::Context::Create
NodeTy * Create(Args &&... TheArgs)
Create an object of type T.
Definition: Context.hpp:126
gtirb::CodeBlock::bytes_end
const_bytes_iterator< T > bytes_end() const
Get an iterator past the last byte in this block.
Definition: CodeBlock.hpp:281
gtirb::Node
Represents the base of the Node class hierarchy.
Definition: Node.hpp:39
gtirb::CodeBlock::getDecodeMode
gtirb::DecodeMode getDecodeMode() const
Get the decode mode from a CodeBlock.
Definition: CodeBlock.hpp:85
gtirb::CfgNode
Represents the base of types that can be inserted into the CFG.
Definition: CfgNode.hpp:30
gtirb::CodeBlock::const_bytes_range
ByteInterval::const_bytes_range< T > const_bytes_range
Const range over bytes in this block.
Definition: CodeBlock.hpp:151
gtirb::UUID
boost::uuids::uuid UUID
Represents a universally unique identifier used to identify Node objects across serialization boundar...
Definition: Context.hpp:36
gtirb::ChangeStatus::Rejected
@ Rejected
gtirb::CodeBlock::setDecodeMode
void setDecodeMode(gtirb::DecodeMode DM)
Set the decode mode of this block.
Definition: CodeBlock.hpp:117
gtirb::Context
The context under which GTIRB operations occur.
Definition: Context.hpp:63
gtirb::CodeBlock::bytes
bytes_range< T > bytes(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get a range of the bytes in this block.
Definition: CodeBlock.hpp:237
gtirb::CodeBlock::getSize
uint64_t getSize() const
Get the size from a CodeBlock.
Definition: CodeBlock.hpp:77
gtirb::CodeBlock::bytes_iterator
ByteInterval::bytes_iterator< T > bytes_iterator
Iterator over bytes in this block.
Definition: CodeBlock.hpp:134
Node.hpp
Class gtirb::Node.
gtirb::ByteInterval::bytes_range
boost::iterator_range< bytes_iterator< T > > bytes_range
Range over bytes.
Definition: ByteInterval.hpp:1775
gtirb::CodeBlock::bytes_begin
const_bytes_iterator< T > bytes_begin() const
Get an iterator to the first byte in this block.
Definition: CodeBlock.hpp:251
gtirb::CodeBlock::rawBytes
T * rawBytes()
Return the raw data underlying this block's byte vector.
Definition: CodeBlock.hpp:350
gtirb::SymAttribute::S
@ S
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::CodeBlock::Create
static CodeBlock * Create(Context &C)
Create an unitialized CodeBlock object.
Definition: CodeBlock.hpp:52
gtirb::CodeBlock::bytes
bytes_range< T > bytes()
Get a range of the bytes in this block.
Definition: CodeBlock.hpp:220
gtirb
Main namespace for the GTIRB API.
Definition: Addr.hpp:28
gtirb::CodeBlock::Create
static CodeBlock * Create(Context &C, uint64_t Size, gtirb::DecodeMode DMode=DecodeMode::Default)
Create a CodeBlock object.
Definition: CodeBlock.hpp:61
Export.hpp
gtirb::CodeBlock::bytes_begin
bytes_iterator< T > bytes_begin(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get an iterator to the first byte in this block.
Definition: CodeBlock.hpp:177
ByteInterval.hpp
Class gtirb::ByteInterval.
gtirb::CodeBlock::bytes_range
ByteInterval::bytes_range< T > bytes_range
Range over bytes in this block.
Definition: CodeBlock.hpp:139
gtirb::CodeBlock::getByteInterval
ByteInterval * getByteInterval()
Get the ByteInterval this block belongs to.
Definition: CodeBlock.hpp:67
CfgNode.hpp
Base class for nodes of the CFG.
gtirb::ByteInterval::const_bytes_iterator
BytesBaseIterator< const ByteInterval, T > const_bytes_iterator
Const iterator over bytes.
Definition: ByteInterval.hpp:1781
gtirb::CodeBlock::getByteInterval
const ByteInterval * getByteInterval() const
Get the ByteInterval this block belongs to.
Definition: CodeBlock.hpp:69
gtirb::DecodeMode
DecodeMode
Variations on decoding a particular ISA.
Definition: DecodeMode.hpp:26
gtirb::CodeBlock::bytes_end
bytes_iterator< T > bytes_end(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native)
Get an iterator past the last byte in this block.
Definition: CodeBlock.hpp:207
gtirb::CodeBlock::bytes_end
bytes_iterator< T > bytes_end()
Get an iterator past the last byte in this block.
Definition: CodeBlock.hpp:190
DecodeMode.hpp
gtirb::CodeBlock::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 first byte in this block.
Definition: CodeBlock.hpp:267
gtirb::DecodeMode::Default
@ Default
Default decode mode for all ISAs.
gtirb::CodeBlock::bytes
const_bytes_range< T > bytes(boost::endian::order InputOrder, boost::endian::order OutputOrder=boost::endian::order::native) const
Get a range of the bytes in this block.
Definition: CodeBlock.hpp:328
gtirb::ByteInterval
A contiguous region of bytes in a binary.
Definition: ByteInterval.hpp:124
gtirb::CodeBlock::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 last byte in this block.
Definition: CodeBlock.hpp:297
gtirb::CodeBlock::setSize
void setSize(uint64_t S)
Set the size of this block.
Definition: CodeBlock.hpp:101
gtirb::ByteInterval::const_bytes_range
boost::iterator_range< const_bytes_iterator< T > > const_bytes_range
Const range over bytes.
Definition: ByteInterval.hpp:1787
gtirb::CodeBlock::rawBytes
const T * rawBytes() const
Return the raw data underlying this block's byte vector.
Definition: CodeBlock.hpp:370
Addr.hpp
Class gtirb::Addr and related functions.
gtirb::CodeBlock::bytes
const_bytes_range< T > bytes() const
Get a range of the bytes in this block.
Definition: CodeBlock.hpp:311
gtirb::ChangeStatus
ChangeStatus
Definition: Observer.hpp:19