c++ - 尝试使用 tcc 针对 gcc 生成的 .o 文件编译源代码时出现奇怪的行为

标签 c++ c gcc mingw tcc

我正在尝试使用 tcc(版本 0.9.26)针对 gcc 生成的 .o 文件编译源代码,但它有奇怪的行为。 gcc (ver 5.3.0) 来自 MinGW 64 位。

更具体地说,我有以下两个文件 (te1.c te2.c)。我在 windows7 框上执行了以下命令

c:\tcc> gcc -c te1.c
c:\tcc> objcopy -O  elf64-x86-64 te1.o   #this is needed because te1.o from previous step is in COFF format, tcc only understand ELF format
c:\tcc> tcc te2.c te1.o
c:\tcc> te2.exe
567in dummy!!!

请注意,它从字符串 1234567in dummy!!!\n 中截断了 4 个字节。想知道是不是出了什么问题。

谢谢 进

========文件te1.c===========

#include <stdio.h>

void dummy () {
    printf1("1234567in dummy!!!\n");
}

========文件te2.c===========

#include <stdio.h>

void printf1(char *p) {
    printf("%s\n",p);
}
extern void dummy();
int main(int argc, char *argv[]) {
    dummy();
    return 0;
}

更新 1

看到 te1.o(由 tcc 编译的 te1.c)和 te1_gcc.o(由 gcc 编译的 te1.c)之间的汇编差异。在编译的tcc中,我看到了lea -0x4(%rip),%rcx,在编译的gcc中,我看到了lea 0x0(%rip),%rcx。 不知道为什么。

C:\temp>objdump -d te1.o

te1.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <dummy>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 81 ec 20 00 00 00    sub    $0x20,%rsp
   b:   48 8d 0d fc ff ff ff    lea    -0x4(%rip),%rcx        # e <dummy+0xe>
  12:   e8 fc ff ff ff          callq  13 <dummy+0x13>
  17:   c9                      leaveq
  18:   c3                      retq
  19:   00 00                   add    %al,(%rax)
  1b:   00 01                   add    %al,(%rcx)
  1d:   04 02                   add    $0x2,%al
  1f:   05 04 03 01 50          add    $0x50010304,%eax

C:\temp>objdump -d te1_gcc.o

te1_gcc.o:     file format pe-x86-64


Disassembly of section .text:

0000000000000000 <dummy>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 20             sub    $0x20,%rsp
   8:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # f <dummy+0xf>
   f:   e8 00 00 00 00          callq  14 <dummy+0x14>
  14:   90                      nop
  15:   48 83 c4 20             add    $0x20,%rsp
  19:   5d                      pop    %rbp
  1a:   c3                      retq
  1b:   90                      nop
  1c:   90                      nop
  1d:   90                      nop
  1e:   90                      nop
  1f:   90                      nop

更新2

使用二进制编辑器,我更改了 te1.o 中的机器码(由 gcc 生成)并将 lea 0(%rip),%rcx 更改为 lea -0x4(%rip ),%rcx 并使用 tcc 链接它,生成的 exe 工作正常。 更准确地说,我做到了

c:\tcc> gcc -c te1.c
c:\tcc> objcopy -O  elf64-x86-64 te1.o 
c:\tcc> use a binary editor to the change the bytes from (48 8d 0d 00 00 00 00) to (48 8d 0d fc ff ff ff)
c:\tcc> tcc te2.c te1.o
c:\tcc> te2
1234567in dummy!!!

更新 3

根据要求,这是 objdump -r te1.o

的输出
C:\temp>gcc -c te1.c

C:\temp>objdump -r te1.o

te1.o:     file format pe-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
000000000000000b R_X86_64_PC32     .rdata
0000000000000010 R_X86_64_PC32     printf1


RELOCATION RECORDS FOR [.pdata]:
OFFSET           TYPE              VALUE
0000000000000000 rva32             .text
0000000000000004 rva32             .text
0000000000000008 rva32             .xdata



C:\temp>objdump -d te1.o

te1.o:     file format pe-x86-64


Disassembly of section .text:

0000000000000000 <dummy>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 20             sub    $0x20,%rsp
   8:   48 8d 0d 00 00 00 00    lea    0x0(%rip),%rcx        # f <dummy+0xf>
   f:   e8 00 00 00 00          callq  14 <dummy+0x14>
  14:   90                      nop
  15:   48 83 c4 20             add    $0x20,%rsp
  19:   5d                      pop    %rbp
  1a:   c3                      retq
  1b:   90                      nop
  1c:   90                      nop
  1d:   90                      nop
  1e:   90                      nop
  1f:   90                      nop

最佳答案

tcc 或调用约定无关。它与 elf64-x86-64 和 pe-x86-64 格式的不同链接器约定有关。

使用 PE,链接器将隐式减去 4 来计算最终偏移量。

对于 ELF,它不会这样做。因此,0 是 PE 的正确初始值,-4 是 ELF 的正确初始值。

不幸的是,objcopy 不会转换此 -> objcopy 中的错误。

关于c++ - 尝试使用 tcc 针对 gcc 生成的 .o 文件编译源代码时出现奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38337121/

相关文章:

c++ - 如何访问 MacBook 上的网络摄像头?

c++ - 递归斐波那契函数(带负数)

c - 无法编译链表程序

c++ - -O3 模式下的段错误?

c++ - List<MyClass*> & 数组问题

c++ - 我可以为局部变量创建一个 boost::shared_ptr 吗?

c++ - 找到两幅图像之间的相同区域

c++ - 绘制 .wav 文件的波形

c - 直接调用信号处理程序和通过 raise() 调用的信号处理程序之间的堆栈差异?

c++ - GCC在被杀死时创建带有随机后缀的目标文件