我知道我们有.dynsym和.symtab,我如何区分导入和导出,就像在 Windows 中的 pe 中一样,导入和导出在数据目录中,它和 elf 中的等效吗?
我正在尝试使用 x86_64 上的链接器脚本更改堆栈的起始位置。我能够使用这个移动我的可执行起始地址:
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x200000)); . = SEGMENT_START("text-segment", 0x200000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)
我像这样改变了我的全局变量:
.data ALIGN(0x10000000) :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用以下内容来移动堆栈区域:
. = 0x50000000;
.stack :
{
stack_start = .;
PROVIDE( stack_start = . );
*(.stack)
. += 0x2000;
stack_end = . ;
PROVIDE( stack_end = . );
}
Run Code Online (Sandbox Code Playgroud)
但这并没有让我去任何地方。
这是我用来测试堆栈位置的测试程序:
#include <stdio.h>
#include <stdlib.h>
int global_var = 555;
void test()
{
int local_test = 666;
printf("address of global_var: %p\n", &global_var);
printf("address of local_test: %p\n", &local_test); …Run Code Online (Sandbox Code Playgroud) 我在这里检查了 ELF 规范http://www.cs.cmu.edu/afs/cs/academic/class/15213-f00/docs/elf.pdf但是,没有提到任何区别。
我有一个较旧的二进制可执行文件(utserver,闭源),我试图在运行 Fedora 22 的系统上运行它。
utserver 需要 openssl_1.0.0 - F22 提供 openssl_1.0.1k
我做了两个符号链接:
$ sudo ln -s /usr/lib64/libssl.so.1.0.1k /usr/lib64/libssl.so.1.0.0
$ sudo ln -s /usr/lib64/libcrypto.so.1.0.1k /usr/lib64/libcrypto.so.1.0.0
Run Code Online (Sandbox Code Playgroud)
但是尝试运行 utserver 会抱怨库版本:
$ ./utserver
./utserver: /lib64/libcrypto.so.1.0.0: version `OPENSSL_1.0.0' not found (required by ./utserver)
./utserver: /lib64/libssl.so.1.0.0: version `OPENSSL_1.0.0' not found (required by ./utserver)
Run Code Online (Sandbox Code Playgroud)
好的,所以它正在寻找一个版本字符串。我编辑了 utserver ELF 以将字符串 OPENSSL_1.0.0 更改为 OPENSSL_1.0.1,但出现相同的错误(未找到“OPENSSL_1.0.1”)
objdump 和 readelf 都显示 OPENSSL_1.0.1 存在于 libssl.so.1.0.1 的版本区域中:
$ objdump -p /lib64/libssl.so.1.0.1 | grep OPENSSL
3 0x00 0x066a2b21 OPENSSL_1.0.1
4 0x00 0x02b21533 OPENSSL_1.0.1_EC
0x02b21533 0x00 07 …Run Code Online (Sandbox Code Playgroud) ELF 可执行文件有一个固定的加载地址(32 位 x86 Linux 二进制文件为 0x804800,64 位 x86_64 二进制文件为 0x40000)。
我阅读了关于这些特定地址的历史原因的 SO 答案(例如,this one)。我仍然不明白的是为什么要使用固定的加载地址而不是随机的地址(给定一些范围内要随机化)?
我有静态链接的二进制文件(ELF 文件),它没有动态段、.dymsym 部分,也不执行 LD_PRELOAD 命令等。我如何创建假虚拟动态段来激活动态加载程序并执行 LD_PRELOAD 命令?
我想手工编写一个ELF文件。我怎样才能让我的elf文件调用c标准库。我知道内核搜索 PT_INTERP 程序头并阅读“/lib/ld-linux.so.2”,我知道全局偏移表(GOT)和过程链接表(PLT)。
但我不知道如何执行带有 PT_INTERP phdr、GOT、PLT 的 ELF 文件并调用 C 库。我需要以二进制形式了解它以帮助我创建一个手工制作的 ELF。
我对这个有问题。我使用 ARM Cortex-A9 和 DS-5 来创建裸机固件。我修改了我的链接器文件,故意将 .data 部分 LMA 与 text 和 Rodata 部分相邻,因为它的默认运行时 VMA 位于 1MB 之外,而 .bin 图像大约为 1MB,但包含 90% 的零。所以我特意制作了 LMA != VMA 以节省空间。我还在 start.S 中添加了一个代码,它将 .data 部分从它的 lma 重新定位到 vma。
然而,在 DS-5 中加载生成的 elf 文件时,它已经将所有部分加载到它们的 VMA。结果,我的 start.S 代码应该重新定位数据,从带有垃圾内容的 LMA 复制到已经正确的 VMA,不久之后这些垃圾导致了错误。
我在 Cortex-M4 中使用过二进制不相等的 VMA 和 LMA,并使用 gdb 进行精灵调试,那里没有问题,但它是微控制器。在我当前的 arm 处理器应用程序中,我将如何在 elf 中模拟调试将数据从其 LMA 正确复制到 VMA 的场景。很可能在使用二进制格式独立启动时不会有问题,但现在我们仍在 elf 调试中,所以我必须解决这个问题。
出于特定原因,我需要将.text部分放在 ELF 文件的最后。
我试图以这种方式实现这一目标:
我采用了默认的大链接脚本并将.text部分移到了部分的最后SECTIONS { ... }。
$ readelf -S beronew
[ #] Name Type Address Offset
Size Size.Ent Flags - - Alignment
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .data PROGBITS 00000000006000b0 000000b0
000000000000003b 0000000000000000 WA 0 0 1
[ 2] .text PROGBITS 0000000000a000f0 000000f0
00000000000003e9 0000000000000000 AX 0 0 1
[ 3] .shstrtab STRTAB 0000000000000000 000004d9
0000000000000027 0000000000000000 0 0 1
[ 4] .symtab SYMTAB 0000000000000000 …Run Code Online (Sandbox Code Playgroud) 我试图从 Linux 程序的 elf 文件中提取特定的字符串变量(即符号),甚至从它来自的 .o 中提取。它在 .rodata 部分,显然我知道符号名称。是否有一系列 objdump 样式的命令和选项可用于转储字符串?
更新:
例如,.map 文件包括:
.rodata.default_environment 0x000000001013f763 0x615 common/built-in.o
0x000000001013f763 default_environment
Run Code Online (Sandbox Code Playgroud)
变量本身 - default_environment- 是标准的以空字符结尾的文本字符串。