Linker error: warning: internal error: out of range error

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm getting several linker warnings in my project like:

    "ClockMenu.c:39: warning: internal error: out of range error"
The locations indicated are all function calls. The linker (incorrectly) creates an elf file, even though it leaves the called function address as 0, resulting in an application that constantly reboots.

Here is ClockMenu.c:39

    CMenuSetCalVal(MenuCalVal ^ 1); //flip
The function "CMenuSetCalVal" is the next function in the file (yes, a prototype has been declared).

The full link log is listed below. The project itself is NOT big: 22720 bytes code and 1489 bytes data. It does have a HUGE assembly source (ScopeClock.S) and several small C sources Clock.C, ClockData.c, ClockMenu.c. I'm converting stuff to C but run into this error continuously.

The only references I can find to this problem have to do with AVRs with >128KB of code space, which is not the case here (Atmega328p)

I'm running WinAVR-20100110. Attached are the object files to repro this problem.

Any workarounds? What is the best place to report this?

Thanks

    Build started 23.3.2010 at 06:23:53
    avr-gcc -mmcu=atmega328p -Wall -gdwarf-2 -std=gnu99 -DF_CPU=20000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT ClockMenu.o -MF dep/ClockMenu.o.d -c ../ClockMenu.c
    avr-gcc -mmcu=atmega328p -Wl,-Map=ScopeClock.map Clock.o ScopeClock.o ClockData.o ClockMenu.o -o ScopeClock.elf
    ScopeClock.o: In function `CMenuSetTable':
    C:\Electronics\DutchtronixClock\winavr\default/.././ChangeMenu.asm:643: warning: internal error: out of range error
    ClockMenu.o: In function `CMenuNextCalVal':
    C:\Electronics\DutchtronixClock\winavr\default/../ClockMenu.c:39: warning: internal error: out of range error
    avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature ScopeClock.elf ScopeClock.hex
    avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex ScopeClock.elf ScopeClock.eep || exit 0
    avr-objdump -h -S ScopeClock.elf > ScopeClock.lss

    AVR Memory Usage
    ----------------
    Device: atmega328p

    Program: 22720 bytes (69.3% Full)
    (.text + .data + .bootloader)

    Data: 1489 bytes (72.7% Full)
    (.data + .bss + .noinit)

    Build succeeded with 2 Warnings...

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We've had a few threads on this before. They seem to be about a problem for AVRs with big flash, eg larger than 128K, which the 328 has not, so they might not help you. Still, putting the string "warning: internal error: out of range error" into the search function here (and checking the Search for all words checkbox), might yield good answers that might help you.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Would you feel comfortable posting your code? I know the problem is reported as a linker problem but your source might show something.

I have seen this error on large switch/case statements. Rearranging the object files cured it for me; try moving ClockMenu.o to a different place in the OBJECTS list in Makefile.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the replies. Yes, I did search for the suggested string, here and other places, but nothing relevant to my case showed up. However, the discussions on this issue go back several years! How can a serious bug like this not be addressed??? At least make it a fatal error in the linker (create no output). If it's a user error, improve the message.

What is the proper place to submit a winavr bug report. I couldn't find it on sourceforge.

