Skip to content

Commit bce1636

Browse files
committed
swift-reflection-dump: Mach-O binding list support
When resolving a pointer value in a Mach-O image, look through the binding list to see if a symbol address will be added at a given location, and return an unresolved `RemoteAbsolutePointer` with the symbol name if so.
1 parent 8add25a commit bce1636

File tree

1 file changed

+74
-5
lines changed

1 file changed

+74
-5
lines changed

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

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,14 @@ class Image {
100100

101101
uint64_t HeaderAddress;
102102
std::vector<Segment> Segments;
103+
llvm::DenseMap<uint64_t, StringRef> DynamicRelocations;
103104

104105
void scanMachO(const MachOObjectFile *O) {
105106
using namespace llvm::MachO;
106107

107108
HeaderAddress = UINT64_MAX;
108109

110+
// Collect the segment preferred vm mappings.
109111
for (const auto &Load : O->load_commands()) {
110112
if (Load.C.cmd == LC_SEGMENT_64) {
111113
auto Seg = O->getSegment64LoadCommand(Load);
@@ -135,6 +137,23 @@ class Image {
135137
HeaderAddress = std::min(HeaderAddress, (uint64_t)Seg.vmaddr);
136138
}
137139
}
140+
141+
// Walk through the bindings list to collect all the external references
142+
// in the image.
143+
llvm::Error error = llvm::Error::success();
144+
auto OO = const_cast<MachOObjectFile*>(O);
145+
146+
for (auto bind : OO->bindTable(error)) {
147+
if (error) {
148+
llvm::consumeError(std::move(error));
149+
break;
150+
}
151+
152+
DynamicRelocations.insert({bind.address(), bind.symbolName()});
153+
}
154+
if (error) {
155+
llvm::consumeError(std::move(error));
156+
}
138157
}
139158

140159
template<typename ELFT>
@@ -249,6 +268,15 @@ class Image {
249268
}
250269
return {};
251270
}
271+
272+
RemoteAbsolutePointer
273+
resolvePointer(uint64_t Addr, uint64_t pointerValue) const {
274+
auto found = DynamicRelocations.find(Addr);
275+
if (found == DynamicRelocations.end())
276+
return RemoteAbsolutePointer("", pointerValue);
277+
278+
return RemoteAbsolutePointer(found->second, pointerValue);
279+
}
252280
};
253281

254282
/// MemoryReader that reads from the on-disk representation of an executable
@@ -260,14 +288,31 @@ class Image {
260288
/// the image.
261289
class ObjectMemoryReader : public MemoryReader {
262290
std::vector<Image> Images;
291+
292+
std::pair<const Image *, uint64_t>
293+
decodeImageIndexAndAddress(uint64_t Addr) const {
294+
unsigned index = Addr >> 48;
295+
if (index >= Images.size())
296+
return {nullptr, 0};
297+
298+
return {&Images[index], Addr & ((1ull << 48) - 1)};
299+
}
300+
301+
uint64_t
302+
encodeImageIndexAndAddress(const Image *image, uint64_t imageAddr) const {
303+
unsigned index = image - Images.data();
304+
return imageAddr | ((uint64_t)index << 48);
305+
}
263306

264307
StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size) {
265-
auto imageIndex = Addr >> 48;
266-
if (imageIndex >= Images.size())
308+
const Image *image;
309+
uint64_t imageAddr;
310+
std::tie(image, imageAddr) = decodeImageIndexAndAddress(Addr);
311+
312+
if (!image)
267313
return StringRef();
268314

269-
return Images[imageIndex]
270-
.getContentsAtAddress(Addr & 0xFFFFFFFFFFFFull, Size);
315+
return image->getContentsAtAddress(imageAddr, Size);
271316
}
272317

273318
public:
@@ -305,7 +350,8 @@ class ObjectMemoryReader : public MemoryReader {
305350
RemoteAddress getImageStartAddress(unsigned i) const {
306351
assert(i < Images.size());
307352

308-
return RemoteAddress(Images[i].getStartAddress() | ((uint64_t)i << 48));
353+
return RemoteAddress(
354+
encodeImageIndexAndAddress(&Images[i], Images[i].getStartAddress()));
309355
}
310356

311357
// TODO: We could consult the dynamic symbol tables of the images to
@@ -338,6 +384,29 @@ class ObjectMemoryReader : public MemoryReader {
338384
Dest.append(resultBuffer.begin(), resultBuffer.begin() + i);
339385
return true;
340386
}
387+
388+
RemoteAbsolutePointer resolvePointer(RemoteAddress Addr,
389+
uint64_t pointerValue) override {
390+
auto addrValue = Addr.getAddressData();
391+
const Image *image;
392+
uint64_t imageAddr;
393+
std::tie(image, imageAddr) =
394+
decodeImageIndexAndAddress(addrValue);
395+
396+
if (!image)
397+
return RemoteAbsolutePointer();
398+
399+
auto resolved = image->resolvePointer(imageAddr, pointerValue);
400+
401+
if (resolved && resolved.isResolved()) {
402+
// Mix in the image index again to produce a remote address pointing into
403+
// the same image.
404+
return RemoteAbsolutePointer("", encodeImageIndexAndAddress(image,
405+
resolved.getResolvedAddress().getAddressData()));
406+
}
407+
// If the pointer is relative to an unresolved relocation, leave it as is.
408+
return resolved;
409+
}
341410
};
342411

343412
static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,

0 commit comments

Comments
 (0)