当前位置: 首页 > news >正文

鸿蒙内核源码分析(ELF解析篇) | 内核加载

ELF,它实在是太重要了,内核加载的就是它,不说清楚它怎么去说清楚应用程序运行的过程呢.看到下面这一坨一坨的,除了.text.bss.data听过见过外,其他的咱也没啥交情。

01     .interp
02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
03     .init .plt .plt.got .plt.sec .text .fini
04     .rodata .eh_frame_hdr .eh_frame
05     .init_array .fini_array .dynamic .got .data .bss

系列篇要全说清楚也不太可能,可以去看 ELF官方文档  ,本篇试图与它多些交情,混个脸熟,方便后续推进.从两个命令入手。
readelf -S app 和 readelf -s app这俩宝贝长的很像,但仔细看中间参数是大S和小s,说到大S小s又有点意思了,这姐妹俩上了点年纪的码农都应该不陌生,据说是性格完全不同.个人喜欢大的,甜美安静,小的太聒噪,受不了,码农最需要安静了。

readelf -S app

先看老大是干啥的,其实她是她们家老二,上面还有个姐姐,没啥存在感,不管她了。

root@5e3abe332c5a:/home/docker/case_code_100# readelf -h...-S --section-headers   Display the sections' header--sections          An alias for --section-headers  -s --syms              Display the symbol table--symbols           An alias for --syms      

显示所有区头信息 | sections’ header

root@5e3abe332c5a:/home/docker/case_code_100# readelf -S app
There are 31 section headers, starting at offset 0x39c0:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.propert NOTE             0000000000000338  000003380000000000000020  0000000000000000   A       0     0     8[ 3] .note.gnu.build-i NOTE             0000000000000358  000003580000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000037c  0000037c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003a0  000003a00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003c8  000003c800000000000000a8  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000470  000004700000000000000084  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           00000000000004f4  000004f4000000000000000e  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000508  000005080000000000000020  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000528  0000052800000000000000d8  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000600  000006000000000000000018  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000020  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001040  000010400000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001060  0000106000000000000001b5  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         0000000000001218  00001218000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  00002000000000000000001b  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         000000000000201c  0000201c000000000000004c  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         0000000000002068  000020680000000000000128  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003dc0  00002dc00000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc8  00002dc800000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb8  00002fb80000000000000048  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000018  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004018  000030180000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003018000000000000002a  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB           0000000000000000  000030480000000000000648  0000000000000018          29    46     8[29] .strtab           STRTAB           0000000000000000  000036900000000000000216  0000000000000000           0     0     1[30] .shstrtab         STRTAB           0000000000000000  000038a6000000000000011a  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),l (large), p (processor specific)

解读
命令结果主要三个部分,区名称(Section Head Name),区类型 (Section Head Type) 和区标签(Section Head Flag)

  • Name部分 出现了一些熟悉的内容 .bss.text,但更多是看不懂的 .fini.plt.relname
  • Type部分 就有更多看不懂的 NULLPROGBITSINIT_ARRAY 等等.
  • Flag部分 好像也似懂非懂.

一个区只属于一个类型,具有排它性,跟男人,女人一样.
但身上可以贴多个标签.可以是码农,可以是高富帅,可以是脱发男,不对!!! 码农你还想是高富帅,想多了.脱发才是你的标配.例如:

  • 代码区(.text)属于PROGBITS类型被贴上了AX (alloc + execute)标签.原来代码区可以被CPU取指运行是因为在ELF中被贴上了可运行标签.但注意.text是只读不可写,因为它身上没有write标签.
  • 再看熟悉两个数据区.bss.data,它们都有WA(write+alloc)标签,可写+运行过程中需要占用内存,但二者区别是类型的不同,.bssNOBITS类型 .dataPROGBITS类型

区名称 | Section Head Name

简称:SHN

在ELF文件中有一些特定的区是预定义好的,其内容是指令代码或者控制信息.这些区专门为操作系统使用,对于不同的操作系统,这些区的类型和属性有所不同。

在构建可执行程序时,链接器(linker)可能需要把一些独立的目标文件和库文件链接在一起,在这个过程中,链接器要解析各个文件中的相互引用,调整某些目标文件中的绝对引用,并重定位指令码。

