Clang 使用 -nostdlib 生成崩溃代码

2024-05-03

我正在尝试为可执行文件设置自己的运行时环境,但无法使用 clang(v3.4-1ubuntu1,目标:x86_64-pc-linux-gnu)来生成没有段错误的可执行文件。我已将问题简化为以下内容:

如果我有一个文件 crt1.c,除了满足 _start 符号的链接器要求之外什么也不做:

void
_start(char *arguments, ...)
{
}

然后我编译它clang -nostdlib crt1.c,它生成以下可执行文件(来自objdump -d a.out):

a.out:     file format elf64-x86-64


Disassembly of section .text:

0000000000400150 <_start>:
  400150:   55                      push   %rbp
  400151:   48 89 e5                mov    %rsp,%rbp
  400154:   48 81 ec f0 00 00 00    sub    $0xf0,%rsp
  40015b:   84 c0                   test   %al,%al
  40015d:   0f 29 bd 30 ff ff ff    movaps %xmm7,-0xd0(%rbp)
  400164:   0f 29 b5 20 ff ff ff    movaps %xmm6,-0xe0(%rbp)
  40016b:   0f 29 ad 10 ff ff ff    movaps %xmm5,-0xf0(%rbp)
  400172:   0f 29 a5 00 ff ff ff    movaps %xmm4,-0x100(%rbp)
  400179:   0f 29 9d f0 fe ff ff    movaps %xmm3,-0x110(%rbp)
  400180:   0f 29 95 e0 fe ff ff    movaps %xmm2,-0x120(%rbp)
  400187:   0f 29 8d d0 fe ff ff    movaps %xmm1,-0x130(%rbp)
  40018e:   0f 29 85 c0 fe ff ff    movaps %xmm0,-0x140(%rbp)
  400195:   48 89 bd b8 fe ff ff    mov    %rdi,-0x148(%rbp)
  40019c:   4c 89 8d b0 fe ff ff    mov    %r9,-0x150(%rbp)
  4001a3:   4c 89 85 a8 fe ff ff    mov    %r8,-0x158(%rbp)
  4001aa:   48 89 8d a0 fe ff ff    mov    %rcx,-0x160(%rbp)
  4001b1:   48 89 95 98 fe ff ff    mov    %rdx,-0x168(%rbp)
  4001b8:   48 89 b5 90 fe ff ff    mov    %rsi,-0x170(%rbp)
  4001bf:   0f 84 5b 00 00 00       je     400220 <_start+0xd0>
  4001c5:   0f 28 85 c0 fe ff ff    movaps -0x140(%rbp),%xmm0
  4001cc:   0f 29 85 70 ff ff ff    movaps %xmm0,-0x90(%rbp)
  4001d3:   0f 28 8d d0 fe ff ff    movaps -0x130(%rbp),%xmm1
  4001da:   0f 29 4d 80             movaps %xmm1,-0x80(%rbp)
  4001de:   0f 28 95 e0 fe ff ff    movaps -0x120(%rbp),%xmm2
  4001e5:   0f 29 55 90             movaps %xmm2,-0x70(%rbp)
  4001e9:   0f 28 9d f0 fe ff ff    movaps -0x110(%rbp),%xmm3
  4001f0:   0f 29 5d a0             movaps %xmm3,-0x60(%rbp)
  4001f4:   0f 28 a5 00 ff ff ff    movaps -0x100(%rbp),%xmm4
  4001fb:   0f 29 65 b0             movaps %xmm4,-0x50(%rbp)
  4001ff:   0f 28 ad 10 ff ff ff    movaps -0xf0(%rbp),%xmm5
  400206:   0f 29 6d c0             movaps %xmm5,-0x40(%rbp)
  40020a:   0f 28 b5 20 ff ff ff    movaps -0xe0(%rbp),%xmm6
  400211:   0f 29 75 d0             movaps %xmm6,-0x30(%rbp)
  400215:   0f 28 bd 30 ff ff ff    movaps -0xd0(%rbp),%xmm7
  40021c:   0f 29 7d e0             movaps %xmm7,-0x20(%rbp)
  400220:   48 8b 85 b0 fe ff ff    mov    -0x150(%rbp),%rax
  400227:   48 89 85 68 ff ff ff    mov    %rax,-0x98(%rbp)
  40022e:   48 8b 8d a8 fe ff ff    mov    -0x158(%rbp),%rcx
  400235:   48 89 8d 60 ff ff ff    mov    %rcx,-0xa0(%rbp)
  40023c:   48 8b 95 a0 fe ff ff    mov    -0x160(%rbp),%rdx
  400243:   48 89 95 58 ff ff ff    mov    %rdx,-0xa8(%rbp)
  40024a:   48 8b b5 98 fe ff ff    mov    -0x168(%rbp),%rsi
  400251:   48 89 b5 50 ff ff ff    mov    %rsi,-0xb0(%rbp)
  400258:   48 8b bd 90 fe ff ff    mov    -0x170(%rbp),%rdi
  40025f:   48 89 bd 48 ff ff ff    mov    %rdi,-0xb8(%rbp)
  400266:   4c 8b 85 b8 fe ff ff    mov    -0x148(%rbp),%r8
  40026d:   4c 89 45 f8             mov    %r8,-0x8(%rbp)
  400271:   48 81 c4 f0 00 00 00    add    $0xf0,%rsp
  400278:   5d                      pop    %rbp
  400279:   c3                      retq   

