// Copyright 2014 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package machoimport ()// A FatFile is a Mach-O universal binary that contains at least one architecture.typeFatFilestruct { Magic uint32 Arches []FatArch closer io.Closer}// A FatArchHeader represents a fat header for a specific image architecture.typeFatArchHeaderstruct { Cpu Cpu SubCpu uint32 Offset uint32 Size uint32 Align uint32}const fatArchHeaderSize = 5 * 4// A FatArch is a Mach-O File inside a FatFile.typeFatArchstruct {FatArchHeader *File}// ErrNotFat is returned from [NewFatFile] or [OpenFat] when the file is not a// universal binary but may be a thin binary, based on its magic number.varErrNotFat = &FormatError{0, "not a fat Mach-O file", nil}// NewFatFile creates a new [FatFile] for accessing all the Mach-O images in a// universal binary. The Mach-O binary is expected to start at position 0 in// the ReaderAt.func ( io.ReaderAt) (*FatFile, error) {varFatFile := io.NewSectionReader(, 0, 1<<63-1)// Read the fat_header struct, which is always in big endian. // Start with the magic number. := binary.Read(, binary.BigEndian, &.Magic)if != nil {returnnil, &FormatError{0, "error reading magic number", nil} } elseif .Magic != MagicFat {// See if this is a Mach-O file via its magic number. The magic // must be converted to little endian first though.var [4]bytebinary.BigEndian.PutUint32([:], .Magic) := binary.LittleEndian.Uint32([:])if == Magic32 || == Magic64 {returnnil, ErrNotFat } else {returnnil, &FormatError{0, "invalid magic number", nil} } } := int64(4)// Read the number of FatArchHeaders that come after the fat_header.varuint32 = binary.Read(, binary.BigEndian, &)if != nil {returnnil, &FormatError{, "invalid fat_header", nil} } += 4if < 1 {returnnil, &FormatError{, "file contains no images", nil} }// Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure // there are not duplicate architectures. := make(map[uint64]bool)// Make sure that all images are for the same MH_ type.varType// Following the fat_header comes narch fat_arch structs that index // Mach-O images further in the file. := saferio.SliceCap[FatArch](uint64())if < 0 {returnnil, &FormatError{, "too many images", nil} } .Arches = make([]FatArch, 0, )for := uint32(0); < ; ++ {varFatArch = binary.Read(, binary.BigEndian, &.FatArchHeader)if != nil {returnnil, &FormatError{, "invalid fat_arch header", nil} } += fatArchHeaderSize := io.NewSectionReader(, int64(.Offset), int64(.Size)) .File, = NewFile()if != nil {returnnil, }// Make sure the architecture for this image is not duplicate. := (uint64(.Cpu) << 32) | uint64(.SubCpu)if , := []; || {returnnil, &FormatError{, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", .Cpu, .SubCpu), nil} } [] = true// Make sure the Mach-O type matches that of the first image.if == 0 { = .Type } else {if .Type != {returnnil, &FormatError{, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", , .Type, ), nil} } } .Arches = append(.Arches, ) }return &, nil}// OpenFat opens the named file using [os.Open] and prepares it for use as a Mach-O// universal binary.func ( string) (*FatFile, error) { , := os.Open()if != nil {returnnil, } , := NewFatFile()if != nil { .Close()returnnil, } .closer = return , nil}func ( *FatFile) () error {varerrorif .closer != nil { = .closer.Close() .closer = nil }return}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.