一、目标文件

在 UNIX® 和 Linux® 中,任何事物都是文件。UNIX 和 Linux 编程实际上是编写处理各种文件的代码。系统由许多类型的文件组成,但目标文件具有一种特殊的设计,提供了灵活和多样的用途。

目标文件是包含带有附加地址和值的助记符号的路线图。这些符号可以用来对各种代码段和数据段进行命名,包括经过初始化的和未初始化的。它们也可以用来定位嵌入的调试信息,就像语义 Web,非常适合由程序进行阅读。

编译器可以将我们在代码编辑器中创建的文本转换为目标文件。最初,目标文件被称为代码的中间表示形式,因为它用作连接编辑器(即连接器)的输入,而连接编辑器最终完成整个任务并生成可执行的程序作为输出。

从代码到可执行代码的转换过程经过了良好的定义并实现了自动化,而目标文件是这个链中有机的连接性环节。在这个转换过程中,目标文件作为连接编辑器所使用的映象,使得它们能够解析各种符号并将不同的代码和数据段连接在一起形成统一的整体。

1.1 目标文件的格式

计算机编程领域中存在许多著名的目标文件格式。DOS 系列包括 COM、OBJ 和 EXE 格式。UNIX 和 Linux 使用 a.out、COFF 和 ELF。Microsoft® Windows® 使用可移植的执行文件 (PE) 格式,而 Macintosh 使用 PEF、Mach-O 和其他文件格式。

最初,各种类型的计算机具有自己独特的目标文件格式,但随着 UNIX 和其他在不同硬件平台上提供可移植性的操作系统的出现,一些常用的文件格式上升为通用的标准。其中包括 a.out、COFF 和 ELF 格式。

要了解目标文件,需要一组可以读取目标文件中不同部分并以更易于读取的格式显示这些内容的工具。

1.2 UNIX 目标文件

写一个简单的程序:hello.c

C 编译器的正常输出是用于所指定的目标处理器的汇编代码。汇编代码是汇编器的输入,在缺省情况下,汇编器将生成所有目标文件的祖先,即 a.out 文件。这个名称本身表示汇编输出 (Assembler Output)。要创建 a.out 文件,可以在 shell 窗口中输入下面的命令:gcc hello.c

最新的 C 编译器将编译和汇编步骤组合成一个步骤。我们可以指定不同开关选项以查看 C 编译器的汇编输出。通过输入下面的命令,我们可以看到 C 编译器的汇编输出:gcc -S hello.c

在当前目录下会生成 hello.s 文件,即为汇编输入文本。

  • 接下来研究目标文件,其中使用的有价值的工具有:
    • nm:列出目标文件中的符号。
    • objdump:显示目标文件中的详细信息。
    • readelf:显示关于 ELF 目标文件的信息。

1.2.1 nm:列出目标文件中的符号

执行命令:nm a.out

这些包含可执行代码的段称为正文段。同样地,数据段包含了不可执行的信息或数据。另一种类型的段,称为 BSS 段,它包含以符号数据开头的块。

对于 nm 命令列出的每个符号,它们的值使用十六进制来表示(缺省行为),并且在该符号前面加上了一个表示符号类型的编码字符。

  • 常见的各种编码包括:
    • A 表示绝对 (absolute),这意味着不能将该值更改为其他的连接;
    • B 表示 BSS 段中的符号;
    • C 表示引用未初始化的数据的一般符号。

可以将目标文件中所包含的不同的部分划分为段。段可以包含可执行代码、符号名称、初始数据值和许多其他类型的数据。

1.2.2 objdump:显示目标文件中的详细信息

通过输入下面的命令,可以看到目标文件中包含可执行代码的每个段的汇编清单。

objdump -d a.out

命令生成的代码如下所示:

 a.out:     file format elf64-x86-

 Disassembly of section .init:

 00000000004003c8 <_init>:
