Skip to content

Commit

Permalink
abc-decompiler: export getter for accessflags
Browse files Browse the repository at this point in the history
  • Loading branch information
magiclf committed Aug 26, 2024
1 parent c3269ac commit cb87330
Showing 1 changed file with 66 additions and 58 deletions.
124 changes: 66 additions & 58 deletions modules/abcde/src/commonMain/kotlin/me/yricky/oh/abcd/cfm/ClassItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,35 @@ import kotlin.jvm.JvmInline

sealed class ClassItem(
final override val abc: AbcBuf,
final override val offset:Int
): AbcBufOffset {
final override val offset: Int
) : AbcBufOffset {
protected val nameItem get() = abc.stringItem(offset)
val name by lazy {
nameItem.value.removePrefix("L").removeSuffix(";")
}
}

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

private val superClassOff = abc.buf.getInt(nameItem.nextOffset)

@Uncleared("reserved")
val superClass get() = if(superClassOff != 0) abc.classes[superClassOff] else null
val superClass get() = if (superClassOff != 0) abc.classes[superClassOff] else null

val accessFlags:AccessFlags
val numFields:Int
val _accessFlags: DataAndNextOff<Int>
private val __accessFlags: AccessFlags
val accessFlags get() = __accessFlags
val accessFlag get() = _accessFlags.value
val numFields: Int

private val _numMethods:DataAndNextOff<Int>
private val _numMethods: DataAndNextOff<Int>
val numMethods get() = _numMethods.value

