I had to rephrase this question and its title completely because my initial analysis turned out to be wrong (thanks for all the hints and suggestions!). The old title of the question was:
GCC -O3 messes up the binary and produces data garbage
As it turns out it has nothing to do with the optimization levels and I'm not sure the data is garbage either.
Anyway, these are the relevant snippets of the SDK code I'm using. I can't post the whole SDK code here obviously.
First I have two constants:
static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl};
and
static const usb_device_class_map_t s_UsbDeviceClassInterfaceMap[] = {
{USB_DeviceCdcAcmInit, USB_DeviceCdcAcmDeinit, USB_DeviceCdcAcmEvent, kUSB_DeviceClassTypeCdc},
{(usb_device_class_init_call_t)NULL, (usb_device_class_deinit_call_t)NULL, (usb_device_class_event_callback_t)NULL,
(usb_device_class_type_t)0},
};
in my main.c, seemingly unrelated, there's this snippet:
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
Now, if I compile with -O3
the application crashes when accessing s_UsbDeviceEhciInterface
, with -O0
the application crashes when accessing s_UsbDeviceClassInterfaceMap
.
Both times the third code snippet seems to be involved.
With -O3
the data inside the disassembly looks like this for s_UsbDeviceEhciInterface
:
000066b4 <s_UsbDeviceEhciInterface>:
66b4: 00000479 0000145d 00001499 000014a5 y...]...........
66c4: 000014ad 00001685 4253556b 7665445f ........kUSB_Dev
66d4: 43656369 76456364 53746e65 6f437465 iceCdcEventSetCo
66e4: 6f72746e 6e694c6c 61745365 65206574 ntrolLineState e
66f4: 726f7272 00000021 rror!...
while s_UsbDeviceClassInterfaceMap
doesn't seem to exist at all.
With -O0
the data inside the disassembly looks like this for s_UsbDeviceEhciInterface
:
00009164 <s_UsbDeviceEhciInterface>:
9164: 000018b5 00001999 00006ebb 00006eed .........n...n..
9174: 00001a21 00001c35 !...5...
and for s_UsbDeviceClassInterfaceMap
:
0000917c <s_UsbDeviceClassInterfaceMap>:
917c: 00007eb1 00007f49 00002985 00000002 .~..I....)......
...
919c: 00007071 4253556b 7665445f 43656369 qp..kUSB_DeviceC
91ac: 76456364 53746e65 6f437465 6f72746e dcEventSetContro
91bc: 6e694c6c 61745365 65206574 726f7272 lLineState error
91cc: ffff0021 !...
In the map file we see both times the main.c data following the const - as the disassembly would suggest. For -O3
:
.rodata.s_UsbDeviceEhciInterface
0x00000000000066b4 0x18 ./usb/device/source/usb_device_dci.o
.rodata.USB_DeviceCdcVcomCallback.str1.4
0x00000000000066cc 0x30 ./source/main.o
and for -O0
:
.rodata.s_UsbDeviceEhciInterface
0x0000000000009164 0x18 ./usb/device/source/usb_device_dci.o
.rodata.s_UsbDeviceClassInterfaceMap
0x000000000000917c 0x20 ./usb/device/class/usb_device_class.o
.rodata 0x000000000000919c 0x32 ./source/main.o
To recap: The application always crashes when accessing the constant preceding the constant string from the main.c
I tried cranking up the compiler warnings and I only get some unused parameters within the SDK code.
For completeness' sake here's the original question:
OUTDATED (see above)
So, I have this code:
static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl};
and somewhere else, in another file, seemingly unrelated, I have this snippet:
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
Now, access to the s_UsbDeviceEhciInterface
crashes the application. Looking into the disassembly file I find the following:
00006674 <s_UsbDeviceEhciInterface>:
6674: 00000479 0000145d 00001499 000014a5 y...]...........
6684: 000014ad 00001685 4253556b 7665445f ........kUSB_Dev
6694: 43656369 76456364 53746e65 6f437465 iceCdcEventSetCo
66a4: 6f72746e 6e694c6c 61745365 65206574 ntrolLineState e
66b4: 726f7272 00000021 rror!...
which seems to be a combination of the two unrelated code parts!
If I remove the second code snippet accessing s_UsbDeviceEhciInterface
works again. The disassembly then looks like this, which makes much more sense:
000042b4 <s_UsbDeviceEhciInterface>:
42b4: 00000479 00000b0d 00000b49 00000b55 y.......I...U...
42c4: 00000b5d 00000d35 ]...5...
This only happens when I use -O3
optimization. When I switch to -O0
everything seems fine again.
How does this happen and is there a way to prevent this while still using -O3
?
EDIT: I just realized it happens with -O0
as well, just in another part of the data. Maybe I messed up my linker script?