add old go tooling
This commit is contained in:
48
macho-go/internal/wrapper/addr2line/addr2line.go
Normal file
48
macho-go/internal/wrapper/addr2line/addr2line.go
Normal file
@ -0,0 +1,48 @@
|
||||
package addr2line
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
. "ios-wrapper/pkg/ios/macho"
|
||||
)
|
||||
|
||||
// Try to get Image base of a DWARF binary
|
||||
// using __mh_execute_header symbol
|
||||
func TryGetImageBase(mc *MachoContext, symbols []*Symbol) uint64 {
|
||||
try := mc.ImageBase()
|
||||
if try != 0 {
|
||||
return try
|
||||
}
|
||||
for _, symbol := range symbols {
|
||||
if symbol.Name() == "__mh_execute_header" {
|
||||
return symbol.Address()
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// find the symbol name from dysymtab
|
||||
// the address given is somewhere in the function,
|
||||
// assuming that the address is sorted, we find the last symbol
|
||||
// has its address smaller than `tofind`
|
||||
// I'm not sure this would work always, ;)
|
||||
func FindSymbol(symbols []*Symbol, tofind uint64) string {
|
||||
var lastSymbol string = ""
|
||||
for _, symbol := range symbols {
|
||||
if symbol.Address() > tofind {
|
||||
return lastSymbol
|
||||
} else {
|
||||
lastSymbol = symbol.Name()
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ParseAddressString(s string) (uint64, error) {
|
||||
s_, err := strconv.ParseInt(s, 0, 64)
|
||||
v := uint64(s_)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
81
macho-go/internal/wrapper/addr2line/resolver.go
Normal file
81
macho-go/internal/wrapper/addr2line/resolver.go
Normal file
@ -0,0 +1,81 @@
|
||||
package addr2line
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
. "ios-wrapper/pkg/ios/macho"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
symbols []*Symbol
|
||||
debuglineInfo *DebuglineInfo
|
||||
aslr uint64
|
||||
addresses []string
|
||||
}
|
||||
|
||||
type Resolved struct {
|
||||
Raw uint64
|
||||
Base uint64
|
||||
Symbol string
|
||||
File string
|
||||
Line uint32
|
||||
}
|
||||
|
||||
func (r *Resolved) Valid() bool {
|
||||
return r.File == "" && r.Line == 0
|
||||
}
|
||||
|
||||
func (resolver *Resolver) HasNext() bool {
|
||||
return len(resolver.addresses) > 0
|
||||
}
|
||||
|
||||
func (resolver *Resolver) Next() (*Resolved, error) {
|
||||
if !resolver.HasNext() {
|
||||
return nil, errors.New("There is no more address to resolve")
|
||||
}
|
||||
|
||||
head, tail := resolver.addresses[0], resolver.addresses[1:]
|
||||
resolver.addresses = tail
|
||||
|
||||
tofind_aslr, err := ParseAddressString(head)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cannot parse hex address (%s)", head)
|
||||
}
|
||||
|
||||
tofind := tofind_aslr - resolver.aslr
|
||||
symbol := FindSymbol(resolver.symbols, tofind)
|
||||
fileLine := resolver.debuglineInfo.Find(tofind)
|
||||
|
||||
if fileLine == nil {
|
||||
return &Resolved{
|
||||
Raw: tofind_aslr,
|
||||
Base: tofind,
|
||||
Symbol: symbol,
|
||||
File: "",
|
||||
Line: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &Resolved{
|
||||
Raw: tofind_aslr,
|
||||
Base: tofind,
|
||||
Symbol: symbol,
|
||||
File: fileLine.File,
|
||||
Line: fileLine.Line,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewResolver(mc *MachoContext, loadaddr uint64, addresses []string) *Resolver {
|
||||
symbols := mc.CollectSymbols()
|
||||
debuglineInfo := mc.DebugLineInfo()
|
||||
imagebase := TryGetImageBase(mc, symbols)
|
||||
aslr := loadaddr - imagebase
|
||||
|
||||
return &Resolver{
|
||||
symbols,
|
||||
debuglineInfo,
|
||||
aslr,
|
||||
addresses,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user