I want function caller to take a thumb function pointer as an argument:
void fun(void) {}
void caller(void(*f)(void)) {
f();
}
void _start(void) {
caller(fun);
}
When I compile it with
arm-elf-gcc -mthumb -c -fpic test.c
and then link
arm-elf-ld test.o
, linker tries to wrap fun with interwork code and warns about interworking not enabled. But I don't want to enable interwork, because I want it to be thumb-only code. Without -fpic, code compiles and function pointer works correctly.
If want to ask why I have to pass thumb function pointers and provide PIC code, it's because the API which I can't change.
Edit:
Gcc version is 4.7.2. Specifying -march=armv4t -mcpu=arm7tdmi didn't help.
Related
I have an object file compiled using gcc with -ffunction-sections option. I have access to the source file but iam not allowed to modify it.
file.c
void foo(void)
{
bar();
}
void bar(void)
{
abc();
}
What iam trying to achieve is to make all the references to bar take an absolute address(which I'll assign in the linker script) whereas bar will be placed at some other address by the linker.
A possible solution is to rename bar to file_bar without changing the call to bar inside foo(). I tried using objcopy -redefine-syms but it seems to rename even the calls to bar.
Solution provided by busybee solves the problem unless the functions are in the same compilation unit.
foo1.c
#include <stdio.h>
extern void bar1();
void foo1(){
printf("foo1\n");
}
int main(){
printf("main\n");
foo1();
bar1();
}
bar1.c
#include <stdio.h>
void bar1(){
printf("bar1\n");
}
wrapper.c
#include <stdio.h>
void __wrap_foo1(){
printf("wrap_foo1\n");
}
void __wrap_bar1(){
printf("wrap_bar1\n");
}
Now,
$ gcc -c -ffunction-sections foo1.c bar1.c wrapper.c
$ gcc -Wl,--wrap=foo1 -Wl,--wrap=bar1 -o output foo1.o bar1.o wrapper.o
$ ./output
main
foo1
wrap_bar1
All functions to be redirected are in their own compilation unit
The linker has the option "--wrap" that replaces all references to the symbol "xxx" by "__wrap_xxx" and the symbol itself by "__real_xxx". It is used to put a wrapper function as an "interceptor" in between call and function.
But with this option you can do whatever you like with those symbols in your linker script. You just need to define "__wrap_xxx" with a symbol so that the references are resolvable.
Depending on your needs you can also write a dummy function named "__wrap_xxx()" that does not even call "__real_xxx()". Or you can place "__real_xxx" in a vector table, or... whatever you can think of.
All functions to be redirected are non-static ("global"), patching immediate values
I looked through the answers of the other question the OP posted in a comment. This gave me the idea to weaken the symbols in question and to override them with a value by the linker.
This example might give you some insight. I tested in on Linux which has address space layout randomization so all addresses are offsets from a random base. But for the OP's target system it should work as expected.
foo1.c
Because of arbitrary values for the redirected addresses the functions can't be called. But the program can print their addresses.
#include <stdio.h>
void foo1(void) {
}
extern void bar1(void);
int main(void) {
printf("%p\n", main);
printf("%p\n", foo1);
printf("%p\n", bar1);
return 0;
}
bar1.c
void bar1(void) {
}
wrapper.ld
This is the first alternative to give the linker the addresses to be used, an additional linker script. For the second one see below. The standard linker script will be augmented here, there is no need to copy and patch it. Because of the simple structure this is probably the most simple way to provide many redirected addresses which can be easily automated.
foo1 = 0x1000;
bar1 = 0x2000;
Note: This is not C! It is "linker script" syntax which happens to be quite similar.
How I built and tested
This command sequence can be automated and sorted for your liking. Especially the calls of objcopy could be done by some loop over a list.
gcc -c -ffunction-sections foo1.c
objcopy --weaken-symbol=foo1 foo1.o foo2.o
gcc -c -ffunction-sections bar1.c
objcopy --weaken-symbol=bar1 bar1.o bar2.o
gcc foo1.o bar1.o -o original
echo original
./original
gcc foo2.o bar2.o -o weakened
echo weakened
./weakened
gcc foo2.o bar2.o wrapper.ld -o redirected
echo redirected
./redirected
Instead of an additional linker script the symbol definitions can be given on the command line, too. This is the mentioned second alternative.
gcc foo2.o bar2.o -Wl,--defsym=foo1=0x1000 -Wl,--defsym=bar1=0x2000 -o redirected
BTW, the linker understands #file to read all arguments from the file file. So there's "no limit" on the size of the linker command.
All functions to be redirected are non-static ("global"), overwriting with new functions
Instead of providing immediate values you can of course just provide your alternative functions. This works like above but instead of the additional linker script or symbol definitions you write a source file.
wrapper.c
Yes, that's right, the names are equal to the names of the originals! Because we made the symbols of the original functions weak, we'll get no error message from the linker when it overwrites the references with the addresses of the new functions.
void foo1(void) {
}
void bar1(void) {
}
Build the redirected program like this (only new commands shown):
gcc -c -ffunction-sections wrapper.c
gcc foo2.o bar2.o wrapper.o -o redirected
A function to be redirected is static
Well, depending on your target architecture it will probably not be possible. This is because of the relocation entry of the reference. It will be some kind of relative, telling the linker to resolve by an offset into the section of the function instead to resolve by the symbol of the function.
I didn't investigate this further.
What code goes into the final executable when using a library?
As an example, we have two files:
/*main.c*/
int main (int argc, char* argv[]){
fc(1); /*This function is defined in fc.c*/
}
Another file:
/*fc.c*/
int fc(int x){
return fe(x);
}
int fe(int y){
return y + 1;
}
We compile fc.c:
gcc -c fc.c
We then get fc.o.
Now lets build a library named test:
ar rcs libtest.a fc.o
We now have libtest.a.
Now we compile main.c
gcc -c main.c
And we obtain main.o
Let's link our main.o to our libtest.a
gcc -L. main.o -ltest
We get the desired a.out
Checking it's symbols:
nm a.out
In between all the symbols, we find:
080483cc T fc
080483df T fe
Seems good.
BUT!
If our main.c changes for this?
/*main.c*/
int main (int argc, char* argv[]){
fe(1); /*This function is defined in fc.c*/
}
After compiling main.c and linking the new main.o to our library, I will still find a symbol for fc. But I don't need that code.
Questions
-Shouldn't the library "give me" only the code I need in main.c?
-Do the functions need to be in separate modules before being added to the library?
-What if I had 300 functions? Would I need to make 300 modules?
Yes, place each function in a separate module. That way the linker will link in only the items needed.
In short, there are compiler flags to prune unused functions from the final executable code, however they are not enabled by default.
GCC can do this "garbage collection" of unused functions if these flags are added:
-ffunction-sections as a compile-time flag. It instructs the compiler to create a separate section (see object file format) for each function. There's also -fdata-sections flag with similar meaning that works for variables.
-Wl,--gc-sections as a link-time flag. The -Wl part instructs GCC to pass the following options to the linker. --gc-sections means "garbage select sections from which all code is unsed". Since due to the compile-time options each function has got a separate section, it effectively performs function-level pruning.
This question already has answers here:
Are prototypes required for all functions in C89, C90 or C99?
(6 answers)
Closed 7 years ago.
I have a C file (say file1.c) that calls a function
fun1(1,b).
This function fun1(int a,int b) resides in another C file (say file2.c) but its prototype is not included in the header file (say file2.h).
file2.h is included in file1.c.
My question is, if I call fun1(a,b) from file1.c, will it work by passing control to the function definition in file2.c? Or will an exception occur or what will be the expected behavior?
Do I have to give a prototype of fun1(int a, int b) in file2.h for this to work?
A couple things can happen depending on the situation and your compiler:
You get a compilation error. The compiler throws up its arms and refuses to produce an object file.
The compiler treats the function declaration as implied by the call and proceeds to link. It may assume that you know what you're doing in terms of function arguments. Usually it also assumes an int return type. Almost every compiler I've worked with will produce a warning when it does this.
The compiler treats the declaration as implied by the call but fails to link. Like the above, but the linker then notices that the implied function you're trying to call and the one you actually did write are different and dies.
You SHOULD provide a prototype regardless.
Expected behaviour is that your functions will get called, provided the object files are linked together. Any undeclared function, is assumed to be an external function that returns an integer for compile purpose, and an external symbol (to the object file) for purposes of linking. I'll give you concrete example:
foo.c:
void foo(const char *name) {
printf("foo called with %s\n", name);
}
bar.c:
void bar(int a) {
printf("bar called with %d\n", a);
}
main.c:
int main(int argc, char *argv[]) {
foo("Hello");
bar(5);
return 0;
}
Compiling the object files using gcc:
gcc -fno-builtin -ansi -c -o foo.o foo.c
gcc -fno-builtin -ansi -c -o bar.o bar.c
gcc -fno-builtin -ansi -c -o main.o main.c
These should not produce any warnings or errors
Now link them together:
gcc -o progy main.o bar.o foo.o
Note that i used gcc to link the binaries, but that is equivalent of:
ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o progy /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbegin.o main.o foo.o bar.o -lc -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1 -lgcc -lgcc_s /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtend.o /usr/lib64/crtn.o
on my Linux 64-bit platform. (GCC actually runs LD like this to do the linking)
Using your C compiler (in my case gcc) for linking will ensure that linker is called correctly for whatever your build target platform is. If you use an IDE then these steps are all hidden by a nice interface.
I have a question. I was wondering if you could re-compile code with another piece of code. For example (theoretical):
main.c:
#include <stdio.h>
void showme();
int main()
{
showme();
}
void showme()
{
fprintf(stderr, "errtest, show me");
}
Compile this file to main. (So the main is compiled)
After this I want to add a piece of code.
addthis.c:
void test()
{
test();
}
Now I want to use the (compiled) main and re-compile it with addthis.c.
When running it (./mainWithAddthis) should show the print 2 times.
I hope I explained it clear. Anybody an idea?
You need a forward declaration for your void test() like you have one for the void showme(). Compile each .c file with -c (compile only) option:
gcc -c addthis.c -o addthis.o
gcc -c main.c -o main.o
Then link the two object files with:
gcc main.o addthis.o -o main
Then enjoy ./main :-)
Your first code will not compile since there's not definition of test();.
As I understand, you want to take the compiled main and add it with the code generated on addthis.o to create a 2nd application named mainWithAddthis. This is not possible!
You are either confused or trying to do some hardcore trick.
Building an executable is a two step process.
For every source file you specify (in your project/makefile), your compiler will build an object file
For every object file you specify (in your project/makefile), your linker will link them together and make your executable
One way to re-compile would be simply to re-build your entire project. You'd get more or less the same result.
But it sounds like what you want to do is recompile only the source file, addthis.c, then re-link the old version of main.o (the object file compiled for main.c) with the new version of addthis.o. How to do this is completely dependent on the compiler and build system you use.
Also, that solution will only work if you have main.o, addthis.c, and have the exact same compiler binaries/install, and compiler flags used to generate main.o. If this is all on your box, then you're probably okay.
If you only have the files addthis.c and main.exe, then no there is no portable way to do what you want.
You can't do what you are talking about after the fact without some hardcore time with a hex editor.
However, if you plan ahead and build it into your software, you can use dynamic loading to achieve the same effect, which is how a lot of software provides plugin functionality. Check out glib modules for a common way to do this in C.
main.c
void f();
int main()
{
f();
return 0;
}
addon1.c
#include <stdio.h>
void f()
{
printf("I am the ONE.\n");
}
addon2.c
#include <stdio.h>
void f()
{
printf("I am the TWO.\n");
}
Compilation
gcc -c main.c -o main.o
gcc -c addon1.c -o addon1.o
gcc -c addon2.c -o addon2.o
gcc main.o addon1.o -o main1
gcc main.o addon2.o -o main2
You will have ./main1 and ./main2 programs which will print ...ONE. and ...TWO..
I've just organized my code by using headers, but just as I've done this, I got a warning that turned into an error when linking.
I have a code(use of a function that is inside a header) in test.c that is like this:
#include "test1.h"
/* Some code */
main()
{
Testing();
}
And my test1.h header is like this:
void Testing();
void print(int, int, int, const char*);
And at test1.c
void Testing()
{
print(0xF9, 27, 5, "\xC9\\xBB");
}
void print(int colour, int x, int y, const char *string)
{
volatile char *video=(volatile char*)0xB8000 + y*160 + x*2;
while(*string != 0)
{
*video=*string;
string++;
video++;
*video=colour;
video++;
}
}
When I try to compile the code, I got this:
ubuntu#eeepc:~/Development/Test$ gcc -o test.o -c test.c -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs
test.c: In function ‘main’:
test.c:11: warning: implicit declaration of function ‘Testing’
ubuntu#eeepc:~/Development/Test$
At the time it's just a simple warning, but when I try to link it...
ubuntu#eeepc:~/Development/Test$ ld -T linker.ld -o kernel.bin loader.o test.o
test.o: In function main':
test.c:(.text+0xfc): undefined reference toTesting'
What I need to do?
Edit: To reflect the OP's question I have struck out some lines of my answer despite being upvoted...
Why is kernel.c flagged up in the compiler, even though you don't have it mentioned here? Am I missing something...
gcc -o test.o -c test.c -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs
kernel.c: In function ‘main’:
kernel.c:11: warning: implicit declaration of function ‘Testing’
ubuntu#eeepc:~/Development/Test$
maybe you need to do it this way somewhere in your header file as I'm judging you want kernel to access this function:
extern void Testing();
And, take out all your functions and place them in a separate .c file, they should not be in there in the first place... for example:
Testing.c
/* all your functions here */
Testing.h
/* Only global, external variables and function prototypes */
Hope this helps,
Best regards,
Tom.
I can't recreate your problem. This works as expected when I try to compile your code on an Ubuntu machine (Which based on your paste, I assume you're using.)
Are you sure the #include is happening correctly?
Try using -E instead of -c to see what the whole code the compiler is trying to compile looks like.
Somewhat of a shot in the dark here, since my C is a bit rusty, but does C allow you to put function bodies in a header? I don't recall that it does. Try moving the definition of Testing() and print() into a .c file? You could also try compiling as C++ as see if that fixes it, if you don't need/want C.
You included test.h into main.c, while your declarations, according to what your wrote, are in test1.h. Note the 1 in the name.
In addition to that, you are compiling test.c and linking test.o, while in reality the name of your file is test1.c. Again, note the 1 in the name.
Edit: Now you edited the name of the file included into main.c. After the edit it is safe to assert that most of the symptoms you describe are not possble with the current versions of the files. Re-verify what you are doing, post updated disgnostic information and/or post real code.
Still, you compiler and linker lines are referring to old file names.
i donno whats causing this , but i had this problem just now .
try to delete the .h file and put the declarations of the functions on the top of .c file itself .
in this case , delete the test1.h and put the declarations of functions of test1.c in test1.c.
and include test1.c in test.c
you wont get that warning message any more , nor the following linking errors .