Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.84 KB | None | 0 0
  1. ##qvm.go
  2.  
  3. package qvm
  4.  
  5. import (
  6.     "encoding/binary"
  7.     "fmt"
  8.     "os"
  9. )
  10.  
  11. const (
  12.     VM_MAGIC_VER1 = 0x12721444
  13.     VM_MAGIC_VER2 = 0x12721445
  14. )
  15.  
  16. //QVMHeader represents the header for a QVMFile. Note that even if VM_MAGIC_VER1
  17. //QVMHeader still contains a JumpTableLength field.
  18. type QVMHeader struct {
  19.     Magic uint32
  20.     InstructionCount uint32
  21.     CodeOffset uint32
  22.     CodeLength uint32
  23.     DataOffset uint32
  24.     DataLength uint32
  25.     LitLength uint32
  26.     BssLength uint32
  27.     JumpTableLength uint32
  28. }
  29.  
  30. //Pretty simple, QVMFile has a header and the three sections normally embedded
  31. //in a QVM file.
  32. type QVMFile struct {
  33.     Header QVMHeader
  34.     Code []byte
  35.     Data []byte
  36.     Lit []byte
  37. }
  38.  
  39. //Also simple. Takes an os.File and creates a QVMFile from it.
  40. //Also performs a few sanity check to save the programmer from
  41. //extra work and potentially malicious files.
  42. func NewQVMFile(file *os.File) (*QVMFile, os.Error) {
  43.  
  44.     //Read the header...
  45.     theFile := &QVMFile{QVMHeader{}, nil, nil, nil}
  46.     if err := binary.Read(file, binary.LittleEndian, &theFile.Header); err != nil {
  47.         return nil, err
  48.     }
  49.  
  50.     //Run a couple sanity checks on the header...
  51.     //First case: Unrecognized magic number
  52.     if theFile.Header.Magic != VM_MAGIC_VER1 && theFile.Header.Magic != VM_MAGIC_VER2 {
  53.         return nil, os.NewError(fmt.Sprintf("Unrecognized QVM version[Magic: 0x%08x]", theFile.Header.Magic))
  54.     }
  55.  
  56.     //Second case: Magic is VM_MAGIC_VER1 but CodeOffset != 32
  57.     if theFile.Header.Magic == VM_MAGIC_VER1 && theFile.Header.CodeOffset != 32 {
  58.         return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver1)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
  59.     }
  60.  
  61.     //Third case: Magic is VM_MAGIC_VER2 but CodeOffset != 36
  62.     if theFile.Header.Magic == VM_MAGIC_VER2 && theFile.Header.CodeOffset != 36 {
  63.         return nil, os.NewError(fmt.Sprintf("Invalid code offset[%d] for magic(Ver2)[0x%08x]", theFile.Header.CodeOffset, theFile.Header.Magic))
  64.     }
  65.  
  66.     //Fourth case: CodeOffset + CodeLength + (CodeLength % 4) != DataOffset
  67.     if theFile.Header.CodeOffset + theFile.Header.CodeLength + (theFile.Header.CodeLength % 4) != theFile.Header.DataOffset {
  68.         return nil, os.NewError(fmt.Sprintf("Invalid data offset[0x%x] or code length[0x%x]", theFile.Header.DataOffset, theFile.Header.CodeLength))
  69.     }
  70.  
  71.     //Read the Code/Data/Lit sections...
  72.     theFile.Code = make([]byte, theFile.Header.CodeLength)
  73.     if _, err := file.ReadAt(theFile.Code, int64(theFile.Header.CodeOffset)); err != nil {
  74.         return nil, err
  75.     }
  76.  
  77.     theFile.Data = make([]byte, theFile.Header.DataLength)
  78.     if _, err := file.ReadAt(theFile.Data, int64(theFile.Header.DataOffset)); err != nil {
  79.         return nil, err
  80.     }
  81.  
  82.     theFile.Lit = make([]byte, theFile.Header.LitLength)
  83.     if _, err := file.ReadAt(theFile.Lit, int64(theFile.Header.DataOffset + theFile.Header.DataLength)); err != nil {
  84.         return nil, err
  85.     }
  86.  
  87.     return theFile, nil
  88. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement