[llvm-dev] lld mishandling R_X86_64_PC32 relocations

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[llvm-dev] lld mishandling R_X86_64_PC32 relocations

U.Mutlu via llvm-dev
Hi,

I've tracked down what I believe is a bug in lld's relocation processing for R_X86_64_PC32 REL relocations.

I'm producing the object file in a slightly unusual way: I'm using objcopy on a relocatable i386 ELF object file to convert it to x86_64 which transforms a R_386_PC32 into a R_X86_64_PC32.

Steps to reproduce:

1. Assemble the attached bug.asm using nasm and note the R_386_PC32 REL.

$ nasm -felf32 -o bug.o bug.asm
$ x86_64-elf-objdump -dr bug.o | grep -A1 -e '<_start>:'
00000000 <_start>:
   0: e8 fc ff ff ff       call   1 <_start+0x1>
$ x86_64-elf-readelf -r bug.o

Relocation section '.rel.text._start' at offset 0x260 contains 1 entry:
 Offset     Info    Type            Sym.Value  Sym. Name
00000001  00000302 R_386_PC32        00000000   .text.foo

2. Convert bug.o to a 64-bit ELF object file and note the R_X86_64_PC32 REL (not RELA!)

$ x86_64-elf-objcopy -I elf32-i386 -O elf64-x86-64 bug.o bug-64.o
$ x86_64-elf-objdump -M i386 -dr bug-64.o | grep -A1 -e '<_start>:'
0000000000000000 <_start>:
   0: e8 fc ff ff ff       call   1 <_start+0x1>
$ x86_64-elf-readelf -r bug-64.o

Relocation section '.rel.text._start' at offset 0x128 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name
000000000001  000300000002 R_X86_64_PC32     0000000000000000 .text.foo

3. Link with a just-built ld.lld and note that the relocation has been misapplied. It's now calling foo+4 rather than foo.

$ ./llvm-build/bin/ld.lld -melf_x86_64 -o bug-lld bug-64.o
$ x86_64-elf-objdump -M i386 -d bug-64-lld | grep -A1 -e '<_start>:'
0000000000201000 <_start>:
  201000: e8 0f 00 00 00       call   201014 <foo+0x4>

If you link with GNU ld instead, the relocation is applied correctly.

$ x86_64-elf-ld -melf_x86_64 -o bug-64-ld bug-64.o
$ x86_64-elf-objdump -M i386 -d bug-64-ld | grep -A1 -e '<_start>:'
0000000000400080 <_start>:
  400080: e8 0b 00 00 00       call   400090 <foo>

Linking the 32-bit object file works correctly with both GNU ld and ld.lld.

$ ./llvm-build/bin/ld.lld -melf_i386 -o bug-lld bug.o
$ x86_64-elf-objdump -d bug-lld | grep -A1 -e '<_start>:'
00011000 <_start>:
   11000: e8 0b 00 00 00       call   11010 <foo>
$ x86_64-elf-ld -melf_i386 -o bug-ld bug.o
$ x86_64-elf-objdump -d bug-ld | grep -A1 -e '<_start>:'
08048060 <_start>:
 8048060: e8 0b 00 00 00       call   8048070 <foo>

I'm not at all familiar with the lld source, but this looks a lot like getImplicitAddend() needs to be implemented for the X86_64 class.

Alternatively (but much less useful for me) would be an error message that REL relocations are not supported on x86-64.

I've attached all of the files created above, in case anyone wants to examine them.

Thank you,

Steve

--
Stephen Checkoway




_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

bug-64-ld (1K) Download Attachment
bug-64-lld (11K) Download Attachment
bug-64.o (1K) Download Attachment
bug-ld (828 bytes) Download Attachment
bug-lld (11K) Download Attachment
bug.asm (245 bytes) Download Attachment
bug.o (852 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] lld mishandling R_X86_64_PC32 relocations

U.Mutlu via llvm-dev
Hi Stephen,

I think the bug is in objcopy, as it is creating a file that does not comply with the x86-64 psABI, which requires all relocations to be RELA:
I also tried passing your bug-64.o to ld.gold, and it rejects it with an internal error.

$ ld.gold -r -o bug-64-2.o bug-64.o
ld.gold: internal error in scan_relocatable_relocs, at ../../gold/x86_64.cc:5118
$ ld.gold  -o bug-64-2.o bug-64.o
ld.gold: error: bug-64.o: unsupported REL reloc section
ld.gold: internal error in relocate_section, at ../../gold/x86_64.cc:5051

Probably what needs to happen is that we need to start rejecting files which use the wrong relocation type and a bug needs to be filed against objcopy.

Peter

On Tue, Jun 5, 2018 at 10:33 AM, Stephen Checkoway via llvm-dev <[hidden email]> wrote:
Hi,

