ELF 檔解析

contributed by <tina0405>

  • 延續學習實作小型作業系統筆記,本系統的在運行後,載入的應用程式的檔是excutable ELF 檔,而提供的新服務則是 relocatable ELF,先用以下的圖解釋一下 ELF 的結構(圖片來源)。
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
  • 針對一份測試應用程式來解析,先編譯成 relocatable ELF 的形式,如上圖介紹會包含: [紅] ELF header / [黃] 各個 section / [綠] section header table
    ​​​​#include <stddef.h>
    ​​​​#include <mutex.h> 
    
    ​​​​void * thread_run(void *arg);
    ​​​​struct thread_mutex mutex;
    ​​​​int count = 0;
    ​​​​int main()
    ​​​​{
    ​​​​    thread_t thread1;
    ​​​​    thread_mutex_lock(&mutex);
    ​​​​    thread_create(&thread1, NULL, thread_run, 0);
    ​​​​    thread_join(thread1, 0);
    ​​​​    return 0;
    ​​​​}
    
    
    ​​​​void * thread_run(void *arg)
    ​​​​{
    ​​​​    int i;
    ​​​​    thread_mutex_unlock(&mutex);
    ​​​​    return 0;
    ​​​​}
    

ELF header

  • user.o 的 file header 大小為 0x40, 因為結構裡64-bit 的 0x34 為 e_ehsize(此header的大小),參考 ELF 格式,因此只有前0x40 bit 是 file header。

    ​​​​                ---file header---
    ​​​​    0000000 457f 464c 0102 0001 0000 0000 0000 0000
    ​​​​    0000010 0001 00b7 0001 0000 0000 0000 0000 0000
    ​​​​    0000020 0000 0000 0000 0000 0430 0000 0000 0000
    ​​​​    0000030 0000 0000 0040 0000 0000 0040 000a 0007
    ​​​​             ---end of  file header---
    
  • 經過 ELF 格式的對照,其實 header 的 內容就如下,會從這裡知道 header section table 的起始是在 0x430(1072)

    • readelf -h user.o
    ​​​​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:                              REL (Relocatable file)
    ​​​​  Machine:                           AArch64
    ​​​​  Version:                           0x1
    ​​​​  Entry point address:               0x0
    ​​​​  Start of program headers:          0 (bytes into file)
    ​​​​  Start of section headers:          1072 (bytes into file)
    ​​​​  Flags:                             0x0
    ​​​​  Size of this header:               64 (bytes)
    ​​​​  Size of program headers:           0 (bytes)
    ​​​​  Number of program headers:         0
    ​​​​  Size of section headers:           64 (bytes)
    ​​​​  Number of section headers:         10
    ​​​​  Section header string table index: 7
    
    
  • 從 0x430 往下找, section headers 共有 10個,然後每個 0x40, index 7 為 section header string table,對照ELF 格式裡 section header 格式,發現位在在 0x3e0,找到 section header string table(下方.shstrtab) 後可以對照每個 section header 的名字,下方已先標上。

    ​​​​--- 0
    ​​​​0000430 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​*
    ​​​​--- 1 .text section
    ​​​​0000470 0020 0000 0001 0000 0006 0000 0000 0000
    ​​​​0000480 0000 0000 0000 0000 0040 0000 0000 0000
    ​​​​0000490 006c 0000 0000 0000 0000 0000 0000 0000
    ​​​​00004a0 0004 0000 0000 0000 0000 0000 0000 0000
    ​​​​--- 2 .rela.text
    ​​​​00004b0 001b 0000 0004 0000 0040 0000 0000 0000
    ​​​​00004c0 0000 0000 0000 0000 02f0 0000 0000 0000
    ​​​​00004d0 00f0 0000 0000 0000 0008 0000 0001 0000
    ​​​​00004e0 0008 0000 0000 0000 0018 0000 0000 0000
    ​​​​--- 3 .data
    ​​​​00004f0 0026 0000 0001 0000 0003 0000 0000 0000
    ​​​​0000500 0000 0000 0000 0000 00ac 0000 0000 0000
    ​​​​0000510 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000520 0001 0000 0000 0000 0000 0000 0000 0000
    ​​​​--- 4 .bss 
    ​​​​0000530 002c 0000 0008 0000 0003 0000 0000 0000
    ​​​​0000540 0000 0000 0000 0000 00ac 0000 0000 0000
    ​​​​0000550 0004 0000 0000 0000 0000 0000 0000 0000
    ​​​​*
    ​​​​--- 5 .comment
    ​​​​0000570 0031 0000 0001 0000 0030 0000 0000 0000
    ​​​​0000580 0000 0000 0000 0000 00ac 0000 0000 0000
    ​​​​0000590 003c 0000 0000 0000 0000 0000 0000 0000
    ​​​​00005a0 0001 0000 0000 0000 0001 0000 0000 0000
    ​​​​--- 6 --- .note.GNU-stack
    ​​​​00005b0 003a 0000 0001 0000 0000 0000 0000 0000
    ​​​​00005c0 0000 0000 0000 0000 00e8 0000 0000 0000
    ​​​​00005d0 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​00005e0 0001 0000 0000 0000 0000 0000 0000 0000
    ​​​​--- 7 .shstrtab section
    ​​​​00005f0 0011 0000 0003 0000 0000 0000 0000 0000
    ​​​​0000600 0000 0000 0000 0000 03e0 0000 0000 0000
    ​​​​0000610 004a 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000620 0001 0000 0000 0000 0000 0000 0000 0000
    ​​​​--- 8 .symtab = symbol table
    ​​​​0000630 0001 0000 0002 0000 0000 0000 0000 0000
    ​​​​0000640 0000 0000 0000 0000 00e8 0000 0000 0000
    ​​​​0000650 0198 0000 0000 0000 0009 0000 0009 0000
    ​​​​0000660 0008 0000 0000 0000 0018 0000 0000 0000
    ​​​​--- 9 .strtab
    ​​​​0000670 0009 0000 0003 0000 0000 0000 0000 0000
    ​​​​0000680 0000 0000 0000 0000 0280 0000 0000 0000
    ​​​​0000690 006a 0000 0000 0000 0000 0000 0000 0000
    ​​​​00006a0 0001 0000 0000 0000 0000 0000 0000 0000
    
  • 之後就可裡用 section header 裡的資訊(地址、大小等)找到 section 在哪,下面先標上 header 名稱。

    ​​​​             ---start of .text---
    ​​​​0000040 7bfd a9be 03fd 9100 0000 9000 0000 9100
    ​​​​0000050 0000 9400 0000 9000 0001 9100 73a0 9100
    ​​​​0000060 0003 5280 03e2 aa01 0001 d280 0000 9400
    ​​​​0000070 1fa0 b940 0001 5280 0000 9400 0000 5280
    ​​​​0000080 7bfd a8c2 03c0 d65f 7bfd a9be 03fd 9100
    ​​​​0000090 0fa0 f900 0000 9000 0000 9100 0000 9400
    ​​​​00000a0 0000 d280 7bfd a8c2 03c0 d65f
    ​​​​              ---end of .text---   
    ​​​​            ---start of .comment---
    ​​​​                                      4700 4343
    ​​​​00000b0 203a 5528 7562 746e 2f75 694c 616e 6f72
    ​​​​00000c0 3520 342e 302e 362d 6275 6e75 7574 7e31
    ​​​​00000d0 3631 302e 2e34 2939 3520 342e 302e 3220
    ​​​​00000e0 3130 3036 3036 0039 
    ​​​​             ---end of .comment---
    ​​​​               ---symbol table---
    ​​​​                            0000 0000 0000 0000
    ​​​​00000f0 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000100 0001 0000 0004 fff1 0000 0000 0000 0000
    ​​​​0000110 0000 0000 0000 0000 0000 0000 0003 0001
    ​​​​0000120 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000130 0000 0000 0003 0003 0000 0000 0000 0000
    ​​​​0000140 0000 0000 0000 0000 0000 0000 0003 0004
    ​​​​0000150 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000160 0008 0000 0000 0004 0000 0000 0000 0000
    ​​​​0000170 0000 0000 0000 0000 000b 0000 0000 0001
    ​​​​0000180 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000190 0000 0000 0003 0006 0000 0000 0000 0000
    ​​​​00001a0 0000 0000 0000 0000 0000 0000 0003 0005
    ​​​​00001b0 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​00001c0 000e 0000 0011 fff2 0008 0000 0000 0000
    ​​​​00001d0 0020 0000 0000 0000 0014 0000 0011 0004
    ​​​​00001e0 0000 0000 0000 0000 0004 0000 0000 0000
    ​​​​00001f0 001a 0000 0012 0001 0000 0000 0000 0000
    ​​​​0000200 0048 0000 0000 0000 001f 0000 0010 0000
    ​​​​0000210 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000220 0031 0000 0012 0001 0048 0000 0000 0000
    ​​​​0000230 0024 0000 0000 0000 003c 0000 0010 0000
    ​​​​0000240 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​0000250 004a 0000 0010 0000 0000 0000 0000 0000
    ​​​​0000260 0000 0000 0000 0000 0056 0000 0010 0000
    ​​​​0000270 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​            --- end of symbol table ---
    ​​​​                --- .strtab ---
    ​​​​0000280 7500 6573 2e72 0063 6424 2400 0078 756d   .user.c.$d.$x.mu
    ​​​​0000290 6574 0078 6f63 6e75 0074 616d 6e69 7400   tex.count.main.t
    ​​​​00002a0 7268 6165 5f64 756d 6574 5f78 6f6c 6b63   hread_mutex_lock
    ​​​​00002b0 7400 7268 6165 5f64 7572 006e 6874 6572   .thread_run.thre
    ​​​​00002c0 6461 635f 6572 7461 0065 6874 6572 6461   ad_create.thread
    ​​​​00002d0 6a5f 696f 006e 6874 6572 6461 6d5f 7475   _join.thread_mut
    ​​​​00002e0 7865 755f 6c6e 636f 006b 0000 0000 0000   ex_unlock.......
    ​​​​             --- .rela.text ---
    ​​​​00002f0 0008 0000 0000 0000 0113 0000 0009 0000
    ​​​​0000300 0000 0000 0000 0000 000c 0000 0000 0000
    ​​​​0000310 0115 0000 0009 0000 0000 0000 0000 0000
    ​​​​0000320 0010 0000 0000 0000 011b 0000 000c 0000
    ​​​​0000330 0000 0000 0000 0000 0014 0000 0000 0000
    ​​​​0000340 0113 0000 000d 0000 0000 0000 0000 0000
    ​​​​0000350 0018 0000 0000 0000 0115 0000 000d 0000
    ​​​​0000360 0000 0000 0000 0000 002c 0000 0000 0000
    ​​​​0000370 011b 0000 000e 0000 0000 0000 0000 0000
    ​​​​0000380 0038 0000 0000 0000 011b 0000 000f 0000
    ​​​​0000390 0000 0000 0000 0000 0054 0000 0000 0000
    ​​​​00003a0 0113 0000 0009 0000 0000 0000 0000 0000
    ​​​​00003b0 0058 0000 0000 0000 0115 0000 0009 0000
    ​​​​00003c0 0000 0000 0000 0000 005c 0000 0000 0000
    ​​​​00003d0 011b 0000 0010 0000 0000 0000 0000 0000
    ​​​​            --- .shstrtab section ---
    ​​​​00003e0 2e00 7973 746d 6261 2e00 7473 7472 6261   ..symtab..strtab
    ​​​​00003f0 2e00 6873 7473 7472 6261 2e00 6572 616c   ..shstrtab..rela
    ​​​​0000400 742e 7865 0074 642e 7461 0061 622e 7373   .text..data..bss
    ​​​​0000410 2e00 6f63 6d6d 6e65 0074 6e2e 746f 2e65   ..comment..note.
    ​​​​0000420 4e47 2d55 7473 6361 006b 0000 0000 0000   GNU-stack.......
    
  • ELF header table:

    • 雖然指令:aarch64-linux-gnu-objdump -h user.o 能觀察出各個 section 的位置和大小,但這部份 -h 不包含 .symtab, .strtab, .shstrtab, .rela.text 內部操作的 section, 但學習 kernel module 須用到。
    ​​​​Idx Name          Size      VMA               LMA               File off  Algn
    ​​​​  0 .text         0000006c  0000000000000000  0000000000000000  00000040  2**2
    ​​​​                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
    ​​​​  1 .data         00000000  0000000000000000  0000000000000000  000000ac  2**0
    ​​​​                  CONTENTS, ALLOC, LOAD, DATA
    ​​​​  2 .bss          00000004  0000000000000000  0000000000000000  000000ac  2**2
    ​​​​                  ALLOC
    ​​​​  3 .comment      0000003c  0000000000000000  0000000000000000  000000ac  2**0
    ​​​​                  CONTENTS, READONLY
    ​​​​  4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000e8  2**0
    ​​​​                  CONTENTS, READONLY
    

