Project Icon

selfie

自编译系统工程教育平台

Selfie是一个系统工程教育平台,通过12000行C代码实现了自编译编译器、自执行模拟器和自托管虚拟机监视器。该项目聚焦系统代码中的自引用挑战,为本科生和研究生提供编译器、库、操作系统和虚拟机监视器的实践构建经验,全面覆盖从编程语言到运行时系统的设计与实现。

自拍 自拍 在Repl.it上运行

自拍是奥地利萨尔茨堡大学计算机科学系计算系统组的一个项目。

自拍项目为本科生和研究生提供了一个教育平台,用于教授编程语言和运行时系统的设计和实现。重点是构建编译器、库、操作系统和虚拟机监控器。共同的主题是识别和解决系统代码中的自引用,这被视为教授系统工程时的关键挑战,因此得名。

自拍是一个自包含的64位、12KLOC C语言实现,包括:

  1. 一个自编译编译器,名为starc,它将一个小但仍然快速的C语言子集称为C Star(C*)编译成一个小型且易于教授的RISC-V子集,称为RISC-U
  2. 一个自执行仿真器,名为mipster,它可以执行RISC-U代码,包括用starc编译的自身,
  3. 一个自托管虚拟机监控器,名为hypster,它提供可以托管整个自拍的RISC-U虚拟机,即starc、mipster和hypster本身,以及
  4. 一个由自拍使用的tiny C*库,名为libcstar。

自拍在一个(!)文件中实现,并保持最小化以简化。还有一个简单的内存链接器、RISC-U反汇编器、垃圾收集器、L1指令和数据缓存、分析器,以及带有重放功能的调试器,以及以RISC-V系统调用形式内置于仿真器和虚拟机监控器中的最小操作系统支持。垃圾收集器是保守的,甚至是自收集的。它可以作为库在与变异器相同的地址空间中运行,和/或作为内核地址空间中仿真器的一部分运行。

自拍生成的ELF二进制文件可以在真实的RISC-V硬件QEMU上运行,并与官方RISC-V工具链兼容,特别是spike仿真器pk内核

自拍被设计为64位系统,因此需要64位系统才能运行(LP64数据模型)。然而,自拍也可以在支持编译和执行32位二进制文件的系统上编译(ILP32数据模型)。在这种情况下,自拍成为一个32位系统,可以直接生成和执行32位二进制文件。这是可能的,因为自拍的实现在整个系统中都小心避免了32位溢出。

支持

  1. Slack:在cksystemsteaching.slack.com的#selfie频道加入对话
  2. 幻灯片:有提供全面介绍自拍设计和实现的课堂幻灯片
  3. 自动评分器:有一个带有编译器和操作系统作业的自动评分器
  4. 论文:有一篇介绍自拍的Onward! 2017论文
  5. 书籍:有一本基于自拍的早期草稿形式的免费书籍,名为基础计算机科学:从比特和字节到计算的普遍性,面向所有对学习计算机科学感兴趣的人。
  6. 代码:自拍代码是开源的,可在github.com/cksystemsteaching/selfie获取
  7. X:在x.com/christophkirsch关注我们
  8. 网站:自拍主页在selfie.cs.uni-salzburg.at

附加内容

  1. 垃圾回收:除了selfie中保守但时间复杂度为O(n^2)的垃圾回收器外,还有一个针对小内存块的O(n)时间复杂度的Boehm垃圾回收器实现,对于大内存块则回退使用selfie中的垃圾回收器。

  2. 模糊测试:有一个基于selfie的简单但自我模糊测试的模糊器,名为buzzr,用于对RISC-U代码(包括selfie的所有代码和自身)进行模糊测试。

  3. 符号执行:有一个基于selfie的自执行符号执行引擎,名为monster,它将RISC-U代码(包括selfie的所有代码和自身)转换为SMT-LIB公式。当且仅当存在使代码以非零退出代码退出或在给定的机器指令数内执行除零操作的输入时,这些公式是可满足的。

  4. 有界模型检查:有一个基于selfie的自翻译建模引擎,名为beator,它将RISC-U代码(包括selfie的所有代码和自身)转换为BTOR2公式。当且仅当存在使代码以非零退出代码退出、执行除零操作或访问已分配内存块之外的内存的输入时,这些公式是可满足的。

  5. 位精确代码分析和合成:有一个基于selfie的自翻译建模引擎,名为rotor,它将完整的RISC-V代码(包括selfie的所有代码和自身)转换为BTOR2和SMT-LIB公式。当且仅当存在使代码以非零退出代码退出、执行除零操作或访问内存段之外的内存的输入时,这些公式是可满足的。Rotor还生成支持RISC-V代码合成的模型。

  6. BTOR2可视化:有一个名为beatle的可视化工具,它将从RISC-U二进制文件生成的BTOR2公式显示为有向无环图。

  7. SAT求解:有一个基于selfie的暴力SAT求解器,名为babysat,用于计算DIMACS CNF格式的SAT公式的可满足性。

  8. 二进制翻译:有一个基于selfie的自翻译二进制翻译器,它将RISC-U代码(包括selfie的所有代码和自身)翻译成x86二进制代码。

安装Selfie

Selfie可以在Linux、macOS和Windows机器上原生运行,可能还支持其他安装了终端和C编译器的系统。即使您的机器上没有安装C编译器,或者您只能访问网络浏览器,您也可以运行selfie。安装和运行selfie至少有三种方式:

  1. 在您的机器上原生安装(推荐):下载并解压selfie。然后,打开终端运行selfie,具体见下文。为此,您需要在机器上安装C编译器。我们推荐使用clanggcc(在Windows上使用cygwin)。

  2. 在您的机器上使用docker(高级):下载并安装docker。然后,打开终端并输入docker run -it cksystemsteaching/selfie。使用docker的优点是您可以在机器上直接运行selfie,而无需安装任何工具,如C编译器。所有必要的甚至可选的工具都预先安装在selfie docker镜像中。但是,您需要知道如何使用docker。

  3. 在云端(简单但需要互联网连接):如果您只能访问网络浏览器,只需点击这里。或者,创建一个github账户(如果您还没有),然后将selfiefork到您的github账户中。接着,创建一个cloud9学生账户,将其连接到您的github账户,验证您的电子邮件地址并设置密码(重要!),最后将您fork的selfie克隆到一个新的cloud9工作空间中。

此时,我们假设您已经有一个支持运行selfie的系统。以下我们使用make命令,假设它已安装在您的系统上,这通常是默认的。但是,我们也会展示make调用的命令,这样如果您的系统没有安装make,您也可以手动执行该命令。

下一步是生成selfie二进制文件。为此,在终端中cd到selfie文件夹,然后输入make。使用docker时,系统会回应make: 'selfie' is up to date,因为已经预先安装了selfie二进制文件。不使用docker时,make将在您的机器上或cloud9工作空间中调用C编译器:

cc -Wall -Wextra -O3 -D'uint64_t=unsigned long' selfie.c -o selfie

然后将selfie.c编译成一个名为selfie的可执行文件,如-o选项所指定。这个可执行文件包含C*编译器、mipster模拟器和hypster虚拟机监控器。-Wall-Wextra选项启用所有编译器警告,这在selfie的进一步开发中很有用。-O3选项指示编译器生成优化代码。-D'uint64_t=unsigned long'选项用于引导代码。它定义了数据类型uint64_t,否则由于C*不包含必要的定义,该类型将是未定义的。如果您的系统支持编译和执行32位二进制文件,您也可以尝试make selfie-32,这将生成一个32位系统,然后生成和执行32位二进制文件。

运行Selfie

一旦您成功编译了selfie.c,您可以不带任何参数调用selfie,如下所示:

$ ./selfie
./selfie { -c { source } | -o binary | [ -s | -S ] assembly | -l binary } [ ( -m | -d | -r | -y ) 0-4096 ... ]

在这种情况下,selfie会回应其使用模式。

为了充分利用自指性,提供选项的顺序很重要。 -c选项调用C*编译器处理给定的source文件列表,将它们编译并链接成内部存储的RISC-U代码。例如,可以使用selfie来编译它自己的源代码selfie.c,如下所示:

$ ./selfie -c selfie.c

-o选项将最近一次编译器调用生成的RISC-U代码写入指定的binary文件。例如,可以指示selfie编译自身,然后将生成的RISC-U代码输出到名为selfie.m的RISC-U二进制文件:

$ ./selfie -c selfie.c -o selfie.m

-s选项将最近一次编译器调用生成的RISC-U代码的RISC-U汇编写入指定的assembly文件,而-S选项还会包括近似的行号和指令的二进制表示。类似地,可以指示selfie编译自身,然后将生成的RISC-U代码输出到名为selfie.s的RISC-U汇编文件:

$ ./selfie -c selfie.c -s selfie.s

-l选项从给定的binary文件加载RISC-U代码。-o-s选项也可以在-l选项之后使用。但在这种情况下,-s选项不会生成近似的源代码行号。例如,可以按如下方式加载之前生成的RISC-U二进制文件selfie.m

$ ./selfie -l selfie.m

-m选项调用mipster模拟器执行最近加载或由编译器调用生成的RISC-U代码。模拟器创建一个具有0-4096 MB内存的机器实例。RISC-U代码的sourcebinary名称以及任何剩余的...参数都会传递给代码的main函数。例如,以下调用使用mipster执行selfie.m

$ ./selfie -l selfie.m -m 1

这在语义上等同于不带任何参数执行selfie

$ ./selfie

