func NewUsercorn(exe string, prefix string) (*Usercorn, error) { l, err := loader.LoadFile(exe) if err != nil { return nil, err } a, os, err := arch.GetArch(l.Arch(), l.OS()) if err != nil { return nil, err } unicorn, err := NewUnicorn(a, os, l.ByteOrder()) if err != nil { return nil, err } exe, _ = filepath.Abs(exe) u := &Usercorn{ Unicorn: unicorn, exe: exe, loader: l, LoadPrefix: prefix, traceMatching: true, } // load kernels // the array cast is a trick to work around circular imports if os.Kernels != nil { kernelI := os.Kernels(u) kernels := make([]common.Kernel, len(kernelI)) for i, k := range kernelI { kernels[i] = k.(common.Kernel) } u.kernels = kernels } // map binary (and interp) into memory u.status = models.StatusDiff{U: u, Color: true} u.interpBase, u.entry, u.base, u.binEntry, err = u.mapBinary(u.loader, false) if err != nil { return nil, err } // find data segment for brk segments, err := l.Segments() if err != nil { return nil, err } for _, seg := range segments { if seg.Prot&uc.PROT_WRITE != 0 { addr := u.base + seg.Addr + seg.Size if addr > u.brk { u.brk = addr } } } // TODO: have a "host page size", maybe arch.Align() mask := uint64(4096 - 1) u.Brk((u.brk + mask) & ^mask) return u, nil }
func NewUsercornRaw(l models.Loader, config *models.Config) (*Usercorn, error) { config = config.Init() a, OS, err := arch.GetArch(l.Arch(), l.OS()) if err != nil { return nil, err } unicorn, err := NewUnicorn(a, OS, l.ByteOrder()) if err != nil { return nil, err } u := &Usercorn{ Unicorn: unicorn, traceMatching: true, config: config, loader: l, exit: 0xffffffffffffffff, } if config.Output == os.Stderr && readline.IsTerminal(int(os.Stderr.Fd())) { config.Color = true } u.memio = memio.NewMemIO( // ReadAt() callback func(p []byte, addr uint64) (int, error) { if err := u.MemReadInto(p, addr); err != nil { return 0, err } if u.config.TraceMemBatch { u.memlog.UpdateBytes(addr, p, false) } return len(p), nil }, // WriteAt() callback func(p []byte, addr uint64) (int, error) { if err := u.MemWrite(addr, p); err != nil { return 0, err } if u.config.TraceMemBatch { u.memlog.UpdateBytes(addr, p, true) } return len(p), nil }, ) // load kernels // the array cast is a trick to work around circular imports if OS.Kernels != nil { kernelI := OS.Kernels(u) kernels := make([]co.Kernel, len(kernelI)) for i, k := range kernelI { kernels[i] = k.(co.Kernel) } u.kernels = kernels } u.status = models.StatusDiff{U: u} if u.config.LoopCollapse > 0 { u.blockloop = models.NewLoopDetect(u.config.LoopCollapse) } // TODO: if we error, should close Usercorn/Unicorn instance? // GC might take its time if err := u.mapStack(); err != nil { return nil, err } if err := u.addHooks(); err != nil { return nil, err } return u, nil }