From f4f54e0a42b99e385db37f4fcf6a2d2886bab5b1 Mon Sep 17 00:00:00 2001 From: blacktop Date: Mon, 23 Oct 2023 01:39:51 -0600 Subject: [PATCH] fix: GetSwiftAccessibleFunctions --- swift.go | 19 +++++++++++---- types/swift/accessible_funcs.go | 43 ++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/swift.go b/swift.go index a8a2c07..aafbcab 100644 --- a/swift.go +++ b/swift.go @@ -513,7 +513,7 @@ func (f *File) GetSwiftDynamicReplacementInfoForOpaqueTypes() (*swift.AutomaticD } // GetSwiftAccessibleFunctions parses the __TEXT.__swift5_acfuncs section -func (f *File) GetSwiftAccessibleFunctions() (*swift.AccessibleFunctionsSection, error) { +func (f *File) GetSwiftAccessibleFunctions() (funcs []swift.TargetAccessibleFunctionRecord, err error) { if sec := f.Section("__TEXT", "__swift5_acfuncs"); sec != nil { off, err := f.vma.GetOffset(f.vma.Convert(sec.Addr)) if err != nil { @@ -526,12 +526,21 @@ func (f *File) GetSwiftAccessibleFunctions() (*swift.AccessibleFunctionsSection, return nil, fmt.Errorf("failed to read %s.%s data: %v", sec.Seg, sec.Name, err) } - var afsec swift.AccessibleFunctionsSection - if err := binary.Read(bytes.NewReader(dat), f.ByteOrder, &afsec); err != nil { - return nil, fmt.Errorf("failed to read %T: %v", afsec, err) + r := bytes.NewReader(dat) + + for { + curr, _ := r.Seek(0, io.SeekCurrent) + var afr swift.TargetAccessibleFunctionRecord + if err := afr.Read(r, sec.Addr+uint64(curr)); err != nil { + if errors.Is(err, io.EOF) { + break + } + return nil, fmt.Errorf("failed to read swift %T: %w", afr, err) + } + funcs = append(funcs, afr) } - return &afsec, nil + return funcs, nil } return nil, fmt.Errorf("MachO has no '__swift5_acfuncs' section: %w", ErrSwiftSectionError) diff --git a/types/swift/accessible_funcs.go b/types/swift/accessible_funcs.go index 4b2c901..4263aeb 100644 --- a/types/swift/accessible_funcs.go +++ b/types/swift/accessible_funcs.go @@ -1,5 +1,10 @@ package swift +import ( + "encoding/binary" + "io" +) + // __swift5_acfuncs type AccessibleFunctionsSection struct { @@ -14,13 +19,43 @@ const ( ) type TargetAccessibleFunctionRecord struct { - Name int32 // char * - GenericEnvironment int32 // TargetGenericEnvironment - FunctionType int32 // mangled name - Function int32 // void * + Name RelativeDirectPointer // char * + GenericEnvironment RelativeDirectPointer // TargetGenericEnvironment + FunctionType RelativeDirectPointer // mangled name + Function RelativeDirectPointer // void * Flags AccessibleFunctionFlags } +func (r TargetAccessibleFunctionRecord) Size() int64 { + return int64( + binary.Size(r.Name.RelOff) + + binary.Size(r.GenericEnvironment.RelOff) + + binary.Size(r.FunctionType.RelOff) + + binary.Size(r.Function.RelOff) + + binary.Size(r.Flags), + ) +} + +func (f *TargetAccessibleFunctionRecord) Read(r io.Reader, addr uint64) error { + f.Name.Address = addr + if err := binary.Read(r, binary.LittleEndian, &f.Name.RelOff); err != nil { + return err + } + f.GenericEnvironment.Address = addr + uint64(binary.Size(f.Name.RelOff)) + if err := binary.Read(r, binary.LittleEndian, &f.GenericEnvironment.RelOff); err != nil { + return err + } + f.FunctionType.Address = addr + uint64(binary.Size(f.Name.RelOff)) + uint64(binary.Size(f.GenericEnvironment.RelOff)) + if err := binary.Read(r, binary.LittleEndian, &f.FunctionType.RelOff); err != nil { + return err + } + f.Function.Address = addr + uint64(binary.Size(f.Name.RelOff)) + uint64(binary.Size(f.GenericEnvironment.RelOff)) + uint64(binary.Size(f.FunctionType.RelOff)) + if err := binary.Read(r, binary.LittleEndian, &f.Function.RelOff); err != nil { + return err + } + return binary.Read(r, binary.LittleEndian, &f.Flags) +} + type AccessibleFunctionCacheEntry struct { Name string NameLen uint32