macho/macho-go/internal/wrapper/action/save_imports.go

163 lines
3.8 KiB
Go
Raw Normal View History

2023-06-15 10:41:18 +07:00
package action
import (
2023-07-10 14:14:03 +07:00
"sort"
2023-07-12 13:37:54 +07:00
"strings"
2024-01-03 22:08:57 +07:00
2023-06-15 10:41:18 +07:00
// log "github.com/sirupsen/logrus"
. "ios-wrapper/internal/wrapper/ofile"
"ios-wrapper/pkg/protomodel"
)
2023-07-12 13:37:54 +07:00
type saveImports struct {
keepSymbols []string
2023-07-11 10:06:59 +07:00
}
2023-06-15 10:41:18 +07:00
func (action *saveImports) withMacho(mf *MachoFile) error {
2023-07-12 13:37:54 +07:00
action.saveToInfo(mf)
mc := mf.Context()
if mc.Header().IsDylib() {
mc.WriteInfoToData(mf.Info())
}
return nil
2023-07-12 13:34:02 +07:00
}
func (action *saveImports) saveToInfo(mf *MachoFile) error {
2023-07-10 14:14:03 +07:00
// calculateHash := func(name string) uint32 {
// var h uint32 = 0x811c9dc5
// for _, s := range name {
// h ^= uint32(s)
// h *= 0x01000193
// }
// return h
// }
2023-06-15 10:41:18 +07:00
2023-06-26 15:28:16 +07:00
mc := mf.Context()
2023-07-10 14:14:03 +07:00
// symbols_storage := []*protomodel.MachoInfo_AllImportedSymbols{}
symbols_raw := mc.CollectBindSymbols()
sort.Slice(symbols_raw, func(i, j int) bool {
orderedByLibrary := symbols_raw[i].Dylib() < symbols_raw[j].Dylib()
if symbols_raw[i].Dylib() == symbols_raw[j].Dylib() {
orderedBySymbol := symbols_raw[i].Name() < symbols_raw[j].Name()
return orderedBySymbol
}
return orderedByLibrary
})
libs := []string{}
symbols := []string{}
tables := []*protomodel.MachoInfo_LibraryImportedSymbols{}
var current_table *protomodel.MachoInfo_LibraryImportedSymbols
current_lib := ""
current_symbol := ""
current_lib_idx := -1
current_symbol_idx := -1
2024-01-03 22:08:57 +07:00
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...)
2023-07-10 14:14:03 +07:00
// 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 {
2024-01-10 14:19:59 +07:00
if !symbol.SafeForRemoval() {
2023-06-26 15:28:16 +07:00
continue
}
2023-07-11 10:06:59 +07:00
2023-07-12 13:37:54 +07:00
skip := false
for _, keep := range action.keepSymbols {
name := keep
lib := ""
parts := strings.Split(keep, ",")
if len(parts) == 2 {
name = parts[0]
lib = parts[1]
}
if symbol.Name() != name {
continue
}
if lib == "" || lib == symbol.Dylib() {
skip = true
break
}
}
if skip {
continue
}
2023-07-11 10:06:59 +07:00
2023-07-10 14:14:03 +07:00
// dylib_hash := calculateHash(symbol.Dylib())
2023-06-26 15:28:16 +07:00
seg := mc.Segments()[symbol.Segment()]
2023-06-15 10:41:18 +07:00
2023-06-26 15:28:16 +07:00
var offset uint64
2023-06-15 10:41:18 +07:00
2023-06-26 15:28:16 +07:00
if symbol.Address() >= seg.Vmaddr() {
// this is virtual address
offset = symbol.Address() - seg.Vmaddr()
} else {
// this is file address
offset = symbol.Address() - seg.Fileoff()
}
2023-06-15 10:41:18 +07:00
2023-07-10 14:14:03 +07:00
if current_lib != symbol.Dylib() {
current_lib_idx += len(current_lib) + 1
current_lib = symbol.Dylib()
libs = append(libs, symbol.Dylib())
tables = append(tables, &protomodel.MachoInfo_LibraryImportedSymbols{
LibIndex: uint32(current_lib_idx),
Nsymbols: 0,
Symbols: []*protomodel.MachoInfo_SymbolTable{},
2023-06-15 10:41:18 +07:00
})
2023-07-10 14:14:03 +07:00
current_table = tables[len(tables)-1]
}
if current_symbol != symbol.Name() {
current_symbol_idx += len(current_symbol) + 1
current_symbol = symbol.Name()
symbols = append(symbols, symbol.Name())
}
current_table.Nsymbols += 1
current_table.Symbols = append(current_table.Symbols, &protomodel.MachoInfo_SymbolTable{
SymbolIndex: uint32(current_symbol_idx),
SegmentIndex: symbol.Segment(),
Offset: uint32(offset),
})
}
mf.Info().Symbols = &protomodel.MachoInfo_AllImportedSymbols{
Libs: libs,
Symbols: symbols,
Tables: tables,
2023-06-26 15:28:16 +07:00
}
2023-07-10 14:14:03 +07:00
mf.Info().Main = mc.Main()
2024-01-10 14:19:59 +07:00
2024-01-10 15:56:32 +07:00
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
2024-01-10 14:19:59 +07:00
2023-06-15 10:41:18 +07:00
return nil
}
func (action *saveImports) withFat(ff *FatFile) error {
return defaultWithFat(action, ff)
}
2023-07-11 10:06:59 +07:00
func NewSaveImportsAction(keepSymbols []string) *saveImports {
return &saveImports{
2023-07-12 13:37:54 +07:00
keepSymbols,
}
2023-06-15 10:41:18 +07:00
}