每种操作系统都有自己的一套链接模型,但总的来说,不外乎静态和动态两类:

  • 静态链接:所有的目标文件和动态链接库被静态地绑定在一起,所有的符号都被解析出来.所创建的目标文件是完整的,运行时不依赖于任何外部的库。

  • 动态链接:所有的目标文件,系统共享资源以及共享库以动态的形式链接在一起,外部库的内容没有完整地拷贝进来。如果创建的是可执行文件的话,程序在运行的时候,在构建时所依赖的那些库必须在系统中能找到,把它们一并装载之后,程序才能运行起来。运行期间如何解析那些动态链接进来的符号引用,不同的系统有各自不同的方式。

根据区功能划分:

  • 有些区包含调试信息,比如.debug和.line区.
  • 有些区包含程序控制信息,比如.bss,.data,.data1,.rodata和.rodata1这些区.
  • 还有一些区含有程序或控制信息,这些区由系统使用,有指定的类型和属性.它们中的大多数都将用于链接过程.动态链接过程所需要的信息由.dynsym,.dynstr,.interp,.hash,.dynamic,.rel,.rela,.got,.plt等区提供.其中有些区(比如.plt和.got)的内容依处理器而不同,但它们都支持同样的链接模型.

以点号"."为前缀的区名字是为系统保留的.应用程序也可以构造自己的区,但最好不要取与上述系统已定义的区相同的名字,也不要取以点号开头的名字,以避免潜在的冲突,注意,目标文件中区的名字并不具有唯一性,可以存在多个相同名字的区.具体如下:

区名              描述说明
.bss            本区中包含目标文件中未初始化的全局变量.一般情况下,可执行程序在开始运行的时候,系统会把这一区内容清零.但是,在运行期间的bss区是由系统初始化而成的,在目标文件中.bss区并不包含任何内容,其长度为0,所以它的区类型为NOBITS。
.comment        本区包含版本控制信息.
.data           这个区不陌生,用于存放程序中被初始化过的全局变量.在目标文件中,它们是占用实际的存储空间的,与.bss区不同。
.debug          本区中含有调试信息,内容格式没有统一规定.所有以".debug"为前缀的区名字都是保留的.
.dynamic        本区包含动态链接信息,并且可能有SHF_ALLOC和SHF_WRITE等属性.是否具有SHF_WRITE属性取决于操作系统和处理器。
.dynstr         本区含有用于动态链接的字符串,一般是那些与符号表相关的名字.具有SHF_ALLOC属性
.dynsym         本区含有动态链接符号表.具有SHF_ALLOC属性,因为它需要在运行时被加载
.got            本区包含全局偏移量表(global offset table).
.hash           本区包含一张符号哈希表.
.init           本区包含进程初始化时要执行的程序指令,当程序开始运行时,系统会在进入主函数之前执行这一区中的代码。
.fini           程序终止代码区,当程序结束运行时,系统会在最后执行这一区中的代码.
.interp         本区含有ELF程序解析器的路径名.如果本区被包含在某个可装载的区中,那么本区的属性中应置SHF_ALLOC标志位,否则不置此标志。
.line           本区也是一个用于调试的区,它包含那些调试符号的行号,为程序指令码与源文件的行号建立起联系.其内容格式没有统一规定。
.note           本区所包含的信息在第2章"注释区(note section)"部分描述。
.plt            本区包含函数链接表.动态链接时使用的过程链接表(precedure linkage table)
.relname        同下
.relaname       这两个区含有重定位信息.如果本区被包含在某个可装载的区中,那么本区的属性中应置SHF_ALLOC标志位,否则不置此标志.注意,这两个区的名字中"name"是可替换的部分,执照惯例,对哪一区做重定位就把"name"换成哪一区的名字.比如,.text区的重定位区的名字将是.rel.text或.rela.text。
.rodata         同下
.rodata1        本区包含程序中的只读数据,在程序装载时,它们一般会被装入进程空间中那些只读的区中去。
.shstrtab       本区是"区名字表",含有所有其它区的名字,如 `.data`,`.bss`,`.text`...
.strtab         本区用于存放字符串,主要是那些符号表项的名字.如果一个目标文件有一个可装载的区,并且其中含有符号表,存储的是变量名,函数名等。
.symtab         本区用于存放符号表.如果一个目标文件有一个可载入的区,并且其中含有符号表,那么本区的属性中应该有SHF_ALLOC。
.text           本区包含程序指令代码。
.rel.text       重定位的地方在.text段内,以offset指定具体要定位位置。在连接时候由连接器完成。注意比较.text段前后变化。指的是比较.o文件和最终的执行文件(或者动态库文件)。就是重定位前后比较,以上是说明了具体比较对象而已。 一般由编译器编译产生,存在于obj文件内。
.rel.dyn        重定位的地方在.got段内。主要是针对外部数据变量符号。例如全局数据。重定位在程序运行时定位,一般是在.init段内。定位过程:获得符号对应value后,根据rel.dyn表中对应的offset,修改.got表对应位置的value。另外,.rel.dyn 含义是指和dyn有关,一般是指在程序运行时候,动态加载。区别于rel.plt,rel.plt是指和plt相关,具体是指在某个函数被调用时候加载。一般由连接器产生,存在于可执行文件或者动态库文件。
.rel.plt        重定位的地方在.got.plt段内(注意也是.got内,具体区分而已)。 主要是针对外部函数符号。一般是函数首次被调用时候重定位。可看汇编,理解其首次访问是如何重定位的,实际很简单,就是初次重定位函数地址,然后把最终函数地址放到.got.plt内,以后读取该.got.plt就直接得到最终函数地址(参考过程说明)。  所有外部函数调用都是经过一个对应桩函数,这些桩函数都在.plt段内。 一般由连接器产生,存在于可执行文件或者动态库文件。借助这两个辅助段可以动态修改对应.got和.got.plt段,从而实现运行时重定位。
.rel.data      常量区重定位信息
.rel.rodata    数据段重定位信息                                 

