Branch error "bug"

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

Technically, this isn't really a bug, more of a "gotcha" for those who first encounter it.

When compiling a GCC program that includes a .S assembly, a very bizarre error is thrown if you use a branch instruction that is out of reach...

5301:(.text+0x2326): relocation truncated to fit: R_AVR_7_PCREL against `no symbol'

I figured this out easily enough since I had only added a BRNE to my code, but this error could certainly be more descriptive and offer something like...

ERROR: Relative Branch Too Far (Line 5432 : BRNE)

This is similar to the no highlight on BRGE "bug" I found.. not really a bug, but could be fixed.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

This is a linker message. The linker is code-agnostic (*); it was the assembler which has seen the "wordy" version of the code the last time and produced binary version, with marks for the linker asking to fix the addresses it does not know at the time of assembling.

Also, the linker uses a codebase common for all processors, that's why the error message is not that specific.

I don't say it can't be made more descriptive, just that it would be quite a bit of work which I am not sure would pay out.

JW

(*) There are exceptions, e.g. the relaxation routine sort of "disassembles" certain sequences to "see", whether it is e.g. a JMP and replaces them by RJMP where appropriate.

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

wek wrote:
This is a linker message. The linker is code-agnostic (*); it was the assembler which has seen the "wordy" version of the code the last time and produced binary version, with marks for the linker asking to fix the addresses it does not know at the time of assembling.

Also, the linker uses a codebase common for all processors, that's why the error message is not that specific.

In the ordinary case, e.g., without linker relaxation,
would the linker have ready access to the name of the opcode?
Quote:
I don't say it can't be made more descriptive, just that it would be quite a bit of work which I am not sure would pay out.

Iluvatar is the better part of Valar.

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

I am not to familiar with what goes on "under the hood", but if the compiler can scan through the assembly to find bogus instructions or problems like "LD R16,22" , then why can't it also look at the "BRNE LABEL" and simply count the number of instructions from there to "LABEL" and then report a more meaningful error? The Atmel compiler did.

It knew enough to throw the error, so it must know that the error is due to a branch out of reach.

Am I making this sound to easy?

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

The compiler will not generate such code. The compiler will shorten branches so that only branches with a valid offset are used.

But you used (inline) assembler and the compiler will never see it.

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB wrote:
The compiler will not generate such code. The compiler will shorten branches so that only branches with a valid offset are used.
Though this is not one of them, there are rare occasions on which it will.
Quote:
But you used (inline) assembler and the compiler will never see it.
The compiler does see inline assembler, but OP didn't use it.
Inline assembler can cause the compiler to emit a bad branch.
Sometimes the compiler needs to know the number of bytes in inline assembler.
Its formula sometimes produces a number that is too small.
On some such occasions, the compiler emits a branch or an rjmp too far.

Iluvatar is the better part of Valar.

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

skeeve wrote:
SprinterSB wrote:
But you used (inline) assembler and the compiler will never see it.
The compiler does see inline assembler,
Well, it sees as much of inline assembler as it does with printf: Insert operands into %-places and then output the string.
Quote:
Inline assembler can cause the compiler to emit a bad branch.
ometimes the compiler needs to know the number of bytes in inline assembler.
The compiler does not look at printf or inline asm strings except for %-operands. Moreover, it tries to deduces the number of lines in the latter case from the number of line breaks. Consequently, if .fill or .rept or .macro or similar is used, a common error is that the number of newlines is to small.

avrfreaks does not support Opera. Profile inactive.

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

AtomicZombie wrote:
I am not to familiar with what goes on "under the hood", but if the compiler can [...]

preprocessor - compiler - assembler - linker

gcc and kin follow quite closely this traditional scheme. You should not accuse the link in the chain which is not guilty.

AtomicZombie wrote:
The Atmel compiler did.

Atmel produces no compiler. You mean assembler. Atmel's assembler is of the non-linking variety; you as a user thus must provide it the entire source at once. It is then quite easy to resolve the unreachable jumps etc. and point directly to their source.

AtomicZombie wrote:
It knew enough to throw the error, so it must know that the error is due to a branch out of reach.

As I said, it's not impossible, but it's laborious.

AtomicZombie wrote:
Am I making this sound to easy?

It's time to deliver you the sermon: Oh, it's all open source. You can fix it yourself...

;-)

Jan

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

skeeve wrote:
In the ordinary case, e.g., without linker relaxation,
would the linker have ready access to the name of the opcode?

There is little difference between relax/nonrelax in this regard. The relaxation routine simply looks for a bit pattern to match the long jump (and a few others, such as the call/ret sequence). Would you call that "ready access to the name of the opcode"?

This is, IMHO, a case to be solved through (enhancement of) documentation, rather than through change in the tools. A list of possible errors emitteed by the toolchain, together with explanation and examples of "use", in a wiki-like easily-editable space, would go a long way...

... no I am not volunteering :-|

JW

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

wek wrote:
skeeve wrote:
In the ordinary case, e.g., without linker relaxation,
would the linker have ready access to the name of the opcode?

There is little difference between relax/nonrelax in this regard. The relaxation routine simply looks for a bit pattern to match the long jump (and a few others, such as the call/ret sequence). Would you call that "ready access to the name of the opcode"?
Access to the opcode pretty much implies access to its name.
Even if the lookup is inconvenient,
the offending instruction is surely available.
I understand "relocation truncated to fit".
To me, "R_AVR_7_PCREL against `no symbol'" is less than clear.
Quote:
This is, IMHO, a case to be solved through (enhancement of) documentation, rather than through change in the tools. A list of possible errors emitteed by the toolchain, together with explanation and examples of "use", in a wiki-like easily-editable space, would go a long way...

