Sources Bugzilla – Bug 1038
resolution of weak symbol not left for the linker if value is already known
Last modified: 2010-09-20 05:16:49 UTC
avr-libc's C run-time startup code uses something like the following to initialize the stack: .weak __stack .set __stack, RAMEND ... ldi r28,lo8(__stack) #ifdef SPH ldi r29,hi8(__stack) out _SFR_IO_ADDR(SPH), r29 #endif out _SFR_IO_ADDR(SPL), r28 Here, RAMEND as a C preprocessor macro that depends on the actual processor type this code is being compiled for, and which evaluates to a 16-bit number by the time this code is being assembled. The idea behind that is that while the stack initially starts at top of RAM (growing downwards), the user can tune the actual stack location at link time by supplying a different value for the weak symbol __stack. However, as the value of __stack is already known to the assembler at that point, the assembler actually inserts the fixed value RAMEND instead of a reference to the weak symbol __stack, thereby entirely defeating the idea behind marking __stack as `weak' in the first place. By reordering the code, and placing the definition of __stack behind its use in the assembly code, the problem can be worked around, but I believe the assembler must not resolve symbols marked as `weak' in the first place but always leave that to the linker.
The method to resolve the issue would probably be to disallow gas to do any fixup work on weak lables. Probably one could use the TC_VALIDATE_FIX hook in order to realize this. E.g. by adapting an expression like #define TC_VALIDATE_FIX(FIXP,SEG,SKIP) \ if (FIXP->fx_r_type == BFD_RELOC_AVR_7_PCREL \ || FIXP->fx_r_type == BFD_RELOC_AVR_13_PCREL \ || FIXP->fx_r_type == BFD_RELOC_AVR_LO8_LDI_PM \ || FIXP->fx_r_type == BFD_RELOC_AVR_HI8_LDI_PM \ || FIXP->fx_r_type == BFD_RELOC_AVR_HH8_LDI_PM \ || FIXP->fx_r_type == BFD_RELOC_AVR_16_PM) \ { \ goto SKIP; \ } to handle the case that FIXP refers to weak lables. The only question would be, how to find out whether or not FIXP refers to a weak label.? This probably would solve the issue for the avr target. I think, however, that the issue should be addressed for all of the targets since I believe it to be present also elsewhere.
Joerg, This is an old bug. Do you still happen to have a test case for this?
Created attachment 4990 [details] Testcase for bug 1038
In reply to comment #2: > This is an old bug. Do you still happen to have a test case for this? The testcase from the original posting is still valid. I've put it into a compilable file, see attachment. Compile with: avr-gcc -mmcu=atmega8 -c bug1038.S Disassemble the result: % avr-objdump -d bug1038.o bug1038.o: file format elf32-avr Disassembly of section .text: 00000000 <.text>: 0: cf e5 ldi r28, 0x5F ; 95 2: d4 e0 ldi r29, 0x04 ; 4 4: de bf out 0x3e, r29 ; 62 6: cd bf out 0x3d, r28 As can be seen, the assembler already resolved the weak symbol __stack (despite as marking it as weak in the symbol table), and inserted the (compile-time) constant RAMEND.