详细解读

  • .text 通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码区为可写,即允许修改程序.在代码区中,也有可能包含一些只读的常数变量,例如字符串常量等。
  • .rodata.data区类型一样但标签有别,.rodata只有A标,是个只读区,比如字符串常量,全局const变量和#define定义的常量,又称为常量区
    但是注意,并不是所有的常量都放在rodata区的,其特殊情况如下:
    • 有些立即数与指令编译在一起直接放在代码区。
    • 对于字符串常量,编译器会去掉重复的常量,让程序的每个字符串常量只有一份
    • 有些系统中rodata区是多个进程共享的,目的是为了提高空间的利用率
  • .bss.data是标签一样但类型有别,.bss区属于静态内存分配.通常是指用来存放程序中未初始化的全局变量和未初始化的局部静态变量.未初始化的全局变量和未初始化的局部静态变量默认值是0,本来这些变量也可以放到data区的,但是因为它们都是0,所以它们在data区分配空间并且存放数据0是没有必要的.在程序运行时,才会给BSS区里面的变量分配内存空间.在目标文件(*.o)和可执行文件中,.bss只是为未初始化的全局变量和未初始化的局部静态变量预留位置而已,它并没有内容,所以它不占据空间。
  • .data 通常是指用来存放程序中已初始化的全局变量和已初始化的静态变量的一块内存区域,属于静态内存分配。

区类型 | Section Head Type

简称:SHT

