__attribute((used))__ malfunction
Hi,
I'm having a problem with CrossWorks 2.0.7 for ARM where variables defined with __attribute__((used)) are being compiled out. For example:
struct _FOO {
uint8_t val;
const uint8_t *string;
};
#define TEST_FOO(name, value) \
const struct _FOO name __attribute__ ((section (".io_dev"),used)) = { \
.val = value, \
.string = #name \
};
TEST_FOO(foo, 55);
int main(void)
{
return 0;
}
will produce the following excerpt from the .map file:
0x0000011c __io_dev_load_start__ = (__vectors_end__ ALIGN 0x4)
.io_dev 0x0000011c 0x0
0x0000011c __io_dev_start__ = .
*(.io_dev .io_dev.*)
0x0000011c __io_dev_end__ = (__io_dev_start__ + SIZEOF (.io_dev))
0x00000001 . = ASSERT (((__io_dev_end__ >= __FLASH_segment_start__) && (__io_dev_end__ <= (__FLASH_segment_start__ + 0x40000))), error: .io_dev is too large to fit in FLASH memory segment)
0x0000011c __init_load_start__ = (__io_dev_end__ ALIGN 0x4)
however, if i write a different main function as shown below:
int main(void)
{
assert(foo.string != NULL);
return 0;
}
the .map file looks like this:
0x0000011c __io_dev_load_start__ = (__vectors_end__ ALIGN 0x4)
.io_dev 0x0000011c 0x8
0x0000011c __io_dev_start__ = .
*(.io_dev .io_dev.*)
.io_dev 0x0000011c 0x8 THUMB Debug/main.o
0x0000011c foo
0x00000124 __io_dev_end__ = (__io_dev_start__ + SIZEOF (.io_dev))
0x00000001 . = ASSERT (((__io_dev_end__ >= __FLASH_segment_start__) && (__io_dev_end__ <= (__FLASH_segment_start__ + 0x40000))), error: .io_dev is too large to fit in FLASH memory segment)
It's my understanding the the __attribute__((used)) should keep the variable 'foo' around even if the linker decides it is not being used. Is this incorrect? If so, how can I ensure that 'foo' is not compiled out by the linker?
Regards,
Scott
-
That doesn't seem to do anything for me. I would also have to know the symbol name for every object created via the TEST_FOO(...) macro which isn't really an option (I can only imagine how long it would take while debugging before realizing I forgot to include one of the symbol names...).
Thanks for the idea!
--scott
-
They will all be used, that's the point of what I'm trying to make and have the linker understand. They are just never accessed directly (referred to by their symbol name). The basic idea is that the macro can be used to create a table in flash that can then be accessed via pointer.
Example:
#include <cross_studio_io.h>
extern struct _FOO *__io_dev_start__;
extern struct _FOO *__io_dev_end__;
TEST_FOO(foo1, 55);
TEST_FOO(foo2, 55);
void print_foo(void) {
struct _FOO *pFoo = &__io_dev_start__;
const struct _FOO *pEnd = &__io_dev_end__;
while(pFoo != pEnd) {
debug_printf("%s\n", pFoo->string);
pFoo += 1;
}
}
So the linker never see's 'foo1' or 'foo2' access directly and compiles them away even though they are, in fact, being used. It was my understanding that the __attribute__((used)) was intended to prevent this exact scenario from happening.
On a side note, with IAR Embedded Workbench (the only other embedded compiler I have used) you achieve this by adding the __root attribute to the variable. This is the functionality I'm trying to duplicate, not sure if this helps explain what I'm doing or not though...
Thanks!
--scott
-
We have a need to keep some unreferenced symbols around, but we do it with the "Keep Symbols" Linker Option (there's only 2 and the names never change).
I've never used the 'used' attribute, but my reading of the Help suggests it should work as you expect.
I just had a play with the 'KEEP()' function in the input section definition in the Section Placement file. When used AS WELL AS the 'used' attribute, this seems to do what you need (in my little test project anyway).
So try changing the definition of your .io_dev segment in the Section Placement file to something like:
<ProgramSection alignment="4" load="No" inputsections="KEEP (*(.io_dev .io_dev.*))" name=".io_dev"/>
My little test project is using optimisation level 1, and has the "Enable Unused Symbol Removal" Build option turned on. Is that the same as yours?
Good Luck!
Wolf
-
Thanks for your post, Wolfgang (btw I remember you from my days at Cubic).
I was struggling to implement a CRP-word in flash (code read protection) on an LPC2136, and your suggestion worked for me.
I used this, in main.c :
static const uint32_t crp __attribute__ ((section(".code_protect"),used)) = 0x87654321;
And this line in my section placement file :
<ProgramSection start="0x1FC" size="4" load="Yes" inputsections="KEEP(*(.code_protect .code_protect.*))" name=".code_protect"/>
All my attempts before this would reserve the section's space, but would not leave the 0x87654321 value in the flash image.
This info should go in a FAQ or a "How do I?" post, to prevent future suffering :-)
-
> This info should go in a FAQ or a "How do I?" post, to prevent future suffering :-)
It is, see http://rowley.zendesk.com/entries/61612-code-read-protection-lpc2000
-
Thanks Jon, I did miss that (although "Troubleshooting" seems an odd place to put it).
I guess I was searching too generally, I was looking for a way to force specific data to be located at a specific FLASH address, which could be useful for many things - data sharing between app and a bootloader, for example.
Always good to have another tool in the toolbox.
-
I've stumbled over this a while ago too. attribute ((used)) is not honored as expected. My way to prevent removal was to set 'Enable Unused Symbol Removal' to No for this specific file. Anyway I consider this is a bug. Or I'm totally misinterpreting the attribute ((used)) description.
-
I also feel that not supporting the used attribute is a bug, since it is described in the CrossWorks help system: "Specifying Attributes of Variables". When I try the following declaration:
uint32_t test __attribute__ ((__used)) = 0xDEADBEEF;
I get a compiler warning:
warning: '__used' attribute directive ignored [-Wattributes]
I am using the "KEEP" thing in my section placement file, but find it a bit clunky for a lot of situations.
-
__attribute__((__used)) is not correct, it should be __attribute__((used)), which is accepted and is not warned.
I do not believe there to be a bug here because GCC documents what it does:
http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
This says that the compiler must emit the variable into the object file -- it does not indicate that the linker needs to keep the variable also.
Please sign in to leave a comment.
Comments
15 comments