Skip to content

Commit

Permalink
fix: category class name bind lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
blacktop committed Apr 19, 2024
1 parent 9a3251c commit d2793fe
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 27 deletions.
13 changes: 7 additions & 6 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,7 @@ func (f *File) GetBindName(pointer uint64) (string, error) {
return "", fmt.Errorf("failed to parse LC_DYLD_INFO_ONLY bind info: %v", err)
}
for _, bind := range binds {
if bind.Value == pointer {
if (bind.Start + bind.SegOffset) == pointer {
return bind.Name, nil
}
}
Expand Down Expand Up @@ -2511,6 +2511,7 @@ func (f *File) parseBinds(r *bytes.Reader, kind types.BindKind) ([]types.Bind, e
}
bind.Start = f.Segments()[imm].Addr
bind.Segment = f.Segments()[imm].Name
bind.SegStart = f.Segments()[imm].Offset
case types.BIND_OPCODE_ADD_ADDR_ULEB:
out, err := trie.ReadUleb128(r)
if err != nil {
Expand All @@ -2524,15 +2525,15 @@ func (f *File) parseBinds(r *bytes.Reader, kind types.BindKind) ([]types.Bind, e
if sec := f.FindSectionForVMAddr(f.Segment(bind.Segment).Addr + segOffset); sec != nil {
bind.Section = sec.Name
}
bind.Offset = segOffset
bind.SegOffset = segOffset
binds = append(binds, bind)
segOffset += f.pointerSize()
}
case types.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
if sec := f.FindSectionForVMAddr(f.Segment(bind.Segment).Addr + segOffset); sec != nil {
bind.Section = sec.Name
}
bind.Offset = segOffset
bind.SegOffset = segOffset
binds = append(binds, bind)
off, err := trie.ReadUleb128(r)
if err != nil {
Expand All @@ -2543,7 +2544,7 @@ func (f *File) parseBinds(r *bytes.Reader, kind types.BindKind) ([]types.Bind, e
if sec := f.FindSectionForVMAddr(f.Segment(bind.Segment).Addr + segOffset); sec != nil {
bind.Section = sec.Name
}
bind.Offset = segOffset
bind.SegOffset = segOffset
binds = append(binds, bind)
segOffset += uint64(imm)*f.pointerSize() + f.pointerSize()
case types.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
Expand All @@ -2559,7 +2560,7 @@ func (f *File) parseBinds(r *bytes.Reader, kind types.BindKind) ([]types.Bind, e
if sec := f.FindSectionForVMAddr(f.Segment(bind.Segment).Addr + segOffset); sec != nil {
bind.Section = sec.Name
}
bind.Offset = segOffset
bind.SegOffset = segOffset
binds = append(binds, bind)
segOffset += skip + f.pointerSize()
}
Expand Down Expand Up @@ -2607,7 +2608,7 @@ func (f *File) parseBinds(r *bytes.Reader, kind types.BindKind) ([]types.Bind, e
return nil, fmt.Errorf("bind ordinal is out of range")
}
ordinalTable[ord].Value = ptr
ordinalTable[ord].Offset = segOffset
ordinalTable[ord].SegOffset = segOffset
binds = append(binds, ordinalTable[ord])
}
// The delta is bits [51..61]
Expand Down
36 changes: 27 additions & 9 deletions objc.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,21 +717,39 @@ func (f *File) GetObjCCategories() ([]objc.Category, error) {
if err != nil {
return nil, fmt.Errorf("failed to read cstring: %v", err)
}
categoryPtr.ClsVMAddr = f.vma.Convert(categoryPtr.ClsVMAddr)
if c, ok := f.objc[categoryPtr.ClsVMAddr]; ok {
category.Class = c.(*objc.Class)
if categoryPtr.ClsVMAddr > 0 {
categoryPtr.ClsVMAddr = f.vma.Convert(categoryPtr.ClsVMAddr)
if c, ok := f.objc[categoryPtr.ClsVMAddr]; ok {
category.Class = c.(*objc.Class)
} else {
category.Class, err = f.GetObjCClass(categoryPtr.ClsVMAddr)
if err != nil {
if f.HasFixups() {
bindName, err := f.GetBindName(categoryPtr.ClsVMAddr)
if err == nil {
category.Class = &objc.Class{Name: strings.TrimPrefix(bindName, "_OBJC_CLASS_$_")}
} else {
return nil, fmt.Errorf("failed to read super class objc_class_t at vmaddr: %#x; %v", categoryPtr.ClsVMAddr, err)
}
} else {
category.Class = &objc.Class{}
}
}
f.PutObjC(categoryPtr.ClsVMAddr, category.Class)
}
} else {
category.Class, err = f.GetObjCClass(categoryPtr.ClsVMAddr)
if err != nil {
bindName, err := f.GetBindName(categoryPtr.ClsVMAddr)
if c, ok := f.objc[categoryPtr.ClsVMAddr]; ok {
category.Class = c.(*objc.Class)
} else {
category.Class = &objc.Class{}
bindName, err := f.GetBindName(ptr + uint64(unsafe.Offsetof(categoryPtr.ClsVMAddr)))
if err == nil {
category.Class = &objc.Class{Name: strings.TrimPrefix(bindName, "_OBJC_CLASS_$_")}
} else {
category.Class = &objc.Class{}
// return nil, fmt.Errorf("failed to read super class objc_class_t at vmaddr: %#x; %v", categoryPtr.ClsVMAddr, err)
return nil, fmt.Errorf("failed to read super class objc_class_t at vmaddr: %#x; %v", ptr+uint64(unsafe.Offsetof(categoryPtr.ClsVMAddr)), err)
}
f.PutObjC(ptr+uint64(unsafe.Offsetof(categoryPtr.ClsVMAddr)), category.Class)
}
f.PutObjC(categoryPtr.ClsVMAddr, category.Class)
}
if categoryPtr.InstanceMethodsVMAddr > 0 {
categoryPtr.InstanceMethodsVMAddr = f.vma.Convert(categoryPtr.InstanceMethodsVMAddr)
Expand Down
28 changes: 16 additions & 12 deletions types/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,25 +108,29 @@ func (bs Binds) Search(name string) (*Bind, error) {
}

type Bind struct {
Name string
Type uint8
Kind BindKind
Flags uint8
Addend int64
Segment string
Section string
Start uint64
Offset uint64
Dylib string
Value uint64
Name string
Type uint8
Kind BindKind
Flags uint8
Addend int64
Segment string
SegStart uint64
SegOffset uint64
Section string
Start uint64
Dylib string
Value uint64
}

func (b Bind) Offset() uint64 {
return b.SegStart + b.SegOffset
}
func (b Bind) String() string {
return fmt.Sprintf(
"%-7s %-16s %#x %-4s %-10s %5d %-25s\t%s%s",
b.Segment,
b.Section,
b.Start+b.Offset,
b.Start+b.SegOffset,
b.Kind,
getBindType(b.Type),
b.Addend,
Expand Down

0 comments on commit d2793fe

Please sign in to comment.