GTIRB  v2.1.0
GrammaTech Intermediate Representation for Binaries: C++ API
DataBlock.hpp
Go to the documentation of this file.
1 //===- DataBlock.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_DataBlock_H
16 #define GTIRB_DataBlock_H
17 
18 #include <gtirb/Addr.hpp>
19 #include <gtirb/ByteInterval.hpp>
20 #include <gtirb/Node.hpp>
21 #include <cstdint>
22 #include <functional>
23 #include <optional>
24 #include <vector>
25 
28 
29 namespace gtirb {
30 namespace proto {
31 class DataBlock;
32 }
33 
34 template <class T> class ErrorOr;
35 
45  DataBlock(Context& C) : Node(C, Kind::DataBlock) {}
46  DataBlock(Context& C, uint64_t S, const UUID& U)
47  : Node(C, Kind::DataBlock, U), Size(S) {}
48  DataBlock(Context& C, uint64_t S) : Node(C, Kind::DataBlock), Size(S) {}
49 
50  static DataBlock* Create(Context& C, uint64_t S, const UUID& U) {
51  return C.Create<DataBlock>(C, S, U);
52  }
53 
54 public:
58  static DataBlock* Create(Context& C) { return C.Create<DataBlock>(C); }
59 
65  static DataBlock* Create(Context& C, uint64_t Size) {
66  return C.Create<DataBlock>(C, Size);
67  }
68 
70  ByteInterval* getByteInterval() { return Parent; }
72  const ByteInterval* getByteInterval() const { return Parent; }
73 
78  uint64_t getSize() const { return Size; }
79 
82  uint64_t getOffset() const;
83 
87  std::optional<Addr> getAddress() const;
88 
94  void setSize(uint64_t S) {
95  if (Observer) {
96  std::swap(S, Size);
97  [[maybe_unused]] ChangeStatus Status =
98  Observer->sizeChange(this, S, Size);
99  assert(Status != ChangeStatus::Rejected &&
100  "recovering from rejected size change is not implemented yet");
101  } else {
102  Size = S;
103  }
104  }
105 
110  template <typename T> using bytes_iterator = ByteInterval::bytes_iterator<T>;
115  template <typename T> using bytes_range = ByteInterval::bytes_range<T>;
120  template <typename T>
126  template <typename T>
128 
136  template <typename T> bytes_iterator<T> bytes_begin() {
137  assert(Parent && "Block has no byte interval!");
138  return bytes_begin<T>(Parent->getBoostEndianOrder());
139  }
140 
151  template <typename T>
152  bytes_iterator<T>
153  bytes_begin(boost::endian::order InputOrder,
154  boost::endian::order OutputOrder = boost::endian::order::native) {
155  assert(Parent && "Block has no byte interval!");
156  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
157  }
158 
166  template <typename T> bytes_iterator<T> bytes_end() {
167  assert(Parent && "Block has no byte interval!");
168  return bytes_end<T>(Parent->getBoostEndianOrder());
169  }
170 
181  template <typename T>
182  bytes_iterator<T>
183  bytes_end(boost::endian::order InputOrder,
184  boost::endian::order OutputOrder = boost::endian::order::native) {
185  assert(Parent && "Block has no byte interval!");
186  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
187  }
188 
196  template <typename T> bytes_range<T> bytes() {
197  assert(Parent && "Block has no byte interval!");
198  return bytes<T>(Parent->getBoostEndianOrder());
199  }
200 
211  template <typename T>
212  bytes_range<T>
213  bytes(boost::endian::order InputOrder,
214  boost::endian::order OutputOrder = boost::endian::order::native) {
215  assert(Parent && "Block has no byte interval!");
216  return bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
217  bytes_end<T>(InputOrder, OutputOrder));
218  }
219 
227  template <typename T> const_bytes_iterator<T> bytes_begin() const {
228  assert(Parent && "Block has no byte interval!");
229  return bytes_begin<T>(Parent->getBoostEndianOrder());
230  }
231 
242  template <typename T>
244  boost::endian::order InputOrder,
245  boost::endian::order OutputOrder = boost::endian::order::native) const {
246  assert(Parent && "Block has no byte interval!");
247  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset();
248  }
249 
257  template <typename T> const_bytes_iterator<T> bytes_end() const {
258  assert(Parent && "Block has no byte interval!");
259  return bytes_end<T>(Parent->getBoostEndianOrder());
260  }
261 
272  template <typename T>
274  boost::endian::order InputOrder,
275  boost::endian::order OutputOrder = boost::endian::order::native) const {
276  assert(Parent && "Block has no byte interval!");
277  return Parent->bytes_begin<T>(InputOrder, OutputOrder) + getOffset() + Size;
278  }
279 
287  template <typename T> const_bytes_range<T> bytes() const {
288  assert(Parent && "Block has no byte interval!");
289  return bytes<T>(Parent->getBoostEndianOrder());
290  }
291 
302  template <typename T>
303  const_bytes_range<T>
304  bytes(boost::endian::order InputOrder,
305  boost::endian::order OutputOrder = boost::endian::order::native) const {
306  assert(Parent && "Block has no byte interval!");
307  return const_bytes_range<T>(bytes_begin<T>(InputOrder, OutputOrder),
308  bytes_end<T>(InputOrder, OutputOrder));
309  }
310 
326  template <typename T> T* rawBytes() {
327  assert(Parent && "Block has no byte interval!");
328  return reinterpret_cast<T*>(Parent->rawBytes<uint8_t>() + getOffset());
329  }
330 
346  template <typename T> const T* rawBytes() const {
347  assert(Parent && "Block has no byte interval!");
348  return reinterpret_cast<const T*>(Parent->rawBytes<uint8_t>() +
349  getOffset());
350  }
351 
353  static bool classof(const Node* N) { return N->getKind() == Kind::DataBlock; }
355 
356 private:
357  ByteInterval* Parent{nullptr};
358  DataBlockObserver* Observer{nullptr};
359  uint64_t Size{0};
360 
361  void setParent(ByteInterval* BI, DataBlockObserver* O) {
362  Parent = BI;
363  Observer = O;
364  }
365 
367  using MessageType = proto::DataBlock;
368 
374  void toProtobuf(MessageType* Message) const;
375 
382  static ErrorOr<DataBlock*> fromProtobuf(Context& C,
383  const MessageType& Message);
384 
385  // Present for testing purposes only.
386  void save(std::ostream& Out) const;
387 
388  // Present for testing purposes only.
389  static DataBlock* load(Context& C, std::istream& In);
390 
391  friend class Context; // Enables Context::Create
392  friend class ByteInterval; // Enables to/fromProtobuf, setByteInterval
393  friend class SerializationTestHarness; // Testing support.
394 };
395 } // namespace gtirb
396 
397 #endif // GTIRB_DataBlock_H
gtirb::DataBlock::const_bytes_iterator
ByteInterval::const_bytes_iterator< T > const_bytes_iterator
Const iterator over bytes in this block.
Definition: DataBlock.hpp:121
gtirb::ByteInterval::bytes_iterator
BytesBaseIterator< ByteInterval, T > bytes_iterator
Iterator over bytes.
Definition: ByteInterval.hpp:1721
gtirb::Context::Create
NodeTy * Create(Args &&... TheArgs)
Create an object of type T.
Definition: Context.hpp:126
gtirb::Node
Represents the base of the Node class hierarchy.
Definition: Node.hpp:39
gtirb::DataBlock::Create
static DataBlock * Create(Context &C)
Create an unitialized DataBlock object.
Definition: DataBlock.hpp:58
gtirb::DataBlock::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: DataBlock.hpp:183
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::DataBlock::bytes
bytes_range< T > bytes()
Get a range of the bytes in this block.
Definition: DataBlock.hpp:196
gtirb::DataBlock::bytes_begin
bytes_iterator< T > bytes_begin()
Get an iterator to the first byte in this block.
Definition: DataBlock.hpp:136
gtirb::DataBlock::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: DataBlock.hpp:304
gtirb::DataBlock
Represents a data object, possibly symbolic.
Definition: DataBlock.hpp:44
gtirb::DataBlock::rawBytes
T * rawBytes()
Return the raw data underlying this block's byte vector.
Definition: DataBlock.hpp:326
gtirb::Context
The context under which GTIRB operations occur.
Definition: Context.hpp:63
Node.hpp
Class gtirb::Node.
gtirb::DataBlock::bytes_range
ByteInterval::bytes_range< T > bytes_range
Range over bytes in this block.
Definition: DataBlock.hpp:115
gtirb::ByteInterval::bytes_range
boost::iterator_range< bytes_iterator< T > > bytes_range
Range over bytes.
Definition: ByteInterval.hpp:1727
gtirb::DataBlock::const_bytes_range
ByteInterval::const_bytes_range< T > const_bytes_range
Const range over bytes in this block.
Definition: DataBlock.hpp:127
gtirb::DataBlock::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: DataBlock.hpp:273
gtirb::DataBlock::bytes_iterator
ByteInterval::bytes_iterator< T > bytes_iterator
Iterator over bytes in this block.
Definition: DataBlock.hpp:110
gtirb::DataBlock::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: DataBlock.hpp:243
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
Main namespace for the GTIRB API.
Definition: Addr.hpp:28
ByteInterval.hpp
Class gtirb::ByteInterval.
gtirb::DataBlock::bytes_end
const_bytes_iterator< T > bytes_end() const
Get an iterator past the last byte in this block.
Definition: DataBlock.hpp:257
gtirb::ByteInterval::const_bytes_iterator
BytesBaseIterator< const ByteInterval, T > const_bytes_iterator
Const iterator over bytes.
Definition: ByteInterval.hpp:1733
gtirb::DataBlock::getByteInterval
const ByteInterval * getByteInterval() const
Get the ByteInterval this block belongs to.
Definition: DataBlock.hpp:72
gtirb::DataBlock::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: DataBlock.hpp:213
gtirb::DataBlock::getSize
uint64_t getSize() const
Get the size of a DataBlock.
Definition: DataBlock.hpp:78
gtirb::DataBlock::bytes_end
bytes_iterator< T > bytes_end()
Get an iterator past the last byte in this block.
Definition: DataBlock.hpp:166
gtirb::DataBlock::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: DataBlock.hpp:153
gtirb::DataBlock::rawBytes
const T * rawBytes() const
Return the raw data underlying this block's byte vector.
Definition: DataBlock.hpp:346
gtirb::DataBlock::getByteInterval
ByteInterval * getByteInterval()
Get the ByteInterval this block belongs to.
Definition: DataBlock.hpp:70
gtirb::DataBlock::setSize
void setSize(uint64_t S)
Set the size of this block.
Definition: DataBlock.hpp:94
gtirb::DataBlock::bytes
const_bytes_range< T > bytes() const
Get a range of the bytes in this block.
Definition: DataBlock.hpp:287
gtirb::ByteInterval
A contiguous region of bytes in a binary.
Definition: ByteInterval.hpp:116
gtirb::ByteInterval::const_bytes_range
boost::iterator_range< const_bytes_iterator< T > > const_bytes_range
Const range over bytes.
Definition: ByteInterval.hpp:1739
gtirb::DataBlock::Create
static DataBlock * Create(Context &C, uint64_t Size)
Create a DataBlock object.
Definition: DataBlock.hpp:65
gtirb::DataBlock::bytes_begin
const_bytes_iterator< T > bytes_begin() const
Get an iterator to the first byte in this block.
Definition: DataBlock.hpp:227
Addr.hpp
Class gtirb::Addr and related functions.
gtirb::ChangeStatus
ChangeStatus
Definition: Observer.hpp:19