我对这个主题相当陌生,即 ELF 和任何与 Linux 相关的东西。我正在尝试编写 ELF 文件,并且更喜欢在 WinXP 上执行此操作。
我的问题是,这可以用 MS Visual Studio 完成,包括编译吗?据我了解,ELF文件不能在Windows操作系统上编译。好吧,至少这是我在谷歌研究中发现的。我是否必须设置 Linux 操作系统并在那里进行编译?
我可以使用 objdumo(GNU binutils 的一部分)来分析 WindowsXP 上的任何 ELF 文件吗?
非常感谢任何帮助和链接。
我手动编写一个可执行的ELF头+程序头,如下所示:
elf_head:
e_ident db 7Fh, 'ELF', 1, 1, 1
times 9 db 0
e_type dw 2 ; ET_EXEC
e_mach dw 3 ; EM_386
e_ver dd 1 ; EV_CURRENT
e_entry dd 0x08048000+elf_head_len ; entry point
e_phoff dd 34h ; program header table offset
e_shoff dd 00h ; section header table offset
e_flags dd 0 ; flags
e_elfhs dw 34h ; ELF header size
e_phes dw 20h ; program header entry size
e_phec dw 01h ; program header entries count
e_shes dw …Run Code Online (Sandbox Code Playgroud) 我正在调查共享库的重定位,并遇到了一些奇怪的事情。考虑这段代码:
int myglob;
int ml_util_func(int p)
{
return p + 2;
}
int ml_func2(int a, int b)
{
int c = ml_util_func(a);
return c + b + myglob;
}
Run Code Online (Sandbox Code Playgroud)
我将其编译为非 PIC共享库,使用gcc -shared. 我在 x86 上运行的 32 位 Ubuntu 上执行此操作。
结果.so有一个用于调用ml_util_funcin的重定位条目ml_func2。objdump -dR -Mintel这是on的输出ml_func2:
0000050d <ml_func2>:
50d: 55 push ebp
50e: 89 e5 mov ebp,esp
510: 83 ec 14 sub esp,0x14
513: 8b 45 08 mov eax,DWORD PTR …Run Code Online (Sandbox Code Playgroud) 全局偏移表(ELF)的结构是什么样的。我想了解动态链接。任何人都可以告诉我们数据结构是什么样子的吗?我不知何故从未在网上找到过它。
是否可以在不同的程序类型之间共享 ebpf 映射。我需要在 tc-bpf 程序和 cgroup bpf 程序之间共享一个映射。如果映射被固定到充当全局命名空间的文件系统,这应该是可能的。但是,我没有得到这个工作。
该映射由 tc-bpf 程序创建并固定到全局命名空间。由于是 tc-bpf 程序,所以映射的类型是 struct bpf_elf_map。这个 bpf 程序是通过 iproute2 加载的。
现在,我有一个应该访问此映射的 cgroup bpf 程序,但由于它是通过 user.c (libbpf) 或 bpftool 而不是 iproute 加载的,因此此处定义的映射不能是“bpf_elf_map”,但它是结构bpf_map_def。所以在 cgroup bpf 程序中,相同的映射被定义为 struct bpf_map_def 而不是 struct bpf_elf_map。
可能正因为如此,当我转储地图(并且不共享预期的地图)时,cgroup 程序会获得一个新的 map_id,理想情况下,当同一个地图在 bpf 程序之间共享时,这些 bpf 程序将具有与其唯一关联的相同 map_id prog_ids。
在控制段上的可执行位的过程中,我发现了PT_GNU_STACK加载程序如何使用的一个巨大的怪癖。
根据elf(5)联机帮助页,PT_GNU_STACK用作:
GNU 扩展,Linux 内核使用它通过 p_flags 成员中设置的标志来控制堆栈的状态。
该execstack手册页,也支持这一点:
... ELF 二进制文件和共享库现在可以标记为需要或不需要可执行堆栈。此标记是通过 PT_GNU_STACK 程序头条目中的 p_flags 字段完成的。
但是,除了设置堆栈可执行文件之外,当我设置该位时,几乎所有段都变为可执行文件。
例如,当我运行时sleep,我得到了这个内存映射
sleep 100 & cat /proc/$!/maps
[1] 1260
561460d8d000-561460d94000 r-xp 00000000 08:01 524383 /bin/sleep
561460f94000-561460f95000 r--p 00007000 08:01 524383 /bin/sleep
561460f95000-561460f96000 rw-p 00008000 08:01 524383 /bin/sleep
561462eca000-561462eeb000 rw-p 00000000 00:00 0 [heap]
7f02b08b9000-7f02b0b97000 r--p 00000000 08:01 1966102 /usr/lib/locale/locale-archive
7f02b0b97000-7f02b0d7e000 r-xp 00000000 08:01 655384 /lib/x86_64-linux-gnu/libc-2.27.so
7f02b0d7e000-7f02b0f7e000 ---p 001e7000 08:01 655384 /lib/x86_64-linux-gnu/libc-2.27.so
7f02b0f7e000-7f02b0f82000 r--p …Run Code Online (Sandbox Code Playgroud) 我想了解动态加载程序如何为 ELF 段创建映射的详细信息。
考虑一个与 GNU ld 链接的小型共享库。程序头是:
类型偏移 VirtAddr PhysAddr FileSiz MemSiz Flg Align 加载 0x000000 0x0000000000000000 0x0000000000000000 0x00095c 0x00095c RE 0x200000 负载 0x000df8 0x0000000000200df8 0x0000000000200df8 0x000250 0x000258 RW 0x200000 动态 0x000e08 0x0000000000200e08 0x0000000000200e08 0x0001d0 0x0001d0 RW 0x8 GNU_EH_FRAME 0x000890 0x0000000000000890 0x0000000000000890 0x00002c 0x00002c R 0x4 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10 GNU_RELRO 0x000df8 0x0000000000200df8 0x0000000000200df8 0x000208 0x000208 R 0x1
这个共享对象可以打印它在 ( /proc/self/maps) 中加载的进程的映射,片段:
7fd1f057b000-7fd1f057c000 r-xp 00000000 fe:00 12090538 /path/libmy.so 7fd1f057c000-7fd1f077b000 ---p 00001000 fe:00 12090538 /path/libmy.so 7fd1f077b000-7fd1f077c000 …
我制作了这个简单的 ELF 用于学习目的:
bits 64
org 0x08048000
elfHeader:
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
db 0 ; abi version
times 7 db 0 ; unused padding
dw 2 ; e_type
dw 62 ; e_machine
dd 1 ; e_version
dq _start ; e_entry
dq programHeader - $$ ; e_phoff
dq 0 ; e_shoff
dd 0 ; e_flags
dw elfHeaderSize ; e_ehsize
dw programHeaderSize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw …Run Code Online (Sandbox Code Playgroud) 我正在编译一个简单的汇编代码(Intel 语法、x86、Linux)打印“Hello World!”。这里是:
SECTION .rodata
msg: db 'Hello world!', 0xA
msg_len: equ $ - msg
SECTION .text
global _start
_start:
mov eax, 4 ; `write` system call
mov ebx, 1 ; to stdout
mov ecx, msg
mov edx, msg_len
int 0x80
mov eax, 1 ; `exit` system call
xor ebx, ebx ; exit code 0
int 0x80
Run Code Online (Sandbox Code Playgroud)
我使用以下命令编译它:
SECTION .rodata
msg: db 'Hello world!', 0xA
msg_len: equ $ - msg
SECTION .text
global _start
_start:
mov eax, 4 ; …Run Code Online (Sandbox Code Playgroud) elf ×10
linux ×7
assembly ×3
glibc ×2
binutils ×1
bpf ×1
ebpf ×1
executable ×1
file-format ×1
gnu ×1
iproute ×1
kernel ×1
ld ×1
linker ×1
linux-kernel ×1
objdump ×1
relocation ×1
unix ×1