为什么GCC根据文件创建共享对象而不是可执行的二进制对象?
我有一个我正在建造的图书馆。当我运行其中一个:
ar rcs lib/libryftts.a $^
gcc -shared $^ -o lib/libryftts.so
在我的makefile中。我还可以成功地将它们安装到/usr/local/lib
中
当我使用NM测试文件时,所有功能都在那里。
我的问题是,当我运行 GCC测试/test.c -lryftts -o test& amp; file ./test
或 gcc testing/test.c lib/libryftts.a -o test&&文件./test
它说:
测试:ELF 64位LSB共享对象
而不是测试:ELF 64位LSB可执行
如我所期望的。我在做什么错?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
没有什么。
听起来您的GCC默认情况下将GCC配置为构建
-pie
二进制文件。这些二进制文件确实是 共享库(类型et_dyn
),除了它们像普通可执行文件一样运行。因此,您应该只运行您的二进制文件,并且(如果有效)不用担心。
或者,您可以将二进制文件与
gcc -no-pie ...
链接,这应该产生非 -pie
typeeT_exec
的可执行文件,用于哪个文件
会说精灵64位LSB可执行文件
。Nothing.
It sounds like your GCC is configured to build
-pie
binaries by default. These binaries really are shared libraries (of typeET_DYN
), except they run just like a normal executable would.So your should just run your binary, and (if it works) not worry about it.
Or you could link your binary with
gcc -no-pie ...
and that should produce a non-PIE
executable of typeET_EXEC
, for whichfile
will sayELF 64-bit LSB executable
.文件
5.36说它清楚file
5.36实际上,如果可执行文件为pie,实际上会清楚地打印出来,如: htttps://unix.stackexchange .com/Question/89211/How-to-To-thewere-a-a-linux-binary-was-was-as as as-as-aS-bositiond-repentent-code/435038#435038例如,派可执行文件显示为:
而非Pie One则为:
该功能,在5.33中引入了功能,但仅做了一个简单的
chmod +xmod +x
检查。在此之前,它只是打印共享对象
pie。在5.34中,它是为了开始检查更专业的
df_1_pie
elf metadata,但由于实现中的错误共享对象。该错误是在5.36中的5.36 commit 。
该错误特别存在于Ubuntu 18.10中,其中具有
file
5.34。由于巧合而将汇编代码与
ld -pie
链接时,它不会自我表现出来。源代码分解显示在“
文件
5.36源代码分析”部分中。linux内核5.0确定是否可以基于
et_dyn
file> file> file> file
“混乱”的根本原因,是两个 pie operutables 共享库是独立的位置,可以放置在随机的内存位置中。at
然后,仅适用于
et_dyn
它是否将load_bias
设置为不为零的东西。load_bias
是确定小精灵偏移的方法: of-a-pie-pie-cecuter-ninux/51343797”>如何在linux中确定的派的文本部分的地址如何?我在实验中确认了这一点: -fpie选项是什么GCC和LD中的位置独立的可执行文件?
文件
5.36行为分解在研究
File> File
从其源起作用。我们将得出结论:elf32_ehdr.e_type == et_exec
可执行文件
elf32_ehdr.e_type == et_dyn
dt_flags_1
动态部分条目存在df_1_pie
在dt_flags_1
中设置pie可执行
共享对象
pie可执行
共享对象
,这里有一些实验,可以证实:
在Ubuntu 18.10,GCC 8.2.0,Binutils 2.31.1中进行了测试。
每种类型实验的完整测试示例描述:
gcc -pie
和gcc -no -pie
: flopectrables-fpie选项是什么在GCC和LD中?请记住,
-pie
默认设置自Ubuntu 17.10,相关:gcc -shared
(.so
共享库):https://github.com/cirosantilli/cpp-cheat/tree/b80ccb4a842db52d719a16d3716b02b684ebbf11/shared_library/basic精灵类型
和df_1_pie
分别用:文件
5.36源代码分析是分析的关键文件IS Magic/Magdir/Elf 。
此魔术格式仅根据固定位置的字节值确定文件类型。
格式本身记录在以下位置:
因此,此时您将需要方便地拥有以下文档:
对文件结束的细分,我们看到:
\ 177ELF
是每个精灵文件开始时的4个魔术字节。\ 177
是0x7f
的八分之一。然后,通过与标准的
elf32_ehdr
结构进行比较,我们看到字节4(第五字节,魔术标识符的第一个字节)确定精灵类:其某些可能的值是:
然后,在
文件
来源中,我们有:和
32-bit
and64位
是file> file
输出的字符串要stdout!因此,现在我们在该文件中搜索
共享对象
,我们被引导到:因此,此
elf-le
是某种标识符,该标识符包含在该文件的上一部分中代码。字节16正是精灵类型:
它的某些值是:
因此,
et_exec
始终以可执行性
打印。et_dyn
有两种可能性,具体取决于$ {x
:pie可执行文件
共享对象
$ {x问:用户,组或其他文件是否可执行文件?如果是,请显示
pie可执行
,else共享对象
。此扩展是在
varexpand
函数中完成的, >src/softmagic.c
:但是,还有一个黑客!在
src/readelf.c
函数dodynamic
,如果存在dt_flags_1
flags动态部分的条目(pt_dynamic
),则在st-中的权限> mode
被df_1_pie
flag的存在或不存在,5.34中的错误是将初始代码写成:
这意味着,如果设置了另一个标志,哪个gcc gcc默认情况下,由于
df_1_now
,可执行文件显示为共享对象
。dt_flags_1
标志条目未在精灵标准中描述,因此必须是binutils扩展名。该标志在Linux内核5.0或GLIBC 2.27中没有用途,因此我似乎纯粹是有用的,以表明文件是否为PIE。
file
5.36 says it clearlyfile
5.36 actually prints it clearly if the executable is PIE or not as shown at: https://unix.stackexchange.com/questions/89211/how-to-test-whether-a-linux-binary-was-compiled-as-position-independent-code/435038#435038For example, a PIE executable shows as:
and a non-PIE one as:
The feature was introduced in 5.33 but it did just a simple
chmod +x
check. Before that it just printedshared object
for PIE.In 5.34, it was meant to start checking the more specialized
DF_1_PIE
ELF metadata, but due to a bug in the implementation at commit 9109a696f3289ba00eaa222fd432755ec4287e28 it actually broke things and showed GCC PIE executables asshared objects
.The bug was fixed in 5.36 at commit 03084b161cf888b5286dbbcd964c31ccad4f64d9.
The bug is present in particular in Ubuntu 18.10 which has
file
5.34.It does not manifest itself when linking assembly code with
ld -pie
because of a coincidence.Source code breakdown is shown in the "
file
5.36 source code analysis" section of this answer.The Linux kernel 5.0 determines if ASLR can be used based on
ET_DYN
The root cause of the
file
"confusion", is that both PIE executables and shared libraries are position independent and can be placed in randomized memory locations.At fs/binfmt_elf.c the kernel only accepts those two types of ELF files:
Then, only for
ET_DYN
does it set theload_bias
to something that is not zero. Theload_bias
is then what determines the ELF offset: How is the address of the text section of a PIE executable determined in Linux?I confirm this experimentally at: What is the -fPIE option for position-independent executables in gcc and ld?
file
5.36 behaviour breakdownAfter studying how
file
works from its source. We will conclude that:Elf32_Ehdr.e_type == ET_EXEC
executable
Elf32_Ehdr.e_type == ET_DYN
DT_FLAGS_1
dynamic section entry is presentDF_1_PIE
is set inDT_FLAGS_1
:pie executable
shared object
pie executable
shared object
And here are some experiments that confirm that:
Tested in Ubuntu 18.10, GCC 8.2.0, Binutils 2.31.1.
The full test example for for each type of experiment is described at:
gcc -pie
andgcc -no-pie
: What is the -fPIE option for position-independent executables in gcc and ld?Keep in mind that
-pie
is set on by default since Ubuntu 17.10, related: 32-bit absolute addresses no longer allowed in x86-64 Linux?gcc -shared
(.so
shared library): https://github.com/cirosantilli/cpp-cheat/tree/b80ccb4a842db52d719a16d3716b02b684ebbf11/shared_library/basicld
experiments: How to create a statically linked position independent executable ELF in Linux?ELF type
andDF_1_PIE
are determined respectively with:file
5.36 source code analysisThe key file to analyse is magic/Magdir/elf.
This magic format determines file types depending only on the values of bytes at fixed positions.
The format itself is documented at:
So at this point you will want to have the following documents handy:
Towards the end of the file, we see:
\177ELF
are the 4 magic bytes at the start of every ELF file.\177
is the octal for0x7F
.Then by comparing with the
Elf32_Ehdr
struct from the standard, we see that byte 4 (the 5th byte, the first one after the magic identifier), determines the ELF class:and some of its possible values are:
In
file
source then, we have:and
32-bit
and64-bit
are the strings thatfile
outputs to stdout!So now we search for
shared object
in that file, and we are led to:So this
elf-le
is some kind of identifier that gets included on the previous part of the code.Byte 16 is exactly the ELF type:
and some of its values are:
Therefore,
ET_EXEC
always gets printed asexecutable
.ET_DYN
however has two possibilities depending on${x
:pie executable
shared object
${x
asks: are the file executable or not by either user, group or other? If yes, showpie executable
, elseshared object
.This expansion is done in the
varexpand
function insrc/softmagic.c
:There is, however, one more hack! In
src/readelf.c
functiondodynamic
, if theDT_FLAGS_1
flags entry of the dynamic section (PT_DYNAMIC
) is present, then the permissions inst->mode
are overridden by the presence or absence of theDF_1_PIE
flag:The bug in 5.34 is that the initial code was written as:
which means that if another flag was set, which GCC does by default due to
DF_1_NOW
, the executable showed asshared object
.The
DT_FLAGS_1
flags entry is not described in the ELF standard so it must be a Binutils extension.That flag has no uses in the Linux kernel 5.0 or glibc 2.27, so I seems to be purely informative to indicate that a file is PIE or not.