func (i *CacheImage) GetMacho() (*macho.File, error) {
	offset, err := i.GetOffset(i.LoadAddress)
	if err != nil {
		return nil, err
	}
	var rsBase uint64
	sec, opt, err := i.cache.getOptimizations()
	if err != nil {
		return nil, err
	}
	if opt.Version == 16 {
		rsBase = sec.Addr + opt.RelativeMethodSelectorBaseAddressCacheOffset
	}
	i.CacheReader = NewCacheReader(0, 1<<63-1, i.cuuid)
	return macho.NewFile(io.NewSectionReader(i.cache.r[i.cuuid], int64(offset), int64(i.TextSegmentSize)), macho.FileConfig{
		Offset:        int64(offset),
		SectionReader: types.NewCustomSectionReader(i.cache.r[i.cuuid], 0, 1<<63-1),
		CacheReader:   i,
		VMAddrConverter: types.VMAddrConverter{
			Converter: func(addr uint64) uint64 {
				return i.cache.SlideInfo.SlidePointer(addr)
			},
			VMAddr2Offet: func(address uint64) (uint64, error) {
				return i.GetOffset(address)
			},
			Offet2VMAddr: func(offset uint64) (uint64, error) {
				return i.GetVMAddress(offset)
			},
		},
		RelativeSelectorBase: rsBase,
	})
}
GetMacho parses dyld image as a MachO (slow)
package dyld
import (
	"fmt"
	"io"
	"sync"
	"github.com/blacktop/go-macho"
	"github.com/blacktop/go-macho/types"
)
type rangeEntry struct {
	StartAddr  uint64
	FileOffset uint64
	Size       uint32
}
type patchableExport struct {
	Name           string
	OffsetOfImpl   uint32
	PatchLocations []CachePatchableLocation
}
type astate struct {
	mu sync.Mutex
	Deps     bool
	Got      bool
	Stubs    bool
	Exports  bool
	Privates bool
}
func (a *astate) SetDeps(done bool) {
	a.mu.Lock()
	a.Deps = done
	a.mu.Unlock()
}
func (a *astate) IsDepsDone() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.Deps
}
func (a *astate) SetGot(done bool) {
	a.mu.Lock()
	a.Got = done
	a.mu.Unlock()
}
func (a *astate) IsGotDone() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.Got
}
func (a *astate) SetStubs(done bool) {
	a.mu.Lock()
	a.Stubs = done
	a.mu.Unlock()
}
func (a *astate) IsStubsDone() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.Stubs
}
func (a *astate) SetExports(done bool) {
	a.mu.Lock()
	a.Exports = done
	a.mu.Unlock()
}
func (a *astate) IsExportsDone() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.Exports
}
func (a *astate) SetPrivates(done bool) {
	a.mu.Lock()
	a.Privates = done
	a.mu.Unlock()
}
func (a *astate) IsPrivatesDone() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.Privates
}
type analysis struct {
	State        astate
	Dependencies []string
	GotPointers  map[uint64]uint64
	SymbolStubs  map[uint64]uint64
}
type CacheImage struct {
	Name         string
	Index        uint32
	Info         CacheImageInfo
	LocalSymbols []*CacheLocalSymbol64
	Mappings     *cacheMappingsWithSlideInfo
	CacheLocalSymbolsEntry
	CacheImageInfoExtra
	CacheImageTextInfo
	Initializer      uint64
	DOFSectionAddr   uint64
	DOFSectionSize   uint32
	SlideInfo        slideInfo
	RangeEntries     []rangeEntry
	PatchableExports []patchableExport
	ObjC             objcInfo
	Analysis analysis
	cache *File  
	cuuid types.UUID
	CacheReader
	m *macho.File
}
func NewCacheReader(off int64, n int64, u types.UUID) CacheReader {
	return CacheReader{off, off, off + n, u}
}
type CacheReader struct {
	base  int64
	off   int64
	limit int64
	ruuid types.UUID
}
func (i *CacheImage) Read(p []byte) (n int, err error) {
	if i.off >= i.limit {
		return 0, io.EOF
	}
	if max := i.limit - i.off; int64(len(p)) > max {
		p = p[0:max]
	}
	n, err = i.cache.r[i.ruuid].ReadAt(p, i.off)
	i.off += int64(n)
	return
}
func (i *CacheImage) Seek(offset int64, whence int) (int64, error) {
	switch whence {
	default:
		return 0, fmt.Errorf("Seek: invalid whence")
	case io.SeekStart:
		offset += i.base
	case io.SeekCurrent:
		offset += i.off
	case io.SeekEnd:
		offset += i.limit
	}
	if offset < i.base {
		return 0, fmt.Errorf("Seek: invalid offset")
	}
	i.off = offset
	return offset - i.base, nil
}
func (i *CacheImage) ReadAt(p []byte, off int64) (n int, err error) {
	var offset uint64
	if i.m == nil {
		i.m, err = i.GetPartialMacho()
		if err != nil {
			return -1, err
		}
	}
	addr, err := i.m.GetVMAddress(uint64(off))
	if err != nil {
		return -1, err
	}
	i.ruuid, offset, err = i.cache.GetOffset(addr)
	if err != nil {
		return -1, err
	}
	off = int64(offset)
	if off < 0 || off >= i.limit-i.base {
		return 0, io.EOF
	}
	off += i.base
	if max := i.limit - off; int64(len(p)) > max {
		p = p[0:max]
		n, err = i.cache.r[i.ruuid].ReadAt(p, off)
		if err == nil {
			err = io.EOF
		}
		return n, err
	}
	return i.cache.r[i.ruuid].ReadAt(p, off)
}
func (i *CacheImage) SeekToAddr(addr uint64) error {
	uuid, offset, err := i.cache.GetOffset(addr)
	if err != nil {
		return err
	}
	i.ruuid = uuid
	i.Seek(int64(offset), io.SeekStart)
	return nil
}
func (i *CacheImage) ReadAtAddr(buf []byte, addr uint64) (int, error) {
	uuid, off, err := i.cache.GetOffset(addr)
	if err != nil {
		return -1, err
	}
	i.ruuid = uuid
	return i.cache.r[i.ruuid].ReadAt(buf, int64(off))
}
func (i *CacheImage) GetOffset(address uint64) (uint64, error) {
	u, _, e := i.cache.GetOffset(address)
	if e != nil {
		return 0, e
	}
	return i.cache.GetOffsetForUUID(u, address)
}
func (i *CacheImage) GetVMAddress(offset uint64) (uint64, error) {
	return i.cache.GetVMAddressForUUID(i.cuuid, offset)
}