Xiao Shi

25 papers A* 4A 4B 1Journal 9Unranked 7
YearRankTypeTitle / Venue / Authors
2026 conf
ASPLOS (2)
Shaoqiang Lu, Yangbo Wei, Junhong Qian, Dongge Qin, Shiji Gao, Yizhi Ding, Qifan Wang, Chen Wu, Xiao Shi, Lei He
2026 J jnl
ACM Trans. Design Autom. Electr. Syst.
Ziqi Wang, Liangji Wu, Xiaoyong Li, Zhongxi Guo, Xiao Shi, Longxing Shi
2026 conf
ASP-DAC
Yangbo Wei, Shaoqiang Lu, Junhong Qian, Lei He, Dongge Qin, Xiao Shi, Chen Wu, Linfeng Zhang
2025 A conf
ICCAD
Shaoqiang Lu, Yangbo Wei, Junhong Qian, Chen Wu, Xiao Shi, Lei He
2025 J jnl
Integr.
Hao Yan, Yaning Jia, Chuangyuan Zeng, Xiaoping Liao, Xiao Shi
2024 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Dongjia Zhao, Lei Qi, Xiao Shi, Yinghuan Shi, Xin Geng
2024 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Ziqi Wang, Liang Pang, Xiao Shi, Longxing Shi
2024 conf
MLCAD
Ziqi Wang, Weihan Sun, Zhongxi Guo, Xiao Shi, Longxing Shi
2024 A* conf
DAC
Junzhuo Zhou, Li Huang, Haoxuan Xia, Yihui Cai, Leilei Jin, Xiao Shi, Wei W. Xing, Ting-Jung Lin, Lei He
2023 J jnl
CoRR
Dongjia Zhao, Lei Qi, Xiao Shi, Yinghuan Shi, Xin Geng
2023 A conf
DATE
Leilei Jin, Jiajie Xu, Wenjie Fu, Hao Yan, Xiao Shi, Ming Ling, Longxing Shi
2023 J jnl
Integr.
Liang Pang, Ziqi Wang, Rui Shi, Mengyun Yao, Xiao Shi, Hao Yan, Longxin Shi
2023 J jnl
Microelectron. J.
Liang Pang, Mengyun Yao, Xiao Shi, Hao Yan, Longxin Shi
2023 B conf
FPL
Tiandong Zhao, Siyuan Miao, Shaoqiang Lu, Jialin Cao, Jun Qiu, Xiao Shi, Kun Wang, Lei He
2022 J jnl
ACM Trans. Design Autom. Electr. Syst.
Xiao Shi, Hao Yan, Qiancun Huang, Chengzhen Xuan, Lei He, Longxing Shi
2021 conf
ASP-DAC
Hao Yan, Xiao Shi, Chengzhen Xuan, Peng Cao, Longxing Shi
2020 A conf
ICCAD
Xiao Shi, Hao Yan, Chuwen Li, Jianli Chen, Longxing Shi, Lei He
2020 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Xiao Shi, Hao Yan, Jinxin Wang, Jiajia Zhang, Longxing Shi, Lei He
2020 A* conf
DAC
Shan Shen, Liang Pang, Tianxiang Shao, Ming Ling, Xiao Shi, Longxing Shi
2019 conf
ISPD
Xiao Shi, Hao Yan, Jinxin Wang, Xiaofen Xu, Fengyuan Liu, Longxing Shi, Lei He
2019 conf
ASICON
Xiao Shi, Jinlong Yan, Hao Yan, Jiajia Zhang, Jinxin Wang, Longxing Shi, Lei He
2019 A conf
ICCAD
Xiao Shi, Hao Yan, Jiajia Zhang, Qiancun Huang, Longxing Shi, Lei He
2019 A* conf
DAC
Xiao Shi, Hao Yan, Qiancun Huang, Jiajia Zhang, Longxing Shi, Lei He
2018 A* conf
DAC
Xiao Shi, Fengyuan Liu, Jun Yang, Lei He
2012 conf
ICSPCS
Meng Zhang, Chenhao Wang, Xiao Shi, Hao Liu, Huacheng Zhu
redb/extractors/decompiler/apk/smali_normalization.py
← Index redb/extractors/decompiler/apk/smali_normalization.py python
"""Semantic normalization of Dalvik/smali instructions.

Analogous to Binary Ninja's LLIL normalization: strips register allocation
noise and instruction encoding variants while preserving semantic operations.

Three normalization levels (most aggressive to most detailed):
  - 'category':    semantic category only (MOV, ALU, CALL, ...)
  - 'opcode':      base opcode, width-invariant (add, sub, invoke, ...)
  - 'opcode_api':  opcode category + API method/field references for
                   invoke/field/alloc instructions (default for MinHash)

References:
  - Smali+ 12-category reduction (Canfora et al.)
  - MOSDroid opcode family grouping
  - DroidSIFT/DroidSim API-sensitive similarity
"""