I've tracked down what I believe is a bug in lld's relocation processing for R_X86_64_PC32 REL relocations.

I'm producing the object file in a slightly unusual way: I'm using objcopy on a relocatable i386 ELF object file to convert it to x86_64 which transforms a R_386_PC32 into a R_X86_64_PC32.

Steps to reproduce:

1. Assemble the attached bug.asm using nasm and note the R_386_PC32 REL.

$ nasm -felf32 -o bug.o bug.asm
$ x86_64-elf-objdump -dr bug.o | grep -A1 -e '<_start>:'
00000000 <_start>:
   0:   e8 fc ff ff ff          call   1 <_start+0x1>
$ x86_64-elf-readelf -r bug.o

Relocation section '.rel.text._start' at offset 0x260 contains 1 entry:
 Offset     Info    Type            Sym.Value  Sym. Name
00000001  00000302 R_386_PC32        00000000   .text.foo

2. Convert bug.o to a 64-bit ELF object file and note the R_X86_64_PC32 REL (not RELA!)

$ x86_64-elf-objcopy -I elf32-i386 -O elf64-x86-64 bug.o bug-64.o
$ x86_64-elf-objdump -M i386 -dr bug-64.o | grep -A1 -e '<_start>:'
0000000000000000 <_start>:
   0:   e8 fc ff ff ff          call   1 <_start+0x1>
$ x86_64-elf-readelf -r bug-64.o

Relocation section '.rel.text._start' at offset 0x128 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name
000000000001  000300000002 R_X86_64_PC32     0000000000000000 .text.foo

3. Link with a just-built ld.lld and note that the relocation has been misapplied. It's now calling foo+4 rather than foo.

$ ./llvm-build/bin/ld.lld -melf_x86_64 -o bug-lld bug-64.o
$ x86_64-elf-objdump -M i386 -d bug-64-lld | grep -A1 -e '<_start>:'
0000000000201000 <_start>:
  201000:       e8 0f 00 00 00          call   201014 <foo+0x4>

If you link with GNU ld instead, the relocation is applied correctly.

$ x86_64-elf-ld -melf_x86_64 -o bug-64-ld bug-64.o
$ x86_64-elf-objdump -M i386 -d bug-64-ld | grep -A1 -e '<_start>:'
0000000000400080 <_start>:
  400080:       e8 0b 00 00 00          call   400090 <foo>

Linking the 32-bit object file works correctly with both GNU ld and ld.lld.

$ ./llvm-build/bin/ld.lld -melf_i386 -o bug-lld bug.o
$ x86_64-elf-objdump -d bug-lld | grep -A1 -e '<_start>:'
00011000 <_start>:
   11000:       e8 0b 00 00 00          call   11010 <foo>
$ x86_64-elf-ld -melf_i386 -o bug-ld bug.o
$ x86_64-elf-objdump -d bug-ld | grep -A1 -e '<_start>:'
08048060 <_start>:
 8048060:       e8 0b 00 00 00          call   8048070 <foo>

I'm not at all familiar with the lld source, but this looks a lot like getImplicitAddend() needs to be implemented for the X86_64 class.

Alternatively (but much less useful for me) would be an error message that REL relocations are not supported on x86-64.

I've attached all of the files created above, in case anyone wants to examine them.

Thank you,

Steve

--
Stephen Checkoway




_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev




--
-- 
Peter

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] lld mishandling R_X86_64_PC32 relocations

U.Mutlu via llvm-dev
Hi Peter,

I hadn't noticed that line about RELA in the ABI document, thanks! I agree that this is a bug in objcopy. I'll file a bug against objcopy.

It seems that lld already supports relocations that don't comply with the standard (namely R_X86_64_16 and R_X86_64_8 <https://github.com/hjl-tools/x86-psABI/blob/hjl/master/object-files.tex#L554>), but I guess that's different than supporting an entirely different format.

Thanks for looking into this.

Steve

