Suppose the following small C program: int main (void) { extern char __heap_start; return (int) & __heap_start; } Compile with: avr-gcc heap-start.c -mmcu=atmega168 -o heal-start.elf -Os -save-temps -Wl,-Map,heap-start.map -Wl,--gc-sections Assembler output is: .file "heap-start.c" __SP_H__ = 0x3e __SP_L__ = 0x3d __SREG__ = 0x3f __tmp_reg__ = 0 __zero_reg__ = 1 .section .text.startup,"ax",@progbits .global main .type main, @function main: .L__stack_usage = 0 ldi r24,lo8(__heap_start) ldi r25,hi8(__heap_start) ret .size main, .-main .ident "GCC: (GNU) 4.7.0 20120206 (experimental)" ATmega168 has RAM start at 0x100 but the generated map file reads ... *(.data) *(.data*) *(.rodata) *(.rodata*) *(.gnu.linkonce.d*) 0x00800100 . = ALIGN (0x2) 0x00800100 _edata = . 0x00800100 PROVIDE (__data_end, .) .bss 0x00800060 0x0 0x00800060 PROVIDE (__bss_start, .) *(.bss) *(.bss*) *(COMMON) 0x00800060 PROVIDE (__bss_end, .) 0x0000008a __data_load_start = LOADADDR (.data) 0x0000008a __data_load_end = (__data_load_start + SIZEOF (.data)) .noinit 0x00800060 0x0 0x00800060 PROVIDE (__noinit_start, .) *(.noinit*) 0x00800060 PROVIDE (__noinit_end, .) 0x00800060 _end = . 0x00800060 PROVIDE (__heap_start, .) ... That is obviously wrong because .bss starts at RAM 0x60. Notice that the program does not define data in the static storage. If data in static storage is added or --gc-sectons is removed, the values are as expected.
Created attachment 6217 [details] heap-start.s avr-gcc's assembler output
Created attachment 6218 [details] heap-start.map
Created attachment 6219 [details] Console Output with -v -Wl,-v Console output for the following command: avr-gcc heap-start.c -mmcu=atmega168 -o heal-start.elf -Os -save-temps -Wl,-Map,heap-start.map -Wl,--gc-sections -v -Wl,-v
Created attachment 6220 [details] heal-start.elf: Disassembly from avr-objdump -d avr-objdump -d heal-start.elf | grep -A 3 '<main>:' 00000080 <main>: 80: 80 e6 ldi r24, 0x60 ; 96 82: 90 e0 ldi r25, 0x00 ; 0 84: 08 95 ret
I think this pain is self-inflicted. You're using -m avr5 -Tdata 0x800100 instead of -m avr51. So you get the avr5 ld script with the data section fudged to be at 0x800100. However, the data section is stripped by -gc-sections. So the address change doesn't affect following sections. They stay at the avr5 data memory region of 0x800060.
(In reply to comment #5) > I think this pain is self-inflicted. > > You're using -m avr5 -Tdata 0x800100 instead of -m avr51. So you get the avr5 > ld script with the data section fudged to be at 0x800100. However, the data > section is stripped by -gc-sections. So the address change doesn't affect > following sections. They stay at the avr5 data memory region of 0x800060. atmega168 is element of avr5 and not element of avr51 (avr51 has ELPM instruction for example. ATmega168 has no ELPM). avr-gcc mixes devices with different RAM-start in the same core architecture, see mcu-devices.def: http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr-mcus.def?revision=184276&content-type=text%2Fplain&view=co
Created attachment 6417 [details] Tentative patch: Keep .data This is a tentative patch to fix the issue by KEEPing .data. Lightly tested with a small program. Johann ld/ PR 13697 * scripttempl/avr.sc (.data): Keep it.
CVSROOT: /cvs/src Module name: src Changes by: nickc@sourceware.org 2012-06-07 16:53:11 Modified files: ld : ChangeLog ld/scripttempl : avr.sc Log message: PR 13697 * scripttempl/avr.sc (.data): Keep it. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/ChangeLog.diff?cvsroot=src&r1=1.2454&r2=1.2455 http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/scripttempl/avr.sc.diff?cvsroot=src&r1=1.12&r2=1.13
Fixed