The source code is mainly in assembler (about 15 files assembled into 1 object using #include, over 15000 lines). Since I just started the conversion process, most of the labels are internal so the linker doesn't even see them. There are just 3 small c files. I'm listing the offending file here:

    #include
    #include
    #include
    #include
    #include

    #include "./config.h"
    #include "./constants.h"
    #include "./ClockData.h"

    void CMenuSetCalVal(byte newVal);
    void UpdateCalibration(byte newVal);
    void UpdateFlashEntryNew(ScanTblEntry_t* p1, pByte p2, pByte p3);

    extern pByte OffOnValTbl[] PROGMEM;

    #define SetCMENULAST CMenuState = CMENULAST

    void CMenuNextCalVal(void)
    {
    CMenuSetCalVal(MenuCalVal ^ 1); //flip
    }

    void CMenuSetCalVal(byte newVal)
    {
    MScanTbl_CalVal->pVect = (pByte)pgm_read_word(&OffOnValTbl[newVal]);
    UpdateFlashEntryNew(MScanTbl_CalVal, CMenuFlashPtr, MScanTbl_CalVal->pVect);
    }

    void CMenuSaveCalVal(void)
    {
    if (MenuCalVal != ShowCalibration) {
    UpdateCalibration(MenuCalVal);
    SetCMENULAST;
    }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jrseattle wrote:
How can a serious bug like this not be addressed???
Simple. No one has provided a test case that shows the problem. You obviously have done enough code to know that the mere statement of a problem is often not enough -- the report must include instructions on how to reproduce the problem.

Please consider that, like you, the compiler maintainers generally do not allow serious problems in their code to go unaddressed if it breaks on their system. The key phrase is "breaks on their system".

jrseattle wrote:
What is the proper place to submit a winavr bug report. I couldn't find it on sourceforge.
WinAVR is being shut down (in favor of something else? Atmel & Co are not saying, but don't worry, something is coming). Since this is a linker problem I would submit it to the GCC Bugzilla list. Be sure to specify the Target avr-*-* and start your summary title with the tag [avr-gcc].

Before submitting your bug, see if you can come up with a reduced code example that causes the problem. In addition to helping the maintainers it may also point to a workaround for you to use.

You can find the complete list of outstanding bugs here.

jrseattle wrote:
The source code is mainly in assembler (about 15 files assembled into 1 object using #include, over 15000 lines). Since I just started the conversion process, most of the labels are internal so the linker doesn't even see them. There are just 3 small c files. I'm listing the offending file here:
That file may be reporting the problem but I suspect it is the assembly that is causing the problem.

The linker seems to report this kind of problem when the generated instruction (RJMP, Branch...) is going to a location that the linker cannot fit into the limited address space of the instruction. The linker cannot change the instruction and so pukes. At least, that has been my experience.

Sorry I cannot be more helpful.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I went looking some more and found out that it is "User Error", though the linker can definitely do a better job at reporting this. The good news is that I learned something in the process: flash based labels that are addressed as data (lpm instruction) do NOT have to be word aligned in the WinAVR world!

Background:
Atmel AVRs flash addresses are WORD sized (16-bits) when referred to from executable code, but BYTE sized (8-bits) when referred to as data (lpm instruction). Winavr uses byte addresses for ALL labels, code and data. This causes a lot of problem in the AVR world, specially when doing indirect calls (icall). On top of that, no static arithmetic is allowed on flash labels (like "flash_label << 1". Coders may have to do run-time arithmetic to get the proper flash label.

The problem:
In my assembly code there are lots of flash based data tables/strings. Somehow, one of these tables got to be odd sized. When using the AVR Studio assembler, this gets reported immediately, but gas (Gnu assembler) does not flag this as a problem. As a result of this, the object module resulting from the assembly file was odd sized (in bytes) and the NEXT flash label was at an odd byte address. Because the linker moves stuff around, the NEXT flash label changes all the time, so the error location changes, sometimes even disappears. When the linker needs to update the relocatable address in an instruction like "call" and finds that the target address is odd, it croaks. I assume that there is a hack in the GNU linker for AVRs where it converts the address from a byte address to a word address, but it cannot issue a proper error message is the address is odd. My problems disappear when I add ".balign 2" at the end of the flash based tables/strings.

The lessons:
1. in WinAVR assembly files, always add ".balign 2" at the end
2. It is not necessary to make all flash based data (strings for example) even length, something that is necessary with the AVR Studio assembler (because it can't handle byte aligned flash addresses). This saves some space.

My request to the WinAVR maintainers:
Please flag this error better.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The linker simply has no clue where that alignment issue
originates from, I guess. But you'd have to dive deep into
the linker in order to know for sure.

As for calculating the word address from a program memory
label, there's an operator called "pm", so you can say
something like:

   ldi  r24, lo8(pm(label))
   ldi  r25, hi8(pm(label))

The reason you are not allowed to do math with the labels is
that the ELF format (and linker) simply cannot perform general
arithmetic expression evaluations on relocatable labels. (The
last linker I've seen that can do this was the RSX-11 taskbuilder
on the PDP-11. I guess VMS might have inherited that feature.)

So instead, the pm operator causes the assembler to emit a
different relocation record type, so the linker eventually knows
when processing that record it has to right-shift the value by
one after computation.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.