[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-1549":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":14,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":15,"starSnapshotCount":15,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},1549,"tiny-dec","ZhangZhuoSJTU\u002Ftiny-dec","ZhangZhuoSJTU","A tiny educational decompiler that helps people understand how decompilation works.","https:\u002F\u002Ftiny-dec.zzhang.xyz",null,"Python",225,10,1,0,14,45.02,"MIT License",false,"main",true,[23,24,25],"decompilation","education","reverse-engineering","2026-06-12 04:00:10","\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Flogo.svg\" alt=\"tiny-dec\" width=\"640\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cstrong>Learn decompilation by building one from scratch.\u003C\u002Fstrong>\u003Cbr>\n  \u003Csub>19 stages. Every step inspectable. From raw RISC-V bytes to readable C.\u003Cbr>\n  RV32I: the simplest real ISA, so the focus stays on decompilation, not instruction encoding.\u003C\u002Fsub>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Ftutor-AI%20powered-D97757?logo=data:image\u002Fsvg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyTDMgN3YxMGw5IDUgOS01VjdMMTIgMnptMCAxOC4yTDUgMTUuOFY4LjJMMTIgMy44bDcgNC40djcuNkwxMiAyMC4yeiIvPjwvc3ZnPg==&logoColor=white\" alt=\"AI Tutor\">\n  \u003Ca href=\"https:\u002F\u002Ftiny-dec.zzhang.xyz\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002F%F0%9F%94%8D_live_demo-tiny--dec.zzhang.xyz-e04832\" alt=\"Live Demo\">\u003C\u002Fa>\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpython-%E2%89%A53.12-3776AB?logo=python&logoColor=white\" alt=\"Python\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Farch-RISC--V%20RV32I-764ABC\" alt=\"RISC-V RV32I\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpipeline-19%20stages-orange\" alt=\"19 stages\">\n\u003C\u002Fp>\n\n> [!TIP]\n> *This project is inspired by the amazing open-source efforts behind [angr](https:\u002F\u002Fgithub.com\u002Fangr\u002Fangr), [radare2](https:\u002F\u002Fgithub.com\u002Fradareorg\u002Fradare2), and [Ghidra](https:\u002F\u002Fgithub.com\u002FNationalSecurityAgency\u002Fghidra). Thanks for all the open-source work that makes projects like this possible.*\n\n> [!NOTE]\n> **This is a teaching tool, not a production decompiler.** The pipeline is deliberately factored into many small, isolated stages so that each concept can be studied independently. A real-world decompiler (Ghidra, IDA, angr, Binary Ninja) would fuse, reorder, or iterate these passes for performance and precision. We trade that efficiency for clarity: if you can follow each stage here, you will understand what the production tools are doing under the hood.\n\n## Learn with Our AI Tutor\n\nWe ship tiny-dec as a **Claude Code plugin**. An AI tutor assesses your level, walks you through each pipeline stage, quizzes you, and lets you experiment with real binaries, all inside your terminal.\n\n\u003Cp align=\"center\">\u003Cimg src=\"assets\u002Ftutor-demo.svg\" alt=\"AI tutor session in Claude Code\" width=\"720\">\u003C\u002Fp>\n\n## See the Pipeline in Action\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Ftiny-dec.zzhang.xyz\">\u003Cimg src=\"assets\u002Fdemo.gif\" alt=\"tiny-dec pipeline walkthrough\" width=\"720\">\u003C\u002Fa>\u003Cbr>\n  \u003Csub>A bird's-eye view of all 19 stages. Explore interactively at \u003Ca href=\"https:\u002F\u002Ftiny-dec.zzhang.xyz\">tiny-dec.zzhang.xyz\u003C\u002Fa>.\u003C\u002Fsub>\n\u003C\u002Fp>\n\n## Quick Start\n\n### Learn with the AI Tutor\n\nInstall Claude Code, then:\n\n```bash\n# 1. Add the marketplace\n\u002Fplugin marketplace add ZhangZhuoSJTU\u002Ftiny-dec\n\n# 2. Install the plugin\n\u002Fplugin install tiny-dec@tiny-dec\n\n# 3. Reload to activate\n\u002Freload-plugins\n```\n\nType **`\u002Ftiny-dec:teach-decompilation`** to start.\n\n### Install from Source\n\n```bash\n# System dependencies (Ubuntu\u002FDebian)\nsudo apt-get install -y clang lld llvm binutils build-essential python3 python3-pip\n\n# Python dependencies\npip install poetry\npoetry install\n\n# Build RV32I fixture binaries for tests\n.\u002Fscripts\u002Fbuild_fixtures.sh\n```\n\n#### Decompile\n\n```bash\n# Full decompilation to C (default)\ntiny-dec decompile .\u002Fbinary.elf\n\n# Target a specific function\ntiny-dec decompile .\u002Fbinary.elf --func parse_record\n\n# Stop at any intermediate stage and look inside\ntiny-dec decompile .\u002Fbinary.elf --stage ssa --func main\n\n# Inspect binary metadata\ntiny-dec info .\u002Fbinary.elf\n```\n\nEvery stage is a window into the pipeline:\n\n```\nloader → decode → pcode → disasm → ir → simplify → dataflow → ssa\n→ calls → stack → memory → scalar_types → aggregate_types → variables\n→ range → interproc → structuring → c_lowering → c\n```\n\n#### Test\n\n```bash\npoetry run pytest            # all 500 tests\npoetry run ruff check .      # lint\npoetry run mypy tiny_dec     # type check\n```\n\n\n## Example Output\n\n**Raw RISC-V instructions go in.** Readable C comes out:\n\n\u003Ctable>\n\u003Ctr>\n\u003Cth>Assembly (RV32I)\u003C\u002Fth>\n\u003Cth>Decompiled Output\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd valign=\"top\">\n\n```asm\n; parse_record\naddi x2, x2, -32\nsw   x1, 28(x2)\nsw   x8, 24(x2)\naddi x8, x2, 32\nsw   x10, -12(x8)\nsw   x11, -16(x8)\naddi x10, x0, 0\nsw   x10, -20(x8)\nsw   x10, -24(x8)\njal  x0, 0x11154\nlw   x10, -24(x8)\nlw   x11, -16(x8)\nbge  x10, x11, 0x111b8\nlw   x10, -12(x8)\nlw   x11, -24(x8)\nslli x11, x11, 3\nadd  x10, x10, x11\nlw   x11, 0(x10)\nlw   x10, -20(x8)\nadd  x10, x10, x11\nsw   x10, -20(x8)\nlw   x10, -12(x8)\nlw   x11, -24(x8)\nslli x11, x11, 3\nadd  x10, x10, x11\nlw   x11, 4(x10)\nlw   x10, -20(x8)\nadd  x10, x10, x11\nsw   x10, -20(x8)\nlw   x10, -24(x8)\naddi x10, x10, 1\nsw   x10, -24(x8)\njal  x0, 0x11154\nlw   x10, -20(x8)\nlw   x1, 28(x2)\nlw   x8, 24(x2)\naddi x2, x2, 32\njalr x0, 0(x1)\n```\n\n\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n```c\n#include \u003Cstdint.h>\n\ntypedef struct agg_8 {\n  int32_t field_0;\n  int32_t field_4;\n} agg_8;\n\nstatic uint32_t main(void) {\n  int32_t local_24_4;\n  int32_t local_20_4;\n  int32_t local_16_4;\n  int32_t local_12_4;\n  uint32_t call_ret;\n\n  local_12_4 = 20;\n  local_16_4 = 2;\n  local_20_4 = 10;\n  local_24_4 = 1;\n  call_ret = parse_record(&local_24_4, 2);\n  return call_ret;\n}\n\nstatic uint32_t parse_record(\n    agg_8* arg_x10_4,\n    int32_t arg_x11_4) {\n  int32_t local_24_4;\n  int32_t local_20_4;\n\n  local_20_4 = 0;\n  local_24_4 = 0;\n  while (local_24_4 \u003Cs arg_x11_4) {\n    local_20_4 = local_20_4\n        + arg_x10_4[local_24_4].field_0;\n    local_20_4 = local_20_4\n        + arg_x10_4[local_24_4].field_4;\n    local_24_4 = local_24_4 + 1;\n  }\n  return local_20_4;\n}\n```\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n> Recovered: **struct layout**, **pointer parameter**, **while loop**, **array indexing with field access**, and **local variables**.\n\nIt handles more than loops and structs:\n\n```c\n\u002F\u002F Switch recovery from equality-ladder CFG patterns\nstatic int32_t dispatch(uint32_t arg_x10_4, uint32_t arg_x11_4) {\n  uint32_t local_24_4;\n  uint32_t local_12_4;\n\n  local_24_4 = arg_x10_4;\n  switch (arg_x10_4) {\n  case 0:\n    local_12_4 = arg_x11_4 + 1;\n    break;\n  case 1:\n    local_12_4 = arg_x11_4 + 4;\n    break;\n  case 2:\n    local_12_4 = arg_x11_4 \u003C\u003C 1;\n    break;\n  case 3:\n    local_12_4 = arg_x11_4 - 3;\n    break;\n  default:\n    local_12_4 = -1;\n    break;\n  }\n  return local_12_4;\n}\n```\n\n```c\n\u002F\u002F Interprocedural analysis with prototype inference\nstatic int32_t main(void) {\n  int32_t local_16_4;\n  int32_t local_12_4;\n\n  local_12_4 = 7;\n  local_16_4 = helper(local_12_4);\n  return local_16_4 - 2;\n}\n\nstatic int32_t helper(int32_t arg_x10_4) {\n  return (arg_x10_4 \u003C\u003C 1) + arg_x10_4 + 1;\n}\n```\n\n## The Pipeline\n\n19 stages, three phases. Each stage produces a typed, deterministic artifact you can inspect with `--stage`. The stages are split for learning purposes; a production decompiler would combine several of these into fewer, more tightly coupled passes.\n\n### Phase 1: Frontend (Bytes to IR)\n\n| # | Stage | What it does |\n|---|-------|-------------|\n| 00 | [**Loader**](tiny_dec\u002Floader\u002F) | Parse ELF structure, resolve symbols, find `main`. The loader is deliberately shallow: it delegates all ELF parsing to [pwntools](https:\u002F\u002Fgithub.com\u002FGallopsled\u002Fpwntools) and uses simple heuristics for main discovery, since binary format parsing is not the educational focus of this project. |\n| 01 | [**Decode**](tiny_dec\u002Fdecode\u002F) | Decode RV32I instruction words into structured objects |\n| 02 | [**P-code Lift**](tiny_dec\u002Fir\u002F) | Lift each instruction into semantic p-code operations |\n| 03 | [**Disassembly**](tiny_dec\u002Fdisasm\u002F) | Recursive traversal to build basic blocks and CFG |\n| 04 | [**IR Containers**](tiny_dec\u002Fir\u002F) | Wrap functions and programs into durable typed containers |\n\n### Phase 2: Analysis\n\n| # | Stage | What it does |\n|---|-------|-------------|\n| 05 | [**Simplify**](tiny_dec\u002Fanalysis\u002Fsimplify\u002F) | Constant folding, identity elimination, temporary forwarding |\n| 06 | [**Dataflow**](tiny_dec\u002Fanalysis\u002Fdataflow\u002F) | Forward intraprocedural constant propagation |\n| 07 | [**SSA**](tiny_dec\u002Fanalysis\u002Fssa\u002F) | Dominance-frontier SSA with memory versioning |\n| 08 | [**Calls**](tiny_dec\u002Fanalysis\u002Fcalls\u002F) | Call classification, ABI argument\u002Freturn snapshots |\n| 09 | [**Stack**](tiny_dec\u002Fanalysis\u002Fstack\u002F) | Frame layout recovery, stack slot identification |\n| 10 | [**Memory**](tiny_dec\u002Fanalysis\u002Fmemory\u002F) | Partition recovery for stack, global, and pointer accesses |\n| 11 | [**Scalar Types**](tiny_dec\u002Fanalysis\u002Ftypes\u002F) | Type inference: `bool`, `int`, `pointer`, `word` |\n| 12 | [**Aggregate Types**](tiny_dec\u002Fanalysis\u002Ftypes\u002F) | Struct layout recovery from pointer arithmetic patterns |\n| 13 | [**Variables**](tiny_dec\u002Fanalysis\u002Fhighvars\u002F) | Group SSA values and memory slots into named variables |\n| 14 | [**Range**](tiny_dec\u002Fanalysis\u002Frange\u002F) | Interval analysis and branch predicate refinement |\n| 15 | [**Interproc**](tiny_dec\u002Fanalysis\u002Finterproc\u002F) | Cross-function prototype inference and summaries |\n\n### Phase 3: Backend (Structure and Emit)\n\n| # | Stage | What it does |\n|---|-------|-------------|\n| 16 | [**Structuring**](tiny_dec\u002Fstructuring\u002F) | Recover `if` \u002F `while` \u002F `switch` from CFG topology |\n| 17 | [**C Lowering**](tiny_dec\u002Fc_emit\u002F) | Lower to C-like IR with typed declarations and expressions |\n| 18 | [**C Render**](tiny_dec\u002Fpipeline\u002F) | Emit readable C with precedence-aware formatting |\n\n## Project Layout\n\n```\ntiny_dec\u002F\n├── loader\u002F            ELF loading and symbol resolution\n├── decode\u002F            RV32I instruction decoder\n├── ir\u002F                P-code semantics and IR containers\n├── disasm\u002F            Recursive disassembler and CFG builder\n├── analysis\u002F\n│   ├── simplify\u002F      Canonical IR cleanup\n│   ├── dataflow\u002F      Constant propagation\n│   ├── ssa\u002F           SSA construction\n│   ├── calls\u002F         Call modeling and ABI facts\n│   ├── stack\u002F         Stack frame recovery\n│   ├── memory\u002F        Memory partitioning\n│   ├── types\u002F         Scalar and aggregate type recovery\n│   ├── highvars\u002F      Variable recovery\n│   ├── range\u002F         Range and predicate analysis\n│   └── interproc\u002F     Interprocedural summaries\n├── structuring\u002F       Control-flow structuring\n├── c_emit\u002F            C lowering and rendering\n├── pipeline\u002F          End-to-end decompilation driver\n└── cli.py             Command-line interface\n\ntests\u002F\n├── fixtures\u002F\n│   ├── src\u002F           13 C programs (loops, structs, calls, switches, ...)\n│   └── bin\u002F           39 cross-compiled RV32I ELF binaries\n└── posts\u002F\n    └── post_00\u002F ... post_18\u002F    One test suite per pipeline stage\n```\n\n## Why Is It Built This Way?\n\n**Explicit over clever.** Every intermediate representation is a concrete, typed Python dataclass. No hidden state, no magic.\n\n**Deterministic output.** Every stage has a text renderer that produces identical output given identical input. This is both the debugging surface and the test oracle.\n\n**One stage, one job.** Each stage solves exactly one problem and passes a well-defined artifact to the next. You can stop the pipeline at any point and inspect what it produced.\n\n**Conservative analysis.** The pipeline never invents information. When evidence is ambiguous, it preserves the raw form rather than guessing. Residual `raw\u003C...>` expressions in the output are honest about what the analysis couldn't resolve.\n\n**This is a teaching tool, not a production decompiler.** The pipeline is deliberately factored into many small, isolated stages so that each concept can be studied independently. A real-world decompiler (Ghidra, IDA, angr, Binary Ninja) would fuse, reorder, or iterate these passes for performance and precision. We trade that efficiency for clarity: if you can follow each stage here, you will understand what the production tools are doing under the hood.\n\n## Fixture Binaries\n\n13 C programs compiled to RV32I ELF at three optimization levels (39 binaries total, with strict no-compressed-instruction verification):\n\n| Variant | Flags | Purpose |\n|---------|-------|---------|\n| `*_O0_nopie` | `-O0 -fno-pie` | Unoptimized, predictable stack layout |\n| `*_O2_nopie` | `-O2 -fno-pie` | Optimized, tests register allocation recovery |\n| `*_O2_pie` | `-O2 -fpie` | Position-independent, tests GOT\u002FPLT handling |\n\nRebuild with `.\u002Fscripts\u002Fbuild_fixtures.sh` (requires `clang`, `lld`, `llvm` with RISC-V support).\n\n## Further Reading\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fdecompilation.wiki\">\u003Cimg src=\"assets\u002Fcard-decompilation-wiki.svg\" alt=\"decompilation.wiki\" width=\"100\">\u003C\u002Fa>\n  &nbsp;\n  \u003Ca href=\"https:\u002F\u002Fmahaloz.re\">\u003Cimg src=\"assets\u002Fcard-mahaloz.svg\" alt=\"mahaloz.re\" width=\"100\">\u003C\u002Fa>\n  &nbsp;\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FZhangZhuoSJTU\u002Ftiny-dec\u002Fissues\u002Fnew?template=suggest-resource.yml\">\u003Cimg src=\"assets\u002Fcard-more.svg\" alt=\"Suggest a resource\" width=\"100\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\u003Csub>Actively-maintained resources that go deeper into the concepts behind each pipeline stage.\u003C\u002Fsub>\u003C\u002Fp>\n\n## Special Thanks\n\n- [Seunghyun Sung](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fseunghyun-sung\u002F)\n- [Hugo Matousek](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fhugo-matousek\u002F)\n\n## License\n\n[MIT](LICENSE)\n","tiny-dec 是一个小型教育用反编译工具，旨在帮助人们理解反编译的工作原理。该项目使用 Python 语言编写，支持 RISC-V RV32I 指令集架构，并通过 19 个可独立检查的阶段逐步将原始字节码转换为可读 C 代码。每个阶段的设计都尽可能地简单和透明，便于学习者逐一掌握反编译的核心概念和技术细节。此外，项目还提供了一个基于 AI 的导师插件，能够根据用户水平定制化指导，非常适合计算机科学教育、逆向工程入门以及对编译器和反编译器工作流程感兴趣的开发者使用。",2,"2026-06-11 02:44:36","CREATED_QUERY"]