I was wondering how this works, creating a library and preloading it so a program can use it instead of the one in the include statement.
here is what I am doing and is not working so far .
//shared.cpp
int rand(){
return 33;
}
//prograndom.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
srand(time(NULL));
int i = 10;
while(i--) printf("%d\n", rand()%100);
return 0;
}
Then in the terminal:
$ gcc -shared -fPIC shared.cpp -o libshared.so
$ gcc prograndom.cpp -o prograndom
$ export LD_PRELOAD=/home/bob/desarrollo/libshared.so
and finally
$ LD_PRELOAD=/home/bob/desarrollo/libshared.so ./prograndom
which doesnt print 33, just random numbers...
Your programs are C programs, but the cpp file extension implies C++, and GCC will interpret it that way.
That's an issue because it means that your function rand (in shared.cpp) will be compiled as a C++ function, with its name mangled to include its type-signature. However, in main you #include <stdlib.h>, which has the effect of declaring:
extern "C" int rand();
and that is the rand that the linker will look for. So your PRELOAD will have no effect.
If you change the name of the file from shared.cpp to shared.c, then it will work as expected.
Other alternatives, of dubious value, are:
Declare rand to be extern "C" in your shared.cpp file. You can then compile it as C++.
Force compilation as C by using the GCC option -x c.
Related
I am trying to wrap the GLIBC math functions including summation, division, multiplication, Cosine, log, and etc. I found a similar post here.
I have created a wrapper script for the log function in which prints something before calculation. Something like this for log function:
#include <dlfcn.h>
#include <stdio.h>
#include <math.h>
static double (*real_log)(double dbl);
double log(double dbl)
{
printf("value is %0.16f\n" , dbl);
real_log = dlsym(RTLD_NEXT, "log");
real_log(dbl);
}
And the test file is something like this:
#include <stdio.h>
#include <math.h>
int main () {
double var;
var = log(2.7);
printf("log is equal to %0.16f\n" , var);
return 0;
}
I have re-compiled the wrapper to create the shared library by this command: gcc -fPIC -shared -o libpreload.so wrapper.c -ldl.
I compiled test file: gcc -fno-builtin-log test.c -o test -lm.
Then I run my test script using: LD_PRELOAD=/path/to/libpreload.so ./test
The output now prints
value is 2.7000000000000002
log is equal to 0.0000000000000000
The log returns zero value while I expect to get the real calculation like this:
value is 2.7000000000000002
log is equal to 0.9932517730102834
I'm so beginner on C programming and also Glibc functionality.
I would appreciate any ideas.
I have three files, test.c, a.h, a.c. test.c call a function declared in a.h, and a.c define the function. But the funcion in a.c are different from a.h in the return value and the parameter. Either case, there is no warning from my gcc and there is some result. Why?
In my test.c
#include "a.h"
#include <stdio.h>
int main(){
int x = a();
printf("%d\n", x);
}
In my a.h
int a();
In my a.c
#include <stdio.h>
void a(int a)
{
printf("%d\n", a);
}
in my terminal:
$ gcc -o test test.c a.c // no warning
$ ./test
1
2
Without the a.h being included in a.c, the compiler doesn't know it's a problem. So you won't get any compile issues at all. Each gets its own .o file and everyone is happy.
The compiler expects a() to return an int so it has the machine code grab the result off the stack (or probably some register).
The compiler expects a() to have a parameter, so it has the machine code grab the parameter off the stack (again, probably a register).
Then the linker comes along and puts them all together. It doesn't know that there's an issue, but it makes the call to a() work.
So you get values that are left over on the register (or stack). And hopefully you're in a protected environment so that you're not getting some other user's information.
I have a main code wich uses some libraries and I been compiling it like this:
gcc importedCFile1.c importedCFile2.c mainCode.c -O3 -lm -Wall -o maincode -lrt
Now I have added CUDA code in mainCode and changed its extension to .cu... So, how can I compile the whole thing?
I tried:
nvcc importedCFile1.c importedCFile2.c mainCode.cu -o maincode
but I got a lot of "undefined reference" to my functions in the imported C files.
To include my C files I am using:
extern "C" {
#include "importedCFile1.h"
#include "importedCFile2.h"
}
And ´importedCFile1.c´ is using some functions and variables declared in ´importedCFile2.c´ and ´mainCode.cu´. Like this:
extern int **se; // Variables from mainCode
extern int *n;
extern int numNodes;
extern int *getVector(int n); // Function from mainCode
extern int iRand(int high); // Function from importedCFile2
This functions are the cause of the undefined references. What should I do?
Also, how do I add the flags I need for the C code, such as -lrt, O3, lm and Wall??
EDIT: You can find a reduced example of the problem here:
https://github.com/mvnarvaezt/cuda/tree/master/minimalExample
If you compile the mainCode.c and importedCFile.c with gcc it works fine. If you compile mainCode.cu and importedCFile.c with nvcc you will get an undefined reference to anExample() (the function in importedCFile.c).
And you comment the header importing importedCFile.c and the call to anExampled() function it would work find.
Your problem is that the C code in importedFile.c is trying to call back C++ functions in mainCode.cu.
In order to be callable from C, C++ functions must have C linkage. Declare getVector() as
extern "C" int *getVector(int n) {
in mainCode.cu, and your example will compile fine.
I want to use the C-coder in Matlab. This translates an m-code to C-code.
I use a simple function that adds 5 numbers.
When the code is generated there are a lot of C- and H-files.
of course you could just pick the code you need and import it in your code, but that's not the point of this exercise, as this will no longer be possible when the matlab-code will get more difficult.
Matlab delivers a main.c file and a .mk file.
/* Include Files */
#include "rt_nonfinite.h"
#include "som.h"
#include "main.h"
#include "som_terminate.h"
#include "som_initialize.h"
//Declare all the functions
int main(int argc, const char * const argv[]){
(void)argc;
(void)argv;
float x1=10;
float x2=20;
float x3=30;
float x4=40;
float x5=50;
float result;
/* Initialize the application.
You do not need to do this more than one time. */
som_initialize();
main_som();
result=som(x1,x2,x3,x4,x5);
printf("%f", result);
som_terminate();
return 0;
}
When I run this on a raspberry-pi with
gcc -o test1 main.c
It gives me undefined references to all the functions...
Any ideas what went wrong?
You have to build it with the generated makefile (the mk file) so it links with the correct Matlab libraries - that's where those functions are defined:
$ make -f test.mk
You also need to compile the other C files along with your main.c. If main.c is in the same directory as the generated code, you should be able to just do:
gcc -o test1 *.c
If the generated code is in another directory, then you can do something like:
gcc -o test1 /path/to/code/*.c -I/path/to/code main.c
I have written a C program, which consists below given three files in same directory
main.c
#include<stdio.h>
#include "test.h"
int main()
{
int b=0;
b = test_add(3,2);
printf("Added: b=%d\n\n",b);
return 0;
}
test.h
int test_add(int a, int b);
test.c
int test_add(int a, int b, int c)
{
return a+b+c;
}
I am compiling the program using below command:
$gcc -Wall -Wextra main.c test.c
It compiles successfully. I can see there is mismatch in number of arguments of calling function and its actual definition. Compiler doesn't give any warning/error for such problem. How can this type of errors be reported by compiler?
This shows one of the oddities of the C standard. It allows entities such as functions to be undefined.
The actual error is that you did not
#include "test.h"
in you test.c file.
That means that the main file only sees the version of the function with three parameters. When it reaches the function call, it implicitly declares the function with two parameters.
When you run it, you get bogus values for b. I am guessing the superuser's password could somehow be in there ;)
If you add the include directive, you get an error at compile time.
What worries me, that there is no warning, not even with -Wall -Wextra -pedantic.