Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##qvm.go
- package qvm
- import (
- "encoding/binary"
- "fmt"
- "os"
- )
- const (
- VM_MAGIC_VER1 = 0x12721444
- VM_MAGIC_VER2 = 0x12721445
- )
- //QVMHeader represents the header for a QVMFile. Note that even if VM_MAGIC_VER1
- //QVMHeader still contains a JumpTableLength field.
- type QVMHeader struct {
- Magic uint32
- InstructionCount uint32
- CodeOffset uint32
- CodeLength uint32
- DataOffset uint32
- DataLength uint32
- LitLength uint32
- BssLength uint32
- JumpTableLength uint32
- }
- //Pretty simple, QVMFile has a header and the three sections normally embedded
- //in a QVM file.
- type QVMFile struct {
- Header QVMHeader
- Code []byte
- Data []byte
- Lit []byte
- }
- //Also simple. Takes an os.File and creates a QVMFile from it.
- //Also performs a few sanity check to save the programmer from
- //extra work and potentially malicious files.
- func NewQVMFile(file *os.File) (*QVMFile, os.Error) {
- //Read the header...
- theFile := &QVMFile{QVMHeader{}, nil, nil, nil}
- if err := binary.Read(file, binary.LittleEndian, &theFile.Header); err != nil {
- return nil, err
- }
- //Run a couple sanity checks on the header...
- //First case: Unrecognized magic number
- if theFile.Header.Magic != VM_MAGIC_VER1 && theFile.Header.Magic != VM_MAGIC_VER2 {
- return nil, os.NewError(fmt.Sprintf("Unrecognized QVM version[Magic: 0x%08x]", theFile.Header.Magic))
- }
- //Second case: Magic is VM_MAGIC_VER1 but CodeOffset != 32
- if theFile.Header.Magic == VM_MAGIC_VER1 && theFile.Header.CodeOffset != 32 {
- return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver1)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
- }
- //Third case: Magic is VM_MAGIC_VER2 but CodeOffset != 36
- if theFile.Header.Magic == VM_MAGIC_VER2 && theFile.Header.CodeOffset != 36 {
- return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver2)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
- }
- //Fourth case: CodeOffset + CodeLength + (CodeLength % 4) != DataOffset
- if theFile.Header.CodeOffset + theFile.Header.CodeLength + (theFile.Header.CodeLength % 4) != theFile.Header.DataOffset {
- return nil, os.NewError(fmt.Sprintf("Invalid data offset[0x%x] or code length[0x%x]", theFile.Header.DataOffset, theFile.Header.CodeLength))
- }
- //Read the Code/Data/Lit sections...
- theFile.Code = make([]byte, theFile.Header.CodeLength)
- if _, err := file.ReadAt(theFile.Code, int64(theFile.Header.CodeOffset)); err != nil {
- return nil, err
- }
- theFile.Data = make([]byte, theFile.Header.DataLength)
- if _, err := file.ReadAt(theFile.Data, int64(theFile.Header.DataOffset)); err != nil {
- return nil, err
- }
- theFile.Lit = make([]byte, theFile.Header.LitLength)
- if _, err := file.ReadAt(theFile.Lit, int64(theFile.Header.DataOffset + theFile.Header.DataLength)); err != nil {
- return nil, err
- }
- return theFile, nil
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement