objdump file 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Disassembly of section .plt: 0000000000402020 <.plt>: 402020: ff 35 e2 bf 02 00 pushq 0x2bfe2(%rip) # 42e008 <_GLOBAL_OFFSET_TABLE_+0x8> 402026: ff 25 e4 bf 02 00 jmpq *0x2bfe4(%rip) # 42e010 <_GLOBAL_OFFSET_TABLE_+0x10> 40202c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000402030 <_Znam@plt>: 402030: ff 25 e2 bf 02 00 jmpq *0x2bfe2(%rip) # 42e018 <_Znam@GLIBCXX_3.4> 402036: 68 00 00 00 00 pushq $0x0 40203b: e9 e0 ff ff ff jmpq 402020 <.plt> 0000000000402040 <_ZNSo3putEc@plt>: 402040: ff 25 da bf 02 00 jmpq *0x2bfda(%rip) # 42e020 <_ZNSo3putEc@GLIBCXX_3.4> 402046: 68 01 00 00 00 pushq $0x1 40204b: e9 d0 ff ff ff jmpq 402020 <.plt>
.plt
节主要实现了使用过程链接表(Procedure Linkage Table)实现延迟绑定 的功能。
openmp相关的执行 omp_outlined函数 问题:objdump 程序 有许多 类似 <.omp_outlined..16>: 的函数,但是main函数里并没有调用。实际openmp是怎么执行这些代码的呢?
在使用了OpenMP指令的C/C++程序编译后,编译器会自动生成一些名为.omp_outlined.
的函数。这些函数是OpenMP所需要的运行时支持函数,不是直接在main函数中调用的,其执行方式主要有以下几种:
一些关键的运行时函数,如线程创建、同步等,是在程序启动时由OpenMP运行时库初始化和直接调用的。
对于并行region,编译器会在主线程发起并行时调用对应的.omp_outlined.
函数创建线程并发布工作。
一些工作分配,同步等调用也是隐式通过运行时库的支持函数实现的。
对于并行循环,编译器会将循环体移动到.omp_outlined.
函数,在循环分配工作时调用。
减少指令,作用域变化等也会引发这些函数的调用。
所以.omp_outlined.
函数的执行是隐式通过运行时库触发和调度的,不需要用户代码直接调用。它们是OpenMP实现所必须的,由编译器和运行时库协调完成。用户只需要编写OpenMP指令,不必关心具体的调用细节。
总体来说,这是一种让并行执行透明化的实现机制,减少了用户的工作量。
OpenMP的汇编代码 不同平台不同,有GOMP_parallel_start开头的。也有如下x86平台的
1 2 3 4 5 6 7 8 9 10 11 405854: 48 c7 84 24 a0 00 00 movq $0x4293b9,0xa0(%rsp) 40585b: 00 b9 93 42 00 405860: 48 8d bc 24 90 00 00 lea 0x90(%rsp),%rdi 405867: 00 405868: ba 10 5f 40 00 mov $0x405f10,%edx 40586d: be 02 00 00 00 mov $0x2,%esi 405872: 4c 89 f9 mov %r15,%rcx 405875: 4c 8b 44 24 20 mov 0x20(%rsp),%r8 40587a: 31 c0 xor %eax,%eax 40587c: e8 ff cb ff ff callq 402480 <__kmpc_fork_call@plt> 405881: 48 8b 7c 24 60 mov 0x60(%rsp),%rdi
这段汇编代码实现了OpenMP中的并行构造,主要执行了以下几个步骤:
在栈上写入一个常量0x4293b9,可能是team的参数 (48 c7 84 24)
准备参数,获取rsp+0x90地址到rdi作为第1参数 (%rdi)
设置edx为0x405f10,可能是kmp_routine函数地址
esi设置为2,可能表示有2个参数
r15设置到rcx,传入线程号参数
r8传入栈上第0x20个参数,可能是void* shareds参数
清空eax,一些调用约定使用
调用 __kmpc_fork_call
函数,这是OpenMP的runtime库函数 ,用来并行执行一个函数
kmpc
fork multiple parallel call?
最后将返回值保存在rdi指定的栈空间上
所以这段代码实现了调用OpenMP runtime并行执行一个函数的操作,准备参数,调用runtime API,获取返回值的一个流程。
利用runtime库的支持函数可以实现汇编级别的OpenMP并行性。
readelf 各section位置以及含义,参考文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 $ readelf -S bfs.inj There are 37 section headers, starting at offset 0xbe8e8: 在文件内 0xbe8e8字节开始 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align 序号 节名称 节类型 节的虚拟地址偏移量 节在文件中的偏移量 节大小 每个条目的大小(如果大小固定) 节的标志 节的链接信息 节的额外信息 节的信息对齐方式 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 00000000004002a8 000002a8 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.gnu.build-i NOTE 00000000004002c4 000002c4 0000000000000024 0000000000000000 A 0 0 4 [ 3] .note.ABI-tag NOTE 00000000004002e8 000002e8 0000000000000020 0000000000000000 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0000000000400308 00000308 000000000000005c 0000000000000000 A 5 0 8 [ 5] .dynsym DYNSYM 0000000000400368 00000368 00000000000007e0 0000000000000018 A 6 1 8 [ 6] .dynstr STRTAB 0000000000400b48 00000b48 0000000000000b1d 0000000000000000 A 0 0 1 [ 7] .gnu.version VERSYM 0000000000401666 00001666 00000000000000a8 0000000000000002 A 5 0 2 [ 8] .gnu.version_r VERNEED 0000000000401710 00001710 0000000000000110 0000000000000000 A 6 5 8 [ 9] .rela.dyn RELA 0000000000401820 00001820 00000000000000f0 0000000000000018 A 5 0 8 [10] .rela.plt RELA 0000000000401910 00001910 00000000000006c0 0000000000000018 AI 5 24 8 [11] .init PROGBITS 0000000000402000 00002000 000000000000001b 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 0000000000402020 00002020 0000000000000490 0000000000000010 AX 0 0 16 [13] .text PROGBITS 00000000004024b0 000024b0 0000000000026475 0000000000000000 AX 0 0 16 [14] .fini PROGBITS 0000000000428928 00028928 000000000000000d 0000000000000000 AX 0 0 4 [15] .rodata PROGBITS 0000000000429000 00029000 0000000000001180 0000000000000000 A 0 0 16 [16] .eh_frame_hdr PROGBITS 000000000042a180 0002a180 00000000000002ac 0000000000000000 A 0 0 4 [17] .eh_frame PROGBITS 000000000042a430 0002a430 0000000000001780 0000000000000000 A 0 0 8 [18] .gcc_except_table PROGBITS 000000000042bbb0 0002bbb0 00000000000005d0 0000000000000000 A 0 0 4 [19] .init_array INIT_ARRAY 000000000042dbc8 0002cbc8 0000000000000010 0000000000000008 WA 0 0 8 [20] .fini_array FINI_ARRAY 000000000042dbd8 0002cbd8 0000000000000008 0000000000000008 WA 0 0 8 [21] .data.rel.ro PROGBITS 000000000042dbe0 0002cbe0 00000000000001f0 0000000000000000 WA 0 0 8 [22] .dynamic DYNAMIC 000000000042ddd0 0002cdd0 0000000000000220 0000000000000010 WA 6 0 8 [23] .got PROGBITS 000000000042dff0 0002cff0 0000000000000010 0000000000000008 WA 0 0 8 [24] .got.plt PROGBITS 000000000042e000 0002d000 0000000000000258 0000000000000008 WA 0 0 8 [25] .data PROGBITS 000000000042e258 0002d258 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 000000000042e280 0002d268 0000000000000180 0000000000000000 WA 0 0 64 [27] .comment PROGBITS 0000000000000000 0002d268 000000000000004a 0000000000000001 MS 0 0 1 [28] .debug_info PROGBITS 0000000000000000 0002d2b2 000000000002a06e 0000000000000000 0 0 1 [29] .debug_abbrev PROGBITS 0000000000000000 00057320 0000000000000a57 0000000000000000 0 0 1 [30] .debug_line PROGBITS 0000000000000000 00057d77 000000000000af9a 0000000000000000 0 0 1 [31] .debug_str PROGBITS 0000000000000000 00062d11 0000000000010328 0000000000000001 MS 0 0 1 [32] .debug_loc PROGBITS 0000000000000000 00073039 0000000000042846 0000000000000000 0 0 1 [33] .debug_ranges PROGBITS 0000000000000000 000b587f 00000000000054c0 0000000000000000 0 0 1 [34] .symtab SYMTAB 0000000000000000 000bad40 00000000000018c0 0000000000000018 35 106 8 [35] .strtab STRTAB 0000000000000000 000bc600 0000000000002177 0000000000000000 0 0 1 [36] .shstrtab STRTAB 0000000000000000 000be777 000000000000016c 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)
字段含义
Type 字段,具体含义参考文档1-10
Link 字段中的值是节头表中节头条目的索引,索引从0开始,表示第一个节头表条目,依此类推。比如5 代表与[ 5] .dynsym
有关
值得注意 One section type, SHT_NOBITS
described below, occupies no space in the file, and its sh_offset
member locates the conceptual placement in the file.
so the number “2d258” remains unchanged.
1 2 3 4 [25] .data PROGBITS 000000000042e258 0002d258 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 000000000042e280 0002d268 0000000000000180 0000000000000000 WA 0 0 64
.got global offset table
.plt This section holds the procedure linkage table. See ‘‘Special Sections’’ in Part 1 and ‘‘Procedure Linkage Table’’ in Part 2 for more information.
Function symbols (those with type STT_FUNC) in shared object files have special significance. When another object file references a function from a shared object, the link editor automatically creates a procedure linkage table entry for the referenced symbol.
参考文档2-17 page48
需要进一步的研究学习 暂无
遇到的问题 暂无
开题缘由、总结、反思、吐槽~~ 参考文献 上面回答部分来自ChatGPT-3.5 ,没有进行正确性的交叉校验。
无