Skip to content

Commit 11b2c29

Browse files
committed
swift-reflection-dump: Virtualize logical-to-physical address mapping.
Instead of copying the entire object file and moving around its sections to make an approximate representation of its mapped state, use the memory-mapped buffer from `llvm::ObjectFile`, and deal with non-contiguous logical mappings entirely in readBytes.
1 parent c377e8b commit 11b2c29

File tree

1 file changed

+46
-18
lines changed

1 file changed

+46
-18
lines changed

tools/swift-reflection-dump/swift-reflection-dump.cpp

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,44 +122,72 @@ static bool needToRelocate(SectionRef S) {
122122

123123

124124
class Image {
125-
std::vector<char> Memory;
125+
const ObjectFile *O;
126+
uint64_t VASize;
126127

127-
public:
128-
explicit Image(const ObjectFile *O) {
129-
uint64_t VASize = O->getData().size();
130-
for (SectionRef S : O->sections()) {
131-
if (auto SectionAddr = getSectionAddress(S))
132-
VASize = std::max(VASize, SectionAddr + S.getSize());
133-
}
134-
Memory.resize(VASize);
135-
std::memcpy(&Memory[0], O->getData().data(), O->getData().size());
128+
struct RelocatedRegion {
129+
uint64_t Start, Size;
130+
const char *Base;
131+
};
136132

133+
std::vector<RelocatedRegion> RelocatedRegions;
134+
135+
public:
136+
explicit Image(const ObjectFile *O) : O(O), VASize(O->getData().size()) {
137137
for (SectionRef S : O->sections()) {
138138
if (!needToRelocate(S))
139139
continue;
140140
StringRef Content;
141+
auto SectionAddr = getSectionAddress(S);
142+
if (SectionAddr)
143+
VASize = std::max(VASize, SectionAddr + S.getSize());
144+
141145
if (auto EC = S.getContents(Content))
142146
reportError(EC);
143-
std::memcpy(&Memory[getSectionAddress(S)], Content.data(),
144-
Content.size());
147+
148+
auto PhysOffset = (uintptr_t)Content.data() - (uintptr_t)O->getData().data();
149+
150+
if (PhysOffset == SectionAddr) {
151+
continue;
152+
}
153+
154+
RelocatedRegions.push_back(RelocatedRegion{
155+
SectionAddr,
156+
Content.size(),
157+
Content.data()});
145158
}
146159
}
147160

148161
RemoteAddress getStartAddress() const {
149-
return RemoteAddress((uintptr_t)Memory.data());
162+
return RemoteAddress((uintptr_t)O->getData().data());
150163
}
151164

152165
bool isAddressValid(RemoteAddress Addr, uint64_t Size) const {
153-
return (uintptr_t)Memory.data() <= Addr.getAddressData() &&
154-
Addr.getAddressData() + Size <=
155-
(uintptr_t)Memory.data() + Memory.size();
166+
auto start = getStartAddress().getAddressData();
167+
return start <= Addr.getAddressData()
168+
&& Addr.getAddressData() + Size <= start + VASize;
156169
}
157170

158171
ReadBytesResult readBytes(RemoteAddress Addr, uint64_t Size) {
159172
if (!isAddressValid(Addr, Size))
160173
return ReadBytesResult(nullptr, [](const void *) {});
161-
return ReadBytesResult((const void *)(Addr.getAddressData()),
162-
[](const void *) {});
174+
175+
auto addrValue = Addr.getAddressData();
176+
auto base = O->getData().data();
177+
auto offset = addrValue - (uint64_t)base;
178+
for (auto &region : RelocatedRegions) {
179+
if (region.Start <= offset && offset < region.Start + region.Size) {
180+
// Read shouldn't need to straddle section boundaries.
181+
if (offset + Size > region.Start + region.Size)
182+
return ReadBytesResult(nullptr, [](const void *) {});
183+
184+
offset -= region.Start;
185+
base = region.Base;
186+
break;
187+
}
188+
}
189+
190+
return ReadBytesResult(base + offset, [](const void *) {});
163191
}
164192
};
165193

0 commit comments

Comments
 (0)