ELF optimization ---链接、装载过程 浅析

先放几张图片
在这里插入图片描述

ff@ubuntu:~/app/0$ readelf -a a4
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400430
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6704 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)  /** ELF文件头的大小, 对应上图的0x40 */
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         32
  Section header string table index: 29
如果想减小program的体积,可以删除一些没有必要的section,
这里增加一个section,将一个变量放入到该section中,看,他与其他section不同的是前面没有"."

这是Gcc一个特色,如,把一个函数指针放入到特定的section,然后需要的时候拿出来使用
当然了,可以使用 KEEP 来强制连接器保留一些特定的 section,
如果想让该section中的内容按照名字来排序的话,可以使用SORT

如: 
	. = ALIGN(8);
	KEEP(*(SORT(.scattered_array*)));
如:
    const initcall_t *call;
    
    for (call = initcall_begin; call < initcall_end; call++) {
	    ret = (*call)();	
	}	

在这里插入图片描述
看到下面的 .interp section 可把我害惨了,它包含程序解释器的路径名,因为找不到动态连接器,结果整个系统都挂了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
好,废话不多说,上正题

ELF Header

/usr/include/elf.h在这里插入图片描述
好吧,下面就看看一个C source code 是怎么经过Gcc LLVM 发生化学变化后产生ELF的,
神奇的数字 8 在这里起不到 8 byte对齐了,好吧,搬起板凳 看戏吧! ? 哈哈

重点关注下面的 st_value 符号值, 看它是这么被生成的

 417 typedef struct
 418 {
    
    
 419   Elf64_Word    st_name;                /* Symbol name (string tbl index) */
 420   unsigned char st_info;                /* Symbol type and binding */
 421   unsigned char st_other;               /* Symbol visibility */
 422   Elf64_Section st_shndx;               /* Section index */
 423   Elf64_Addr    st_value;               /* Symbol value */
 424   Elf64_Xword   st_size;                /* Symbol size */
 425 } Elf64_Sym;

符号地址 = 符号所在的段基址 + 符号所在段内偏移

/* 该符号在本文件中未定义 */
if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) {
    
      
	....
} else
	*where = rela->r_addend + sym_tab[sym_idx].st_value + vabase;

猜你喜欢

转载自blog.csdn.net/leesagacious/article/details/87530313
今日推荐