Skip to content

Commit 8821c6c

Browse files
committed
swift-reflection-dump: Create ReflectionContext with correct target pointer size
Necessary to make sure we read pointers as the right size, and use the correct object layouts when using swift-reflection-dump for cross-platform dumps.
1 parent c39a2ae commit 8821c6c

File tree

2 files changed

+83
-35
lines changed

2 files changed

+83
-35
lines changed

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,8 @@ class TypeRefBuilder {
376376
// Try to resolve to the underlying type, if we can.
377377
if (opaqueDescriptor->getKind() ==
378378
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
379-
if (!OpaqueUnderlyingTypeReader)
380-
return nullptr;
381-
382379
auto underlyingTy = OpaqueUnderlyingTypeReader(
383-
(const void *)opaqueDescriptor->getIndex(), ordinal);
380+
opaqueDescriptor->getIndex(), ordinal);
384381

385382
if (!underlyingTy)
386383
return nullptr;
@@ -598,7 +595,7 @@ class TypeRefBuilder {
598595
unsigned PointerSize;
599596
std::function<Demangle::Node * (RemoteRef<char>)>
600597
TypeRefDemangler;
601-
std::function<const TypeRef* (const void*, unsigned)>
598+
std::function<const TypeRef* (uint64_t, unsigned)>
602599
OpaqueUnderlyingTypeReader;
603600

604601
public:
@@ -613,9 +610,8 @@ class TypeRefBuilder {
613610
Dem, /*useOpaqueTypeSymbolicReferences*/ true);
614611
}),
615612
OpaqueUnderlyingTypeReader(
616-
[&reader](const void *descriptor, unsigned ordinal) -> const TypeRef* {
617-
auto context = (typename Runtime::StoredPointer)descriptor;
618-
return reader.readUnderlyingTypeForOpaqueTypeDescriptor(context,
613+
[&reader](uint64_t descriptorAddr, unsigned ordinal) -> const TypeRef* {
614+
return reader.readUnderlyingTypeForOpaqueTypeDescriptor(descriptorAddr,
619615
ordinal);
620616
})
621617
{}

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

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -81,23 +81,19 @@ template <typename T> static T unwrap(llvm::Expected<T> value) {
8181
exit(EXIT_FAILURE);
8282
}
8383

84-
using NativeReflectionContext =
85-
swift::reflection::ReflectionContext<External<RuntimeTarget<sizeof(uintptr_t)>>>;
86-
8784
using ReadBytesResult = swift::remote::MemoryReader::ReadBytesResult;
8885

8986
// Since ObjectMemoryReader maintains ownership of the ObjectFiles and their
9087
// raw data, we can vend ReadBytesResults with no-op destructors.
9188
static void no_op_destructor(const void*) {}
9289

93-
9490
class Image {
9591
private:
9692
struct Segment {
9793
uint64_t Addr;
9894
StringRef Contents;
9995
};
100-
96+
const ObjectFile *O;
10197
uint64_t HeaderAddress;
10298
std::vector<Segment> Segments;
10399
llvm::DenseMap<uint64_t, StringRef> DynamicRelocations;
@@ -148,7 +144,6 @@ class Image {
148144
llvm::consumeError(std::move(error));
149145
break;
150146
}
151-
152147
DynamicRelocations.insert({bind.address(), bind.symbolName()});
153148
}
154149
if (error) {
@@ -224,7 +219,7 @@ class Image {
224219
}
225220

226221
public:
227-
explicit Image(const ObjectFile *O) {
222+
explicit Image(const ObjectFile *O) : O(O) {
228223
// Unfortunately llvm doesn't provide a uniform interface for iterating
229224
// loadable segments or dynamic relocations in executable images yet.
230225
if (auto macho = dyn_cast<MachOObjectFile>(O)) {
@@ -249,6 +244,10 @@ class Image {
249244
}
250245
}
251246
}
247+
248+
unsigned getBytesInAddress() const {
249+
return O->getBytesInAddress();
250+
}
252251

253252
uint64_t getStartAddress() const {
254253
return HeaderAddress;
@@ -263,19 +262,21 @@ class Image {
263262
continue;
264263

265264
auto offset = Addr - Segment.Addr;
266-
267-
return Segment.Contents.drop_front(offset);
265+
auto result = Segment.Contents.drop_front(offset);
266+
return result;
268267
}
269268
return {};
270269
}
271270

272271
RemoteAbsolutePointer
273272
resolvePointer(uint64_t Addr, uint64_t pointerValue) const {
274273
auto found = DynamicRelocations.find(Addr);
274+
RemoteAbsolutePointer result;
275275
if (found == DynamicRelocations.end())
276-
return RemoteAbsolutePointer("", pointerValue);
277-
278-
return RemoteAbsolutePointer(found->second, pointerValue);
276+
result = RemoteAbsolutePointer("", pointerValue);
277+
else
278+
result = RemoteAbsolutePointer(found->second, pointerValue);
279+
return result;
279280
}
280281
};
281282

@@ -318,28 +319,42 @@ class ObjectMemoryReader : public MemoryReader {
318319
public:
319320
explicit ObjectMemoryReader(
320321
const std::vector<const ObjectFile *> &ObjectFiles) {
322+
if (ObjectFiles.empty()) {
323+
fputs("no object files provided\n", stderr);
324+
abort();
325+
}
321326
// We use a 16-bit index for images, so can't take more than 64K at once.
322-
if (ObjectFiles.size() >= 0x10000) {
323-
fputs("can't dump more than 65,536 images at once", stderr);
327+
if (ObjectFiles.size() > 0x10000) {
328+
fputs("can't dump more than 65,536 images at once\n", stderr);
324329
abort();
325330
}
326-
for (const ObjectFile *O : ObjectFiles)
331+
unsigned WordSize = 0;
332+
for (const ObjectFile *O : ObjectFiles) {
333+
// All the object files we look at should share a word size.
334+
if (!WordSize) {
335+
WordSize = O->getBytesInAddress();
336+
} else if (WordSize != O->getBytesInAddress()) {
337+
fputs("object files must all be for the same architecture\n", stderr);
338+
abort();
339+
}
327340
Images.emplace_back(O);
341+
}
328342
}
329343

330344
ArrayRef<Image> getImages() const { return Images; }
331345

332346
bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
333347
void *outBuffer) override {
348+
auto wordSize = Images.front().getBytesInAddress();
334349
switch (type) {
335350
case DLQ_GetPointerSize: {
336351
auto result = static_cast<uint8_t *>(outBuffer);
337-
*result = sizeof(void *);
352+
*result = wordSize;
338353
return true;
339354
}
340355
case DLQ_GetSizeSize: {
341356
auto result = static_cast<uint8_t *>(outBuffer);
342-
*result = sizeof(size_t);
357+
*result = wordSize;
343358
return true;
344359
}
345360
}
@@ -409,6 +424,47 @@ class ObjectMemoryReader : public MemoryReader {
409424
}
410425
};
411426

427+
using ReflectionContextOwner
428+
= std::unique_ptr<void, void (*)(void*)>;
429+
430+
template<typename Runtime>
431+
static std::pair<ReflectionContextOwner, TypeRefBuilder &>
432+
makeReflectionContextForMetadataReader(
433+
std::shared_ptr<ObjectMemoryReader> reader) {
434+
using ReflectionContext = ReflectionContext<Runtime>;
435+
auto context = new ReflectionContext(reader);
436+
auto &builder = context->getBuilder();
437+
for (unsigned i = 0, e = reader->getImages().size(); i < e; ++i) {
438+
context->addImage(reader->getImageStartAddress(i));
439+
}
440+
return {ReflectionContextOwner(context,
441+
[](void *x){ delete (ReflectionContext*)x; }),
442+
builder};
443+
}
444+
445+
446+
static std::pair<ReflectionContextOwner, TypeRefBuilder &>
447+
makeReflectionContextForObjectFiles(
448+
const std::vector<const ObjectFile *> &objectFiles) {
449+
auto Reader = std::make_shared<ObjectMemoryReader>(objectFiles);
450+
451+
uint8_t pointerSize;
452+
Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
453+
nullptr, &pointerSize);
454+
455+
switch (pointerSize) {
456+
case 4:
457+
return makeReflectionContextForMetadataReader<External<RuntimeTarget<4>>>
458+
(std::move(Reader));
459+
case 8:
460+
return makeReflectionContextForMetadataReader<External<RuntimeTarget<8>>>
461+
(std::move(Reader));
462+
default:
463+
fputs("unsupported word size in object file\n", stderr);
464+
abort();
465+
}
466+
}
467+
412468
static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
413469
StringRef Arch, ActionType Action,
414470
std::ostream &OS) {
@@ -437,17 +493,14 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
437493
ObjectOwners.push_back(std::move(ObjectOwner));
438494
ObjectFiles.push_back(O);
439495
}
440-
441-
auto Reader = std::make_shared<ObjectMemoryReader>(ObjectFiles);
442-
NativeReflectionContext Context(Reader);
443-
for (unsigned i = 0, e = Reader->getImages().size(); i < e; ++i) {
444-
Context.addImage(Reader->getImageStartAddress(i));
445-
}
496+
497+
auto context = makeReflectionContextForObjectFiles(ObjectFiles);
498+
auto &builder = context.second;
446499

447500
switch (Action) {
448501
case ActionType::DumpReflectionSections:
449502
// Dump everything
450-
Context.getBuilder().dumpAllSections(OS);
503+
builder.dumpAllSections(OS);
451504
break;
452505
case ActionType::DumpTypeLowering: {
453506
for (std::string Line; std::getline(std::cin, Line);) {
@@ -460,15 +513,14 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
460513
Demangle::Demangler Dem;
461514
auto Demangled = Dem.demangleType(Line);
462515
auto *TypeRef =
463-
swift::Demangle::decodeMangledType(Context.getBuilder(), Demangled);
516+
swift::Demangle::decodeMangledType(builder, Demangled);
464517
if (TypeRef == nullptr) {
465518
OS << "Invalid typeref: " << Line << "\n";
466519
continue;
467520
}
468521

469522
TypeRef->dump(OS);
470-
auto *TypeInfo =
471-
Context.getBuilder().getTypeConverter().getTypeInfo(TypeRef);
523+
auto *TypeInfo = builder.getTypeConverter().getTypeInfo(TypeRef);
472524
if (TypeInfo == nullptr) {
473525
OS << "Invalid lowering\n";
474526
continue;

0 commit comments

Comments
 (0)