I am trying to intercept libpthred( POSIX ) function calls using LD_PRELOAD technique. First I tried to create my own shared library having the same functin names as in the pthread library. Here is an example of my own created pthread_create function which first gets the address of original pthread_create function in the pthread library, then it calls the original function in the pthread library using the function pointer.
#include <stdio.h>
#include <dlfcn.h>
#include <pthread.h>
int pthread_create (pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void*), void *arg )
{
int return_value;
static int (*fptr) () = 0;
printf( "\n this is the test of LD_PRELOAD" );
char *lError = dlerror();
if( fptr == 0 )
{
fptr = ( int (*) () ) dlsym( RTLD_NEXT, "pthread_create" );
if( fptr == 0 )
{
(void) printf( "Error dlopen: %s", dlerror() );
return 0;
}
}
return (return_value);
}
I tried to compile it in this way:
g++ -fPIC -g -rdynamic -c -Wall ldtest.C -lrt -lpthread -ldl
But its giving the following error
ldtest.C:26: error: too many arguments to function
Line 26 is this line in the program.
return_value = (*fptr)( thread, attr, start_routine, arg );
Can anyone please tell me what is the problem here Or is this the right way to compile it?
There's no such line 26 in the code that you posted. Please, post relevant code.
If the fptr you use in line 26 is declared exactly as the one in your pthread_create above (i.e. with empty parameter list ()), then the code will not compile as C++, since in C++ the () as parameter list means "no parameters at all". And you are trying to pass arguments, which is what causes the error. Declare fptr with the proper parameter list if you want your code to work as C++.
The declaration with () as parameter list will work in C code, since in C it means "unspecified parameters", but not in C++.
You've declared fptr as a pointer to a function that takes no arguments and returns an int. Thus, gcc complains when you try calling it with three arguments.
Try redeclaring fptr with the proper arguments.
Related
I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60
When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;
You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative
I'm trying to wrap a c++ function called i_receive() by following this tutorial, I first created a wrap.c file, the content of this file is like this:
int i_receive(const uint32_t *f, int32_t t){
static int (*real_i_receive)(const uint32_t *, int32_t)=NULL;
printf("hello world");
return real_i_receive;
}
I compiled this file with gcc -fPIC -shared -o wrap.so wrap.c -ldl, when I used the LD_PRELOAD to run some C++ code with LD_PRELOAD=/full/path/to/wrap.so ./mycppcode I got this message:
ERROR: ld.so: object '/full/path/to/wrap.so' from LD_PRELOAD cannot be preloaded: ignored`.
I was guessing the reason might be that the wrap file is a C file, and I'm using it with C++ code, am I right?
I changed the file to wrap.cc with the same content, when compiling in the same way as before, I got:
ERROR: invalid conversion from 'int (*)(const uint32_t*, int32_t)' to 'int'
First of all, your 2nd error your are getting becase you are returning a Pointer to function type instead of a int type.
If you want to return an int, call the function from the code :
return real_i_receive(f,t);
Notice the "()" which means a function call.
Regarding your guess : it doesn't matter if you are using C or C++ code, the libaries are all assembly code.
One difference between exporting C functions and C++ functions is the name mangling. You would rather export a function as a C function to be able to access it inside your library through unmagled name.
To export a function without name mangling it, you can use extern "C" .
Replace
return real_i_receive;
with
return real_i_receive(f, t);
As it is, the return type of your function is int but you're returning a function pointer.
I'm newbie in the ansi and iso world, i compiled my program with :
-asni -pedantic -std=c++11 -std=c++98
Now, i get the following warning:
warning: converting from 'void (NetworkSocket::*)()' to 'void* (*)(void*)' [-pedantic]
for the following line:
if (pthread_create(this->threadArray, NULL, (void*(*)(void*)) &NetworkSocket::threadProcedure , (void *)this) != 0)
{ /* error */ }
How can i pass pedantic warning?
pthread_create is a C function expecting a C function taking a void pointer, and returning a void pointer. So you can use such a C function to dispatch the call to you member function, if you use the this pointer as thread argument:
extern "C" void* startThread( void* p )
{
static_cast< NetworkSocket* >( p )->threadProcedure();
return 0;
}
if ( pthread_create( this->threadArray, 0, startThread, this ) )
...
I would like to create a thread passing a vector as parameter.
but i got the following errors:
error: invalid conversion from ‘int’ to ‘void* (*)(void*)’ [-fpermissive]
error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’ [-fpermissive]
I have the following code:
#include <iostream>
#include <vector>
#include <pthread.h>
using namespace std;
void* func(void* args)
{
vector<int>* v = static_cast<vector<int>*>(args);
cout << "Vector size: " << v->size();
}
int main ( int argc, char* argv[] )
{
vector<int> integers;
pthread_t thread;
for ( int i = 0; i < 10; i++)
integers.push_back(i+1);
// overheat call
//pthread_create( &thread, NULL, func, static_cast<void*>(&integers));
pthread_create( &thread, NULL,func,&integers);
cout << "Main thread finalized" << endl;
return 0;
}
How I can do it properly ?
Thanks
EDIT: forgot the includes posting here only; Revised.
I got new errors:
error: stray ‘\305’ in program
error: stray ‘\231’ in program
I am trying to know about it.
Thanks in advance.
FINAL EDIT : Thanks to all. Sorry, I had another int var called func in other location.
Thanks for your help.
You have forgotten to include <vector>; this confuses the compiler as it first fails to generate func, and then fails to identify it as a function in the call to pthread_create.
Once you include that, your code should compile (and you can remove the static_cast<void*> if you like); but to work correctly you also need to call pthread_join before the vector goes out of scope, and return a value from func.
UPDATE: your latest edit has broken the code: you should not cast func to void*, but leave it as a function pointer. This should work:
pthread_create(&thread, NULL, func, &integers);
Errors like stray ‘\305’ in program imply that you have some strange characters in your code, although they're not in the code you've posted. Have a look at the lines that the error messages refer to.
Refactoring legacy code, I came across this function (pseudocode):
int getMessage( char * buffer, int size = 300 );
Gee, look at that buffer just waiting to overflow. So I came up with a function using std::string, and thought it would be nice to use function overloading:
int getMessage( std::string & buffer );
So far, so good. But when I try to call the function with a string:
std::string buffer;
int rc = getMessage( buffer );
I get this error:
cannot convert 'std::string' to 'char*' for argument '1' to 'int getMessage(char*, int)'
Obviously, the compiler (GCC 4.1.2) tries hard to convert std::string to char* to satisfy the first function's parameter list (using the default value to satisfy the second parameter), gives up, but doesn't try the second function...
I wouldn't have a problem working around this issue, but I'd like to know why this fails, and whether there would be a way to make it work as intended.
It works as expected on my GCC 4.3.2, maybe you misspelled the name of the overload? There's no conversion from std::string to char*, so the compiler shouldn't have any problems choosing the correct overload.
$ cat test.cpp
#include <string>
#include <stdio.h>
int getMessage( char * buffer, int size = 300 )
{
printf("1\n");
return 1;
}
int getMessage( std::string & buffer )
{
printf("2\n");
return 2;
}
int main()
{
std::string buffer;
buffer = "Hello";
int rc = getMessage( buffer );
}
$ g++ test.cpp -Wall -pedantic
test.cpp: In function ‘int main()’:
test.cpp:20: warning: unused variable ‘rc’
$ ./a.out
2
$ $ g++ -v 2>&1|tail -n1
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)
$
Hmmm. There is no implicit conversion from std::string to char*, so that can't be your problem. Are you sure your new function is visible at the call site?
You said this is pseudo-code. Are you leaving something out? Are these template functions or member functions? Please post more of the code or try to boil it down to a smaller test case.
My guess is that the overload for the string version of the function isn't visible where you called it. Are you sure that it is in the correct header file, and is spelled correctly?
Do you have a declaration of `int getMessage( std::string & buffer );' in scope? You are hitting this error because the proper function is not being found.
As always, once the problem is solved, the solution is painfully trivial and should have been obvious all along.
So I came up with a function using std::string...
...in my working directory, which compiled just fine, but -I and -L in my makefile were still pointing at the previous version of the library, which was blissfully unaware of the new function.
Sorry for the bother. I've been an idiot. I hope this doesn't become a habit. ;-)