forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStub.cpp
More file actions
109 lines (95 loc) · 3.23 KB
/
Copy pathStub.cpp
File metadata and controls
109 lines (95 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* Copyright 2017 - 2025 R. Thomas
* Copyright 2017 - 2025 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LIEF/MachO/Stub.hpp"
#include "LIEF/MachO/Section.hpp"
#include "LIEF/utils.hpp"
#include "internal_utils.hpp"
#include "logging.hpp"
namespace LIEF::MachO {
inline uint32_t nb_stubs(const Section& section) {
return section.size() / section.reserved2();
}
inline uint64_t get_offset(size_t pos, const Section& section) {
return section.reserved2() * pos;
}
const Section*
Stub::Iterator::find_section_offset(size_t pos, uint64_t& offset) const
{
if (stubs_.size() == 1) {
offset = get_offset(pos, *stubs_.back());
return stubs_.back();
}
if (stubs_.size() == 2) {
const Section* first = stubs_[0];
const Section* second = stubs_[1];
const uint32_t nb_stubs_1 = nb_stubs(*first);
[[maybe_unused]] const uint32_t nb_stubs_2 = nb_stubs(*second);
if (pos < nb_stubs_1) {
offset = get_offset(pos, *first);
return first;
}
assert(nb_stubs_1 <= pos && pos < nb_stubs_1 + nb_stubs_2);
offset = get_offset(pos - nb_stubs_1, *second);
return second;
}
uint64_t limit = nb_stubs(*stubs_[0]);
for (size_t idx = 0; idx < stubs_.size(); ++idx) {
if (pos < limit) {
offset = idx > 0 ?
get_offset(pos - (limit - nb_stubs(*stubs_[idx - 1])), *stubs_[idx]) :
get_offset(pos, *stubs_[idx]);
return stubs_[idx];
}
if (idx < stubs_.size() - 1) {
limit += nb_stubs(*stubs_[idx + 1]);
}
}
return nullptr;
}
Stub Stub::Iterator::operator*() const {
uint64_t offset = 0;
const Section* section = find_section_offset(pos_, offset);
if (section == nullptr) {
logging::fatal_error("Can't find section for stub position: {}", pos_);
}
LIEF::span<const uint8_t> content = section->content();
const uint32_t stride = section->reserved2();
if (offset >= content.size() || offset + stride > content.size()) {
logging::fatal_error("Stub out of range at pos: {}", pos_);
}
LIEF::span<const uint8_t> stub_raw = section->content().subspan(offset, stride);
const uint64_t addr = section->virtual_address() + offset;
return Stub(
target_info_, addr, as_vector(stub_raw)
);
}
#if !defined(LIEF_EXTENDED)
result<uint64_t> Stub::target() const {
logging::needs_lief_extended();
return make_error_code(lief_errors::require_extended_version);
}
#endif
std::ostream& operator<<(std::ostream& os, const Stub& stub) {
if (is_extended()) {
os << fmt::format("0x{:010x}: 0x{:010x} ({} bytes)",
stub.address(), stub.target().value_or(0),
stub.raw().size());
} else {
os << fmt::format("0x{:010x} ({} bytes)", stub.address(), stub.raw().size());
}
return os;
}
}