使用自定义__start从GCC / LD获得不寻常的输出

时间:2015-05-29 04:09:39

标签: 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方法,在分支延迟槽中执行no-op,然后将数字1写入寄存器0(我知道这违反了MIPS规范,它是故意的 - 它表示代码已完成,并且在实际发生之前被捕获。

但是,当我使用mips ld使用此命令mips-linux-gnu-ld --section-start=.text=0 start.o main.o -o executable

将其与示例代码链接时

使用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以上。

我想删除这个&#34;功能&#34;完全,但失败,希望它始终出现在MinWidth之后。

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

1 个答案:

答案 0 :(得分:2)

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

我会尝试使用

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

我把钱放在前两个。