LIEF: Library to Instrument Executable Formats Version 0.17.0
Loading...
Searching...
No Matches
iostream.hpp
Go to the documentation of this file.
1/* Copyright 2017 - 2025 R. Thomas
2 * Copyright 2017 - 2025 Quarkslab
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef LIEF_OSTREAM_H
17#define LIEF_OSTREAM_H
18#include <limits>
19#include <cassert>
20#include <ios>
21#include <cstdint>
22#include <cstring>
23#include <vector>
24#include <array>
25
26#include "LIEF/span.hpp"
27#include "LIEF/optional.hpp"
29
30namespace LIEF {
32 public:
33 static size_t uleb128_size(uint64_t value);
34 static size_t sleb128_size(int64_t value);
35
36 using pos_type = std::streampos;
37 using off_type = std::streamoff;
38 enum class RELOC_OP {
40 };
41
42 vector_iostream() = default;
43 vector_iostream(std::vector<uint8_t>& ref) :
44 raw_(&ref)
45 {}
46 vector_iostream(bool endian_swap) :
47 endian_swap_(endian_swap)
48 {}
49
51 raw_->reserve(size);
52 return *this;
53 }
54
56 raw_->reserve(raw_->size() + size);
57 return *this;
58 }
59
60 vector_iostream& put(uint8_t c);
61 vector_iostream& write(const uint8_t* s, std::streamsize n);
63 return write(sp.data(), sp.size());
64 }
65
66 vector_iostream& write(std::vector<uint8_t> s) {
67 if (s.empty()) {
68 return *this;
69 }
70 return write(s.data(), s.size());
71 }
72
73 vector_iostream& write(const std::string& s) {
74 return write(reinterpret_cast<const uint8_t*>(s.c_str()), s.size() + 1);
75 }
76
77 bool empty() const {
78 return raw_->empty();
79 }
80
81 vector_iostream& write(const std::u16string& s, bool with_null_char);
82
83 vector_iostream& write(size_t count, uint8_t value) {
84 raw_->insert(raw_->end(), count, value);
85 current_pos_ += count;
86 return *this;
87 }
88 vector_iostream& write_sized_int(uint64_t value, size_t size) {
89 const uint64_t stack_val = value;
90 return write(reinterpret_cast<const uint8_t*>(&stack_val), size);
91 }
92
94 return write(other.data());
95 }
96
97 template<class T, typename = typename std::enable_if<std::is_standard_layout<T>::value && std::is_trivial<T>::value>::type>
98 vector_iostream& write(const T& t) {
99 const auto pos = static_cast<size_t>(tellp());
100 if (raw_->size() < (pos + sizeof(T))) {
101 raw_->resize(pos + sizeof(T));
102 }
103 if (endian_swap_) {
104 T tmp = t;
105 swap_endian(&tmp);
106 memcpy(raw_->data() + pos, &tmp, sizeof(T));
107 } else {
108 memcpy(raw_->data() + pos, &t, sizeof(T));
109 }
110 current_pos_ += sizeof(T);
111 return *this;
112 }
113
114 vector_iostream& align(size_t alignment, uint8_t fill = 0);
115
116 template<typename T>
117 vector_iostream& write(const std::pair<T, T>& p) {
118 write(p.first);
119 write(p.second);
120 return *this;
121 }
122
123 template<typename T, size_t size>
124 vector_iostream& write(const std::array<T, size>& t) {
125 static_assert(std::numeric_limits<T>::is_integer, "Requires integer type");
126 for (T val : t) {
127 write<T>(val);
128 }
129 return *this;
130 }
131
132 template<typename T>
133 vector_iostream& write(const std::vector<T>& elements) {
134 for (const T& e : elements) {
135 write(e);
136 }
137 return *this;
138 }
139
140 template<typename T, class U>
141 vector_iostream& write(const optional<U>& opt) {
142 return opt ? write<T>(*opt) : *this;
143 }
144
147
148 vector_iostream& get(std::vector<uint8_t>& c) {
149 c = *raw_;
150 return *this;
151 }
152 vector_iostream& move(std::vector<uint8_t>& c) {
153 c = std::move(owned_);
154 return *this;
155 }
156
158 return *this;
159 }
160
161 size_t size() const {
162 return raw_->size();
163 }
164
165 // seeks:
166 pos_type tellp() const {
167 return current_pos_;
168 }
169
171 current_pos_ = p;
172 return *this;
173 }
174
176 return seekp(raw_->size());
177 }
178
179 vector_iostream& pad(size_t size, uint8_t value = 0) {
180 raw_->resize(raw_->size() + size, value);
181 return *this;
182 }
183
184 vector_iostream& seekp(vector_iostream::off_type p, std::ios_base::seekdir dir);
185
186 const std::vector<uint8_t>& raw() const {
187 return *raw_;
188 }
189
190 std::vector<uint8_t>& raw() {
191 return *raw_;
192 }
193
194 void set_endian_swap(bool swap) {
195 endian_swap_ = swap;
196 }
197
198 template<class T>
199 vector_iostream& reloc(uint64_t offset, T shift, RELOC_OP op = RELOC_OP::ADD) {
200 static_assert(std::numeric_limits<T>::is_integer, "Requires integer type");
201 if (offset > raw_->size() || (offset + sizeof(T) > raw_->size())) {
202 return *this;
203 }
204 T& value = *reinterpret_cast<T*>(raw_->data() + offset);
205
206 switch (op) {
207 case RELOC_OP::ADD: value += shift; break;
208 case RELOC_OP::SUB: value -= shift; break;
209 }
210
211 return *this;
212 }
213
215 fixups_.resize(count);
216 return *this;
217 }
218
219
220 vector_iostream& record_fixup(size_t id, bool cond) {
221 if (cond) {
222 fixups_[id].push_back(tellp());
223 }
224 return *this;
225 }
226
227
229 return record_fixup(id, /*cond=*/true);
230 }
231
232 template<class T>
233 vector_iostream& apply_fixup(size_t id, T value) {
234 static_assert(std::numeric_limits<T>::is_integer, "Requires integer type");
235 for (uint64_t offset : get_fixups(id)) {
236 reloc<T>(offset, value);
237 }
238 return *this;
239 }
240
241 const std::vector<uint64_t>& get_fixups(size_t id) const {
242 return fixups_[id];
243 }
244
245 template<class T>
246 T* edit_as() {
247 assert(((size_t)current_pos_ + sizeof(T)) <= raw_->size());
248 return reinterpret_cast<T*>(raw_->data() + current_pos_);
249 }
250
251 template<class T>
252 T* edit_as(size_t pos) {
253 seekp(pos);
254 assert(((size_t)current_pos_ + sizeof(T)) <= raw_->size());
255 return reinterpret_cast<T*>(raw_->data() + current_pos_);
256 }
257
258 const vector_iostream& copy_into(const span<uint8_t>& sp, size_t sz) const {
259 assert(sz <= raw_->size());
260 std::copy(raw_->data(), raw_->data() + sz, sp.data());
261 return *this;
262 }
263
264 const vector_iostream& copy_into(const span<uint8_t>& sp) const {
265 if (sp.size() < this->size()) {
266 return *this;
267 }
268
269 std::copy(raw_->begin(), raw_->end(), sp.begin());
270 return *this;
271 }
272
274 return *raw_;
275 }
276
278 raw_->clear();
279 return *this;
280 }
281
282 std::vector<uint8_t>::iterator begin() {
283 return raw_->begin();
284 }
285
286 std::vector<uint8_t>::iterator end() {
287 return raw_->end();
288 }
289
290 std::vector<uint8_t>::const_iterator begin() const {
291 return raw_->begin();
292 }
293
294 std::vector<uint8_t>::const_iterator end() const {
295 return raw_->end();
296 }
297
298 private:
299 std::vector<std::vector<uint64_t>> fixups_;
300 pos_type current_pos_ = 0;
301 std::vector<uint8_t> owned_;
302 std::vector<uint8_t>* raw_ = &owned_;
303 bool endian_swap_ = false;
304};
305
307 public:
308 ScopeOStream(const ScopeOStream&) = delete;
310
313
314 explicit ScopeOStream(vector_iostream& stream, uint64_t pos) :
315 pos_{stream.tellp()},
316 stream_{stream}
317 {
318 stream_.seekp(pos);
319 }
320
321 explicit ScopeOStream(vector_iostream& stream) :
322 pos_{stream.tellp()},
323 stream_{stream}
324 {}
325
327 stream_.seekp(pos_);
328 }
329
330 vector_iostream* operator->() {
331 return &stream_;
332 }
333
334 vector_iostream& operator*() {
335 return stream_;
336 }
337
338 const vector_iostream& operator*() const {
339 return stream_;
340 }
341
342 private:
343 std::streampos pos_ = 0;
344 vector_iostream& stream_;
345};
346
347
348
349}
350#endif
Definition iostream.hpp:306
vector_iostream & operator*()
Definition iostream.hpp:334
ScopeOStream(vector_iostream &stream)
Definition iostream.hpp:321
vector_iostream * operator->()
Definition iostream.hpp:330
ScopeOStream(const ScopeOStream &)=delete
ScopeOStream & operator=(const ScopeOStream &)=delete
~ScopeOStream()
Definition iostream.hpp:326
ScopeOStream(vector_iostream &stream, uint64_t pos)
Definition iostream.hpp:314
ScopeOStream & operator=(ScopeOStream &&)=delete
const vector_iostream & operator*() const
Definition iostream.hpp:338
ScopeOStream(ScopeOStream &&)=delete
Definition iostream.hpp:31
std::vector< uint8_t > & raw()
Definition iostream.hpp:190
vector_iostream & reloc(uint64_t offset, T shift, RELOC_OP op=RELOC_OP::ADD)
Definition iostream.hpp:199
static size_t sleb128_size(int64_t value)
vector_iostream & flush()
Definition iostream.hpp:157
std::vector< uint8_t >::iterator end()
Definition iostream.hpp:286
vector_iostream & seekp(vector_iostream::off_type p, std::ios_base::seekdir dir)
const vector_iostream & copy_into(const span< uint8_t > &sp) const
Definition iostream.hpp:264
const std::vector< uint8_t > & raw() const
Definition iostream.hpp:186
bool empty() const
Definition iostream.hpp:77
vector_iostream & write(const std::array< T, size > &t)
Definition iostream.hpp:124
vector_iostream & seek_end()
Definition iostream.hpp:175
vector_iostream & apply_fixup(size_t id, T value)
Definition iostream.hpp:233
size_t size() const
Definition iostream.hpp:161
vector_iostream & put(uint8_t c)
vector_iostream & write_uleb128(uint64_t value)
vector_iostream & write(const uint8_t *s, std::streamsize n)
vector_iostream & seekp(pos_type p)
Definition iostream.hpp:170
vector_iostream & write(const std::u16string &s, bool with_null_char)
vector_iostream & clear()
Definition iostream.hpp:277
vector_iostream & write(const optional< U > &opt)
Definition iostream.hpp:141
span< const uint8_t > data() const
Definition iostream.hpp:273
vector_iostream & increase_capacity(size_t size)
Definition iostream.hpp:55
vector_iostream & init_fixups(size_t count)
Definition iostream.hpp:214
vector_iostream & move(std::vector< uint8_t > &c)
Definition iostream.hpp:152
T * edit_as(size_t pos)
Definition iostream.hpp:252
vector_iostream & write_sized_int(uint64_t value, size_t size)
Definition iostream.hpp:88
vector_iostream & write(const std::pair< T, T > &p)
Definition iostream.hpp:117
vector_iostream & write(const std::string &s)
Definition iostream.hpp:73
std::streampos pos_type
Definition iostream.hpp:36
vector_iostream & record_fixup(size_t id)
Definition iostream.hpp:228
vector_iostream & record_fixup(size_t id, bool cond)
Definition iostream.hpp:220
const std::vector< uint64_t > & get_fixups(size_t id) const
Definition iostream.hpp:241
pos_type tellp() const
Definition iostream.hpp:166
vector_iostream & write(const vector_iostream &other)
Definition iostream.hpp:93
vector_iostream & write(span< const uint8_t > sp)
Definition iostream.hpp:62
vector_iostream & align(size_t alignment, uint8_t fill=0)
vector_iostream & reserve(size_t size)
Definition iostream.hpp:50
void set_endian_swap(bool swap)
Definition iostream.hpp:194
RELOC_OP
Definition iostream.hpp:38
@ SUB
Definition iostream.hpp:39
@ ADD
Definition iostream.hpp:39
vector_iostream & write(std::vector< uint8_t > s)
Definition iostream.hpp:66
vector_iostream & write(const T &t)
Definition iostream.hpp:98
std::vector< uint8_t >::const_iterator end() const
Definition iostream.hpp:294
T * edit_as()
Definition iostream.hpp:246
static size_t uleb128_size(uint64_t value)
std::streamoff off_type
Definition iostream.hpp:37
std::vector< uint8_t >::iterator begin()
Definition iostream.hpp:282
vector_iostream & write(const std::vector< T > &elements)
Definition iostream.hpp:133
vector_iostream(std::vector< uint8_t > &ref)
Definition iostream.hpp:43
vector_iostream & write_sleb128(int64_t value)
const vector_iostream & copy_into(const span< uint8_t > &sp, size_t sz) const
Definition iostream.hpp:258
std::vector< uint8_t >::const_iterator begin() const
Definition iostream.hpp:290
vector_iostream & write(size_t count, uint8_t value)
Definition iostream.hpp:83
vector_iostream(bool endian_swap)
Definition iostream.hpp:46
vector_iostream & pad(size_t size, uint8_t value=0)
Definition iostream.hpp:179
vector_iostream & get(std::vector< uint8_t > &c)
Definition iostream.hpp:148
LIEF namespace.
Definition Abstract/Binary.hpp:36
tcb::span< ElementType, Extent > span
Definition span.hpp:22
void swap_endian(T *)
Definition endianness_support.hpp:116