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 生成崩溃代码 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 如何在没有 Control.Invoke() 的情况下从后台线程修改控件属性

    最近 我们遇到了一些旧版 WinForms 应用程序 我们需要更新一些新功能 在专家测试该应用程序时 发现一些旧功能被破坏 无效的跨线程操作 现在 在您认为我是新手之前 我确实有一些 Windows 窗体应用程序的经验 我不是专家 但我认为
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 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 除了满足