> On Jun 5, 2018, at 14:34, Peter Collingbourne via llvm-dev <[hidden email]> wrote:
>
> Hi Stephen,
>
> I think the bug is in objcopy, as it is creating a file that does not comply with the x86-64 psABI, which requires all relocations to be RELA:
> https://github.com/hjl-tools/x86-psABI/blob/hjl/master/object-files.tex#L429
> I also tried passing your bug-64.o to ld.gold, and it rejects it with an internal error.
>
> $ ld.gold -r -o bug-64-2.o bug-64.o
> ld.gold: internal error in scan_relocatable_relocs, at ../../gold/x86_64.cc:5118
> $ ld.gold  -o bug-64-2.o bug-64.o
> ld.gold: error: bug-64.o: unsupported REL reloc section
> ld.gold: internal error in relocate_section, at ../../gold/x86_64.cc:5051
>
> Probably what needs to happen is that we need to start rejecting files which use the wrong relocation type and a bug needs to be filed against objcopy.
>
> Peter
>
> On Tue, Jun 5, 2018 at 10:33 AM, Stephen Checkoway via llvm-dev <[hidden email]> wrote:
> Hi,
>
> I've tracked down what I believe is a bug in lld's relocation processing for R_X86_64_PC32 REL relocations.
>
> I'm producing the object file in a slightly unusual way: I'm using objcopy on a relocatable i386 ELF object file to convert it to x86_64 which transforms a R_386_PC32 into a R_X86_64_PC32.
>
> Steps to reproduce:
>
> 1. Assemble the attached bug.asm using nasm and note the R_386_PC32 REL.
>
> $ nasm -felf32 -o bug.o bug.asm
> $ x86_64-elf-objdump -dr bug.o | grep -A1 -e '<_start>:'
> 00000000 <_start>:
>    0:   e8 fc ff ff ff          call   1 <_start+0x1>
> $ x86_64-elf-readelf -r bug.o
>
> Relocation section '.rel.text._start' at offset 0x260 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name
> 00000001  00000302 R_386_PC32        00000000   .text.foo
>
> 2. Convert bug.o to a 64-bit ELF object file and note the R_X86_64_PC32 REL (not RELA!)
>
> $ x86_64-elf-objcopy -I elf32-i386 -O elf64-x86-64 bug.o bug-64.o
> $ x86_64-elf-objdump -M i386 -dr bug-64.o | grep -A1 -e '<_start>:'
> 0000000000000000 <_start>:
>    0:   e8 fc ff ff ff          call   1 <_start+0x1>
> $ x86_64-elf-readelf -r bug-64.o
>
> Relocation section '.rel.text._start' at offset 0x128 contains 1 entry:
>   Offset          Info           Type           Sym. Value    Sym. Name
> 000000000001  000300000002 R_X86_64_PC32     0000000000000000 .text.foo
>
> 3. Link with a just-built ld.lld and note that the relocation has been misapplied. It's now calling foo+4 rather than foo.
>
> $ ./llvm-build/bin/ld.lld -melf_x86_64 -o bug-lld bug-64.o
> $ x86_64-elf-objdump -M i386 -d bug-64-lld | grep -A1 -e '<_start>:'
> 0000000000201000 <_start>:
>   201000:       e8 0f 00 00 00          call   201014 <foo+0x4>
>
> If you link with GNU ld instead, the relocation is applied correctly.
>
> $ x86_64-elf-ld -melf_x86_64 -o bug-64-ld bug-64.o
> $ x86_64-elf-objdump -M i386 -d bug-64-ld | grep -A1 -e '<_start>:'
> 0000000000400080 <_start>:
>   400080:       e8 0b 00 00 00          call   400090 <foo>
>
> Linking the 32-bit object file works correctly with both GNU ld and ld.lld.
>
> $ ./llvm-build/bin/ld.lld -melf_i386 -o bug-lld bug.o
> $ x86_64-elf-objdump -d bug-lld | grep -A1 -e '<_start>:'
> 00011000 <_start>:
>    11000:       e8 0b 00 00 00          call   11010 <foo>
> $ x86_64-elf-ld -melf_i386 -o bug-ld bug.o
> $ x86_64-elf-objdump -d bug-ld | grep -A1 -e '<_start>:'
> 08048060 <_start>:
>  8048060:       e8 0b 00 00 00          call   8048070 <foo>
>
> I'm not at all familiar with the lld source, but this looks a lot like getImplicitAddend() needs to be implemented for the X86_64 class.
>
> Alternatively (but much less useful for me) would be an error message that REL relocations are not supported on x86-64.
>
> I've attached all of the files created above, in case anyone wants to examine them.
>
> Thank you,
>
> Steve
>
> --
> Stephen Checkoway
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>
>
>
> --
> --
> Peter
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

--
Stephen Checkoway



_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] lld mishandling R_X86_64_PC32 relocations

U.Mutlu via llvm-dev
On Tue, Jun 5, 2018 at 1:50 PM Stephen Checkoway via llvm-dev <[hidden email]> wrote:
Hi Peter,

I hadn't noticed that line about RELA in the ABI document, thanks! I agree that this is a bug in objcopy. I'll file a bug against objcopy.

It seems that lld already supports relocations that don't comply with the standard (namely R_X86_64_16 and R_X86_64_8 <https://github.com/hjl-tools/x86-psABI/blob/hjl/master/object-files.tex#L554>), but I guess that's different than supporting an entirely different format.

