简体   繁体   English

编译器优化创建了系统调用?

[英]Compiler optimization creating a syscall?

I am compiling a fairly sophisticated application in two modes: Debug and Release. 我正在以两种模式编译一个相当复杂的应用程序:调试和发布。 The main difference, as I see it, is -O0 vs -O3 (I can provide the relevant part of makefile if needed). 如我所见,主要区别是-O0与-O3(如果需要,我可以提供makefile的相关部分)。 I am trying to avoid syscall generation as much as possible, as I am simulating this application in syscall emulation mode (no OS running underneath). 我试图尽可能避免生成syscall,因为我正在syscall仿真模式下模拟此应用程序(在其下不运行任何操作系统)。 The problem that i am currently having is that in Release mode the compiler generates an extra socket syscall, which I prefer not to happen (and which does not happen in Debug mode). 我目前遇到的问题是,在Release模式下,编译器会生成一个额外的套接字syscall,我不希望发生(并且在Debug模式下不会发生)。

The reason that I think the socket might be created is that I am using pthreads and two of my threads are communicating through a volatile char*. 我认为可能会创建套接字的原因是我正在使用pthreads,而我的两个线程正在通过volatile char *通信。 So I'm guessing maybe the compiler is trying to implement it in a fancy way when I set the -O3 flag? 所以我猜测也许当我设置-O3标志时,编译器正在尝试以一种奇特的方式实现它? But I'm not sure if that is a reasonable assumption. 但是我不确定这是否是一个合理的假设。

  1. Is it possible that the socket syscall is being generated because of the -O3 flag? 是否可能由于-O3标志而正在生成套接字syscall? (doesn't make too much sense) (没有太大意义)
  2. If so, how can I hint to the compiler to avoid generating this syscall? 如果是这样,我如何向编译器提示以避免生成此syscall?

EDIT: BTW the code is in C and C++ 编辑:顺便说一句,代码在C和C ++中

EDIT: The code is statically linked against the following shared libraries: 编辑:代码静态链接到以下共享库:

libstdc++.a 
libm.a 
libglib-2.0.a 
-static-libgcc 
*special pthreads library*

Also, I found where in the binary the call to socket is happening: 此外,我发现在二进制文件中发生了对套接字的调用:

8c716:       db28            blt.n   8c76a <openlog_internal+0xf2>
8c718:       f8d9 1008       ldr.w   r1, [r9, #8]
8c71c:       4620            mov     r0, r4
8c71e:       2200            movs    r2, #0
8c720:       f441 2100       orr.w   r1, r1, #524288 ; 0x80000
8c724:       f001 e97c       blx     8da20 <__socket>
8c728:       4b20            ldr     r3, [pc, #128]  ; (8c7ac <openlog_internal+0x134>)
8c72a:       681b            ldr     r3, [r3, #0]
8c72c:       f8c9 0004       str.w   r0, [r9, #4]
8c730:       b943            cbnz    r3, 8c744 <openlog_internal+0xcc>
8c732:       1c43            adds    r3, r0, #1

EDIT: I found out why this is happening (see my answer below). 编辑:我发现了为什么会这样(请参阅下面的答案)。 If anyone has an explanation as to why the compiler behaves like that please share!!! 如果有人对编译器为何如此行事有一个解释,请分享!!!

Although, one can imagine such an optimization, I haven't heard of such and I really doubt it, because any system call is usually very expensive. 尽管可以想象到这样的优化,但我还没有听说过,我对此表示怀疑,因为任何系统调用通常都非常昂贵。

If you are on a *nix system, you can verify it by looking for undefined symbols with nm 如果您使用的是* nix系统,则可以通过查找带有nm未定义符号来进行验证

nm -u file1.o file2.o | grep socket

should show somewhere the missing socket symbol as 应该将缺少的socket符号显示为

        U socket

if there is somewhere a call to socket. 如果在某处有套接字调用。

As I mentioned, I doubt, that there is an optimization inserting any system call and I expect no output from the command line above. 正如我所提到的,我怀疑是否存在插入任何系统调用的优化,并且我期望上面的命令行没有输出。

Update: 更新:

On my system (Ubuntu 12.04, gcc 4.6), I found the following note in man gcc 在我的系统(Ubuntu 12.04,gcc 4.6)上,我在man gcc发现了以下注意事项

-O2 Optimize even more. -O2进一步优化。 ... ...
NOTE: In Ubuntu 8.10 and later versions, -D_FORTIFY_SOURCE=2 is set by default, and is activated when -O is set to 2 or higher. 注意:在Ubuntu 8.10和更高版本中,默认情况下设置-D_FORTIFY_SOURCE = 2,并在-O设置为2或更高时被激活。 This enables additional compile- time and run-time checks for several libc functions. 这样就可以对几个libc函数进行附加的编译时和运行时检查。 To disable, specify either -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0. 要禁用,请指定-U_FORTIFY_SOURCE或-D_FORTIFY_SOURCE = 0。

So, maybe through this or a similar mechanism, there is some code included when the optimization is set to -O2 or -O3 . 因此,也许通过这种或类似的机制,当优化设置为-O2-O3时,会包含一些代码。

After a whole day of debugging, it turns out that arm-cross-gcc compiles strcpy() differently under -O0 and -O1,-O2,-O3 when the string you are copying from is a volatile char* . 经过一整天的调试,事实证明,当要从中复制的字符串是volatile char *时,arm-cross-gcc在-O0和-O1,-O2,-O3下编译strcpy()的方式有所不同。 -O0 compiles using standard user mode assembly, whereas -O1,-O2,-O3 compile it with extra syscalls, such as socket, connect, and send. -O0使用标准用户模式汇编进行编译,而-O1,-O2,-O3使用额外的系统调用(例如套接字,连接和发送)进行编译。

So, after all, my initial hunch is justified: 因此,毕竟我最初的直觉是合理的:

"The reason that I think the socket might be created is that I am using pthreads and two of my threads are communicating through a volatile char*. So I'm guessing maybe the compiler is trying to implement it in a fancy way when I set the -O3 flag? But I'm not sure if that is a reasonable assumption." “我认为可能会创建套接字的原因是我正在使用pthreads,而我的两个线程正在通过volatile char *通信。因此,我猜测也许编译器在设置时试图以一种奇特的方式实现它。 -O3标志?但是我不确定这是否合理。”

EDIT: Here are some observations to support this claim: 编辑:这是支持此主张的一些观察:

I compiled my code in 4 versions 我将代码编译为4个版本

 1. without strcpy() -O0 => obj.o0
 2. with    strcpy() -O0 => obj_strcpy.o0
 3. without strcpy() -O3 => obj.o3
 4. with    strcpy() -O3 => obj_strcpy.o3

I ran nm -u on all of the above. 我在所有上述情况上都运行了nm -u。

Here are the diffs: 这是差异:

$> diff obj.o0 obj_strcpy.o0
$> diff obj.o3 obj_strcpy.o3
>          U __strcpy_chk
$>

This means that when you add strcpy() to your code and compile with -O0 no external symbols are added, whereas when you add strcpy() to your code and compile with -O3 U __strcpy_chk symbol is added to the object file. 这意味着,当您将strcpy()添加到代码中并使用-O0进行编译时,不会添加任何外部符号,而当您将strcpy()添加到您的代码中并使用-O3进行编译时, U __strcpy_chk符号添加到目标文件中。 I will look into the implementation of U __strcpy_chk on ARM to figure out where the syscalls are coming from. 我将研究ARM上U __strcpy_chk的实现,以确定系统调用来自何处。 As of right now it seems like U __strcpy_chk is doing buffer overflow checks - here is the reference: 截至目前,似乎U __strcpy_chk正在执行缓冲区溢出检查-这是参考:

http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/libc---strcpy-chk-1.html http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/libc---strcpy-chk-1.html

EDIT: So there are two solutions so far: one proposed by Olaf Dietsche to use another compiler flag in addition to -O3. 编辑:到目前为止,有两种解决方案:一种由Olaf Dietsche提出,除了-O3之外还使用另一种编译器标志。 The other option is to avoid strcpy() altogether and use something as follows: 另一种选择是完全避免使用strcpy()并使用如下所示的内容:

for(int i=0;i<64;i++)
{
  cmd[i] = msg[i];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM