docs: wip devguide

This commit is contained in:
2025-06-20 18:39:30 +08:00
parent 19b5c1aef3
commit 9af3d8d4fb
8 changed files with 154 additions and 2 deletions

View File

@@ -1,8 +1,11 @@
{ {
"cSpell.words": [ "cSpell.words": [
"pycdas",
"Pycdc", "Pycdc",
"Pydumpck",
"Pynosaur", "Pynosaur",
"Uncompyle" "Uncompyle",
"xdis"
], ],
"[python]": { "[python]": {
"editor.defaultFormatter": "ms-python.black-formatter" "editor.defaultFormatter": "ms-python.black-formatter"

View File

@@ -2,15 +2,68 @@
简体中文 | [English](README.en.md) 简体中文 | [English](README.en.md)
[👉 跳转到安装与用法小节](#安装)
## 功能特性 ## 功能特性
### 高版本 CPython 字节码
### 是命令行程序,也是 Python 库
### 推测 Python 版本
如果传入 Marshal 产生的代码对象Code Object字节串Pynosaur 可以尽可能根据字节码指令推测出其对应的 Python 版本。这一特性对于 pyc 头丢失、只有反汇编文本等情况非常有用。
### 人为构造的代码对象
对于每个新的 Python 版本Pynosaur 首先尽可能实现对 CPython 编译器生成的字节码序列的支持。在此基础上,我们尝试在遇到 CPython 编译器通常情况下不会产生的字节码序列时,产生尽可能有用的结果。这样,就不会因为恶意构造的字节码而导致 Pynosaur 反编译失败。以下是一个仅用于描述的恶意构造的例子(其中的注释不是 Pynosaur 生成的,只是对例子的说明):
```plaintext
LOAD_CONST 1 (1)
LOAD_CONST 2 (2)
COMPARE_OP 148 (bool(>))
POP_JUMP_IF_FALSE 10 (to L1) # 下一条指令代表 1 大于 2 的分支
LOAD_GLOBAL 5678 (??? + NULL) # globals 的第五千多项?越界!
CALL 1234 # 从栈上弹出一千多个参数?
POP_TOP
```
一种可能的反编译输出是 `pass` 并在后面的注释中提供无法处理的字节码指令。
### 文本格式
除 pyc 文件等二进制格式外Pynosaur 也接受以下输入形式或其片段:
- 标准库 `dis.dis` 输出的反汇编字节码文本
- 标准库 `ast.dump` 输出的抽象语法树文本
- 标准库 `tokenize` 输出的词法单元文本
- [pycdas]() 输出的反汇编字节码文本
- [xdis]() 输出的反汇编字节码文本
### 版本转换
Pynosaur 还支持不同版本之间的字节码转换。例如,通过适当的命令行参数或脚本,可以用 Python 3.12 运行 Pynosaur 本身,传入文本格式的 Python 3.13 的字节码,输出可用于的 Python 3.11 的 pyc 文件。
### 与运行 Pynosaur 的 CPython 标准库或原生类型互操作
### 可转换的形式小结
### 衍生产品
- **Pynosaur UI**: 一个可视化的字节码反编译、原地编辑、跨版本回编译工具。由 Pynosaur 开发者维护。
- **Pynosaur Duck**: 只需一条命令,解包并递归反编译 PyInstaller 和 Py2exe 打包的可执行文件。由 Pynosaur 开发者维护。灵感来源于 [Pydumpck]()。
## 设计 ## 设计
### 没有历史包袱
不同于其他支持早期版本(甚至 2.x, 1.x的反编译器Pynosaur 从一开始就被设计为只支持最近几个 CPython 版本,目前支持 CPython 3.9 至 3.14 的字节码。
这样的好处在于可以专注于现代 Python 语言的特性和优化,而不必考虑向后兼容性的问题。例如,从 Python 3.6 开始CPython 字节码指令是定长的。由于不需要考虑旧版本的字节码Pynosaur 可以安全地假定字节码指令的长度是固定的,这使得反编译器的实现更简单、更高效。
新的 Python 版本发布时,针对不再受支持版本的反编译逻辑可能会被 Pynosaur 移除。如果发生这种情况Pynosaur 会发布新的主要版本。旧的主要版本仍然可用,但不再维护。这使得 Pynosaur 代码库可以保持简洁、灵活,在实现新的字节码时不需考虑过多兼容问题。
如果你需要处理 3.8 及更低版本的字节码,可以选择其他工具,见下文对比章节。
## 工作原理 ## 工作原理

View File

@@ -0,0 +1,18 @@
欢迎来到 Pynosaur 的开发指南!本指南旨在帮助开发者理解和参与 Pynosaur 的开发工作,涵盖项目的设计理念、开发工作流、实现细节等。
你正在阅读版本 0.0.1 的文档。文档 MarkDown 源文件位于代码仓库 `docs/zh/docs/devguide/` 目录下,切换到另一个版本的分支或标签可以查看其他版本的文档。
<details>
<summary>历史版本</summary>
</details>
开发文档假定读者已经熟悉 Python 编程语言和基本的编程概念,例如变量、函数、类和模块等。
还假定读者学习过编译原理课程,或至少了解编译器前端的基本工作原理。读者应当了解词法分析、语法分析、语义分析、中间代码生成的主要任务和算法。
# 术语约定
# 项目组成
# 目录结构

View File

@@ -0,0 +1,23 @@
# 工作语言
目前项目的主要开发者母语为中文。为了便于更多人参与,建议遵循以下语言使用规范:
- 通常情况下由主要开发者编写的文档首先使用中文,然后翻译成英文。也就是说,中文文档是原始准确的,英文文档可能存在偏差。
- 为了术语翻译清楚明白,可能会在中文后面用括号标注英文原文。
- 文件名、代码注释、议题issue标题、拉取请求pull request标题、拉取请求描述、拉取请求评论、提交消息commit message**总是**使用英文。议题内容、议题回复或评论可以使用中文或英文。
# Git 工作流
# 版本发布策略
# 贡献
## 代码贡献
### 代码规范
## 文档贡献
### 翻译

View File

@@ -0,0 +1,11 @@
# 字节码是什么
# 从源代码到字节码
# PYC 文件的生成
# PYC 文件的结构
# 标准库语言服务
# CPython 源码和相关资料

View File

@@ -0,0 +1,44 @@
本文通过一个完全虚构的小的例子,引导读者初步了解项目代码结构和原理,帮助读者快速上手开发工作。
假设下一个版本 CPython 添加了一条 `RETURN_INT` 字节码指令,指令编号是 [TODO] ,取代 CPython 3.14 中的 [TODO] 指令。我们要将它添加到已经实现的字节码指令中。该指令的操作数是一个整数值,作用是将该整数值作为函数的返回值。该指令没有栈副作用。
# 保留中间结果
# 建立一个新的分支
# 确认调试环境与工作区相同
# 了解待添加的指令
首先我们通常会观察 CPython 在什么情况下会生成 `RETURN_INT` 指令。CPython 的代码生成器源代码位于 [TODO] 文件中。我们可以搜索 `RETURN_INT` 来找到相关代码。由于本例是完全虚构的,我们假设对于以下源代码,会生成该指令:
```python
def foo():
return 42
```
`dis.dis(foo)` 产生以下输出:
```plaintext
1 RESUME 0
RETURN_INT 42
```
相应的,如果使用现有的 Python 版本,产生以下输出:
```plaintext
1 RESUME 0
RETURN_CONST 1 (42)
```
`RETURN_CONST` 的语义没有改变,我们不需要修改它。
# 添加指令到字节码指令列表
# 对 CFG 的影响
# 从 CFG 到 AST
# 从 AST 到 Python 代码
# 测试

View File