无.interp段的libonload.so为何具备可执行性?
为什么无.interp段的libonload.so可直接执行?
我了解libc.so可执行的原因如下:
libc.so拥有入口点函数libc.so中存在.interp段
查阅资料得知,.interp段被认为是可执行共享对象的必要条件,但我发现libonload.so(SolarFlare网卡驱动)可直接执行,而readelf显示其无.interp段,无法理解其运行机制。
执行libonload.so的结果
[root@localhost onload-7.1.1.75]# /usr/lib64/libonload.so Onload 7.1.1.75 Copyright 2019-2021 Xilinx, 2006-2019 Solarflare Communications, 2002-2005 Level 5 Networks Built: Mar 4 2024 15:49:30 (release) Build profile header: <ci/internal/transport_config_opt_extra.h>
readelf -l /usr/lib64/libonload.so的输出
[root@localhost onload-7.1.1.75]# readelf -l /usr/lib64/libonload.so Elf file type is DYN (Shared object file) Entry point 0xa2e0 There are 8 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x00000000000a5ff0 0x00000000000a5ff0 R E 200000 LOAD 0x00000000000a6818 0x00000000002a6818 0x00000000002a6818 0x0000000000002770 0x0000000000003060 RW 200000 DYNAMIC 0x00000000000a6d90 0x00000000002a6d90 0x00000000002a6d90 0x00000000000001f0 0x00000000000001f0 RW 8 NOTE 0x0000000000000200 0x0000000000000200 0x00000000000000200 0x0000000000000024 0x0000000000000024 R 4 TLS 0x00000000000a6818 0x00000000002a6818 0x00000000002a6818 0x0000000000000000 0x0000000000000bec R 8 GNU_EH_FRAME 0x0000000000094684 0x0000000000094684 0x0000000000094684 0x000000000000245c 0x000000000000245c R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x00000000000a6818 0x00000000002a6818 0x00000000002a6818 0x00000000000007e8 0x00000000000007e8 R 1 Section to Segment mapping: Segment Sections... 00 .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .plt .text .rodata .eh_frame_hdr .eh_frame 01 .init_array .data.rel.ro .dynamic .got .got.plt .data .bss 02 .dynamic 03 .note.gnu.build-id 04 .tbss 05 .eh_frame_hdr 06 07 .init_array .data.rel.ro .dynamic .got
我的测试过程
参照onload源码编写了示例程序:
#include <sys/uio.h> #include <linux/unistd.h> #include <unistd.h> int my_do_syscall3(int num, long a1, long a2, long a3) { int rc; __asm__ __volatile__( "syscall" : "=a" (rc) : "0"((long)num), "D"(a1), "S"(a2), "d"(a3) : "r11","rcx","memory" ); return rc; } #define my_syscall3(call, a1, a2, a3) \ my_do_syscall3(__NR_##call, (a1), (a2), (a3)) extern "C" int func() { struct iovec v[1]; static const char msg0[] = "Hello so\n"; v[0].iov_base = (void*) msg0; v[0].iov_len = sizeof(msg0)-1; my_syscall3(writev, STDOUT_FILENO, (long) v, 1); my_syscall3(exit, 0, 0, 0); return 0; }
编译命令:
gcc -fPIC -shared -e func test.cpp -o libtest.so
执行./libtest.so时出现段错误。随后添加.interp段:
extern const char elf_interpreter[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
重新编译后程序正常运行。最后给my_do_syscall3添加static修饰符后,程序无需.interp段也能正常运行。想了解libonload.so无需.interp段即可执行的原理。
内容的提问来源于stack exchange,提问作者Frank Liu
相关产品推荐
相关产品推荐

