Bug 13812 - Suboptimal default linker script cause "internal error: out of range error"
Summary: Suboptimal default linker script cause "internal error: out of range error"
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: ---
Assignee: Senthil Kumar Selvaraj
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-05 21:26 UTC by Georg-Johann Lay
Modified: 2013-03-27 13:24 UTC (History)
4 users (show)

See Also:
Host:
Target: avr
Build:
Last reconfirmed:


Attachments
stubc.c: Simplified C test case (98 bytes, text/plain)
2012-03-05 21:36 UTC, Georg-Johann Lay
Details
stubc.s: Assembler file (361 bytes, text/plain)
2012-03-05 21:48 UTC, Georg-Johann Lay
Details
Patch that loops over all sections (528 bytes, patch)
2013-03-12 17:54 UTC, Senthil Kumar Selvaraj
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Georg-Johann Lay 2012-03-05 21:26:36 UTC
On big devices where stubs are generated to reach all targets of indirect jumps, the following error might occur:

>> warning: internal error: out of range error

Reason is the following part of the default linker script that
places .trampolines after .progmem:

    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;

Thus, if there is lot of data in the .progmem.data section (which is avr-gcc's default section for data located in flash), the .trampolines section is located outside the first 64 Ki word segment.

There are two issues:

1) The error message is not helpful at all. It should mention that something
   goes wrong with the .trampolines or gs() modifiers or stubs generation.

2) The error could be avoided by placing .trampolines prior to .progmem like so:

    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;
    *(.progmem*)

The .progmem.gcc* section is used for jump dispatch tables (e.g. .progmem.gcc_sw_table) and must be located in lower 64 KiB
Comment 1 Georg-Johann Lay 2012-03-05 21:36:52 UTC
Created attachment 6262 [details]
stubc.c: Simplified C test case

Compile with

avr-gcc -mmcu=atmega2560 stubs.c -S -Os
Comment 2 Georg-Johann Lay 2012-03-05 21:48:30 UTC
Created attachment 6263 [details]
stubc.s: Assembler file

Assemble/Link with:

avr-as -mmcu=atmega2560 stubs.s -o stubs.o
avr-ld -mavr6 stubs.o

or at your option

avr-gcc -mmcu=atmega2560 stubs.s

Error message:

stubs.o: In function `main':
stubs.c:(.text.startup+0x0): warning: internal error: out of range error
stubs.c:(.text.startup+0x2): warning: internal error: out of range error

Relevant part of the map file:

.text           0x00000000    0x2720e
 *(.vectors)
 .vectors       0x00000000       0xe4 e:/winavr/4.7.0-3/bin/../lib/gcc/avr/4.7.0/../../../../avr/lib/avr6/crtm2560.o
                0x00000000                __vector_default
                0x00000000                __vectors
 *(.vectors)
 *(.progmem.gcc*)
 *(.progmem*)
 .progmem.data  0x000000e4    0x27100 stubs.o
                0x000000e4                array4
                0x00007de4                array3
                0x0000fae4                array2
                0x000177e4                array1
                0x0001f4e4                array0
                0x000271e4                . = ALIGN (0x2)
                0x000271e4                __trampolines_start = .
 *(.trampolines)
 .trampolines   0x000271e4        0x4 linker stubs
 *(.trampolines*)
                0x000271e8                __trampolines_end = .
 *(.jumptables)
Comment 3 Georg-Johann Lay 2012-05-03 20:13:06 UTC
*** Bug 14058 has been marked as a duplicate of this bug. ***
Comment 4 Senthil Kumar Selvaraj 2013-03-12 17:53:02 UTC
Actually, the linker relaxation code already considers cases where deletion of the ret in call/ret or jmp/ret might be unsafe - just that it missed this specific case.

The case being that GCC puts the array containing the addresses of the labels in a separate section (.rodata). The safe ret deletion logic assumes that only relocations in the local section (containing the ret) could potentially have symbols whose values evaluate to the address containing the ret, but that is not true in this case.

Looping over all sections in the BFD, and repeating the check for each section fixes the problem (see attached patch).
Comment 5 Senthil Kumar Selvaraj 2013-03-12 17:54:26 UTC
Created attachment 6931 [details]
Patch that loops over all sections
Comment 6 Senthil Kumar Selvaraj 2013-03-12 17:57:33 UTC
Oops - Disregard my previous comments - they were meant for bug #12494
Comment 7 Sourceware Commits 2013-03-27 13:21:40 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	nickc@sourceware.org	2013-03-27 13:21:38

Modified files:
	ld             : ChangeLog 
	ld/scripttempl : avr.sc 

Log message:
	PR ld/13812
	* scripttempl/avr.sc: Place trampolines before .progmem section.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/ChangeLog.diff?cvsroot=src&r1=1.2573&r2=1.2574
http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/scripttempl/avr.sc.diff?cvsroot=src&r1=1.15&r2=1.16
Comment 8 Nick Clifton 2013-03-27 13:24:29 UTC
Hi Georg-Johann,

  I have applied a patch to update the default linker script as you suggested.

  I have not created a patch to change the error message, because I could not think of anything helpful to actually tell the user.  Well not that would fit into a single sentence anyway.  With a bit of luck, the linker patch will stop further outofrange stub errors anyway, so the error message problem will become moot.

Cheers
  Nick