首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >调试符号如何影响由GCC编译的Linux可执行文件的性能?

调试符号如何影响由GCC编译的Linux可执行文件的性能?
EN

Stack Overflow用户
提问于 2011-12-30 13:31:35
回答 2查看 10.5K关注 0票数 33

在所有其他因素相同的情况下(例如优化级别),在ELF中拥有调试符号或其他因素会如何影响:

  1. 加载时间。
  2. 运行时memory footprint.
  3. Runtime performance?

可以做些什么来减轻任何负面影响?

编辑我看过这个问题,但我发现讨论没有帮助,因为代码优化因素在那里混淆了这个问题。Why does my code run slower with multiple threads than with a single thread when it is compiled for profiling (-pg)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-30 13:54:36

调试符号位于与代码/数据部分完全不同的部分。你可以用objdump检查它

代码语言:javascript
复制
$ objdump -h a.out

a.out:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400200  0000000000400200  00000200  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  000000000040021c  000000000040021c  0000021c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  000000000040023c  000000000040023c  0000023c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .hash         00000018  0000000000400260  0000000000400260  00000260  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.hash     0000001c  0000000000400278  0000000000400278  00000278  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynsym       00000048  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .dynstr       00000038  00000000004002e0  00000000004002e0  000002e0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version  00000006  0000000000400318  0000000000400318  00000318  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .gnu.version_r 00000020  0000000000400320  0000000000400320  00000320  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.dyn     00000018  0000000000400340  0000000000400340  00000340  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .rela.plt     00000018  0000000000400358  0000000000400358  00000358  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .init         00000018  0000000000400370  0000000000400370  00000370  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt          00000020  0000000000400388  0000000000400388  00000388  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         000001c8  00000000004003b0  00000000004003b0  000003b0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         0000000e  0000000000400578  0000000000400578  00000578  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       00000004  0000000000400588  0000000000400588  00000588  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame_hdr 00000024  000000000040058c  000000000040058c  0000058c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     0000007c  00000000004005b0  00000000004005b0  000005b0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .ctors        00000010  0000000000600630  0000000000600630  00000630  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 19 .dtors        00000010  0000000000600640  0000000000600640  00000640  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000008  0000000000600650  0000000000600650  00000650  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      000001a0  0000000000600658  0000000000600658  00000658  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          00000008  00000000006007f8  00000000006007f8  000007f8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000020  0000000000600800  0000000000600800  00000800  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000010  0000000000600820  0000000000600820  00000820  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          00000010  0000000000600830  0000000000600830  00000830  2**3
                  ALLOC
 26 .comment      00000039  0000000000000000  0000000000000000  00000830  2**0
                  CONTENTS, READONLY
 27 .debug_aranges 00000030  0000000000000000  0000000000000000  00000869  2**0
                  CONTENTS, READONLY, DEBUGGING
 28 .debug_pubnames 0000001b  0000000000000000  0000000000000000  00000899  2**0
                  CONTENTS, READONLY, DEBUGGING
 29 .debug_info   00000055  0000000000000000  0000000000000000  000008b4  2**0
                  CONTENTS, READONLY, DEBUGGING
 30 .debug_abbrev 00000034  0000000000000000  0000000000000000  00000909  2**0
                  CONTENTS, READONLY, DEBUGGING
 31 .debug_line   0000003b  0000000000000000  0000000000000000  0000093d  2**0
                  CONTENTS, READONLY, DEBUGGING
 32 .debug_str    00000026  0000000000000000  0000000000000000  00000978  2**0
                  CONTENTS, READONLY, DEBUGGING
 33 .debug_loc    0000004c  0000000000000000  0000000000000000  0000099e  2**0
                  CONTENTS, READONLY, DEBUGGING

您可以看到额外的部分(27到33)。这些部分不会在运行时加载,因此不会有任何性能损失。使用gdb,您还可以在运行时检查它们:

