Consider the following code:
#define VER __attribute__((section(".version")))
const uint8_t VER major=0x01;
const uint8_t VER minor=0x03;
const uint8_t VER patch=0x0a;
const uint8_t VER build=0x00;
When compiled with avr-gcc 4.3 all the variables are in order of declaration in output hex file.
When compiled with avr-gcc 4.7 all the variables are in reverse order in output hex file.
Is there any compiler/linker option to unify this behavior?
When compiled with avr-gcc 4.3 all the variables are in order of declaration in output hex file.
When compiled with avr-gcc 4.7 all the variables are in reverse order in output hex file.
There is no specified order in which objects are placed into input sections, so Binutils internals — for example how sections and objects are represented internally — might affect their ordering.
Is there any compiler/linker option to unify this behavior?
There are several ways:
You can advise in the linker description file, that objects are sorted according to their name or their alignment, see SORT_BY_NAME and SORT_BY_ALIGNMENT in the Binutils documentation.
Similar can be achieved during link by means of option -Wl,--sort-sections,alignment resp. with parameter name.
You can add respective section to the linker script, like
*(.version.major)
*(.version.minor)
*(.version.patch)
*(.version.build)
KEEP(*(.version*))
which has the additional benefit that it's no more orphan sections.
Do it on C/C++ level, like for example by putting things into a composite:
typedef struct
{
uint8_t major, minor, patch, built;
} version_t
__attribute__((__used__, __section__(".version")))
const version_t version = { 0x1, 0x3, 0xa, 0x0 };
Related
I'm using GCC and writing embedded software for STM32.
How do I read a section that is added with --add-section?
I want to add a section into an elf and inside my program assign a pointer to point to data of this section.
For example:
extern char * ptr_to_my_section = &my_array;
Then I will compile a file my_data.cpp and inject it into a specific section my_section.
my_data.cpp
char my_array[] = "This is the custom data";
And finally I'll create the binary executable.
Then I will compile a file my_data.cpp and inject it into a specific section my_section.
You don't need to use objcopy --add-section for this. You can simply ask GCC to put your array into my_section using __attribute__((section("my_section"))).
To find the start of this section, you can use {__start,__end} symbols which the linker "magically" adds for you:
const char *ptr_to_my_section = &__start_my_section;
const char *end_my_section = &__stop_my_section;
Could anyone please point me out what is the limitation to the alignment value which makes the creation of multiple segment for a section.
With The test case mentioned below:
#include <stdio.h>
#define SIZE (1 << 11)
int Buffer[SIZE] __attribute__ ((aligned (SIZE * sizeof(int)))) ;
int main (int argc, char * argv[])
{
printf("Test\n");
return 0;
}
And here if i change the macro as:
#define SIZE (1 << 11) to #define SIZE (1 << 12)
Without the above changes we see only two loadable segment while with the above changes we observed three loadable segment. As the alignment of BSS changes from 8K to 16K for GCC 4.8.1 which creates three loadable segments.
So can anyone please tell me what changes need to be done in linker script to make creation of only one loadable segment for data.
There are two ways of creating a linker script:
1. Under ld/emulparam directory there are shell script which creates linker script.
2. While other part of linker script came from the actual source.
Now in the source part there depends which linker you are using ie. GNU linker or gold linker.
GNU Linker script is build based on:
Under directory ~/binutils-2013.11/ld/emulparams/, there are different architecture specifics shell script based on different ELF type and platform like for i386/Vxworks
elf_i386_vxworks.sh
While still the rest of generic contains in the script came from the ld/elf sources.
While about segment creation then please look into procedure **bfd_boolean
_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)**
under source "bfd/elf.c"
Take this sample code:
#include <string.h>
#define STRcommaLEN(str) (str), (sizeof(str)-1)
int main() {
const char * b = "string2";
const char * c = "string3";
strncmp(b, STRcommaLEN(c));
}
If you don't use optimizations in GCC, all is fine, but if you add -O1 and above, as in gcc -E -std=gnu99 -Wall -Wextra -c -I/usr/local/include -O1 sample.c, strncmp becomes a macro, and in preprocessing stage STRcommaLen is not expanded. In fact in resulting "code" strncmp's arguments are completely stripped.
I know if I add #define NEWstrncmp(a, b) strncmp (a, b) and use it instead, the problem goes away. However, mapping your own functions to every standard function that may become a macro doesn't seem like a great solution.
I tried finding the specific optimization that is responsible for it and failed. In fact if I replace -O1 with all the flags that it enables according to man gcc, the problem goes away. My conclusion is that -O1 adds some optimizations that are not controlled by flags and this is one of them.
How would you deal with this issue in a generic way? There may be some macro magic I am not familiar with or compiler flags I haven't looked at? We have many macros and a substantial code base - this code is just written to demonstrate one example.
Btw, GCC version/platform is gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5).
Thanks,
Alen
You correctly noted that
in preprocessing stage STRcommaLen is not expanded
- more precisely, not before the strncmp macro gets expanded. This inevitably leads to an error you probably overlooked or forgot to mention:
sample.c:7:30: error: macro "strncmp" requires 3 arguments, but only 2 given
Your conclusion
that -O1 adds some optimizations that are not controlled by flags and
this is one of them
is also right - this is controlled by the macro __OPTIMIZE__ which apparently gets set by -O1.
If I'd do something like that (which I probably wouldn't, in respect of the pitfall you demonstrated by using sizeof a char *), I'd still choose
mapping your own functions to every standard function that may become
a macro
- but rather like
#include <string.h>
#define STRNCMP(s1, s2) strncmp(s1, s2, sizeof(s2)-1)
int main()
{
const char b[] = "string2";
const char c[] = "string3";
STRNCMP(b, c);
}
I have a project that requires a bunch of graphic files in the executable. Since there is no file system at the target I cant just use the fopen function. One way would converting the file content to a C source code that contains the variable definition like this
unsigned char file1_content[] = {
0x01, 0x02, ...
};
It's cumbersome to build such files even with a converter tool.
Is there any way to add binary files to the rdata section while specifying a variable name for each file? I think about using the linker script for this but didn't find a way.
It's not particularly cumbersome with a tool, and that's the classic solution. Search for "bin2c" to find some.
You simply need to include these "asset-building" steps in your build process, i.e. call the tool from the Makefile. This also means that the tool is only run if the source data has changed, which is nice.
At least the GNU linker (LD) seems capable of placing files in the sections of the output file (see the Section Placement documentation, like so:
.data : { afile.o bfile.o cfile.o }
But this sounds quite cumbersome, and it needs you to think about the sections of your executable file which often a bit too low-level. Also, it seems to require the input(s) to be object files, which kind of makes the problem circular since a generic binary asset isn't a linker-compatible object file.
I would recommend going with the bin2c approach.
You may use linker option --format along with -Wl, to pass it to linker, like:
gcc -Wl,--format=binary -Wl,myfile.bin -Wl,--format=default
Last setting format to default allows you to switch linker back to standard input format.
You may access your binary resources from sources via simple _binary_myfile_bin_start assembler symbol (for myfile.bin, for xxx.yyy it will be _binary_xxx_yyy_start and _binary_xxx_yyy_end) like:
extern uint8_t data[] asm("_binary_myfile_bin_start");
And next use data. It is much better then do objcopy by yourself, or use resource hacking.
UPD: Expanding with a little example -- main outputs first four bytes of its own object file:
#include "stdio.h"
#include "stdint.h"
extern uint8_t data[] asm("_binary_main_o_start");
int
main(void)
{
fprintf(stdout, "0x%x, 0x%x, 0x%x, 0x%x\n", data[0], data[1], data[2], data[3]);
return 0;
}
Now compile an run:
$ gcc -o main.o -c main.c
$ gcc -o main main.o -Wl,--format=binary -Wl,main.o -Wl,--format=default
$ ./main
0x7f, 0x45, 0x4c, 0x46
I have some C++0x code. I was able to reproduce it below. The code below works fine without -std=c++0x however i need it for my real code.
How do i include strdup in C++0x? with gcc 4.5.2
note i am using mingw. i tried including cstdlib, cstring, string.h and tried using std::. No luck.
>g++ -std=c++0x a.cpp
a.cpp: In function 'int main()':
a.cpp:4:11: error: 'strdup' was not declared in this scope
code:
#include <string.h>
int main()
{
strdup("");
return 0;
}
-std=gnu++0x (instead of -std=c++0x) does the trick for me; -D_GNU_SOURCE didn't work (I tried with a cross-compiler, but perhaps it works with other kinds of g++).
It appears that the default (no -std=... passed) is "GNU C++" and not "strict standard C++", so the flag for "don't change anything except for upgrading to C++11" is -std=gnu++0x, not -std=c++0x; the latter means "upgrade to C++11 and be stricter than by default".
strdup may not be included in the library you are linking against (you mentioned mingw). I'm not sure if it's in c++0x or not; I know it's not in earlier versions of C/C++ standards.
It's a very simple function, and you could just include it in your program (though it's not legal to call it simply "strdup" since all names beginning with "str" and a lowercase letter are reserved for implementation extensions.)
char *my_strdup(const char *str) {
size_t len = strlen(str);
char *x = (char *)malloc(len+1); /* 1 for the null terminator */
if(!x) return NULL; /* malloc could not allocate memory */
memcpy(x,str,len+1); /* copy the string into the new buffer */
return x;
}
This page explains that strdup is conforming, among others, to the POSIX and BSD standards, and that GNU extensions implement it. Maybe if you compile your code with "-D_GNU_SOURCE" it works?
EDIT: just to expand a bit, you probably do not need anything else than including cstring on a POSIX system. But you are using GCC on Windows, which is not POSIX, so you need the extra definition to enable strdup.
add this preprocessor "_CRT_NONSTDC_NO_DEPRECATE" to Project Properties->C/C++ Build->GCC C++ Compiler->Preprocessor->Tool Settings
Don't forget to check Preprocessor Only(-E)
This worked for me on windows mingw32.