我正在拆解可执行文件:
(gdb) disas main
Dump of assembler code for function main:
0x004012d0 <main+0>: push %ebp
0x004012d1 <main+1>: mov %esp,%ebp
...
Run Code Online (Sandbox Code Playgroud)
每次内存地址相同:0x004012d0.
操作系统不是要动态分配的内存地址吗?
UPDATE
现在我看到它的虚拟空间,它可以在某些平台上随机化.
有人可以发布更改的gdb转储吗?
我正在开发一个基于arm9处理器的项目.我们只使用裸机而没有任何操作系统,所以很遗憾我们还不支持共享库/动态加载器.
我希望能够从SD卡加载库,也可以从主应用程序调用函数.
我的第一次尝试是使用链接器覆盖功能(将库放在特定的绝对定位部分),但是这里有一个问题,就像前面提到的那样调用主应用程序函数 - >每次更改主应用程序时都需要重新编译库能够回调.
根据这个我的事情,我将不得不编写自己的动态加载器,但我是这个领域的新手.可以请有人给我任何一个例子如何处理它或如何开始这样的项目?我们正在使用gcc作为arm-elf目标.
尊重Jan
我想要发布和归档二进制文件(带有库的可执行文件),它们向后和向前兼容尽可能多的 Linux 发行版,并且整个包可重定位。libc据我了解,还需要提供系统库,因为给定不同版本的libc. 同时libc似乎是耦合的ld-linux
(例如,在 Debian 测试上编译的二进制文件已经无法在 Ubuntu 18.04 LTS 上工作),所以我ld-linux也需要打包。
我的解决方案是将所有可执行文件和库放入一个目录并将 rpath 设置为$ORIGIN(通过使用 链接-Wl,rpath=$ORIGIN或设置chrpath或patchelf)。这使得库可以与可执行文件一起重定位,并且适用于除ld-linux链接器本身之外的所有库。
可以通过以下方式更改动态链接器路径-Wl,--dynamic-linker=/my/path/ld-linux.so或设置它patchelf,但路径必须是绝对路径:
$ORIGIN不起作用./有效,但仅当当前目录与加载器本身相同时才有效(从其他地方启动时,可执行文件会因错误而崩溃)/my/path/ld-linux.so /my/path/myexecutable $@,但这意味着我想避免另一层间接和开销。有没有办法将ld-linux相对于可执行文件的路径直接设置为可执行文件?
也许有一种方法可以静态链接 ld-linux 加载程序?
因此x86-64具有RIP相对地址,这使得PIC代码易于编写,重定位所需的更少.为什么在x86-64上仍然需要重定位?有什么功能?我可以尝试探索objdump但是要编译哪些C/C++代码模式?
我目前无法理解PE Base Relocations的构建方式.
我知道可以有一个以上的重定位,我也理解为什么以及如何完成这个,但我只是不能以编程方式理解它:
以下哪项是正确的(WinNT.h中的IMAGE_BASE_RELOCATION)?
// Base relocation #1
DWORD VirtualAddress;
DWORD SizeOfBlock; // size of current relocation
WORD TypeOffset[1];
// Base relocation #2
DWORD VirtualAddress;
DWORD SizeOfBlock; // size of current relocation
WORD TypeOffset[1];
// Base relocation #3
DWORD VirtualAddress;
DWORD SizeOfBlock; // size of current relocation
WORD TypeOffset[1];
Run Code Online (Sandbox Code Playgroud)
要么
DWORD VirtualAddress;
DWORD SizeOfBlock; // size of all relocations
WORD TypeOffset[1]; // relocation #1
WORD TypeOffset[1]; // relocation #2
WORD TypeOffset[1]; // relocation #3
Run Code Online (Sandbox Code Playgroud)
或者都不正确?我该如何以编程方式遍历所有基址重定位?
目前我有这个代码,似乎在某处不正确:
DWORD baseRelocationSize = …Run Code Online (Sandbox Code Playgroud) 全局偏移表(GOT):用于重定位ELF符号(实现GCC),它有助于共享相同的二进制文件,而不需要为每个进程进行任何特定链接.因此减少了存储器中相同二进制图像的副本.
我的问题是,有没有办法禁用R_386_GOT32,R_386_GOTOFF在可重定位的ELF图像中键入重定位条目?我的意思是,我可以强制GCC使用R_386_PC32或R_386_32键入重定位而不是GOT类型重定位吗?
如果没有,你能解释实施GOT的方式吗?我正在为ELF编写动态链接和加载库.
编辑:
参考链接
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-74186.html
http://man7.org/linux/man-pages/man8/ld.so.8 .html
http://wiki.osdev.org/ELF
首先:我不是专家,所以请原谅我试图解释自己的任何错误.
我正在尝试使用Sparc-为SPARC机器交叉编译外部Linux模块Linux-GCC-4.4.2.Linux内核的版本是2.6.36.4-00037-g059aa91-dirty.它已经使用LEON处理器中的一些文件进行了修补.构建流程提供给我和它使用LinuxBuild,Buildroot和Busybox.我正在尝试制作32位操作系统.
一切似乎都有效,但在我编译模块并尝试将其发送到SPARC系统后,我收到此错误:
module hellok: Unknown relocation: 6
Run Code Online (Sandbox Code Playgroud)
这个错误来自于~/linuxbuild-1.0.3/linux/linux-2.6-git/arch/sparc/kernel/module.c
我将为完整性提供整个方法:
int apply_relocate_add(Elf_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
unsigned int i;
Elf_Rela *rel = (void *)sechdrs[relsec].sh_addr;
Elf_Sym *sym;
u8 *location;
u32 *loc32;
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
Elf_Addr v;
/* This is where to make the change */
location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ …Run Code Online (Sandbox Code Playgroud) 我注意到ARM 64位程序集的GNU asm 重定位语法.什么是喜欢那件#:abs_g0_nc:和:pg_hi21:?他们在哪里解释?他们是否有一种模式,或者他们是否在旅途中弥补?我在哪里可以了解更多?
假设我fn在.textELF64可执行文件的某个部分中有某个功能.有没有办法知道fn函数所在的ELF文件的起始位置(以字节为单位)?请注意,我不需要知道它在链接时重定位的VA,而是它在ELF文件中的位置.
我试图更好地理解 Linux 中的运行时重定位,特别是谁在不同情况下执行它们。以下是我目前的理解,是否准确?
ld.so) 加载库,然后执行重定位ld.so是一个自重定位的二进制文件谢谢
relocation ×10
elf ×5
assembly ×2
disassembly ×2
executable ×2
linux ×2
arm ×1
bare-metal ×1
dynamic-data ×1
function ×1
gcc ×1
installation ×1
intel ×1
linux-kernel ×1
portability ×1
sparc ×1
x86 ×1
x86-64 ×1