c - 与链接器脚本链接时无法执行可执行文件
问题描述
我是链接器脚本概念的新手。所以我尝试使用简单的 c 程序、链接器脚本和内存文件。
我尝试为 ac 程序传递自定义链接器脚本,当我查看生成的内存文件时,我能够看到初始化的变量被放置在链接器脚本中提到的地址处。
但问题是我无法执行为 c 程序生成的可执行文件
这是我的c文件simpleHello.c
#include<stdio.h>
int g1 = 100;
int main(int argc , char *argv[])
{
printf("value of g1 is %d",g1);
return 0;
}
这是我的链接器脚本文件名linker.ld
ENTRY(main)
SECTIONS
{
. = ALIGN(4);
. = 0x0000000000400410;
.text : { *(.text) }
. = 0x0000000000601038;
.data : { *(.data) }
.bss : { *(.bss) }
}
我正在运行以下命令
clang simpleHello.c -g -Wl,-emain,-Map=o.map,-Tlinker.ld -ffreestanding -nostartfiles -nodefaultlibs -L/usr/lib/x86_64-linux-gnu -lc -o simple
如果我跑./simple
分段错误(核心转储)
所以我用 gdb 调试了可执行文件,我得到了这个。
gdb ./simple
Reading symbols from ./simple...done.
(gdb) b main
Breakpoint 1 at 0x40041f: file simpleHello.c, line 9.
(gdb) r
Starting program: Desktop/Memory-Map/programs/simple
Breakpoint 1, main (argc=-134225560, argv=0x1) at simpleHello.c:9
9 printf("value of g1 is %d",g1);
(gdb) bt
#0 main (argc=-134225560, argv=0x1) at simpleHello.c:9
(gdb)
所以问题是 argc 和 argv 还是我通过的链接器文件。?
请为此问题提出一些解决方案。
解决方案
可执行文件的链接描述文件并不是那么简单。您需要为应用程序和操作系统提供各种部分来加载和运行应用程序。
请查看默认链接器脚本:
- 在 Linux 上,它们在
/usr/lib/ldscripts
- 至少在我尝试过的发行版中。 - 在 Windows 上,它们在
<your-installation-path>\mingw64\x86_64-w64-mingw32\lib\ldscripts
- 至少在我尝试过的安装中。
- 在 Linux 上,它们在
您在脚本中放置了类似
0x0000000000400410
for的硬编码地址。.text
您不能这样做,因为我们的临时操作系统会自行决定加载这些部分的位置。
因此,如果您喜欢使用链接器脚本,我建议您复制系统的链接器脚本之一并对其进行编辑。你需要哪一个,我不知道。
可能有一些选项可以让链接器显示它使用哪一个。你可以从一个标准的编译命令和-v
可以给你很多细节的选项开始。但是您肯定需要阅读链接器的文档。
推荐阅读
- c# - c++/WinRT 组件代码中的断点未触发
- reactjs - Module not found: Error: Can't resolve 'core-js/fn/array' React Webpack
- r - R中的多行文本摘要
- facebook - 如果我不属于我,我想通过他们的(posts') id 获取帖子的用户名。那么,我该怎么做呢?
- flutter - Flutter 中的 `Future.delayed(Duration.zero, ...)` 和 `SchedulerBinding.instance.addPostFrameCallback(...)` 有什么区别?
- r - R:在同一个图上绘制一条线和水平条形图
- javascript - 应用脚本中两个数组的求和(Google 表格)
- c++ - 为什么“int const B::bsm1a;” 不考虑重新定义?
- javascript - 使用javascript函数过滤数据返回
- c# - 如果我的数据源是 memoy,我如何在部署期间将我的 sqlite 数据库添加到我的应用程序中