Skip to content

Commit 53cd4b3

Browse files
committed
feat:annotation、优化字符串获取方式
1 parent 6efa161 commit 53cd4b3

File tree

11 files changed

+170
-30
lines changed

11 files changed

+170
-30
lines changed

kra/src/main/java/me/yricky/oh/abcd/AbcBuf.kt

+17
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ package me.yricky.oh.abcd
33
import me.yricky.oh.abcd.cfm.*
44
import me.yricky.oh.abcd.literal.LiteralArray
55
import me.yricky.oh.abcd.literal.ModuleLiteralArray
6+
import me.yricky.oh.utils.DataAndNextOff
7+
import me.yricky.oh.utils.MUtf8
8+
import me.yricky.oh.utils.readULeb128
69
import java.nio.ByteBuffer
710
import java.nio.ByteOrder
11+
import java.util.WeakHashMap
812

913
/**
1014
* ABC文件解析类入口
@@ -55,4 +59,17 @@ class AbcBuf(
5559
fun isValidOffset(offset:Int): Boolean{
5660
return offset >= 60 && offset < buf.limit()
5761
}
62+
63+
//TODO 线程安全
64+
private val _stringCache = HashMap<Int,DataAndNextOff<String>>()
65+
fun stringItem(offset:Int):DataAndNextOff<String>{
66+
return _stringCache[offset].also {
67+
// println("hitCache:${offset.toString(16)}")
68+
} ?: run {
69+
val (utf16Size,strDataOff) = buf.readULeb128(offset)
70+
MUtf8.getMUtf8String(buf,strDataOff,utf16Size.ushr(1)).also {
71+
_stringCache[offset] = it
72+
}
73+
}
74+
}
5875
}

kra/src/main/java/me/yricky/oh/abcd/cfm/AbcClass.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ sealed class AbcClass(
99
val abc: AbcBuf,
1010
val offset:Int
1111
) {
12-
protected val nameItem = abc.buf.stringItem(offset)
13-
val name get() = nameItem.first
12+
protected val nameItem = abc.stringItem(offset)
13+
val name get() = nameItem.value
1414
}
1515

1616
class ForeignClass(abc: AbcBuf, offset: Int) : AbcClass(abc, offset)
1717
class ClassItem(abc: AbcBuf, offset: Int) : AbcClass(abc, offset){
1818
val region by lazy { abc.regions.first { it.contains(offset) } }
1919

20-
val superClassOff by lazy { abc.buf.getInt(nameItem.second) }
20+
val superClassOff by lazy { abc.buf.getInt(nameItem.nextOffset) }
2121

2222
private val _accessFlags by lazy { abc.buf.readULeb128(nameItem.nextOffset + 4) }
2323
val accessFlags get() = AccessFlags(_accessFlags.value)

kra/src/main/java/me/yricky/oh/abcd/cfm/AbcField.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class AbcField(
1414
private val typeIdx:UShort = abc.buf.getShort(offset + 2).toUShort()
1515
val type:FieldType get() = region.classes[typeIdx.toInt()]
1616
private val nameOff:Int = abc.buf.getInt(offset + 4)
17-
val name :String by lazy { abc.buf.stringItem(nameOff).value }
17+
val name :String get() = abc.stringItem(nameOff).value
1818
private val _accessFlags by lazy {
1919
abc.buf.readULeb128(offset + 8)
2020
}

kra/src/main/java/me/yricky/oh/abcd/cfm/AbcMethod.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class AbcMethod(
1616
private val protoIdx:UShort = abc.buf.getShort(offset + 2).toUShort()
1717
val proto get() = region.protos[protoIdx.toInt()]
1818
private val nameOff:Int = abc.buf.getInt(offset + 4)
19-
val name :String by lazy { abc.buf.stringItem(nameOff).value }
19+
val name :String get() = abc.stringItem(nameOff).value
2020
private val _accessFlags by lazy {
2121
abc.buf.readULeb128(offset + 8)
2222
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package me.yricky.oh.abcd.cfm
2+
3+
import me.yricky.oh.abcd.AbcBuf
4+
import me.yricky.oh.utils.value
5+
6+
class Annotation(
7+
val abc: AbcBuf,
8+
val offset:Int
9+
) {
10+
private val region by lazy { abc.regions.first { it.contains(offset) } }
11+
private val classIdx:UShort by lazy {
12+
abc.buf.getShort(offset).toUShort()
13+
}
14+
val clazz get() = region.classes[classIdx.toInt()]
15+
val elementCount:UShort by lazy {
16+
abc.buf.getShort(offset+2).toUShort()
17+
}
18+
val elements by lazy {
19+
val list = ArrayList<AnnotationElement>(elementCount.toInt())
20+
repeat(elementCount.toInt()){
21+
list.add(
22+
AnnotationElement(
23+
nameOff = abc.buf.getInt(offset + 4 + 8 * it),
24+
value = abc.buf.getInt(offset + 8 + 8 * it),
25+
type = abc.buf.get(offset + 4 + 8 * elementCount.toInt() + it).let { Char(it.toUShort()) }
26+
)
27+
)
28+
}
29+
list
30+
}
31+
32+
class AnnotationElement(
33+
val nameOff:Int,
34+
val value:Int,
35+
val type:Char
36+
){
37+
fun name(abc: AbcBuf) = abc.stringItem(nameOff).value
38+
fun toString(abc: AbcBuf): String {
39+
return "(${type},${value.toString(16)})${name(abc)}"
40+
}
41+
}
42+
}

kra/src/main/java/me/yricky/oh/abcd/code/Code.kt

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ class Code(
2222
val instructions by lazy {
2323
abc.buf.slice(_triesSize.nextOffset,_codeSize.value).order(ByteOrder.LITTLE_ENDIAN)
2424
}
25+
val tryBlocks:List<TryBlock> by lazy {
26+
var off = _triesSize.nextOffset+_codeSize.value
27+
val list = ArrayList<TryBlock>(triesSize)
28+
repeat(triesSize){
29+
val tb = TryBlock(abc, off)
30+
list.add(tb)
31+
off = tb.nextOff
32+
}
33+
list
34+
}
2535

2636
val asm:List<String> by lazy {
2737
val li = mutableListOf<String>()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package me.yricky.oh.abcd.code
2+
3+
import me.yricky.oh.abcd.AbcBuf
4+
import me.yricky.oh.utils.DataAndNextOff
5+
import me.yricky.oh.utils.nextOffset
6+
import me.yricky.oh.utils.readULeb128
7+
import me.yricky.oh.utils.value
8+
9+
class TryBlock(
10+
val abc: AbcBuf,
11+
val offset:Int
12+
) {
13+
private val _startPc by lazy {
14+
abc.buf.readULeb128(offset)
15+
}
16+
val startPc = _startPc.value
17+
18+
private val _length by lazy {
19+
abc.buf.readULeb128(_startPc.nextOffset)
20+
}
21+
val length = _length.value
22+
23+
private val _numCatches by lazy {
24+
abc.buf.readULeb128(_length.nextOffset)
25+
}
26+
val numCatches = _numCatches.value
27+
28+
private val _catchBlocks by lazy {
29+
var off = _numCatches.nextOffset
30+
val list = ArrayList<CatchBlock>(_numCatches.value)
31+
repeat(_numCatches.value){
32+
val _tIdx = abc.buf.readULeb128(off)
33+
val _hPc = abc.buf.readULeb128(_tIdx.nextOffset)
34+
val _cs = abc.buf.readULeb128(_hPc.nextOffset)
35+
off = _cs.nextOffset
36+
list.add(CatchBlock(_tIdx.value,_hPc.value,_cs.value))
37+
}
38+
DataAndNextOff(list,off)
39+
}
40+
val catchBlocks get() = _catchBlocks.value
41+
42+
val nextOff get() = _catchBlocks.nextOffset
43+
44+
data class CatchBlock(
45+
val typeIdx:Int,
46+
val handlerPc:Int,
47+
val codeSize:Int
48+
)
49+
}

kra/src/main/java/me/yricky/oh/abcd/literal/ModuleLiteralArray.kt

+8-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import me.yricky.oh.abcd.AbcBuf
44
import me.yricky.oh.abcd.AbcHeader
55
import me.yricky.oh.utils.DataAndNextOff
66
import me.yricky.oh.utils.nextOffset
7-
import me.yricky.oh.utils.stringItem
87
import me.yricky.oh.utils.value
98

109
class ModuleLiteralArray(
@@ -15,7 +14,7 @@ class ModuleLiteralArray(
1514
val moduleRequestNum = abc.buf.getInt(offset + 4)
1615
private val _moduleRequests by lazy {
1716
(0 until moduleRequestNum).map {
18-
abc.buf.stringItem(abc.buf.getInt(offset + 8 + 4 * it)).value
17+
abc.stringItem(abc.buf.getInt(offset + 8 + 4 * it)).value
1918
}.let { DataAndNextOff(it,offset + 8 + (4 * moduleRequestNum)) }
2019
}
2120
val moduleRequests get() = _moduleRequests.value
@@ -68,13 +67,13 @@ class ModuleLiteralArray(
6867
){
6968
val localName :String? by lazy {
7069
if(localNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
71-
mla.abc.buf.stringItem(localNameOffset).value
70+
mla.abc.stringItem(localNameOffset).value
7271
} else null
7372
}
7473

7574
val importName :String? by lazy {
7675
if(importNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
77-
mla.abc.buf.stringItem(importNameOffset).value
76+
mla.abc.stringItem(importNameOffset).value
7877
} else null
7978
}
8079

@@ -106,7 +105,7 @@ class ModuleLiteralArray(
106105
){
107106
val localName :String? by lazy {
108107
if(localNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
109-
mla.abc.buf.stringItem(localNameOffset).value
108+
mla.abc.stringItem(localNameOffset).value
110109
} else null
111110
}
112111

@@ -136,13 +135,13 @@ class ModuleLiteralArray(
136135
){
137136
val localName :String? by lazy {
138137
if(localNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
139-
mla.abc.buf.stringItem(localNameOffset).value
138+
mla.abc.stringItem(localNameOffset).value
140139
} else null
141140
}
142141

143142
val exportName :String? by lazy {
144143
if(exportNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
145-
mla.abc.buf.stringItem(exportNameOffset).value
144+
mla.abc.stringItem(exportNameOffset).value
146145
} else null
147146
}
148147
override fun toString(): String {
@@ -167,13 +166,13 @@ class ModuleLiteralArray(
167166
){
168167
val exportName :String? by lazy {
169168
if(exportNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
170-
mla.abc.buf.stringItem(exportNameOffset).value
169+
mla.abc.stringItem(exportNameOffset).value
171170
} else null
172171
}
173172

174173
val importName :String? by lazy {
175174
if(importNameOffset in (AbcHeader.SIZE until mla.abc.buf.limit())){
176-
mla.abc.buf.stringItem(importNameOffset).value
175+
mla.abc.stringItem(importNameOffset).value
177176
} else null
178177
}
179178

kra/src/main/java/me/yricky/oh/utils/utils.kt

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package me.yricky.oh.utils
22

3+
import me.yricky.oh.abcd.AbcBuf
34
import java.nio.ByteBuffer
45
import kotlin.experimental.and
56

@@ -33,9 +34,4 @@ fun ByteBuffer.readSLeb128(index:Int): DataAndNextOff<Int> {
3334

3435
typealias DataAndNextOff<T> = Pair<T,Int>
3536
val <T> DataAndNextOff<T>.value:T get() = first
36-
val <T> DataAndNextOff<T>.nextOffset:Int get() = second
37-
38-
fun ByteBuffer.stringItem(offset:Int):DataAndNextOff<String>{
39-
val (utf16Size,strDataOff) = readULeb128(offset)
40-
return MUtf8.getMUtf8String(this,strDataOff,utf16Size.ushr(1))
41-
}
37+
val <T> DataAndNextOff<T>.nextOffset:Int get() = second

kra/src/test/java/me/yricky/oh/abcd/AbcHeaderTest.kt

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package me.yricky.oh.abcd
22

3+
import me.yricky.oh.abcd.cfm.Annotation
34
import me.yricky.oh.abcd.cfm.ClassItem
5+
import me.yricky.oh.abcd.cfm.MethodTag
46
import org.junit.jupiter.api.Test
57
import java.io.File
68
import java.nio.channels.FileChannel
@@ -49,6 +51,31 @@ class AbcHeaderTest{
4951
}
5052
}
5153

54+
@Test
55+
fun testMethod(){
56+
abc.classes.forEach { l ->
57+
val it = l.value
58+
if(it is ClassItem) {
59+
it.methods.filter { (it.codeItem?.triesSize ?: 0) > 0 }.forEach {
60+
println("(m) ${it.clazz.name} ${it.proto.shorty}\t${it.name}")
61+
it.data.forEach { t ->
62+
if(t is MethodTag.Annotation){
63+
val anno = Annotation(abc,t.annoOffset)
64+
println(" annoType(${anno.clazz.name}):${anno.elements.map { it.toString(abc) }}")
65+
}
66+
}
67+
println(" cSize${it.codeItem?.codeSize}, tbSize:${it.codeItem?.triesSize}")
68+
it.codeItem?.tryBlocks?.forEach {
69+
println(" spc:${it.startPc},len:${it.length},nch:${it.numCatches}")
70+
it.catchBlocks.forEach {
71+
println(" ch:${it}")
72+
}
73+
}
74+
}
75+
}
76+
}
77+
}
78+
5279
@Test
5380
fun testLA(){
5481
abc.literalArrays.forEachIndexed { i,it ->

src/main/kotlin/me/yricky/abcde/page/ClassView.kt

+10-10
Original file line numberDiff line numberDiff line change
@@ -146,51 +146,51 @@ fun ClassViewPage(
146146
LazyColumnWithScrollBar {
147147
clazz.moduleInfo?.let { m ->
148148
stickyHeader {
149-
Text("ModuleRequests(${m.moduleRequestNum})")
149+
Text("ModuleRequests(${m.moduleRequestNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
150150
}
151151
items(m.moduleRequests){
152152
Text("- $it")
153153
}
154154
stickyHeader {
155-
Text("RegularImports(${m.regularImportNum})")
155+
Text("RegularImports(${m.regularImportNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
156156
}
157157
items(m.regularImports){
158-
Column {
158+
Column(Modifier.padding(4.dp)) {
159159
Text("- localName:${it.localName}")
160160
Text("- importName:${it.importName}")
161161
Text("- moduleRequest:${it.moduleRequest}")
162162
}
163163
}
164164
stickyHeader {
165-
Text("NamespaceImports(${m.namespaceImportNum})")
165+
Text("NamespaceImports(${m.namespaceImportNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
166166
}
167167
items(m.namespaceImports){
168-
Column {
168+
Column(Modifier.padding(4.dp)) {
169169
Text("- localName:${it.localName}")
170170
Text("- moduleRequest:${it.moduleRequest}")
171171
}
172172
}
173173
stickyHeader {
174-
Text("LocalExports(${m.localExportNum})")
174+
Text("LocalExports(${m.localExportNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
175175
}
176176
items(m.localExports){
177-
Column {
177+
Column(Modifier.padding(4.dp)) {
178178
Text("- localName:${it.localName}")
179179
Text("- exportName:${it.exportName}")
180180
}
181181
}
182182
stickyHeader {
183-
Text("IndirectExports(${m.indirectExportNum})")
183+
Text("IndirectExports(${m.indirectExportNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
184184
}
185185
items(m.indirectExports){
186-
Column {
186+
Column(Modifier.padding(4.dp)) {
187187
Text("- importName:${it.importName}")
188188
Text("- exportName:${it.exportName}")
189189
Text("- moduleRequest:${it.moduleRequest}")
190190
}
191191
}
192192
stickyHeader {
193-
Text("StarExports(${m.starExportNum})")
193+
Text("StarExports(${m.starExportNum})",Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface))
194194
}
195195
items(m.starExports){
196196
Column {

0 commit comments

Comments
 (0)