import re
from typing import List

# ---------------------------------------------------------------------------
# Dalvik opcode -> semantic category mapping
# ---------------------------------------------------------------------------
# Prefix-matched against instruction opcodes. Order matters for overlapping
# prefixes (longer/more-specific prefixes should come first in iteration,
# but since we use startswith and break on first match, we order by
# specificity within the list).

OPCODE_CATEGORIES = {
    # Arithmetic/logic
    "add": "ALU", "sub": "ALU", "mul": "ALU", "div": "ALU",
    "rem": "ALU", "and": "ALU", "or": "ALU", "xor": "ALU",
    "shl": "ALU", "shr": "ALU", "ushr": "ALU", "neg": "ALU",
    "not": "ALU",
    # Data movement
    "move": "MOV", "const": "CONST",
    # Memory access (field/array)
    "iget": "LOAD", "sget": "LOAD", "aget": "LOAD",
    "iput": "STORE", "sput": "STORE", "aput": "STORE",
    # Invocations
    "invoke": "CALL",
    # Control flow
    "if": "BRANCH", "goto": "JMP",
    "switch": "SWITCH",
    "return": "RET",
    # Object/type
    "new": "ALLOC", "check": "TYPE", "instance": "TYPE",
    # Array
    "fill": "ARR", "array": "ARR",
    # Comparison
    "cmpl": "CMP", "cmpg": "CMP", "cmp": "CMP",
    # Exception / synchronization
    "throw": "EXC", "monitor": "SYNC",
    # Conversion (int-to-long, float-to-int, etc.)
    "int-to": "CONV", "long-to": "CONV", "float-to": "CONV",
    "double-to": "CONV",
}

# Pre-compiled regexes for operand extraction
_METHOD_REF_RE = re.compile(r"(L[\w/$]+;->[\w<>]+\(.*?\)[\w/$;\[]*)")
_FIELD_REF_RE = re.compile(r"(L[\w/$]+;->[\w]+:[\w/$;\[]+)")
_CLASS_REF_RE = re.compile(r"(L[\w/$]+;)")
_CONST_STRING_RE = re.compile(r'^const-string(?:/jumbo)?\s')


def categorize_opcode(opcode: str) -> str:
    """Map a Dalvik opcode to its semantic category.

    Prefix-matched: 'add-int/2addr' matches 'add' -> 'ALU'.
    Returns 'OTHER' for unrecognized opcodes.
    """
    for prefix, cat in OPCODE_CATEGORIES.items():
        if opcode.startswith(prefix):
            return cat
    return "OTHER"


