Skip to content

Commit 7e4c74d

Browse files
authored
Merge pull request #7 from wreulicke/feature/add-attribute-methods
Add opcode parser
2 parents f455f84 + 550b7af commit 7e4c74d

File tree

9 files changed

+783
-45
lines changed

9 files changed

+783
-45
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
build-java:
55
mkdir -p testdata/classes
66
javac -d testdata/classes $$(find testdata -name *.java)
7+
mkdir -p testdata/dist
78
jar -c -f testdata/dist/test.jar --main-class main.Main -C testdata/classes .
89
cd testdata/dist && jar xf test.jar
910

attribute.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package parser
22

3+
import "github.com/wreulicke/classfile-parser/code"
4+
35
var (
46
deprecated = &AttributeDeprecated{}
57
synthetic = &AttributeSynthetic{}
@@ -83,6 +85,11 @@ func (a *AttributeCode) RuntimeInvisibleTypeAnnotations() *AttributeRuntimeInvis
8385
return nil
8486
}
8587

88+
func (a *AttributeCode) ParseCode() ([]*code.Instruction, error) {
89+
p := code.NewCodeParser(a.Codes)
90+
return p.Parse()
91+
}
92+
8693
type Exception struct {
8794
StartPc uint16
8895
EndPc uint16
@@ -403,3 +410,12 @@ type RecordComponentInfo struct {
403410
DescriptorIndex uint16
404411
Attributes []Attribute
405412
}
413+
414+
type AttributePermittedSubclasses struct {
415+
NumberOfClasses uint16
416+
Classes []uint16
417+
}
418+
419+
func (a *AttributePermittedSubclasses) Name() string {
420+
return "PermittedSubclasses"
421+
}

attribute_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package parser
22

3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
39
func findAttribute(attrs []Attribute, name string) Attribute {
410
for _, e := range attrs {
511
if e.Name() == name {
@@ -8,3 +14,16 @@ func findAttribute(attrs []Attribute, name string) Attribute {
814
}
915
return nil
1016
}
17+
18+
func TestParseCode(t *testing.T) {
19+
cf, err := parseFile("./testdata/classes/main/Test.class")
20+
assert.NoError(t, err)
21+
22+
for _, e := range cf.Methods {
23+
attr := findAttribute(e.Attributes, "Code")
24+
if code, ok := attr.(*AttributeCode); ok {
25+
_, err := code.ParseCode()
26+
assert.NoError(t, err)
27+
}
28+
}
29+
}

binary_parser.go renamed to binary/binary_parser.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package parser
1+
package binary
22

33
import (
44
"bufio"
@@ -8,11 +8,11 @@ import (
88
"math"
99
)
1010

11-
type binaryParser struct {
11+
type parser struct {
1212
input *bufio.Reader
1313
}
1414

15-
type BinaryParser interface {
15+
type Parser interface {
1616
ReadBytes(size int) ([]byte, error)
1717
ReadUint8() (uint8, error)
1818
ReadUint16() (uint16, error)
@@ -22,15 +22,15 @@ type BinaryParser interface {
2222
ReadDouble() (float64, error)
2323
}
2424

25-
var _ BinaryParser = (*binaryParser)(nil)
25+
var _ Parser = (*parser)(nil)
2626

27-
func NewBinaryParser(reader io.Reader) BinaryParser {
28-
return &binaryParser{
27+
func NewParser(reader io.Reader) Parser {
28+
return &parser{
2929
input: bufio.NewReader(reader),
3030
}
3131
}
3232

33-
func (p *binaryParser) ReadBytes(size int) ([]byte, error) {
33+
func (p *parser) ReadBytes(size int) ([]byte, error) {
3434
bs := make([]byte, size)
3535
n, err := io.ReadFull(p.input, bs)
3636
if n != size {
@@ -42,43 +42,43 @@ func (p *binaryParser) ReadBytes(size int) ([]byte, error) {
4242
return bs, nil
4343
}
4444

45-
func (p *binaryParser) ReadUint8() (uint8, error) {
45+
func (p *parser) ReadUint8() (uint8, error) {
4646
return p.input.ReadByte()
4747
}
4848

49-
func (p *binaryParser) ReadUint16() (uint16, error) {
49+
func (p *parser) ReadUint16() (uint16, error) {
5050
bs, err := p.ReadBytes(2)
5151
if err != nil {
5252
return 0, err
5353
}
5454
return binary.BigEndian.Uint16(bs), nil
5555
}
5656

57-
func (p *binaryParser) ReadUint32() (uint32, error) {
57+
func (p *parser) ReadUint32() (uint32, error) {
5858
bs, err := p.ReadBytes(4)
5959
if err != nil {
6060
return 0, err
6161
}
6262
return binary.BigEndian.Uint32(bs), nil
6363
}
6464

65-
func (p *binaryParser) ReadUint64() (uint64, error) {
65+
func (p *parser) ReadUint64() (uint64, error) {
6666
bs, err := p.ReadBytes(8)
6767
if err != nil {
6868
return 0, err
6969
}
7070
return binary.BigEndian.Uint64(bs), nil
7171
}
7272

73-
func (p *binaryParser) ReadFloat() (float32, error) {
73+
func (p *parser) ReadFloat() (float32, error) {
7474
bytes, err := p.ReadUint32()
7575
if err == nil {
7676
return math.Float32frombits(bytes), nil
7777
}
7878
return 0, err
7979
}
8080

81-
func (p *binaryParser) ReadDouble() (float64, error) {
81+
func (p *parser) ReadDouble() (float64, error) {
8282
bytes, err := p.ReadUint64()
8383
if err == nil {
8484
return math.Float64frombits(bytes), nil

code/opcodes.go

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
package code
2+
3+
type opcode uint8
4+
5+
// Instruction set is here.
6+
// https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-6.html#jvms-6.5
7+
const (
8+
_ opcode = iota
9+
Aaload = 50 // (0x32)
10+
Aastore = 83 // (0x53)
11+
Aconst_null = 1 // (0x1)
12+
Aload = 25 // (0x19)
13+
Aload_0 = 42 // (0x2a)
14+
Aload_1 = 43 // (0x2b)
15+
Aload_2 = 44 // (0x2c)
16+
Aload_3 = 45 // (0x2d)
17+
Anewarray = 189 // (0xbd)
18+
Areturn = 176 // (0xb0)
19+
Arraylength = 190 // (0xbe)
20+
Astore = 58 // (0x3a)
21+
Astore_0 = 75 // (0x4b)
22+
Astore_1 = 76 // (0x4c)
23+
Astore_2 = 77 // (0x4d)
24+
Astore_3 = 78 // (0x4e)
25+
Athrow = 191 // (0xbf)
26+
Baload = 51 // (0x33)
27+
Bastore = 84 // (0x54)
28+
Bipush = 16 // (0x10)
29+
Caload = 52 // (0x34)
30+
Castore = 85 // (0x55)
31+
Checkcast = 192 // (0xc0)
32+
D2f = 144 // (0x90)
33+
D2i = 142 // (0x8e)
34+
D2l = 143 // (0x8f)
35+
Dadd = 99 // (0x63)
36+
Daload = 49 // (0x31)
37+
Dastore = 82 // (0x52)
38+
Dcmpg = 152 // (0x98)
39+
Dcmpl = 151 // (0x97)
40+
Dconst_0 = 14 // (0xe)
41+
Dconst_1 = 15 // (0xf)
42+
Ddiv = 111 // (0x6f)
43+
Dload = 24 // (0x18)
44+
Dload_0 = 38 // (0x26)
45+
Dload_1 = 39 // (0x27)
46+
Dload_2 = 40 // (0x28)
47+
Dload_3 = 41 // (0x29)
48+
Dmul = 107 // (0x6b)
49+
Dneg = 119 // (0x77)
50+
Drem = 115 // (0x73)
51+
Dreturn = 175 // (0xaf)
52+
Dstore = 57 // (0x39)
53+
Dstore_0 = 71 // (0x47)
54+
Dstore_1 = 72 // (0x48)
55+
Dstore_2 = 73 // (0x49)
56+
Dstore_3 = 74 // (0x4a)
57+
Dsub = 103 // (0x67)
58+
Dup = 89 // (0x59)
59+
Dup_x1 = 90 // (0x5a)
60+
Dup_x2 = 91 // (0x5b)
61+
Dup2 = 92 // (0x5c)
62+
Dup2_x1 = 93 // (0x5d)
63+
Dup2_x2 = 94 // (0x5e)
64+
F2d = 141 // (0x8d)
65+
F2i = 139 // (0x8b)
66+
F2l = 140 // (0x8c)
67+
Fadd = 98 // (0x62)
68+
Faload = 48 // (0x30)
69+
Fastore = 81 // (0x51)
70+
Fcmpg = 150 // (0x96)
71+
Fcmpl = 149 // (0x95)
72+
Fconst_0 = 11 // (0xb)
73+
Fconst_1 = 12 // (0xc)
74+
Fconst_2 = 13 // (0xd)
75+
Fdiv = 110 // (0x6e)
76+
Fload = 23 // (0x17)
77+
Fload_0 = 34 // (0x22)
78+
Fload_1 = 35 // (0x23)
79+
Fload_2 = 36 // (0x24)
80+
Fload_3 = 37 // (0x25)
81+
Fmul = 106 // (0x6a)
82+
Fneg = 118 // (0x76)
83+
Frem = 114 // (0x72)
84+
Freturn = 174 // (0xae)
85+
Fstore = 56 // (0x38)
86+
Fstore_0 = 67 // (0x43)
87+
Fstore_1 = 68 // (0x44)
88+
Fstore_2 = 69 // (0x45)
89+
Fstore_3 = 70 // (0x46)
90+
Fsub = 102 // (0x66)
91+
Getfield = 180 // (0xb4)
92+
Getstatic = 178 // (0xb2)
93+
Goto = 167 // (0xa7)
94+
Goto_w = 200 // (0xc8)
95+
I2b = 145 // (0x91)
96+
I2c = 146 // (0x92)
97+
I2d = 135 // (0x87)
98+
I2f = 134 // (0x86)
99+
I2l = 133 // (0x85)
100+
I2s = 147 // (0x93)
101+
Iadd = 96 // (0x60)
102+
Iaload = 46 // (0x2e)
103+
Iand = 126 // (0x7e)
104+
Iastore = 79 // (0x4f)
105+
Iconst_m1 = 2 // (0x2)
106+
Iconst_0 = 3 // (0x3)
107+
Iconst_1 = 4 // (0x4)
108+
Iconst_2 = 5 // (0x5)
109+
Iconst_3 = 6 // (0x6)
110+
Iconst_4 = 7 // (0x7)
111+
Iconst_5 = 8 // (0x8)
112+
Idiv = 108 // (0x6c)
113+
If_acmpeq = 165 // (0xa5)
114+
If_acmpne = 166 // (0xa6)
115+
If_icmpeq = 159 // (0x9f)
116+
If_icmpne = 160 // (0xa0)
117+
If_icmplt = 161 // (0xa1)
118+
If_icmpge = 162 // (0xa2)
119+
If_icmpgt = 163 // (0xa3)
120+
If_icmple = 164 // (0xa4)
121+
Ifeq = 153 // (0x99)
122+
Ifne = 154 // (0x9a)
123+
Iflt = 155 // (0x9b)
124+
Ifge = 156 // (0x9c)
125+
Ifgt = 157 // (0x9d)
126+
Ifle = 158 // (0x9e)
127+
Ifnonnull = 199 // (0xc7)
128+
Ifnull = 198 // (0xc6)
129+
Iinc = 132 // (0x84)
130+
Iload = 21 // (0x15)
131+
Iload_0 = 26 // (0x1a)
132+
Iload_1 = 27 // (0x1b)
133+
Iload_2 = 28 // (0x1c)
134+
Iload_3 = 29 // (0x1d)
135+
Imul = 104 // (0x68)
136+
Ineg = 116 // (0x74)
137+
Instanceof = 193 // (0xc1)
138+
Invokedynamic = 186 // (0xba)
139+
Invokeinterface = 185 // (0xb9)
140+
Invokespecial = 183 // (0xb7)
141+
Invokestatic = 184 // (0xb8)
142+
Invokevirtual = 182 // (0xb6)
143+
Ior = 128 // (0x80)
144+
Irem = 112 // (0x70)
145+
Ireturn = 172 // (0xac)
146+
Ishl = 120 // (0x78)
147+
Ishr = 122 // (0x7a)
148+
Istore = 54 // (0x36)
149+
Istore_0 = 59 // (0x3b)
150+
Istore_1 = 60 // (0x3c)
151+
Istore_2 = 61 // (0x3d)
152+
Istore_3 = 62 // (0x3e)
153+
Isub = 100 // (0x64)
154+
Iushr = 124 // (0x7c)
155+
Ixor = 130 // (0x82)
156+
Jsr = 168 // (0xa8)
157+
Jsr_w = 201 // (0xc9)
158+
L2d = 138 // (0x8a)
159+
L2f = 137 // (0x89)
160+
L2i = 136 // (0x88)
161+
Ladd = 97 // (0x61)
162+
Laload = 47 // (0x2f)
163+
Land = 127 // (0x7f)
164+
Lastore = 80 // (0x50)
165+
Lcmp = 148 // (0x94)
166+
Lconst_0 = 9 // (0x9)
167+
Lconst_1 = 10 // (0xa)
168+
Ldc = 18 // (0x12)
169+
Ldc_w = 19 // (0x13)
170+
Ldc2_w = 20 // (0x14)
171+
Ldiv = 109 // (0x6d)
172+
Lload = 22 // (0x16)
173+
Lload_0 = 30 // (0x1e)
174+
Lload_1 = 31 // (0x1f)
175+
Lload_2 = 32 // (0x20)
176+
Lload_3 = 33 // (0x21)
177+
Lmul = 105 // (0x69)
178+
Lneg = 117 // (0x75)
179+
Lookupswitch = 171 // (0xab)
180+
Lor = 129 // (0x81)
181+
Lrem = 113 // (0x71)
182+
Lreturn = 173 // (0xad)
183+
Lshl = 121 // (0x79)
184+
Lshr = 123 // (0x7b)
185+
Lstore = 55 // (0x37)
186+
Lstore_0 = 63 // (0x3f)
187+
Lstore_1 = 64 // (0x40)
188+
Lstore_2 = 65 // (0x41)
189+
Lstore_3 = 66 // (0x42)
190+
Lsub = 101 // (0x65)
191+
Lushr = 125 // (0x7d)
192+
Lxor = 131 // (0x83)
193+
Monitorenter = 194 // (0xc2)
194+
Monitorexit = 195 // (0xc3)
195+
Multianewarray = 197 // (0xc5)
196+
New = 187 // (0xbb)
197+
Newarray = 188 // (0xbc)
198+
Nop = 0 // (0x0)
199+
Pop = 87 // (0x57)
200+
Pop2 = 88 // (0x58)
201+
Putfield = 181 // (0xb5)
202+
Putstatic = 179 // (0xb3)
203+
Ret = 169 // (0xa9)
204+
Return = 177 // (0xb1)
205+
Saload = 53 // (0x35)
206+
Sastore = 86 // (0x56)
207+
Sipush = 17 // (0x11)
208+
Swap = 95 // (0x5f)
209+
Tableswitch = 170 // (0xaa)
210+
Wide = 196 // (0xc4)
211+
)

0 commit comments

Comments
 (0)