当前的 macOS 二进制可执行文件使用一种称为的格式,在此之前有,维基百科称“它针对 RISC 处理器进行了优化”。

这让人觉得这是将 PowerPC 处理器引入 Mac 时的一种新格式。虽然措辞可能有些含糊,但实际上应该暗示存在一种“原始”PEF 格式,后来进行了更新或“优化”。

我似乎找不到任何地方说明 Mac 的原始文件格式是什么,或者在 PEF 之前是否有几种文件格式。


最佳答案
2

一般来说,MacOS Classic 中没有“二进制文件”这样的东西——应用程序的资源分支中存在 CODE 资源,其中包含二进制文件的代码段,由 CODE 资源 0 松散地保存在一起。

经典 Mac 上的应用程序运行时结构受到早期 68k CPU 功能和“一切都是浮动的”(即没有固定内存地址)范式的强烈影响。(请注意,以下所有内容均描述了初始 MacOS 版本中使用的机制。Apple 在后续版本中开发了许多修正,以修复此模型的一些限制 – 后来被称为“近模型”,主要是程序可以拥有的全局数据量(32k)和最大段大小(也是 32k)。

原始 68000 可以在整个 24 位地址范围内执行绝对跳转和调用,因此显然需要某种运行时重定位 – 而且您根本无法在 Classic MacOS 应用程序中使用这些指令。它还可以执行寄存器相关跳转,即在表中查找地址并在那里分支(这些指令被大量使用,见下文)。CPU 还可以执行PC 相关跳转和分支(即“分支到这里+ 256 字节”),但这些指令被限制在 +- 32k 范围内,同样被大量使用(这个 32k 限制在后来的 CPU 中被取消)。

这些 CPU 功能会影响 MacOS 二进制文件在段中的布局– 代码片段,基本上大小限制为 32k(*),因此段内的所有内容都在 PC 相对分支的范围内,这些分支存储在单个 CODE 资源中,可以初始加载或按需加载。单个 CODE 资源内的代码分支严格与 PC 相关,并在编译时静态链接。要加载 CODE 资源,因此不需要进行段内调用的重定位。由此可见,只有单个 CODE 资源的应用程序代码大小限制为 32k。

对于段间调用和完整的应用程序,加载 CODE 资源 0 非常重要 – 加载 CODE 资源时,它会根据 CODE 0 资源和已加载的特定段中的信息生成跳转表,该表始终由 a5 指向并解析段间地址解析(即段调用)。段间调用始终相对于 a5 寄存器(即不需要进一步重定位),并且基本上所有段间分支都必须经过此跳转表(识别要调用的“远”例程,在跳转表中查找其加载地址,跳转) – 非常类似于现代操作系统中的共享库调用。有一个巧妙的机制允许自动按需加载 CODE 资源 – 跳转到当前未加载的段将自动加载相应的 CODE 资源,相应地修补跳转表条目,并执行例程。这种通过表的跳转显然会产生一些运行时开销。另一方面,通过跳转表允许操作系统随意移动代码段,即使应用程序正在运行,例如为了压缩内存占用 – 只要调整跳转表中的值即可。(顺便说一句:虽然 MacOS 支持按需加载代码段,但它永远不会在不再需要时卸载段。只有在开发人员明确说明的情况下才会这样做)

因此,MacOS 二进制文件中唯一的重定位信息(更确切地说是:随时可用的地址修复)包含在加载时构建此跳转表的 CODE 0 资源中。其他段的其他 CODE 资源只是静态链接的、完全与位置无关的平面二进制文件。

(*) 一些编译器允许创建更大的代码段,方法是创建所谓的“跳转岛”,一系列小于 32k 的分支指令分布在代码中,将较长的分支拆分为多个 32k 跳转,以便到达 32k 以外的位置。因此,代码段可以超过 32k,但代价是二进制文件混乱且运行时开销大。

经典 MacOS 是一个有点奇怪的操作系统。接下来,您需要研究其动态内存管理,它对句柄而不是地址进行操作,并且可能会随意移动您分配的内存而您却没有注意到 – 使指针和地址无效…

再说几句 2cents 的话:过去,人们对摩托罗拉 CPU 架构优于英特尔 x86 的争论很大,因为它不依赖分段。Apple 设法人为地将分段(因为这正是 CODE 资源的本质 – 段大小有限,甚至只有 x86 CPU 上段大小的一半)引入 Classic MacOS,因为他们不想为运行时重定位机制(即“适当的”重定位加载器)付出代价,并且想要小的浮动实体(即段 :)),以便能够在早期 Mac 非常有限的内存中塞入更多内容。后来拥有更多内存和扩展 CPU 的 Mac 受到这些机制的阻碍

回想起来,MacOS 如此严格地围绕 68k CPU 进行定制,使得整个系统非常难以移植,并且很可能在 PowerPC 迁移期间给他们带来麻烦。另一方面,在 20 世纪 80 年代初期,可移植性根本不存在……

我继续寻找并找到了答案。

可执行代码存储在资源的资源分支中CODE。(可能也存储在数据分支等效.rsrc资源文件中?)

来自

有些文件只有资源分支。一个例子是经典 Mac OS 中的字体文件。另一个例子是 Classic 68k 应用程序,其中甚至可执行代码也包含在“CODE”类型的资源中。后来的 PowerPC 二进制文件将可执行代码存储在数据分支中。

在下面评论中中,“关于细分经理”的说明更加清晰。

应用程序的可执行代码作为一个或多个“CODE”类型的资源存储在其资源分支中。这些代码资源称为段,因为例程到代码资源的划分由您提供给开发系统的分段指令控制。

我仍然想了解更多信息。例如,该CODE资源是否具有内部格式,或者它是否依赖其他资源来提供诸如重定位和调试信息之类的信息?

4

  • 1
    我认为你会对


    – 


  • 否决是因为可执行代码没有存储在资源分支中?还是因为它不在资源中CODE


    – 

  • 投票反对,因为你在第一个简单版本的答案中扩展了你的问题。现在它有了更多内容,不过我建议删除这个附加问题。


    – 

  • 1
    请参阅,特别是第 10 章“经典 68K 运行时架构”。


    –