可执行文件因地址 40015d 处的指令(保存 %xmm7 的指令)处的分段错误而崩溃。我不知道为什么 clang 要把这些保存起来,gcc 没有产生这样的指令。

%rbp 中传递的值是 7fffffffe588,它不是 16 字节对齐的,我想这在某种意义上解释了分段错误。但我该如何让它发挥作用呢?让它抑制那些保存指令?让它以某种方式对齐 rbp 指针?

EDIT:我猜这个问题归结为 clang 生成的代码假设 %rsp 将是 16 字节对齐的。这是一个有效的假设吗?为什么这个例子中的情况不正确呢?


EDIT:找到了解决方案 - 跳到下面看...


首先,确保堆栈(%rsp) 是 16 字节对齐的:

pushq  %rbp
movq   %rsp, %rbp
andq   $-0x10, %rsp  ; rsp = rsp & 0xffffffffffffff0

这是有问题的,因为通常调用者有责任确保%rsp是 16 字节对齐的,如%rbp + 16.n可能不在 16 字节边界上。所以也许movq %rsp, %rbp应该在对齐后出现%rsp.

sub $0xf0, %rsp分配0xf0字节的堆栈空间; 0xf0 是 (16) 的倍数。如果%rsp不是 16 字节对齐,movaps %xmm7, -0xd0(%rbp) => movaps %xmm7, 0x20(%rsp)。换句话说,SSE寄存器存储在%rsp + 32。如果未对齐,则会引发“一般保护异常”,即段错误。

您可能遇到的另一个问题是读/写-0x170(%rbp)=> 那是-0x80(%rsp),它要么在(或过去?我可能在我的偏移量中)的边界上red zone https://stackoverflow.com/questions/8337783/why-does-gcc-subtract-the-wrong-value-to-the-stack-pointer-when-allocating-a-big。由于这是一个叶函数,因此您可以自由使用它,但不能写过去。

Note:如果你的函数是called,您应该从中减去另外 (8) 个字节%rsp以确保 16 字节对齐。这反过来又会影响偏移量(%ebp).

我在这里并没有根据 ABI 标准进行事实核查,我可能犯了一些错误;所以最好与x86-64 SysV ABI http://www.x86-64.org/documentation/abi.pdf(第 3.2 节)。


解决方案:使用以下命令编译上面的函数-mstackrealign标志明确对齐%rsp到 16 字节边界。我在 OS X 上使用 clang,它在调用约定和对齐要求方面与 x86-64 SysV (x86-64 ELF / Linux) 基本相同:

clang -nostdlib -mstackrealign -c crt1.c

0000000000000000        pushq   %rbp
0000000000000001        movq    %rsp, %rbp
0000000000000004        andq    $0xfffffffffffffff0, %rsp
000000000000000b        subq    $0x170, %rsp
0000000000000012        testb   %al, %al
...

BTW- 这避免了%rbp完全通过使所有加载/存储相对于%rsp。因此,没有使用红色区域 - 至少对于 Apple 的基于 LLVM 3.3 的 clang 来说是这样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clang 使用 -nostdlib 生成崩溃代码 的相关文章

