@@ -3661,6 +3661,10 @@ struct class_ro32_t {
3661
3661
#define RO_ROOT (1 << 1 )
3662
3662
#define RO_HAS_CXX_STRUCTORS (1 << 2 )
3663
3663
3664
+ /* Values for method_list{64,32}_t->entsize */
3665
+ #define ML_HAS_RELATIVE_PTRS (1 << 31 )
3666
+ #define ML_ENTSIZE_MASK 0xFFFF
3667
+
3664
3668
struct method_list64_t {
3665
3669
uint32_t entsize;
3666
3670
uint32_t count;
@@ -3685,6 +3689,12 @@ struct method32_t {
3685
3689
uint32_t imp; /* IMP (32-bit pointer) */
3686
3690
};
3687
3691
3692
+ struct method_relative_t {
3693
+ int32_t name; /* SEL (32-bit relative) */
3694
+ int32_t types; /* const char * (32-bit relative) */
3695
+ int32_t imp; /* IMP (32-bit relative) */
3696
+ };
3697
+
3688
3698
struct protocol_list64_t {
3689
3699
uint64_t count; /* uintptr_t (a 64-bit value) */
3690
3700
/* struct protocol64_t * list[0]; These pointers follow inline */
@@ -3986,6 +3996,12 @@ inline void swapStruct(struct method32_t &m) {
3986
3996
sys::swapByteOrder (m.imp );
3987
3997
}
3988
3998
3999
+ inline void swapStruct (struct method_relative_t &m) {
4000
+ sys::swapByteOrder (m.name );
4001
+ sys::swapByteOrder (m.types );
4002
+ sys::swapByteOrder (m.imp );
4003
+ }
4004
+
3989
4005
inline void swapStruct (struct protocol_list64_t &pl) {
3990
4006
sys::swapByteOrder (pl.count );
3991
4007
}
@@ -4440,6 +4456,84 @@ static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4440
4456
print_layout_map (layout_map, left);
4441
4457
}
4442
4458
4459
+ static void print_relative_method_list (uint32_t structSizeAndFlags,
4460
+ uint32_t structCount, uint64_t p,
4461
+ struct DisassembleInfo *info,
4462
+ const char *indent,
4463
+ uint32_t pointerBits) {
4464
+ struct method_relative_t m;
4465
+ const char *r, *name;
4466
+ uint32_t offset, xoffset, left, i;
4467
+ SectionRef S, xS;
4468
+
4469
+ assert (((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0 ) &&
4470
+ " expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag" );
4471
+
4472
+ outs () << indent << " \t\t entsize "
4473
+ << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n " ;
4474
+ outs () << indent << " \t\t count " << structCount << " \n " ;
4475
+
4476
+ for (i = 0 ; i < structCount; i++) {
4477
+ r = get_pointer_64 (p, offset, left, S, info);
4478
+ memset (&m, ' \0 ' , sizeof (struct method_relative_t ));
4479
+ if (left < sizeof (struct method_relative_t )) {
4480
+ memcpy (&m, r, left);
4481
+ outs () << indent << " (method_t extends past the end of the section)\n " ;
4482
+ } else
4483
+ memcpy (&m, r, sizeof (struct method_relative_t ));
4484
+ if (info->O ->isLittleEndian () != sys::IsLittleEndianHost)
4485
+ swapStruct (m);
4486
+
4487
+ outs () << indent << " \t\t name " << format (" 0x%" PRIx32, m.name );
4488
+ uint64_t relNameRefVA = p + offsetof (struct method_relative_t , name);
4489
+ uint64_t absNameRefVA = relNameRefVA + m.name ;
4490
+ outs () << " (" << format (" 0x%" PRIx32, absNameRefVA) << " )" ;
4491
+
4492
+ // since this is a relative list, absNameRefVA is the address of the
4493
+ // __objc_selrefs entry, so a pointer, not the actual name
4494
+ const char *nameRefPtr =
4495
+ get_pointer_64 (absNameRefVA, xoffset, left, xS, info);
4496
+ if (nameRefPtr) {
4497
+ uint32_t pointerSize = pointerBits / CHAR_BIT;
4498
+ if (left < pointerSize)
4499
+ outs () << indent << " (nameRefPtr extends past the end of the section)" ;
4500
+ else {
4501
+ if (pointerSize == 64 ) {
4502
+ name = get_pointer_64 (*reinterpret_cast <const uint64_t *>(nameRefPtr),
4503
+ xoffset, left, xS, info);
4504
+ } else {
4505
+ name = get_pointer_32 (*reinterpret_cast <const uint32_t *>(nameRefPtr),
4506
+ xoffset, left, xS, info);
4507
+ }
4508
+ if (name != nullptr )
4509
+ outs () << format (" %.*s" , left, name);
4510
+ }
4511
+ }
4512
+ outs () << " \n " ;
4513
+
4514
+ outs () << indent << " \t\t types " << format (" 0x%" PRIx32, m.types );
4515
+ uint64_t relTypesVA = p + offsetof (struct method_relative_t , types);
4516
+ uint64_t absTypesVA = relTypesVA + m.types ;
4517
+ outs () << " (" << format (" 0x%" PRIx32, absTypesVA) << " )" ;
4518
+ name = get_pointer_32 (absTypesVA, xoffset, left, xS, info);
4519
+ if (name != nullptr )
4520
+ outs () << format (" %.*s" , left, name);
4521
+ outs () << " \n " ;
4522
+
4523
+ outs () << indent << " \t\t imp " << format (" 0x%" PRIx32, m.imp );
4524
+ uint64_t relImpVA = p + offsetof (struct method_relative_t , imp);
4525
+ uint64_t absImpVA = relImpVA + m.imp ;
4526
+ outs () << " (" << format (" 0x%" PRIx32, absImpVA) << " )" ;
4527
+ name = GuessSymbolName (absImpVA, info->AddrMap );
4528
+ if (name != nullptr )
4529
+ outs () << " " << name;
4530
+ outs () << " \n " ;
4531
+
4532
+ p += sizeof (struct method_relative_t );
4533
+ offset += sizeof (struct method_relative_t );
4534
+ }
4535
+ }
4536
+
4443
4537
static void print_method_list64_t (uint64_t p, struct DisassembleInfo *info,
4444
4538
const char *indent) {
4445
4539
struct method_list64_t ml;
@@ -4461,10 +4555,17 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4461
4555
memcpy (&ml, r, sizeof (struct method_list64_t ));
4462
4556
if (info->O ->isLittleEndian () != sys::IsLittleEndianHost)
4463
4557
swapStruct (ml);
4558
+ p += sizeof (struct method_list64_t );
4559
+
4560
+ if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0 ) {
4561
+ print_relative_method_list (ml.entsize , ml.count , p, info, indent,
4562
+ /* pointerBits=*/ 64 );
4563
+ return ;
4564
+ }
4565
+
4464
4566
outs () << indent << " \t\t entsize " << ml.entsize << " \n " ;
4465
4567
outs () << indent << " \t\t count " << ml.count << " \n " ;
4466
4568
4467
- p += sizeof (struct method_list64_t );
4468
4569
offset += sizeof (struct method_list64_t );
4469
4570
for (i = 0 ; i < ml.count ; i++) {
4470
4571
r = get_pointer_64 (p, offset, left, S, info);
@@ -4552,10 +4653,17 @@ static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4552
4653
memcpy (&ml, r, sizeof (struct method_list32_t ));
4553
4654
if (info->O ->isLittleEndian () != sys::IsLittleEndianHost)
4554
4655
swapStruct (ml);
4656
+ p += sizeof (struct method_list32_t );
4657
+
4658
+ if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0 ) {
4659
+ print_relative_method_list (ml.entsize , ml.count , p, info, indent,
4660
+ /* pointerBits=*/ 32 );
4661
+ return ;
4662
+ }
4663
+
4555
4664
outs () << indent << " \t\t entsize " << ml.entsize << " \n " ;
4556
4665
outs () << indent << " \t\t count " << ml.count << " \n " ;
4557
4666
4558
- p += sizeof (struct method_list32_t );
4559
4667
offset += sizeof (struct method_list32_t );
4560
4668
for (i = 0 ; i < ml.count ; i++) {
4561
4669
r = get_pointer_32 (p, offset, left, S, info);
0 commit comments