# Mapping from semantic categories to the ACFG feature vector indices
# used by Binary Ninja's build_block_features (cfg_features.py).
# This enables cross-platform ACFG feature comparison.
CATEGORY_TO_ACFG_INDEX = {
    "ALU": 0,       # CAT_ARITHMETIC
    "CONV": 0,      # arithmetic-adjacent
    "CMP": 4,       # CAT_COMPARISON
    "MOV": 2,       # CAT_TRANSFER
    "CONST": 2,     # transfer-adjacent (loading constants)
    "LOAD": 5,      # CAT_MEMORY
    "STORE": 5,     # CAT_MEMORY
    "CALL": 3,      # CAT_CALL
    "BRANCH": 1,    # CAT_LOGIC (conditional logic)
    "JMP": 1,       # CAT_LOGIC
    "SWITCH": 1,    # CAT_LOGIC
    "RET": 2,       # CAT_TRANSFER
    "ALLOC": 5,     # CAT_MEMORY (heap allocation)
    "TYPE": 6,      # CAT_OTHER
    "ARR": 5,       # CAT_MEMORY
    "EXC": 6,       # CAT_OTHER
    "SYNC": 6,      # CAT_OTHER
    "OTHER": 6,     # CAT_OTHER
}


def normalize_instruction(line: str, level: str = "opcode_api") -> str:
    """Normalize a single smali instruction line.

    Args:
        line: A single smali instruction (whitespace-stripped).
        level: Normalization level:
            'category'   - most aggressive: just semantic category
            'opcode'     - base opcode only, width/addressing-mode invariant
            'opcode_api' - category + API references for invoke/field/alloc
                          (default, best for MinHash similarity)

    Returns:
        Normalized instruction string, or empty string for non-instructions.
    """
    stripped = line.strip()
    if not stripped:
        return ""

    parts = stripped.split(None, 1)
    opcode = parts[0]
    operands = parts[1] if len(parts) > 1 else ""

    if level == "category":
        return categorize_opcode(opcode)

    if level == "opcode":
        # Strip type/width suffixes for invariance:
        # add-int, add-long, add-float -> 'add'
        # add-int/2addr -> 'add'
        base = re.split(r"[-/]", opcode)[0]
        return base

    if level == "opcode_api":
        # const-string: preserve string content (encrypted strings are a
        # key malware indicator)
        if _CONST_STRING_RE.match(stripped):
            # Extract the string literal
            str_match = re.search(r'"(.*)"', operands)
            if str_match:
                return f"CONST_STR \"{str_match.group(1)}\""
            return "CONST_STR"

        # invoke-*: preserve method reference
        if opcode.startswith("invoke"):
            ref = _METHOD_REF_RE.search(operands)
            if ref:
                return f"CALL {ref.group(1)}"
            return "CALL"

        # Field access: preserve field reference
        if opcode.startswith(("iget", "iput", "sget", "sput")):
            ref = _FIELD_REF_RE.search(operands)
            if ref:
                cat = "LOAD" if "get" in opcode else "STORE"
                return f"{cat} {ref.group(1)}"
            # Fallback: try space-separated format from androguard
            # e.g. "iget v0, p0, Lcom/Foo;->field Ljava/lang/String;"
            space_ref = re.search(
                r"(L[\w/$]+;->[\w]+)\s+([\w/$;\[]+)", operands
            )
            if space_ref:
                cat = "LOAD" if "get" in opcode else "STORE"
                return f"{cat} {space_ref.group(1)}:{space_ref.group(2)}"
            cat = "LOAD" if "get" in opcode else "STORE"
            return cat

        # new-instance: preserve allocated type
        if opcode.startswith("new-instance") or opcode == "new-array":
            ref = _CLASS_REF_RE.search(operands)
            if ref:
                return f"ALLOC {ref.group(1)}"
            return "ALLOC"

        # Everything else: just the category
        return categorize_opcode(opcode)

    # Unknown level: return raw opcode
    return opcode


def normalize_method_body(
    body: str, level: str = "opcode_api"
) -> List[str]:
    """Normalize all instructions in a smali method body.

    Filters out directives (.), labels (:), comments (#), and blank lines.
    Returns a list of normalized instruction strings.

    Args:
        body: Raw smali method body text.
        level: Normalization level (see normalize_instruction).

    Returns:
        List of normalized instruction strings (no empty strings).
    """
    normalized = []
    for line in body.split("\n"):
        stripped = line.strip()
        # Skip non-instructions
        if not stripped:
            continue
        if stripped.startswith((".",":", "#")):
            continue
        result = normalize_instruction(stripped, level)
        if result:
            normalized.append(result)
    return normalized