Skip to content

Commit

Permalink
add all constant
Browse files Browse the repository at this point in the history
  • Loading branch information
phith0n committed Aug 18, 2021
1 parent 9312b0a commit 7c5987d
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 15 deletions.
26 changes: 22 additions & 4 deletions class/classfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ type ClassFile struct {
MajorVersion uint16
ConstantPool []Constant
AccessFlag uint16
ThisClassOffset uint16
SuperClassOffset uint16
InterfaceOffsetArray []uint16
ThisClassIndex uint16
SuperClassIndex uint16
InterfaceIndexArray []uint16
Fields []*Field
Methods []*Method
Attributes []*Attribute
Expand Down Expand Up @@ -53,7 +53,7 @@ func (cf *ClassFile) readConstantPool(stream *commons.Stream) error {

// Note: Constant Pool index is start from 1, not 0
for i := uint16(1); i < size; i++ {
err = cf.readConstantPool(stream)
err = cf.readConstant(stream)
if err != nil {
return err
}
Expand Down Expand Up @@ -84,6 +84,24 @@ func (cf *ClassFile) readConstant(stream *commons.Stream) error {
obj, err = readConstantClass(stream)
case CONSTANT_STRING_INGFO:
obj, err = readConstantString(stream)
case CONSTANT_FIELD_REF_INFO:
obj, err = readConstantFieldRef(stream)
case CONSTANT_METHOD_REF_INFO:
obj, err = readConstantMethodRef(stream)
case CONSTANT_INTERFACE_METHOD_REF:
obj, err = readConstantInterfaceMethodRef(stream)
case CONSTANT_NAME_AND_TYPE_INFO:
obj, err = readConstantNameAndType(stream)
case CONSTANT_DYNAMIC_INFO:
obj, err = readConstantDynamic(stream)
case CONSTANT_INVOKE_DYNAMIC_INFO:
obj, err = readConstantInvokeDynamic(stream)
case CONSTANT_MODULE_INFO:
obj, err = readConstantModule(stream)
case CONSTANT_PACKAGE_INFO:
obj, err = readConstantPackage(stream)
default:
err = fmt.Errorf("constant type %v doesn't exists", bs)
}

if err != nil {
Expand Down
8 changes: 3 additions & 5 deletions class/constant_class.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (
)

type ConstantClass struct {
NameOffset uint16
Reference *ConstantUTF8 // Reference must be a ConstantUTF8 object
NameIndex uint16
}

func (c *ConstantClass) ToBytes() []byte {
var bs = []byte{CONSTANT_CLASS_INFO}
bs = append(bs, commons.NumberToBytes(c.NameOffset)...)
bs = append(bs, commons.NumberToBytes(c.NameIndex)...)
return bs
}

Expand All @@ -26,7 +25,6 @@ func readConstantClass(stream *commons.Stream) (*ConstantClass, error) {

var i = binary.BigEndian.Uint16(bs)
return &ConstantClass{
NameOffset: i,
// lack of Reference because ConstantPool have not been constructed yet
NameIndex: i,
}, nil
}
34 changes: 34 additions & 0 deletions class/constant_dynamic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantDynamic struct {
BootstrapMethodIndex uint16 // a reference to the BootstrapMethod in ClassFile.Attributes
NameAndTypeIndex uint16
}

func (c *ConstantDynamic) ToBytes() []byte {
var bs = []byte{CONSTANT_DYNAMIC_INFO}
bs = append(bs, commons.NumberToBytes(c.BootstrapMethodIndex)...)
bs = append(bs, commons.NumberToBytes(c.NameAndTypeIndex)...)
return bs
}

func readConstantDynamic(stream *commons.Stream) (*ConstantDynamic, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant dynamic failed, no enough data in the stream")
}

var c = &ConstantDynamic{}
c.BootstrapMethodIndex = binary.BigEndian.Uint16(bs[:2])
c.NameAndTypeIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}

30 changes: 29 additions & 1 deletion class/constant_fieldref.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantFieldRef struct {

ClassIndex uint16
NameAndTypeIndex uint16
}

func (c *ConstantFieldRef) ToBytes() []byte {
var bs = []byte{CONSTANT_FIELD_REF_INFO}
bs = append(bs, commons.NumberToBytes(c.ClassIndex)...)
bs = append(bs, commons.NumberToBytes(c.NameAndTypeIndex)...)
return bs
}

func readConstantFieldRef(stream *commons.Stream) (*ConstantFieldRef, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant field ref failed, no enough data in the stream")
}

var c = &ConstantFieldRef{}
c.ClassIndex = binary.BigEndian.Uint16(bs[:2])
c.NameAndTypeIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}
33 changes: 33 additions & 0 deletions class/constant_interface_methodref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantInterfaceMethodRef struct {
ClassIndex uint16
NameAndTypeIndex uint16
}

func (c *ConstantInterfaceMethodRef) ToBytes() []byte {
var bs = []byte{CONSTANT_INTERFACE_METHOD_REF}
bs = append(bs, commons.NumberToBytes(c.ClassIndex)...)
bs = append(bs, commons.NumberToBytes(c.NameAndTypeIndex)...)
return bs
}

func readConstantInterfaceMethodRef(stream *commons.Stream) (*ConstantInterfaceMethodRef, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant interface method ref failed, no enough data in the stream")
}

var c = &ConstantInterfaceMethodRef{}
c.ClassIndex = binary.BigEndian.Uint16(bs[:2])
c.NameAndTypeIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}
35 changes: 35 additions & 0 deletions class/constant_invoke_dynamic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantInvokeDynamic struct {
BootstrapMethodIndex uint16 // a reference to the BootstrapMethod in ClassFile.Attributes
NameAndTypeIndex uint16
}

func (c *ConstantInvokeDynamic) ToBytes() []byte {
var bs = []byte{CONSTANT_INVOKE_DYNAMIC_INFO}
bs = append(bs, commons.NumberToBytes(c.BootstrapMethodIndex)...)
bs = append(bs, commons.NumberToBytes(c.NameAndTypeIndex)...)
return bs
}

func readConstantInvokeDynamic(stream *commons.Stream) (*ConstantInvokeDynamic, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant invoke dynamic failed, no enough data in the stream")
}

var c = &ConstantInvokeDynamic{}
c.BootstrapMethodIndex = binary.BigEndian.Uint16(bs[:2])
c.NameAndTypeIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}