ELF 中的 section

  • .text
  • 我們會發現因為這個 ELF 還未經過連結,會發現裡面 0xc 的地方 94000000 bl 0 <thread_mutex_lock> 還不知道要 bl 的地址,所以先寫 0, add 的地方因為還沒放置變數,因此也先空著,這些會在之後 .rela.text 作介紹
    ​​​​Disassembly of section .text:
    
    ​​​​0000000000000000 <main>:
    ​​​​   0:	a9be7bfd 	stp	x29, x30, [sp,#-32]!
    ​​​​   4:	910003fd 	mov	x29, sp
    ​​​​   8:	90000000 	adrp	x0, 20 <main+0x20>
    ​​​​   c:	91000000 	add	x0, x0, #0x0
    ​​​​  10:	94000000 	bl	0 <thread_mutex_lock>
    ​​​​  14:	90000000 	adrp	x0, 48 <thread_run>
    ​​​​  18:	91000001 	add	x1, x0, #0x0
    ​​​​  1c:	910073a0 	add	x0, x29, #0x1c
    ​​​​  20:	52800003 	mov	w3, #0x0                   	// #0
    ​​​​  24:	aa0103e2 	mov	x2, x1
    ​​​​  28:	d2800001 	mov	x1, #0x0                   	// #0
    ​​​​  2c:	94000000 	bl	0 <thread_create>
    ​​​​  30:	b9401fa0 	ldr	w0, [x29,#28]
    ​​​​  34:	52800001 	mov	w1, #0x0                   	// #0
    ​​​​  38:	94000000 	bl	0 <thread_join>
    ​​​​  3c:	52800000 	mov	w0, #0x0                   	// #0
    ​​​​  40:	a8c27bfd 	ldp	x29, x30, [sp],#32
    ​​​​  44:	d65f03c0 	ret
    
    ​​​​0000000000000048 <thread_run>:
    ​​​​  48:	a9be7bfd 	stp	x29, x30, [sp,#-32]!
    ​​​​  4c:	910003fd 	mov	x29, sp
    ​​​​  50:	f9000fa0 	str	x0, [x29,#24]
    ​​​​  54:	90000000 	adrp	x0, 20 <main+0x20>
    ​​​​  58:	91000000 	add	x0, x0, #0x0
    ​​​​  5c:	94000000 	bl	0 <thread_mutex_unlock>
    ​​​​  60:	d2800000 	mov	x0, #0x0                   	// #0
    ​​​​  64:	a8c27bfd 	ldp	x29, x30, [sp],#32
    ​​​​  68:	d65f03c0 	ret
    
  • .comment: 這個部份帶的資訊用 ascii code 轉換放置旁邊
    ​​Contents of section .comment:
    ​​   0000 00474343 3a202855 62756e74 752f4c69  .GCC: (Ubuntu/Li
    ​​   0010 6e61726f 20352e34 2e302d36 7562756e  naro 5.4.0-6ubun
    ​​   0020 7475317e 31362e30 342e3929 20352e34  tu1~16.04.9) 5.4
    ​​   0030 2e302032 30313630 36303900           .0 20160609.   
    
  • .symtab = symbol table
    • 64-bit 裡面的結構 symbol 的結構: 也就是一個 symbol 應該要帶有的資訊,一個 symbol 24 byte,至於各個名稱的解釋放置下面。
    ​​​​typedef struct
    ​​​​{
    
    ​​​​ Elf64_Word st_name;  /* (4 bytes) Symbol name  */
    ​​​​ unsigned char st_info;  /* (1 byte) Symbol type and binding */
    ​​​​ unsigned char st_other; /* (1 byte) Symbol visibility */
    ​​​​ Elf64_Section st_shndx; /* (2 bytes) Section index */ 
    ​​​​ Elf64_Addr st_value; /* (8 bytes) Symbol value */
    ​​​​ Elf64_Xword st_size; /*  (8 bytes) Symbol size */
    
    ​​​​} Elf64_Sym;
    
    • 以下是 symbol table 原始的 object code
    ​​​​            ---symbol table---
    ​​​​                            0000 0000 0000 0000
    ​​​​00000f0 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000100 0001 0000 0004 fff1 0000 0000 0000 0000
    ​​​​0000110 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            0000 0000 0003 0001
    ​​​​0000120 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000130 0000 0000 0003 0003 0000 0000 0000 0000
    ​​​​0000140 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            0000 0000 0003 0004
    ​​​​0000150 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000160 0008 0000 0000 0004 0000 0000 0000 0000
    ​​​​0000170 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            000b 0000 0000 0001
    ​​​​0000180 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000190 0000 0000 0003 0006 0000 0000 0000 0000
    ​​​​00001a0 0000 0000 0000 0000 
    ​​​​- 
    ​​​​                            0000 0000 0003 0005
    ​​​​00001b0 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​- mutex
    ​​​​00001c0 000e 0000 0011 fff2 0008 0000 0000 0000
    ​​​​00001d0 0020 0000 0000 0000 
    ​​​​- count
    ​​​​                            0014 0000 0011 0004
    ​​​​00001e0 0000 0000 0000 0000 0004 0000 0000 0000
    ​​​​- main
    ​​​​00001f0 001a 0000 0012 0001 0000 0000 0000 0000
    ​​​​0000200 0048 0000 0000 0000 
    ​​​​-
    ​​​​                            001f 0000 0010 0000
    ​​​​0000210 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000220 0031 0000 0012 0001 0048 0000 0000 0000
    ​​​​0000230 0024 0000 0000 0000 
    ​​​​-
    ​​​​                            003c 0000 0010 0000
    ​​​​0000240 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000250 004a 0000 0010 0000 0000 0000 0000 0000
    ​​​​0000260 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            0056 0000 0010 0000
    ​​​​0000270 0000 0000 0000 0000 0000 0000 0000 0000
    ​​​​            --- end of symbol table ---       
    
    • 以上的 byte 數剛好分成 17 組,如下表:
    ​​​​Symbol table '.symtab' contains 17 entries:
    ​​​Num:    Value          Size Type    Bind   Vis      Ndx Name
    ​​​​ 0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
    ​​​​ 1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS user.c
    ​​​​ 2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
    ​​​​ 3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
    ​​​​ 4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
    ​​​​ 5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    4 $d
    ​​​​ 6: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    1 $x
    ​​​​ 7: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    ​​​​ 8: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
    ​​​​ 9: 0000000000000008    32 OBJECT  GLOBAL DEFAULT  COM mutex
    ​​​​10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 count
    ​​​​11: 0000000000000000    72 FUNC    GLOBAL DEFAULT    1 main
    ​​​​12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND thread_mutex_lock
    ​​​​13: 0000000000000048    36 FUNC    GLOBAL DEFAULT    1 thread_run
    ​​​​14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND thread_create
    ​​​​15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND thread_join
    ​​​​16: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND thread_mutex_unlock
    
    
  • 拿第 13 組 thread_run 來作解釋(因為是 little endian 記得要倒過來):

    • st_name(4 byte): 0000 0031

    • st_info(1 byte): 12

      ​​​​​​​​#define ELF64_ST_BIND(info) ((info) >> 4) ​​​​​​​​#define ELF64_ST_TYPE(info) ((info) & 0xf) ​​​​​​​​#define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf))
      • 低位(symbol type):1 GLOBAL
      • 高位(binding): 2 FUNCTION
    • st_other(1 byte): 00 ,參考 File format:

      ​​​​​​​​00 - STV_DEFAULT
      ​​​​​​​​The visibility of symbols with the STV_DEFAULT attribute is 
      ​​​​​​​​as specified by the symbol's binding type. That is, global 
      ​​​​​​​​and weak symbols are visible outside of their defining 
      ​​​​​​​​component, the executable file or shared object. Local 
      ​​​​​​​​symbols are hidden. Global and weak symbols can also be 
      ​​​​​​​​preempted, that is, they may by interposed by definitions of 
      ​​​​​​​​the same name in another component.
      
    • st_shndx(2 bytes): 0001

      • 00-SHT_NULL: 沒定義等待跟其他檔案連結
      • 01-SHT_PROGBITS: 在這份檔案內
    • st_value(8 bytes): 0000 0000 0000 0048

      • 程式從 48 開始
    • st_size(8 bytes):0000 0000 0000 0024

      • 程式的大小 24,6 行指令,1 行 4 bytes。
    ​​​​0000220 0031 0000 0012 0001 0048 0000 0000 0000
    ​​​​0000230 0024 0000 0000 0000
    
  • .strtab

    ​​​​                 --- .strtab ---
    ​​​​    0000280 7500 6573 2e72 0063 6424 2400 0078 756d   .user.c.$d.$x.mu
    ​​​​    0000290 6574 0078 6f63 6e75 0074 616d 6e69 7400   tex.count.main.t
    ​​​​    00002a0 7268 6165 5f64 756d 6574 5f78 6f6c 6b63   hread_mutex_lock
    ​​​​    00002b0 7400 7268 6165 5f64 7572 006e 6874 6572   .thread_run.thre
    ​​​​    00002c0 6461 635f 6572 7461 0065 6874 6572 6461   ad_create.thread
    ​​​​    00002d0 6a5f 696f 006e 6874 6572 6461 6d5f 7475   _join.thread_mut
    ​​​​    00002e0 7865 755f 6c6e 636f 006b 0000 0000 0000   ex_unlock....... 
    
  • .rela.text

    • 結構
    ​​​​ typedef struct { ​​​​ Elf64_Addr r_offset; /*8 bytes*/ ​​​​ Elf64_Xword r_info; /*8 bytes*/ ​​​​ Elf64_Sxword r_addend; /*8 bytes*/ ​​​​ } Elf64_Rela;
    • .rela.text
    ​​​​00002f0 0008 0000 0000 0000 0113 0000 0009 0000
    ​​​​0000300 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            000c 0000 0000 0000
    ​​​​0000310 0115 0000 0009 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000320 0010 0000 0000 0000 011b 0000 000c 0000
    ​​​​0000330 0000 0000 0000 0000 
    ​​​​-     
    ​​​​                            0014 0000 0000 0000
    ​​​​0000340 0113 0000 000d 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000350 0018 0000 0000 0000 0115 0000 000d 0000
    ​​​​0000360 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            002c 0000 0000 0000
    ​​​​0000370 011b 0000 000e 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​0000380 0038 0000 0000 0000 011b 0000 000f 0000
    ​​​​0000390 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            0054 0000 0000 0000
    ​​​​00003a0 0113 0000 0009 0000 0000 0000 0000 0000
    ​​​​-
    ​​​​00003b0 0058 0000 0000 0000 0115 0000 0009 0000
    ​​​​00003c0 0000 0000 0000 0000 
    ​​​​-
    ​​​​                            005c 0000 0000 0000
    ​​​​00003d0 011b 0000 0010 0000 0000 0000 0000 0000
    
    • relocation text 資訊: offset 表示在原程式中的哪, info 裡包含了,在 symbol 中的 index 和 type
    ​​​​tina@tina-X550VB:~/Hw/raspberry-pi3-mini-os/9.ldaxr+cache_on/testcode/mutex_testina@tina-X550VB:~/Hw/raspberry-pi3-mini-os/9.ldaxr+cache_on/testcode/mutex_tesm$ readelf -r user.o ​​​​Relocation section '.rela.text' at offset 0x2f0 contains 10 entries: ​​​​ Offset Info Type Sym. Value Sym. Name + Addend ​​​​000000000008 000900000113 R_AARCH64_ADR_PRE 0000000000000008 mutex + 0 ​​​​00000000000c 000900000115 R_AARCH64_ADD_ABS 0000000000000008 mutex + 0 ​​​​000000000010 000c0000011b R_AARCH64_CALL26 0000000000000000 thread_mutex_lock + 0 ​​​​000000000014 000d00000113 R_AARCH64_ADR_PRE 0000000000000048 thread_run + 0 ​​​​000000000018 000d00000115 R_AARCH64_ADD_ABS 0000000000000048 thread_run + 0 ​​​​00000000002c 000e0000011b R_AARCH64_CALL26 0000000000000000 thread_create + 0 ​​​​000000000038 000f0000011b R_AARCH64_CALL26 0000000000000000 thread_join + 0 ​​​​000000000054 000900000113 R_AARCH64_ADR_PRE 0000000000000008 mutex + 0 ​​​​000000000058 000900000115 R_AARCH64_ADD_ABS 0000000000000008 mutex + 0 ​​​​00000000005c 00100000011b R_AARCH64_CALL26 0000000000000000 thread_mutex_unlock + 0
  • .shstrtab: 提供給 section header table 去利用 offset 找尋名稱。

    ​​        --- .shstrtab section ---
    ​​  00003e0 2e00 7973 746d 6261 2e00 7473 7472 6261   ..symtab..strtab
    ​​  00003f0 2e00 6873 7473 7472 6261 2e00 6572 616c   ..shstrtab..rela
    ​​  0000400 742e 7865 0074 642e 7461 0061 622e 7373   .text..data..bss
    ​​  0000410 2e00 6f63 6d6d 6e65 0074 6e2e 746f 2e65   ..comment..note.
    ​​  0000420 4e47 2d55 7473 6361 006b 0000 0000 0000   GNU-stack.......
    
    • 拿 section header table 中的 .text 舉例, 0x20 為 offset, 對照上表 0x00003e0 + 0x20 = 0x0000400, 即為 .text
      ​​​​​​​​--- 1 .text section
      ​​​​​​​​0000470 0020 0000 0001 0000 0006 0000 0000 0000
      ​​​​​​​​0000480 0000 0000 0000 0000 0040 0000 0000 0000
      ​​​​​​​​0000490 006c 0000 0000 0000 0000 0000 0000 0000
      ​​​​​​​​00004a0 0004 0000 0000 0000 0000 0000 0000 0000
      

Linker to relocate

  • 我們從 relocation text 留給我們的資訊上發現, 有 10 筆資料樣填入,我會將第一筆和第二筆一起看,因為他們是有關係的:

    ​​​​   Offset          Info           Type           Sym. Value    Sym. Name + Addend
    ​​​​000000000008  000900000113 R_AARCH64_ADR_PRE 0000000000000008 mutex + 0
    ​​​​00000000000c  000900000115 R_AARCH64_ADD_ABS 0000000000000008 mutex + 0
    
    • 比較未經過 relocation 的檔案, 0x8 和 0xc 目前都先未填
    ​​​​ 0:	a9be7bfd 	stp	x29, x30, [sp,#-32]!
    ​​​​ 4:	910003fd 	mov	x29, sp
    ​​​​ 8:	90000000 	adrp	x0, 20 <main+0x20>
    ​​​​ c:	91000000 	add	x0, x0, #0x0
    ​​​​10:	94000000 	bl	0 <thread_mutex_lock>
    ​​​​14:	90000000 	adrp	x0, 48 <thread_run>
    ​​​​18:	91000001 	add	x1, x0, #0x0
    ​​​​1c:	910073a0 	add	x0, x29, #0x1c
    ​​​​....
    
    • 下方為 linker 後的 ELF 片段(完整的連結), 因為 linker 知道 mutex這個 data 被放置 0x188, 因此 basic + offset 的方式,x0 先載入 adrp x0, 0 <main>, 再放置 add x0, x0, #0x188
      • 註: 0x188 = 392(十進位), 392*4 = 1568(十進位) = 0x620, 故機器碼為 91062000
    ​​​​0000000000000000 <main>: ​​​​ 0: a9be7bfd stp x29, x30, [sp,#-32]! ​​​​ 4: 910003fd mov x29, sp ​​​​ 8: 90000000 adrp x0, 0 <main> ​​​​ c: 91062000 add x0, x0, #0x188 ​​​​ 10: 94000050 bl 150 <thread_mutex_lock> ​​​​ 14: 90000000 adrp x0, 0 <main> ​​​​ 18: 91012001 add x1, x0, #0x48 ​​​​ 1c: 910073a0 add x0, x29, #0x1c ​​​​ ...
  • bl 的對應,我們看未連結的機器碼 10: 94000000 bl 0 <thread_mutex_lock>, 因為 linker 把另一份有 thread_mutex_lock(.text)的 relocation elf, 一起重新配置, 已經知道放置 thread_mutex_lock 的 addr 是 0x150

    • 註: 0x150 - 0x10(pc) = 0x140 = 320(十進位), 32/4(指令4-byte) = 80(十進位) = 0x50,故0x10 行重新填入 10: 94000050

linker 後的完整 ELF

0000000000000000 <main>: 0: a9be7bfd stp x29, x30, [sp,#-32]! 4: 910003fd mov x29, sp 8: 90000000 adrp x0, 0 <main> c: 91062000 add x0, x0, #0x188 10: 94000050 bl 150 <thread_mutex_lock> 14: 90000000 adrp x0, 0 <main> 18: 91012001 add x1, x0, #0x48 1c: 910073a0 add x0, x29, #0x1c 20: 52800003 mov w3, #0x0 // #0 24: aa0103e2 mov x2, x1 28: d2800001 mov x1, #0x0 // #0 2c: 94000025 bl c0 <thread_create> 30: b9401fa0 ldr w0, [x29,#28] 34: 52800001 mov w1, #0x0 // #0 38: 94000028 bl d8 <thread_join> 3c: 52800000 mov w0, #0x0 // #0 40: a8c27bfd ldp x29, x30, [sp],#32 44: d65f03c0 ret 0000000000000048 <thread_run>: 48: a9be7bfd stp x29, x30, [sp,#-32]! 4c: 910003fd mov x29, sp 50: f9000fa0 str x0, [x29,#24] 54: 90000000 adrp x0, 0 <main> 58: 91062000 add x0, x0, #0x188 5c: 94000040 bl 15c <thread_mutex_unlock> 60: d2800000 mov x0, #0x0 // #0 64: a8c27bfd ldp x29, x30, [sp],#32 68: d65f03c0 ret 000000000000006c <user_delay>: 6c: f1000400 subs x0, x0, #0x1 70: 54ffffe1 b.ne 6c <user_delay> 74: d65f03c0 ret 0000000000000078 <call_sys_write>: 78: 52800008 mov w8, #0x0 // #0 7c: d4000001 svc #0x0 80: d65f03c0 ret 0000000000000084 <call_sys_write_int>: 84: 528000a8 mov w8, #0x5 // #5 88: d4000001 svc #0x0 8c: d65f03c0 ret 0000000000000090 <call_sys_exit>: 90: 52800048 mov w8, #0x2 // #2 94: d4000001 svc #0x0 98: d65f03c0 ret 000000000000009c <call_sys_fork>: 9c: 52800028 mov w8, #0x1 // #1 a0: d4000001 svc #0x0 a4: d65f03c0 ret 00000000000000a8 <call_sys_led>: a8: 52800068 mov w8, #0x3 // #3 ac: d4000001 svc #0x0 b0: d65f03c0 ret 00000000000000b4 <call_sys_read>: b4: 52800088 mov w8, #0x4 // #4 b8: d4000001 svc #0x0 bc: d65f03c0 ret 00000000000000c0 <thread_create>: c0: 528000c8 mov w8, #0x6 // #6 c4: d4000001 svc #0x0 c8: d65f03c0 ret 00000000000000cc <thread_self>: cc: 528000e8 mov w8, #0x7 // #7 d0: d4000001 svc #0x0 d4: d65f03c0 ret 00000000000000d8 <thread_join>: d8: 52800108 mov w8, #0x8 // #8 dc: d4000001 svc #0x0 e0: d65f03c0 ret 00000000000000e4 <thread_cond_signal>: e4: 52800148 mov w8, #0xa // #10 e8: d4000001 svc #0x0 ec: d65f03c0 ret 00000000000000f0 <call_sys_list>: f0: 52800168 mov w8, #0xb // #11 f4: d4000001 svc #0x0 f8: d65f03c0 ret 00000000000000fc <call_sys_cd>: fc: 52800188 mov w8, #0xc // #12 100: d4000001 svc #0x0 104: d65f03c0 ret 0000000000000108 <call_sys_dump>: 108: 528001a8 mov w8, #0xd // #13 10c: d4000001 svc #0x0 110: d65f03c0 ret 0000000000000114 <call_sys_root>: 114: 528001c8 mov w8, #0xe // #14 118: d4000001 svc #0x0 11c: d65f03c0 ret 0000000000000120 <call_sys_mod>: 120: 528001e8 mov w8, #0xf // #15 124: d4000001 svc #0x0 128: d65f03c0 ret 000000000000012c <call_sys_send>: 12c: 52800208 mov w8, #0x10 // #16 130: d4000001 svc #0x0 134: d65f03c0 ret 0000000000000138 <call_sys_recv>: 138: 52800228 mov w8, #0x11 // #17 13c: d4000001 svc #0x0 140: d65f03c0 ret 0000000000000144 <thread_mutex_trylock>: 144: 52800248 mov w8, #0x12 // #18 148: d4000001 svc #0x0 14c: d65f03c0 ret 0000000000000150 <thread_mutex_lock>: 150: 52800248 mov w8, #0x12 // #18 154: d4000001 svc #0x0 158: d65f03c0 ret 000000000000015c <thread_mutex_unlock>: 15c: 52800268 mov w8, #0x13 // #19 160: d4000001 svc #0x0 164: d65f03c0 ret 0000000000000168 <thread_equal>: 168: eb01001f cmp x0, x1 16c: 54000060 b.eq 178 <eq> 170: d2800000 mov x0, #0x0 // #0 174: 14000002 b 17c <neq> 0000000000000178 <eq>: 178: d2800020 mov x0, #0x1 // #1 000000000000017c <neq>: 17c: d65f03c0 ret Disassembly of section .bss: 0000000000000180 <count>: ... 0000000000000188 <mutex>: ... Disassembly of section .comment: 0000000000000000 <.comment>: 0: 3a434347 ccmn w26, w3, #0x7, mi 4: 62552820 .inst 0x62552820 ; undefined 8: 75746e75 .inst 0x75746e75 ; undefined c: 6e694c2f uqshl v15.8h, v1.8h, v9.8h 10: 206f7261 .inst 0x206f7261 ; undefined 14: 2e342e35 uqsub v21.8b, v17.8b, v20.8b 18: 75362d30 .inst 0x75362d30 ; undefined 1c: 746e7562 .inst 0x746e7562 ; undefined 20: 317e3175 adds w21, w11, #0xf8c, lsl #12 24: 34302e36 cbz w22, 605e8 <mutex+0x60460> 28: 2029392e .inst 0x2029392e ; undefined 2c: 2e342e35 uqsub v21.8b, v17.8b, v20.8b 30: 30322030 adr x16, 64435 <mutex+0x642ad> 34: 36303631 tbz w17, #6, 6f8 <mutex+0x570> 38: Address 0x0000000000000038 is out of bounds.
  • 簡易的了解以下 3 點,終於要進入實做的部份載入,連結與重配置
    • elf 如何配置
    • 重填 rela.text 的 addr
    • 對照 symbol table 填 value

Reference