func (a *attribute_info) String(c *ConstantPool) (ret string) { ret = c.Lut(a.Attribute_name_index).String() switch n := c.Lut(a.Attribute_name_index).String(); n { case "Signature", "SourceFile": ret += "=" br := binary.BinaryReader{bytes.NewReader(a.Info), binary.BigEndian} if i16, err := br.Uint16(); err != nil { ret += err.Error() } else { ret += c.Lut(u2(i16)).String() } case "Code": ret += " (" var cl Code_attribute br := binary.BinaryReader{bytes.NewReader(a.Info), binary.BigEndian} if err := br.ReadInterface(&cl); err != nil { ret += err.Error() } else { for _, a2 := range cl.Attributes { ret += fmt.Sprintf(" %s", c.Lut(a2.Attribute_name_index)) } } ret += " )" } return ret }
func PacketToBinary(p *Packet, i interface{}) (interface{}, error) { reader := binary.BinaryReader{Reader: util.Seeker(bytes.NewBuffer(p.Data)), Endianess: binary.LittleEndian} err := reader.ReadInterface(i) return i, err }
func (s *state) executeLNE(op DW_LNE, length LEB128, br *binary.BinaryReader) error { switch op { case DW_LNE_end_sequence: s.end_sequence = true s.header.matrix = append(s.header.matrix, s.lineEntry) s.reset() case DW_LNE_set_address: var err error if length == 8 { s.address, err = br.Uint64() } else { var v uint32 v, err = br.Uint32() s.address = uint64(v) } s.op_index = 0 return err case DW_LNE_define_file: var fe fileEntry if err := br.ReadInterface(&fe); err != nil { return err } else { s.header.file_names = append(s.header.file_names, fe) } case DW_LNE_set_discriminator: var arg LEB128 if err := br.ReadInterface(&arg); err != nil { return err } s.discriminator = uint(arg) default: panic(fmt.Errorf("%s", op)) } return nil }
func (dw *DW_VIRTUALITY) Read(br *binary.BinaryReader) error { var v LEB128 if err := br.ReadInterface(&v); err != nil { return err } *dw = DW_VIRTUALITY(v) return nil }
func (dw *DW_CHILDREN) Read(br *binary.BinaryReader) error { var v LEB128 if err := br.ReadInterface(&v); err != nil { return err } *dw = DW_CHILDREN(v) return nil }
func NewClass(reader io.ReadSeeker) (*Class, error) { r := binary.BinaryReader{reader, binary.BigEndian} var c Class if err := r.ReadInterface(&c); err != nil { return nil, err } else if c.Magic != magic { return nil, errors.New(fmt.Sprintf("Magic isn't what's expected: %x", c.Magic)) } return &c, nil }
func TagRead(r io.ReadSeeker) (TagFileEntry, error) { reader := binary.BinaryReader{Reader: r, Endianess: binary.LittleEndian} var err error var entry TagFileEntry if err = reader.ReadInterface(&entry); err == nil { offset, err := r.Seek(0, 1) entry.Data = io.NewSectionReader(util.ReaderAt(r), offset, int64(entry.Size)) return entry, err } return TagFileEntry{}, err }
func (ih *InfoHeader) Read(br *binary.BinaryReader) error { err := br.ReadInterface(&ih.Header) if err != nil { return err } if ih.is64 { ih.DebugAbbrevOffset, err = br.Int64() } else { var v uint32 v, err = br.Uint32() ih.DebugAbbrevOffset = int64(v) } if err != nil { return err } ih.AddressSize, err = br.Uint8() return err }
func TestLEB128Read(t *testing.T) { tests := []struct { output LEB128 input []byte }{ {2, []byte{2}}, {127, []byte{127}}, {128, []byte{0 + 0x80, 1}}, {129, []byte{1 + 0x80, 1}}, {130, []byte{2 + 0x80, 1}}, {12857, []byte{57 + 0x80, 100}}, } for _, test := range tests { br := binary.BinaryReader{Reader: bytes.NewReader(test.input)} var v LEB128 if err := br.ReadInterface(&v); err != nil { t.Error(err) } else if v != test.output { t.Errorf("%d != %d", v, test.output) } } }
func (a *Archive) parse() (err error) { reader := binary.BinaryReader{Reader: a.reader, Endianess: binary.LittleEndian} if err = reader.ReadInterface(&a.header); err != nil { return } entryOffset := int64(0x10) a.entries = make([]archiveEntry, a.header.EntryCount) for i := uint32(0); i < a.header.EntryCount; i++ { entry := &a.entries[i] if err = reader.ReadInterface(entry); err != nil { return } entry.Data = io.NewSectionReader(util.ReaderAt(a.reader), entryOffset+int64(entry.DataOffset), int64(entry.DataSize)) entryOffset += int64(entry.DataEnd) } return }
func (f *TagFile) parse() error { var err error reader := binary.BinaryReader{Reader: f.reader, Endianess: binary.LittleEndian} offset := int64(0) var entry TagFileEntry for err = reader.ReadInterface(&entry); err == nil; err = reader.ReadInterface(&entry) { offset += 8 entry.Data = io.NewSectionReader(util.ReaderAt(f.reader), offset, int64(entry.Size)) f.Entries = append(f.Entries, entry) _, err = f.reader.Seek(int64(entry.Size), 1) offset += int64(entry.Size) } if err == io.EOF { return nil } return err }
func (c *ConstantPool) Read(br *binary.BinaryReader) error { var count uint16 if err := br.ReadInterface(&count); err != nil { return err } ic := int(count) ic-- c.constants = make([]Constant, ic, ic) for i := 0; i < len(c.constants); i++ { cc := &c.constants[i] cc.cp = c if err := c.readConstant(cc, br); err != nil { return err } if cc.Tag == CONSTANT_Double || cc.Tag == CONSTANT_Long { // All 8-byte constants take up two entries in the constant_pool table of the class file. i++ } } return 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 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 (a *attribute_info) String(c *ConstantPool) (ret string) { ret = c.Lut(a.Attribute_name_index).String() switch n := c.Lut(a.Attribute_name_index).String(); n { case "Signature", "SourceFile": ret += "=" br := binary.BinaryReader{Reader: bytes.NewReader(a.Info), Endianess: binary.BigEndian} if i16, err := br.Uint16(); err != nil { ret += err.Error() } else { ret += c.Lut(u2(i16)).String() } case "Code": ret += " ( " var cl Code_attribute br := binary.BinaryReader{Reader: bytes.NewReader(a.Info), Endianess: binary.BigEndian} if err := br.ReadInterface(&cl); err != nil { ret += err.Error() } else { ret += strings.Join(sortStrings(cl.Attributes, c), " ") } ret += " )" } return ret }
func (ae *AbbrevEntry) Read(br *binary.BinaryReader) error { if err := br.ReadInterface(&ae.Code); err != nil { return err } else if err := br.ReadInterface(&ae.Tag); err != nil { return err } else if err := br.ReadInterface(&ae.Children); err != nil { return err } for { var v AttributeSpecification if err := br.ReadInterface(&v); err != nil { return err } if v.Name == 0 && v.Form == 0 { break } ae.Attributes = append(ae.Attributes, v) } return nil }
func (ie *InfoEntry) Read(br *binary.BinaryReader) error { ret := br.ReadInterface(&ie.id) ie.debugInfoOffset, _ = br.Seek(0, 1) return ret }
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 (m *MetadataUtil) Create(br *binary.BinaryReader, v interface{}) error { t := reflect.ValueOf(v) if t.Kind() != reflect.Ptr { return errors.New(fmt.Sprintf("Expected a pointer not %s", t.Kind())) } v2 := t.Elem() name := v2.Type().Name() if name == "StringIndex" { size := m.StringHeap.RowSize index, err := m.ReadIndex(br, uint(size)) if err != nil { return err } data := m.StringHeap.data[index:m.StringHeap.Rows] for i := range data { if data[i] == '\u0000' { data = data[:i] break } } v2.SetString(string(data)) } else if name == "Guid" { size := m.GuidHeap.RowSize if index, err := m.ReadIndex(br, uint(size)); err != nil { return err } else if index != 0 { index = (index - 1) * 16 g := Guid(m.GuidHeap.data[index : index+16]) v2.Set(reflect.ValueOf(g)) } } else if strings.HasSuffix(name, "EncodedIndex") { size, err := m.Size(v2.Type()) if err != nil { return err } idx, err := m.ReadIndex(br, size) if err != nil { return err } var ( tables = enc_lut[idx_name_lut[name]] b = util.Bits(len(tables)) mask = uint32(0xffff << b) tbl = idx &^ mask ti ConcreteTableIndex ) idx = idx >> b ti.index = idx ti.table = tables[int(tbl)] ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else if strings.HasSuffix(name, "Index") { size, err := m.Size(v2.Type()) if err != nil { return err } var ti ConcreteTableIndex if ti.index, err = m.ReadIndex(br, size); err != nil { return err } if name == "BlobIndex" { ti.table = id_Blob } else { ti.table = idx_name_lut[name] } ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else { if v2.Kind() != reflect.Struct { return br.ReadInterface(v) } for i := 0; i < v2.NumField(); i++ { f := v2.Field(i) a := f.Addr() if err := m.Create(br, a.Interface()); err != nil { return err } } } return nil }
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 }
func (cp *ConstantPool) readConstant(c *Constant, br *binary.BinaryReader) error { err := br.ReadInterface(&c.Tag) if err != nil { return err } switch c.Tag { case CONSTANT_String: fallthrough case CONSTANT_MethodType: fallthrough case CONSTANT_Class: return br.ReadInterface(&c.Index[0]) case CONSTANT_Fieldref: fallthrough case CONSTANT_Methodref: fallthrough case CONSTANT_NameAndType: fallthrough case CONSTANT_InvokeDynamic: fallthrough case CONSTANT_InterfaceMethodref: if err := br.ReadInterface(&c.Index[0]); err != nil { return err } return br.ReadInterface(&c.Index[1]) case CONSTANT_Integer: var v int32 return br.ReadInterface(&v) case CONSTANT_Float: var v float32 return br.ReadInterface(&v) case CONSTANT_Long: var v int64 return br.ReadInterface(&v) case CONSTANT_Double: var v float64 return br.ReadInterface(&v) case CONSTANT_Utf8: var length u2 if err := br.ReadInterface(&length); err != nil { return err } else if d, err := br.Read(int(length)); err != nil { return err } else { c.Value = string(d) } case CONSTANT_MethodHandle: var ref_kind u1 if err := br.ReadInterface(&ref_kind); err != nil { return err } c.Index[0] = u2(ref_kind) return br.ReadInterface(&c.Index[1]) default: return errors.New(fmt.Sprintf("Unimplemented tag: %d", c.Tag)) } return nil }
func (s *state) execute(op DW_LNS, br *binary.BinaryReader) error { switch op { case DW_LNS_copy: s.header.matrix = append(s.header.matrix, s.lineEntry) s.discriminator = 0 s.basic_block = false s.prologue_end = false s.epilogue_begin = false case DW_LNS_advance_pc: var advance LEB128 if err := br.ReadInterface(&advance); err != nil { return err } s.advance(uint(advance)) case DW_LNS_advance_line: var delta SLEB128 if err := br.ReadInterface(&delta); err != nil { return err } s.line += int(delta) case DW_LNS_set_file: var arg LEB128 if err := br.ReadInterface(&arg); err != nil { return err } s.file = int(arg) case DW_LNS_set_column: var arg LEB128 if err := br.ReadInterface(&arg); err != nil { return err } s.column = int(arg) case DW_LNS_negate_stmt: s.is_stmt = !s.is_stmt case DW_LNS_set_basic_block: s.basic_block = true case DW_LNS_fixed_advance_pc: var arg uint16 if err := br.ReadInterface(&arg); err != nil { return err } s.address += uint64(arg) s.op_index = 0 case DW_LNS_set_prologue_end: s.prologue_end = true case DW_LNS_set_epilogue_begin: s.epilogue_begin = true case DW_LNS_set_isa: var arg LEB128 if err := br.ReadInterface(&arg); err != nil { return err } s.isa = int(arg) case DW_LNS_const_add_pc: op = 255 fallthrough default: if uint8(op) > s.header.opcode_base { op2 := int(uint8(op) - s.header.opcode_base) advance := op2 / int(s.header.line_range) line := (int(op2) % int(s.header.line_range)) + int(s.header.line_base) s.line += line s.advance(uint(advance)) s.header.matrix = append(s.header.matrix, s.lineEntry) s.discriminator = 0 s.epilogue_begin = false s.prologue_end = false s.basic_block = false } } return nil }
func (ie *InfoEntry) data(form DW_FORM, br binary.BinaryReader) interface{} { if form == DW_FORM_ref_addr && ie.header.Version < 3 { form = DW_FORM_addr } switch form { case DW_FORM_flag_present: return true case DW_FORM_exprloc, DW_FORM_block: var size LEB128 br.ReadInterface(&size) r, _ := br.Read(int(size)) return r case DW_FORM_block1: size, _ := br.Uint8() r, _ := br.Read(int(size)) return r case DW_FORM_block2: size, _ := br.Uint16() r, _ := br.Read(int(size)) return r case DW_FORM_block4: size, _ := br.Uint32() r, _ := br.Read(int(size)) return r case DW_FORM_addr: if ie.header.AddressSize == 8 { v, _ := br.Uint64() return v } else { v, _ := br.Uint32() return uint64(v) } case DW_FORM_ref_addr, DW_FORM_strp, DW_FORM_sec_offset: if ie.header.is64 { v, _ := br.Uint64() return v } else { v, _ := br.Uint32() return uint64(v) } case DW_FORM_ref1, DW_FORM_flag, DW_FORM_data1: v, _ := br.Uint8() return uint64(v) case DW_FORM_ref2, DW_FORM_data2: v, _ := br.Uint16() return uint64(v) case DW_FORM_ref4, DW_FORM_data4: v, _ := br.Uint32() return uint64(v) case DW_FORM_ref8, DW_FORM_data8: v, _ := br.Uint64() return v case DW_FORM_sdata, DW_FORM_udata: var r LEB128 br.ReadInterface(&r) return uint64(r) case DW_FORM_string: buf := make([]byte, 4096) for i := range buf { if v, err := br.Uint8(); err != nil { return err } else if v == 0 { buf = buf[:i] break } else { buf[i] = byte(v) } } return string(buf) } panic(fmt.Errorf("Unimplemented format: %s", form)) }
func (t *TextFile) parse(r io.ReadSeeker) (err error) { nifl, err := TagRead(r) if err != nil { return err } if nifl.Tag != "NIFL" { return errors.New("NIFL tag expected") } reader := binary.BinaryReader{Reader: nifl.Data, Endianess: binary.LittleEndian} type niflHeaderType struct { Unk, OffsetREL0, SizeREL0, OffsetNOF0, SizeNOF0 uint32 } var niflHeader niflHeaderType if err = reader.ReadInterface(&niflHeader); err != nil { return err } if niflHeader.Unk != 1 { return errors.New("NIFL header magic != 1") } r.Seek(int64(niflHeader.OffsetREL0), 0) rel0, err := TagRead(r) if rel0.Tag != "REL0" { return errors.New("REL0 tag expected") } var rel0data io.ReadSeeker var rel0strings io.ReadSeeker reader = binary.BinaryReader{Reader: rel0.Data, Endianess: binary.LittleEndian} rel0size, err := reader.Uint32() rel0data = io.NewSectionReader(util.ReaderAt(rel0.Data), 8, int64(rel0size)-8) rel0strings = io.NewSectionReader(util.ReaderAt(rel0.Data), int64(rel0size), int64(rel0.Size-rel0size)) if rel0size < textBufferDataThreshold { rel0data, err = util.MemReader(rel0data) if err != nil { return err } } if rel0.Size-rel0size < textBufferThreshold { rel0strings, err = util.MemReader(rel0strings) if err != nil { return err } } r.Seek(int64(niflHeader.OffsetNOF0), 0) nof0, err := TagRead(r) if nof0.Tag != "NOF0" { return errors.New("NOF0 tag expected") } nof0reader := binary.BinaryReader{Reader: nof0.Data, Endianess: binary.LittleEndian} count, err := nof0reader.Uint32() offsets := make([]uint32, int(count)+1) i := 0 for offset, _ := nof0reader.Uint32(); i < int(count); i++ { end, _ := nof0reader.Uint32() offsets[i] = end - offset offset = end if offsets[i]%4 != 0 { return errors.New("nof0 entry not a multiple of 32 bits") } } offsets[i] = 8 t.Entries = make([]TextEntry, len(offsets)) rel0reader := binary.BinaryReader{Reader: rel0data, Endianess: binary.LittleEndian} pairMode := false var pair *string var pairi int for i, offset := range offsets { entry := &t.Entries[i] entry.Value = make([]uint32, offset/4) for i := 0; i < int(offset/4); i++ { entry.Value[i], err = rel0reader.Uint32() } if entry.Value[0] == 0xffffffff { pairMode = true } else if entry.Value[0] == 0x14 { pairMode = false pair = nil } if len(entry.Value) == 1 && entry.Value[0] != 0xffffffff { rel0strings.Seek(int64(entry.Value[0]-rel0size-8), 0) charSize := 1 if pair != nil { charSize = 2 } entry.Text, _ = readString(charSize, rel0strings) if pair != nil { entry.TextStatus = TextEntryString t.Pairs = append(t.Pairs, TextPair{*pair, entry.Text, pairi, i}) pair = nil } else { entry.TextStatus = TextEntryIdentifier if pairMode { pair = &entry.Text pairi = i } } } } _, err = r.Seek(int64((nof0.Size+8+0x0f)/0x10*0x10)-8, 1) nend, err := TagRead(r) if nend.Tag != "NEND" { return errors.New("NEND tag expected") } return err }