macho/macho-go/pkg/ios/fat/fat.go
2023-05-31 16:17:03 +07:00

111 lines
2.4 KiB
Go

package fat
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"os"
. "ios-wrapper/pkg/ios"
"ios-wrapper/pkg/ios/macho"
)
type FatHeader struct {
Magic uint32
Nfat_arch uint32
}
func (h *FatHeader) Serialize() []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, h.Magic)
binary.Write(buf, binary.BigEndian, h.Nfat_arch)
return buf.Bytes()
}
type FatArch struct {
Cputype uint32
Cpusubtype uint32
Offset uint32
Size uint32
Align uint32
}
func (arch *FatArch) Serialize() []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, arch.Cputype)
binary.Write(buf, binary.BigEndian, arch.Cpusubtype)
binary.Write(buf, binary.BigEndian, arch.Offset)
binary.Write(buf, binary.BigEndian, arch.Size)
binary.Write(buf, binary.BigEndian, arch.Align)
return buf.Bytes()
}
// don't know when to use
// it seems that only use if the size of any file is > 4GB
// else just use FatArch
type FatArch64 struct {
Cputype uint32
Cpusubtype uint32
Offset uint64
Size uint64
Align uint32
}
type FatContext struct {
fatArch []*FatArch
}
func (fc *FatContext) ParseFile(file *os.File) {
r := bufio.NewReader(file)
{ // read magic to define byteorder and pointersize
var magic uint32
magic_buf := make([]byte, 4)
r.Read(magic_buf)
magic_r := bytes.NewReader(magic_buf)
binary.Read(magic_r, binary.BigEndian, &magic)
if magic != MagicFat {
return
}
}
var nfat_arch uint32
binary.Read(r, binary.BigEndian, &nfat_arch)
for i := uint32(0); i < nfat_arch; i++ {
var fat_arch FatArch
binary.Read(r, binary.BigEndian, &fat_arch.Cputype)
binary.Read(r, binary.BigEndian, &fat_arch.Cpusubtype)
binary.Read(r, binary.BigEndian, &fat_arch.Offset)
binary.Read(r, binary.BigEndian, &fat_arch.Size)
binary.Read(r, binary.BigEndian, &fat_arch.Align)
fc.fatArch = append(fc.fatArch, &fat_arch)
}
}
func (fc *FatContext) Machos() []*FatArch {
return fc.fatArch
}
func FatSplit(path string) ([]string, error) {
return CreateMachosFromFat(path)
}
// Parse files into Mach-O, calculate fat_arch and join
// into a Fat binary
// @paths: paths to Mach-O binaries
// @out: output Fat file path
// returns success?
func FatJoin(paths []string, out string) error {
machos, err := macho.MachosFromFiles(paths)
if err != nil {
return err
}
if macho.CheckDuplicateArch(machos) {
return errors.New("Duplicate Arch")
}
return CreateFat(machos, out)
}