子张问善人之道。子曰:“不践迹,亦不入于室。” 《论语》:先进篇

鸿蒙内核源码分析(重定位篇) | 与国际接轨的对外部发言人 | 百篇博客分析OpenHarmony源码 | v55.02

百篇博客系列篇.本篇为:

v55.xx 鸿蒙内核源码剖析(重定位篇) | 与世界接轨的对外部发言人

加载运转相关篇为:

  • v51.xx 鸿蒙内核源码剖析(ELF格式) | 应用程序进口并不是main
  • v53.xx 鸿蒙内核源码剖析(ELF解析) | 你要忘了她姐俩你就不是银
  • v54.xx 鸿蒙内核源码剖析(静态链接) | 完好小项目看透静态链接进程
  • v55.xx 鸿蒙内核源码剖析(重定位) | 与世界接轨的对外部发言人
  • v56.xx 鸿蒙内核源码剖析(进程映像) | ELF是如何被加载运转的?

一个程序从源码到被执行,当中阅历了3个进程:

  • 编译:将.c文件编译成.o文件,不关心.o文件之间的联络.
  • 静态链接:将一切.o文件合并成一个.so或.out文件,处理一切.o文件节区在方针文件中的布局.
  • 动态链接:将.so或a.out文件加载到内存,处理加载文件在的内存中的布局.

什么是重定位

重定位便是把程序的逻辑地址空间变换成内存中的实践物理地址空间的进程。它是完成多道程序在内存中一起运转的根底。重定位有两种,分别是动态重定位与静态重定位。

  • 1.静态重定位:即在程序装入内存的进程中完结,是指在程序开端运转前,程序中的各个地址有关的项均已完结重定位,地址变换通常是在装入时一次完结的,以后不再改动,故称为静态重定位。也便是在生成可执行/同享方针文件的一起已完结地址的静态定位,它处理了可执行文件/同享方针文件的内部矛盾.
  • 2.动态重定位:它不是在程序装入内存时完结的,而是CPU每次访问内存时 由动态地址变换机构(硬件)自动进行把相对地址转换为绝对地址。动态重定位需求软件和硬件相互配合完结。也便是说可执行文件/同享方针文件的外部矛盾需求外部环境处理,它向外供给了一份入住地球村的交际阐明.即本篇最终部分内容.

重定位十种类型

  • 重定位有10种类型,在实践中请对号入座,这些类型部分在本篇能见到,如下:
类型 公式 具体描绘
R_X86_64_32 公式:S+A
S:重定项中VALUE成员所指符号的内存地址
A:被重定位处原值,表明”引证符号的内存地址”与S的偏移
大局变量,在不加-fPIC编译生成的.o文件中,每个引证处对应一个R_X86_64_32重定位项,非static大局变量,在不加-fPIC编译生成的.so文件中,每个引证处对应一个R_X86_64_32重定位项.
R_X86_64_PC32 公式:S+A-P
S:重定项中VALUE成员所指符号的内存地址
A:被重定位处原值,表明”被重定位处”与”下一条指令”的偏移
P:被重定位处的内存地址
非static函数,在不加-fPIC编译生成的.o和.so文件中,每个调用途对应一个R_X86_64_PC32重定位项
R_X86_64_PLT32 公式:L+A-P
L:<重定项中VALUE成员所指符号@plt>的内存地址
A:被重定位处原值,表明”被重定位处”相关于”下一条指令”的偏移 P:被重定位处的内存地址
非static函数,在加-fPIC编译生成的.o文件中,每个调用途对应一个R_386_PLT32重定位项.
R_X86_64_RELATIVE 公式:B+A
B:.so文件加载到内存中的基地址
A:被重定位处原值,表明引证符号在.so文件中的偏移
static大局变量,在不加-fPIC编译生成的.so文件中,每个引证处对应一个R_X86_64_RELATIVE重定位项.
R_X86_64_GOT32 公式:G
G:引证符号的地址指针,相关于GOT的偏移
非static大局变量,在加-fPIC编译生成的.o文件中,每个引证处对应一个R_X86_64_GOT32重定位项
R_X86_64_GOTOFF 公式:S-GOT
S:重定项中VALUE成员所指符号的内存地址
GOT:运转时,.got段的完毕地址
static大局变量,在加-fPIC编译生成的.o文件中,每个引证处对应一个R_X86_64_GOTOFF重定位项.
R_X86_64_GOLB_DAT 公式:S
S:重定项中VALUE成员所指符号的内存地址
非static大局变量,在加-fPIC编译生成的.so文件中,每个引证处对应一个R_X86_64_GOLB_DAT重定位项.
R_X86_64_COPY 公式:无 .out中使用extern引证.so中的变量,每个引证处对应一个R_X86_64_COPY重定位项.
R_X86_64_JUMP_SLOT 公式:S(与R_386_GLOB_DAT的公式一样,但关于动态ld,R_386_JMP_SLOT类型与R_386_RELATIVE等价)
S:重定项中VALUE成员所指符号的内存地址
非static函数,在加-fPIC编译生成的.so文件中,每个调用途对应一个R_X86_64_JMP_SLOT重定位项.
R_X86_64_GOTPC 公式:GOT+A-P
GOT:运转时,.got段的完毕地址
A:被重定位处原值,表明”被重定位处”在机器码中的偏移
P:被重定位处的内存地址
大局变量,在加-fPIC编译生成的.o文件中,会额定生成R_X86_64_PC32和R_X86_64_GOTPC重定位项,非static函数,在加-fPIC编译生成的.o文件中,也会额定 生成R_X86_64_PC32和R_X86_64_GOTPC重定位项.