SHT_NULL        本区头是一个无效的(非活动的)区头,它也没有对应的区.本区头中的其它成员的值也都是没有意义的。
SHT_PROGBITS    本区所含有的信息是由程序定义的,本区内容的格式和含义都由程序来决定。
SHT_SYMTAB      同DYNSYM
SHT_DYNSYM      这两类区都含有符号表.目前,目标文件中最多只能各包含一个这两种区,但这种限制以后可能会取消。一般来说,SYMTAB提供的符号用于在创建目标文件的时候编辑链接,在运行期间也有可能会用于动态链接。SYMTAB包含完整的符号表,它往往会包含很多在运行期间(动态链接)用不到的符号.所以,一个目标文件可以再有一个DYNSYM区,它含有一个较小的符号表,专门用于动态链接。
SHT_STRTAB      本区是字符串表.目标文件中可以包含多个字符串表区。
SHT_RELA        本区是一个重定位区,含有带明确加数(addend)的重定位项,对于32位类型的目标文件来说,这个加数就是Elf32_Rela.一个目标文件可能含有多个重定位区。
SHT_HASH        本区包含一张哈希表.所有参与动态链接的目标文件都必须要包含一个符号哈希表.目前,一个目标文件中最多只能有一个哈希表,但这一限制以后可能会取消。
SHT_DYNAMIC     本区包含的是动态链接信息。目前,一个目标文件中最多只能有一个DYNAMIC区,但这一限制以后可能会取消。
SHT_NOTE        本区包含的信息用于以某种方式来标记本文件。
SHT_NOBITS      这一区的内容是空的,区并不占用实际的空间。只代表一个逻辑上的位置概念,并不代表实际的内容。
SHT_REL         本区是一个重定位区,含有带明确加数的重定位项,对于32位类型的目标文件来说,这个加数就是Elf32_Rel。一个目标文件可能含有多个重定位区。
SHT_SHLIB       此值是一个保留值,暂未指定语义。
SHT_LOPROC      为特殊处理器保留的区类型索引值的下边界。
SHT_HIPROC      为特殊处理器保留的区类型索引值的上边界。LOPROC ~ HIPROC区间是为特殊处理器区类型的保留值。
SHT_LOUSER      为应用程序保留区类型索引值的下边界。
SHT_HIUSER      为应用程序保留区类型索引值的下边界。LOUSER ~ HIUSER区间的区类型可由应用程序自行定义,是一区保留值。

解读

  • .bss 类型为 NOBITS,这一区的内容是空的,区并不占用实际的空间, 没有初值的全局变量就放在这个区.它是真没有值,由运行过程中映射到哪个地址就取哪个地址的值.鬼知道跑哪个位置的。
  • PROGBITS本区内容的格式和含义都由程序来决定,属于这个区的内容还挺多的 .text.data, .init, .rodata ,这些区默认自带运行时数据.不需要你额外提供,区别是这些自带数据运行时可不可以被改变. .data可以被程序运行时逻辑所修改,.rodata不可改,即常量数据。

区标签 | Section Head Flag

简称:SHF

Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),l (large), p (processor specific)

名字         值       描述
SHF_WRITE       0x01       如果此标志被设置,表示本区所包含的内容在进程运行过程中是可写的。
SHF_ALLOC       0x02       如果此标志被设置,表示本区内容在进程运行过程中要占用内存单元。并不是所有区。都会占用实际的内存,有一些起控制作用的区,在目标文件映射到进程空间时,并不需要占用内存。
SHF_EXECUTE     0x04        如果此标志被设置,表示本区内容是指令代码。

解读
此处看下与数据相关的三个区,仔细对照看参数发现其真正的区别.

Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[18] .rodata           PROGBITS         0000000000002000  00002000000000000000001b  0000000000000000   A       0     0     4[25] .data             PROGBITS         0000000000004000  000030000000000000000018  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004018  000030180000000000000008  0000000000000000  WA       0     0     1

readelf -s app

说完大S再来说小S

root@5e3abe332c5a:/home/docker/case_code_100# readelf -h...-S --section-headers   Display the sections' header--sections          An alias for --section-headers  -s --syms              Display the symbol table--symbols           An alias for --syms      

显示所有符号表 | Symbol Table.

