I am trying to use linker symbols to automatically set a version number in my executables, and it seems to work as long as the symbols aren't set to zero...
In my C code:
extern char __VERSION_MAJ;
extern char __VERSION_MIN;
...
printf("Version %u.%u\n", (unsigned) &__VERSION_MAJ, (unsigned) &__VERSION_MIN);
And in my makefile:
LDFLAGS += -Xlinker --defsym=__VERSION_MAJ=1
LDFLAGS += -Xlinker --defsym=__VERSION_MIN=0
Results in the following output when I try to run the executable test:
./test: symbol lookup error: ./test: undefined symbol: __VERSION_MIN
If I change the symbol definition as follows:
LDFLAGS += -Xlinker --defsym=__VERSION_MAJ=1
LDFLAGS += -Xlinker --defsym=__VERSION_MIN=1
Then it works just fine:
Version 1.1
I've read about linker symbols here http://web.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/Linker.pdf and trawled google but haven't spotted anything that says 0 is a disallowed value for custom linker symbols.
Also, if I look at the linker map output it does have __VERSION_MIN:
0x0000000000000001 __VERSION_MAJ = 0x1
0x0000000000000000 __VERSION_MIN = 0x0
So, I'm quite stumped!
I would just use gcc -D__VERSION_MIN=0 instead, but that leads to trickiness and makefile ugliness with using prerequisites to rebuild the application when the version changes (it will be stored in a text file, not hard-coded in the makefile as above.)
I'm compiling and linking with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) for target i686-linux-gnu, if any of that makes a difference.
Executive summary:
Should a --defsym expression that results in 0 be allowed?
What am I doing wrong?
Is there a better/simpler way to achieve this?
If you want to use
gcc -D__VERSION_MIN=0
then you have to remove the definition from your header file
extern char __VERSION_MIN;
The
gcc -D__VERSION_MIN=0
is equivalent to define __VERSION_MIN as a macro in your c code
#define __VERSION_MIN 0
And then you can not define __VERSION_MIN twice in your C code
extern char __VERSION_MIN;
#define __VERSION_MIN 0
This is not allowed
So If you want to use
gcc -D__VERSION_MIN=0
then you have to remove extern char __VERSION_MIN; from your code
Related
Sample code for fmod:
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 0.14527, y = 3.14159;
printf("fmod(x, y) = %.6lf\n", fmod(x, y));
return 0;
}
Compiling:
$ gcc main.c -o main
I get
/tmp/ccztJO01.o: In function `main':
main.c:(.text+0x4d): undefined reference to `fmod'
collect2: ld returned 1 exit status
Then I found this in Google:
$ gcc -lm main.c -o main
Why should I use -lm, what is it exactly? From where I can get more information about gcc in detail?
-lm is simply telling it to link libm, which contains all the floating point math routines, including (no surprise here) fmod.
When I input gcc -lm main.c -o main I still get a linker error. I need to write gcc main.c -lm -o main for it work right. If it's working for you the other way, that's a bit odd. I understand that the linker will find the symbol declared in main.c (i.e. double fmod(double,double)), but only resolve it if it finds its definition later on (i.e. in libm.a).
Long story short, the libraries must be placed (at least once) "to the right of" the place where they are used.
It's not the compiler, but the linker, ld, that is complaining. It cannot find the routine fmod in your program. You have to tell it to link with math library libm with the -l flag.
[Much] more info: GCC, the GNU Compiler Collection.
I have a project set up where I compile and link a shared library (libexample.so) with a linker script that looks like this:
SECTIONS
{
.modules : {
__MODULES_START = .;
KEEP(*(.mod*));
__MODULES_END = .;
}
...
}
I use these in my code to load modules compiled into the library.
extern uint32_t __MODULES_START;
extern uint32_t __MODULES_END;
unsigned int init_mods (void) {
void (*p)(void) = (void *)&__MODULES_START;
...
}
And when I compile the library in my Makefile
build/%.o: %.c
gcc -o $# -c $< -fPIC -g -Os -Iinclude
bin/libexample.so: $(OBJS)
gcc -o $# $^ -shared -fPIC -lc -T$(LINKER_SCRIPT)
It builds and links just fine, and it works when I try to link the library to another project that calls "init_mods".
build/%.o: %.c
gcc -o $# -c $< -fPIE -g -Os -Iinclude -I../libexample/include
bin/untitled-program: $(OBJS)
gcc -o $# $^ -fPIE -lc -lexample -Lbin '-Wl,-rpath,$$ORIGIN'
However, when I run the program where it can find the library, I receive the following linking error:
/bin/untitled-program: error while loading shared libraries: /blah/blah/libexample.so: unexpected PLT reloc type 0x08
When I readelf the shared library, I get the two definitions in my symbol table
Symbol table '.symtab' contains 223 entries:
Num: Value Size Type Bind Vis Ndx Name
...
154: 0000000000000050 0 NOTYPE GLOBAL DEFAULT 2 __MODULE_INIT_END
...
222: 0000000000000028 0 NOTYPE GLOBAL DEFAULT 2 __MODULE_INIT_START
So I'm wondering if my issue has to do with the NOTYPE, but I'm having trouble finding documentation on this.
To explain why I think my issue has to do with the linker script variables, when I run my program with linker debugging on, one of them is the last one to show up.
$ LD_DEBUG=all ./untitled-program
...
23856: symbol=__MODULE_END; lookup in file=./bin/untitled-program [0]
23856: symbol=__MODULE_END; lookup in file=/usr/lib/libc.so.6 [0]
23856: symbol=__MODULE_END; lookup in file=./bin/libexample.so [0]
23856: binding file ./bin/libexample.so [0] to ./bin/libexample.so [0]: normal symbol `__MODULE_END'
...
23856: symbol=__MODULE_START; lookup in file=./bin/untitled-program [0]
23856: symbol=__MODULE_START; lookup in file=/usr/lib/libc.so.6 [0]
23856: symbol=__MODULE_START; lookup in file=./bin/libexample.so [0]
23856: binding file ./bin/libexample.so [0] to ./bin/libexample.so [0]: normal symbol `__MODULE_START'
./bin/untitled-program: error while loading shared libraries: ./bin/libexample.so: unexpected PLT reloc type 0x08
But, that's the weird thing because it's able to bind one of the other linker script variables before it fails.
I have been working on this issue for too long, so I'm having trouble seeing the bigger picture. Maybe I'm thinking about this wrong and the issue is with another symbol. Any help or guidance would be appreciated!
Just mark your module init function with the GCC constructor function attribute (it has nothing to do with C++ constructors!), and it will include its address in the init_array section; the dynamic linker will then execute it before main(), or immediately when a dynamic library is loaded.
static void my_mod_init(void) __attribute__((constructor));
static void my_mod_init(void)
{
/* Initialize this module, hook up to the library */
}
This has the benefit that because the dynamic linker executes these automatically, these are also run when you load a dynamic library with such modules with e.g. dlopen(path, RTLD_NOW | RTLD_GLOBAL).
If you want to replicate the functionality under your own control,
then have each module declare an array of the init function addresses to a special section, say "mod_inits". Define some helper macros:
#define MERGE2_(a, b) a ## b
#define MERGE2(a, b) MERGE2_(a, b)
#define MODULE_INIT(func) \
static void *MERGE2(_init_, __LINE__) \
__attribute__((section ("mod_inits"), used)) = &func
Then, in your module source files, make some functions:
static void hello(void) {
puts("Hello!");
}
MODULE_INIT(hello);
static void also(void) {
puts("Also hello!");
}
MODULE_INIT(also);
In the library file, to scan and execute all functions in any compilation units marked with MODULE_INIT():
extern void *__start_mod_inits;
extern void *__stop_mod_inits;
void run_mod_inits(void)
{
for (void **ptr = &__start_mod_inits; ptr < &__stop_mod_inits; ptr++) {
void (*func)(void) = *ptr;
func(); /* Could pass parameters, if they have the same prototype */
}
}
You do not need any linker file for this, as gcc provides the __start_ and __stop_ symbols for all sections whose names are valid C identifiers.
I have a function in my C code that is being called implicitly, and getting dumped by the linker. how can I prevent this phenomena?
I'm compiling using gcc and the linker flag -gc-sections, and I don't want to exclude the whole file from the flag. I tried using attributes: "used" and "externally_visible" and neither has worked.
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
on map file I can see that the function has compiled but didn't linked. am I using it wrong? is there any other way to do it?
You are misunderstanding the used attribute
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced...
i.e the compiler must emit the function definition even the function appears
to be unreferenced. The compiler will never conclude that a function is unreferenced
if it has external linkage. So in this program:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
compiled with:
$ gcc -c -O1 main1.c
No definition of foo is emitted at all:
$ nm main1.o
0000000000000000 T main
because foo is not referenced in the translation unit, is not external,
and so may be optimised out.
But in this program:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used)) compels the compiler to emit the local definition:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
But this does nothing to inhibit the linker from discarding a section
in which foo is defined, in the presence of -gc-sections, even if foo is external, if that section is unused:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
Compile with function-sections:
$ gcc -c -ffunction-sections -O1 main3.c
The global definition of foo is in the object file:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
But after linking:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo is not defined in the program:
$ nm a.out | grep foo; echo Done
Done
And the function-section defining foo was discarded:
mapfile
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
As per Eric Postpischil's comment, to force the linker to retain
an apparently unused function-section you must tell it to assume that the program
references the unused function, with linker option {-u|--undefined} foo:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
If you don't tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo is not defined in the program. If you do tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
it is defined. There's no use for attribute used.
Apart from -u already mentioned here are two other ways to keep the symbol using GCC.
Create a reference to it without calling it
This approach does not require messing with linker scripts, which means it will work for hosted programs and libraries using the operating system's default linker script.
However it varies with compiler optimization settings and may not be very portable.
For example, in GCC 7.3.1 with LD 2.31.1, you can keep a function without actually calling it, by calling another function on its address, or branching on a pointer to its address.
bool function_exists(void *address) {
return (address != NULL);
}
// Somewhere reachable from main
assert(function_exists(foo));
assert(foo != NULL); // Won't work, GCC optimises out the constant expression
assert(&foo != NULL); // works on GCC 7.3.1 but not GCC 10.2.1
Another way is to create a struct containing function pointers, then you can group them all together and just check the address of the struct. I use this a lot for interrupt handlers.
Modify the linker script to keep the section
If you are developing a hosted program or a library, then it's pretty tricky to change the linker script.
Even if you do, its not very portable, for example gcc on OSX does not actually use the GNU linker since OSX uses the Mach-O format instead of ELF.
Your code already shows a custom section though, so it's possible you are working on an embedded system and can easily modify the linker script.
SECTIONS {
// ...
.mySec {
KEEP(*(.mySec));
}
}
So I'm trying trying to use a function defined in another C (file1.c) file in my file (file2.c). I'm including the header of file1 (file1.h) in order to do this.
However, I keep getting the following error whenever I try to compile my file using gcc:
Undefined symbols for architecture x86_64:
"_init_filenames", referenced from:
_run_worker in cc8hoqCM.o
"_read_list", referenced from:
_run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64
I've been told I need to "link the object files together" in order to use the functions from file1 in file2, but I have no clue what that means :(
I assume you are using gcc, to simply link object files do:
$ gcc -o output file1.o file2.o
To get the object-files simply compile using
$ gcc -c file1.c
this yields file1.o and so on.
If you want to link your files to an executable do
$ gcc -o output file1.c file2.c
The existing answers already cover the "how", but I just wanted to elaborate on the "what" and "why" for others who might be wondering.
What a compiler (gcc) does: The term "compile" is a bit of an overloaded term because it is used at a high-level to mean "convert source code to a program", but more technically means to "convert source code to object code". A compiler like gcc actually performs two related, but arguably distinct functions to turn your source code into a program: compiling (as in the latter definition of turning source to object code) and linking (the process of combining the necessary object code files together into one complete executable).
The original error that you saw is technically a "linking error", and is thrown by "ld", the linker. Unlike (strict) compile-time errors, there is no reference to source code lines, as the linker is already in object space.
By default, when gcc is given source code as input, it attempts to compile each and then link them all together. As noted in the other responses, it's possible to use flags to instruct gcc to just compile first, then use the object files later to link in a separate step. This two-step process may seem unnecessary (and probably is for very small programs) but it is very important when managing a very large program, where compiling the entire project each time you make a small change would waste a considerable amount of time.
You could compile and link in one command:
gcc file1.c file2.c -o myprogram
And run with:
./myprogram
But to answer the question as asked, simply pass the object files to gcc:
gcc file1.o file2.o -o myprogram
Add foo1.c , foo2.c , foo3.c and makefile in one folder
the type make in bash
if you do not want to use the makefile, you can run the command
gcc -c foo1.c foo2.c foo3.c
then
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h>
#include <string.h>
void funk1();
void funk1() {
printf ("\nfunk1\n");
}
int main(void) {
char *arg2;
size_t nbytes = 100;
while ( 1 ) {
printf ("\nargv2 = %s\n" , arg2);
printf ("\n:> ");
getline (&arg2 , &nbytes , stdin);
if( strcmp (arg2 , "1\n") == 0 ) {
funk1 ();
} else if( strcmp (arg2 , "2\n") == 0 ) {
funk2 ();
} else if( strcmp (arg2 , "3\n") == 0 ) {
funk3 ();
} else if( strcmp (arg2 , "4\n") == 0 ) {
funk4 ();
} else {
funk5 ();
}
}
}
foo2.c
#include <stdio.h>
void funk2(){
printf("\nfunk2\n");
}
void funk3(){
printf("\nfunk3\n");
}
foo3.c
#include <stdio.h>
void funk4(){
printf("\nfunk4\n");
}
void funk5(){
printf("\nfunk5\n");
}
makefile
outputTest: foo1.o foo2.o foo3.o
gcc -o output foo1.o foo2.o foo3.o
make removeO
outputTest.o: foo1.c foo2.c foo3.c
gcc -c foo1.c foo2.c foo3.c
clean:
rm -f *.o output
removeO:
rm -f *.o
Since there's no mention of how to compile a .c file together with a bunch of .o files, and this comment asks for it:
where's the main.c in this answer? :/ if file1.c is the main, how do
you link it with other already compiled .o files? – Tom Brito Oct 12
'14 at 19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
Here, main.c is the C file with the main() function and the object files (*.o) are precompiled. GCC knows how to handle these together, and invokes the linker accordingly and results in a final executable, which in our case is x0rbin.
You will be able to use functions not defined in the main.c but using an extern reference to functions defined in the object files (*.o).
You can also link with .obj or other extensions if the object files have the correct format (such as COFF).
Sample code for fmod:
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 0.14527, y = 3.14159;
printf("fmod(x, y) = %.6lf\n", fmod(x, y));
return 0;
}
Compiling:
$ gcc main.c -o main
I get
/tmp/ccztJO01.o: In function `main':
main.c:(.text+0x4d): undefined reference to `fmod'
collect2: ld returned 1 exit status
Then I found this in Google:
$ gcc -lm main.c -o main
Why should I use -lm, what is it exactly? From where I can get more information about gcc in detail?
-lm is simply telling it to link libm, which contains all the floating point math routines, including (no surprise here) fmod.
When I input gcc -lm main.c -o main I still get a linker error. I need to write gcc main.c -lm -o main for it work right. If it's working for you the other way, that's a bit odd. I understand that the linker will find the symbol declared in main.c (i.e. double fmod(double,double)), but only resolve it if it finds its definition later on (i.e. in libm.a).
Long story short, the libraries must be placed (at least once) "to the right of" the place where they are used.
It's not the compiler, but the linker, ld, that is complaining. It cannot find the routine fmod in your program. You have to tell it to link with math library libm with the -l flag.
[Much] more info: GCC, the GNU Compiler Collection.