4003c8: ec sub $0x8,%rsp
4003cc: 8b 0c mov 0x200c25(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003d3: c0 test %rax,%rax
4003d6: je 4003dd <_init+0x15>
4003d8: e8 callq <__libc_start_main@plt+0x10>
4003dd: c4 add $0x8,%rsp
4003e1: c3 retq Disassembly of section .plt: 00000000004003f0 <puts@plt-0x10>:
4003f0: ff 0c pushq 0x200c12(%rip) # <_GLOBAL_OFFSET_TABLE_+0x8>
4003f6: ff 0c jmpq *0x200c14(%rip) # <_GLOBAL_OFFSET_TABLE_+0x10>
4003fc: 0f 1f nopl 0x0(%rax) <puts@plt>:
: ff 0c jmpq *0x200c12(%rip) # <_GLOBAL_OFFSET_TABLE_+0x18>
: pushq $0x0
40040b: e9 e0 ff ff ff jmpq 4003f0 <_init+0x28> <__libc_start_main@plt>:
: ff 0a 0c jmpq *0x200c0a(%rip) # <_GLOBAL_OFFSET_TABLE_+0x20>
: pushq $0x1
40041b: e9 d0 ff ff ff jmpq 4003f0 <_init+0x28> Disassembly of section .plt.got: <.plt.got>:
: ff d2 0b jmpq *0x200bd2(%rip) # 600ff8 <_DYNAMIC+0x1d0>
: xchg %ax,%ax Disassembly of section .text: <_start>:
: ed xor %ebp,%ebp
: d1 mov %rdx,%r9
: 5e pop %rsi
: e2 mov %rsp,%rdx
: e4 f0 and $0xfffffffffffffff0,%rsp
40043d: push %rax
40043e: push %rsp
40043f: c7 c0 c0 mov $0x4005c0,%r8
: c7 c1 mov $0x400550,%rcx
40044d: c7 c7 mov $0x400526,%rdi
: e8 b7 ff ff ff callq <__libc_start_main@plt>
: f4 hlt
40045a: 0f 1f nopw 0x0(%rax,%rax,) <deregister_tm_clones>:
: b8 3f mov $0x60103f,%eax
: push %rbp
: 2d sub $0x601038,%rax
40046c: f8 0e cmp $0xe,%rax
: e5 mov %rsp,%rbp
: 1b jbe <deregister_tm_clones+0x30>
: b8 mov $0x0,%eax
40047a: c0 test %rax,%rax
40047d: je <deregister_tm_clones+0x30>
40047f: 5d pop %rbp
: bf mov $0x601038,%edi
: ff e0 jmpq *%rax
: 0f 1f nopw 0x0(%rax,%rax,)
40048e:
: 5d pop %rbp
: c3 retq
: 0f 1f nopl 0x0(%rax)
: 2e 0f 1f nopw %cs:0x0(%rax,%rax,)
40049d: 00000000004004a0 <register_tm_clones>:
4004a0: be mov $0x601038,%esi
4004a5: push %rbp
4004a6: ee sub $0x601038,%rsi
4004ad: c1 fe sar $0x3,%rsi
4004b1: e5 mov %rsp,%rbp
4004b4: f0 mov %rsi,%rax
4004b7: c1 e8 3f shr $0x3f,%rax
4004bb: c6 add %rax,%rsi
4004be: d1 fe sar %rsi
4004c1: je 4004d8 <register_tm_clones+0x38>
4004c3: b8 mov $0x0,%eax
4004c8: c0 test %rax,%rax
4004cb: 0b je 4004d8 <register_tm_clones+0x38>
4004cd: 5d pop %rbp
4004ce: bf mov $0x601038,%edi
4004d3: ff e0 jmpq *%rax
4004d5: 0f 1f nopl (%rax)
4004d8: 5d pop %rbp
4004d9: c3 retq
4004da: 0f 1f nopw 0x0(%rax,%rax,) 00000000004004e0 <__do_global_dtors_aux>:
4004e0: 3d 0b cmpb $0x0,0x200b51(%rip) # <__TMC_END__>
4004e7: jne 4004fa <__do_global_dtors_aux+0x1a>
4004e9: push %rbp
4004ea: e5 mov %rsp,%rbp
4004ed: e8 6e ff ff ff callq <deregister_tm_clones>
4004f2: 5d pop %rbp
4004f3: c6 3e 0b movb $0x1,0x200b3e(%rip) # <__TMC_END__>
4004fa: f3 c3 repz retq
4004fc: 0f 1f nopl 0x0(%rax) <frame_dummy>:
: bf 0e mov $0x600e20,%edi
: 3f cmpq $0x0,(%rdi)
: jne <frame_dummy+0x10>
40050b: eb jmp 4004a0 <register_tm_clones>
40050d: 0f 1f nopl (%rax)
: b8 mov $0x0,%eax
: c0 test %rax,%rax
: f1 je 40050b <frame_dummy+0xb>
40051a: push %rbp
40051b: e5 mov %rsp,%rbp
40051e: ff d0 callq *%rax
: 5d pop %rbp
: e9 7a ff ff ff jmpq 4004a0 <register_tm_clones> <main>:
: push %rbp
: e5 mov %rsp,%rbp
40052a: ec sub $0x10,%rsp
40052e: 7d fc mov %edi,-0x4(%rbp)
: f0 mov %rsi,-0x10(%rbp)
: bf d4 mov $0x4005d4,%edi
40053a: e8 c1 fe ff ff callq <puts@plt>
40053f: b8 mov $0x0,%eax
: c9 leaveq
: c3 retq
: 2e 0f 1f nopw %cs:0x0(%rax,%rax,)
40054d: <__libc_csu_init>:
: push %r15
: push %r14
: ff mov %edi,%r15d
: push %r13
: push %r12
40055b: 4c 8d ae lea 0x2008ae(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
: push %rbp
: 8d 2d ae lea 0x2008ae(%rip),%rbp # 600e18 <__init_array_end>
40056a: push %rbx
40056b: f6 mov %rsi,%r14
40056e: d5 mov %rdx,%r13
: 4c e5 sub %r12,%rbp
: ec sub $0x8,%rsp
: c1 fd sar $0x3,%rbp
40057c: e8 fe ff ff callq 4003c8 <_init>
: ed test %rbp,%rbp
: je 4005a6 <__libc_csu_init+0x56>
: db xor %ebx,%ebx
: 0f 1f nopl 0x0(%rax,%rax,)
40058f:
: 4c ea mov %r13,%rdx
: 4c f6 mov %r14,%rsi
: ff mov %r15d,%edi
: ff dc callq *(%r12,%rbx,)
40059d: c3 add $0x1,%rbx
4005a1: eb cmp %rbp,%rbx
4005a4: ea jne <__libc_csu_init+0x40>
4005a6: c4 add $0x8,%rsp
4005aa: 5b pop %rbx
4005ab: 5d pop %rbp
4005ac: 5c pop %r12
4005ae: 5d pop %r13
4005b0: 5e pop %r14
4005b2: 5f pop %r15
4005b4: c3 retq
4005b5: nop
4005b6: 2e 0f 1f nopw %cs:0x0(%rax,%rax,)
4005bd: 00000000004005c0 <__libc_csu_fini>:
4005c0: f3 c3 repz retq Disassembly of section .fini: 00000000004005c4 <_fini>:
4005c4: ec sub $0x8,%rsp
4005c8: c4 add $0x8,%rsp
4005cc: c3 retq
 

每个可执行代码段将在需要特定的事件时执行,这些事件包括库的初始化和该程序本身主入口点。

对于着迷于底层编程细节的程序员来说,这是一个功能非常强大的工具,可用于研究编译器和汇编器的输出。细节信息,比如这段代码中所显示的这些信息,可以揭示有关本地处理器本身运行方式的很多内容。对该处理器制造商提供的技术文档进行深入的研究,我们可以收集关于一些有价值的信息,通过这些信息可以深入地了解内部的运行机制,因为功能程序提供了清晰的输出。

1.2.3 readelf:显示关于 ELF 目标文件的信息

readelf 程序也可以清楚地列出目标文件中的内容。输入下面的命令,可以看到这一点:

readelf -all a.out

输出如下:

 ELF Header:
Magic: 7f 4c
Class: ELF64
Data: 's complement, little endian
Version: (current)
OS/ABI: UNIX - System V
ABI Version:
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-
Version: 0x1
Entry point address: 0x400430
Start of program headers: (bytes into file)
Start of section headers: (bytes into file)
Flags: 0x0
Size of this header: (bytes)
Size of program headers: (bytes)
Number of program headers:
Size of section headers: (bytes)
Number of section headers:
Section header string table index: Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ ] NULL [ ] .interp PROGBITS
000000000000001c A
[ ] .note.ABI-tag NOTE
A
[ ] .note.gnu.build-i NOTE
A
[ ] .gnu.hash GNU_HASH
000000000000001c A
[ ] .dynsym DYNSYM 00000000004002b8 000002b8
A
[ ] .dynstr STRTAB
000000000000003d A
[ ] .gnu.version VERSYM
A
[ ] .gnu.version_r VERNEED
A
[ ] .rela.dyn RELA
A
[] .rela.plt RELA
AI
[] .init PROGBITS 00000000004003c8 000003c8
000000000000001a AX
[] .plt PROGBITS 00000000004003f0 000003f0
AX
[] .plt.got PROGBITS
AX
[] .text PROGBITS
AX
[] .fini PROGBITS 00000000004005c4 000005c4
AX
[] .rodata PROGBITS 00000000004005d0 000005d0
A
[] .eh_frame_hdr PROGBITS 00000000004005e4 000005e4
A
[] .eh_frame PROGBITS
00000000000000f4 A
[] .init_array INIT_ARRAY 0000000000600e10 00000e10
WA
[] .fini_array FINI_ARRAY 0000000000600e18 00000e18
WA
[] .jcr PROGBITS 0000000000600e20 00000e20
WA
[] .dynamic DYNAMIC 0000000000600e28 00000e28
00000000000001d0 WA
[] .got PROGBITS 0000000000600ff8 00000ff8
WA
[] .got.plt PROGBITS
WA
[] .data PROGBITS
WA
[] .bss NOBITS
WA
[] .comment PROGBITS
MS
[] .shstrtab STRTAB 000018cc
000000000000010c
[] .symtab SYMTAB [] .strtab STRTAB 000016b8 Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R
[Requesting program interpreter: /lib64/ld-linux-x86-.so.]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000070c 0x000000000000070c R E
LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
0x0000000000000228 0x0000000000000230 RW
DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28
0x00000000000001d0 0x00000000000001d0 RW
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R
GNU_EH_FRAME 0x00000000000005e4 0x00000000004005e4 0x00000000004005e4
0x0000000000000034 0x0000000000000034 R
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW
GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
0x00000000000001f0 0x00000000000001f0 R Section to Segment mapping:
Segment Sections... .interp
.interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
.init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
.dynamic
.note.ABI-tag .note.gnu.build-id
.eh_frame_hdr .init_array .fini_array .jcr .dynamic .got Dynamic section at offset 0xe28 contains entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.]
0x000000000000000c (INIT) 0x4003c8
0x000000000000000d (FINI) 0x4005c4
0x0000000000000019 (INIT_ARRAY) 0x600e10
0x000000000000001b (INIT_ARRAYSZ) (bytes)
0x000000000000001a (FINI_ARRAY) 0x600e18
0x000000000000001c (FINI_ARRAYSZ) (bytes)
0x000000006ffffef5 (GNU_HASH) 0x400298
0x0000000000000005 (STRTAB) 0x400318
0x0000000000000006 (SYMTAB) 0x4002b8
0x000000000000000a (STRSZ) (bytes)
0x000000000000000b (SYMENT) (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x601000
0x0000000000000002 (PLTRELSZ) (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x400398
0x0000000000000007 (RELA) 0x400380
0x0000000000000008 (RELASZ) (bytes)
0x0000000000000009 (RELAENT) (bytes)
0x000000006ffffffe (VERNEED) 0x400360
0x000000006fffffff (VERNEEDNUM)
0x000000006ffffff0 (VERSYM) 0x400356
0x0000000000000000 (NULL) 0x0 Relocation section '.rela.dyn' at offset 0x380 contains entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600ff8 R_X86_64_GLOB_DAT __gmon_start__ + Relocation section '.rela.plt' at offset 0x398 contains entries:
Offset Info Type Sym. Value Sym. Name + Addend
R_X86_64_JUMP_SLO puts@GLIBC_2.2.5 +
R_X86_64_JUMP_SLO __libc_start_main@GLIBC_2.2.5 + The decoding of unwind sections for machine type Advanced Micro Devices X86- is not currently supported. Symbol table '.dynsym' contains entries:
Num: Value Size Type Bind Vis Ndx Name
: NOTYPE LOCAL DEFAULT UND
: FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 ()
: FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 ()
: NOTYPE WEAK DEFAULT UND __gmon_start__ Symbol table '.symtab' contains entries:
Num: Value Size Type Bind Vis Ndx Name
: NOTYPE LOCAL DEFAULT UND
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: 00000000004002b8 SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: 00000000004003c8 SECTION LOCAL DEFAULT
: 00000000004003f0 SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: 00000000004005c4 SECTION LOCAL DEFAULT
: 00000000004005d0 SECTION LOCAL DEFAULT
: 00000000004005e4 SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: 0000000000600e10 SECTION LOCAL DEFAULT
: 0000000000600e18 SECTION LOCAL DEFAULT
: 0000000000600e20 SECTION LOCAL DEFAULT
: 0000000000600e28 SECTION LOCAL DEFAULT
: 0000000000600ff8 SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: SECTION LOCAL DEFAULT
: FILE LOCAL DEFAULT ABS crtstuff.c
: 0000000000600e20 OBJECT LOCAL DEFAULT __JCR_LIST__
: FUNC LOCAL DEFAULT deregister_tm_clones
: 00000000004004a0 FUNC LOCAL DEFAULT register_tm_clones
: 00000000004004e0 FUNC LOCAL DEFAULT __do_global_dtors_aux
: OBJECT LOCAL DEFAULT completed.
: 0000000000600e18 OBJECT LOCAL DEFAULT __do_global_dtors_aux_fin
: FUNC LOCAL DEFAULT frame_dummy
: 0000000000600e10 OBJECT LOCAL DEFAULT __frame_dummy_init_array_
: FILE LOCAL DEFAULT ABS hello.c
: FILE LOCAL DEFAULT ABS crtstuff.c
: OBJECT LOCAL DEFAULT __FRAME_END__
: 0000000000600e20 OBJECT LOCAL DEFAULT __JCR_END__
: FILE LOCAL DEFAULT ABS
: 0000000000600e18 NOTYPE LOCAL DEFAULT __init_array_end
: 0000000000600e28 OBJECT LOCAL DEFAULT _DYNAMIC
: 0000000000600e10 NOTYPE LOCAL DEFAULT __init_array_start
: 00000000004005e4 NOTYPE LOCAL DEFAULT __GNU_EH_FRAME_HDR
: OBJECT LOCAL DEFAULT _GLOBAL_OFFSET_TABLE_
: 00000000004005c0 FUNC GLOBAL DEFAULT __libc_csu_fini
: NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
: NOTYPE WEAK DEFAULT data_start
: FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
: NOTYPE GLOBAL DEFAULT _edata
: 00000000004005c4 FUNC GLOBAL DEFAULT _fini
: FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
: NOTYPE GLOBAL DEFAULT __data_start
: NOTYPE WEAK DEFAULT UND __gmon_start__
: OBJECT GLOBAL HIDDEN __dso_handle
: 00000000004005d0 OBJECT GLOBAL DEFAULT _IO_stdin_used
: FUNC GLOBAL DEFAULT __libc_csu_init
: NOTYPE GLOBAL DEFAULT _end
: FUNC GLOBAL DEFAULT _start
: NOTYPE GLOBAL DEFAULT __bss_start
: FUNC GLOBAL DEFAULT main
: NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
: OBJECT GLOBAL HIDDEN __TMC_END__
: NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
: 00000000004003c8 FUNC GLOBAL DEFAULT _init Version symbols section '.gnu.version' contains entries:
Addr: Offset: 0x000356 Link: (.dynsym)
: (*local*) (GLIBC_2.2.5) (GLIBC_2.2.5) (*local*) Version needs section '.gnu.version_r' contains entries:
Addr: 0x0000000000400360 Offset: 0x000360 Link: (.dynstr)
: Version: File: libc.so. Cnt:
0x0010: Name: GLIBC_2.2.5 Flags: none Version: Displaying notes found at file offset 0x00000254 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6. Displaying notes found at file offset 0x00000274 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: c0f3db4f9706877127ed96aa53ddd338e1632814
 

ELF Header 为该文件中所有段入口显示了详细的摘要。在列举出这些 Header 中的内容之前,可以看到 Header 的具体数目。在研究一个较大的目标文件时,该信息可能非常有用。

从该输出中看到的,简单的 a.out Hello World 文件中包含了大量有价值的细节信息,包括版本信息、柱状图、各种符号类型的表格,等等。

除了所有这些段之外,编译器可以将调试信息放入到目标文件中,并且还可以显示这些信息。输入下面的命令,仔细分析编译器的输出(假设您扮演了调试程序的角色):readelf --debug-dump a.out | less

1.3 目标文件

在 UNIX 中,可执行文件是目标文件,并且我们可以像对 a.out 文件那样对它们进行分析。

如果倾向于使用编译器和其他的语言工具,那么您可以对组成计算机系统的各种目标文件进行仔细研究。UNIX 操作系统具有许多层次,那些通过工具查看目标文件所公开的层次,非常接近底层硬件。通过这种方式,可以真实地接触到系统。

GCC编译器原理(二)------编译原理一:目标文件的更多相关文章

  1. Linux源码与编译出的目标文件汇编代码的一致性问题

    start_kernel是内核启动时比较重要的一个函数,然而我发现一个问题,我编译出来的目标文件中的汇编代码与C源码并不完全对应,这是怎么一回事呢? asmlinkage void __init st ...

  2. 使用gcc不同选项来编译查看中间生成文件

    gcc编译C程序的总体流程如下图 用到的命令如下: .c---> .i gcc -E hello.c .c--->.s gcc -S hello.c .c--->.o gcc -c ...

  3. clang在编译时指定目标文件所需的最低macOS版本

    调研这个的原因,是因为有个同事在macOS 12.2上打包好的程序,放在macOS 10.15上运行时报错: Dyld Error Message:  Symbol not found: __ZNKS ...

  4. 浅谈C++编译原理 ------ C++编译器与链接器工作原理

    原文:https://blog.csdn.net/zyh821351004/article/details/46425823 第一篇:      首先是预编译,这一步可以粗略的认为只做了一件事情,那就 ...

  5. Knowledge Point 20180303 对比编译器、解释器与Javac编译原理

    编译器与Javac编译原理 在前文我们知道了Java是一种编译语言和解释语言,它的源代码经过编译器Javac编译为能够被JVM识别的二进制语言,然后JVM将其解释为能够被平台识别的机器语言.那么什么是 ...

  6. GCC编译器原理(一)04------GCC 工具:nlmconv、nm、objcopy、objdump和 ranlib

    1.3.13 nlmconv nlmconv 将可重定位的对象文件(Infile)转换为 NetWare 可加载模块(outfile),并可选择读取头文件信息获取 NLM 头信息. 选项,描述 -I ...

  7. GCC编译器原理(一)03------GCC 工具:gprof、ld、libbfd、libiberty 和libopcodes

    1.3.7 gprof:性能分析工具 参考文档:https://www.cnblogs.com/andashu/p/6378000.html gprof是GNU profile工具,可以运行于linu ...

  8. linux下编译原理分析

    linux下编译hello.c 程序,使用gcc hello.c,然后./a.out就能够执行:在这个简单的命令后面隐藏了很多复杂的过程,这个过程包含了以下的步骤: ================= ...

  9. C语言_来了解一下GCC编译器编译C可执行脚本的过程

    GCC简介    Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作品之一.gcc是可以在多种硬体平台上编译出可执行程序的超级编译 ...

  10. 前端与编译原理——用JS写一个JS解释器

    说起编译原理,印象往往只停留在本科时那些枯燥的课程和晦涩的概念.作为前端开发者,编译原理似乎离我们很远,对它的理解很可能仅仅局限于"抽象语法树(AST)".但这仅仅是个开头而已.编 ...

随机推荐

  1. cf1000F One Occurrence (线段树)

    这题我是离线做的 设i位置的数上次出现的位置是pre[i](如果第一次出现那就是0) 可以想到,用线段树维护一个区间的pre的最小值,如果它小于区间左端点,那这个数就是一个合法的答案 但直接这样做是错 ...

  2. luogu P4299 首都

    题目描述 在X星球上有N个国家,每个国家占据着X星球的一座城市.由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的. X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失, ...

  3. 数组拆分I

    题目描述 给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最 ...

  4. Java,mysql String与date类型转换

    String 与 date类型转换 字符串转换成日期类型: SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");//小写 ...

  5. java thread 线程40个问题汇总

    http://www.codeceo.com/article/40-java-thread-problems.html 1.多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了, ...

  6. ubuntu 百度云

    下载链接:https://pan.baidu.com/s/1HBu5T3PZ8JsS93PgOKnUYw提取密码:6J1A 在终端中输入命令: sudo dpkg -i bcloud_3..1_all ...

  7. 洛谷P3959 宝藏

    去年NOIP第二毒瘤(并不)的题终于被我攻克了,接下来就只剩noip难度巅峰列队了. 首先说一下三种做法:随机化,状压DP和搜索. 前两种做法我都A了,搜索实在是毒瘤,写鬼啊. 有些带DFS的记忆化搜 ...

  8. Appium的图像界面浅说

    appium的图形用户界面(GUI) (1)Application中各个项的含义作用: Application Path:填写你需要测试的Android APK的包地址(两种方式:1直接点击Choos ...

  9. 斯坦福大学公开课机器学习: neural networks learning - autonomous driving example(通过神经网络实现自动驾驶实例)

    使用神经网络来实现自动驾驶,也就是说使汽车通过学习来自己驾驶. 下图是通过神经网络学习实现自动驾驶的图例讲解: 左下角是汽车所看到的前方的路况图像.左上图,可以看到一条水平的菜单栏(数字4所指示方向) ...

  10. php如何判断数组是一维还是多维

    php>4.2 int count ( mixed $var [, int $mode ] )  --  计算数组中的单元数目或对象中的属性个数  如果可选的 mode 参数设为 COUNT_R ...