... no I am not volunteering :-|

JW

If one did want to start tinkering with gcc or avr-gcc,
where should one start?
Perhaps there could be a "Patches Welcome" sticky.
My starting point is that I have written code professionally,
mostly C, C++ and AVR assembly.
I've even written my own make files, but I've struggled just using Bingo's scripts.

Iluvatar is the better part of Valar.

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

Ok, I see that "fixing" this is beyond my pay grade! I am just the end user, and have no desire to dig into modifying the tool chain, make files, and all that mumbo. I code, I compile, I enjoy. That's as far as I intend to take it!

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

skeeve wrote:
If one did want to start tinkering with gcc or avr-gcc, where should one start?
What do you want to know?

avrfreaks does not support Opera. Profile inactive.

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

Quote:

AtomicZombie wrote:
The Atmel compiler did.

Atmel produces no compiler.


I've often used that line here on 'Freaks over the years. In my informal view that is very blurry now with AS6. Produces? Packages? Provides? Whatever word is appropriate, I've seen several discussions about the Atmel version/build/package.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
Quote:

AtomicZombie wrote:
The Atmel compiler did.

Atmel produces no compiler.


I've often used that line here on 'Freaks over the years. In my informal view that is very blurry now with AS6. Produces? Packages? Provides? Whatever word is appropriate, I've seen several discussions about the Atmel version/build/package.
Indeed; nevertheless Brad referred to Atmel's assembler, and that was my point.

JW

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

skeeve wrote:
To me, "R_AVR_7_PCREL against `no symbol'" is less than clear.
I guess, in this particular case there would be less confusion if some named symbol would be mentioned. I don't know why "no symbol" - could that be result of a particular switch set used to assemble the offending .S?

JW

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

I guess this is not a big deal, but I can see this being a nasty "gotcha" for someone new to assembly or a new GCC-AS convert coming from the Atmel version.

When you do something dorky with jumps and labels, such as spelling the name incorrectly, you get an obvious message that you can even double click on to send your cursor hurling to the very line in the .S file that has the problem. For instance...

