来自可移植可执行文件和 Windows,我尝试在Linux (Ubuntu AMD64)中使用NASM创建一个小型ELF可执行文件。我的一小段代码如下所示:
BITS 64
; The default virtual address where the executable is linked
_START_VAD equ 0x400000
; Here I write the header byte by byte
ELF_HEADER:
.ident_magic db 0x7f, "ELF"
.ident_class db 2
.ident_data db 1
.ident_version db 1
.ident_osabi db 0
.ident_abiversion db 0
; Pad with zeros until we have 16 bytes for the identifier
times 16-$+ELF_HEADER db 0
.object_type dw 2
.machine dw 0x3e
.version dd 1
.entry_point …Run Code Online (Sandbox Code Playgroud) 我正在尝试找到一种方法来衡量在 ARM 平台上使用 relro 和早期绑定链接选项对启动性能的影响。
有人可以建议我如何找到使用该选项编译的二进制文件链接共享库所花费的时间?
非常感谢。
编辑 1:我的机器上没有时间信息。
root@arm:/# LD_DEBUG=统计信息/bin/date
Run Code Online (Sandbox Code Playgroud)1470: number of relocations: 90 1470: number of relocations from cache: 3 1470: number of relative relocations: 1207 Thu Jan 1 00:17:00 UTC 1970 1470: 1470: runtime linker statistics: 1470: final number of relocations: 108 1470: final number of relocations from cache: 3
我正在使用交叉预链接来预链接使用 Qt 用于嵌入式 ARM 设备的大型 C++ 可执行文件。请注意,我没有使用 Yocto,而是使用自定义发行版 - 因此我目前正在手动运行预链接。
查看 prelink 的输出,它似乎有效:
$ prelink --verbose --ld-library-path=/opt/<product>/lib:/usr/local/Qt-5.3.1/lib --root=$PRODUCT_TARGET_ROOT/<product>/rfs/ /path/to/binary
Laying out 56 libraries in virtual address space 41000000-50000000
Assigned virtual address space slots for libraries:
/lib/ld-linux.so.3 41000000-41027908
/opt/<product>/lib/lib<product>common.so.1 41030000-41cf0fd0
/lib/libc.so.6 442b0000-443e3980
/usr/local/Qt-5.3.1/lib/libQt5Qml.so.5 434f0000-4380ee84
[..]
Prelinking /lib/ld-2.17.so
Prelinking /lib/libc-2.17.so
Prelinking /path/to/binary
Prelinking /<product>/lib/lib<product>common.so.1.0.0
Prelinking /usr/local/Qt-5.3.1/lib/libQt5Qml.so.5.3.1
[..]
Run Code Online (Sandbox Code Playgroud)
当库被加载时,至少 libQt5Qml.so 和 libproductcommon.so 似乎被加载到预链接设置的首选加载地址:
$ cat /proc/`pidof binary`/maps
2ab49000-2ab4a000 r--p 0001e000 07:00 9357 /roroot/lib/ld-2.17.so
2ab4a000-2ab4b000 rw-p 0001f000 07:00 9357 /roroot/lib/ld-2.17.so …Run Code Online (Sandbox Code Playgroud) 已解决: 解决方案是调用personality(0x40000)。请参阅下面评论中的详细信息。
ASLR 标志位于 ELF 文件中的什么位置?我需要禁用特定库 (.so) 的 ASLR。我尝试过使用 objdump 但不知道如何操作。
我无法使用 /proc,因为它似乎不适用于我的 Android 4.4.4,因此我尝试修改二进制文件。
编辑: 我已经编译了以下内容:
#include <stdio.h>
void* getEIP()
{
return __builtin_return_address(0) - 0x5;
}
int main(int argc, char** argv)
{
printf("EIP located at: %p\n", getEIP());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
没有 ASLR (PIE):
arm-linux-androideabi-gcc.exe code.c -o noPIE --sysroot=%NDK%\platforms\android-3\arch-arm
Run Code Online (Sandbox Code Playgroud)
与ASLR(PIE):
arm-linux-androideabi-gcc.exe -fPIE -pie code.c -o withPIE --sysroot=%NDK%\platforms\android-3\arch-arm
Run Code Online (Sandbox Code Playgroud)
noPIE 二进制文件确实没有被随机化,尽管:
# cat /proc/sys/kernel/randomize_va_space
2
Run Code Online (Sandbox Code Playgroud) 当我在终端中运行命令时(使用 El Capitan)
ld -m elf_i386 -T linker.ld -o kernel kasm.o kc.o
Run Code Online (Sandbox Code Playgroud)
它显示以下错误:
ld: warning: option -m is obsolete and being ignored
ld: file not found: elf_i386
Run Code Online (Sandbox Code Playgroud)
有人能帮我解决这个问题吗?
我正在尝试制作一个简单的操作系统内核的上半部分。当像我一样使用 Grub 作为引导加载程序时,还必须有一些下半部分(32 位)代码。因为我想让这个 32 位代码尽可能简短,所以我不想在其中编写一个 ELF 加载程序只是为了加载 64 位代码,因为这显然是荒谬的(这实际上是最常见的解决方案,但我如果可能的话想避免它)。
我发现链接描述文件允许加载与虚拟地址不同的地址。这很有用,这样我就可以加载 64 位部分以适应小型二进制文件,然后使用虚拟内存将正确的虚拟地址映射到它们加载的物理地址。除了低文本部分未放入文本段之外,此方法有效。入口点_start位于本节中。
除非我在命令中指定文本段,否则我无法将低文本部分(所在_start位置)放入文本段中PHDRS。当然,使用此命令使链接器决定放弃生成通常预期的段。当我也这样做时,这些部分最终会重叠,我不完全确定为什么。我按照数据、rodata、文本的顺序指定段,并且这些部分是相同的,但它们的加载内存地址是用rodata和交换的数据分配的,并且所有三个都是重叠的。
这是我的链接器脚本:
ENTRY(_start)
PHDRS {
.low PT_LOAD FILEHDR PHDRS;
.data PT_LOAD;
.rodata PT_LOAD;
.text PT_LOAD;
}
SECTIONS {
. = 1M;
.data_low BLOCK(4K) : ALIGN(4K) {
*(.bss_low)
} : .low
.rodata_low BLOCK(4K) : ALIGN(4K) {
KEEP(*(.multiboot_low))
*(.rodata_low)
} : .low
.text_low BLOCK(4K) : ALIGN(4K) {
*(.text_low)
} : .low
.stack 0xC0000000 : AT(0x200000) ALIGN(4K) {
*(.bootstrap_stack)
} : .data
_LADD_ = …Run Code Online (Sandbox Code Playgroud) 我开始学习为微控制器编写一些底层软件,并且我已经开始研究链接器脚本。
我真的不明白 ENTRY 命令在这种情况下的含义。由于大多数微控制器在预定地址开始执行,因此我们在链接描述文件中选择哪个入口点有什么区别?
我知道我可以在我的(GNU binutils )链接器脚本中定义一个符号/标签,ld只需为符号分配一个地址,如下所示:my_symbol = 0xdeadbeef; 但是,如果我想给该符号一个大小(如0x02)和类型(如OBJECT或FUNC)怎么办?它会显示在符号表 ( .symtab) 中吗?
我将此程序编译-m32 -nostdlib为 ELF 可执行文件:
void _start() {}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,readelf -l我惊讶地发现 LOAD 段上的偏移量是 0x000000,因为这意味着可执行标头将与文本段同时加载到内存中。于是我查了一下GDB,确实是这样:
(gdb) b _start
Breakpoint 1 at 0x8048083
(gdb) r
Starting program: /home/tbodt/ish/build/a.out
Breakpoint 1, 0x08048083 in _start ()
(gdb) x/4c 0x08048000
0x8048000: 127 '\177' 69 'E' 76 'L' 70 'F'
Run Code Online (Sandbox Code Playgroud)
为什么这有用?