解读

  • fPIC的全称是 Position Independent Code, 用于生成方位无关代码。

objdump指令

objdump指令是Linux下的反汇编方针文件或者可执行文件的指令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息.本篇将用它阐明静态重定位的完成细节和动态重定位前置条件预备.先整体走读下objdump指令

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump
Usage: objdump <option(s)> <file(s)>
 Display information from object <file(s)>.
 At least one of the following switches must be given:
  -a, --archive-headers    Display archive header information
  -f, --file-headers       Display the contents of the overall file header
  -p, --private-headers    Display object format specific file header contents
  -P, --private=OPT,OPT... Display object format specific contents
  -h, --[section-]headers  Display the contents of the section headers
  -x, --all-headers        Display the contents of all headers
  -d, --disassemble        Display assembler contents of executable sections
  -D, --disassemble-all    Display assembler contents of all sections
      --disassemble=<sym>  Display assembler contents from <sym>
  -S, --source             Intermix source code with disassembly
      --source-comment[=<txt>] Prefix lines of source code with <txt>
  -s, --full-contents      Display the full contents of all sections requested
  -g, --debugging          Display debug information in object file
  -e, --debugging-tags     Display debug information using ctags style
  -G, --stabs              Display (in raw form) any STABS info in the file
  -W[lLiaprmfFsoRtUuTgAckK] or
  --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
          =frames-interp,=str,=loc,=Ranges,=pubtypes,
          =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
          =addr,=cu_index,=links,=follow-links]
                           Display DWARF info in the file
  --ctf=SECTION            Display CTF info from SECTION
  -t, --syms               Display the contents of the symbol table(s)
  -T, --dynamic-syms       Display the contents of the dynamic symbol table
  -r, --reloc              Display the relocation entries in the file
  -R, --dynamic-reloc      Display the dynamic relocation entries in the file
  @<file>                  Read options from <file>
  -v, --version            Display this program's version number
  -i, --info               List object formats and architectures supported
  -H, --help               Display this information

objdump -S ./obj/main.o

main.o是个可重定位文件,通过 readelf 可知

root@5e3abe332c5a:/home/docker/test4harmony/54# readelf -h ./obj/main.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:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./obj/main.o 
./obj/main.o:     file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:     
#include <stdio.h>
#include "part.h"
extern int g_int;
extern char *g_str;
int main() {
   0:   f3 0f 1e fa             endbr64
   4:   55                      push   %rbp
   5:   48 89 e5                mov    %rsp,%rbp
   8:   48 83 ec 10             sub    $0x10,%rsp
        int loc_int = 53;
   c:   c7 45 f4 35 00 00 00    movl   $0x35,-0xc(%rbp)
        char *loc_str = "harmony os";
  13:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # 1a <main+0x1a>
  1a:   48 89 45 f8             mov    %rax,-0x8(%rbp)
        printf("main 开端 - 大局 g_int = %d, 大局 g_str = %s.\n", g_int, g_str);
  1e:   48 8b 15 00 00 00 00    mov    0x0(%rip),%rdx        # 25 <main+0x25>
  25:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 2b <main+0x2b>
  2b:   89 c6                   mov    %eax,%esi
  2d:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 34 <main+0x34>
  34:   b8 00 00 00 00          mov    $0x0,%eax
  39:   e8 00 00 00 00          callq  3e <main+0x3e>
        func_int(loc_int);
  3e:   8b 45 f4                mov    -0xc(%rbp),%eax
  41:   89 c7                   mov    %eax,%edi
  43:   e8 00 00 00 00          callq  48 <main+0x48>
        func_str(loc_str);
  48:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  4c:   48 89 c7                mov    %rax,%rdi
  4f:   e8 00 00 00 00          callq  54 <main+0x54>
        printf("main 完毕 - 大局 g_int = %d, 大局 g_str = %s.\n", g_int, g_str);
  54:   48 8b 15 00 00 00 00    mov    0x0(%rip),%rdx        # 5b <main+0x5b>
  5b:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 61 <main+0x61>
  61:   89 c6                   mov    %eax,%esi
  63:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 6a <main+0x6a>
  6a:   b8 00 00 00 00          mov    $0x0,%eax
  6f:   e8 00 00 00 00          callq  74 <main+0x74>
        return 0;
  74:   b8 00 00 00 00          mov    $0x0,%eax
  79:   c9                      leaveq
  7a:   c3                      retq

解读

  • 注意那些 00 00 00 00部分,这些都是编译器暂时无法确认的内容.肉眼计算下此刻OFFSET偏移位为 0x160x21,即下表内容

objdump -r ./obj/main.o

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -r ./obj/main.o
./obj/main.o:     file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000016 R_X86_64_PC32     .rodata-0x0000000000000004
0000000000000021 R_X86_64_PC32     g_str-0x0000000000000004
0000000000000027 R_X86_64_PC32     g_int-0x0000000000000004
0000000000000030 R_X86_64_PC32     .rodata+0x000000000000000c
000000000000003a R_X86_64_PLT32    printf-0x0000000000000004
0000000000000044 R_X86_64_PLT32    func_int-0x0000000000000004
0000000000000050 R_X86_64_PLT32    func_str-0x0000000000000004
0000000000000057 R_X86_64_PC32     g_str-0x0000000000000004
000000000000005d R_X86_64_PC32     g_int-0x0000000000000004
0000000000000066 R_X86_64_PC32     .rodata+0x0000000000000044
0000000000000070 R_X86_64_PLT32    printf-0x0000000000000004

解读

  • 0x160x21对应的这些值都是 0,也便是说关于编译器不能确认的地址都这设置为空(0x000000),一起编译器都生成一一对应的记载,该记载告知链接器在进行链接时要批改这条指令中函数的内存地址,并告知是什么重定位类型,要去哪里找数据填充.

  • 外部大局变量重定位g_strg_int

    0000000000000021 R_X86_64_PC32     g_str-0x0000000000000004
    0000000000000027 R_X86_64_PC32     g_int-0x0000000000000004
    ---
    1e:   48 8b 15 00 00 00 00    mov    0x0(%rip),%rdx        # 25 <main+0x25>
    25:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 2b <main+0x2b>
    

    编译器连g_str在哪个.o文件都不知道,当然更不知道g_str运转时的地址,所以在g.o文件中设置一个重定位,要求后续进程依据”S(g_str内存地址)-A(0x04)”,修正main.o镜像中0x21偏移处的值.

  • 函数重定位,重定位类型为 R_X86_64_PLT32

    000000000000003a R_X86_64_PLT32    printf-0x0000000000000004
    0000000000000044 R_X86_64_PLT32    func_int-0x0000000000000004
    0000000000000050 R_X86_64_PLT32    func_str-0x0000000000000004
    0000000000000070 R_X86_64_PLT32    printf-0x0000000000000004
    ---
    39:   e8 00 00 00 00          callq  3e <main+0x3e>
    43:   e8 00 00 00 00          callq  48 <main+0x48>
    

    相同编译器连“func_intprintf`在哪个.o文件都不知道,当然更不知道它们的运转时的地址,所以在main.o文件中设置一个重定位,后续将 修正main.o镜像中3a偏移处的值.

  • 另一部分数据由本.o自己供给,如下

objdump -sj .rodata ./obj/main.o

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -sj .rodata ./obj/main.o
./obj/main.o:     file format elf64-x86-64
Contents of section .rodata:
 0000 6861726d 6f6e7920 6f730000 00000000  harmony os......
 0010 6d61696e 20e5bc80 e5a78b20 2d20e585  main ...... - ..
 0020 a8e5b180 20675f69 6e74203d 2025642c  .... g_int = %d,
 0030 20e585a8 e5b18020 675f7374 72203d20   ...... g_str =
 0040 25732e0a 00000000 6d61696e 20e7bb93  %s......main ...
 0050 e69d9f20 2d20e585 a8e5b180 20675f69  ... - ...... g_i
 0060 6e74203d 2025642c 20e585a8 e5b18020  nt = %d, ......
 0070 675f7374 72203d20 25732e0a 00        g_str = %s...

解读

  • 内部变量重定位.
    13:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # 1a <main+0x1a>
    ---
    0000000000000016 R_X86_64_PC32     .rodata-0x0000000000000004
    
    由于是局部变量,编译器知道数据放在了 .rodata区,要求后续进程依据 “S(main.o镜像中.rodata的内存地址)-A(0x04)”,修正main.o镜像中0x16偏移处的值.

再剖析通过静态链接之后的可执行文件

objdump -S ./bin/weharmony

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./bin/weharmony 
Disassembly of section .text:
0000000000001188 <func_str>:
void func_str(char *str) {
    1188:       f3 0f 1e fa             endbr64
    118c:       55                      push   %rbp
    118d:       48 89 e5                mov    %rsp,%rbp
    1190:       48 83 ec 10             sub    $0x10,%rsp
    1194:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
        g_str = str;
    1198:       48 8b 45 f8             mov    -0x8(%rbp),%rax
    119c:       48 89 05 75 2e 00 00    mov    %rax,0x2e75(%rip)        # 4018 <g_str>
        printf("func_str g_str = %s.\n", g_str);
    11a3:       48 8b 05 6e 2e 00 00    mov    0x2e6e(%rip),%rax        # 4018 <g_str>
    11aa:       48 89 c6                mov    %rax,%rsi
    11ad:       48 8d 3d 83 0e 00 00    lea    0xe83(%rip),%rdi        # 2037 <_IO_stdin_used+0x37>
    11b4:       b8 00 00 00 00          mov    $0x0,%eax
    11b9:       e8 92 fe ff ff          callq  1050 <printf@plt>
    11be:       90                      nop
    11bf:       c9                      leaveq
    11c0:       c3                      retq
00000000000011c1 <main>:
#include <stdio.h>
#include "part.h"
extern int g_int;
extern char *g_str;
int main() {
    11c1:       f3 0f 1e fa             endbr64
    11c5:       55                      push   %rbp
    11c6:       48 89 e5                mov    %rsp,%rbp
    11c9:       48 83 ec 10             sub    $0x10,%rsp
        int loc_int = 53;
    11cd:       c7 45 f4 35 00 00 00    movl   $0x35,-0xc(%rbp)
        char *loc_str = "harmony os";
    11d4:       48 8d 05 75 0e 00 00    lea    0xe75(%rip),%rax        # 2050 <_IO_stdin_used+0x50>
    11db:       48 89 45 f8             mov    %rax,-0x8(%rbp)
        printf("main 开端 - 大局 g_int = %d, 大局 g_str = %s.\n", g_int, g_str);
    11df:       48 8b 15 32 2e 00 00    mov    0x2e32(%rip),%rdx        # 4018 <g_str>
    11e6:       8b 05 24 2e 00 00       mov    0x2e24(%rip),%eax        # 4010 <g_int>
    11ec:       89 c6                   mov    %eax,%esi
    11ee:       48 8d 3d 6b 0e 00 00    lea    0xe6b(%rip),%rdi        # 2060 <_IO_stdin_used+0x60>
    11f5:       b8 00 00 00 00          mov    $0x0,%eax
    11fa:       e8 51 fe ff ff          callq  1050 <printf@plt>
        func_int(loc_int);
    11ff:       8b 45 f4                mov    -0xc(%rbp),%eax
    1202:       89 c7                   mov    %eax,%edi
    1204:       e8 40 ff ff ff          callq  1149 <func_int>
        func_str(loc_str);
    1209:       48 8b 45 f8             mov    -0x8(%rbp),%rax
    120d:       48 89 c7                mov    %rax,%rdi
    1210:       e8 73 ff ff ff          callq  1188 <func_str>
        printf("main 完毕 - 大局 g_int = %d, 大局 g_str = %s.\n", g_int, g_str);
    1215:       48 8b 15 fc 2d 00 00    mov    0x2dfc(%rip),%rdx        # 4018 <g_str>
    121c:       8b 05 ee 2d 00 00       mov    0x2dee(%rip),%eax        # 4010 <g_int>
    1222:       89 c6                   mov    %eax,%esi
    1224:       48 8d 3d 6d 0e 00 00    lea    0xe6d(%rip),%rdi        # 2098 <_IO_stdin_used+0x98>
    122b:       b8 00 00 00 00          mov    $0x0,%eax
    1230:       e8 1b fe ff ff          callq  1050 <printf@plt>
        return 0;
    1235:       b8 00 00 00 00          mov    $0x0,%eax
    123a:       c9                      leaveq
    123b:       c3                      retq
    123c:       0f 1f 40 00             nopl   0x0(%rax)
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -s ./bin/weharmony
...省掉部分
Contents of section .plt.got:
 1040 f30f1efa f2ff25ad 2f00000f 1f440000  ......%./....D..
Contents of section .plt.sec:
 1050 f30f1efa f2ff2575 2f00000f 1f440000  ......%u/....D..
Contents of section .data:
 4000 00000000 00000000 08400000 00000000  .........@......
 4010 33000000 00000000 08200000 00000000  3........ ......
Contents of section .rodata:
 2000 01000200 00000000 68656c6c 6f20776f  ........hello wo
 2010 726c6400 00000000 66756e63 5f696e74  rld.....func_int
 2020 20675f69 6e74203d 2025642c 746d7020   g_int = %d,tmp
 2030 3d202564 2e0a0066 756e635f 73747220  = %d...func_str
 2040 675f7374 72203d20 25732e0a 00000000  g_str = %s......
 2050 6861726d 6f6e7920 6f730000 00000000  harmony os......
 2060 6d61696e 20e5bc80 e5a78b20 2d20e585  main ...... - ..
 2070 a8e5b180 20675f69 6e74203d 2025642c  .... g_int = %d,
 2080 20e585a8 e5b18020 675f7374 72203d20   ...... g_str =
 2090 25732e0a 00000000 6d61696e 20e7bb93  %s......main ...
 20a0 e69d9f20 2d20e585 a8e5b180 20675f69  ... - ...... g_i
 20b0 6e74203d 2025642c 20e585a8 e5b18020  nt = %d, ......
 20c0 675f7374 72203d20 25732e0a 00        g_str = %s...

解读

  • main.o中被重定位的部分不再是00 00 00 00都已经有了实践的数据,例如:
    char *loc_str = "harmony os";
    11d4:       48 8d 05 75 0e 00 00    lea    0xe75(%rip),%rax        # 2050 <_IO_stdin_used+0x50>
    
    对应的# 2050 <_IO_stdin_used+0x50>地址数据正是.rodata 2050方位的 harmony os
  • 看main()中的
      1209:       48 8b 45 f8             mov    -0x8(%rbp),%rax
      120d:       48 89 c7                mov    %rax,%rdi
      1210:       e8 73 ff ff ff          callq  1188 <func_str>
    
    callq 1188 1188正是 func_str的进口地址
    void func_str(char *str) {
        1188:       f3 0f 1e fa             endbr64
    
  • 看大局变量 g_str``g_int对应的链接地址 0x40180x4010
    1215:       48 8b 15 fc 2d 00 00    mov    0x2dfc(%rip),%rdx        # 4018 <g_str>
    121c:       8b 05 ee 2d 00 00       mov    0x2dee(%rip),%eax        # 4010 <g_int>
    
    .data区供给
      4000 00000000 00000000 08400000 00000000  .........@......
      4010 33000000 00000000 08200000 00000000  3........ ......
    
    0x4010 = 0x33 = 51
  • main函数中调用 printf代码为 callq 1050
      1230:       e8 1b fe ff ff          callq  1050 <printf@plt>
    
    内容由.plt.sec区供给,并反汇编该区为
      Contents of section .plt.sec:
      1050 f30f1efa f2ff2575 2f00000f 1f440000  ......%u/....D..
      Disassembly of section .plt.sec:
      0000000000001050 <printf@plt>:
          1050:       f3 0f 1e fa             endbr64
          1054:       f2 ff 25 75 2f 00 00    bnd jmpq *0x2f75(%rip)        # 3fd0 <printf@GLIBC_2.2.5>
          105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
    
    注意3fd0,需求运转时环境供给,加载器动态重定位完成.
  • 总结下来便是 weharmony 已完结了一切.o文件的静态重定位部分, 组合成一个新的可执行文件,其中只还有动态链接部分没有完结,由于那需求运转时重定位地址.如下:

objdump -R ./bin/weharmony

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -R ./bin/weharmony 
./bin/weharmony:     file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE
0000000000003db8 R_X86_64_RELATIVE  *ABS*+0x0000000000001140
0000000000003dc0 R_X86_64_RELATIVE  *ABS*+0x0000000000001100
0000000000004008 R_X86_64_RELATIVE  *ABS*+0x0000000000004008
0000000000004018 R_X86_64_RELATIVE  *ABS*+0x0000000000002008
0000000000003fd8 R_X86_64_GLOB_DAT  _ITM_deregisterTMCloneTable
0000000000003fe0 R_X86_64_GLOB_DAT  __libc_start_main@GLIBC_2.2.5
0000000000003fe8 R_X86_64_GLOB_DAT  __gmon_start__
0000000000003ff0 R_X86_64_GLOB_DAT  _ITM_registerTMCloneTable
0000000000003ff8 R_X86_64_GLOB_DAT  __cxa_finalize@GLIBC_2.2.5
0000000000003fd0 R_X86_64_JUMP_SLOT  printf@GLIBC_2.2.5

解读

  • 这是weharmony对运转时环境提交的一份交际阐明,有了它就能够与世界接轨,入住地球村.
  • 这份阐明其他部分很陌生,看个熟悉的3fd0,其动态链接重定位类型为 R_X86_64_JUMP_SLOT,它在告知动态加载器,在运转时环境中找到 printf并完结动态重定位.

百万汉字注解.精读内核源码

四大码仓同步注解内核源码, >> 检查 gitee 仓库

百篇博客剖析.深挖内核地基

给鸿蒙内核源码加注释进程中,整理出以下文章。内容立足源码,常以日子场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解回忆。说他人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得绘声绘色,倍感亲切.的确有难度,自不量力,但已经出发,回头已是不可能的了。 :P
与代码有bug需不断debug一样,文章和注解内容会存在不少讹夺之处,请多包容,但会重复批改,继续更新,.xx 代表修正的次数,精雕细琢,要言不烦,力求打造精品内容。

编译构建 根底工具 加载运转 进程办理
编译环境
编译进程
环境脚本
构建工具
gn应用
忍者ninja
双向链表
位图办理
用栈方式
定时器
原子操作
时间办理
ELF格式
ELF解析
静态链接
重定位
进程映像
进程办理
进程概念
Fork
特殊进程
进程回收
信号出产
信号消费
Shell编辑
Shell解析
进程通讯 内存办理 来龙去脉 使命办理
自旋锁
互斥锁
进程通讯
信号量
事情操控
消息行列
内存分配
内存办理
内存汇编
内存映射
内存规则
物理内存
总目录
调度故事
内存主奴
源码注释
源码结构
静态站点
时钟使命
使命调度
使命办理
调度行列
调度机制
线程概念
并发并行
体系调用
使命切换
文件体系 硬件架构
文件概念
文件体系
索引节点
挂载目录
根文件体系
字符设备
VFS
文件句柄
管道文件
汇编根底
汇编传参
作业形式
寄存器
反常接收
汇编汇总
中止切换
中止概念
中止办理

鸿蒙研讨站 | 每天死磕一点点,原创不易,欢迎转载,但请注明出处。