lld supports the extension because LLVM supports the extension too (https://llvm.org/docs/Extensions.html#x86). But yeah, as you said, that's a small extension to the standard, and that's different from supporting an entirely different format.
 
Thanks for looking into this.

Steve

> On Jun 5, 2018, at 14:34, Peter Collingbourne via llvm-dev <[hidden email]> wrote:
>
> Hi Stephen,
>
> I think the bug is in objcopy, as it is creating a file that does not comply with the x86-64 psABI, which requires all relocations to be RELA:
> https://github.com/hjl-tools/x86-psABI/blob/hjl/master/object-files.tex#L429
> I also tried passing your bug-64.o to ld.gold, and it rejects it with an internal error.
>
> $ ld.gold -r -o bug-64-2.o bug-64.o
> ld.gold: internal error in scan_relocatable_relocs, at ../../gold/x86_64.cc:5118
> $ ld.gold  -o bug-64-2.o bug-64.o
> ld.gold: error: bug-64.o: unsupported REL reloc section
> ld.gold: internal error in relocate_section, at ../../gold/x86_64.cc:5051
>
> Probably what needs to happen is that we need to start rejecting files which use the wrong relocation type and a bug needs to be filed against objcopy.
>
> Peter
>
> On Tue, Jun 5, 2018 at 10:33 AM, Stephen Checkoway via llvm-dev <[hidden email]> wrote:
> Hi,
>
> I've tracked down what I believe is a bug in lld's relocation processing for R_X86_64_PC32 REL relocations.
>
> I'm producing the object file in a slightly unusual way: I'm using objcopy on a relocatable i386 ELF object file to convert it to x86_64 which transforms a R_386_PC32 into a R_X86_64_PC32.
>
> Steps to reproduce:
>
> 1. Assemble the attached bug.asm using nasm and note the R_386_PC32 REL.
>
> $ nasm -felf32 -o bug.o bug.asm
> $ x86_64-elf-objdump -dr bug.o | grep -A1 -e '<_start>:'
> 00000000 <_start>:
>    0:   e8 fc ff ff ff          call   1 <_start+0x1>
> $ x86_64-elf-readelf -r bug.o
>
> Relocation section '.rel.text._start' at offset 0x260 contains 1 entry:
>  Offset     Info    Type            Sym.Value  Sym. Name
> 00000001  00000302 R_386_PC32        00000000   .text.foo
>
> 2. Convert bug.o to a 64-bit ELF object file and note the R_X86_64_PC32 REL (not RELA!)
>
> $ x86_64-elf-objcopy -I elf32-i386 -O elf64-x86-64 bug.o bug-64.o
> $ x86_64-elf-objdump -M i386 -dr bug-64.o | grep -A1 -e '<_start>:'
> 0000000000000000 <_start>:
>    0:   e8 fc ff ff ff          call   1 <_start+0x1>
> $ x86_64-elf-readelf -r bug-64.o
>
> Relocation section '.rel.text._start' at offset 0x128 contains 1 entry:
>   Offset          Info           Type           Sym. Value    Sym. Name
> 000000000001  000300000002 R_X86_64_PC32     0000000000000000 .text.foo
>
> 3. Link with a just-built ld.lld and note that the relocation has been misapplied. It's now calling foo+4 rather than foo.
>
> $ ./llvm-build/bin/ld.lld -melf_x86_64 -o bug-lld bug-64.o
> $ x86_64-elf-objdump -M i386 -d bug-64-lld | grep -A1 -e '<_start>:'
> 0000000000201000 <_start>:
>   201000:       e8 0f 00 00 00          call   201014 <foo+0x4>
>
> If you link with GNU ld instead, the relocation is applied correctly.
>
> $ x86_64-elf-ld -melf_x86_64 -o bug-64-ld bug-64.o
> $ x86_64-elf-objdump -M i386 -d bug-64-ld | grep -A1 -e '<_start>:'
> 0000000000400080 <_start>:
>   400080:       e8 0b 00 00 00          call   400090 <foo>
>
> Linking the 32-bit object file works correctly with both GNU ld and ld.lld.
>
> $ ./llvm-build/bin/ld.lld -melf_i386 -o bug-lld bug.o
> $ x86_64-elf-objdump -d bug-lld | grep -A1 -e '<_start>:'
> 00011000 <_start>:
>    11000:       e8 0b 00 00 00          call   11010 <foo>
> $ x86_64-elf-ld -melf_i386 -o bug-ld bug.o
> $ x86_64-elf-objdump -d bug-ld | grep -A1 -e '<_start>:'
> 08048060 <_start>:
>  8048060:       e8 0b 00 00 00          call   8048070 <foo>
>
> I'm not at all familiar with the lld source, but this looks a lot like getImplicitAddend() needs to be implemented for the X86_64 class.
>
> Alternatively (but much less useful for me) would be an error message that REL relocations are not supported on x86-64.
>
> I've attached all of the files created above, in case anyone wants to examine them.
>
> Thank you,
>
> Steve
>
> --
> Stephen Checkoway
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>
>
>
> --
> --
> Peter
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

--
Stephen Checkoway



_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev