@@ -3661,6 +3661,10 @@ struct class_ro32_t {
36613661#define RO_ROOT (1 << 1 )
36623662#define RO_HAS_CXX_STRUCTORS (1 << 2 )
36633663
3664+ /* Values for method_list{64,32}_t->entsize */
3665+ #define ML_HAS_RELATIVE_PTRS (1 << 31 )
3666+ #define ML_ENTSIZE_MASK 0xFFFF
3667+
36643668struct method_list64_t {
36653669 uint32_t entsize;
36663670 uint32_t count;
@@ -3685,6 +3689,12 @@ struct method32_t {
36853689 uint32_t imp; /* IMP (32-bit pointer) */
36863690};
36873691
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+
36883698struct protocol_list64_t {
36893699 uint64_t count; /* uintptr_t (a 64-bit value) */
36903700 /* struct protocol64_t * list[0]; These pointers follow inline */
@@ -3986,6 +3996,12 @@ inline void swapStruct(struct method32_t &m) {
39863996 sys::swapByteOrder (m.imp );
39873997}
39883998
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+
39894005inline void swapStruct (struct protocol_list64_t &pl) {
39904006 sys::swapByteOrder (pl.count );
39914007}
@@ -4440,6 +4456,84 @@ static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
44404456 print_layout_map (layout_map, left);
44414457}
44424458
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+
44434537static void print_method_list64_t (uint64_t p, struct DisassembleInfo *info,
44444538 const char *indent) {
44454539 struct method_list64_t ml;
@@ -4461,10 +4555,17 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
44614555 memcpy (&ml, r, sizeof (struct method_list64_t ));
44624556 if (info->O ->isLittleEndian () != sys::IsLittleEndianHost)
44634557 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+
44644566 outs () << indent << " \t\t entsize " << ml.entsize << " \n " ;
44654567 outs () << indent << " \t\t count " << ml.count << " \n " ;
44664568
4467- p += sizeof (struct method_list64_t );
44684569 offset += sizeof (struct method_list64_t );
44694570 for (i = 0 ; i < ml.count ; i++) {
44704571 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,
45524653 memcpy (&ml, r, sizeof (struct method_list32_t ));
45534654 if (info->O ->isLittleEndian () != sys::IsLittleEndianHost)
45544655 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+
45554664 outs () << indent << " \t\t entsize " << ml.entsize << " \n " ;
45564665 outs () << indent << " \t\t count " << ml.count << " \n " ;
45574666
4558- p += sizeof (struct method_list32_t );
45594667 offset += sizeof (struct method_list32_t );
45604668 for (i = 0 ; i < ml.count ; i++) {
45614669 r = get_pointer_32 (p, offset, left, S, info);
0 commit comments