c - fpic 和 O3 优化标志

标签 c gcc compiler-optimization fpic

我正在尝试编译使用 libnothing.so 的 main.c。这是源代码:

主.c

#include "nothing.h"

int main(void)
{
    doAlmostNothing();
    return 0;
}

无.c

#include "nothing.h"

void doNothingStatic(void) {
   volatile int x = 45;
   x++;
}

void doNothing(void) {}

void doAlmostNothing(void)
{
    doNothingStatic();
    doNothing();
}

无.h

void doAlmostNothing(void);

首先,我在没有 fpic 的情况下像这样编译 nothing.c:gcc -c nothing.c 我会得到这个错误:/usr/bin/ld: nothing.o: relocation R_X86_64_PC32反对符号 doNothing 在创建共享对象时不能使用;构建 .so 时使用 -fPIC 重新编译 gcc -shared nothing.o -o libnothing.so

但是如果我使用 O3 gcc -c -O3 nothing.c 编译它,我就不会再收到重定位错误了。

-O3 默认添加 fpic 吗?

编辑

我根据评论中的建议通过添加 void 对代码进行了一些更改,从 doNothingStatic 中删除了 static 并在其中添加了一些虚拟工作。

这是运行命令时的控制台输出:

bil@bil-VirtualBox:~/Documents/test/linking$ gcc-7 -c nothing.c
bil@bil-VirtualBox:~/Documents/test/linking$ gcc-7 -shared nothing.o -o nothing.so
/usr/bin/ld: nothing.o: relocation R_X86_64_PC32 against symbol `doNothingStatic' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
bil@bil-VirtualBox:~/Documents/test/linking$ gcc-7 -c -O3 nothing.c
bil@bil-VirtualBox:~/Documents/test/linking$ gcc-7 -shared nothing.o -o libnothing.so
bil@bil-VirtualBox:~/Documents/test/linking$ ls
libnothing.so  main  main.c  main.o  nothing.c  nothing.h  nothing.o  libnothing.so

我还看了objdump提供的程序集:

  • 没有氧气:
    nothing.o:     file format elf64-x86-64


    Disassembly of section .text:

    0000000000000000 <doNothingStatic>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   c7 45 fc 2d 00 00 00    movl   $0x2d,-0x4(%rbp)
       b:   8b 45 fc                mov    -0x4(%rbp),%eax
       e:   83 c0 01                add    $0x1,%eax
      11:   89 45 fc                mov    %eax,-0x4(%rbp)
      14:   90                      nop
      15:   5d                      pop    %rbp
      16:   c3                      retq   

    0000000000000017 <doNothing>:
      17:   55                      push   %rbp
      18:   48 89 e5                mov    %rsp,%rbp
      1b:   90                      nop
      1c:   5d                      pop    %rbp
      1d:   c3                      retq   

    000000000000001e <doAlmostNothing>:
      1e:   55                      push   %rbp
      1f:   48 89 e5                mov    %rsp,%rbp
      22:   e8 00 00 00 00          callq  27 <doAlmostNothing+0x9>
      27:   e8 00 00 00 00          callq  2c <doAlmostNothing+0xe>
      2c:   90                      nop
      2d:   5d                      pop    %rbp
      2e:   c3                      retq   
  • 与 O3
    nothing.o:     file format elf64-x86-64


    Disassembly of section .text:

    0000000000000000 <doNothingStatic>:
       0:   c7 44 24 fc 2d 00 00    movl   $0x2d,-0x4(%rsp)
       7:   00 
       8:   8b 44 24 fc             mov    -0x4(%rsp),%eax
       c:   83 c0 01                add    $0x1,%eax
       f:   89 44 24 fc             mov    %eax,-0x4(%rsp)
      13:   c3                      retq   
      14:   66 90                   xchg   %ax,%ax
      16:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
      1d:   00 00 00 

    0000000000000020 <doNothing>:
      20:   f3 c3                   repz retq 
      22:   0f 1f 40 00             nopl   0x0(%rax)
      26:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
      2d:   00 00 00 

    0000000000000030 <doAlmostNothing>:
      30:   c7 44 24 fc 2d 00 00    movl   $0x2d,-0x4(%rsp)
      37:   00 
      38:   8b 44 24 fc             mov    -0x4(%rsp),%eax
      3c:   83 c0 01                add    $0x1,%eax
      3f:   89 44 24 fc             mov    %eax,-0x4(%rsp)
      43:   c3                      retq  

确实,使用 -O3 时函数似乎是内联的

最佳答案

不,只是函数 doNothing 被内联,因此没有剩余的模块内函数调用。

relocation type表示使用符号扩展的 32 位指针的绝对函数或数据访问,即基本上是前 2 GiB 虚拟内存中的某些内容。当使用 -O3 编译时,所有函数调用都是内联的,因此不需要使用重定位的调用。

关于c - fpic 和 O3 优化标志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57245580/

相关文章:

c - 如何在结构中存储多数据值并使用它们?

c++ - 类数据成员中可以使用模板参数推导吗?

c - 用 C 中的值初始化整个数组

c++ - "Function has no address"尽管禁用了优化 (/Od)

加载字节时,Clang 不会将高位清零。这是一个错误还是一个故意的选择?

c - Linux 中的 printf 无法正常工作

条件表达式

c - wchar_t 到八位字节 - 在 C 中?

linux - 有没有办法在不更改 makefile 的情况下将 '-lpthread' 添加到默认链接器标志

C++ 优化 : avoid a copy operation