https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61577

--- Comment #202 from Peter Bisroev <peter.bisroev at groundlabs dot com> ---
(In reply to dave.anglin from comment #201)
> On 2020-02-22 4:33 p.m., peter.bisroev at groundlabs dot com wrote:
> > They both seem to be ELF32
> Maybe run failing program under gdb to find faulting instruction.  Compare
> with executable that works.

Hi Dave,

Well, decoding IA-64 instruction bundles by hand is not fun :) But at least we
know what is going on here now.

Looking at main.o generated by aCC, the relocation is as expected:
------------------------------
30:   05 00 00 00 01 00       [MLX]       nop.m 0x0
                        32: PCREL60B    hello
36:   00 00 00 00 00 00                   brl.call.dptk.many b0=30
<main+0x30>;;
3c:   08 00 00 d2
------------------------------

Once ld takes care of relocation everything is as expected as well:
------------------------------
40009b0:       05 00 00 00 01 00       [MLX]       nop.m 0x0
40009b6:       00 00 00 00 00 00                   brl.call.dptk.many
b0=4000a40 <hello>;;
40009bc:       98 00 00 d2
------------------------------

I've decoded this instruction bundle by hand and verified that immediate value
is 0x90 (0x9 << 4) which matches our relative offset of 0x4000a40−0x40009b0 as
expected.


Now looking at the main.o generated by gcc, the relocation seems to be as
expected but the relocation address seems to be off:
------------------------------
20:   04 00 00 00 01 00       [MLX]       nop.m 0x0
                      21: PCREL60B    hello
26:   00 00 00 00 00 00                   brl.call.sptk.many b0=20 <main+0x20>
2c:   08 00 00 d0
------------------------------

As can be seen above, GNU as is telling HP's ld to do the relocation at 0x21,
which falls into slot 1 and 0. However the relocation needs to be done at 0x26
to cover slots 2 and 1.


Now looking at the linked binary we are getting the following:
------------------------------
4000950:       04 00 00 00 00 00       [MLX]       break.m 0x0
4000956:       00 40 00 00 00 00                   brl.call.sptk.many
b0=4000950 <_end+0xc3ff0908>
400095c:       08 00 00 d0
------------------------------

As can be seen above, the slot 0 instruction changed from nop.m to break.m, and
this is where we are getting the illegal instruction. In this linked binary,
hello() is located at 0x40009d0. So based on this, we expect the offset to be
0x80 (0x40009d0 - 0x4000950). So the expected immediate value for brl.call
should be 0x08 (0x80>>4).

I decided to double check that HP's ld is doing this relocation properly but at
the wrong offset requested by GNU as. Based on our relocation offset of 0x21, I
have interpreted slots 1 and 0 by hand as if they were slots 2 and 1. Once we
do that, we get the immediate value of 0x08 as expected. The nop.m changes to
break.m because ld cleared bits of imm39 (bits 20-58) that form the 60 bit
immediate.

Based on the above, unless I am mistaken, it looks like a bug in GNU as. Once I
get a bit of time this week I will try to look through it to see what is going
on there.

Just out of curiosity, I have also tried to patch the reloc offset to 0x26 in
the object file just to see what happens :). After that, objdump shows expected
relocation offset. However HP's linker dies with bus error when I try to link
the executable. 

But I think we are making some progress here. What do you think?

Thanks!
--peter

Reply via email to