@@ -81,23 +81,19 @@ template <typename T> static T unwrap(llvm::Expected<T> value) {
81
81
exit (EXIT_FAILURE);
82
82
}
83
83
84
- using NativeReflectionContext =
85
- swift::reflection::ReflectionContext<External<RuntimeTarget<sizeof (uintptr_t )>>>;
86
-
87
84
using ReadBytesResult = swift::remote::MemoryReader::ReadBytesResult;
88
85
89
86
// Since ObjectMemoryReader maintains ownership of the ObjectFiles and their
90
87
// raw data, we can vend ReadBytesResults with no-op destructors.
91
88
static void no_op_destructor (const void *) {}
92
89
93
-
94
90
class Image {
95
91
private:
96
92
struct Segment {
97
93
uint64_t Addr;
98
94
StringRef Contents;
99
95
};
100
-
96
+ const ObjectFile *O;
101
97
uint64_t HeaderAddress;
102
98
std::vector<Segment> Segments;
103
99
llvm::DenseMap<uint64_t , StringRef> DynamicRelocations;
@@ -148,7 +144,6 @@ class Image {
148
144
llvm::consumeError (std::move (error));
149
145
break ;
150
146
}
151
-
152
147
DynamicRelocations.insert ({bind.address (), bind.symbolName ()});
153
148
}
154
149
if (error) {
@@ -224,7 +219,7 @@ class Image {
224
219
}
225
220
226
221
public:
227
- explicit Image (const ObjectFile *O) {
222
+ explicit Image (const ObjectFile *O) : O(O) {
228
223
// Unfortunately llvm doesn't provide a uniform interface for iterating
229
224
// loadable segments or dynamic relocations in executable images yet.
230
225
if (auto macho = dyn_cast<MachOObjectFile>(O)) {
@@ -249,6 +244,10 @@ class Image {
249
244
}
250
245
}
251
246
}
247
+
248
+ unsigned getBytesInAddress () const {
249
+ return O->getBytesInAddress ();
250
+ }
252
251
253
252
uint64_t getStartAddress () const {
254
253
return HeaderAddress;
@@ -263,19 +262,21 @@ class Image {
263
262
continue ;
264
263
265
264
auto offset = Addr - Segment.Addr ;
266
-
267
- return Segment. Contents . drop_front (offset) ;
265
+ auto result = Segment. Contents . drop_front (offset);
266
+ return result ;
268
267
}
269
268
return {};
270
269
}
271
270
272
271
RemoteAbsolutePointer
273
272
resolvePointer (uint64_t Addr, uint64_t pointerValue) const {
274
273
auto found = DynamicRelocations.find (Addr);
274
+ RemoteAbsolutePointer result;
275
275
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;
279
280
}
280
281
};
281
282
@@ -318,28 +319,42 @@ class ObjectMemoryReader : public MemoryReader {
318
319
public:
319
320
explicit ObjectMemoryReader (
320
321
const std::vector<const ObjectFile *> &ObjectFiles) {
322
+ if (ObjectFiles.empty ()) {
323
+ fputs (" no object files provided\n " , stderr);
324
+ abort ();
325
+ }
321
326
// 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);
324
329
abort ();
325
330
}
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
+ }
327
340
Images.emplace_back (O);
341
+ }
328
342
}
329
343
330
344
ArrayRef<Image> getImages () const { return Images; }
331
345
332
346
bool queryDataLayout (DataLayoutQueryType type, void *inBuffer,
333
347
void *outBuffer) override {
348
+ auto wordSize = Images.front ().getBytesInAddress ();
334
349
switch (type) {
335
350
case DLQ_GetPointerSize: {
336
351
auto result = static_cast <uint8_t *>(outBuffer);
337
- *result = sizeof ( void *) ;
352
+ *result = wordSize ;
338
353
return true ;
339
354
}
340
355
case DLQ_GetSizeSize: {
341
356
auto result = static_cast <uint8_t *>(outBuffer);
342
- *result = sizeof ( size_t ) ;
357
+ *result = wordSize ;
343
358
return true ;
344
359
}
345
360
}
@@ -409,6 +424,47 @@ class ObjectMemoryReader : public MemoryReader {
409
424
}
410
425
};
411
426
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
+
412
468
static int doDumpReflectionSections (ArrayRef<std::string> BinaryFilenames,
413
469
StringRef Arch, ActionType Action,
414
470
std::ostream &OS) {
@@ -437,17 +493,14 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
437
493
ObjectOwners.push_back (std::move (ObjectOwner));
438
494
ObjectFiles.push_back (O);
439
495
}
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 ;
446
499
447
500
switch (Action) {
448
501
case ActionType::DumpReflectionSections:
449
502
// Dump everything
450
- Context. getBuilder () .dumpAllSections (OS);
503
+ builder .dumpAllSections (OS);
451
504
break ;
452
505
case ActionType::DumpTypeLowering: {
453
506
for (std::string Line; std::getline (std::cin, Line);) {
@@ -460,15 +513,14 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
460
513
Demangle::Demangler Dem;
461
514
auto Demangled = Dem.demangleType (Line);
462
515
auto *TypeRef =
463
- swift::Demangle::decodeMangledType (Context. getBuilder () , Demangled);
516
+ swift::Demangle::decodeMangledType (builder , Demangled);
464
517
if (TypeRef == nullptr ) {
465
518
OS << " Invalid typeref: " << Line << " \n " ;
466
519
continue ;
467
520
}
468
521
469
522
TypeRef->dump (OS);
470
- auto *TypeInfo =
471
- Context.getBuilder ().getTypeConverter ().getTypeInfo (TypeRef);
523
+ auto *TypeInfo = builder.getTypeConverter ().getTypeInfo (TypeRef);
472
524
if (TypeInfo == nullptr ) {
473
525
OS << " Invalid lowering\n " ;
474
526
continue ;
0 commit comments