代码语言:javascript
复制
$ gdb ./a.out
(gdb) break main
(gdb) run
(gdb) info files
// blah blah ....
Local exec file:
        `/home/kghost/a.out', file type elf64-x86-64.
        Entry point: 0x4003b0
        0x0000000000400200 - 0x000000000040021c is .interp
        0x000000000040021c - 0x000000000040023c is .note.ABI-tag
        0x000000000040023c - 0x0000000000400260 is .note.gnu.build-id
        0x0000000000400260 - 0x0000000000400278 is .hash
        0x0000000000400278 - 0x0000000000400294 is .gnu.hash
        0x0000000000400298 - 0x00000000004002e0 is .dynsym
        0x00000000004002e0 - 0x0000000000400318 is .dynstr
        0x0000000000400318 - 0x000000000040031e is .gnu.version
        0x0000000000400320 - 0x0000000000400340 is .gnu.version_r
        0x0000000000400340 - 0x0000000000400358 is .rela.dyn
        0x0000000000400358 - 0x0000000000400370 is .rela.plt
        0x0000000000400370 - 0x0000000000400388 is .init
        0x0000000000400388 - 0x00000000004003a8 is .plt
        0x00000000004003b0 - 0x0000000000400578 is .text
        0x0000000000400578 - 0x0000000000400586 is .fini
        0x0000000000400588 - 0x000000000040058c is .rodata
        0x000000000040058c - 0x00000000004005b0 is .eh_frame_hdr
        0x00000000004005b0 - 0x000000000040062c is .eh_frame
        0x0000000000600630 - 0x0000000000600640 is .ctors
        0x0000000000600640 - 0x0000000000600650 is .dtors
        0x0000000000600650 - 0x0000000000600658 is .jcr
        0x0000000000600658 - 0x00000000006007f8 is .dynamic
        0x00000000006007f8 - 0x0000000000600800 is .got
        0x0000000000600800 - 0x0000000000600820 is .got.plt
        0x0000000000600820 - 0x0000000000600830 is .data
        0x0000000000600830 - 0x0000000000600840 is .bss
// blah blah ....

因此,唯一的缺点是您需要额外的磁盘空间来存储此信息。您还可以使用strip删除调试信息:

代码语言:javascript
复制
$ strip a.out

使用objdump再次检查,您将看到不同之处。

编辑:

实际上,加载器根据objdump -p可以看到的Program Header加载elf文件,而不是查看节(下面的示例使用不同的elf二进制文件):

代码语言:javascript
复制
$ objdump -p /bin/cat

/bin/cat:     file format elf64-x86-64

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3
         filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x
  INTERP off    0x0000000000000238 vaddr 0x0000000000000238 paddr 0x0000000000000238 align 2**0
         filesz 0x000000000000001c memsz 0x000000000000001c flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x00000000000078bc memsz 0x00000000000078bc flags r-x
    LOAD off    0x0000000000007c28 vaddr 0x0000000000207c28 paddr 0x0000000000207c28 align 2**21
         filesz 0x0000000000000678 memsz 0x0000000000000818 flags rw-
 DYNAMIC off    0x0000000000007dd8 vaddr 0x0000000000207dd8 paddr 0x0000000000207dd8 align 2**3
         filesz 0x00000000000001e0 memsz 0x00000000000001e0 flags rw-
    NOTE off    0x0000000000000254 vaddr 0x0000000000000254 paddr 0x0000000000000254 align 2**2
         filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off    0x0000000000006980 vaddr 0x0000000000006980 paddr 0x0000000000006980 align 2**2
         filesz 0x0000000000000274 memsz 0x0000000000000274 flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
   RELRO off    0x0000000000007c28 vaddr 0x0000000000207c28 paddr 0x0000000000207c28 align 2**0
         filesz 0x00000000000003d8 memsz 0x00000000000003d8 flags r--

程序头告诉哪个段将加载什么rwx标志;具有相同标志的多个段将被合并到单个段中。

顺便说一句:

当加载elf文件时,加载器不关心部分,但当需要时,它会查看几个与符号相关的部分来解析符号。

票数 40
EN

Stack Overflow用户

发布于 2011-12-30 13:43:47

您可能希望查看Why does my code run slower with multiple threads than with a single thread when it is compiled for profiling (-pg)?来快速解释调试符号如何影响优化。

要回答您的3个问题:

当调试符号存在而不存在时,

  1. 加载时间将增加
  2. 磁盘占用空间将更大
  3. 如果您在零优化的情况下编译,那么您实际上不会丢失任何东西。如果设置了optimization,则优化后的代码将因为调试符号而不太优化。
票数 -5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8676466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档