Created attachment 7426 [details] archive of small program reproducing alignment issue A program that has an const char array initialized to {1, 2, 3, 4} sees the data as {0, 1, 2, 3} after linking. It is thought that the linker must be padding with zeros without fixing the symbol offset, or something like that. Several things have to be true for this to happen. It's very strange: * The program is cross-compiled for Cortex-M3. Native x86 programs don't have this issue. * The program needs to be optimized for size, -Os. The data file, too! * Specify -fdata-sections. Attached is an archive with four very small files: dl.c contains the array initialization. One 4-byte array, one long. dlm.c contains a main program just to reference the data. mod.ld is a linker script. Makefile. Do make clean debug to build, and then display dlarray with gdb. It'll show up as starting with 0 instead of 1. Like this: $ make clean debug rm -f dl *.o arm-none-eabi-gcc -mthumb -mcpu=cortex-m3 -mlittle-endian -g -Os -fdata-sections -c -o dlm.o dlm.c arm-none-eabi-gcc -mthumb -mcpu=cortex-m3 -mlittle-endian -g -Os -fdata-sections -c -o dl.o dl.c arm-none-eabi-gcc --version arm-none-eabi-gcc (GCC) 4.6.1 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. arm-none-eabi-ld --version GNU ld (GNU Binutils) 2.21.1 Copyright 2011 Free Software Foundation, Inc. This program is free software; you may redistribute it under the terms of the GNU General Public License version 3 or (at your option) a later version. This program has absolutely no warranty. arm-none-eabi-gcc -g --static -Wl,-static -Wl,--cref -nostartfiles -Wl,-T mod.ld -o dl dlm.o dl.o Cross Reference Table Symbol File _start dlm.o check dlm.o dlarray dl.o dlm.o dlarray_size dl.o main dlm.o arm-none-eabi-gdb dl GNU gdb (GDB) 7.3.1 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-eabi". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... /home/jre/.gdbinit:2: Error in sourced command file: No symbol table is loaded. Use the "file" command. Reading symbols from /home/jre/x/reloc/dl...done. (gdb) x/4bu dlarray 0x8020056 <dlarray>: 0 1 2 3 If I change any of the essential elements of this, the array is correctly shown by gdb as: (gdb) x/4bu dlarray 0x8020088 <dlarray>: 1 2 3 4 I know I can work around this one instance in several ways, but I'm worried that -Os could cause similar but hard-to-diagnose problems throughout our large program if the root cause isn't known.
Also tried this with binutils 2.24 and had the same result.
Hi Joe, I tried to reproduce this problem using the mainline versions of gcc, gdb and the binutils, but this failed. (Ie the array contained the correct values). Please could you upload the dl.o and dlm.o object files and the broken dl executable so that I can have a look at them ? Cheers Nick
Created attachment 7433 [details] archive of program with objects and executable
Thank you very much for looking at this issue! I attached a new .tgz with the objects.
This does not look like a linker problem. dl_array is linked at 0x8020057. The symbol and debug info reflect this fact. Now, examining dl_array under gdb looks at 0x8020056. This is wrong, so perhaps this is a gdb bug, triggered by you putting .rodata into .text, an executable section. Recall that arm uses the low bit of executable symbol addresses as a flag to mark thumb code.
Alan, thanks very much for explaining what I'm seeing in gdb. This isn't the first time I've been confused or misled by way ARM uses the low-order bit of the PC. I was using gdb here to see the layout of the program without actually downloading it but I'll look at it with objdump instead now. Maybe my problem can be avoided with a better linker script. I believed I was really getting the wrong data from the array in the program, not just from gdb, so let me re-investigate that. It seems unlikely at this point that this is due to a ld problem.
After further investigation, my original problem is not linker-related or compiler-related, so this can be closed. Thanks to those who looked into this issue.
Not a bug.