随机推荐

  • boost::unordered_map 是...有序的吗?

    我有一个 boost unordered map 但它看起来是有序的 给我一种压倒性的 你做错了 的感觉 为什么输出是这样的 我希望底层的哈希算法能够随机化这个顺序 include
  • htaccess 重定向非 www http 和 https

    我想要 http example com重定向至 http www example com https example com重定向至 https www example com 以及任何东西http whatever example co
  • Laravel 查询生成器:枢轴不在的地方

    wherePivotIn已提及here https laravel com docs 5 5 eloquent relationships many to many under 通过中间表列过滤关系 但我找不到任何有关相反功能的信息 As
  • 将设备 3D 方向与太阳位置进行比较

    我正在开发一款应用程序 要求用户将 iPhone 对准太阳才能触发特殊事件 我可以基于陀螺仪和 CoreMotion 框架检索设备 3D 方向四元数 从中我可以获得偏航角 滚动角和俯仰角 我还可以根据当前日期和时间 GMT 以及纬度和经度计
  • 使用全局管理员帐户访问 Office 365/SharePoint Online 被拒绝

    自从两天解决问题以来我都快疯了 问题是 我正在制作一个控制台应用程序 它使用全局管理员帐户 在进行新订阅时被指定为管理员的帐户 与 SharePoint Online 进行通信 我想要实现的是 我想使用 CSOM 将自定义操作添加到 Off
  • 如何检测鼠标指针位于浏览器关闭按钮上时的事件? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 换句话说 这是用于检测事件的 javascript jquery 代码当鼠标指针位于浏览器的关闭按钮 X按钮 上时 或者当鼠标指针进入
  • 有没有一种方法可以在不测试整个应用程序的情况下对类库(通用 Windows)进行单元测试?

    我需要进行单元测试Class Library Universal Windows 但是从 添加新项目 窗口中 我只看到了这一点 该项目使用应用程序容器运行所有测试 它始终打开一个应用程序 由于我不需要所有这些开销 我想知道是否有一种方法可以
  • Thymeleaf 文本文字中的下划线

    问题 如何转义文本中的多个连续下划线 我正在使用 HTML 的标准 Thymeleaf 方言 我是not此处使用 Spring 或 SpEL 在 Thymeleaf 中 我可以创建一个下划线作为文字文字 https www thymelea
  • 在 Django 中使用多处理时,应用程序尚未加载,出现异常

    我正在做一个 Django 项目并尝试提高后端的计算速度 该任务类似于 CPU 限制的转换过程 这是我的环境 Python 3 6 1 姜戈 1 10 PostgreSQL 9 6 当我尝试通过 python 多处理库并行计算 API 时
  • 从alertDialog构建器获取editText值

    我是新来的android 我需要得到editText s搜索某些东西的价值 但是当我运行程序时 出现错误null pointer exception EditText etSearch 没有获取它的文本 请帮我 谢谢 public bool
  • 提高 ASP.NET/C# 编译速度的最佳方法是什么?

    更新 请将您的答案集中在硬件解决方案上 您使用什么硬件 工具 插件来提高 ASP NET 编译和首次执行速度 我们正在寻找固态硬盘来加快速度 但现在价格确实很高 我现在有两个 RAID 0 的 7200 rpm 硬盘 但我对性能不再满意 所
  • Bootstrap 中的垂直菜单

    有没有办法使用任何引导类来创建垂直菜单 不是下拉菜单 侧边栏上完全独立的垂直菜单 我可以使用我的 css 创建一个 但只是想知道引导程序中是否有任何内置类 或者可以使用顶部栏通过任何 hack 来完成吗 这个问题现在已经很老了 但如果有人看
  • 在 Asp.net Web API 中处理 CORS 预检

    我的架构中有三个应用程序 它们位于同一服务器上 但具有不同的端口号 A Token Application port 4444 Asp net WebApi B API Application port 3333 Asp net WebAp
  • 如何从对象 URL 获取文件或 blob?

    我允许用户通过拖放和其他方法将图像加载到页面中 当图像被删除时 我正在使用URL createObjectURL转换为对象 URL 以显示图像 我不会撤销该网址 因为我会重复使用它 所以 当需要创建一个FormData对象 以便我可以允许他
  • 尝试使用 fopen() 将文件写入不同的目录

    我正在尝试将文件从一个目录写入另一个目录 例如 http www xxxxxxx com admin upload php http www xxxxxxx com admin upload php to http www xxxxxxx
  • onCreateOptionsMenu(菜单菜单)是什么

    方法中的Menu和menu两个参数是什么onCreateOptionsMenu Menu menu 以及如何使用这个方法 我还有一个问题为什么this参数用于 Intent intent new Intent this DisplayMes
  • 尝试利用?

    我看到我的 nopCommerce 网站记录了以下搜索 ADw script AD4 alert 202 ADw script AD4 我有点好奇他们想要完成什么 我搜索了一下 似乎是ADw script AD4 以 UTF7 编码为
  • C# 中的异步方法如何工作?

    我在我的一些项目中使用异步方法 我喜欢它 因为它使我的应用程序更具可扩展性 但是 我想知道异步方法如何在后台真正工作 NET 或 Windows 如何知道调用已完成 根据我进行的异步调用的数量 我可以看到创建了新线程 但并不总是 为什么 此
  • (jQuery) 在 cookie 中单击时保存复选框状态

    关于此功能有很多主题 但我似乎无法让它工作 我在谷歌上搜索了这个具体案例 有一堆链接让我来到这里 但奇怪的是我似乎无法让它们工作 我所做的唯一工作如下 http dl dropbox com u 2238080 a old z htm ht
  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足