[llvm] [llvm-objdump][macho] Add support for ObjC relative method lists (PR #85477)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 15 15:22:25 PDT 2024


https://github.com/alx32 created https://github.com/llvm/llvm-project/pull/85477

For Mach-O, ld64 supports the -fobjc-relative-method-lists flag which changes the format in which method lists are generated. The format uses delta encoding vs the original direct-pointer encoding.
This change adds support to llvm-objdump and llvm-otool for decoding/dumping of method lists in the delta format. Previously, if a binary with this information format was passed to the tooling, it would output invalid information, trying to parse the delta lists as pointer lists.
After this change, the tooling will output correct information if a binary in this format is encountered.
The output format is closest feasible match to XCode 15.1's otool output. Tests are included for both 32bit and 64bit binaries.

The code style was matched as close as possible to existing implementation of parsing non-delta method lists.

Diff between llvm-objdump and XCode 15.1 otool:
![image](https://github.com/llvm/llvm-project/assets/103613512/2277e3ff-d59c-4fff-b93a-e0587ee740a6)

Note: This is a retry of this PR: https://github.com/llvm/llvm-project/pull/84250
On the original PR, the armv7+armv8 builds were failing due to absolute offsets being different. 

>From b6c56a6903ffd2fcfba191d6a90f49154532b923 Mon Sep 17 00:00:00 2001
From: Alex B <alexborcan at meta.com>
Date: Wed, 6 Mar 2024 14:31:24 -0800
Subject: [PATCH] [llvm-objdump][macho] Add support for ObjC relative method
 lists

---
 .../Inputs/rel-method-lists-arm64.dylib       | Bin 0 -> 3206 bytes
 .../Inputs/rel-method-lists-arm64_32.dylib    | Bin 0 -> 2716 bytes
 .../AArch64/macho-relative-method-lists.test  |  86 ++++++++++++++
 llvm/tools/llvm-objdump/MachODump.cpp         | 112 +++++++++++++++++-
 4 files changed, 196 insertions(+), 2 deletions(-)
 create mode 100755 llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib
 create mode 100755 llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib
 create mode 100644 llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test

diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib
new file mode 100755
index 0000000000000000000000000000000000000000..051e28f33d74949db5b9c3c9a875cf45b7486f48
GIT binary patch
literal 3206
zcmbVOZ)jUp6u(QO+icfAIAr2vaTcu;O;XAbL0C+Jt#)l~3+vEveNEnMN?u-QUbhq#
z0y@}7|DYCB2q<HMA2vk6Z=Ij|!9V>l#y$+G;0O0X7zi>3+WpRb=cF$$$($ZIx#xH8
zy}x(vIrmR~zV*jHJxc9Rkb9xM&?y*aR6n`YgV3RfQd-Yu=Vpzo>1ShS6I6olft!>#
zNwoIts^{B2ZsuF%f%|v}VSIL5qN=tHh|is0%xTB=7K(+6*Am|a=6jVV5$*~Sgly)^
z6|G98WI1+ty*<3nT|7^)&@{ygXCOYJYl&|!^A(st at LlkEE9F+cw?gp=?##DbI$bE`
zb)j_9HSspr<1F)yG6CW68iku$+9$t5wa%nwQ#w64F=KX%><520smA^gOf?}TZt?}|
zK!xqZCv_nHP+f%@Yz at AGW4&(EQp0>#LwO_oZ|gjZ)8g}(Pne%g=82h;q?F)(#<I>R
zPmy)HC2U?uC%$)iJn at Cr$vu9<d=<O6WS^|G@|8JZ37$nb$cMAqE^m3uv&@Wee0AoV
zVm`t_K6W=6t#hv9xFvCf`ED>@Fo+- at r%|Sx{Wc1u_4wGtOWDkr+)cavA$6WCydN<p
zo*>sA;MbsZ?*#qv1=q3TR?)7`yGuE%6xW_pjwh13VmalaO{*yvigw&x_Qd5R9V at 4c
z`NJbm+f^HUBnOqMQO+rj;Mz=Q at CR|1fobniELC8-i|6hG0RroWJq0C!%P8$78uNeT
zAxxt0JpO^ZVO at Xj+uE-OuD;Rt+2SyKF{qyl`f9ha{q$LpL+}LG at fhPW;-wNk!I<JF
zc^FFLH$iod9Cs;eUHVEp#amUQST+#gCA7b7ZEgJk`y1HTV6Vge682 at -Xq1enGy5L!
zdHCOfeFk<NHsy8&_A2b7D`~p^m3air)8giJA`!yL5FS<qoMEe!vjbCFT*=l^!|GJ>
z at R7u`&*1YW$NR~E1Y6n<^cIewCA|onglx(~4`%k8+2mCbIhO>EKxxbnE1HJL`z7yW
zqoadCakLZR+2pv|jS2cPd`}+Zc9C0o{{|V4aJx>MDj+u*%efw6EaPPT;c;>w4?Ln?
zKDclCh3U+()Ex2d(D<JcnSB1mv{w85KNYr9_Exl-P?7X_YGy_cYS|f?quJS1*g4jv
z>H|ph`T+8O%CqK+c%E}sZoyXhE_H*tZlcSV)jd%XbsVr4dr$uNoM!wf=kY_vb;e&a
z{(|vOjL$Q^&iE_FQE>O7Xj0!t8B3kAgmFeCFFD4NPpWqx&aC8<?h3+^XSyf)aJVGT
zS;kVAn9?Sv;bi&Vc4_1n%ul|bz9tuE_NiC67_pW!mN=pA(3`wt at 9+urWP>?$0d(#H
zXQx>p)c#@zwVwnmdUP@~)7VUn?lJsVN=>A*y2FU=Y)wxFHY3mX$(wpm3z1vD^sK=?
z2StUA?1hiY`@V|c1&Np^X9?IG2ecU1y%~$p)%o9~^IQ1lU%Qu6(JSc#)dzn3?)#75
VzHsRN+UM>ke-5sV+twxf at 7pLg<SzgK

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib
new file mode 100755
index 0000000000000000000000000000000000000000..d3a339057abc349e5959a3a67077f0ae5c5bafe8
GIT binary patch
literal 2716
zcmd5-J!}+L5FYz3Kw_{RiNaD`K!PG533q2Xkrh#JxjV^Dz$W%7fC74~_m=pg-P;ql
zU|;7VNE9?kq=_g}I8s0^h=2l#!jW7fXn-PBDuakbi6SMJ at 7sNQe%{4IqGEJ&^Sya9
zvorJl?*0AOzuQH6dqiXlcnA34TOt=^P^i0)Kc%Xb<5dg{I=VF)P{KT9`jeCjoP{95
z(Ric(ML7J53CiAeGm)$;#zUq2+3#)TIl-J;Zw09w^7z<E7*l3qr-aloY}abF8kXlI
z>$n8pZSbKq$;`>fgCSCRT!C*L&Xgu?5+i6g(=q;mFWX6J(#9C)8uRr=P1PG`d>AEb
z$s)iw^pvKb8E<_(%f)JOeTHjz14GK6A=yuIoQ~N?E{0NR|19k3pZNA5)FJ5 at b<g_F
zVF}3?Rrqo(C=)Ss1lAnx3EOXALx7SoPQv#n^pyV-qvg0~oinX;jAi%^AqJ%x16ws&
zOU()_rjg2H6~23+r!- at P#`;ew+xI-b5$lq*JcBR$K{8`-4Pzo611oiSV)Cm>c_Kce
zaJ&Jh=ZLWkNjuYzXZ$pnb(;FzobNd~%XJoJ{j;{!$f>|<=JEyAvb?72Fym(3b#nf>
zAXd#=fj#H9lw133^gylc)@Kp(eUZgHB){Kn8pbI?o-UL~G0Y{vxF2}<Z3IAKeZX8#
z(mR^D&uH^H^d6j8^VM%Y{rH!aeCM}|*Z%xz`SucXjq+qBJ+i+$1_12_?*uPm6YxGH
zeF&zHi=6S3eR|9qUWYm*d9ap|>uUpYXD!oneXURKKzDg1qaMCVb9gHjc{gx<euuo;
z>2wx=Zv!s_H-WDK-vx${*uD(?WsHZQKL~sQcrWlMa2t3G_(;3Nt6IVfJG}b+n#$)B
z<3eIQB6ZvcR>O7-mz1iIwi=Q1V~6sekA`Pp7&(wk$=$#=Y7~-O&=(>xd$1jz(JP6;
zV027*=1GUZwBf!Xllac?y-E_lV-oF7zr=18x<}xrV7 at m?;9KCw`kTBnNIyVQ$6R6^
z??lqOyQMiaJw9DNR%~Xg#jmAD;qC67`r^xylHurrb-ZTKRx&BQrNhOU8MQ~nD^osF
zsTPyUiHxicpxDO)ILfwV&*6nTA6T=lBeje?<J5CZp_hHbBsl at xk9B8n=QUme{!!x<
z;F}u%0eny67r;+6-if-ih|!Pcv8Nws%)V8Kafh&GTVwWweICH2!oKhxAZDLNh_O-G
ztBS_FyLO2R`;sg;(!Q(}`h|)bs9Rz7RJY}mZ*@a=rS at t5l)PfL at XFbdQ}R(aa^ete
zK82W at c_E;Riru54CZOo?sq##BLv*JnCTFU}$x=maVzJ(>=_zAFY5yqrh8e8Gf2j)e
A#{d8T

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test b/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test
new file mode 100644
index 00000000000000..b1b96a41a32939
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test
@@ -0,0 +1,86 @@
+RUN: llvm-objdump --macho --objc-meta-data    %p/Inputs/rel-method-lists-arm64_32.dylib | FileCheck %s --check-prefix=CHK32
+RUN: llvm-otool -ov                           %p/Inputs/rel-method-lists-arm64_32.dylib | FileCheck %s --check-prefix=CHK32
+
+RUN: llvm-objdump --macho --objc-meta-data    %p/Inputs/rel-method-lists-arm64.dylib    | FileCheck %s --check-prefix=CHK64
+RUN: llvm-otool -ov                           %p/Inputs/rel-method-lists-arm64.dylib    | FileCheck %s --check-prefix=CHK64
+
+CHK32:                 baseMethods 0x660 (struct method_list_t *)
+CHK32-NEXT:                 entsize 12 (relative)
+CHK32-NEXT:                   count 3
+CHK32-NEXT:                    name 0x144 (0x{{[0-9a-f]*}}) instance_method_00
+CHK32-NEXT:                   types 0x91 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffff18 (0x{{[0-9a-f]*}}) -[MyClass instance_method_00]
+CHK32-NEXT:                    name 0x13c (0x{{[0-9a-f]*}}) instance_method_01
+CHK32-NEXT:                   types 0x85 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffff28 (0x{{[0-9a-f]*}}) -[MyClass instance_method_01]
+CHK32-NEXT:                    name 0x134 (0x{{[0-9a-f]*}}) instance_method_02
+CHK32-NEXT:                   types 0x79 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffff38 (0x{{[0-9a-f]*}}) -[MyClass instance_method_02]
+
+CHK32:                 baseMethods 0x630 (struct method_list_t *)
+CHK32-NEXT:                 entsize 12 (relative)
+CHK32-NEXT:                   count 3
+CHK32-NEXT:                    name 0x180 (0x{{[0-9a-f]*}}) class_method_00
+CHK32-NEXT:                   types 0xc1 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffff9c (0x{{[0-9a-f]*}}) +[MyClass class_method_00]
+CHK32-NEXT:                    name 0x178 (0x{{[0-9a-f]*}}) class_method_01
+CHK32-NEXT:                   types 0xb5 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffffac (0x{{[0-9a-f]*}}) +[MyClass class_method_01]
+CHK32-NEXT:                    name 0x170 (0x{{[0-9a-f]*}}) class_method_02
+CHK32-NEXT:                   types 0xa9 (0x{{[0-9a-f]*}}) v8 at 0:4
+CHK32-NEXT:                     imp 0xffffffbc (0x{{[0-9a-f]*}}) +[MyClass class_method_02]
+
+CHK64:                  baseMethods 0x6e0 (struct method_list_t *)
+CHK64-NEXT:                  entsize 12 (relative)
+CHK64-NEXT:                    count 3
+CHK64-NEXT:                     name 0x188 (0x{{[0-9a-f]*}}) instance_method_00
+CHK64-NEXT:                    types 0x91 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffffa8 (0x{{[0-9a-f]*}}) -[MyClass instance_method_00]
+CHK64-NEXT:                     name 0x184 (0x{{[0-9a-f]*}}) instance_method_01
+CHK64-NEXT:                    types 0x85 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffffa0 (0x{{[0-9a-f]*}}) -[MyClass instance_method_01]
+CHK64-NEXT:                     name 0x180 (0x{{[0-9a-f]*}}) instance_method_02
+CHK64-NEXT:                    types 0x79 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffff98 (0x{{[0-9a-f]*}}) -[MyClass instance_method_02]
+
+CHK64:                  baseMethods 0x6b0 (struct method_list_t *)
+CHK64-NEXT:                  entsize 12 (relative)
+CHK64-NEXT:                    count 3
+CHK64-NEXT:                     name 0x1d0 (0x{{[0-9a-f]*}}) class_method_00
+CHK64-NEXT:                    types 0xc1 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffffe4 (0x{{[0-9a-f]*}}) +[MyClass class_method_00]
+CHK64-NEXT:                     name 0x1cc (0x{{[0-9a-f]*}}) class_method_01
+CHK64-NEXT:                    types 0xb5 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffffdc (0x{{[0-9a-f]*}}) +[MyClass class_method_01]
+CHK64-NEXT:                     name 0x1c8 (0x{{[0-9a-f]*}}) class_method_02
+CHK64-NEXT:                    types 0xa9 (0x{{[0-9a-f]*}}) v16 at 0:8
+CHK64-NEXT:                      imp 0xffffffd4 (0x{{[0-9a-f]*}}) +[MyClass class_method_02]
+
+######## Generate rel-method-lists-arm64.dylib ########
+// clang -c main.mm -o main.o -target arm64-apple-macos -arch arm64
+// ld64.ld64 -dylib -demangle -dynamic main.o -o rel-method-lists-arm64.dylib -syslibroot MacOSX14.2.sdk -segalign 0x10 -objc_relative_method_lists
+
+######## Generate rel-method-lists-arm64_32.dylib ########
+// clang -c main.mm -o main.o -target arm64_32-apple-watchos -arch arm64_32
+// ld64.ld64 -dylib -demangle -dynamic main.o -o rel-method-lists-arm64_32.dylib -syslibroot WatchOS.sdk -segalign 0x10 -objc_relative_method_lists
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~ main.mm ~~~~~~~~~~~~~~~~~~~~~~~~~
+__attribute__((objc_root_class))
+ at interface MyClass
+- (void)instance_method_00;
+- (void)instance_method_01;
+- (void)instance_method_02;
++ (void)class_method_00;
++ (void)class_method_01;
++ (void)class_method_02;
+ at end
+ at implementation MyClass
+- (void)instance_method_00 {}
+- (void)instance_method_01 {}
+- (void)instance_method_02 {}
++ (void)class_method_00 {}
++ (void)class_method_01 {}
++ (void)class_method_02 {}
+ at end
+void *_objc_empty_cache;
+void *_objc_empty_vtable;
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index 0e6935c0ac5895..1b0e5ba279d06b 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -3661,6 +3661,10 @@ struct class_ro32_t {
 #define RO_ROOT (1 << 1)
 #define RO_HAS_CXX_STRUCTORS (1 << 2)
 
+/* Values for method_list{64,32}_t->entsize */
+#define ML_HAS_RELATIVE_PTRS (1 << 31)
+#define ML_ENTSIZE_MASK 0xFFFF
+
 struct method_list64_t {
   uint32_t entsize;
   uint32_t count;
@@ -3685,6 +3689,12 @@ struct method32_t {
   uint32_t imp;   /* IMP (32-bit pointer) */
 };
 
+struct method_relative_t {
+  int32_t name;  /* SEL (32-bit relative) */
+  int32_t types; /* const char * (32-bit relative) */
+  int32_t imp;   /* IMP (32-bit relative) */
+};
+
 struct protocol_list64_t {
   uint64_t count; /* uintptr_t (a 64-bit value) */
   /* struct protocol64_t * list[0];  These pointers follow inline */
@@ -3986,6 +3996,12 @@ inline void swapStruct(struct method32_t &m) {
   sys::swapByteOrder(m.imp);
 }
 
+inline void swapStruct(struct method_relative_t &m) {
+  sys::swapByteOrder(m.name);
+  sys::swapByteOrder(m.types);
+  sys::swapByteOrder(m.imp);
+}
+
 inline void swapStruct(struct protocol_list64_t &pl) {
   sys::swapByteOrder(pl.count);
 }
@@ -4440,6 +4456,84 @@ static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
   print_layout_map(layout_map, left);
 }
 
+static void print_relative_method_list(uint32_t structSizeAndFlags,
+                                       uint32_t structCount, uint64_t p,
+                                       struct DisassembleInfo *info,
+                                       const char *indent,
+                                       uint32_t pointerBits) {
+  struct method_relative_t m;
+  const char *r, *name;
+  uint32_t offset, xoffset, left, i;
+  SectionRef S, xS;
+
+  assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) &&
+         "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag");
+
+  outs() << indent << "\t\t   entsize "
+         << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n";
+  outs() << indent << "\t\t     count " << structCount << "\n";
+
+  for (i = 0; i < structCount; i++) {
+    r = get_pointer_64(p, offset, left, S, info);
+    memset(&m, '\0', sizeof(struct method_relative_t));
+    if (left < sizeof(struct method_relative_t)) {
+      memcpy(&m, r, left);
+      outs() << indent << "   (method_t extends past the end of the section)\n";
+    } else
+      memcpy(&m, r, sizeof(struct method_relative_t));
+    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+      swapStruct(m);
+
+    outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
+    uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name);
+    uint64_t absNameRefVA = relNameRefVA + m.name;
+    outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")";
+
+    // since this is a relative list, absNameRefVA is the address of the
+    // __objc_selrefs entry, so a pointer, not the actual name
+    const char *nameRefPtr =
+        get_pointer_64(absNameRefVA, xoffset, left, xS, info);
+    if (nameRefPtr) {
+      uint32_t pointerSize = pointerBits / CHAR_BIT;
+      if (left < pointerSize)
+        outs() << indent << " (nameRefPtr extends past the end of the section)";
+      else {
+        if (pointerSize == 64) {
+          name = get_pointer_64(*reinterpret_cast<const uint64_t *>(nameRefPtr),
+                                xoffset, left, xS, info);
+        } else {
+          name = get_pointer_32(*reinterpret_cast<const uint32_t *>(nameRefPtr),
+                                xoffset, left, xS, info);
+        }
+        if (name != nullptr)
+          outs() << format(" %.*s", left, name);
+      }
+    }
+    outs() << "\n";
+
+    outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
+    uint64_t relTypesVA = p + offsetof(struct method_relative_t, types);
+    uint64_t absTypesVA = relTypesVA + m.types;
+    outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")";
+    name = get_pointer_32(absTypesVA, xoffset, left, xS, info);
+    if (name != nullptr)
+      outs() << format(" %.*s", left, name);
+    outs() << "\n";
+
+    outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
+    uint64_t relImpVA = p + offsetof(struct method_relative_t, imp);
+    uint64_t absImpVA = relImpVA + m.imp;
+    outs() << " (" << format("0x%" PRIx32, absImpVA) << ")";
+    name = GuessSymbolName(absImpVA, info->AddrMap);
+    if (name != nullptr)
+      outs() << " " << name;
+    outs() << "\n";
+
+    p += sizeof(struct method_relative_t);
+    offset += sizeof(struct method_relative_t);
+  }
+}
+
 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
                                   const char *indent) {
   struct method_list64_t ml;
@@ -4461,10 +4555,17 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
     memcpy(&ml, r, sizeof(struct method_list64_t));
   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
     swapStruct(ml);
+  p += sizeof(struct method_list64_t);
+
+  if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
+    print_relative_method_list(ml.entsize, ml.count, p, info, indent,
+                               /*pointerBits=*/64);
+    return;
+  }
+
   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
   outs() << indent << "\t\t     count " << ml.count << "\n";
 
-  p += sizeof(struct method_list64_t);
   offset += sizeof(struct method_list64_t);
   for (i = 0; i < ml.count; i++) {
     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,
     memcpy(&ml, r, sizeof(struct method_list32_t));
   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
     swapStruct(ml);
+  p += sizeof(struct method_list32_t);
+
+  if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
+    print_relative_method_list(ml.entsize, ml.count, p, info, indent,
+                               /*pointerBits=*/32);
+    return;
+  }
+
   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
   outs() << indent << "\t\t     count " << ml.count << "\n";
 
-  p += sizeof(struct method_list32_t);
   offset += sizeof(struct method_list32_t);
   for (i = 0; i < ml.count; i++) {
     r = get_pointer_32(p, offset, left, S, info);



More information about the llvm-commits mailing list