- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编译文件 stacktrace.d:void main(){assert(false);}
关闭 ASLR,运行时我得到:
core.exception.AssertError@stacktrace.d(2): Assertion failure
----------------
??:? _d_assertp [0x55586ed8]
??:? _Dmain [0x55586e20]
objdump -t stacktrace|grep _Dmain
给出
0000000000032e0c w F .text 0000000000000019 _Dmain
如果我运行gdb -q -nx -ex start -ex 'disas/rs _Dmain' -ex q stacktrace
:
...
Dump of assembler code for function _Dmain:
0x0000555555586e0c <+0>: 55 push %rbp
0x0000555555586e0d <+1>: 48 8b ec mov %rsp,%rbp
=> 0x0000555555586e10 <+4>: be 02 00 00 00 mov $0x2,%esi
0x0000555555586e15 <+9>: 48 8d 3d 44 c0 02 00 lea 0x2c044(%rip),%rdi # 0x5555555b2e60 <_TMP0>
0x0000555555586e1c <+16>: e8 47 00 00 00 callq 0x555555586e68 <_d_assertp>
0x0000555555586e21 <+21>: 31 c0 xor %eax,%eax
0x0000555555586e23 <+23>: 5d pop %rbp
0x0000555555586e24 <+24>: c3 retq
因此,即使前两个 0x55 字节被截断,堆栈跟踪中给出的 0x...86e20 也与指令的开头不匹配。
最佳答案
好的,我刚刚从评论中找到了证明我直觉的源代码部分。
这是添加时的 git 责任:https://github.com/dlang/druntime/blame/bc940316b4cd7cf6a76e34b7396de2003867fbef/src/core/runtime.d#L756
唉,提交消息并不是非常丰富,但代码本身,加上我的内存,让我非常确信。
这就是 druntime
库中的文件 core/runtime.d
。截至撰写本文时,它恰好位于第 756 行
enum CALL_INSTRUCTION_SIZE = 1; // it may not be 1 but it is good enough to get
// in CALL instruction address range for backtrace
callstack[numframes++] = *(stackPtr + 1) - CALL_INSTRUCTION_SIZE;
请注意,抛出异常时,callstack
变量会生成当前调用的副本。当请求实际将其写出时,跟踪打印机将查看该数组以确定要写入的内容。 (看,查找调试信息以打印文件/行号和函数名称真的很慢,所以它只在必须时才这样做,以保持正常的异常使用 - 当它被抛出并稍后捕获时 - 更快。)
无论如何,我记得回溯曾经打印过错误的行。它将打印包含下一条指令的代码行 - 这可能在源代码中距实际的断言/抛出语句相当远,使得打印的帮助不大。如果您查看 git Blame 链接,您会看到旧代码用于直接从堆栈中复制地址。
call
指令的工作原理是将返回地址压入堆栈,然后跳转到子例程地址。返回地址紧接在调用指令之后,因此当CPU返回那里时,它不会再次运行调用。这就是为什么旧代码会显示错误的行号,错误地将责任归咎于以下指令。
新代码会稍微倒回该地址,使其返回到调用指令本身 - 从而将打印的函数放在它所属的行上。但是,在 x86 上,有一些不同的调用指令,我什至不确定是否可以正确倒回 - 您只能通过查看操作码来确定指令的实际大小,只有当您知道指令的大小,或者像CPU本身一样按正向顺序读取代码时,您才知道操作码在哪里。此外,在其他处理器架构上,大小也会有所不同。
就像该行中的评论所说,我们实际上不必做到完美。此回溯的目标是让用户查看正确的位置。调试信息使用一种边界框 - 如果您位于该函数或源代码行的起始地址或之后,但尚未到达下一个函数/行的起始地址,则它认为您在那里。它不知道也不关心代码的小数行。
因此,只需假设大小为 1 - 足以使其回到该边界,就大大简化了实现。
我敢打赌,gdb 在内部做了类似的事情,只是它的打印机隐藏了这一点,直接在其回溯中显示堆栈的返回地址。 (顺便说一句,有趣的提示:在 gdb 中运行程序时,将 --DRT-trapExceptions=no
传递给程序的命令行参数。然后,它会在程序仍在运行时捕获抛出点,而不是打印消息并说程序退出并显示代码 1!)
druntime 打印代码也可以在打印之前返回 +1 以隐藏这个内部实现黑客......但是,嗯。返回地址也不是实际发生调用的位置,无论如何,您都需要在反汇编程序中查看上面的内容。甚至 gdb 实际上也不显示调用的地址(至少不是我的旧版本,也许新版本会显示)。但如果它是 grep 反汇编中的一个值,那可能会很好,不管怎样......如果你想向 druntime 做一个 PR,我会支持你(注意我在那里没有权限,但可以帮助评论)。
但这至少明确地解释了现状。
关于assembly - DMD 堆栈跟踪中的地址有何含义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54550999/
我编译文件 stacktrace.d:void main(){assert(false);} 关闭 ASLR,运行时我得到: core.exception.AssertError@stacktrace
我正在尝试在 Windows 中使用 DMD 编译器本身(没有 IDE)构建一个项目。而且我发现自己几乎无法意识到有关链接的某些时刻。通常 IDE 会为我做这件事。 我的项目结构 project ├─
我目前正在试用DerelictSDL2 (绑定(bind)到 D 的 SDL2 库)并且我编写了一个成功加载 JPG 图像并将其显示在窗口中的代码。也就是说,当它使用 dmd 编译时。当我尝试使用 g
我可以测试 DMD 是否正在使用 version(DMD){} 编译给定的代码,但我如何检查它的哪个版本? (2.66/2.65 等) 更简洁地说,我想检查 @nogc修饰符存在, 如果不是 - 定义
根据 http://dlang.org/statement.html 的“Foreach 限制”部分以下代码 int[] a; int[] b; foreach (int i; a) { a
有时 SciTE(以及程序员记事本)会停止处理 DMD.exe 输出的错误消息。 我发现,他们都无法跳转到 game.d 中的第 81 行:“game.d(81):一些错误” 而这个有效:“game.
这里我想锁步迭代两个 size_t 数组 import std.stdio; import std.range; import std.exception; import std.conv; stru
人们一直试图用旧版本的 Dmd 和 Dub(0.9.2 而不是 1.0.0)来构建我的项目,但它不起作用。我可以在 dub.json 文件中指定所需的最小配音版本吗? 最佳答案 不幸的是你不能。见 t
我有一个名为“dprogram.d”的 d 源文件,并在 mac osx 的终端中使用命令 $ dmd dprogram.d 创建一个可执行文件。根据官方文档,编译器将自动编译源代码并链接 .o 目标
根据 http://dlang.org/statement.html 的“Foreach 限制”部分以下代码 int[] a; int[] b; foreach (int i; a) { a
我是 D 编程新手。选择 DMD (2.061) 或 GDC(4.6、4.7 或 4.8,快照)的优缺点是什么?我应该选择哪个 GDC 版本?我已经成功构建了 GCC-4.8 和 GDC-4.8 的最
我在 D 中有一个模板类,它以另一个模板作为参数,它是这样开始的: class RuleVars(alias RuleType, RuleRange, SubstitutionRange) if (_
我有一个名为“dprogram.d”的 d 源文件,并在 mac osx 的终端中使用命令 $ dmd dprogram.d 创建一个可执行文件。根据官方文档,编译器将自动编译源代码并链接 .o 目标
每当我使用 DMD 构建静态库时,我都能够将它链接到我的应用程序并且编译正常,但是在应用程序中调用库的任何时候我都会得到: Segmentation fault (core dumped) 为了构建我
我正在尝试安装 DMD,因此完全遵循此页面上提供的建议:http://dlang.org/dmd-osx.html .但是,当我尝试构建 .d 文件时出现错误: 这是我的hello.d import
我有 Solaris 10 + Zenoss 2.7.0,如果没有 Oracle 许可证,我无法升级它,因此我尝试寻找解决方法,这就是我请求您帮助的原因。 对于过去 5 分钟内收到的来自同一设备的任何
我只是从 http://www.digitalmars.com/d/download.html 安装了 DMD 编译器对于 Ubuntu 64 位 (dmd_2.055-0_amd64.deb)。但是
有人在 Snow Leopard 上试过 Digitalmars D 编译器(第 2 版)吗?我想升级,但我宁愿有一个可用的 D 编译器。 最佳答案 如果您仍然不确定,请深呼吸并开始尝试: Chang
我想部分等效的问题:使用 DMD 编译的代码是否应该在所有情况下使用 GDC 自动编译? 我问是因为我在从 ubuntu 10.4(看似循环依赖,叹气)存储库安装现代版本的 GDC 时遇到问题。 最佳
当我import etc.c.curl; DMD 告诉我 Warning 2: File Not Found curl.lib 这个 curl.lib 在哪里? (我尝试了 http://curl.h
我是一名优秀的程序员,十分优秀!