From 0ebc22a6a86f6d43c01bb05824991f9e0315c2ca Mon Sep 17 00:00:00 2001 From: Grazfather Date: Thu, 4 May 2017 19:41:20 -0700 Subject: [PATCH] Add COM cmd to load MS-DOS COM files Since COM files don't have a header/magic, has a simple memory map, it's best to have it a separate command. --- .gitignore | 1 + Makefile | 4 +++ go/arch/x86_16/dos.go | 7 +----- go/cmd/com/com.go | 57 +++++++++++++++++++++++++++++++++++++++++++ go/loader/com.go | 2 +- go/loader/load.go | 9 +------ 6 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 go/cmd/com/com.go diff --git a/.gitignore b/.gitignore index f89f07d..0927839 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ deps/ /cgc +/com /fuzz /imgtrace /repl diff --git a/Makefile b/Makefile index 46ebedd..9675e59 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,10 @@ trace: .gopath sh -c "PATH=$(PATHX) $(GOBUILD) -o trace ./go/cmd/trace" $(FIXRPATH) trace +com: .gopath + sh -c "PATH=$(PATHX) $(GOBUILD) -o com ./go/cmd/com" + $(FIXRPATH) com + get: .gopath sh -c "PATH=$(PATHX) go get -u ${DEPS}" diff --git a/go/arch/x86_16/dos.go b/go/arch/x86_16/dos.go index ae86c2e..44f0e16 100644 --- a/go/arch/x86_16/dos.go +++ b/go/arch/x86_16/dos.go @@ -83,12 +83,7 @@ func DosInit(u models.Usercorn, args, env []string) error { u.RegWrite(enum, uint64(reg.Val)) } } - u.RegWrite(u.Arch().SP, 0xbaaaaffc) - // TODO: Determine stack address. Right now making it linux x86 32-like - // with the stack ending at 0xC... - if err := u.MapStack(0xA000, 0x2000); err != nil { - return err - } + u.RegWrite(u.Arch().SP, 0x8000) return nil } diff --git a/go/cmd/com/com.go b/go/cmd/com/com.go new file mode 100644 index 0000000..494be16 --- /dev/null +++ b/go/cmd/com/com.go @@ -0,0 +1,57 @@ +package main + +import ( + "bytes" + "github.com/pkg/errors" + "io/ioutil" + "os" + + "github.com/lunixbochs/usercorn/go" + "github.com/lunixbochs/usercorn/go/cmd" + "github.com/lunixbochs/usercorn/go/loader" + "github.com/lunixbochs/usercorn/go/models" +) + +func main() { + c := cmd.NewUsercornRawCmd() + c.NoArgs = true + + c.MakeUsercorn = func(exe string) (models.Usercorn, error) { + p, err := ioutil.ReadFile(exe) + if err != nil { + return nil, err + } + r := bytes.NewReader(p) + l, err := loader.NewComLoader(r) + if err != nil { + return nil, errors.Wrap(err, "failed to load COM file") + } + u, err := usercorn.NewUsercornRaw(l, c.Config) + + // Map in entire 16 bit address space + err = u.MemMapProt(0, 0x10000, 7) + if err != nil { + return nil, errors.Wrap(err, "failed to map in address space") + } + + // Write in each segment's data + segments, err := l.Segments() + if err != nil { + return nil, errors.Wrap(err, "failed to get segments from loader") + } + for _, seg := range segments { + data, err := seg.Data() + if err != nil { + return nil, errors.Wrap(err, "failed to read segment data") + } + + err = u.MemWrite(seg.Addr, data) + if err != nil { + return nil, errors.Wrap(err, "failed to write segment data") + } + } + + return u, nil + } + c.Run(os.Args, os.Environ()) +} diff --git a/go/loader/com.go b/go/loader/com.go index ea42a7d..d59ba45 100644 --- a/go/loader/com.go +++ b/go/loader/com.go @@ -24,7 +24,7 @@ func (c *ComLoader) OS() string { return "DOS" } -func NewComLoader(r io.ReaderAt, arch string) (models.Loader, error) { +func NewComLoader(r io.ReaderAt) (models.Loader, error) { // Calculate bin size // TODO: We could maybe just pass the file, not the reader buf := make([]byte, 0x1000) diff --git a/go/loader/load.go b/go/loader/load.go index 3788874..1074fb5 100644 --- a/go/loader/load.go +++ b/go/loader/load.go @@ -35,13 +35,6 @@ func LoadArch(r io.ReaderAt, arch string) (models.Loader, error) { } else if MatchCgc(r) { return NewCgcLoader(r, arch) } else { - // TODO: Make COM a separate, explicit command - // COM doesn't have a header - loader, err := NewComLoader(r, arch) - if err != nil { - return nil, errors.WithStack(UnknownMagic) - } else { - return loader, err - } + return nil, errors.WithStack(UnknownMagic) } }