33 changes: 33 additions & 0 deletions class/constant_methodref.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantMethodRef struct {
ClassIndex uint16
NameAndTypeIndex uint16
}

func (c *ConstantMethodRef) ToBytes() []byte {
var bs = []byte{CONSTANT_METHOD_REF_INFO}
bs = append(bs, commons.NumberToBytes(c.ClassIndex)...)
bs = append(bs, commons.NumberToBytes(c.NameAndTypeIndex)...)
return bs
}

func readConstantMethodRef(stream *commons.Stream) (*ConstantMethodRef, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant method ref failed, no enough data in the stream")
}

var c = &ConstantMethodRef{}
c.ClassIndex = binary.BigEndian.Uint16(bs[:2])
c.NameAndTypeIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}
29 changes: 29 additions & 0 deletions class/constant_module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantModule struct {
NameIndex uint16
}

func (c *ConstantModule) ToBytes() []byte {
var bs = []byte{CONSTANT_MODULE_INFO}
bs = append(bs, commons.NumberToBytes(c.NameIndex)...)
return bs
}

func readConstantModule(stream *commons.Stream) (*ConstantModule, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(2)
if err != nil {
return nil, fmt.Errorf("read constant module failed, no enough data in the stream")
}

return &ConstantModule{
NameIndex: binary.BigEndian.Uint16(bs),
}, nil
}
33 changes: 33 additions & 0 deletions class/constant_nametype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantNameAndType struct {
NameIndex uint16
DescriptorIndex uint16
}

func (c *ConstantNameAndType) ToBytes() []byte {
var bs = []byte{CONSTANT_NAME_AND_TYPE_INFO}
bs = append(bs, commons.NumberToBytes(c.NameIndex)...)
bs = append(bs, commons.NumberToBytes(c.DescriptorIndex)...)
return bs
}

func readConstantNameAndType(stream *commons.Stream) (*ConstantNameAndType, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(4)
if err != nil {
return nil, fmt.Errorf("read constant name and type failed, no enough data in the stream")
}

var c = &ConstantNameAndType{}
c.NameIndex = binary.BigEndian.Uint16(bs[:2])
c.DescriptorIndex = binary.BigEndian.Uint16(bs[2:])

return c, nil
}
30 changes: 30 additions & 0 deletions class/constant_package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package class

import (
"encoding/binary"
"fmt"
"github.com/phith0n/zkar/commons"
)

type ConstantPackage struct {
NameIndex uint16
}

func (c *ConstantPackage) ToBytes() []byte {
var bs = []byte{CONSTANT_PACKAGE_INFO}
bs = append(bs, commons.NumberToBytes(c.NameIndex)...)
return bs
}

func readConstantPackage(stream *commons.Stream) (*ConstantPackage, error) {
_, _ = stream.ReadN(1)
bs, err := stream.ReadN(2)
if err != nil {
return nil, fmt.Errorf("read constant package failed, no enough data in the stream")
}

return &ConstantPackage{
NameIndex: binary.BigEndian.Uint16(bs),
}, nil
}

8 changes: 3 additions & 5 deletions class/constant_string.go → class/constant_str.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (
)

type ConstantString struct {
StringOffset uint16
Reference *ConstantUTF8 // Reference must be a ConstantUTF8 object
StringIndex uint16
}

func (c *ConstantString) ToBytes() []byte {
var bs = []byte{CONSTANT_STRING_INGFO}
bs = append(bs, commons.NumberToBytes(c.StringOffset)...)
bs = append(bs, commons.NumberToBytes(c.StringIndex)...)
return bs
}

Expand All @@ -26,7 +25,6 @@ func readConstantString(stream *commons.Stream) (*ConstantString, error) {

var i = binary.BigEndian.Uint16(bs)
return &ConstantString{
StringOffset: i,
// lack of Reference because ConstantPool have not been constructed yet
StringIndex: i,
}, nil
}
5 changes: 5 additions & 0 deletions class/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ func ParseClass(data []byte) (*ClassFile, error) {
return nil, err
}

err = classFile.readConstantPool(stream)
if err != nil {
return nil, err
}

return classFile, nil
}

0 comments on commit 7c5987d

Please sign in to comment.