【编译、链接、装载六】汇编——目标文件
【编译和链接六】汇编——目标文件
- 一、目标文件_存储格式
- 1、生成目标文件
- 2、目标文件存储格式
- 3、file查看文件格式
- 二、查看目标文件的内部结构——objdump
- 三、代码段
- 四、 数据段和只读数据段
- 五、 ELF文件结构描述
- 1、头文件
- 2、段表
- 2.1、重定位表
- 2.2、字符串表
- 2.3、查看重定位表 和 字符串表
- 六、调试信息
一、目标文件_存储格式
- 目标文件就是源代码编译后但未进行链接的那些中间文件(Windows的.obj和Linux下的.o)
1、生成目标文件
- 代码
#include<stdio.h>int global_init_var = 123;
int global_uninit_var;void show( int i )
{printf( "%d\n", i );
}int main()
{static int static_var = 456;static int static_var2;int a = 1;int b;show(a);return -1;
}
- 生成目标文件的指令
gcc -c hello.c -o hello.o
2、目标文件存储格式
目标文件跟可执行文件的内容与结构很相似,所以一般跟可执行文件格式一起采用一种格式存储。
在Windows下,我们可以统称它们为PECOFF文件格式。
在Linux下,我们可以将它们统称为ELF文件。
其他不太常见的可执行文件格式还有Intel/Microsoft的OMF(Object Module Format)、Unix a.out格式和MS-DOS .COM格式等。
不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。它们在Windows下都按照PE-COFF格式存储,Linux下按照ELF格式存储。静态链接库稍有不同,它是把很多目标文件捆绑在一起形成一个文件,再加上一些索引,你可以简单地把它理解为一个包含有很多目标文件的文件包。
3、file查看文件格式
- file:查看文件格式
$file hello.o
二、查看目标文件的内部结构——objdump
一般目标文件将这些信息按不同的属性,以“节”(Section)的形式存储,有时候也叫“段”(Segment).
在一般情况下,它们都表示一个一定长度的区域,基本上不加以区别,唯一的区别是在ELF的链接视图和装载视图的时候,后面会专门提到。
- objdump指令,参数“-h”就是把ELF文件的各个段的基本信息打印出来。我们也可以使用“objdump –x”把更多的信息打印出来.
$objdump -h hello.o
$objdump -x hello.o
如上图,目标文件的格式是ELF,从图中可以看到,ELF文件的开头是一个“文件头”,它描述了整个文件的文件属性,包括文件是否可执行、是静态链接还是动态链接及入口地址(如果是可执行文件)、目标硬件、目标操作系统等信息,文件头还包括一个段表(Section Table),段表其实是一个描述文件中各个段的数组。段表描述了文件中各个段在文件中的偏移位置及段的属性等,从段表里面可以得到每个段的所有信息。文件头后面就是各个段的内容,比如代码段保存的就是程序的指令,数据段保存的就是程序的静态变量
段 | 段名 | 解释 |
---|---|---|
.code或.text | 代码段 | 程序源代码编译后的机器指令经常被放在代码段(Code Section)里 |
.data | 数据段 | 全局变量和局部静态变量数据经常放在数据段(Data Section)。让我们 |
.bss | 数据段 | 未初始化的全局变量和局部静态变量一般放在一个叫.“bss”的段里。 |
.rodata | 数据段 | 只读数据段,const的全局变量,#define定义的常量,以及诸如“Hello World”的字符串常量 |
.comment | 注释信息段 | 没太懂 |
.note.GNU-stack | 编译信息 | 编译器的版本信息段 |
.en_frame | 调试信息 | 调试时,栈回溯时用到 |
const修饰的全局变量在常量区;const修饰的局部变量只是为了防止修改,没有放入常量区(代码区.text)。
未初始化的全局变量和局部静态变量默认值都为0,本来它们也可以被放在.data段的,但是因为它们都是0,所以为它们在.data段分配空间并且存放数据0是没有必要的。程序运行的时候它们的确是要占内存空间的,并且可执行文件必须记录所有未初始化的全局量和局部静态变量的大小总和,记为.bss段。所以.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,它并没有内容,所以它在文件中也不占据空间。
数据段,.bss、.rdata、.data
导出数据段,.edata
导入数据段,.idata
段是导入数据,.idata
.edata段包含了应用程序或DLL的导出数据。在这个段出现的时候,它会包含一个到达导出信息的导出目录。
- 查看目标文件详细信息
$objdump -x hello.o
- size命令
做“size”,它可以用来查看ELF文件的代码段、数据段和BSS段的长度(dec表示3个段长度的和的十进制,hex表示长度和的十六进制):
三、代码段
- objdump的 “-s”参数可以将所有段的内容以十六进制的方式打印出来 ,“-d ”参数可以将所有包含指令的段反汇编。
$gcc -c hello.c -o hello.o
[dev1@localhost test01]$ gcc -c hello.c -o hello.o
[dev1@localhost test01]$ objdump -s -d hello.ohello.o: 文件格式 elf64-x86-64Contents of section .text:0000 554889e5 4883ec10 897dfc8b 45fc89c6 UH..H....}..E...0010 bf000000 00b80000 0000e800 000000c9 ................0020 c3554889 e54883ec 10c745fc 01000000 .UH..H....E.....0030 8b45fc89 c7e80000 0000b8ff ffffffc9 .E..............0040 c3 .
Contents of section .data:0000 7b000000 c8010000 {.......
Contents of section .rodata:0000 25640a00 %d..
Contents of section .comment:0000 00474343 3a202847 4e552920 342e382e .GCC: (GNU) 4.8.0010 35203230 31353036 32332028 52656420 5 20150623 (Red 0020 48617420 342e382e 352d3434 2900 Hat 4.8.5-44).
Contents of section .eh_frame:0000 14000000 00000000 017a5200 01781001 .........zR..x..0010 1b0c0708 90010000 1c000000 1c000000 ................0020 00000000 21000000 00410e10 8602430d ....!....A....C.0030 065c0c07 08000000 1c000000 3c000000 .\..........<...0040 00000000 20000000 00410e10 8602430d .... ....A....C.0050 065b0c07 08000000 .[...... Disassembly of section .text:0000000000000000 <show>:0: 55 push %rbp1: 48 89 e5 mov %rsp,%rbp4: 48 83 ec 10 sub $0x10,%rsp8: 89 7d fc mov %edi,-0x4(%rbp)b: 8b 45 fc mov -0x4(%rbp),%eaxe: 89 c6 mov %eax,%esi10: bf 00 00 00 00 mov $0x0,%edi15: b8 00 00 00 00 mov $0x0,%eax1a: e8 00 00 00 00 callq 1f <show+0x1f>1f: c9 leaveq 20: c3 retq 0000000000000021 <main>:21: 55 push %rbp22: 48 89 e5 mov %rsp,%rbp25: 48 83 ec 10 sub $0x10,%rsp29: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp)30: 8b 45 fc mov -0x4(%rbp),%eax33: 89 c7 mov %eax,%edi35: e8 00 00 00 00 callq 3a <main+0x19>3a: b8 ff ff ff ff mov $0xffffffff,%eax3f: c9 leaveq 40: c3 retq
[dev1@localhost test01]$
跟前面我们了解到的“.text”段长度相符合,最左面一列是偏移量,中间4列是十六进制内容,最右面一列是.text段的ASCII码形式。对照下面的反汇编结果,可以很明显地看到,.text段里所包含的正是hello.c里两个函数 func1() 和 main() 的指令
四、 数据段和只读数据段
- .data段保存的是那些已经初始化了的全局静态变量和局部静态变量。前面的SimpleSection.c代码里面一共有两个这样的变量,分别是global_init_varabal 与 static_var 。这两个变量每个4个字节,一共刚好8个字节,所以“.data”这个段的大小为8个字节。
- SimpleSection.c里面我们在调用“printf”的时候,用到了一个字符串常量“%d\n”,它是一种只读数据,所以它被放到了“.rodata”段,我们可以从输出结果看到“.rodata”这个段的4个字节刚好是这个字符串常量的ASCII字节序,最后以\0结尾。
- “.rodata”段存放的是只读数据,一般是程序里面的只读变量(如const修饰的变量)和字符串常量。单独设立“.rodata”段有很多好处,不光是在语义上支持了C++的const关键字,而且操作系统在加载的时候可以将“.rodata”段的属性映射成只读,
有时候编译器会把字符串常量放到“.data”段,而不会单独放在“.rodata”段。
objdump -x -s -d hello.o
[dev1@localhost test01]$ objdump -x -s -d hello.ohello.o: 文件格式 elf64-x86-64
hello.o
体系结构:i386:x86-64,标志 0x00000011:
HAS_RELOC, HAS_SYMS
起始地址 0x0000000000000000节:
Idx Name Size VMA LMA File off Algn0 .text 00000041 0000000000000000 0000000000000000 00000040 2**0CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data 00000008 0000000000000000 0000000000000000 00000084 2**2CONTENTS, ALLOC, LOAD, DATA2 .bss 00000004 0000000000000000 0000000000000000 0000008c 2**2ALLOC3 .rodata 00000004 0000000000000000 0000000000000000 0000008c 2**0CONTENTS, ALLOC, LOAD, READONLY, DATA4 .comment 0000002e 0000000000000000 0000000000000000 00000090 2**0CONTENTS, READONLY5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000be 2**0CONTENTS, READONLY6 .eh_frame 00000058 0000000000000000 0000000000000000 000000c0 2**3CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 hello.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000000 l O .bss 0000000000000004 static_var2.2184
0000000000000004 l O .data 0000000000000004 static_var.2183
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g O .data 0000000000000004 global_init_var
0000000000000004 O *COM* 0000000000000004 global_uninit_var
0000000000000000 g F .text 0000000000000021 show
0000000000000000 *UND* 0000000000000000 printf
0000000000000021 g F .text 0000000000000020 mainContents of section .text:0000 554889e5 4883ec10 897dfc8b 45fc89c6 UH..H....}..E...0010 bf000000 00b80000 0000e800 000000c9 ................0020 c3554889 e54883ec 10c745fc 01000000 .UH..H....E.....0030 8b45fc89 c7e80000 0000b8ff ffffffc9 .E..............0040 c3 .
Contents of section .data:0000 7b000000 c8010000 {.......
Contents of section .rodata:0000 25640a00 %d..
Contents of section .comment:0000 00474343 3a202847 4e552920 342e382e .GCC: (GNU) 4.8.0010 35203230 31353036 32332028 52656420 5 20150623 (Red 0020 48617420 342e382e 352d3434 2900 Hat 4.8.5-44).
Contents of section .eh_frame:0000 14000000 00000000 017a5200 01781001 .........zR..x..0010 1b0c0708 90010000 1c000000 1c000000 ................0020 00000000 21000000 00410e10 8602430d ....!....A....C.0030 065c0c07 08000000 1c000000 3c000000 .\..........<...0040 00000000 20000000 00410e10 8602430d .... ....A....C.0050 065b0c07 08000000 .[...... Disassembly of section .text:0000000000000000 <show>:0: 55 push %rbp1: 48 89 e5 mov %rsp,%rbp4: 48 83 ec 10 sub $0x10,%rsp8: 89 7d fc mov %edi,-0x4(%rbp)b: 8b 45 fc mov -0x4(%rbp),%eaxe: 89 c6 mov %eax,%esi10: bf 00 00 00 00 mov $0x0,%edi11: R_X86_64_32 .rodata15: b8 00 00 00 00 mov $0x0,%eax1a: e8 00 00 00 00 callq 1f <show+0x1f>1b: R_X86_64_PC32 printf-0x41f: c9 leaveq 20: c3 retq 0000000000000021 <main>:21: 55 push %rbp22: 48 89 e5 mov %rsp,%rbp25: 48 83 ec 10 sub $0x10,%rsp29: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp)30: 8b 45 fc mov -0x4(%rbp),%eax33: 89 c7 mov %eax,%edi35: e8 00 00 00 00 callq 3a <main+0x19>36: R_X86_64_PC32 show-0x43a: b8 ff ff ff ff mov $0xffffffff,%eax3f: c9 leaveq 40: c3 retq
[dev1@localhost test01]$
下一篇文章,详细的展示下全局变量、局部变量、常量、static、const,分别存储在哪儿?
五、 ELF文件结构描述
1、头文件
我们已经通过SimpleSection.o的结构大致了解了ELF文件的轮廓,接着就来看看ELF文件的结构格式。
ELF目标文件格式的最前部是ELF文件头(ELF Header),它包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等。
- 我们可以用readelf命令来详细查看ELF文件
[dev1@localhost test01]$ readelf -h hello.o
ELF 头:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64数据: 2 补码,小端序 (little endian)版本: 1 (current)OS/ABI: UNIX - System VABI 版本: 0类型: REL (可重定位文件)系统架构: Advanced Micro Devices X86-64版本: 0x1入口点地址: 0x0程序头起点: 0 (bytes into file)Start of section headers: 984 (bytes into file)标志: 0x0本头的大小: 64 (字节)程序头大小: 0 (字节)Number of program headers: 0节头大小: 64 (字节)节头数量: 13字符串表索引节头: 12
从上面输出的结果可以看到,ELF的文件头中定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段的数量等。
- 类型
2、段表
我们知道ELF文件中有很多各种各样的段,这个段表(Section Header Table)就是保存这些段的基本属性的结构。
前文中我们使用了“objudmp -h”来查看ELF文件中包含的段,结果是SimpleSection里面看到了总共有6个段,分别是 “.code”、“.data”、“.bss ”、“.rodata ”、“. comment ”和“. note.GNU-stack ”。实际上的情况却有所不同,“objdump -h”命令只是把ELF文件中关键的段显示了出来,而省略了其他的辅助性的段,比如:符号表、字符串表、段名字符串表、重定位表等。我们可以使用readelf工具来查看ELF文件的段,它显示出来的结果才是真正的段表结构:
注意:这是大写的-S
[dev1@localhost test01]$ readelf -S hello.o
共有 13 个节头,从偏移量 0x3d8 开始:节头:[号] 名称 类型 地址 偏移量大小 全体大小 旗标 链接 信息 对齐[ 0] NULL 0000000000000000 000000000000000000000000 0000000000000000 0 0 0[ 1] .text PROGBITS 0000000000000000 000000400000000000000041 0000000000000000 AX 0 0 1[ 2] .rela.text RELA 0000000000000000 000002f80000000000000048 0000000000000018 I 10 1 8[ 3] .data PROGBITS 0000000000000000 000000840000000000000008 0000000000000000 WA 0 0 4[ 4] .bss NOBITS 0000000000000000 0000008c0000000000000004 0000000000000000 WA 0 0 4[ 5] .rodata PROGBITS 0000000000000000 0000008c0000000000000004 0000000000000000 A 0 0 1[ 6] .comment PROGBITS 0000000000000000 00000090000000000000002e 0000000000000001 MS 0 0 1[ 7] .note.GNU-stack PROGBITS 0000000000000000 000000be0000000000000000 0000000000000000 0 0 1[ 8] .eh_frame PROGBITS 0000000000000000 000000c00000000000000058 0000000000000000 A 0 0 8[ 9] .rela.eh_frame RELA 0000000000000000 000003400000000000000030 0000000000000018 I 10 8 8[10] .symtab SYMTAB 0000000000000000 000001180000000000000180 0000000000000018 11 11 8[11] .strtab STRTAB 0000000000000000 00000298000000000000005d 0000000000000000 0 0 1[12] .shstrtab STRTAB 0000000000000000 000003700000000000000061 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)
- 目标文件——常用段名
常用段名 | Value |
---|---|
.text | 代码段,存放代码和局部const变量 |
.rela.text | 重定位表,重定位的信息 |
.data | 保存的是那些已经初始化了的全局静态变量和局部静态变量 |
.bbs | 存放的是未初始化的全局变量和局部静态变量 |
.rodata | read only data 。存放的是只读数据,比如字符串常量,全局const变量。 |
.comment | 存放的是编译器的版本信息,比如字符串: |
.note | 额外的编译器信息。比如程序的公司名,发布版本号等。 |
.en_frame | 调用栈信息 |
.rela…en_frame | 重定位的调用栈信息 |
.systab | symbol table 符号表 |
.strtab | string table ,字符串表,用于存储ELE文件中用到的字符串 |
.shstrtab | section string table 段名表 |
2.1、重定位表
链接器在处理目标文件时,须要对目标文件中某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用的位置。这些重定位的信息都记录在ELF文件的重定位表里面,对于每个须要重定位的代码段或数据段,都会有一个相应的重定位表。
“.data”段则没有对绝对地址的引用,它只包含了几个常量,所以hello.o中没有针对“.data”段的重定位表“.rel.data”
2.2、字符串表
常见的段名为“.strtab”或“.shstrtab”。这两个字符串表分别为字符串表(String Table)和段表字符串表(Section Header String Table)。
- 字符串表用来保存普通的字符串,比如符号的名字;
- 段表字符串表用来保存段表中用到的字符串,最常见的就是段名( sh_name )。
我们可以使用很多工具来查看ELF文件的符号表,比如readelf、objdump、nm等,比如使用“nm”来查看“hello.o”的符号结果如下
[dev1@localhost test01]$ nm hello.o
0000000000000000 D global_init_var
0000000000000004 C global_uninit_var
0000000000000021 T mainU printf
0000000000000000 T show
0000000000000004 d static_var.2183
0000000000000000 b static_var2.2184
[dev1@localhost test01]$
2.3、查看重定位表 和 字符串表
[dev1@localhost test01]$ readelf -a hello.o
ELF 头:Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64数据: 2 补码,小端序 (little endian)版本: 1 (current)OS/ABI: UNIX - System VABI 版本: 0类型: REL (可重定位文件)系统架构: Advanced Micro Devices X86-64版本: 0x1入口点地址: 0x0程序头起点: 0 (bytes into file)Start of section headers: 984 (bytes into file)标志: 0x0本头的大小: 64 (字节)程序头大小: 0 (字节)Number of program headers: 0节头大小: 64 (字节)节头数量: 13字符串表索引节头: 12节头:[号] 名称 类型 地址 偏移量大小 全体大小 旗标 链接 信息 对齐[ 0] NULL 0000000000000000 000000000000000000000000 0000000000000000 0 0 0[ 1] .text PROGBITS 0000000000000000 000000400000000000000041 0000000000000000 AX 0 0 1[ 2] .rela.text RELA 0000000000000000 000002f80000000000000048 0000000000000018 I 10 1 8[ 3] .data PROGBITS 0000000000000000 000000840000000000000008 0000000000000000 WA 0 0 4[ 4] .bss NOBITS 0000000000000000 0000008c0000000000000004 0000000000000000 WA 0 0 4[ 5] .rodata PROGBITS 0000000000000000 0000008c0000000000000004 0000000000000000 A 0 0 1[ 6] .comment PROGBITS 0000000000000000 00000090000000000000002e 0000000000000001 MS 0 0 1[ 7] .note.GNU-stack PROGBITS 0000000000000000 000000be0000000000000000 0000000000000000 0 0 1[ 8] .eh_frame PROGBITS 0000000000000000 000000c00000000000000058 0000000000000000 A 0 0 8[ 9] .rela.eh_frame RELA 0000000000000000 000003400000000000000030 0000000000000018 I 10 8 8[10] .symtab SYMTAB 0000000000000000 000001180000000000000180 0000000000000018 11 11 8[11] .strtab STRTAB 0000000000000000 00000298000000000000005d 0000000000000000 0 0 1[12] .shstrtab STRTAB 0000000000000000 000003700000000000000061 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)There are no section groups in this file.本文件中没有程序头。重定位节 '.rela.text' 位于偏移量 0x2f8 含有 3 个条目:偏移量 信息 类型 符号值 符号名称 + 加数
000000000011 00050000000a R_X86_64_32 0000000000000000 .rodata + 0
00000000001b 000e00000002 R_X86_64_PC32 0000000000000000 printf - 4
000000000036 000d00000002 R_X86_64_PC32 0000000000000000 show - 4重定位节 '.rela.eh_frame' 位于偏移量 0x340 含有 2 个条目:偏移量 信息 类型 符号值 符号名称 + 加数
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + 21The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.Symbol table '.symtab' contains 16 entries:Num: Value Size Type Bind Vis Ndx Name0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 5 6: 0000000000000000 4 OBJECT LOCAL DEFAULT 4 static_var2.21847: 0000000000000004 4 OBJECT LOCAL DEFAULT 3 static_var.21838: 0000000000000000 0 SECTION LOCAL DEFAULT 7 9: 0000000000000000 0 SECTION LOCAL DEFAULT 8 10: 0000000000000000 0 SECTION LOCAL DEFAULT 6 11: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 global_init_var12: 0000000000000004 4 OBJECT GLOBAL DEFAULT COM global_uninit_var13: 0000000000000000 33 FUNC GLOBAL DEFAULT 1 show14: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf15: 0000000000000021 32 FUNC GLOBAL DEFAULT 1 mainNo version information found in this file.
[dev1@localhost test01]$
六、调试信息
如果我们在GCC编译时加上“-g”参数,编译器就会在产生的目标文件里面加上调试信息,我们通过readelf等工具可以看到,目标文件里多了很多“debug”相关的段:
[dev1@localhost test01]$ gcc -c hello.c -o hello.o -g
[dev1@localhost test01]$ objdump -h hello.ohello.o: 文件格式 elf64-x86-64节:
Idx Name Size VMA LMA File off Algn0 .text 00000041 0000000000000000 0000000000000000 00000040 2**0CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data 00000008 0000000000000000 0000000000000000 00000084 2**2CONTENTS, ALLOC, LOAD, DATA2 .bss 00000004 0000000000000000 0000000000000000 0000008c 2**2ALLOC3 .rodata 00000004 0000000000000000 0000000000000000 0000008c 2**0CONTENTS, ALLOC, LOAD, READONLY, DATA4 .debug_info 00000129 0000000000000000 0000000000000000 00000090 2**0CONTENTS, RELOC, READONLY, DEBUGGING5 .debug_abbrev 000000a9 0000000000000000 0000000000000000 000001b9 2**0CONTENTS, READONLY, DEBUGGING6 .debug_aranges 00000030 0000000000000000 0000000000000000 00000262 2**0CONTENTS, RELOC, READONLY, DEBUGGING7 .debug_line 00000041 0000000000000000 0000000000000000 00000292 2**0CONTENTS, RELOC, READONLY, DEBUGGING8 .debug_str 00000119 0000000000000000 0000000000000000 000002d3 2**0CONTENTS, READONLY, DEBUGGING9 .comment 0000002e 0000000000000000 0000000000000000 000003ec 2**0CONTENTS, READONLY10 .note.GNU-stack 00000000 0000000000000000 0000000000000000 0000041a 2**0CONTENTS, READONLY11 .eh_frame 00000058 0000000000000000 0000000000000000 00000420 2**3CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
参考
1、《程序员的自我修养链接装载与库》
相关文章:

