c - 使用自定义 __start 的 GCC/LD 的异常输出

标签 c gcc mips

作为这个问题的扩展:GCC compile and link raw output

我正在尝试使用自定义 __start 编译和链接一段代码。请注意,我不要求它在任何已知的架构上工作,因此遵守任何规范并不重要,重要的是让它一致工作。

我有一个简单的组件(我从现在找不到的 URL 中获得)。

.set noreorder  /* so we can use delay slots explicitly */

    .text
    .globl main
    .globl __start
    .type __start,@function
    .ent __start

__start:
    jal main;
    nop;
    li $0,1;
    .end __start

如果我理解正确的话,这一切所做的就是调用我的 main 方法,在分支延迟槽中执行无操作,然后将数字 1 写入寄存器 0 (我知道这违反了 MIPS 规范,这是故意的- 它表示代码完成并在实际发生之前被“捕获”)。

但是,当我使用 mips ld 使用此命令将其与示例代码片段链接时 mips-linux-gnu-ld --section-start=.text=0 start.o main.o -o 可执行文件

使用 objdump 查看时得到一些不寻常的输出

00000000 <.pic.main>:
0:  3c190000    lui t9,0x0
4:  0800022b    j   8ac <main>
8:  273908ac    addiu   t9,t9,2220
c:  00000000    nop

00000010 <__start>:
10: 0c000000    jal 0 <.pic.main>
14: 00000000    nop
18: 24000001    li  zero,1
1c: 00000000    nop

.........

000008ac <main>
.........

无论我的测试程序多么简单,我总是得到相同的 .pic.main 函数。但是,在某些情况下,它出现在 __start 上方,在某些情况下出现在下方。

我想完全删除这个“函数”,但如果做不到这一点,我会希望它总是出现在__start之后。

作为奖励,如果有人知道这个函数是什么或者为什么会发生,我会很感兴趣。

最佳答案

它看起来像一个与位置无关的跳转代码。链接器不知道你的东西将被放在哪里,因此它为所有情况创建一个 PIC。相对跳转或使用寄存器的跳转可以解决问题,尽管它不是跳转和链接

我会尝试使用

  • -mrelax-pic-calls 将通常通过寄存器 $t9 分派(dispatch)的 PIC 调用转换为直接调用。仅当链接器可以在链接时解析目标并且目标位于直接调用的范围内时,这才有可能。
  • mbranch-cost=num 将分支成本设置为大约 num 个“简单”指令。 “此成本只是一种启发式方法,并不能保证在各个版本中产生一致的结果。”
  • -mno-shared 不生成完全位置无关的代码,因此可以链接到共享库
  • -mno-embedded-pic

我会把钱押在前两个之一上。

关于c - 使用自定义 __start 的 GCC/LD 的异常输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30520978/

相关文章:

c - 相同的代码在 C 中给出不同的输出

linux - 无法禁用 gcc 警告 - 从整数创建指针而不进行强制转换

c++ - 如何强制编译器为手动切换生成等效代码?

MIPS - 如何找到分支和跳转指令的地址值

c - OpenGL/GLUT 窗口显示白屏

c - 操作系统 - 进程

c - 在C中使用深度优先搜索找到最小生成树

c - 如何制作假代理导入库

function - MIPS 中的函数(过程)

assembly - MIPS汇编语言程序中如何将所有小写字母转换为大写字母