root@5e3abe332c5a:/home/docker/case_code_100# readelf -s app
Symbol table '.dynsym' contains 7 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable6: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)Symbol table '.symtab' contains 67 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND1: 0000000000000318     0 SECTION LOCAL  DEFAULT    12: 0000000000000338     0 SECTION LOCAL  DEFAULT    23: 0000000000000358     0 SECTION LOCAL  DEFAULT    34: 000000000000037c     0 SECTION LOCAL  DEFAULT    45: 00000000000003a0     0 SECTION LOCAL  DEFAULT    56: 00000000000003c8     0 SECTION LOCAL  DEFAULT    67: 0000000000000470     0 SECTION LOCAL  DEFAULT    78: 00000000000004f4     0 SECTION LOCAL  DEFAULT    89: 0000000000000508     0 SECTION LOCAL  DEFAULT    910: 0000000000000528     0 SECTION LOCAL  DEFAULT   1011: 0000000000000600     0 SECTION LOCAL  DEFAULT   1112: 0000000000001000     0 SECTION LOCAL  DEFAULT   1213: 0000000000001020     0 SECTION LOCAL  DEFAULT   1314: 0000000000001040     0 SECTION LOCAL  DEFAULT   1415: 0000000000001050     0 SECTION LOCAL  DEFAULT   1516: 0000000000001060     0 SECTION LOCAL  DEFAULT   1617: 0000000000001218     0 SECTION LOCAL  DEFAULT   1718: 0000000000002000     0 SECTION LOCAL  DEFAULT   1819: 000000000000201c     0 SECTION LOCAL  DEFAULT   1920: 0000000000002068     0 SECTION LOCAL  DEFAULT   2021: 0000000000003db8     0 SECTION LOCAL  DEFAULT   2122: 0000000000003dc0     0 SECTION LOCAL  DEFAULT   2223: 0000000000003dc8     0 SECTION LOCAL  DEFAULT   2324: 0000000000003fb8     0 SECTION LOCAL  DEFAULT   2425: 0000000000004000     0 SECTION LOCAL  DEFAULT   2526: 0000000000004018     0 SECTION LOCAL  DEFAULT   2627: 0000000000000000     0 SECTION LOCAL  DEFAULT   2728: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c29: 0000000000001090     0 FUNC    LOCAL  DEFAULT   16 deregister_tm_clones30: 00000000000010c0     0 FUNC    LOCAL  DEFAULT   16 register_tm_clones31: 0000000000001100     0 FUNC    LOCAL  DEFAULT   16 __do_global_dtors_aux32: 0000000000004018     1 OBJECT  LOCAL  DEFAULT   26 completed.806033: 0000000000003dc0     0 OBJECT  LOCAL  DEFAULT   22 __do_global_dtors_aux_fin34: 0000000000001140     0 FUNC    LOCAL  DEFAULT   16 frame_dummy35: 0000000000003db8     0 OBJECT  LOCAL  DEFAULT   21 __frame_dummy_init_array_36: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.c37: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c38: 000000000000218c     0 OBJECT  LOCAL  DEFAULT   20 __FRAME_END__39: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS40: 0000000000003dc0     0 NOTYPE  LOCAL  DEFAULT   21 __init_array_end41: 0000000000003dc8     0 OBJECT  LOCAL  DEFAULT   23 _DYNAMIC42: 0000000000003db8     0 NOTYPE  LOCAL  DEFAULT   21 __init_array_start43: 000000000000201c     0 NOTYPE  LOCAL  DEFAULT   19 __GNU_EH_FRAME_HDR44: 0000000000003fb8     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_45: 0000000000001000     0 FUNC    LOCAL  DEFAULT   12 _init46: 0000000000001210     5 FUNC    GLOBAL DEFAULT   16 __libc_csu_fini47: 0000000000004010     8 OBJECT  GLOBAL DEFAULT   25 my_name48: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab49: 0000000000004000     0 NOTYPE  WEAK   DEFAULT   25 data_start50: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   25 _edata51: 0000000000001218     0 FUNC    GLOBAL HIDDEN    17 _fini52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.553: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_54: 0000000000004000     0 NOTYPE  GLOBAL DEFAULT   25 __data_start55: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__56: 0000000000004008     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle57: 0000000000002000     4 OBJECT  GLOBAL DEFAULT   18 _IO_stdin_used58: 00000000000011a0   101 FUNC    GLOBAL DEFAULT   16 __libc_csu_init59: 0000000000004020     0 NOTYPE  GLOBAL DEFAULT   26 _end60: 0000000000001060    47 FUNC    GLOBAL DEFAULT   16 _start61: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start62: 0000000000001174    30 FUNC    GLOBAL DEFAULT   16 main63: 0000000000001149    43 FUNC    GLOBAL DEFAULT   16 say_hello64: 0000000000004018     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__65: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable66: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.2