【编译、链接、装载六】汇编——目标文件
【编译和链接六】汇编——目标文件 一、目标文件_存储格式1、生成目标文件2、目标文件存储格式3、file查看文件格式 二、查看目标文件的内部结构——objdump三、代码段四、 数据段和只读数据段五、 ELF文件结构描述1、头文件2、段表2.1、重定位表2.2、字符串表2.3、查看重定位表…...
王道计算机考研408计算机组成原理汇总(下)
提示:真正的英雄是明白世界的残酷,也遭受了社会带给他的苦难,他依然能用心的说“我热爱这个世界,我愿竭尽所能去为我的世界而好好战斗 文章目录 前言4.1.1 指令格式4.1.2 扩展操作码指令格式4.2.1 指令寻址4.2.2 数据寻址4.2.3 偏移寻址4.2.4 堆栈寻址汇总前言4.3.1 高级语…...

偏向锁、轻量级锁、重量级锁、自旋锁、自适应自旋锁
1. 偏向锁 偏向锁就是在运行过程中,对象的锁偏向某个线程。即在开启偏向锁机制的情况下,某个线程获得锁,当该线程下次再想要获得锁时,不需要重新申请获得锁(即忽略synchronized关键词),直接就可…...

Delta 一个新的 git diff 对比显示工具
目录 介绍git diff 介绍delta介绍 一、安装1.下载 Git2.下载 delta3.解压4.修改配置文件5. 修改主题6.其他配置和说明 二、对比命令1.在项目中 git diff 常用命令2.对比电脑上两个文件3.对比电脑上的两个文件夹 三、在Git 命令行中使用效果四、在idea 的Terminal命令行中使用效…...
C# 二进制序列化和反序列化示例
.NET框架提供了两种种串行化的方式: 1、是使用BinaryFormatter进行串行化; 2、使用XmlSerializer进行串行化。 第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息,而第二种将数据流格式化为XML存储。可以使用[Serializable]属…...

【CSS】文字扫光 | 渐变光
码来 可调整角度与颜色值来改变效果 <p class"gf-gx-color">我是帅哥</p> <style>.gf-gx-color {background: -webkit-linear-gradient(135deg,red,red 25%,red 50%,#fff 55%,red 60%,red 80%,red 95%,red);-webkit-text-fill-color: transparen…...

Overhaul Distillation(ICCV 2019)原理与代码解析
paper:A Comprehensive Overhaul of Feature Distillation official implementation:GitHub - clovaai/overhaul-distillation: Official PyTorch implementation of "A Comprehensive Overhaul of Feature Distillation" (ICCV 2019) 本文的…...

<Linux开发>驱动开发 -之-内核定时器与中断
<Linux开发>驱动开发 -之-内核定时器与中断 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详…...

希尔贝壳邀您参加2023深圳国际人工智能展览会
2023深圳国际人工智能展览会“AIE”将于2023年5月16-18日在深圳国际会展中心 (宝安)举办,希尔贝壳受邀参加,展位号:A331。 伴随着智能行业的快速发展,展会已被越来越多的企业列入每年必选展会,也成为各采购商选购的理…...

设计优质微信小程序的实用指南!
微信小程序是一种快速发展的应用形式,设计良好的小程序能够提升用户体验并吸引更多的用户。在设计微信小程序时,有一些关键的指南可以帮助我们做出出色的设计。以下是即时设计总结的一些设计指南,希望能对准备设计微信小程序的人有所帮助。 …...
大数据期末总结
文章目录 一、这学期分别学习了Scala、spark、spring、SpringMvc、SpringBoot1、scala2、spark3、spring4、SpringMvc5、SpringBoot 二、总结 一、这学期分别学习了Scala、spark、spring、SpringMvc、SpringBoot 1、scala Scala是一门基于JVM的编程语言,具有强大的…...

selenium面试题总结
今天有同学问到seleinum面试的时候会问到的问题,随便想了想,暂时纪录一下。欢迎大家在评论中提供更多问题。 1.selenium中如何判断元素是否存在? selenium中没有提供原生的方法判断元素是否存在,一般我们可以通过定位元素异常捕获…...

⑧电子产品拆解分析-1拖4USB拓展坞
⑧电子产品拆解分析-1拖4USB拓展坞 一、功能介绍二、电路分析以及器件作用1、内部电路拆解三、参考资料学习一、功能介绍 ①USB2.0一拖四通讯;②具备OTG功能,可适配大部分USB接口设备;二、电路分析以及器件作用 1、内部电路拆解 分析:❤️ ❤️ ❤️ 主控是MA8601 USB 2.0…...

月度精华汇总 | 最新XR行业资讯、场景案例、活动都在这一篇里啦!
在过去的一个月中,平行云为您带来了关于XR领域的一系列精彩文章,涵盖了行业资讯、应用案例,市场互动,帮助您掌握XR领域最新动态,了解实时云渲染、Cloud XR技术的价值,以及平行云实时云渲染解决方案LarkX…...

Redis实战案例1-短信登录
Redis的共享session应用 1. 项目的相关工作 导入sql文件 找到对应的sql文件即可 基本表的信息 基本架构 导入对应的项目文件,启动相关的service服务; 在nginx-1.18.0目录下启动命令行start nginx.exe; 2. 基于session实现登录的流程 这里利用到Javaweb中…...

华为OD机试真题 JavaScript 实现【找终点】【2023 B卷 100分】,附详细解题思路
一、题目描述 给定一个正整数数组,设为nums,最大为100个成员,求从第一个成员开始,正好走到数组最后一个成员,所使用的最少步骤数。 要求: 第一步必须从第一元素开始,且1 < 第一步的步长 &…...
详解数据仓库数据湖及湖仓一体
比别人更快接收好文章 随着近几年数据湖概念的兴起,业界对于数据仓库和数据湖的对比甚至争论就一直不断。有人说数据湖是下一代大数据平台,各大云厂商也在纷纷的提出自己的数据湖解决方案,一些云数仓产品也增加了和数据湖联动的特性。 但是…...
基于注解切换、Hikari实现的SpringBoot动态数据源(支持JNDI)
实现效果 先说效果,要实现方法级别注解切换当前数据源,不设置注解时走默认数据源,同时支持JNDI源。 总体思路 Spring框架中存在一个抽象类AbstractRoutingDataSource,他是一个可以动态选择当前DataSource的路由类,我…...

Java中的动态链接VS操作系统动态链接
在操作系统OS中为了优化内存的使用会采用一种动态链接方式,一个文件想要在操作系统中运行必须经过编译、汇编译、链接、装载等步骤。可以参考Java程序是怎么跑起来的。本篇主要讲解Java栈帧中动态链接部分与操作系统的的动态链接的区别与联系 操纵系统为什么需要动态…...

深入理解Linux虚拟内存管理(七)
系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 Linux 设备驱动程序 Linux设备驱动开发详解 深入理解Linux虚拟内存管理(一) 深入理解Linux虚拟内存管理(二) 深入理解Linux虚拟内存管理(三) 深入理…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...