-d选项类似于-m选项,但mipster会输出每条执行的指令、其近似源代码行号(如果可用)以及相关的机器状态。另外,-r选项通过让mipster仅在发生运行时错误(如除以零)时重放代码执行,来限制-d选项创建的输出量。在这种情况下,mipster只输出错误发生前刚刚执行的指令。

如果你使用docker,也可以直接在spike和pk上执行selfie.m,如下所示:

$ spike pk selfie.m

这在语义上再次等同于不带任何参数执行selfie

-y选项调用hypster虚拟机监控器执行RISC-U代码,类似于mipster模拟器。与mipster的区别在于,hypster创建RISC-U虚拟机而不是RISC-U模拟器来执行代码。请参见下面的示例。

自编译

以下是如何执行selfie.c的自编译,然后检查通过执行./selfie二进制文件为selfie.c生成的RISC-U代码selfie1.m是否等同于通过执行刚刚生成的selfie1.m二进制文件生成的代码selfie2.m的示例:

$ ./selfie -c selfie.c -o selfie1.m -m 2 -c selfie.c -o selfie2.m
$ diff -s selfie1.m selfie2.m
Files selfie1.m and selfie2.m are identical

注意,这需要至少2MB的内存才能工作。

自执行

以下示例展示了如何执行mipster模拟器的自执行。在这种情况下,我们调用mipster来调用自身以执行selfie

$ ./selfie -c selfie.c -o selfie.m -m 2 -l selfie.m -m 1

这在语义上再次等同于不带任何参数执行selfie,但这次selfie打印其使用模式的速度要慢得多,因为有一个mipster运行在另一个mipster之上。

自托管

前面的示例也可以通过在mipster上运行hypster来完成。这显著更快,并且需要更少的内存,因为hypster不会在第一个模拟器实例之上创建第二个模拟器实例。相反,hypster创建一个虚拟机来执行selfie,该虚拟机与第一个模拟器实例上的hypster并行运行:

$ ./selfie -c selfie.c -o selfie.m -m 1 -l selfie.m -y 1

我们甚至可以在mipster上运行hypster上的hypster,这仍然相当快,因为仍然只涉及一个模拟器实例,而hypster本身并不增加太多开销:

$ ./selfie -c selfie.c -o selfie.m -m 2 -l selfie.m -y 1 -l selfie.m -y 1

工作流程

要编译任何C*源代码并立即执行它,而不生成RISC-U二进制文件,可以在单次调用selfie时使用:

$ ./selfie -c any-cstar-file.c -m 1 "arguments for any-cstar-file.c"

同样,你也可以使用selfie编译的selfie版本,让mipster模拟器执行selfie来编译任何C*源代码,然后立即用hypster在同一模拟器实例上执行它:

$ ./selfie -c selfie.c -m 1 -c any-cstar-file.c -y 1 "arguments for any-cstar-file.c"

你也可以用这两种方式生成RISC-U二进制文件,它们将是相同的:

$ ./selfie -c any-cstar-file.c -o any-cstar-file1.m
$ ./selfie -c selfie.c -m 1 -c any-cstar-file.c -o any-cstar-file2.m
$ diff -s any-cstar-file1.m any-cstar-file2.m
Files any-cstar-file1.m and any-cstar-file2.m are identical

这也可以在单次调用selfie时完成:

$ ./selfie -c any-cstar-file.c -o any-cstar-file1.m -c selfie.c -m 1 -c any-cstar-file.c -o any-cstar-file2.m
$ diff -s any-cstar-file1.m any-cstar-file2.m
Files any-cstar-file1.m and any-cstar-file2.m are identical

然后可以按如下方式加载和执行生成的RISC-U二进制文件:

$ ./selfie -l any-cstar-file1.m -m 1 "arguments for any-cstar-file1.m"

链接

要从多个源文件编译和链接任何C*源代码,请使用:

$ ./selfie -c any-cstar-file1.c any-cstar-file2.c ... -m 1

例如,要将 selfie.c 的源代码作为库代码在任何 C* 源代码中使用,请执行:

$ ./selfie -c any-cstar-file.c selfie.c -m 1

请注意,编译器会忽略多重符号定义,并发出警告。

调试

Selfie 的控制台消息始终以当前运行的源文件或二进制文件的名称开头。Mipster 模拟器还会显示为其机器实例分配的内存量以及执行如何终止(退出代码)。

如前所述,selfie 和任何其他 C* 文件的 RISC-U 汇编代码可以通过以下方式生成:

$ ./selfie -c selfie.c -s selfie.s

如果汇编代码是由编译器生成的二进制文件生成的(而不是从文件加载的),汇编文件中会包含大致的源代码行号。

使用 -d 选项可以打印详细的调试信息,例如:

$ ./selfie -c selfie.c -d 1

同样,如果执行的二进制文件是由编译器生成的(而不是从文件加载的),调试信息中会包含大致的源代码行号。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号