func LoadAssembly(r io.ReadSeeker) (*Assembly, error) { var ( br = binary.BinaryReader{r, binary.LittleEndian} err error pe_offset uint32 coff coff_file_header cor20 image_cor20 t MetadataHeader ) if _, err := r.Seek(pe_signature_offset, 0); err != nil { return nil, err } if pe_offset, err = br.Uint32(); err != nil { return nil, err } else if _, err := r.Seek(int64(pe_offset), 0); err != nil { return nil, err } if err := br.ReadInterface(&coff); err != nil { return nil, err } net := coff.OptionalHeader.RVAS[14] off := coff.VirtualToFileOffset(net.VirtualAddress) if _, err := br.Seek(int64(off), 0); err != nil { return nil, err } if err := br.ReadInterface(&cor20); err != nil { return nil, err } off = coff.VirtualToFileOffset(cor20.MetaData.VirtualAddress) if _, err := br.Seek(int64(off), 0); err != nil { return nil, err } if err := br.ReadInterface(&t); err != nil { return nil, err } if _, err := br.Seek(int64(off), 0); err != nil { return nil, err } md, err := t.MetadataUtil(&br) if err != nil { return nil, err } a := Assembly{*md, make(map[string]*TypeDef)} idx := ConcreteTableIndex{&a.MetadataUtil, 0, id_TypeDef} for i := uint32(0); i < a.Tables[id_TypeDef].Rows; i++ { idx.index = 1 + i if td, err := TypeDefFromIndex(&idx); err == nil { a.typelut[td.Name().Absolute] = td } } return &a, nil }
func (m *Model) parse() (err error) { reader := binary.BinaryReader{Reader: m.reader, Endianess: binary.LittleEndian} if err = reader.ReadInterface(&m.Header); err != nil { return } reader.Seek(int64(m.Header.HeaderSize)-0x10, 1) offset := int64(m.Header.HeaderSize) for err == nil { entry := ModelEntry{} if err = reader.ReadInterface(&entry); err != nil { if err == io.EOF { return nil } return } entry.Data = io.NewSectionReader(util.ReaderAt(m.reader), offset+0x0c, int64(entry.Size)-0x04) offset += 0x08 + int64(entry.Size) m.Entries = append(m.Entries, entry) switch entry.SubType { case "NODE": // Bone data case "NODO": // More bone things case "VSET": // Vertex data shit err = parseModelEntryVSET(&entry) } } return }
func (mh *MetadataHeader) MetadataUtil(br *binary.BinaryReader) (*MetadataUtil, error) { var ( ret MetadataUtil ) off, err := br.Seek(0, 1) if err != nil { return nil, err } base := off for _, h := range mh.StreamHeaders { switch h.Name { case "#~": off += int64(h.Offset) case "#Strings": if _, err := br.Seek(base+int64(h.Offset), 0); err != nil { return nil, err } else if ret.StringHeap.data, err = br.Read(int(h.Size)); err != nil { return nil, err } ret.StringHeap.Rows = h.Size case "#Blob": if _, err := br.Seek(base+int64(h.Offset), 0); err != nil { return nil, err } else if ret.BlobHeap.data, err = br.Read(int(h.Size)); err != nil { return nil, err } ret.BlobHeap.Rows = h.Size case "#GUID": if _, err := br.Seek(base+int64(h.Offset), 0); err != nil { return nil, err } else if ret.GuidHeap.data, err = br.Read(int(h.Size)); err != nil { return nil, err } ret.GuidHeap.Rows = h.Size } } if _, err := br.Seek(off, 0); err != nil { return nil, err } h := hash_tilde_stream_header{} if err := br.ReadInterface(&h); err != nil { return nil, err } if h.HeapSizes&bit_stringHeapIndexSize != 0 { ret.StringHeap.RowSize = 4 } else { ret.StringHeap.RowSize = 2 } if h.HeapSizes&bit_blobHeapIndexSize != 0 { ret.BlobHeap.RowSize = 4 } else { ret.BlobHeap.RowSize = 2 } if h.HeapSizes&bit_guidHeapIndexSize != 0 { ret.GuidHeap.RowSize = 4 } else { ret.GuidHeap.RowSize = 2 } for i := range ret.Tables { if valid := (h.Valid >> uint(i)) & 1; valid == 0 { continue } if ret.Tables[i].Rows, err = br.Uint32(); err != nil { return nil, err } ret.Tables[i].RowType = table_row_type_lut[i] } for i := range ret.Tables { if ret.Tables[i].Rows == 0 { continue } size, err := ret.Size(ret.Tables[i].RowType) if err != nil { return nil, err } ret.Tables[i].RowSize = uint32(size) if ret.Tables[i].data, err = br.Read(int(ret.Tables[i].RowSize * ret.Tables[i].Rows)); err != nil { return nil, err } } return &ret, nil }
func (ie *InfoEntry) Read(br *binary.BinaryReader) error { ret := br.ReadInterface(&ie.id) ie.debugInfoOffset, _ = br.Seek(0, 1) return ret }
func (lh *lineHeader) Read(br *binary.BinaryReader) error { start, _ := br.Seek(0, 1) err := br.ReadInterface(&lh.Header) if err != nil { return err } if lh.is64 { lh.header_length, err = br.Int64() } else { var v uint32 v, err = br.Uint32() lh.header_length = int64(v) } if err != nil { return err } if lh.minimum_instruction_length, err = br.Uint8(); err != nil { return err } lh.maximum_operations_per_instruction = 1 // TODO: // if lh.maximum_operations_per_instruction, err = br.Uint8(); err != nil { // return err // } if err = br.ReadInterface(&lh.default_is_stmt); err != nil { return err } else if lh.line_base, err = br.Int8(); err != nil { return err } else if lh.line_range, err = br.Uint8(); err != nil { return err } else if lh.opcode_base, err = br.Uint8(); err != nil { return err } lh.standard_opcode_lengths = make([]uint8, lh.opcode_base-1) if err := br.ReadInterface(&lh.standard_opcode_lengths); err != nil { return err } for { var s string if err := br.ReadInterface(&s); err != nil { return err } else if s == "" { break } else { lh.include_directories = append(lh.include_directories, s) } } for { var f fileEntry pos, _ := br.Seek(0, 1) if v, err := br.Uint8(); err != nil { return err } else if v == '\u0000' { break } else { br.Seek(pos, 0) } if err := br.ReadInterface(&f); err != nil { return err } else { lh.file_names = append(lh.file_names, f) } } var s state s.header = lh s.reset() pos, _ := br.Seek(0, 1) for (pos - 4 - start) < int64(lh.Length) { var op DW_LNS if err := br.ReadInterface(&op); err != nil { return err } if op == 0 { var length LEB128 if err := br.ReadInterface(&length); err != nil { return err } var op2 DW_LNE if err := br.ReadInterface(&op2); err != nil { return err } s.executeLNE(op2, length-1, br) } else { s.execute(op, br) } pos, _ = br.Seek(0, 1) } return nil }