undefined reference to `Render3D'

But the other nonsensical message thrown when a branch tries to jump too far is not so easy to track down, especially if you had just altered a single instruction in between the branch and the address. In my case, I was already jumping to the max, and only added a single nop, so it took s some time to realize what I had done, since the error means nothing and you can't click to take you to the place in the code.

When I first moved to GCC-AS, I did not like it, but after some time it became clear that it was far more powerful than the Atmel assembler, especially when coding in C and assembly at the same time.

But it could certainly use a little polishing on the assembly end.

I still don't see why the error can't be made more clear (and clickable) though. Would it not be just a matter of the preprocessor counting the number of instructions between branch and landing? Would this "no symbol" error be the same on another processor like ARM as well?

I wonder if this would be a good idea for Atmel?...

Release an Atmel version of GCC that has been made to be more AVR aware, and even fix it to be properly compatible with the XMega's program memory space.

That would sure be a nice way to support the new XMega series, and would certainly be easier than writing a brand new toolchain from scratch, no?

*** Atmel Studio 7 Coming soon!! ***
- Now includes automatic Far Pointer support
- Use data arrays up to 1.6MB in size
- Register aliases shared between C and assembly
- Advanced AVR preproccessor and assembler
- Automatic prototype parameter mismatch checker

And thanks to millions of requests from our users, we have added a programming sidebar that does not have to be opened and closed each time you want to program your chip - just press "program" and go right back to the IDE! Yay!

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

The RELOCs you are after are defined in BFD, see ./bfd/reloc.c.

RELOCs are a general BFD feature and are nothing AVR specific.

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB wrote:
The RELOCs you are after are defined in BFD, see ./bfd/reloc.c.

RELOCs are a general BFD feature and are nothing AVR specific.

However, one could make this particular error message more specific... Some of the details:
  • in said bfd/reloc.c, in cases which result in the "relocation truncated to fit" message, an enum constant bfd_reloc_overflow is returned
  • this is checked in the same bfd/reloc.c in the bfd_generic_get_relocated_section_contents() function - see case bfd_reloc_overflow
  • there, the printout function is called through (*link_info->callbacks->reloc_overflow), mark all the parameters passed, they provide all the info related to the given point where the relocation failed (i.e. from them the opcode should be inferred somehow)
  • the (*link_info->callbacks->reloc_overflow)() function pointer is initialized through initialized link_callbacks variable defined in ld/ldmain.c (and through initialization of the link_info.callbacks in the same file in main()); so that it points to reloc_overflow() function in ld/ldmain.c - that is the (generic, all-emulation) function which prints out the "truncated to fit" message now
  • to override this generic function, in /ld/emultemp/avrelf.em some of the "emulation-specific startup routines" should be used to override the default (*link_info->callbacks->reloc_overflow)() function pointer to point to our specific function, e.g. avr_elf_reloc_overflow() (living probably in the same /ld/emultemp/avrelf.em)
  • avr_elf_reloc_overflow() then should implement the original functionality of reloc_overflow() plus the avr-specific decoding of the offending opcode and appropriate printout
Simple and easy, isn't it? :-P

JW

PS. I still think it is a bad idea and that it is a much better idea to pay much more attention to enhanced documentation. I also believe it is a bad idea to stick to AS6 or any other IDE when it comes to resolving GNU-related issues, and I believe it is a bad idea even for Atmel to do that.

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

Quote:

*** Atmel Studio 7 Coming soon!! ***
- Now includes automatic Far Pointer support
- Use data arrays up to 1.6MB in size
- Register aliases shared between C and assembly
- Advanced AVR preproccessor and assembler
- Automatic prototype parameter mismatch checker

Will it run on other OSes than Windows? :wink:

Quote:
- Automatic prototype parameter mismatch checker

What did I miss here?

Quote:
And thanks to millions of requests from our users, we have added a programming sidebar that does not have to be opened and closed each time you want to program your chip - just press "program" and go right back to the IDE! Yay!

We've already been at this several times, Brad. It already exists, although not in precisely the form you are describing.

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

It finally dawned on me that R_AVR_7_PCREL is the kind of relocation.

Iluvatar is the better part of Valar.

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

wek wrote:
[*] in said bfd/reloc.c, in cases which result in the "relocation truncated to fit" message, an enum constant bfd_reloc_overflow is returned

I was probably wrong. It appears, that relocations for AVR are handled entirely in bfd/elf32-avr.c, thus the reloc_overflow() function (which prints out the message) is called from elf32_avr_relocate_section() through the same function pointer mechanism.

Thus, AVR-specific info could be printer quite easily at that point.

There is still a problem with the 'no symbol' - this appears to be the case when the target of relocation lies in the same section. It appears, that there is a problem with retrieving the symbol's name (into variable "name") in that case, earlier in the same function.

JW

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

JohanEkdahl wrote:
Quote:

*** Atmel Studio 7 Coming soon!! ***
- Now includes automatic Far Pointer support
- Use data arrays up to 1.6MB in size
- Register aliases shared between C and assembly
- Advanced AVR preproccessor and assembler
- Automatic prototype parameter mismatch checker

Will it run on other OSes than Windows? :wink:

Quote:
- Automatic prototype parameter mismatch checker

What did I miss here?

Quote:
And thanks to millions of requests from our users, we have added a programming sidebar that does not have to be opened and closed each time you want to program your chip - just press "program" and go right back to the IDE! Yay!

We've already been at this several times, Brad. It already exists, although not in precisely the form you are describing.

Yes, the "Start Without Debugging" function was great when working with only assembly, but now that I am using C and assembly, it does not start the programmer. oddly enough, the light does blink on the AVRISP once, but I still have to open the programming window, press program, and then close it just to get back to the IDE.

As for my other comment on prototypes, it's probably something I am doing wrong, but it seems that you can have an assembly prototype completely wrong and there is no error checking. in fact, the only difference I see from not having any protos is the message "impicit decleration of function".

I am making a lot of changes as I adjust my program, and having this incorrect proto...

extern int DrawPixel(uint8_t,uint8_t,uint8_t);

still allow a call to the routine as such...

DrawPixel(X,Y);

I would have figured that some kind of error would have been tossed on compile. perhaps "missing function parameter" or something?

It seems that having no protos at all is just easier?
.... still learning this C side of thing.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

Provide proper prototypes and compile with, e.g. -Werror=strict-prototypes

Maybe it's already enough you enable warnings and mind them.

avrfreaks does not support Opera. Profile inactive.

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

wek wrote:
There is still a problem with the 'no symbol' - this appears to be the case when the target of relocation lies in the same section. It appears, that there is a problem with retrieving the symbol's name (into variable "name") in that case, earlier in the same function.
Could the issue be the assembler?
Might the assembler compute the branch distance and leave checking it for the linker?
There is at least the possibility that a linker relaxation would reduce a branch too far to one that fits.

Iluvatar is the better part of Valar.

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

AtomicZombie wrote:
the "Start Without Debugging" function was great when working with only assembly, but now that I am using C and assembly, it does not start the programmer. oddly enough, the light does blink on the AVRISP once, but I still have to open the programming window, press program, and then close it just to get back to the IDE.

You can probably address that by modifying the programmer settings. There is a separate set of settings for [/Debug/Start Without Debugging].

- Open your project settings.
- Go to the Tool tab.
- Select your programmer, interface and other settings.
- Make sure you set a low enough ISP clock if applicable.
- In the Programming Settings combobox, you should probably select Erase entire chip.
- Save the settings
- [/Debug/Start Without Debugging]

Also note that if your Solution contains more than one Project, you should select the one you want to work on as the Startup Project.

Sid

Life... is a state of mind

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

skeeve wrote:
wek wrote:
There is still a problem with the 'no symbol' - this appears to be the case when the target of relocation lies in the same section. It appears, that there is a problem with retrieving the symbol's name (into variable "name") in that case, earlier in the same function.
Could the issue be the assembler?
Might the assembler compute the branch distance and leave checking it for the linker?
Ah, you mean that the name of (local) target got lost during assembling, as the target in "reloc" is referred to as an offset to the beginning of the given section?

That's a possibility, but the linker still should have the complete information so that it could reconstruct the label's name, IMO. In other words, the linker still has chance to recover the name and the current method to do that *is* faulty, either way.

c:\tmp>cat s1.s
.global main
.text
main:
  nop
  brne label1
.skip 0x1000
label1:
  nop
  brne main



c:\tmp>avr-as s1.S -o s1.o

c:\tmp>avr-objdump -t -r s1.o

s1.o:     file format elf32-avr

SYMBOL TABLE:
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00001004 l       .text  00000000 label1
00000000 g       .text  00000000 main


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000002 R_AVR_7_PCREL     .text+0x00001004
00001006 R_AVR_7_PCREL     .text


c:\tmp>avr-ld s1.o
s1.o: In function `main':
(.text+0x2): relocation truncated to fit: R_AVR_7_PCREL against `no symbol'
s1.o: In function `label1':
(.text+0x1006): relocation truncated to fit: R_AVR_7_PCREL against `no symbol'

c:\tmp>

Michael wrote:
There is at least the possibility that a linker relaxation would reduce a branch too far to one that fits.

I don't understand this remark. The "relocation truncated to fit" with "`no symbol'" appears regardless of relaxation is on or off.

