ld segfaults with LTO, static library, and memcpy

Bug #1757457 reported by Erlkoenig
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
GNU Arm Embedded Toolchain
New
Undecided
Unassigned

Bug Description

Dear maintainers,

I have discovered that LD from the ARM toolchain version 7-2017-q4-major segfaults when a specific set of conditions coincide:
- A startup code that calls main() is compiled into a static library (.a)
- A main() function calls memcpy with a variable as 3rd parameter
- LTO is enabled
- A custom but trivial linker script is used

The output is:
$ make
arm-none-eabi-gcc -flto -c -o main.o main.c
arm-none-eabi-gcc -flto -c -o startup.o startup.c
arm-none-eabi-gcc-ar -r startup.a startup.o
/home/erlkoenig/programs/gcc-arm-embedded/gcc-arm-none-eabi-7-2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ar: creating startup.a
arm-none-eabi-gcc -flto -o app.elf main.o startup.a -T ldscript.ld -nostartfiles
collect2: fatal error: ld terminated with signal 11 [Segmentation fault]
compilation terminated.
makefile:6: recipe for target 'app.elf' failed
make: *** [app.elf] Error 1

The problem occurs on both Windows and Linux and on different machines (Core-i3 i4010U, Xeon E5520), using both the prebuilt binary packages and a self-compiled one (see bug #1742188 ).
Attempting to compile the attached testcase (run "make") triggers the problem. The code is of course rather stupid and would not work when compiled, and is the result of reducing actually useful code to a compact example.

Thanks for looking into this!

Tags: crash ld
Revision history for this message
Erlkoenig (profclonk) wrote :
Revision history for this message
Erlkoenig (profclonk) wrote :

I built debuggable toolchain, obtained a core dump and ran gdb on it:

Core was generated by `.../arm-none-eabi-ld'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000004527a3 in arm_build_one_stub (gen_entry=0x1545370, in_arg=0x77f540 <link_info>) at .../binutils/bfd/elf32-arm.c:4731
4731 + stub_entry->target_section->output_section->vma);
(gdb) bt
#0 0x00000000004527a3 in arm_build_one_stub (gen_entry=0x1545370, in_arg=0x77f540 <link_info>) at .../binutils/bfd/elf32-arm.c:4731
#1 0x000000000043b7dc in bfd_hash_traverse (table=0x153c440, func=0x4525f6 <arm_build_one_stub>, info=0x77f540 <link_info>) at .../binutils/bfd/hash.c:656
#2 0x0000000000456c7d in elf32_arm_build_stubs (info=0x77f540 <link_info>) at ./binutils/bfd/elf32-arm.c:6722
#3 0x000000000042b260 in gldarmelf_finish () at earmelf.c:517
#4 0x00000000004237ee in ldemul_finish () at .../binutils/ld/ldemul.c:94
#5 0x00000000004193e5 in lang_process () at .../binutils/ld/ldlang.c:7402
#6 0x000000000041d52e in main (argc=23, argv=0x7ffd7f69b3b8) at .../binutils/ld/ldmain.c:432
(gdb) print stub_entry->target_section->output_section
$1 = (struct bfd_section *) 0x0

The code in question is:

  /* This is the address of the stub destination. */
  sym_value = (stub_entry->target_value
        + stub_entry->target_section->output_offset
        + stub_entry->target_section->output_section->vma);

Since stub_entry->target_section->output_section is 0, this is a classic null-pointer dereferencing bug.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.