解读
.dynsym,.symtab两区的类型如下,是一个含义.

SHT_SYMTAB      同DYNSYM
SHT_DYNSYM      这两类区都含有符号表.目前,目标文件中最多只能各包含一个这两种区,但这种限制以后可能会取消.一般来说,SYMTAB提供的符号用于在创建目标文件的时候编辑链接,在运行期间也有可能会用于动态链接.SYMTAB包含完整的符号表,它往往会包含很多在运行期间(动态链接)用不到的符号.所以,一个目标文件可以再有一个DYNSYM区,它含有一个较小的符号表,专门用于动态链接.

正如描述所言,.dynsym是.symtab的缩小版,在其中能看到亲切的printf.具体请参考以下四个维度来理解符号表.

符号表绑定 | Symbol Table Bind

简称 STB

STB_LOCAL       表明本符号是一个本地符号.它只出现在本文件中,在本文件外该符号无效。所以在不同的文件中可以定义相同的符号名,它们之间不会互相影响。
STB_GLOBAL      表明本符号是一个全局符号。当有多个文件被链接在一起时,在所有文件中该符号都是可见的。正常情况下,在一个文件中定义的全局符号,一定是在其它文件中需要被引用,否则无须定义为全局。
STB_WEAK        类似于全局符号,但是相对于STB_GLOBAL,它们的优先级更低。全局符号(global symbol)和弱符号(weak symbol)在以下两方面有区别:• 当链接编辑器把若干个可重定位目标文件链接起来时,同名的STB_GLOBAL符号不允许出现多次。而如果在一个目标文件中已经定义了一个全局的符号(global symbol),当一个同名的弱符号(weak symbol)出现时,并不会发生错误。链接编辑器会以全局符号为准,忽略弱符号。与全局符号相似,如果已经存在的是一个公用符号,即st_shndx域为SHN_COMMON值的符号,当一个同名的弱符号(weak symbol)出现时,也不会发生错误。链接编辑器会以公用符号为准,忽略弱符号。• 在查找符号定义时,链接编辑器可能会搜索存档的库文件。如果是查找全局符号,链接编辑器会提取包含该未定义的全局符号的存档成员,存档成员可能是一个全局的符号,也可能是弱符号。而如果是查找弱符号,链接编辑器不会去提取存档成员。未解析的弱符号值为0。
STB_LOPROC ~ STB_HIPROC 为特殊处理器保留的属性区间。

符号表类型 | Symbol Table Type

简称 STT

STT_NOTYPE      本符号类型未指定。
STT_OBJECT      本符号是一个数据对象,比如变量,数组等。
STT_FUNC        本符号是一个函数,或者其它的可执行代码。函数符号在共享目标文件中有特殊的意义。当另外一个目标文件引用一个共享目标文件中的函数符号时,链接编辑器为被引用符号自动创建一个链接表项。非STT_FUNC类型的共享目标符号不会通过这种链接表项被自动引用。
STT_SECTION     本符号与一个区相关联,用于重定位,通常具有STB_LOCAL属性。
STT_FILE        本符号是一个文件符号,它具有STB_LOCAL属性,它的区索引值是SHN_ABS。在符号表中如果存在本类符号的话,它会出现在所有STB_LOCAL类符号的前部。
STT_LOPROC ~ STT_HIPROC 这一区间的符号类型为特殊处理器保留。

符号表可见性 | Symbol Table Visibility

简称 STV

STV_DEFAULT     当符号的可见性是STV_DEFAULT时,那么该符号的可见性由符号的绑定属性决定。这类情况下,(可执行文件和共享库中的)全局符号和弱符号默认是外部可访问的,本地符号默认外部是无法被访问的。但是,可见性是STV_DEFAULT的全局符号和弱符号是可被覆盖的。什么意思?举个最典型的例子,共享库中的可见性值为STV_DEFAULTD的全局符号和弱符号是可被可执行文件中的同名符号覆盖的。
STV_HIDDEN      当符号的可见性是STV_HIDDEN时,证明该符号是外部无法访问的。这个属性主要用来控制共享库对外接口的数量。需要注意的是,一个可见性为STV_HIDDEN的数据对象,如果能获取到该符号的地址,那么依然是可以访问或者修改该数据对象的。在可重定位文件中,如果一个符号的可见性是STV_HIDDEN的话,那么在链接生成可执行文件或者共享库的过程中,该符号要么被删除,要么绑定属性变成STB_LOCAL。
STV_PROTECTED   当符号的可见性是STV_PROTECTED时,它是外部可见的,这点跟可见性是STV_DEFAULT的一样,但不同的是它是不可覆盖的。这样的符号在共享库中比较常见。不可覆盖意味着如果是在该符号所在的共享库中访问这个符号,那么就一定是访问的这个符号,尽管可执行文件中也会存在同样名字的符号也不会被覆盖掉。规定绑定属性为STB_LOCAL的符号的可见性不可以是STV_PROTECTED。
STV_INTERNAL    该可见性属性的含义可以由处理器补充定义,以进一步约束隐藏的符号。 处理器补充程序的定义应使通用工具可以安全地将内部符号视为隐藏符号。当可重定位对象包含在可执行文件或共享对象中时,可重定位对象中包含的内部符号必须被链接编辑器删除或转换为STB_LOCAL绑定。

符号表索引 | Symbol Table Ndx

简称 STN
任何一个符号表项的定义都与某一个"区"相联系,因为符号是为区而定义,在区中被引用。本数据成员即指明了相关联的区。本数据成员是一个索引值,它指向相关联的区在区头表中的索引。在重定位过程中,区的位置会改变,本数据成员的值也随之改变,继续指向区的新位置。当本数据成员指向下面三种特殊的区索引值时,本符号具有如下特别的意义:

SHN_ABS     符号的值是绝对的,具有常量性,在重定位过程中,此值不需要改变。
SHN_COMMON  本符号所关联的是一个还没有分配的公共区,本符号的值规定了其内容的字区对齐规则,与sh_addralign相似。也就是说,链接器会为本符号分配存储空间,而且其起始地址是向st_value对齐的。本符号的值指明了要分配的字区数。
SHN_UNDEF   当一个符号指向第1区(SHN_UNDEF)时,表明本符号在当前目标文件中未定义,在链接过程中,链接器会找到此符号被定义的文件,并把这些文件链接在一起。本文件中对该符号的引用会被链接到实际的定义上去。

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN

图片

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 每日一练 - Overlay VPN 模型技术
  • docker 修改数据目录
  • Java面试题———MySql篇③
  • GD32双路CAN踩坑记录
  • 人才流失预测项目
  • MySQL(二)——CRUD
  • [数据集][目标检测]机械常用工具检测数据集VOC+YOLO格式4713张8类别
  • 小阿轩yx-Kubernetes Pod入门
  • 实现Bezier样条曲线
  • JAVA Unsafe 类介绍
  • 封装websocket
  • 代码随想录算法训练营day50 | 深度优先搜索理论基础、98. 所有可达路径、广度优先搜索理论基础
  • 教程:使用Python裁剪TIF影像为多个自定义大小的小块(分割栅格)
  • K8S 探针
  • 创建、使用、删除 数据库
  • isset在php5.6-和php7.0+的一些差异
  • Java程序员幽默爆笑锦集
  • java多线程
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • vue:响应原理
  • 猴子数据域名防封接口降低小说被封的风险
  • 简单数学运算程序(不定期更新)
  • 聊聊directory traversal attack
  • 前端之React实战:创建跨平台的项目架构
  • 人脸识别最新开发经验demo
  • 算法-插入排序
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 为什么要用IPython/Jupyter?
  • 主流的CSS水平和垂直居中技术大全
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ( 10 )MySQL中的外键
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (Python) SOAP Web Service (HTTP POST)
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (待修改)PyG安装步骤
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (回溯) LeetCode 40. 组合总和II
  • (十二)Flink Table API
  • (四)进入MySQL 【事务】
  • (学习日记)2024.02.29:UCOSIII第二节
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .Net Core 笔试1
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .net web项目 调用webService
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net 受管制代码
  • .NET6实现破解Modbus poll点表配置文件
  • .net网站发布-允许更新此预编译站点