我们正在为客户端架构开发GNU Assembler的端口.现在面临的问题是:
如果指令的立即操作数是涉及多个可重定位符号的表达式,那么它是如何在elf格式的输出文件中处理的.在这种情况下产生的搬迁信息是什么?
例如:
j label1 + label2
Run Code Online (Sandbox Code Playgroud)
其中label1和label2在可重定位部分中定义,它们可能是相同的部分或不同的可重定位部分.
我的意思是可以在Win32和Linux i386中运行单个二进制文件吗?
跟进为什么ELF执行入口点虚拟地址为0x80xxxxx而不是0x0?和为什么Linux程序的虚拟内存地址为0x8048000开始?,为什么我不能ld使用与默认值不同的入口点ld -e?
如果我这样做,我会得到一个segmentation fault返回代码139,即使对于默认入口点附近的地址.为什么?
编辑:
我会更具体地提出这个问题:
.text
.globl _start
_start:
movl $0x4,%eax # eax = code for 'write' system call
movl $1,%ebx # ebx = file descriptor to standard output
movl $message,%ecx # ecx = pointer to the message
movl $13,%edx # edx = length of the message
int $0x80 # make the system call
movl $0x0,%ebx # the status returned by 'exit'
movl $0x1,%eax # eax = code for …Run Code Online (Sandbox Code Playgroud) 我试图通过访问sh_nameelf文件的成员来获取部分名称的正确偏移量,但它一直给我零或null ...
我应该只使用mmap()和elf.h- 没有辅助功能
所以我做了:
void* map_start = mmap(0, fd_stat.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0))
header = (Elf32_Ehdr *) map_start;
secoff = header->e_shoff;
section = (Elf32_Shdr *)(map_start + secoff);
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时:
printf("name offset = %d\n", (section->sh_name));
Run Code Online (Sandbox Code Playgroud)
它一直给我0 ...我做错了什么?
我得到一些符号,我得到一个精灵文件的hexedit.我怎么知道这个符号出现在哪个部分?
strtab和之间有什么不同shstrtab?还有一个符号字符串数组?
当我在名表中获得索引时,它是索引strtab还是shstrtab?
我有兴趣使用Linux头文件提供的unistd.h构建一个没有(g)libc的静态ELF程序.
我已经阅读了这些文章/问题,这些文章/问题粗略地概括了我正在尝试做什么,但并不完全:http: //www.muppetlabs.com/~breadbox/software/tiny/teensy.html
https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free
我有基本代码,它只依赖于unistd.h,其中我的理解是每个函数都是由内核提供的,而且不需要libc.这是我采取的最有希望的道路:
$ gcc -I /usr/include/asm/ -nostdlib grabbytes.c -o grabbytesstatic
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400144
/tmp/ccn1mSkn.o: In function `main':
grabbytes.c:(.text+0x38): undefined reference to `open'
grabbytes.c:(.text+0x64): undefined reference to `lseek'
grabbytes.c:(.text+0x8f): undefined reference to `lseek'
grabbytes.c:(.text+0xaa): undefined reference to `read'
grabbytes.c:(.text+0xc5): undefined reference to `write'
grabbytes.c:(.text+0xe0): undefined reference to `read'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
在此之前,我必须根据内核头文件中的值手动定义SEEK_END和SEEK_SET.否则就会错误地说那些没有定义,这是有道理的.
我想我需要链接到未经剥离的vmlinux来提供符号来使用.然而,我读完了符号,虽然有很多llseeks,但他们并不是llseek逐字逐句.
所以我的问题可以在几个方面:
如何指定ELF文件以使用符号?而且我猜测是否/如何可能,符号将不匹配.如果这是正确的,是否有一个现有的头文件将重新定义llseek和default_llseek或内核中的任何内容?
有没有更好的方法在没有libc的情况下在C语言中编写Posix代码?
我的目标是使用(可能只是)unistd.h编写或移植相当标准的C代码,并在没有libc的情况下调用它.我可能没有一些unistd函数,并且不确定哪些"纯粹"存在于内核调用或不存在.我喜欢集会,但这不是我的目标.希望保持尽可能严格的C(如果必须的话,我可以使用一些外部汇编文件),以便在某些时候允许无libc的静态系统.
谢谢你的阅读!
只是好奇.这显然不是一个非常好的实际编程解决方案,但是我想在Bless(十六进制编辑器)中创建一个可执行文件.
我的架构是x86.我能制作一个非常简单的程序是什么?你好世界?无限循环?与此问题类似,但在Linux中.
我知道有很多关于共享和静态库的用例的问题,这个问题与此无关.我问的是存储在磁盘上的文件格式的差异.
为什么问题是,两者之间有什么区别?或者它们是否完全相同,仅在使用方面有所不同?
我认为它们不一样,因为在共享库上运行'nm'需要-D标志.显然,它需要做一些不同的事情.为什么?
它们都是ELF文件吗?
共享库可以包含某些依赖路径的唯一区别是什么?
我想要发布和归档二进制文件(带有库的可执行文件),它们向后和向前兼容尽可能多的 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-unknown-linux-musl目标编译时,此代码将产生一个.got部分:
fn main() {
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
fn main() {
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
根据针对类似C代码的答案,该.got部分是可以安全删除的工件。但是,它对我来说是段错误:
$ cargo build --release --target x86_64-unknown-linux-musl
$ readelf -S hello
There are 30 section headers, starting at offset 0x26dc08:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[12] .got PROGBITS 0000000000637b58 00037b58
00000000000004a8 0000000000000008 WA 0 0 8
...
Run Code Online (Sandbox Code Playgroud)
看一下反汇编,我发现GOT基本上拥有静态函数地址:
$ objcopy -R.got hello hello_no_got
$ ./hello_no_got
[1] 3131 segmentation fault (core …Run Code Online (Sandbox Code Playgroud)