init {
val _accessFlags = abc.buf.readULeb128(nameItem.nextOffset + 4)
accessFlags = AccessFlags(_accessFlags.value)
_accessFlags = abc.buf.readULeb128(nameItem.nextOffset + 4)
__accessFlags = AccessFlags(_accessFlags.value)
val _numFields = abc.buf.readULeb128(_accessFlags.nextOffset)
numFields = _numFields.value
_numMethods = abc.buf.readULeb128(_numFields.nextOffset)
Expand All @@ -44,100 +48,104 @@ class AbcClass(abc: AbcBuf, offset: Int) : ClassItem(abc, offset){
private val _data by lazy {
var tagOff = _numMethods.nextOffset
val tagList = mutableListOf<ClassTag>()
while (tagList.lastOrNull() != ClassTag.Nothing){
val (tag,nextOff) = ClassTag.readTag(abc, tagOff)
while (tagList.lastOrNull() != ClassTag.Nothing) {
val (tag, nextOff) = ClassTag.readTag(abc, tagOff)
tagList.add(tag)
tagOff = nextOff
}
if(tagList.lastOrNull() == ClassTag.Nothing){
if (tagList.lastOrNull() == ClassTag.Nothing) {
tagList.removeLast()
}
DataAndNextOff(tagList,tagOff)
DataAndNextOff(tagList, tagOff)
}
val data:List<ClassTag> get() = _data.value
val data: List<ClassTag> get() = _data.value

private val _fields by lazy {
val list = ArrayList<AbcField>(numFields)
var off = _data.nextOffset
repeat(numFields){
list.add(AbcField(abc,off))
repeat(numFields) {
list.add(AbcField(abc, off))
off = list.last().nextOff
}
DataAndNextOff(list,off)
DataAndNextOff(list, off)
}
val fields:List<AbcField> get() = _fields.value
val moduleInfo:ModuleLiteralArray? by lazy {
val fields: List<AbcField> get() = _fields.value
val moduleInfo: ModuleLiteralArray? by lazy {
fields.firstOrNull { it.isModuleRecordIdx() }?.getIntValue()
?.takeIf { abc.isValidOffset(it) }
?.let { ModuleLiteralArray(abc,it) }
?.let { ModuleLiteralArray(abc, it) }
}

private val _methods by lazy {
val list = ArrayList<AbcMethod>(numMethods)
var off = _fields.nextOffset
repeat(numMethods){
repeat(numMethods) {
list.add(abc.method(off) as AbcMethod)
off = list.last().nextOff
}
DataAndNextOff(list,off)
DataAndNextOff(list, off)
}
val methods:List<AbcMethod> get() = _methods.value
val methods: List<AbcMethod> get() = _methods.value

@JvmInline
value class AccessFlags(private val value:Int){
val isPublic:Boolean get() = (value and 0x0001) != 0
val isFinal:Boolean get() = (value and 0x0010) != 0
val isInterface:Boolean get() = (value and 0x0200) != 0
val isAbstract:Boolean get() = (value and 0x0400) != 0
val isSynthetic:Boolean get() = (value and 0x1000) != 0
val isAnnotation:Boolean get() = (value and 0x2000) != 0
val isEnum:Boolean get() = (value and 0x4000) != 0
value class AccessFlags(private val value: Int) {
val isPublic: Boolean get() = (value and 0x0001) != 0
val isFinal: Boolean get() = (value and 0x0010) != 0
val isInterface: Boolean get() = (value and 0x0200) != 0
val isAbstract: Boolean get() = (value and 0x0400) != 0
val isSynthetic: Boolean get() = (value and 0x1000) != 0
val isAnnotation: Boolean get() = (value and 0x2000) != 0
val isEnum: Boolean get() = (value and 0x4000) != 0
}

}

sealed class ClassTag{
sealed class AnnoTag(abc: AbcBuf, annoOffset:Int):ClassTag(){
val anno:AbcAnnotation = AbcAnnotation(abc,annoOffset)
sealed class ClassTag {
sealed class AnnoTag(abc: AbcBuf, annoOffset: Int) : ClassTag() {
val anno: AbcAnnotation = AbcAnnotation(abc, annoOffset)

override fun toString(): String {
return "Annotation(${anno.clazz.name}[${anno.elements}])"
}
}
data object Nothing: ClassTag()

data object Nothing : ClassTag()
data class Interfaces(
val count:Int,
val indexInRegionList:List<Short>
): ClassTag()
data class SourceLang(val value:Byte): ClassTag(){
val count: Int,
val indexInRegionList: List<Short>
) : ClassTag()

data class SourceLang(val value: Byte) : ClassTag() {
override fun toString(): String {
return if(value == 0x0.toByte()) "SourceLang(ArkTS/TS/JS)" else "SourceLang($value)"
return if (value == 0x0.toByte()) "SourceLang(ArkTS/TS/JS)" else "SourceLang($value)"
}
}
class RuntimeAnno(abc: AbcBuf, annoOffset:Int): AnnoTag(abc,annoOffset)
class Anno(abc: AbcBuf, annoOffset:Int): AnnoTag(abc, annoOffset)
class RuntimeTypeAnno(abc: AbcBuf, annoOffset:Int): AnnoTag(abc, annoOffset)
class TypeAnno(abc: AbcBuf, annoOffset:Int): AnnoTag(abc, annoOffset)
data class SourceFile(val stringOffset:Int): ClassTag()

companion object{
fun readTag(abc: AbcBuf, offset: Int):DataAndNextOff<ClassTag>{

class RuntimeAnno(abc: AbcBuf, annoOffset: Int) : AnnoTag(abc, annoOffset)
class Anno(abc: AbcBuf, annoOffset: Int) : AnnoTag(abc, annoOffset)
class RuntimeTypeAnno(abc: AbcBuf, annoOffset: Int) : AnnoTag(abc, annoOffset)
class TypeAnno(abc: AbcBuf, annoOffset: Int) : AnnoTag(abc, annoOffset)
data class SourceFile(val stringOffset: Int) : ClassTag()

companion object {
fun readTag(abc: AbcBuf, offset: Int): DataAndNextOff<ClassTag> {
val buf = abc.buf
return when(val type = buf.get(offset).toInt()){
0 -> Pair(Nothing,offset + 1)
1 -> run{
val (count,off) = buf.readULeb128(offset + 1)
return when (val type = buf.get(offset).toInt()) {
0 -> Pair(Nothing, offset + 1)
1 -> run {
val (count, off) = buf.readULeb128(offset + 1)
val list = (0 until count).map {
buf.getShort(off + it * 2)
}
Pair(Interfaces(count,list), off + count * 2)
Pair(Interfaces(count, list), off + count * 2)
}

2 -> Pair(SourceLang(buf.get(offset + 1)), offset + 2)
3 -> Pair(RuntimeAnno(abc,abc.buf.getInt(offset + 1)),offset + 5)
4 -> Pair(Anno(abc,abc.buf.getInt(offset + 1)),offset + 5)
5 -> Pair(RuntimeTypeAnno(abc,abc.buf.getInt(offset + 1)),offset + 5)
6 -> Pair(TypeAnno(abc,abc.buf.getInt(offset + 1)),offset + 5)
7 -> Pair(SourceFile(buf.getInt(offset + 1)),offset + 5)
3 -> Pair(RuntimeAnno(abc, abc.buf.getInt(offset + 1)), offset + 5)
4 -> Pair(Anno(abc, abc.buf.getInt(offset + 1)), offset + 5)
5 -> Pair(RuntimeTypeAnno(abc, abc.buf.getInt(offset + 1)), offset + 5)
6 -> Pair(TypeAnno(abc, abc.buf.getInt(offset + 1)), offset + 5)
7 -> Pair(SourceFile(buf.getInt(offset + 1)), offset + 5)
else -> throw IllegalStateException("No this Tag:${type.toString(16)}")
}
}
Expand Down

0 comments on commit cb87330

Please sign in to comment.