JW

[EDIT] added nops so that labels' and relocs' addresses could be distinguished

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

ChaunceyGardiner wrote:
AtomicZombie wrote:
the "Start Without Debugging" function was great when working with only assembly, but now that I am using C and assembly, it does not start the programmer. oddly enough, the light does blink on the AVRISP once, but I still have to open the programming window, press program, and then close it just to get back to the IDE.

You can probably address that by modifying the programmer settings. There is a separate set of settings for [/Debug/Start Without Debugging].

- Open your project settings.
- Go to the Tool tab.
- Select your programmer, interface and other settings.
- Make sure you set a low enough ISP clock if applicable.
- In the Programming Settings combobox, you should probably select Erase entire chip.
- Save the settings
- [/Debug/Start Without Debugging]

Also note that if your Solution contains more than one Project, you should select the one you want to work on as the Startup Project.

Thanks, now it's working again.
Oddly, I had no issues with this command in any assembly project and this time I only had to click the tool tab but not change anything to get it working again. Settings are always the same... AVRISPII, PDI, and Erase Entire Chip.

Another bug? or is it just a quirk?

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

Do you have more than one project in your solution ?

Sid

Life... is a state of mind

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

ChaunceyGardiner wrote:
Do you have more than one project in your solution ?

Nope, just one C file, one .S file, and some data includes.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

No doubt what the build target is, then.

I have noticed that the tool changes to the simulator sometimes when my programmer isn't connected. So maybe it's caused by saving the settings when the programmer is offline ?

Anyway, it's easy enough to work around that once you know where to look.

Sid

Life... is a state of mind

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

Thanks, it's all good.
AS6 with GCC and GCC-AS has been a good experience now that I have some time in.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

wek wrote:
Michael wrote:
There is at least the *possibility* that a linker relaxation would reduce a branch too far to one that fits.

I don't understand this remark. The "relocation truncated to fit" with "`no symbol'" appears regardless of relaxation is on or off.
*emphasis* added.
Had your code included a JMP,
linker relaxation might have shortened it to an RJMP.
Such a shortening might have converted a branch too far into branch just close enough.

Iluvatar is the better part of Valar.