GTIRB  v2.1.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/Export.hpp>
22 #include <gtirb/Node.hpp>
23 #include <gtirb/proto/CodeBlock.pb.h>
24 #include <boost/range/iterator_range.hpp>
25 #include <cstdint>
26 #include <functional>
27 #include <optional>
28 #include <vector>
29 
34 
35 namespace gtirb {
36 template <class T> class ErrorOr;
37 
38 namespace proto {
39 class CodeBlock;
40 } // namespace proto
41 
45 enum class DecodeMode : uint8_t {
46  Default = proto::All_Default,
47  Thumb = proto::ARM_Thumb,
48 };
49 
55 public:
59  static CodeBlock* Create(Context& C) { return C.Create<CodeBlock>(C); }
60 
68  static CodeBlock* Create(Context& C, uint64_t Size,
70  return C.Create<CodeBlock>(C, Size, DMode);
71  }
72 
74  ByteInterval* getByteInterval() { return Parent; }
76  const ByteInterval* getByteInterval() const { return Parent; }
77 
84  uint64_t getSize() const { return Size; }
85 
92  gtirb::DecodeMode getDecodeMode() const { return this->DecodeMode; }
93 
96  uint64_t getOffset() const;
97 
101  std::optional<Addr> getAddress() const;
102 
108  void setSize(uint64_t S) {
109  if (Observer) {
110  std::swap(Size, S);
111  [[maybe_unused]] ChangeStatus Status =
112  Observer->sizeChange(this, S, Size);
113  assert(Status != ChangeStatus::Rejected &&
114  "recovering from rejected size change is not implemented yet");
115  } else {
116  Size = S;
117  }
118  }
119 
124  void setDecodeMode(gtirb::DecodeMode DM) { this->DecodeMode = DM; }
125 
130  template <typename T> using bytes_iterator = ByteInterval::bytes_iterator<T>;
135  template <typename T> using bytes_range = ByteInterval::bytes_range<T>;
140  template <typename T>
146  template <typename T>
148 
156  template <typename T> bytes_iterator<T> bytes_begin() {
157  assert(Parent && "Block has no byte interval!");
158  return bytes_begin<T>(Parent->getBoostEndianOrder());
159  }
160 
171  template <typename T>
172  bytes_iterator<T>
173  bytes_begin(boost::endian::order InputOrder,
174  boost::endian::order OutputOrder = boost::endian::order::native) {
175  assert(Parent && "Block has no byte interval!");
176  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
177  }
178 
186  template <typename T> bytes_iterator<T> bytes_end() {
187  assert(Parent && "Block has no byte interval!");
188  return bytes_end<T>(Parent->getBoostEndianOrder());
189  }
190 
201  template <typename T>
202  bytes_iterator<T>
203  bytes_end(boost::endian::order InputOrder,
204  boost::endian::order OutputOrder = boost::endian::order::native) {
205  assert(Parent && "Block has no byte interval!");
206  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
207  }
208 
216  template <typename T> bytes_range<T> bytes() {
217  assert(Parent && "Block has no byte interval!");
218  return bytes<T>(Parent->getBoostEndianOrder());
219  }
220 
231  template <typename T>
232  bytes_range<T>
233  bytes(boost::endian::order InputOrder,
234  boost::endian::order OutputOrder = boost::endian::order::native) {
235  assert(Parent && "Block has no byte interval!");
236  return bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
237  bytes_end<T>(InputOrder, OutputOrder));
238  }
239 
247  template <typename T> const_bytes_iterator<T> bytes_begin() const {
248  assert(Parent && "Block has no byte interval!");
249  return bytes_begin<T>(Parent->getBoostEndianOrder());
250  }
251 
262  template <typename T>
264  boost::endian::order InputOrder,
265  boost::endian::order OutputOrder = boost::endian::order::native) const {
266  assert(Parent && "Block has no byte interval!");
267  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
268  }
269 
277  template <typename T> const_bytes_iterator<T> bytes_end() const {
278  assert(Parent && "Block has no byte interval!");
279  return bytes_end<T>(Parent->getBoostEndianOrder());
280  }
281 
292  template <typename T>
294  boost::endian::order InputOrder,
295  boost::endian::order OutputOrder = boost::endian::order::native) const {
296  assert(Parent && "Block has no byte interval!");
297  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
298  }
299 
307  template <typename T> const_bytes_range<T> bytes() const {
308  assert(Parent && "Block has no byte interval!");
309  return bytes<T>(Parent->getBoostEndianOrder());
310  }
311 
322  template <typename T>
323  const_bytes_range<T>
324  bytes(boost::endian::order InputOrder,
325  boost::endian::order OutputOrder = boost::endian::order::native) const {
326  assert(Parent && "Block has no byte interval!");
327  return const_bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
328  bytes_end<T>(InputOrder, OutputOrder));
329  }
330 
346  template <typename T> T* rawBytes() {
347  assert(Parent && "Block has no byte interval!");
348  return reinterpret_cast<T*>(Parent->rawBytes<uint8_t>() + getOffset());
349  }
350 
366  template <typename T> const T* rawBytes() const {
367  assert(Parent && "Block has no byte interval!");
368  return reinterpret_cast<const T*>(Parent->rawBytes<uint8_t>() +
369  getOffset());
370  }
371 
373  static bool classof(const Node* N) { return N->getKind() == Kind::CodeBlock; }
375 
376 private:
377  CodeBlock(Context& C) : CfgNode(C, Kind::CodeBlock) {}
378  CodeBlock(Context& C, uint64_t S, gtirb::DecodeMode DMode)
379  : CfgNode(C, Kind::CodeBlock), Size(S), DecodeMode(DMode) {}
380  CodeBlock(Context& C, uint64_t S, gtirb::DecodeMode DMode, const UUID& U)
381  : CfgNode(C, Kind::CodeBlock, U), Size(S), DecodeMode(DMode) {}
382 
383  void setParent(ByteInterval* BI, CodeBlockObserver* O) {
384  Parent = BI;
385  Observer = O;
386  }
387 
388  static CodeBlock* Create(Context& C, uint64_t Size, gtirb::DecodeMode DMode,
389  const UUID& U) {
390  return C.Create<CodeBlock>(C, Size, DMode, U);
391  }
392 
394  using MessageType = proto::CodeBlock;
395 
401  void toProtobuf(MessageType* Message) const;
402 
409  static ErrorOr<CodeBlock*> fromProtobuf(Context& C,
410  const MessageType& Message);
411 
412  // Present for testing purposes only.
413  void save(std::ostream& Out) const;
414 
415  // Present for testing purposes only.
416  static CodeBlock* load(Context& C, std::istream& In);
417 
418  ByteInterval* Parent{nullptr};
419  CodeBlockObserver* Observer{nullptr};
420  uint64_t Size{0};
422 
423  friend class Context; // Enables Context::Create
424  friend class ByteInterval; // Enables to/fromProtobuf, setByteInterval
425  friend class SerializationTestHarness; // Testing support.
426 };
427 
428 } // namespace gtirb
429 
430 #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:141
gtirb::ByteInterval::bytes_iterator
BytesBaseIterator< ByteInterval, T > bytes_iterator
Iterator over bytes.
Definition: ByteInterval.hpp:1721
gtirb::CodeBlock
A basic block.
Definition: CodeBlock.hpp:54
gtirb::CodeBlock::bytes_begin
bytes_iterator< T > bytes_begin()
Get an iterator to the first byte in this block.
Definition: CodeBlock.hpp:156
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:277
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:92
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:147
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:124
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:233
gtirb::CodeBlock::getSize
uint64_t getSize() const
Get the size from a CodeBlock.
Definition: CodeBlock.hpp:84
gtirb::CodeBlock::bytes_iterator
ByteInterval::bytes_iterator< T > bytes_iterator
Iterator over bytes in this block.
Definition: CodeBlock.hpp:130
Node.hpp
Class gtirb::Node.
gtirb::ByteInterval::bytes_range
boost::iterator_range< bytes_iterator< T > > bytes_range
Range over bytes.
Definition: ByteInterval.hpp:1727
gtirb::CodeBlock::bytes_begin
const_bytes_iterator< T > bytes_begin() const
Get an iterator to the first byte in this block.
Definition: CodeBlock.hpp:247
gtirb::CodeBlock::rawBytes
T * rawBytes()
Return the raw data underlying this block's byte vector.
Definition: CodeBlock.hpp:346
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:59
gtirb::CodeBlock::bytes
bytes_range< T > bytes()
Get a range of the bytes in this block.
Definition: CodeBlock.hpp:216
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:68
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:173
ByteInterval.hpp
Class gtirb::ByteInterval.
gtirb::DecodeMode::Thumb
@ Thumb
Thumb decode mode for ARM32.
gtirb::CodeBlock::bytes_range
ByteInterval::bytes_range< T > bytes_range
Range over bytes in this block.
Definition: CodeBlock.hpp:135
gtirb::CodeBlock::getByteInterval
ByteInterval * getByteInterval()
Get the ByteInterval this block belongs to.
Definition: CodeBlock.hpp:74
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:1733
gtirb::CodeBlock::getByteInterval
const ByteInterval * getByteInterval() const
Get the ByteInterval this block belongs to.
Definition: CodeBlock.hpp:76
gtirb::DecodeMode
DecodeMode
Variations on decoding a particular ISA.
Definition: CodeBlock.hpp:45
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:203
gtirb::CodeBlock::bytes_end
bytes_iterator< T > bytes_end()
Get an iterator past the last byte in this block.
Definition: CodeBlock.hpp:186
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:263
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:324
gtirb::ByteInterval
A contiguous region of bytes in a binary.
Definition: ByteInterval.hpp:116
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:293
gtirb::CodeBlock::setSize
void setSize(uint64_t S)
Set the size of this block.
Definition: CodeBlock.hpp:108
gtirb::ByteInterval::const_bytes_range
boost::iterator_range< const_bytes_iterator< T > > const_bytes_range
Const range over bytes.
Definition: ByteInterval.hpp:1739
gtirb::CodeBlock::rawBytes
const T * rawBytes() const
Return the raw data underlying this block's byte vector.
Definition: CodeBlock.hpp:366
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:307
gtirb::ChangeStatus
ChangeStatus
Definition: Observer.hpp:19