可执行文件的ELF文件有一个程序(段)标题和一个节头,可以看到readelf -a,这是一个例子:


上面的两张图分别是节标题和节目(段)标题.可以看出,段头由若干段头组成,用于将程序加载到存储器中.
是否只需将.text,.rodata,.data,.bss部分加载到内存中?
段中的所有其他部分(例如,第3段中的.ctors,.dtors .jcr)是否用于对齐?
嗨我正在为我正在编写的编译器生成x86程序集,并且在我的64位VM上链接文件时遇到一些问题(汇编代码是32位).
我能够使用此命令组合目标文件:
as --32 mult.S -o mult.o
Run Code Online (Sandbox Code Playgroud)
但我似乎无法找到任何选项ld,使它生成一个32位的ELF文件:
ld <some-option?> mult.o -o mult
Run Code Online (Sandbox Code Playgroud)
任何帮助都会很棒.
我在Linux x86_64上试验ELF可执行文件和gnu工具链:
我已经链接并剥离(手工)"Hello World"测试.:
.global _start
.text
_start:
mov $1, %rax
...
Run Code Online (Sandbox Code Playgroud)
到一个267字节的ELF64可执行文件...
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
0000010: 0200 3e00 0100 0000 d400 4000 0000 0000 ..>.......@.....
0000020: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
0000030: 0000 0000 4000 3800 0100 4000 0000 0000 ....@.8...@.....
0000040: 0100 0000 0500 0000 0000 0000 0000 0000 ................
0000050: 0000 4000 0000 0000 0000 4000 0000 0000 ..@.......@.....
0000060: 0b01 0000 0000 0000 0b01 0000 …Run Code Online (Sandbox Code Playgroud) 这是我在Mac OS X上使用clang ++面临的问题的缩小版本.这是经过严格编辑以更好地反映真正的问题(第一次尝试描述问题并没有表现出问题).
我在C++中有一大块软件,在目标文件中有大量符号,所以我-fvisibility=hidden用来保持我的符号表小.众所周知,在这种情况下,必须特别注意vtable,我想我遇到了这个问题.然而,我不知道如何以一种令gcc和clang取悦的方式优雅地解决它.
考虑一个base具有向下转换运算符as的derived类,以及包含一些有效负载的类模板.pair base/ derived<T>用于实现类型擦除:
// foo.hh
#define API __attribute__((visibility("default")))
struct API base
{
virtual ~base() {}
template <typename T>
const T& as() const
{
return dynamic_cast<const T&>(*this);
}
};
template <typename T>
struct API derived: base
{};
struct payload {}; // *not* flagged as "default visibility".
API void bar(const base& b);
API void baz(const base& b);
Run Code Online (Sandbox Code Playgroud)
然后我有两个不同的编译单元提供类似的服务,我可以将其近似为相同功能的两倍:向下转换base为derive<payload>:
// bar.cc
#include "foo.hh" …Run Code Online (Sandbox Code Playgroud) 我想将一些用户定义的数据放入自定义部分,以便同时由应用程序和离线分析器读取.假设以下示例:
const int* get_data()
{
__attribute__((section(".custom")))
static const int data = 123;
return & data;
}
inline const int* inline_get_data()
{
__attribute__((section(".custom")))
static const int inline_data = 123;
return & inline_data;
}
int main()
{
(void) get_data();
(void) inline_get_data();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
的价值data和inline_data将出现在部分.custom.Clang编译此示例并生成正确的结果,就像MSVC一样,当它__attributes__被相应的编译指示替换时.
不幸的是,GCC 5.2给出了以下错误:
error: inline_data causes a section type conflict with data
Run Code Online (Sandbox Code Playgroud)
这个问题归结为一个事实,即这两个变量具有不同的链接(data在一节标记与a,的部分inline_data将被标记aG).如果第二个函数没有标记为内联但是模板(GCC 5.2编译它),则GCC 4.9会以相同的方式失败.
如果临时更改了一个部分名称并在生成的程序集中手动修复,GCC 5.2也会编译正常.
这个问题有没有已知的解决方法?我无法控制函数签名, …
我有一个ELF目标文件.我想知道它包含哪种类型的调试信息.它是用PPC架构的Diab编译器(C源代码)编译的.我很确定它是用调试符号构建的.
我试过提取调试信息,dwarfdump但我不工作,所以我猜调试信息不是DWARF类型.
$ dwarfdump file.elf
No DWARF information present in file.elf
Run Code Online (Sandbox Code Playgroud)
使用objdump显示调试信息是空的.
$ objdump -g file.elf
file.elf: file format elf32-powerpc
Run Code Online (Sandbox Code Playgroud)
可能是这个ELF文件不包含调试信息,即使ELF文件中有调用的部分.debug_sfnames,.debug_srcinfo并且.debug.srcinfo?或者调试信息是以objdump无法处理的格式存储的?
我的问题:
这是一个例子.上面的问题归结为C是否保证main.c打印: "Function equality: 1"或者"Function equality: 0",在第一种情况下,动态加载器如何实现这一点.
common.h:
extern void * getc_main;
extern void * getc_shared;
void assign_getc_shared();
Run Code Online (Sandbox Code Playgroud)
main.c:
#include <stdio.h>
#include "common.h"
int main()
{
getc_main = (void*) getc;
assign_getc_shared();
printf("Function equality: %d\n", getc_main == getc_shared);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
shared.c:
#include <stdio.h>
#include "common.h"
void assign_getc_shared()
{
getc_shared = (void*) getc;
}
Run Code Online (Sandbox Code Playgroud)
在Unix中,这将使用以下命令进行编译:
cc -shared -fPIC -o libshared.so shared.c
cc -o main main.c -L. -lshared
Run Code Online (Sandbox Code Playgroud)
并执行:
LD_LIBRARY_PATH=. ./main
Run Code Online (Sandbox Code Playgroud) 我已经看到使用gcc __section__属性(特别是在Linux内核中)将数据(通常是函数指针)收集到自定义ELF部分中.如何检索和使用这些自定义部分中的"东西"?
测试是在Ubuntu 12.04 64位上进行的.x86架构.
我对位置独立可执行(PIE)和位置无关代码(PIC)的概念感到困惑,我猜它们不是正交的.
这是我的快速实验.
gcc -fPIC -pie quickSort.c -o a_pie.out
gcc -fPIC quickSort.c -o a_pic.out
gcc a.out
objdump -Dr -j .text a.out > a1.temp
objdump -Dr -j .text a_pic.out > a2.temp
objdump -Dr -j .text a_pie.out > a3.temp
Run Code Online (Sandbox Code Playgroud)
我有以下发现.
A. a.out包含一些PIC代码,但仅在libc序言和结尾函数中有效,如下所示:
4004d0: 48 83 3d 70 09 20 00 cmpq $0x0,0x200970(%rip) # 600e48 <__JCR_END__>
Run Code Online (Sandbox Code Playgroud)
在我的简单快速排序程序的汇编指令中,我没有找到任何PIC指令.
B. a_pic.out包含PIC代码,我没有找到任何非PIC指令...在我的快速排序程序的指令中,所有全局数据都由PIC指令访问,如下所示:
40053b: 48 8d 05 ea 02 00 00 lea 0x2ea(%rip),%rax # 40082c <_IO_stdin_used+0x4>
Run Code Online (Sandbox Code Playgroud)
C. a_pie.out包含与a_pic.out比较的语法相同的指令.但是,a_pie.out的.text段的内存地址范围为0x630到0xa57,而a_pic.out的相同部分的范围是0x400410到0x400817.
谁能给我一些关于这些现象的解释?特别是发现 …