コード例 #1
0
ファイル: class.go プロジェクト: NeoTse/completion
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
}
コード例 #2
0
ファイル: packet.go プロジェクト: keyphact/pso2-go
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
}
コード例 #3
0
ファイル: line.go プロジェクト: NeoTse/completion
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
}
コード例 #4
0
ファイル: encoding.go プロジェクト: NeoTse/completion
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
}
コード例 #5
0
ファイル: encoding.go プロジェクト: NeoTse/completion
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
}
コード例 #6
0
ファイル: class.go プロジェクト: NeoTse/completion
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
}
コード例 #7
0
ファイル: tagfile.go プロジェクト: keyphact/pso2-go
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
}
コード例 #8
0
ファイル: info.go プロジェクト: NeoTse/completion
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
}
コード例 #9
0
ファイル: encoding_test.go プロジェクト: NeoTse/completion
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)
		}
	}
}
コード例 #10
0
ファイル: archive.go プロジェクト: keyphact/pso2-go
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
}
コード例 #11
0
ファイル: tagfile.go プロジェクト: keyphact/pso2-go
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
}
コード例 #12
0
ファイル: class.go プロジェクト: NeoTse/completion
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
}
コード例 #13
0
ファイル: model.go プロジェクト: keyphact/pso2-go
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
}
コード例 #14
0
ファイル: assembly.go プロジェクト: NeoTse/completion
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
}
コード例 #15
0
ファイル: class.go プロジェクト: noname007/completion
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
}
コード例 #16
0
ファイル: abbrev.go プロジェクト: NeoTse/completion
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
}
コード例 #17
0
ファイル: info.go プロジェクト: NeoTse/completion
func (ie *InfoEntry) Read(br *binary.BinaryReader) error {
	ret := br.ReadInterface(&ie.id)
	ie.debugInfoOffset, _ = br.Seek(0, 1)
	return ret
}
コード例 #18
0
ファイル: metadata.go プロジェクト: NeoTse/completion
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
}
コード例 #19
0
ファイル: metadata.go プロジェクト: NeoTse/completion
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
}
コード例 #20
0
ファイル: line.go プロジェクト: NeoTse/completion
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
}
コード例 #21
0
ファイル: class.go プロジェクト: NeoTse/completion
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
}
コード例 #22
0
ファイル: line.go プロジェクト: NeoTse/completion
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
}
コード例 #23
0
ファイル: info.go プロジェクト: NeoTse/completion
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))
}
コード例 #24
0
ファイル: textfile.go プロジェクト: keyphact/pso2-go
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
}