PoC 1.0 #1

Merged
nganhkhoa merged 15 commits from merge into main 2024-01-10 15:37:59 +07:00
15 changed files with 1490 additions and 231 deletions

View File

@ -5,10 +5,11 @@ go 1.17
require (
github.com/alecthomas/kong v0.2.16
github.com/sirupsen/logrus v1.8.0
google.golang.org/protobuf v1.26.0
google.golang.org/protobuf v1.31.0
)
require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/magefile/mage v1.10.0 // indirect
github.com/pkg/errors v0.8.1 // indirect
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect

View File

@ -3,6 +3,8 @@ github.com/alecthomas/kong v0.2.16/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QL
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
@ -22,3 +24,5 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

View File

@ -1,9 +1,9 @@
package action
import (
// "fmt"
"sort"
"strings"
// log "github.com/sirupsen/logrus"
. "ios-wrapper/internal/wrapper/ofile"
@ -57,10 +57,18 @@ func (action *saveImports) saveToInfo(mf *MachoFile) error {
current_lib_idx := -1
current_symbol_idx := -1
intlSymbols := []string{}
for _, symbol := range symbols_raw {
if symbol.Dylib() == "/usr/local/opt/gettext/lib/libintl.8.dylib" {
intlSymbols = append(intlSymbols, symbol.Name())
}
}
action.keepSymbols = append(action.keepSymbols, intlSymbols...)
// now we expect everything is sorted and easier to build strings tables
// this is not fully optimized, there can be repeated symbol name in different libraries
for _, symbol := range symbols_raw {
if symbol.Type() != "lazy" {
if !symbol.SafeForRemoval() {
continue
}
@ -130,6 +138,16 @@ func (action *saveImports) saveToInfo(mf *MachoFile) error {
}
mf.Info().Main = mc.Main()
selectors_list := []*protomodel.MachoInfo_Selector{}
for _, sel := range mc.CollectSpecialSelectors() {
selectors_list = append(selectors_list, &protomodel.MachoInfo_Selector{
Idx: uint32(sel.Idx()),
Name: sel.Name(),
})
}
mf.Info().SpecialSelectors = selectors_list
return nil
}

View File

@ -299,6 +299,21 @@ func bcell2header(bfile string, header string) {
}
fmt.Fprintf(w, "};\n")
fmt.Fprintf(w, "uint32_t n_instructions = %d;\n", n_instructions)
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
fmt.Fprintf(w, "uint32_t special_selectors_idx[] = {\n")
for _, selector := range info.GetSpecialSelectors() {
fmt.Fprintf(w, "%x,\n", selector.Idx)
}
fmt.Fprintf(w, "};\n")
fmt.Fprintf(w, "__attribute__((section(\"__DATA,bshield\")))\n")
fmt.Fprintf(w, "const char* special_selectors_name[] = {\n")
for _, selector := range info.GetSpecialSelectors() {
fmt.Fprintf(w, "\"%s\",\n", selector.Name)
}
fmt.Fprintf(w, "};\n")
fmt.Fprintf(w, "uint32_t n_selectors = %d;\n", len(info.GetSpecialSelectors()))
}
fmt.Fprintf(w, "}// namespace bshield_data\n")
w.Flush()

View File

@ -63,7 +63,7 @@ type PepeArgument struct {
Rpath []string `short:"r" help:"Add more LC_RPATH"`
RemoveCodeSign bool `default:"false" negatable:"" help:"Remove LC_CODE_SIGNATURE"`
RemoveExports bool `default:"false" negatable:"" help:"Clear the export table/trie"`
RemoveSymbolTable bool `default:"true" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
RemoveSymbolTable bool `default:"false" negatable:"" help:"Remove LC_SYMTAB and LC_DYSYMTAB"`
RemoveOthers bool `default:"false" negatable:"" help:"Remove LC_FUNCTION_STARTS, LC_DATA_IN_CODE, ..."`
RemoveID bool `default:"false" negatable:"" help:"(TODO) Remove LC_ID_DYLIB"`
RemoveInitFunctions bool `default:"false" name:"remove-inits" negatable:"" help:"Clear MOD_INIT_FUNC section"`

View File

@ -42,6 +42,10 @@ func (sym *ImportSymbol) Type() string {
return sym.typ
}
func (sym *ImportSymbol) SafeForRemoval() bool {
return sym.typ == "lazy" || sym.typ == "fixups"
}
func (sym *ImportSymbol) Dylib() string {
return sym.dylib
}
@ -150,7 +154,7 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
sym.address = uint64(address)
sym.name = name
sym.dylib = dylib
sym.typ = "lazy"
sym.typ = "fixups"
sym.lib_ordinal = uint32(s.lib_ordinal)
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))

View File

@ -280,7 +280,10 @@ func (mc *MachoContext) RemoveBindSymbols() {
rand.Seed(time.Now().UnixNano())
if mc.dyldinfo == nil {
isModernSymbol := mc.dyldinfo == nil
isLegacySymbol := !isModernSymbol
if isModernSymbol {
mc.removeBindSymbolsModern()
} else {
mc.removeBindSymbolsLegacy()
@ -290,14 +293,12 @@ func (mc *MachoContext) RemoveBindSymbols() {
mc.ReworkForObjc()
}
// due to some limitations when design this tool
// we write the c code to stdout lol
for _, symbol := range mc.CollectBindSymbols() {
if symbol.Type() != "lazy" {
if !symbol.SafeForRemoval() {
continue
}
if mc.dyldinfo != nil {
if isLegacySymbol {
// for legacy resolve the opcodes can be rewritten as 0x00
mc.file.WriteAt(make([]byte, 8), int64(symbol.file_address))
} else {
@ -359,174 +360,6 @@ func (mc *MachoContext) removeBindSymbolsLegacy() {
mc.file.WriteAt(make([]byte, size), int64(start))
}
func (mc *MachoContext) ReworkForObjc() {
text_start := 0
data_end := 0
lc_main_offset := int64(0)
ptr := int64(0)
if mc.Is64bit() {
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
} else {
ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart)
}
for _, cmd := range mc.commands {
if cmd.Cmd() == LC_MAIN {
lc_main_offset = ptr + 8
ptr += int64(cmd.Cmdsize())
continue
}
if cmd.Cmd() != LC_SEGMENT_64 {
ptr += int64(cmd.Cmdsize())
continue
}
var segment = cmd.(*Segment64)
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
text_start = int(section.Offset())
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
// edit flags to not S_MOD_INIT_FUNC
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
// end of __DATA segment, should have enough space for a pointer
// __bss section is dynamically allocated at the end to or something, hmmge
// assume that it order correctly, which it should if compiled and not modified
// each section has their addr field which we can use that with segment virtual address
// to calculate the offset of the last section from segment starts
// then use the size of section to calculate the end of segment in file
sections := segment.Sections()
last := sections[len(sections)-1]
data_end = int(last.Addr() - segment.Vmaddr() + segment.Fileoff() + last.Size())
}
ptr += int64(cmd.Cmdsize())
}
mc.file.Seek(0, io.SeekStart)
// dummy value past the end of __DATA segment (logical size),
// its physical size is still a page
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
// we use 2 registers, x8 x9
// stack values:
// [ return address, header, argc, argv, env, apple ]
// we need to store the return address, and parameters passed to main
// we also store our header address to not calculate many times
// must expand stack to store arguments passed
// must use newly allocated stack region
// must save return address
// must recover stack to same value before calling main
// must recover link register before calling main
// we use shorthand store/load multiple
// arm also has different indexing instruction, so be careful
// https://developer.arm.com/documentation/102374/0101/Loads-and-stores---addressing
/*
adr x8, 0
# x9 = (offset end of __DATA) - (offset shellcode)
movz x9, #0x9999
add x8, x8, x9
stp x30, x8, [sp], #-0x10
stp x3, x2, [sp], #-0x10
stp x1, x0, [sp], #-0x10
# custom intializer
ldr x9, [x8]
blr x9
ldp x1, x0, [sp, #0x10]!
ldp x3, x2, [sp, #0x10]!
ldp x30, x8, [sp, #0x10]!
# original main
# link register is set so jump only
ldr x9, [x8, #8]
br x9
*/
// TODO: fix to work with offset larger than 0xffff
shellcode := []uint32{
0x10000008,
0, // x9 = (offset end of __DATA) - (offset shellcode)
0x8B090108,
0xA8BF23FE,
0xA8BF0BE3,
0xA8BF03E1,
0xF9400109,
0xD63F0120,
0xA9C103E1,
0xA9C10BE3,
0xA9C123FE,
0xF9400509,
0xD61F0120,
}
ins_size_byte := 4
shellcode_offset := text_start - (ins_size_byte * len(shellcode))
main_offset := int(mc.entryoff)
encode_movz := func(v int) uint32 {
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
}
// movz_shellcode_offset := encode_movz(shellcode_offset)
// movz_main_offset := encode_movz(main_offset)
// movz_data_end_offset := encode_movz(data_end)
movz_calculate_offset := encode_movz(data_end - shellcode_offset)
shellcode[1] = movz_calculate_offset
// shellcode[10] = movz_data_end_offset
// shellcode[19] = movz_main_offset
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
fmt.Printf("// main_offset=%x\n", main_offset)
fmt.Printf("// data_end=%x\n", data_end)
fmt.Printf("// movz_calculate_offset=%x\n", movz_calculate_offset)
// fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
// fmt.Printf("// movz_main_offset=%x\n", movz_main_offset)
// fmt.Printf("// movz_data_end_offset=%x\n", movz_data_end_offset)
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
offset := int64(shellcode_offset)
{
// fix main to point to our newly created shellcode
bs := make([]byte, 8)
mc.byteorder.PutUint64(bs, uint64(offset))
mc.file.WriteAt(bs, int64(lc_main_offset))
}
bs := make([]byte, 4)
for _, ins := range shellcode {
mc.byteorder.PutUint32(bs, ins)
mc.file.WriteAt(bs, offset)
offset += 4
}
}
func (mc *MachoContext) RewriteImportsTable(keepSymbols []string) {
allSymbols := mc.CollectBindSymbols()
fixups, fixupsOffset := mc.Fixups()
@ -539,6 +372,23 @@ func (mc *MachoContext) RewriteImportsTable(keepSymbols []string) {
// but because we keep a few symbols, we need to rewrite the pointers
// as well as rebuild the import table and strings table, and bind values
// some symbols are annoyingly distributed by another library
// dispite the name asking for X, the dyld loads a Y library
// LC_DYLD_ID of Y is equal to X and dyld can resolve these symbols
// because we do not search for library using LC_DYLD_ID,
// paths are mistaken and will not resolve symbols
//
// the most common library that has this behavior is libintl
// and fixing the resolver takes time, we temporarily ignore this library
// and so we keep symbols referenced by libintl
intlSymbols := []string{}
for _, symbol := range allSymbols {
if symbol.Dylib() == "/usr/local/opt/gettext/lib/libintl.8.dylib" {
intlSymbols = append(intlSymbols, symbol.Name())
}
}
keepSymbols = append(keepSymbols, intlSymbols...)
keepCount := uint32(0)
for _, symbol := range keepSymbols {
name := symbol

View File

@ -0,0 +1,365 @@
package macho
import (
"fmt"
"bytes"
"encoding/binary"
"io"
"strings"
. "ios-wrapper/pkg/ios"
)
type SpecialSelector struct {
idx uint
name string
}
func (sel *SpecialSelector) Idx() uint {
return sel.idx
}
func (sel *SpecialSelector) Name() string {
return sel.name
}
// collect the index and the name in selector list of special method names
// these names are resolved by the dyld objc cache
// through __dyld_get_objc_selector
//
// we currently have the following symbols guaranteed to be in this list:
// - load
// - retain
func (mc *MachoContext) CollectSpecialSelectors() []*SpecialSelector {
var special_selectors []*SpecialSelector
var methods []byte
var methname_offset uint32
for _, cmd := range mc.commands {
if cmd.Cmd() == LC_MAIN {
continue
}
if cmd.Cmd() != LC_SEGMENT_64 {
continue
}
var segment = cmd.(*Segment64)
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
methname_offset = section.Offset()
methods = make([]byte, section.Size())
mc.file.ReadAt(methods, int64(section.Offset()))
}
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
selectors_buffer := make([]byte, section.Size())
mc.file.ReadAt(selectors_buffer, int64(section.Offset()))
buffer := bytes.NewReader(selectors_buffer)
for i := uint(0); i < uint(section.Size()) / 8; i++ {
// this field is actually a Rebase
// we assume that no rebase is needed
// so everything sticks to its file offset
var offset uint32
binary.Read(buffer, mc.byteorder, &offset) // first 4 bytes is offset
var name_builder strings.Builder
for j := uint32(0); ; j++ {
c := methods[offset - methname_offset + j]
if c == 0 {
break
}
name_builder.WriteByte(c)
}
name := name_builder.String()
if name == "load" {
special_selectors = append(special_selectors, &SpecialSelector{
idx: i,
name: name,
})
}
binary.Read(buffer, mc.byteorder, &offset) // ignore rebase arguments
}
}
}
}
}
return special_selectors
}
func (mc *MachoContext) ReworkForObjc() {
text_start := 0
data_end := 0
lc_main_offset := int64(0)
ptr := int64(0)
if mc.Is64bit() {
ptr, _ = mc.file.Seek(int64(Header_size_64), io.SeekStart)
} else {
ptr, _ = mc.file.Seek(int64(Header_size), io.SeekStart)
}
for _, cmd := range mc.commands {
if cmd.Cmd() == LC_MAIN {
lc_main_offset = ptr + 8
ptr += int64(cmd.Cmdsize())
continue
}
if cmd.Cmd() != LC_SEGMENT_64 {
ptr += int64(cmd.Cmdsize())
continue
}
var segment = cmd.(*Segment64)
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__TEXT")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__text")) == 0 {
text_start = int(section.Offset())
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__init_offsets")) == 0 {
// mc.file.WriteAt([]byte("__init_offsetx"), section_ptr)
// edit flags to not S_MOD_INIT_FUNC
mc.file.WriteAt([]byte{0, 0, 0, 0}, section_ptr+0x40)
}
// erases all objc method names
// this should still works because the cache inserts the pointer value not string
// but some symbols relies on pre-defined implementations, such as **load** method
// load method is the same across all classes and so objc define an implementation
// selector should points to this load selector to make objc thinks that it's "load"
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_methname")) == 0 {
// mc.file.WriteAt([]byte("__objc_methbruh"), section_ptr)
mc.file.WriteAt(make([]byte, section.Size()), int64(section.Offset()))
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA_CONST")) == 0 {
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_classlist")) == 0 {
mc.file.WriteAt([]byte("__objc_classbruh"), section_ptr)
}
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_nlclslist")) == 0 {
mc.file.WriteAt([]byte("__objc_nlclsbruh"), section_ptr)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
if bytes.Compare(bytes.Trim(segment.SegName(), "\x00"), []byte("__DATA")) == 0 {
// end of __DATA segment, should have enough space for a pointer
// __bss section is dynamically allocated at the end to or something, hmmge
// assume that it order correctly, which it should if compiled and not modified
// each section has their addr field which we can use that with segment virtual address
// to calculate the offset of the last section from segment starts
// then use the size of section to calculate the end of segment in file
sections := segment.Sections()
last := sections[len(sections)-1]
data_end = int(last.Addr() - segment.Vmaddr() + segment.Fileoff() + last.Size())
// do not register selector and see what happens
section_ptr := ptr + 0x40 + 8
for _, section := range segment.Sections() {
if bytes.Compare(bytes.Trim(section.SectName(), "\x00"), []byte("__objc_selrefs")) == 0 {
// mc.file.WriteAt([]byte("__objc_selbruh"), section_ptr)
}
section_ptr += 16*2 + 8*2 + 4*8
}
}
ptr += int64(cmd.Cmdsize())
}
mc.file.Seek(0, io.SeekStart)
// dummy value past the end of __DATA segment (logical size),
// its physical size is still a page
// mc.file.WriteAt([]byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}, int64(0x81d8))
// we use 2 registers, x8 x9
// stack values:
// [ return address, header, argc, argv, env, apple ]
// we need to store the return address, and parameters passed to main
// we also store our header address to not calculate many times
// must expand stack to store arguments passed
// must use newly allocated stack region
// must save return address
// must recover stack to same value before calling main
// must recover link register before calling main
// ┌─────────────────┐
// │ │
// shellcode starts ────┼─────────────────┼───── │ │instruction
// │ │ │ │fetch RIP size
// RIP returns ────┼─────────────────┼───── ▲ │ │
// │ │ │ │
// │ │ │ │ shellcode length
// shellcode ends │ │ │ offset │
// __text ────┼─────────────────┼───── │ range │
// │ │ │ │ __DATA ends - __text
// │ │ │ │
// __DATA ends ────┼─────────────────┼───── ▼ │
// │ │
// │ │
// │ │
// │ │
// │ │
// └─────────────────┘
shellcode := []uint32{}
ins_size_byte := 4
main_offset := int(mc.entryoff)
var shellcode_offset int
isArm := (mc.header.cputype & 0xff) == 12
if isArm {
// we use shorthand store/load multiple
// arm also has different indexing instruction, so be careful
// https://developer.arm.com/documentation/102374/0101/Loads-and-stores---addressing
/*
adr x8, 0
# x9 = (offset end of __DATA) - (offset shellcode)
movz x9, #0x9999
add x8, x8, x9
stp x30, x8, [sp], #-0x10
stp x3, x2, [sp], #-0x10
stp x1, x0, [sp], #-0x10
# custom intializer
ldr x9, [x8]
blr x9
ldp x1, x0, [sp, #0x10]!
ldp x3, x2, [sp, #0x10]!
ldp x30, x8, [sp, #0x10]!
# original main
# link register is set so jump only
ldr x9, [x8, #8]
br x9
*/
shellcode = []uint32{
0x10000008,
0, // x9 = (offset end of __DATA) - (offset shellcode)
0x8B090108,
0xA8BF23FE,
0xA8BF0BE3,
0xA8BF03E1,
0xF9400109,
0xD63F0120,
0xA9C103E1,
0xA9C10BE3,
0xA9C123FE,
0xF9400509,
0xD61F0120,
}
shellcode_offset = text_start - (ins_size_byte * len(shellcode))
encode_movz := func(v int) uint32 {
return uint32(uint32(v)<<5 | uint32(0x694)<<21 | uint32(0x09))
}
// movz_shellcode_offset := encode_movz(shellcode_offset)
// movz_main_offset := encode_movz(main_offset)
// movz_data_end_offset := encode_movz(data_end)
movz_calculate_offset := encode_movz(data_end - shellcode_offset)
shellcode[1] = movz_calculate_offset
// shellcode[10] = movz_data_end_offset
// shellcode[19] = movz_main_offset
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
fmt.Printf("// main_offset=%x\n", main_offset)
fmt.Printf("// data_end=%x\n", data_end)
fmt.Printf("// movz_calculate_offset=%x\n", movz_calculate_offset)
// fmt.Printf("// movz_shellcode_offset=%x\n", movz_shellcode_offset)
// fmt.Printf("// movz_main_offset=%x\n", movz_main_offset)
// fmt.Printf("// movz_data_end_offset=%x\n", movz_data_end_offset)
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
} else {
shellcode_start := []uint8{
0x4c, 0x8d, 0x05, 0x00, 0x00, 0x00, 0x00,
0x49, 0xC7, 0xC1,
}
shellcode_end := []uint8{
0x4d, 0x01, 0xc8,
0x57,
0x56,
0x52,
0x51,
0x41, 0x50,
0x4d, 0x8b, 0x08,
0x41, 0xff, 0xd1,
0x41,
0x58,
0x59,
0x5a,
0x5e,
0x5f, 0x4d, 0x8b, 0x48, 0x08,
0x41, 0xff, 0xe1,
// pad to %4
0x00, 0x00,
}
offset := []uint8{0x00, 0x00, 0x00, 0x00} // offset
shellcode_size := len(shellcode_start) + len(offset) + len(shellcode_end)
// could use buffer encoding, but for correctness,
// we do this by hand
encode_movz := func(v int) {
for i := 0; i < 4; i++ {
offset[i] = uint8(v >> (i * 8))
}
}
encode_movz((data_end - text_start) + (shellcode_size - len(shellcode_start)))
shellcode_offset = text_start - shellcode_size
shellcode_bytes := append(shellcode_start, offset...)
shellcode_bytes = append(shellcode_bytes, shellcode_end...)
for i := 0; i < len(shellcode_bytes); i += 4 {
val := 0
// little endian
val |= int(shellcode_bytes[i+0]) << 0
val |= int(shellcode_bytes[i+1]) << 8
val |= int(shellcode_bytes[i+2]) << 16
val |= int(shellcode_bytes[i+3]) << 24
shellcode = append(shellcode, uint32(val))
}
fmt.Printf("// shellcode_offset=%x\n", shellcode_offset)
fmt.Printf("// main_offset=%x\n", main_offset)
fmt.Printf("// data_end=%x\n", data_end)
fmt.Printf("// lc_main_offset=%x\n", lc_main_offset)
}
offset := int64(shellcode_offset)
{
// fix main to point to our newly created shellcode
bs := make([]byte, 8)
mc.byteorder.PutUint64(bs, uint64(offset))
mc.file.WriteAt(bs, int64(lc_main_offset))
}
bs := make([]byte, 4)
for _, ins := range shellcode {
mc.byteorder.PutUint32(bs, ins)
mc.file.WriteAt(bs, offset)
offset += 4
}
}

View File

@ -44,11 +44,15 @@ message MachoInfo {
repeated LibraryImportedSymbols tables = 3;
}
message Selector {
uint32 idx = 1;
string name = 2;
}
PointerSize pointer_size = 1;
uint64 image_base = 2;
uint64 main = 3;
repeated InitPointer init_pointers = 4;
// repeated BindSymbol symbols = 5;
AllImportedSymbols symbols = 5;
repeated Selector special_selectors = 6;
}

View File

@ -1,4 +1,5 @@
#import <Foundation/Foundation.h>
#include <objc/message.h>
#include <stdio.h>
@interface Foo : NSObject
@ -6,7 +7,7 @@
@implementation Foo
- (void)bar {
NSLog(@"%@", self);
NSLog(@"[Foo bar]: %@", self);
}
@end
@ -44,9 +45,16 @@ hmmge(int argc, char** argv) {
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
NSLog(@"main()");
NSLog(@"selector for \"bar:\" %p", @selector(bar:));
Foo *foo = [[Foo alloc] init];
[foo bar];
NSLog(@"directly call \"bar\" %p through objc_msgSend %p with object foo %p\n", @selector(bar), objc_msgSend, foo);
typedef void (*barfunc)(id, SEL);
barfunc bar_ = (barfunc)&objc_msgSend;
bar_(foo, @selector(bar));
}
printf("argc=%d\n", argc);

View File

@ -72,17 +72,18 @@ struct libcache {
void *main;
void *thislib;
void *libdyld;
int nrpath;
char **rpaths;
};
// try these hashes
// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b
uint32_t fnv_hash(const char *str) {
uint32_t fnv_hash_extend(const char *str, uint32_t h) {
unsigned char *s = (unsigned char *)str; /* unsigned string */
/* See the FNV parameters at www.isthe.com/chongo/tech/comp/fnv/#FNV-param */
const uint32_t FNV_32_PRIME = 0x01000193; /* 16777619 */
uint32_t h = 0x811c9dc5; /* 2166136261 */
// uint32_t h = 0x811c9dc5; /* 2166136261 */x
while (*s != 0) {
/* xor the bottom with the current octet */
h ^= *s++;
@ -92,6 +93,10 @@ uint32_t fnv_hash(const char *str) {
return h;
}
uint32_t fnv_hash(const char *str) { return fnv_hash_extend(str, 0x811c9dc5); }
// try these hashes
// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b
// calculate the hash to search
// _dyld_get_image_name returns the full path to the library
@ -115,7 +120,20 @@ uint32_t calculate_libname_hash(const libcache *cache, const char *name) {
// then resolve the full path for all rpath
//
// which rpath is correct can be done by checking if the cache has that hash
printf("resolver for @rpath is not supported yet\n");
for (int i = 0; i < cache->nrpath; i++) {
char *rpath = cache->rpaths[i];
char *p = realpath(rpath, 0);
hash = hash_func(p);
hash = fnv_hash_extend(&name[6], hash);
for (size_t j = 0; j < cache->size; j++) {
if (cache->libs[j].hash == hash) {
free(p);
return hash;
}
}
free(p);
}
// printf("resolver for @rpath is not supported yet\n");
} else {
hash = hash_func(name);
}
@ -428,7 +446,7 @@ uint32_t should_follow_symbol(char *&buffer, char *&_find) {
return is_prefix;
}
void *find_in_export_trie(const void *header, void *trie, const char *symbol) {
void *find_in_export_trie(const void *header, void *trie, char *&symbol) {
uint32_t func = 0;
char *ptr = (char *)trie;
@ -465,17 +483,37 @@ void *find_in_export_trie(const void *header, void *trie, const char *symbol) {
}
char count = *(ptr - 1);
ptr++; // flags
uint8_t flag = *ptr++; // flags
// uleb128 offset
decode_uleb128(ptr, &func);
if (flag == 0x8 /*re-export*/) {
// this hits a re-export symbol but with another name
// usually, the re-export is the same name on another library
// but somehow, for system libraries, a lot of symbols are
// renamed and re-exported from another library
// probably this was to build wrappers and
// have custom platform optimizations
//
// example of these is _strlen in libsystem_c.dylib
// is re-exported from __platform_strlen in libplatform
//
// The purpose of using char*& is to change the symbol searching
// to another symbols and do it quickly using references (pointer)
//
// we return 0 so the dlsym continues to search,
// but with another symbol name because the symbol points to another string
symbol = ptr;
return 0;
}
return (void *)((char *)header + func);
}
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
const char *symbol);
char *&symbol);
void *find_in_reexport(struct libcache *cache, struct libcache_item *lib,
const char *symbol) {
char *&symbol) {
void *header = lib->header;
const uint32_t magic = *(uint32_t *)header;
char *ptr = (char *)header;
@ -511,7 +549,7 @@ void *find_in_reexport(struct libcache *cache, struct libcache_item *lib,
}
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
const char *symbol) {
char *&symbol) {
void *direct = find_in_export_trie(lib->header, lib->trie, symbol);
if (direct) {
return direct;
@ -520,11 +558,34 @@ void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
return find_in_reexport(cache, lib, symbol);
}
// the current logic of dlsym is not correct, but it works for PoC
//
// dlsym searchs and match libraries based on the LC_DYLD_ID load command
// while for our PoC, we use the paths of libraries to search for them
//
// for performance reasons, we do not compare the paths as strings
// we instead use a simple hash to carry out comparision
// using hashes allows us to compare integers and would be faster
void *custom_dlsym(struct libcache *cache, uint32_t hash, const char *symbol) {
for (size_t i = 0; i < cache->size; i++) {
struct libcache_item *cache_lib = &cache->libs[i];
if (cache_lib->hash == hash) {
return find_in_lib(cache, cache_lib, symbol);
// read find_in_export_trie comments to know the use of char*&
//
// this code is for when the symbol searching references
// a previous item in search chain
//
// For example:
// searching for X in [A, B, C],
// C has X but it is a re-export from B with the name Y
// then we have to perform a search again from the top
// but with symbol Y
char **symbol_copy = (char **)&symbol;
void *func = find_in_lib(cache, cache_lib, *symbol_copy);
if (*symbol_copy != symbol) {
func = find_in_lib(cache, cache_lib, *symbol_copy);
}
return func;
}
}
return 0;
@ -745,6 +806,7 @@ struct ProgramVars {
void build_cache(struct libcache &cache, void *main);
void fix(struct libcache &cache);
void find_all_rpath(struct libcache &cache, void *main);
void test(struct libcache &cache);
@ -832,6 +894,7 @@ void build_cache(struct libcache &cache, void *main) {
printf("lib header at %p\n", thislib);
printf("libdyld header at %p\n", libdyld);
find_all_rpath(cache, main);
uint32_t trie_size;
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
@ -842,14 +905,20 @@ void build_cache(struct libcache &cache, void *main) {
typedef int (*dyld_image_count_t)(void);
typedef char *(*dyld_get_image_name_t)(int);
typedef void *(*dyld_get_image_header_t)(int);
char *dyld_image_count_s = (char*)"__dyld_image_count";
int (*dyld_image_count_func)(void) = (dyld_image_count_t)find_in_export_trie(
libdyld, libdyld_export_trie, "__dyld_image_count");
libdyld, libdyld_export_trie, dyld_image_count_s);
char *dyld_get_image_header_s = (char*)"__dyld_get_image_header";
void *(*dyld_get_image_header_func)(int) =
(dyld_get_image_header_t)find_in_export_trie(libdyld, libdyld_export_trie,
"__dyld_get_image_header");
dyld_get_image_header_s);
char *dyld_get_image_name_s = (char*)"__dyld_get_image_name";
char *(*dyld_get_image_name_func)(int) =
(dyld_get_image_name_t)find_in_export_trie(libdyld, libdyld_export_trie,
"__dyld_get_image_name");
dyld_get_image_name_s);
cache.size = dyld_image_count_func();
cache.libs =
@ -859,10 +928,46 @@ void build_cache(struct libcache &cache, void *main) {
char *name = dyld_get_image_name_func(i);
bootstrap_libcache_item(&cache.libs[i], header, name);
cache.libs[i].hash = calculate_libname_hash(&cache, name);
// printf("%p %s\n", header, name);
printf("%p %s\n", header, name);
}
}
// Function to find all rpath entries of the main executable
void find_all_rpath(struct libcache &cache, void *header) {
const uint32_t magic = *(uint32_t *)header;
char *ptr = (char *)header;
if (magic == magic64) {
ptr += 0x20;
} else {
ptr += 0x20 - 0x4;
}
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
const uint32_t ncmds = *((uint32_t *)header + 4);
printf("RPATHS:\n");
cache.nrpath = 0;
for (uint32_t i = 0; i < ncmds; i++) {
const uint32_t cmd = *((uint32_t *)ptr + 0);
const uint32_t cmdsize = *((uint32_t *)ptr + 1);
if (cmd == LC_RPATH)
cache.nrpath++;
ptr += cmdsize;
}
uint32_t idx = 0;
ptr = (char *)header;
ptr += (magic == magic64) ? 0x20 : 0x20 - 0x4;
cache.rpaths = (char **)malloc(sizeof(char *) * cache.nrpath);
for (uint32_t i = 0; i < ncmds; i++) {
const uint32_t cmd = *((uint32_t *)ptr + 0);
const uint32_t cmdsize = *((uint32_t *)ptr + 1);
if (cmd == LC_RPATH) {
cache.rpaths[idx++] = (char *)ptr + 12;
printf("%s\n", cache.rpaths[idx - 1]);
}
ptr += cmdsize;
}
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
}
void fix_binds(struct libcache_item *libfixing, struct libcache *cache,
int n_ins, uint32_t *instructions, char *libs, char *symbols) {
uint32_t libsystem_hash =
@ -1086,7 +1191,7 @@ void fix(struct libcache &cache) {
void volatile custom_initializer(int argc, const char *const argv[],
const char *const envp[],
const char *const apple[]) {
printf("run custom initializers %p\n", custom_initializer_i);
printf("[+] run custom initializers\n");
if (custom_initializer_i->cls != 0) {
// for Objective-C load
@ -1155,6 +1260,7 @@ void volatile custom_initializer(int argc, const char *const argv[],
free(custom_initializer_i->constructors);
}
printf("[+] initializers completed\n");
free(custom_initializer_i);
}
@ -1172,6 +1278,7 @@ void fix_objc(struct libcache_item *libfixing, struct libcache &cache) {
// "mov rcx, 123;"
// "call r12;");
printf("fixing objective-c\n");
void *header = libfixing->header;
const uint32_t magic = *(uint32_t *)header;
char *ptr = (char *)header;
@ -1198,6 +1305,50 @@ void fix_objc(struct libcache_item *libfixing, struct libcache &cache) {
printf("segment %s\n", name);
if (custom_strcmp(name, "__TEXT") == 0) {
slide = (uint64_t)header - vmaddr;
uint64_t nsect = *((uint32_t *)ptr + 8 * 2);
char *sections_ptr = (char *)((uint32_t *)ptr + 18);
for (int sec = 0; sec < nsect; sec++) {
char *secname = sections_ptr;
printf("section %s\n", secname);
if (custom_strncmp(secname, "__objc_methname", 16) == 0) {
uint64_t addr = *((uint64_t *)sections_ptr + 4);
uint64_t size = *((uint64_t *)sections_ptr + 5);
uint64_t *data_ptr = (uint64_t *)(addr + slide);
// printf("methname addr %p : %s\n", data_ptr, (char*)data_ptr);
break;
}
sections_ptr += 16 * 2 + 8 * 2 + 4 * 8;
}
} else if (custom_strcmp(name, "__DATA") == 0) {
uint64_t nsect = *((uint32_t *)ptr + 8 * 2);
char *sections_ptr = (char *)((uint32_t *)ptr + 18);
for (int sec = 0; sec < nsect; sec++) {
char *secname = sections_ptr;
printf("section %s\n", secname);
if (custom_strncmp(secname, "__objc_selrefs", 16) == 0) {
uint64_t addr = *((uint64_t *)sections_ptr + 4);
uint64_t size = *((uint64_t *)sections_ptr + 5);
uint64_t *data_ptr = (uint64_t *)(addr + slide);
uint32_t trie_size;
char* symbol = (char*)"__dyld_get_objc_selector";
void *libdyld = cache.libdyld;
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
typedef void *(*dyld_get_objc_selector_t)(const char *);
dyld_get_objc_selector_t dyld_get_objc_selector_func =
(dyld_get_objc_selector_t)find_in_export_trie(
libdyld, libdyld_export_trie, symbol);
// resolve method names that cached in the dyld
for (int i = 0; i < bshield_data::n_selectors; i++) {
uint32_t idx = bshield_data::special_selectors_idx[i];
const char *name = bshield_data::special_selectors_name[i];
data_ptr[idx] = (uint64_t)dyld_get_objc_selector_func(name);
}
}
sections_ptr += 16 * 2 + 8 * 2 + 4 * 8;
}
} else if (custom_strcmp(name, "__DATA_CONST") == 0) {
uint64_t nsect = *((uint32_t *)ptr + 8 * 2);
char *sections_ptr = (char *)((uint32_t *)ptr + 18);
@ -1355,30 +1506,18 @@ void fix_initializer(struct libcache_item *libfixing, struct libcache &cache) {
// (note: __TEXT segment is aligned to the end of the page, free space in the
// middle)
//
// Below is the shellcode.
/*
adr x8, 0
# x9 = (offset end of __DATA) - (offset shellcode)
movz x9, #0x9999
add x8, x8, x9
stp x30, x8, [sp], #-0x10
stp x3, x2, [sp], #-0x10
stp x1, x0, [sp], #-0x10
# custom intializer
ldr x9, [x8]
blr x9
ldp x1, x0, [sp, #0x10]!
ldp x3, x2, [sp, #0x10]!
ldp x30, x8, [sp, #0x10]!
# original main
# link register is set so jump only
ldr x9, [x8, #8]
br x9
*/
// The shellcode is built using the ios-wrapper tool
// The idea is:
//
// push main arguments
// r8 = shellcode location
// r9 = offset from shellcode to __DATA end
// r8 = r8 + r9 -- get __DATA end address
// r9 = *r8 -- the first pointer is custom_initializer
// call r9
// r9 = *(r8 + 4) -- the second pointer is main function
// pop main arguments
// jump r9 -- do not call, return to dyld
void *header = libfixing->header;
const uint32_t magic = *(uint32_t *)header;
@ -1445,7 +1584,9 @@ void fix_initializer(struct libcache_item *libfixing, struct libcache &cache) {
uint64_t *dummy = (uint64_t *)(addr + slide + size);
dummy[0] = (uint64_t)custom_initializer;
dummy[1] = (uint64_t)(header) + bshield_data::main;
printf("add custom main-peg at %p\n", dummy);
printf("-- add custom main-peg at %p\n", dummy);
printf("-- custom initializer at %llx\n", dummy[0]);
printf("-- main function at %llx\n", dummy[1]);
} else if (custom_strcmp(name, "__LINKEDIT") == 0) {
linkedit_vmaddr = vmaddr;
linkedit_fileoffset = fileoffset;

View File

@ -2,7 +2,7 @@
VERSION=${1:-14}
OUT=./out
LOGIC=3
LOGIC=${2}
mkdir -p $OUT
@ -14,6 +14,21 @@ else
echo "Resulting binary uses LEGACY symbol resolver"
fi
cat <<'fly'
______
_\ _~-\___
= = ==(____AA____D
\_____\___________________,-~~~~~~~`-.._
/ o O o o o o O O o o o o o o O o |\_
`~-.__ ___..----.. )
`---~~\___________/------------`````
= ===(_________D
fly
# this is a joke for those who knows
# https://www.blackhat.com/presentations/bh-dc-09/Iozzo/BlackHat-DC-09-Iozzo-let-your-mach0-fly-whitepaper.pdf
echo "make your Mach-O fly"
if [[ $LOGIC -eq 0 ]]
then
@ -39,7 +54,7 @@ clang++ -mmacosx-version-min=$VERSION -o $OUT/libc.dylib -shared c.cc
# create our dummy lib first
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib dummy.cc
# build a references libb
clang++ -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.cc
clang++ -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -Xlinker -no_data_const -lb a.cc
# extract symbols from a
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a
@ -64,11 +79,11 @@ clang -fobjc-arc -ObjC -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.m
# extract symbols from a
# ../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table --keep-imports _printf $OUT/a
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports $OUT/a
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table --remove-others $OUT/a
../../macho-go/bin/ios-wrapper bcell2header -b $OUT/b.bcell -o $OUT/b.h
# build libb with symbols extracted from a
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
../../macho-go/bin/ios-wrapper pepe -o $OUT/libb.dylib -b $OUT/libb.bcell --remove-imports --remove-exports --keep-imports _dyld_get_sdk_version --keep-imports _malloc --keep-imports _printf --keep-imports ___stack_chk_guard $OUT/libb.dylib
../../macho-go/bin/ios-wrapper pepe -o $OUT/libb.dylib -b $OUT/libb.bcell --remove-imports --remove-exports --remove-symbol-table --remove-others --keep-imports _dyld_get_sdk_version --keep-imports _malloc --keep-imports ___stack_chk_guard --keep-imports _printf $OUT/libb.dylib
# resign
codesign --force --deep -s - $OUT/a-fixed
@ -82,10 +97,37 @@ $OUT/a-fixed
else
# dummy test build
# remove imports test
clang++ -mmacosx-version-min=$VERSION -o $OUT/libc.dylib -shared c.cc
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
clang++ -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.cc
# test rpath
clang++ -mmacosx-version-min=$VERSION -o $OUT/libc.dylib -install_name @rpath/libc.dylib -shared c.cc
# linked with libd
# with rpath = $OUT
clang++ -mmacosx-version-min=$VERSION -Xlinker -no_data_const -o $OUT/a \
-rpath ./heheeeekkkkkkk \
-rpath $OUT \
-rpath ./hehe \
-rpath ./haha \
$OUT/libc.dylib a.cc \
# extract symbols from a
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell -l out/libb.dylib --remove-imports --remove-exports $OUT/a
# build restoration libb with symbols extracted from a
../../macho-go/bin/ios-wrapper bcell2header -b $OUT/b.bcell -o $OUT/b.h
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared b.cc
# obfuscate libb (bugged)
# ../../macho-go/bin/ios-wrapper pepe -o $OUT/libb.dylib -b $OUT/libb.bcell --remove-imports --remove-exports --keep-imports _dyld_get_sdk_version --keep-imports _malloc --keep-imports _printf --keep-imports ___stack_chk_guard $OUT/libb.dylib
# resign
codesign --force --deep -s - $OUT/a-fixed
codesign --force --deep -s - $OUT/libb.dylib
# export OBJC_PRINT_LOAD_METHODS=1
# export OBJC_PRINT_CLASS_SETUP=1
$OUT/a-fixed
# unset OBJC_PRINT_LOAD_METHODS
# unset OBJC_PRINT_CLASS_SETUP
fi

View File

@ -0,0 +1,57 @@
struct class {
class* isa;
class* super;
struct {
void* bucket;
void* preoptimize;
} cache;
uint64_t cache_bits;
}
realizeClassWithoutSwift(class* cls, class* previous) {
// x0 = cls
// x1 = previous
x19 = x0
if (!x0) {
return
}
x28 = x1
x8 = *x19 - 1
if (x8 < 0xf) {
} else {
x8 = x19
x16 = *(x8 + 0x20)
x9 = x16
// strip pointer auth x9
x9 = x9 & 0x7ffffffffff8
w9 = *x9
if (w9 & 0x1f) {
x17 = x8
x17 = 0xc93a << 48
// authenticate x16 x17
x17 = x16
// strip pointer auth x17
if (x16 != x17) {
throw
}
x20 = x16 & 0x7ffffffffff8
x0 = x20
x0 = malloc_size(x0)
if (x0 > 0x1f) {
return
}
} else {
w20 = -0x7ff80000
x21 = x19 + w20
x0 = x21
x0 = safe_ro(x0)
x8 = *x0 & 0x1
}
}
}

View File

@ -0,0 +1,657 @@
libobjc.A.dylib`realizeClassWithoutSwift:
0x193755cac <+0>: pacibsp
0x193755cb0 <+4>: sub sp, sp, #0xc0
0x193755cb4 <+8>: stp x28, x27, [sp, #0x60]
0x193755cb8 <+12>: stp x26, x25, [sp, #0x70]
0x193755cbc <+16>: stp x24, x23, [sp, #0x80]
0x193755cc0 <+20>: stp x22, x21, [sp, #0x90]
0x193755cc4 <+24>: stp x20, x19, [sp, #0xa0]
0x193755cc8 <+28>: stp x29, x30, [sp, #0xb0]
0x193755ccc <+32>: add x29, sp, #0xb0
0x193755cd0 <+36>: mov x19, x0
0x193755cd4 <+40>: cbz x0, 0x193756550 ; <+2212>
0x193755cd8 <+44>: mov x28, x1
0x193755cdc <+48>: ldr x8, [x19]
0x193755ce0 <+52>: sub x8, x8, #0x1
0x193755ce4 <+56>: cmp x8, #0xf
0x193755ce8 <+60>: b.lo 0x193755d08 ; <+92>
0x193755cec <+64>: mov x8, x19
0x193755cf0 <+68>: ldr x16, [x8, #0x20]!
0x193755cf4 <+72>: mov x9, x16
0x193755cf8 <+76>: xpacd x9
0x193755cfc <+80>: and x9, x9, #0x7ffffffffff8
0x193755d00 <+84>: ldr w9, [x9]
0x193755d04 <+88>: tbnz w9, #0x1f, 0x1937560e8 ; <+1084>
0x193755d08 <+92>: mov w20, #-0x7ff80000
0x193755d0c <+96>: add x21, x19, #0x20
0x193755d10 <+100>: mov x0, x21
0x193755d14 <+104>: bl 0x1937753cc ; class_ro_t const* class_data_bits_t::safe_ro<(Authentication)0>() const
0x193755d18 <+108>: ldr w8, [x0]
0x193755d1c <+112>: and w26, w8, #0x1
0x193755d20 <+116>: tbnz w8, #0x1e, 0x193755d58 ; <+172>
0x193755d24 <+120>: mov x23, x0
0x193755d28 <+124>: mov w0, #0x20
0x193755d2c <+128>: mov w1, #0x1
0x193755d30 <+132>: bl 0x193786a90 ; symbol stub for: calloc
0x193755d34 <+136>: mov x22, x0
0x193755d38 <+140>: add x8, x0, #0x8
0x193755d3c <+144>: ldr x9, [x0, #0x8]
0x193755d40 <+148>: tbnz w9, #0x0, 0x193755dd8 ; <+300>
0x193755d44 <+152>: mov x9, x8
0x193755d48 <+156>: movk x9, #0x949b, lsl #48
0x193755d4c <+160>: mov x17, x23
0x193755d50 <+164>: mov x16, x9
0x193755d54 <+168>: b 0x193755e08 ; <+348>
0x193755d58 <+172>: ldr x16, [x21]
0x193755d5c <+176>: mov x17, x21
0x193755d60 <+180>: movk x17, #0xc93a, lsl #48
0x193755d64 <+184>: autdb x16, x17
0x193755d68 <+188>: mov x17, x16
0x193755d6c <+192>: xpacd x17
0x193755d70 <+196>: cmp x16, x17
0x193755d74 <+200>: b.eq 0x193755d7c ; <+208>
0x193755d78 <+204>: brk #0xc473
0x193755d7c <+208>: and x22, x16, #0x7ffffffffff8
0x193755d80 <+212>: mov x0, x22
0x193755d84 <+216>: bl 0x193772238 ; class_rw_t::ro() const
0x193755d88 <+220>: mov x23, x0
0x193755d8c <+224>: ldr x16, [x21]
0x193755d90 <+228>: mov x17, x21
0x193755d94 <+232>: movk x17, #0xc93a, lsl #48
0x193755d98 <+236>: autdb x16, x17
0x193755d9c <+240>: mov x17, x16
0x193755da0 <+244>: xpacd x17
0x193755da4 <+248>: cmp x16, x17
0x193755da8 <+252>: b.eq 0x193755db0 ; <+260>
0x193755dac <+256>: brk #0xc473
0x193755db0 <+260>: and x8, x16, #0x7ffffffffff8
0x193755db4 <+264>: mov w9, #0x3ff7ffff
0x193755db8 <+268>: ldr w10, [x8]
0x193755dbc <+272>: and w11, w10, w9
0x193755dc0 <+276>: orr w11, w11, w20
0x193755dc4 <+280>: mov x12, x10
0x193755dc8 <+284>: casal w12, w11, [x8]
0x193755dcc <+288>: cmp w12, w10
0x193755dd0 <+292>: b.ne 0x193755db8 ; <+268>
0x193755dd4 <+296>: b 0x193755e24 ; <+376>
0x193755dd8 <+300>: and x16, x9, #0xfffffffffffffffe
0x193755ddc <+304>: mov x17, x8
0x193755de0 <+308>: movk x17, #0xe4f, lsl #48
0x193755de4 <+312>: autdb x16, x17
0x193755de8 <+316>: mov x17, x16
0x193755dec <+320>: xpacd x17
0x193755df0 <+324>: cmp x16, x17
0x193755df4 <+328>: b.eq 0x193755dfc ; <+336>
0x193755df8 <+332>: brk #0xc473
0x193755dfc <+336>: mov x8, x16
0x193755e00 <+340>: movk x16, #0xa0d3, lsl #48
0x193755e04 <+344>: mov x17, x23
0x193755e08 <+348>: pacdb x17, x16
0x193755e0c <+352>: str x17, [x8]
0x193755e10 <+356>: orr w8, w26, w20
0x193755e14 <+360>: str w8, [x22]
0x193755e18 <+364>: mov x0, x21
0x193755e1c <+368>: mov x1, x22
0x193755e20 <+372>: bl 0x19377576c ; class_data_bits_t::setData(class_rw_t*)
0x193755e24 <+376>: adrp x8, 50
0x193755e28 <+380>: add x8, x8, #0x5c0 ; _objc_empty_cache
0x193755e2c <+384>: str x8, [x19, #0x10]
0x193755e30 <+388>: str xzr, [x19, #0x18]
0x193755e34 <+392>: cbz w26, 0x193755e44 ; <+408>
0x193755e38 <+396>: add x8, x19, #0x1e
0x193755e3c <+400>: mov w9, #0x4
0x193755e40 <+404>: ldseth w9, w8, [x8]
0x193755e44 <+408>: adrp x8, 363074
0x193755e48 <+412>: ldr w8, [x8, #0x4f0]
0x193755e4c <+416>: cbnz w8, 0x193756574 ; <+2248>
0x193755e50 <+420>: mov x27, x19
0x193755e54 <+424>: ldr x16, [x27, #0x8]!
0x193755e58 <+428>: str x22, [sp, #0x40]
0x193755e5c <+432>: cbz x16, 0x193755e88 ; <+476>
0x193755e60 <+436>: mov x17, x27
0x193755e64 <+440>: movk x17, #0xb5ab, lsl #48
0x193755e68 <+444>: autda x16, x17
0x193755e6c <+448>: mov x17, x16
0x193755e70 <+452>: xpacd x17
0x193755e74 <+456>: cmp x16, x17
0x193755e78 <+460>: b.eq 0x193755e80 ; <+468>
0x193755e7c <+464>: brk #0xc472
0x193755e80 <+468>: mov x0, x16
0x193755e84 <+472>: b 0x193755e8c ; <+480>
0x193755e88 <+476>: mov x0, #0x0
0x193755e8c <+480>: bl 0x19375573c ; remapClass(objc_class*)
0x193755e90 <+484>: mov x24, x0
0x193755e94 <+488>: mov x1, #0x0
0x193755e98 <+492>: bl 0x193755cac ; <+0>
0x193755e9c <+496>: ldr x8, [x19]
0x193755ea0 <+500>: and x0, x8, #0x7ffffffffff8
0x193755ea4 <+504>: bl 0x19375573c ; remapClass(objc_class*)
0x193755ea8 <+508>: mov x25, x0
0x193755eac <+512>: mov x1, #0x0
0x193755eb0 <+516>: bl 0x193755cac ; <+0>
0x193755eb4 <+520>: adrp x20, 373658
0x193755eb8 <+524>: cbz w26, 0x193755ecc ; <+544>
0x193755ebc <+528>: add x8, x19, #0x1e
0x193755ec0 <+532>: mov w9, #0x2000
0x193755ec4 <+536>: ldseth w9, w8, [x8]
0x193755ec8 <+540>: b 0x193755ee0 ; <+564>
0x193755ecc <+544>: ldr w8, [x20, #0xa64]
0x193755ed0 <+548>: cbz w8, 0x193756130 ; <+1156>
0x193755ed4 <+552>: mov w1, #0x0
0x193755ed8 <+556>: mov x0, x19
0x193755edc <+560>: bl 0x193757828 ; objc_class::setInstancesRequireRawIsaRecursively(bool)
0x193755ee0 <+564>: mov x17, x24
0x193755ee4 <+568>: mov x8, x27
0x193755ee8 <+572>: movk x8, #0xb5ab, lsl #48
0x193755eec <+576>: mov x16, x8
0x193755ef0 <+580>: pacda x17, x16
0x193755ef4 <+584>: str x17, [x27]
0x193755ef8 <+588>: ldr w8, [x20, #0xa64]
0x193755efc <+592>: mov x16, x19
0x193755f00 <+596>: movk x16, #0x6ae1, lsl #48
0x193755f04 <+600>: cbnz w8, 0x193755f2c ; <+640>
0x193755f08 <+604>: ldrh w8, [x25, #0x1e]
0x193755f0c <+608>: tbnz w8, #0xd, 0x193755f2c ; <+640>
0x193755f10 <+612>: mov x17, x25
0x193755f14 <+616>: pacda x17, x16
0x193755f18 <+620>: and x8, x17, #0x7ffffffffffff8
0x193755f1c <+624>: mov x9, #0x1
0x193755f20 <+628>: movk x9, #0x100, lsl #48
0x193755f24 <+632>: orr x8, x8, x9
0x193755f28 <+636>: b 0x193755f38 ; <+652>
0x193755f2c <+640>: mov x17, x25
0x193755f30 <+644>: pacda x17, x16
0x193755f34 <+648>: and x8, x17, #0x7ffffffffffff8
0x193755f38 <+652>: str x8, [x19]
0x193755f3c <+656>: cbz x24, 0x193756280 ; <+1492>
0x193755f40 <+660>: cbnz w26, 0x193756280 ; <+1492>
0x193755f44 <+664>: ldr x16, [x21]
0x193755f48 <+668>: mov x17, x21
0x193755f4c <+672>: movk x17, #0xc93a, lsl #48
0x193755f50 <+676>: autdb x16, x17
0x193755f54 <+680>: mov x17, x16
0x193755f58 <+684>: xpacd x17
0x193755f5c <+688>: cmp x16, x17
0x193755f60 <+692>: b.eq 0x193755f68 ; <+700>
0x193755f64 <+696>: brk #0xc473
0x193755f68 <+700>: and x25, x16, #0x7ffffffffff8
0x193755f6c <+704>: mov x8, x24
0x193755f70 <+708>: ldr x16, [x8, #0x20]!
0x193755f74 <+712>: mov x17, x8
0x193755f78 <+716>: movk x17, #0xc93a, lsl #48
0x193755f7c <+720>: autdb x16, x17
0x193755f80 <+724>: mov x17, x16
0x193755f84 <+728>: xpacd x17
0x193755f88 <+732>: cmp x16, x17
0x193755f8c <+736>: b.eq 0x193755f94 ; <+744>
0x193755f90 <+740>: brk #0xc473
0x193755f94 <+744>: and x0, x16, #0x7ffffffffff8
0x193755f98 <+748>: bl 0x193772238 ; class_rw_t::ro() const
0x193755f9c <+752>: mov x26, x0
0x193755fa0 <+756>: adrp x8, 363071
0x193755fa4 <+760>: ldr w8, [x8, #0x3c4]
0x193755fa8 <+764>: cbz w8, 0x193755fc8 ; <+796>
0x193755fac <+768>: mov x0, x19
0x193755fb0 <+772>: bl 0x193775830 ; objc_class::mangledName()
0x193755fb4 <+776>: mov x27, x0
0x193755fb8 <+780>: adrp x1, 60
0x193755fbc <+784>: add x1, x1, #0x660 ; "NSCF"
0x193755fc0 <+788>: bl 0x193786fb0 ; symbol stub for: strstr
0x193755fc4 <+792>: cbz x0, 0x1937561b0 ; <+1284>
0x193755fc8 <+796>: ldr w8, [x23, #0x4]
0x193755fcc <+800>: ldr w9, [x26, #0x8]
0x193755fd0 <+804>: cmp w8, w9
0x193755fd4 <+808>: b.hs 0x193756280 ; <+1492>
0x193755fd8 <+812>: adrp x8, 363071
0x193755fdc <+816>: ldr w8, [x8, #0x380]
0x193755fe0 <+820>: cbnz w8, 0x193756688 ; <+2524>
0x193755fe4 <+824>: mov x0, x25
0x193755fe8 <+828>: bl 0x193770194 ; make_ro_writeable(class_rw_t*)
0x193755fec <+832>: mov x27, x0
0x193755ff0 <+836>: mov x0, x25
0x193755ff4 <+840>: bl 0x193772238 ; class_rw_t::ro() const
0x193755ff8 <+844>: mov x23, x0
0x193755ffc <+848>: ldr w9, [x26, #0x8]
0x193756000 <+852>: ldr w8, [x27, #0x4]
0x193756004 <+856>: sub w26, w9, w8
0x193756008 <+860>: ldr x25, [x27, #0x30]
0x19375600c <+864>: cbz x25, 0x193756264 ; <+1464>
0x193756010 <+868>: ldp w20, w9, [x25]
0x193756014 <+872>: mul w22, w9, w20
0x193756018 <+876>: cbz w22, 0x193756264 ; <+1464>
0x19375601c <+880>: mov x8, #0x0
0x193756020 <+884>: mov w9, #0x1
0x193756024 <+888>: mov w11, #0x8
0x193756028 <+892>: mov w10, #0x1
0x19375602c <+896>: add x12, x25, x8
0x193756030 <+900>: ldr x13, [x12, #0x8]
0x193756034 <+904>: cbz x13, 0x193756050 ; <+932>
0x193756038 <+908>: ldr w12, [x12, #0x20]
0x19375603c <+912>: lsl w13, w9, w12
0x193756040 <+916>: cmn w12, #0x1
0x193756044 <+920>: csel w12, w11, w13, eq
0x193756048 <+924>: cmp w12, w10
0x19375604c <+928>: csel w10, w12, w10, hi
0x193756050 <+932>: add x8, x8, x20
0x193756054 <+936>: cmp x22, x8
0x193756058 <+940>: b.ne 0x19375602c ; <+896>
0x19375605c <+944>: str x28, [sp, #0x38]
0x193756060 <+948>: mov x28, #0x0
0x193756064 <+952>: add w8, w26, w10
0x193756068 <+956>: sub w8, w8, #0x1
0x19375606c <+960>: neg w9, w10
0x193756070 <+964>: and w26, w8, w9
0x193756074 <+968>: adrp x11, 363070
0x193756078 <+972>: add x8, x25, x28
0x19375607c <+976>: ldr x10, [x8, #0x8]
0x193756080 <+980>: cbz x10, 0x193756098 ; <+1004>
0x193756084 <+984>: ldr w8, [x10]
0x193756088 <+988>: add w9, w8, w26
0x19375608c <+992>: str w9, [x10]
0x193756090 <+996>: ldr w10, [x11, #0x380]
0x193756094 <+1000>: cbnz w10, 0x1937560a8 ; <+1020>
0x193756098 <+1004>: add x28, x28, x20
0x19375609c <+1008>: cmp x22, x28
0x1937560a0 <+1012>: b.ne 0x193756078 ; <+972>
0x1937560a4 <+1016>: b 0x19375625c ; <+1456>
0x1937560a8 <+1020>: add x10, x25, x28
0x1937560ac <+1024>: ldr x11, [x10, #0x10]
0x1937560b0 <+1028>: ldp w12, w10, [x10, #0x20]
0x1937560b4 <+1032>: mov w13, #0x1
0x1937560b8 <+1036>: lsl w13, w13, w12
0x1937560bc <+1040>: cmn w12, #0x1
0x1937560c0 <+1044>: mov w12, #0x8
0x1937560c4 <+1048>: csel w12, w12, w13, eq
0x1937560c8 <+1052>: stp x11, x10, [sp, #0x10]
0x1937560cc <+1056>: stp x8, x9, [sp]
0x1937560d0 <+1060>: str x12, [sp, #0x20]
0x1937560d4 <+1064>: adrp x0, 59
0x1937560d8 <+1068>: add x0, x0, #0x71e ; "IVARS: offset %u -> %u for %s (size %u, align %u)"
0x1937560dc <+1072>: bl 0x19376dd58 ; _objc_inform
0x1937560e0 <+1076>: adrp x11, 363070
0x1937560e4 <+1080>: b 0x193756098 ; <+1004>
0x1937560e8 <+1084>: mov x17, x8
0x1937560ec <+1088>: movk x17, #0xc93a, lsl #48
0x1937560f0 <+1092>: autdb x16, x17
0x1937560f4 <+1096>: mov x17, x16
0x1937560f8 <+1100>: xpacd x17
0x1937560fc <+1104>: cmp x16, x17
0x193756100 <+1108>: b.eq 0x193756108 ; <+1116>
0x193756104 <+1112>: brk #0xc473
0x193756108 <+1116>: and x20, x16, #0x7ffffffffff8
0x19375610c <+1120>: mov x0, x20
0x193756110 <+1124>: bl 0x193786c70 ; symbol stub for: malloc_size
0x193756114 <+1128>: cmp x0, #0x1f
0x193756118 <+1132>: b.hi 0x193756550 ; <+2212>
0x19375611c <+1136>: stp x20, x0, [sp, #0x8]
0x193756120 <+1140>: str x19, [sp]
0x193756124 <+1144>: adrp x0, 59
0x193756128 <+1148>: add x0, x0, #0x61e ; "realized class %p has corrupt data pointer: malloc_size(%p) = %zu"
0x19375612c <+1152>: bl 0x193785458 ; _objc_fatal(char const*, ...)
0x193756130 <+1156>: ldrh w22, [x19, #0x1e]
0x193756134 <+1160>: adrp x8, 373657
0x193756138 <+1164>: ldrb w8, [x8, #0xa48]
0x19375613c <+1168>: tbnz w8, #0x0, 0x193756160 ; <+1204>
0x193756140 <+1172>: add x8, x23, #0x18
0x193756144 <+1176>: ldapr x0, [x8]
0x193756148 <+1180>: cbz x0, 0x193756160 ; <+1204>
0x19375614c <+1184>: adrp x1, 59
0x193756150 <+1188>: add x1, x1, #0x614 ; "OS_object"
0x193756154 <+1192>: bl 0x193786f30 ; symbol stub for: strcmp
0x193756158 <+1196>: adrp x9, 373657
0x19375615c <+1200>: cbz w0, 0x193756610 ; <+2404>
0x193756160 <+1204>: cbz x24, 0x1937561a8 ; <+1276>
0x193756164 <+1208>: mov x8, x24
0x193756168 <+1212>: ldr x16, [x8, #0x8]!
0x19375616c <+1216>: cbz x16, 0x1937561a8 ; <+1276>
0x193756170 <+1220>: mov x17, x8
0x193756174 <+1224>: movk x17, #0xb5ab, lsl #48
0x193756178 <+1228>: autda x16, x17
0x19375617c <+1232>: mov x17, x16
0x193756180 <+1236>: xpacd x17
0x193756184 <+1240>: cmp x16, x17
0x193756188 <+1244>: b.eq 0x193756190 ; <+1252>
0x19375618c <+1248>: brk #0xc472
0x193756190 <+1252>: cbz x16, 0x1937561a8 ; <+1276>
0x193756194 <+1256>: ldrh w8, [x24, #0x1e]
0x193756198 <+1260>: orr w9, w8, w22
0x19375619c <+1264>: tbz w9, #0xd, 0x193755ee0 ; <+564>
0x1937561a0 <+1268>: ubfx w1, w8, #13, #1
0x1937561a4 <+1272>: b 0x193755ed8 ; <+556>
0x1937561a8 <+1276>: tbnz w22, #0xd, 0x193755ed4 ; <+552>
0x1937561ac <+1280>: b 0x193755ee0 ; <+564>
0x1937561b0 <+1284>: adrp x1, 59
0x1937561b4 <+1288>: add x1, x1, #0x665 ; "__CF"
0x1937561b8 <+1292>: mov x0, x27
0x1937561bc <+1296>: mov w2, #0x4
0x1937561c0 <+1300>: bl 0x193786f90 ; symbol stub for: strncmp
0x1937561c4 <+1304>: cbz w0, 0x193755fc8 ; <+796>
0x1937561c8 <+1308>: adrp x1, 59
0x1937561cc <+1312>: add x1, x1, #0x66a ; "NSConstantString"
0x1937561d0 <+1316>: mov x0, x27
0x1937561d4 <+1320>: bl 0x193786f30 ; symbol stub for: strcmp
0x1937561d8 <+1324>: cbz w0, 0x193755fc8 ; <+796>
0x1937561dc <+1328>: adrp x1, 59
0x1937561e0 <+1332>: add x1, x1, #0x67b ; "NSSimpleCString"
0x1937561e4 <+1336>: mov x0, x27
0x1937561e8 <+1340>: bl 0x193786f30 ; symbol stub for: strcmp
0x1937561ec <+1344>: cbz w0, 0x193755fc8 ; <+796>
0x1937561f0 <+1348>: ldr w20, [x23, #0x4]
0x1937561f4 <+1352>: mov x0, x25
0x1937561f8 <+1356>: bl 0x193770194 ; make_ro_writeable(class_rw_t*)
0x1937561fc <+1360>: mov x27, x0
0x193756200 <+1364>: mov x0, x25
0x193756204 <+1368>: bl 0x193772238 ; class_rw_t::ro() const
0x193756208 <+1372>: mov x23, x0
0x19375620c <+1376>: ldr x8, [x0, #0x30]
0x193756210 <+1380>: cbz x8, 0x193756620 ; <+2420>
0x193756214 <+1384>: ldp w9, w10, [x8]
0x193756218 <+1388>: mul w10, w10, w9
0x19375621c <+1392>: mov w11, #0x8
0x193756220 <+1396>: cbz w10, 0x193756620 ; <+2420>
0x193756224 <+1400>: mov x13, #0x0
0x193756228 <+1404>: add x14, x8, #0x20
0x19375622c <+1408>: mov w15, #0x1
0x193756230 <+1412>: mov w12, #0x8
0x193756234 <+1416>: ldr w16, [x14, x13]
0x193756238 <+1420>: lsl w17, w15, w16
0x19375623c <+1424>: cmn w16, #0x1
0x193756240 <+1428>: csel w16, w11, w17, eq
0x193756244 <+1432>: cmp w16, w12
0x193756248 <+1436>: csel w12, w16, w12, hi
0x19375624c <+1440>: add x13, x13, x9
0x193756250 <+1444>: cmp x10, x13
0x193756254 <+1448>: b.ne 0x193756234 ; <+1416>
0x193756258 <+1452>: b 0x193756624 ; <+2424>
0x19375625c <+1456>: ldr w8, [x27, #0x4]
0x193756260 <+1460>: ldr x28, [sp, #0x38]
0x193756264 <+1464>: add w8, w26, w8
0x193756268 <+1468>: ldr w9, [x27, #0x8]
0x19375626c <+1472>: add w9, w9, w26
0x193756270 <+1476>: stp w8, w9, [x27, #0x4]
0x193756274 <+1480>: add x8, x23, #0x18
0x193756278 <+1484>: ldapr xzr, [x8]
0x19375627c <+1488>: bl 0x1937650d8 ; gdb_objc_class_changed
0x193756280 <+1492>: ldr w1, [x23, #0x8]
0x193756284 <+1496>: mov x0, x19
0x193756288 <+1500>: bl 0x193775884 ; objc_class::setInstanceSize(unsigned int)
0x19375628c <+1504>: ldr w8, [x23]
0x193756290 <+1508>: tbz w8, #0x2, 0x1937562b4 ; <+1544>
0x193756294 <+1512>: add x9, x19, #0x1e
0x193756298 <+1516>: mov w8, #0x1
0x19375629c <+1520>: ldseth w8, w8, [x9]
0x1937562a0 <+1524>: ldr w8, [x23]
0x1937562a4 <+1528>: tbnz w8, #0x8, 0x1937562b4 ; <+1544>
0x1937562a8 <+1532>: mov w8, #0x2
0x1937562ac <+1536>: ldseth w8, w8, [x9]
0x1937562b0 <+1540>: ldr w8, [x23]
0x1937562b4 <+1544>: tbnz w8, #0xa, 0x193756304 ; <+1624>
0x1937562b8 <+1548>: cbz x24, 0x193756358 ; <+1708>
0x1937562bc <+1552>: mov x8, x24
0x1937562c0 <+1556>: ldr x16, [x8, #0x20]!
0x1937562c4 <+1560>: mov x17, x8
0x1937562c8 <+1564>: movk x17, #0xc93a, lsl #48
0x1937562cc <+1568>: autdb x16, x17
0x1937562d0 <+1572>: mov x17, x16
0x1937562d4 <+1576>: xpacd x17
0x1937562d8 <+1580>: cmp x16, x17
0x1937562dc <+1584>: b.eq 0x1937562e4 ; <+1592>
0x1937562e0 <+1588>: brk #0xc473
0x1937562e4 <+1592>: and x8, x16, #0x7ffffffffff8
0x1937562e8 <+1596>: ldrb w8, [x8, #0x2]
0x1937562ec <+1600>: tbz w8, #0x4, 0x193756318 ; <+1644>
0x1937562f0 <+1604>: ldr x9, [sp, #0x40]
0x1937562f4 <+1608>: ldr w8, [x9]
0x1937562f8 <+1612>: orr w8, w8, #0x100000
0x1937562fc <+1616>: str w8, [x9]
0x193756300 <+1620>: b 0x193756318 ; <+1644>
0x193756304 <+1624>: ldr x9, [sp, #0x40]
0x193756308 <+1628>: ldr w8, [x9]
0x19375630c <+1632>: orr w8, w8, #0x100000
0x193756310 <+1636>: str w8, [x9]
0x193756314 <+1640>: cbz x24, 0x193756358 ; <+1708>
0x193756318 <+1644>: mov x0, x24
0x19375631c <+1648>: mov x1, x19
0x193756320 <+1652>: bl 0x1937566e8 ; addSubclass(objc_class*, objc_class*)
0x193756324 <+1656>: ldr x16, [x19, #0x20]
0x193756328 <+1660>: mov x20, x21
0x19375632c <+1664>: movk x20, #0xc93a, lsl #48
0x193756330 <+1668>: mov x17, x21
0x193756334 <+1672>: movk x17, #0xc93a, lsl #48
0x193756338 <+1676>: autdb x16, x17
0x19375633c <+1680>: mov x17, x16
0x193756340 <+1684>: xpacd x17
0x193756344 <+1688>: cmp x16, x17
0x193756348 <+1692>: b.eq 0x193756350 ; <+1700>
0x19375634c <+1696>: brk #0xc473
0x193756350 <+1700>: and x22, x16, #0x7ffffffffff8
0x193756354 <+1704>: b 0x1937563a8 ; <+1788>
0x193756358 <+1708>: adrp x8, 373657
0x19375635c <+1712>: ldr x9, [x8, #0x868]
0x193756360 <+1716>: add x9, x9, #0x1
0x193756364 <+1720>: str x9, [x8, #0x868]
0x193756368 <+1724>: adrp x8, 373657
0x19375636c <+1728>: ldr x9, [x8, #0xa50]
0x193756370 <+1732>: ldr x16, [x19, #0x20]
0x193756374 <+1736>: mov x20, x21
0x193756378 <+1740>: movk x20, #0xc93a, lsl #48
0x19375637c <+1744>: mov x17, x21
0x193756380 <+1748>: movk x17, #0xc93a, lsl #48
0x193756384 <+1752>: autdb x16, x17
0x193756388 <+1756>: mov x17, x16
0x19375638c <+1760>: xpacd x17
0x193756390 <+1764>: cmp x16, x17
0x193756394 <+1768>: b.eq 0x19375639c ; <+1776>
0x193756398 <+1772>: brk #0xc473
0x19375639c <+1776>: and x22, x16, #0x7ffffffffff8
0x1937563a0 <+1780>: str x9, [x22, #0x18]
0x1937563a4 <+1784>: str x19, [x8, #0xa50]
0x1937563a8 <+1788>: ldrh w23, [x19, #0x1e]
0x1937563ac <+1792>: mov x0, x22
0x1937563b0 <+1796>: bl 0x193772238 ; class_rw_t::ro() const
0x1937563b4 <+1800>: mov x21, x0
0x1937563b8 <+1804>: ldr x8, [x22, #0x8]
0x1937563bc <+1808>: tbz w8, #0x0, 0x1937563f4 ; <+1864>
0x1937563c0 <+1812>: ands x16, x8, #0xfffffffffffffffe
0x1937563c4 <+1816>: b.eq 0x1937563f4 ; <+1864>
0x1937563c8 <+1820>: add x8, x22, #0x8
0x1937563cc <+1824>: mov x17, x8
0x1937563d0 <+1828>: movk x17, #0xe4f, lsl #48
0x1937563d4 <+1832>: autdb x16, x17
0x1937563d8 <+1836>: mov x17, x16
0x1937563dc <+1840>: xpacd x17
0x1937563e0 <+1844>: cmp x16, x17
0x1937563e4 <+1848>: b.eq 0x1937563ec ; <+1856>
0x1937563e8 <+1852>: brk #0xc473
0x1937563ec <+1856>: mov x22, x16
0x1937563f0 <+1860>: b 0x1937563f8 ; <+1868>
0x1937563f4 <+1864>: mov x22, #0x0
0x1937563f8 <+1868>: adrp x8, 363073
0x1937563fc <+1872>: ldr w8, [x8, #0x4f0]
0x193756400 <+1876>: cbnz w8, 0x1937565dc ; <+2352>
0x193756404 <+1880>: mov x8, x21
0x193756408 <+1884>: ldr x16, [x8, #0x20]!
0x19375640c <+1888>: cbz x16, 0x19375648c ; <+2016>
0x193756410 <+1892>: mov x17, x8
0x193756414 <+1896>: movk x17, #0xc310, lsl #48
0x193756418 <+1900>: autda x16, x17
0x19375641c <+1904>: mov x17, x16
0x193756420 <+1908>: xpacd x17
0x193756424 <+1912>: cmp x16, x17
0x193756428 <+1916>: b.eq 0x193756430 ; <+1924>
0x19375642c <+1920>: brk #0xc472
0x193756430 <+1924>: str x16, [sp, #0x58]
0x193756434 <+1928>: cbz x16, 0x193756490 ; <+2020>
0x193756438 <+1932>: ldr x16, [x19, #0x20]
0x19375643c <+1936>: autdb x16, x20
0x193756440 <+1940>: mov x17, x16
0x193756444 <+1944>: xpacd x17
0x193756448 <+1948>: cmp x16, x17
0x19375644c <+1952>: b.eq 0x193756454 ; <+1960>
0x193756450 <+1956>: brk #0xc473
0x193756454 <+1960>: and x0, x16, #0x7ffffffffff8
0x193756458 <+1964>: bl 0x193772238 ; class_rw_t::ro() const
0x19375645c <+1968>: ldr w8, [x0]
0x193756460 <+1972>: ubfx w3, w8, #29, #1
0x193756464 <+1976>: add x1, sp, #0x58
0x193756468 <+1980>: mov x0, x19
0x19375646c <+1984>: mov w2, #0x1
0x193756470 <+1988>: bl 0x193775914 ; prepareMethodLists(objc_class*, method_list_t**, int, bool, bool, char const*)
0x193756474 <+1992>: cbz x22, 0x1937564dc ; <+2096>
0x193756478 <+1996>: add x0, x22, #0x8
0x19375647c <+2000>: add x1, sp, #0x58
0x193756480 <+2004>: mov w2, #0x1
0x193756484 <+2008>: bl 0x1937749ac ; list_array_tt<method_t, method_list_t, method_list_t_authed_ptr>::attachLists(method_list_t* const*, unsigned int)
0x193756488 <+2012>: b 0x193756490 ; <+2020>
0x19375648c <+2016>: str xzr, [sp, #0x58]
0x193756490 <+2020>: ldr x8, [x21, #0x40]
0x193756494 <+2024>: str x8, [sp, #0x50]
0x193756498 <+2028>: cmp x22, #0x0
0x19375649c <+2032>: cset w20, ne
0x1937564a0 <+2036>: cbz x22, 0x1937564bc ; <+2064>
0x1937564a4 <+2040>: cbz x8, 0x1937564bc ; <+2064>
0x1937564a8 <+2044>: add x0, x22, #0x10
0x1937564ac <+2048>: mov w20, #0x1
0x1937564b0 <+2052>: add x1, sp, #0x50
0x1937564b4 <+2056>: mov w2, #0x1
0x1937564b8 <+2060>: bl 0x193774c28 ; list_array_tt<property_t, property_list_t, RawPtr>::attachLists(property_list_t* const*, unsigned int)
0x1937564bc <+2064>: ldr x8, [x21, #0x28]
0x1937564c0 <+2068>: str x8, [sp, #0x48]
0x1937564c4 <+2072>: cbz w20, 0x1937564dc ; <+2096>
0x1937564c8 <+2076>: cbz x8, 0x1937564dc ; <+2096>
0x1937564cc <+2080>: add x0, x22, #0x18
0x1937564d0 <+2084>: add x1, sp, #0x48
0x1937564d4 <+2088>: mov w2, #0x1
0x1937564d8 <+2092>: bl 0x193774d78 ; list_array_tt<unsigned long, protocol_list_t, RawPtr>::attachLists(protocol_list_t* const*, unsigned int)
0x1937564dc <+2096>: ldr x8, [x19]
0x1937564e0 <+2100>: and x8, x8, #0x7ffffffffff8
0x1937564e4 <+2104>: cmp x8, x19
0x1937564e8 <+2108>: b.ne 0x193756518 ; <+2156>
0x1937564ec <+2112>: adrp x8, 326768
0x1937564f0 <+2116>: add x1, x8, #0x2f
0x1937564f4 <+2120>: adrp x3, 61
0x1937564f8 <+2124>: add x3, x3, #0xbf3 ; ""
0x1937564fc <+2128>: adrp x16, 42
0x193756500 <+2132>: add x16, x16, #0xb74 ; objc_noop_imp
0x193756504 <+2136>: paciza x16
0x193756508 <+2140>: mov x2, x16
0x19375650c <+2144>: mov x0, x19
0x193756510 <+2148>: mov w4, #0x0
0x193756514 <+2152>: bl 0x1937568a8 ; addMethod(objc_class*, objc_selector*, void (*)(), char const*, bool)
0x193756518 <+2156>: cbz x28, 0x193756538 ; <+2188>
0x19375651c <+2160>: tst w23, #0x4
0x193756520 <+2164>: mov w8, #0x2
0x193756524 <+2168>: mov w9, #0x4
0x193756528 <+2172>: csel w2, w9, w8, eq
0x19375652c <+2176>: mov x0, x19
0x193756530 <+2180>: mov x1, x28
0x193756534 <+2184>: bl 0x19375714c ; objc::UnattachedCategories::attachToClass(objc_class*, objc_class*, int)
0x193756538 <+2188>: tst w23, #0x4
0x19375653c <+2192>: mov w8, #0x1
0x193756540 <+2196>: cinc w2, w8, ne
0x193756544 <+2200>: mov x0, x19
0x193756548 <+2204>: mov x1, x19
0x19375654c <+2208>: bl 0x19375714c ; objc::UnattachedCategories::attachToClass(objc_class*, objc_class*, int)
0x193756550 <+2212>: mov x0, x19
0x193756554 <+2216>: ldp x29, x30, [sp, #0xb0]
0x193756558 <+2220>: ldp x20, x19, [sp, #0xa0]
0x19375655c <+2224>: ldp x22, x21, [sp, #0x90]
0x193756560 <+2228>: ldp x24, x23, [sp, #0x80]
0x193756564 <+2232>: ldp x26, x25, [sp, #0x70]
0x193756568 <+2236>: ldp x28, x27, [sp, #0x60]
0x19375656c <+2240>: add sp, sp, #0xc0
-> 0x193756570 <+2244>: retab
0x193756574 <+2248>: mov x0, x19
0x193756578 <+2252>: bl 0x193775470 ; objc_class::nameForLogging()
0x19375657c <+2256>: adrp x8, 61
0x193756580 <+2260>: add x8, x8, #0xbf3 ; ""
0x193756584 <+2264>: adrp x9, 59
0x193756588 <+2268>: add x9, x9, #0x111 ; " (meta)"
0x19375658c <+2272>: cmp w26, #0x0
0x193756590 <+2276>: csel x9, x9, x8, ne
0x193756594 <+2280>: ldr x10, [x19, #0x20]
0x193756598 <+2284>: adrp x11, 59
0x19375659c <+2288>: add x11, x11, #0x5f9 ; "(swift)"
0x1937565a0 <+2292>: tst x10, #0x2
0x1937565a4 <+2296>: csel x11, x8, x11, eq
0x1937565a8 <+2300>: adrp x12, 59
0x1937565ac <+2304>: add x12, x12, #0x601 ; "(pre-stable swift)"
0x1937565b0 <+2308>: tst x10, #0x1
0x1937565b4 <+2312>: csel x8, x8, x12, eq
0x1937565b8 <+2316>: stp x11, x8, [sp, #0x28]
0x1937565bc <+2320>: stp x23, xzr, [sp, #0x18]
0x1937565c0 <+2324>: stp x9, x19, [sp, #0x8]
0x1937565c4 <+2328>: adrp x8, 59
0x1937565c8 <+2332>: add x8, x8, #0x5cc ; "CLASS: realizing class '%s'%s %p %p #%u %s%s"
0x1937565cc <+2336>: str x0, [sp]
0x1937565d0 <+2340>: mov x0, x8
0x1937565d4 <+2344>: bl 0x19376dd58 ; _objc_inform
0x1937565d8 <+2348>: b 0x193755e50 ; <+420>
0x1937565dc <+2352>: mov x0, x19
0x1937565e0 <+2356>: bl 0x193775470 ; objc_class::nameForLogging()
0x1937565e4 <+2360>: adrp x8, 59
0x1937565e8 <+2364>: add x8, x8, #0x774 ; "(meta)"
0x1937565ec <+2368>: adrp x9, 61
0x1937565f0 <+2372>: add x9, x9, #0xbf3 ; ""
0x1937565f4 <+2376>: tst w23, #0x4
0x1937565f8 <+2380>: csel x8, x9, x8, eq
0x1937565fc <+2384>: stp x0, x8, [sp]
0x193756600 <+2388>: adrp x0, 59
0x193756604 <+2392>: add x0, x0, #0x753 ; "CLASS: methodizing class '%s' %s"
0x193756608 <+2396>: bl 0x19376dd58 ; _objc_inform
0x19375660c <+2400>: b 0x193756404 ; <+1880>
0x193756610 <+2404>: mov w1, #0x0
0x193756614 <+2408>: mov w8, #0x1
0x193756618 <+2412>: strb w8, [x9, #0xa48]
0x19375661c <+2416>: b 0x193755ed8 ; <+556>
0x193756620 <+2420>: mov w12, #0x8
0x193756624 <+2424>: ldr w9, [x23, #0x4]
0x193756628 <+2428>: udiv w10, w9, w12
0x19375662c <+2432>: mul w22, w10, w12
0x193756630 <+2436>: sub w9, w9, w22
0x193756634 <+2440>: ldr w10, [x27, #0x8]
0x193756638 <+2444>: sub w10, w10, w22
0x19375663c <+2448>: stp w9, w10, [x27, #0x4]
0x193756640 <+2452>: adrp x9, 363070
0x193756644 <+2456>: ldr w9, [x9, #0x380]
0x193756648 <+2460>: cbnz w9, 0x1937566b0 ; <+2564>
0x19375664c <+2464>: cbz x8, 0x193755fc8 ; <+796>
0x193756650 <+2468>: ldp w9, w10, [x8]
0x193756654 <+2472>: mul w10, w10, w9
0x193756658 <+2476>: cbz w10, 0x193755fc8 ; <+796>
0x19375665c <+2480>: mov x11, #0x0
0x193756660 <+2484>: add x8, x8, #0x8
0x193756664 <+2488>: ldr x12, [x8, x11]
0x193756668 <+2492>: cbz x12, 0x193756678 ; <+2508>
0x19375666c <+2496>: ldr w13, [x12]
0x193756670 <+2500>: sub w13, w13, w22
0x193756674 <+2504>: str w13, [x12]
0x193756678 <+2508>: add x11, x11, x9
0x19375667c <+2512>: cmp x10, x11
0x193756680 <+2516>: b.ne 0x193756664 ; <+2488>
0x193756684 <+2520>: b 0x193755fc8 ; <+796>
0x193756688 <+2524>: mov x0, x19
0x19375668c <+2528>: bl 0x193775470 ; objc_class::nameForLogging()
0x193756690 <+2532>: ldr w8, [x23, #0x4]
0x193756694 <+2536>: ldr w9, [x26, #0x8]
0x193756698 <+2540>: stp x8, x9, [sp, #0x8]
0x19375669c <+2544>: str x0, [sp]
0x1937566a0 <+2548>: adrp x0, 59
0x1937566a4 <+2552>: add x0, x0, #0x6da ; "IVARS: sliding ivars for class %s (superclass was %u bytes, now %u)"
0x1937566a8 <+2556>: bl 0x19376dd58 ; _objc_inform
0x1937566ac <+2560>: b 0x193755fe4 ; <+824>
0x1937566b0 <+2564>: mov x0, x19
0x1937566b4 <+2568>: bl 0x193775470 ; objc_class::nameForLogging()
0x1937566b8 <+2572>: ldr w8, [x23, #0x4]
0x1937566bc <+2576>: stp x20, x8, [sp, #0x8]
0x1937566c0 <+2580>: str x0, [sp]
0x1937566c4 <+2584>: adrp x0, 59
0x1937566c8 <+2588>: add x0, x0, #0x68b ; "IVARS: DEBUG: forcing ivars for class '%s' to slide (instanceStart %zu -> %zu)"
0x1937566cc <+2592>: bl 0x19376dd58 ; _objc_inform
0x1937566d0 <+2596>: ldr x8, [x23, #0x30]
0x1937566d4 <+2600>: cbnz x8, 0x193756650 ; <+2468>
0x1937566d8 <+2604>: b 0x193755fc8 ; <+796>
0x1937566dc <+2608>: udf #0x0
0x1937566e0 <+2612>: udf #0x0
0x1937566e4 <+2616>: udf #0x0

View File

@ -0,0 +1,93 @@
libobjc.A.dylib`schedule_class_load:
libobjc.A.dylib[0x1800687c8] <+0>: pacibsp
libobjc.A.dylib[0x1800687cc] <+4>: sub sp, sp, #0x50
libobjc.A.dylib[0x1800687d0] <+8>: stp x24, x23, [sp, #0x10]
libobjc.A.dylib[0x1800687d4] <+12>: stp x22, x21, [sp, #0x20]
libobjc.A.dylib[0x1800687d8] <+16>: stp x20, x19, [sp, #0x30]
libobjc.A.dylib[0x1800687dc] <+20>: stp x29, x30, [sp, #0x40]
libobjc.A.dylib[0x1800687e0] <+24>: add x29, sp, #0x40
libobjc.A.dylib[0x1800687e4] <+28>: cbz x0, 0x1800688fc ; <+308>
libobjc.A.dylib[0x1800687e8] <+32>: mov x19, x0
libobjc.A.dylib[0x1800687ec] <+36>: mov x21, x0
libobjc.A.dylib[0x1800687f0] <+40>: ldr x16, [x21, #0x20]!
libobjc.A.dylib[0x1800687f4] <+44>: mov x17, x21
libobjc.A.dylib[0x1800687f8] <+48>: movk x17, #0xc93a, lsl #48
libobjc.A.dylib[0x1800687fc] <+52>: autdb x16, x17
libobjc.A.dylib[0x180068800] <+56>: mov x17, x16
libobjc.A.dylib[0x180068804] <+60>: xpacd x17
libobjc.A.dylib[0x180068808] <+64>: cmp x16, x17
libobjc.A.dylib[0x18006880c] <+68>: b.eq 0x180068814 ; <+76>
libobjc.A.dylib[0x180068810] <+72>: brk #0xc473
libobjc.A.dylib[0x180068814] <+76>: and x8, x16, #0x7ffffffffff8
libobjc.A.dylib[0x180068818] <+80>: ldrb w8, [x8, #0x2]
libobjc.A.dylib[0x18006881c] <+84>: tbnz w8, #0x7, 0x1800688fc ; <+308>
libobjc.A.dylib[0x180068820] <+88>: mov x8, x19
libobjc.A.dylib[0x180068824] <+92>: ldr x16, [x8, #0x8]!
libobjc.A.dylib[0x180068828] <+96>: cbz x16, 0x180068854 ; <+140>
libobjc.A.dylib[0x18006882c] <+100>: mov x17, x8
libobjc.A.dylib[0x180068830] <+104>: movk x17, #0xb5ab, lsl #48
libobjc.A.dylib[0x180068834] <+108>: autda x16, x17
libobjc.A.dylib[0x180068838] <+112>: mov x17, x16
libobjc.A.dylib[0x18006883c] <+116>: xpacd x17
libobjc.A.dylib[0x180068840] <+120>: cmp x16, x17
libobjc.A.dylib[0x180068844] <+124>: b.eq 0x18006884c ; <+132>
libobjc.A.dylib[0x180068848] <+128>: brk #0xc472
libobjc.A.dylib[0x18006884c] <+132>: mov x0, x16
libobjc.A.dylib[0x180068850] <+136>: b 0x180068858 ; <+144>
libobjc.A.dylib[0x180068854] <+140>: mov x0, #0x0
libobjc.A.dylib[0x180068858] <+144>: bl 0x1800687c8 ; <+0>
libobjc.A.dylib[0x18006885c] <+148>: ldr x0, [x19]
libobjc.A.dylib[0x180068860] <+152>: bl 0x18007b0d8 ; objc_class::getLoadMethod()
libobjc.A.dylib[0x180068864] <+156>: cbz x0, 0x1800688cc ; <+260>
libobjc.A.dylib[0x180068868] <+160>: mov x20, x0
libobjc.A.dylib[0x18006886c] <+164>: adrp x8, 363064
libobjc.A.dylib[0x180068870] <+168>: ldr w8, [x8, #0x374]
libobjc.A.dylib[0x180068874] <+172>: cbnz w8, 0x180068914 ; <+332>
libobjc.A.dylib[0x180068878] <+176>: adrp x22, 363064
libobjc.A.dylib[0x18006887c] <+180>: ldrsw x23, [x22, #0x220]
libobjc.A.dylib[0x180068880] <+184>: adrp x8, 363064
libobjc.A.dylib[0x180068884] <+188>: ldr w9, [x8, #0x224]
libobjc.A.dylib[0x180068888] <+192>: cmp w23, w9
libobjc.A.dylib[0x18006888c] <+196>: b.ne 0x1800688b4 ; <+236>
libobjc.A.dylib[0x180068890] <+200>: lsl w9, w23, #1
libobjc.A.dylib[0x180068894] <+204>: add w9, w9, #0x10
libobjc.A.dylib[0x180068898] <+208>: str w9, [x8, #0x224]
libobjc.A.dylib[0x18006889c] <+212>: adrp x24, 363064
libobjc.A.dylib[0x1800688a0] <+216>: ldr x0, [x24, #0x228]
libobjc.A.dylib[0x1800688a4] <+220>: sbfiz x1, x9, #4, #32
libobjc.A.dylib[0x1800688a8] <+224>: bl 0x180092ec0 ; symbol stub for: realloc
libobjc.A.dylib[0x1800688ac] <+228>: str x0, [x24, #0x228]
libobjc.A.dylib[0x1800688b0] <+232>: b 0x1800688bc ; <+244>
libobjc.A.dylib[0x1800688b4] <+236>: adrp x8, 363064
libobjc.A.dylib[0x1800688b8] <+240>: ldr x0, [x8, #0x228]
libobjc.A.dylib[0x1800688bc] <+244>: add x8, x0, x23, lsl #4
libobjc.A.dylib[0x1800688c0] <+248>: stp x19, x20, [x8]
libobjc.A.dylib[0x1800688c4] <+252>: add w8, w23, #0x1
libobjc.A.dylib[0x1800688c8] <+256>: str w8, [x22, #0x220]
libobjc.A.dylib[0x1800688cc] <+260>: ldr x16, [x21]
libobjc.A.dylib[0x1800688d0] <+264>: mov x17, x21
libobjc.A.dylib[0x1800688d4] <+268>: movk x17, #0xc93a, lsl #48
libobjc.A.dylib[0x1800688d8] <+272>: autdb x16, x17
libobjc.A.dylib[0x1800688dc] <+276>: mov x17, x16
libobjc.A.dylib[0x1800688e0] <+280>: xpacd x17
libobjc.A.dylib[0x1800688e4] <+284>: cmp x16, x17
libobjc.A.dylib[0x1800688e8] <+288>: b.eq 0x1800688f0 ; <+296>
libobjc.A.dylib[0x1800688ec] <+292>: brk #0xc473
libobjc.A.dylib[0x1800688f0] <+296>: and x8, x16, #0x7ffffffffff8
libobjc.A.dylib[0x1800688f4] <+300>: mov w9, #0x800000
libobjc.A.dylib[0x1800688f8] <+304>: ldset w9, w8, [x8]
libobjc.A.dylib[0x1800688fc] <+308>: ldp x29, x30, [sp, #0x40]
libobjc.A.dylib[0x180068900] <+312>: ldp x20, x19, [sp, #0x30]
libobjc.A.dylib[0x180068904] <+316>: ldp x22, x21, [sp, #0x20]
libobjc.A.dylib[0x180068908] <+320>: ldp x24, x23, [sp, #0x10]
libobjc.A.dylib[0x18006890c] <+324>: add sp, sp, #0x50
libobjc.A.dylib[0x180068910] <+328>: retab
libobjc.A.dylib[0x180068914] <+332>: mov x0, x19
libobjc.A.dylib[0x180068918] <+336>: bl 0x180081470 ; objc_class::nameForLogging()
libobjc.A.dylib[0x18006891c] <+340>: str x0, [sp]
libobjc.A.dylib[0x180068920] <+344>: adrp x0, 52
libobjc.A.dylib[0x180068924] <+348>: add x0, x0, #0x7e6 ; "LOAD: class '%s' scheduled for +load"
libobjc.A.dylib[0x180068928] <+352>: bl 0x180079d58 ; _objc_inform
libobjc.A.dylib[0x18006892c] <+356>: b 0x180068878 ; <+176>
libobjc.A.dylib[0x180068930] <+360>: udf #0x0