add keep imports action
This commit is contained in:
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"time"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
@ -524,6 +525,77 @@ func (mc *MachoContext) ReworkForObjc() {
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MachoContext) RewriteImportsTable(keepSymbols []string) {
|
||||
allSymbols := mc.CollectBindSymbols()
|
||||
fixups, fixupsOffset := mc.Fixups()
|
||||
|
||||
importTable := fixups.ImportsOffset(uint32(fixupsOffset))
|
||||
symbolTable := fixups.SymbolsOffset(uint32(fixupsOffset))
|
||||
symbolTablePtr := symbolTable
|
||||
|
||||
// in removeBindSymbolsModern, we erase these pointers in file
|
||||
// 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
|
||||
|
||||
keepCount := uint32(0)
|
||||
for _, symbol := range keepSymbols {
|
||||
name := symbol
|
||||
lib := ""
|
||||
parts := strings.Split(symbol, ",")
|
||||
if len(parts) == 2 {
|
||||
name = parts[0]
|
||||
lib = parts[1]
|
||||
}
|
||||
|
||||
symbolInfo := (*ImportSymbol)(nil)
|
||||
for _, s := range allSymbols {
|
||||
if s.Name() != name {
|
||||
continue
|
||||
}
|
||||
if lib == "" || lib == s.Dylib() {
|
||||
symbolInfo = s
|
||||
break
|
||||
}
|
||||
}
|
||||
if symbolInfo == nil {
|
||||
// symbol not found
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("keep symbol %s\n", name)
|
||||
fmt.Printf("importTable at 0x%x; stringTable at 0x%x\n", importTable, symbolTablePtr)
|
||||
fmt.Printf("bind value at 0x%x\n", symbolInfo.file_address)
|
||||
|
||||
// write string to string table
|
||||
mc.file.WriteAt([]byte(name), int64(symbolTablePtr))
|
||||
// fix bind value
|
||||
rebaseOpcodeBytes := make([]byte, 8)
|
||||
mc.file.ReadAt(rebaseOpcodeBytes, int64(symbolInfo.file_address))
|
||||
rebaseOpcode := mc.byteorder.Uint64(rebaseOpcodeBytes)
|
||||
bindOpcode := C.MakeBindFixupOpcodeFromRebase(C.uint64_t(rebaseOpcode), C.uint(keepCount))
|
||||
|
||||
{
|
||||
v := make([]byte, 8)
|
||||
mc.byteorder.PutUint64(v, uint64(bindOpcode))
|
||||
mc.file.WriteAt(v, int64(symbolInfo.file_address))
|
||||
}
|
||||
// write import data to import table
|
||||
entry := C.MakeImportTableEntry(C.uint(symbolInfo.LibOrdinal()), C.uint(symbolTablePtr - symbolTable))
|
||||
{
|
||||
v := make([]byte, 4)
|
||||
mc.byteorder.PutUint32(v, uint32(entry))
|
||||
mc.file.WriteAt(v, int64(importTable))
|
||||
}
|
||||
|
||||
keepCount += 1
|
||||
importTable += 4
|
||||
symbolTablePtr += uint32(len(name)) + 1
|
||||
}
|
||||
|
||||
fixups.imports_count = keepCount
|
||||
mc.file.WriteAt(fixups.Serialize(mc), int64(mc.fixups.dataoff))
|
||||
}
|
||||
|
||||
func (mc *MachoContext) RemoveSymbolTable() {
|
||||
// try to remove symtab and dysymtab
|
||||
mc.removeSymtabCommand()
|
||||
|
@ -104,6 +104,28 @@ uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8) {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t MakeBindFixupOpcodeFromRebase(uint64_t rebaseOpcode, uint32_t ordinal) {
|
||||
printf("fix bind value\n");
|
||||
uint64_t ret;
|
||||
struct dyld_chained_ptr_64_bind* b = (struct dyld_chained_ptr_64_bind*)&ret;
|
||||
b->next = ((struct dyld_chained_ptr_64_rebase*)&rebaseOpcode)->next;
|
||||
b->bind = 1;
|
||||
b->ordinal = ordinal;
|
||||
b->addend = 0;
|
||||
b->reserved = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t MakeImportTableEntry(uint32_t lib_ordinal, uint32_t name_offset) {
|
||||
printf("append import table\n");
|
||||
uint32_t ret;
|
||||
struct dyld_chained_import* import = (struct dyld_chained_import*)&ret;
|
||||
import->lib_ordinal = lib_ordinal;
|
||||
import->name_offset = name_offset;
|
||||
import->weak_import = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ParseFixUps(uint8_t* buffer) {
|
||||
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
||||
printf("starts=0x%x\n", header->starts_offset);
|
||||
|
@ -31,4 +31,7 @@ struct ImportSymbol GetImportsAt(struct ImportTable* table, int i);
|
||||
int GetSegmentFixAt(uint8_t* buffer, uint32_t i, struct SegmentFix* fix);
|
||||
int ParseFixValue(int format, uint64_t value, int* bind, uint64_t* ret1, uint64_t* ret2);
|
||||
uint64_t MakeRebaseFixupOpcode(int next, uint64_t target, uint64_t high8);
|
||||
|
||||
uint64_t MakeBindFixupOpcodeFromRebase(uint64_t rebaseOpcode, uint32_t ordinal);
|
||||
uint32_t MakeImportTableEntry(uint32_t lib_ordinal, uint32_t name_offset);
|
||||
#endif
|
||||
|
@ -37,6 +37,14 @@ func (h *Header) Cpusubtype() uint32 {
|
||||
return h.cpusubtype
|
||||
}
|
||||
|
||||
func (h *Header) IsExecutable() bool {
|
||||
return h.filetype == 0x2
|
||||
}
|
||||
|
||||
func (h *Header) IsDylib() bool {
|
||||
return h.filetype == 0x6
|
||||
}
|
||||
|
||||
func (h *Header) Serialize(mc *MachoContext) []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
binary.Write(buf, mc.byteorder, h.magic)
|
||||
@ -406,6 +414,14 @@ type Fixups struct {
|
||||
symbols_format uint32
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) ImportsOffset(fixups_offset uint32) uint32 {
|
||||
return lcmd.imports_offset + fixups_offset
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) SymbolsOffset(fixups_offset uint32) uint32 {
|
||||
return lcmd.symbols_offset + fixups_offset
|
||||
}
|
||||
|
||||
func (lcmd *Fixups) Serialize(mc *MachoContext) []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
binary.Write(buf, mc.byteorder, lcmd.fixups_version)
|
||||
|
@ -68,6 +68,14 @@ func (mc *MachoContext) Main() uint64 {
|
||||
return mc.entryoff
|
||||
}
|
||||
|
||||
func (mc *MachoContext) Fixups() (*Fixups, uint64) {
|
||||
start := mc.fixups.dataoff
|
||||
size := mc.fixups.datasize
|
||||
fixups := new(Fixups)
|
||||
fixups.Deserialize(mc, mc.buf[start:start+size])
|
||||
return fixups, uint64(mc.fixups.dataoff)
|
||||
}
|
||||
|
||||
func (mc *MachoContext) WriteEnabled() bool {
|
||||
return mc.file != nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user