欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux : No such file or directory when execute a elf file

程序员文章站 2022-01-21 19:02:26
...

现象:

[email protected]:~# ./bug-iconv14 
-sh: ./bug-iconv14: No such file or directory
[email protected]:~# ldd ./bug-iconv14 
	linux-vdso.so.1 (0x00007ffc63d65000)
	libc.so.6 => /lib64/libc.so.6 (0x00007ff1f13b8000)
	../../build-x86_64-wrs-linux/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007ff1f1582000)
[email protected]:~# ./bug-iconv14 
-sh: ./bug-iconv14: No such file or directory
[email protected]:~# readelf -l ./bug-iconv14

Elf file type is DYN (Shared object file)
Entry point 0x2310
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000000002a8 0x00000000000002a8
                 0x0000000000000032 0x0000000000000032  R      0x1
      [Requesting program interpreter: ../../build-x86_64-wrs-linux/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000001178 0x0000000000001178  R      0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000001fd9 0x0000000000001fd9  R E    0x1000
  LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                 0x0000000000000f30 0x0000000000000f30  R      0x1000
  LOAD           0x0000000000005d08 0x0000000000006d08 0x0000000000006d08
                 0x0000000000000428 0x0000000000000460  RW     0x1000
  DYNAMIC        0x0000000000005da0 0x0000000000006da0 0x0000000000006da0
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x00000000000002dc 0x00000000000002dc 0x00000000000002dc
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x00000000000047ac 0x00000000000047ac 0x00000000000047ac
                 0x00000000000000ac 0x00000000000000ac  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000005d08 0x0000000000006d08 0x0000000000006d08
                 0x00000000000002f8 0x00000000000002f8  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 
   03     .init .plt .plt.got .text .fini 
   04     .rodata .eh_frame_hdr .eh_frame 
   05     .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss 
   06     .dynamic 
   07     .note.ABI-tag .note.gnu.build-id 
   08     .eh_frame_hdr 
   09     
   10     .init_array .fini_array .data.rel.ro .dynamic .got 

原因

interpreter 设置错了.

[Requesting program interpreter: ../../build-x86_64-wrs-linux/ld-linux-x86-64.so.2]

正确的是:

-Wl,-dynamic-linker=/lib64/ld-linux-x86-64.so.2

这里对我这个初学者来说,困惑了好一会.
编译器链接时,我们只需要告知相关的动态库在哪里就可以,然后linker进行symbol链接.
没想到这个路径,是直接写入elf文件头.
这超出了程序员的认知.

多亏有人指导, 否则,这个提示信息:No such file or directory, 难以从网上找到有用的信息.

很快就明白,这是一个法理问题,是一个责任界定的组织管理问题.

可执行文件,需要自己为自己指定解释器.
OS只给出了法律条文,自己并不执行.Loader只是调用请求方自己为自己指定的解释器.

这里有点像, 请求方,自己为自己指定律师.

哲学分析(或者机器理解)

一共五个元素,一个目标,一个形式(本因)即7个元信息.

动因和物因:OS,Loader,Requesting program interpreter, excutable file,shell

然后本因是活动的进程,
极因是这个进程的任务.

shell相关于,空气,社会,平台,场景,语言,文化,等大家统一的默认的沟通平台,可以排除在外.
剩下4个,分为两个阵营,即动因和物因.

动因是OS,但OS是一个被动的服务方,虽然有生命, 但在这里它没有法律主体地位, 因为它只是被动服务方不能执行主动任务,而可执行文件装载,却要OS执行.
这里的矛盾,由OS的代理人:Loader 来实现.  Means : Loader is agent of OS.

在物因方面,物因很明确,就是可执行文件,即 elf文件.
那么解释器(interpreter )是什么呢? 是一个工具,它本身没有主动执行的能力,是被主动方驱动,执行的结果向主动方交接,即按主动方的要求,填写合同的内容,即进程的各项参数,而这些参数(接口)的定义,是由os制度,loader来检查的.

解释器(interpreter )虽然由主动方驱动,但转变的目标却是物因.

=========================================
这样一来,法理关系得到理清.
主动方与物因的界面,就是进程生成的接口,由LOADER具体负责接收和检查. 确认后,进程得以生成.

即,主动方,制法了法律,但行为的本身,即*本身,还是放给了请求方. \

这也就解释了,为什么GCC,即物因的提供方,要自己来写入,并且是写死解析器所在的位置.
而不是说,请OS自己来指定解释器,因为那样,法律问题就无法得到解决.
OS是动态部分,不负责构建.
即不负责物因.
--------------------------------------------------
动因,这里看起来是两个主动对象,一个是OS,一个是Loader.
虽然二都是主动的,而且Loader本身就是OS的一部分,但为什么要指定一个Loader呢?
Loader 相关于卫兵, 守卫在边界之上. 在接到请求后,他会检查物因是否满足双方的条约, 然后调用解释器,将指定的可执行文件,装载到内存,并填充好PCB(进程控制块),一切请绪后,压入调度对列. **进程.
所以OS,会得到两个响应,一个是Loader报告一切就绪, 另一个是被生成的进程向OS的报告.
=============================================
这里难以理解的就是法理的边界的问题.
理解清楚后,自然清晰.
==============================================

好比,社会出了试卷,人去考,通过得到社会颁发的资格证书.
=============================
这里要注意的,一个是解释器(interpreter ), 在执行过程中,本身没有改变,并且,也从来没有生存过.它是活在 Loader 的进程中. 但重点和要点是,Loader却并不负责过程中的责任问题,只关注结果. 一旦找不到 请求方自己指定的解释器, Loader因为无法承担法律(由OS制定)后果, 则会拒绝执行. 并且给出这个难以理解的信息.
第二个是主动方的Loader,也没有发生改变.它只是调用了一个过程,自己什么也没有参与.只是进行了一系列的合规的审查.
========================================

标准描述: 
The "No such file" error coused by unexist interpreter path in elf head trigged in load process by loader for OS

google翻译后:

由OS的加载程序在加载过程中触发的elf头中不存在的解释器路径引起的“无此类文件”错误