Unable to hook ncurses functions with LD_PRELOAD - c++

I'm trying to hook some ncurses functions but they don't have any effect.
ncurses isn't statically linked, so I don't see why it wouldn't work.
test.cpp
#include <cstdio>
#include <cstdlib>
#include <curses.h>
int main() {
initscr();
cbreak();
noecho();
getch();
endwin();
return 0;
}
Compiled with: gcc test.cpp -o test -std=c++11 -lncurses
hook.cpp
#include <dlfcn.h>
#include <cstdio>
#include <cstdlib>
int getch() {
typedef int getch ();
getch* old_getch = (getch*) dlsym(RTLD_NEXT, "getch");
int result = old_getch();
fprintf(stderr, "getch() = %i\n", result);
return result;
}
int noecho() {
typedef int noecho ();
noecho* old_noecho = (noecho*) dlsym(RTLD_NEXT, "noecho");
int result = old_noecho();
fprintf(stderr, "noecho() = %i\n", result);
return result;
}
int endwin() {
typedef int endwin ();
endwin* old_endwin = (endwin*) dlsym(RTLD_NEXT, "endwin");
int result = old_endwin();
printf("endwin called");
return result;
}
Compiled with: gcc hook.cpp -o hook.so -shared -ldl -fPIC -std=c++11
It sadly outputs nothing, and I'm completely stumped.

The specification doesn't state getch has to be a function (not a macro). Actually, in ncurses-6.1, getch defined as
#define getch() wgetch(stdscr)
Nonetheless, there is a getch function in libncurses (which simply calls wgetch(stdscr)), so dlsym(libncurses_handle,"getch") does work.

Related

My file can compile but I get "no such file or directory" when I try to run it

I figured that the problem was that I was not using ./a.out instead of ./filename, but that wasn't the case.
This is how I compile my program:
g++ -o -Wall -pthread filename.cpp
Running:
./filename
I figured that running pthread programs would be different than running a standard c++ program, but that wasn't the case.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct argStruct {
int arg1;
int arg2;
};
void *sum(void *arguments) {
struct argStruct *args = (struct argStruct *)arguments;
int a = args -> arg1;
int b = args -> arg2;
int c = a + b;
printf("%d + %d = %d ",a,b,c);
pthread_exit(NULL);
}
int main() {
pthread_t thr1, thr2;
struct argStruct args;
args.arg1 = 3;
args.arg2 = 10;
int t1, t2;
pthread_create(&thr1, NULL, &sum, (void *)&args);
pthread_create(&thr2, NULL, &sum, (void *)&args);
pthread_join(thr1, NULL);
pthread_join(thr2, NULL);
exit(EXIT_SUCCESS);
}
By calling
g++ -o -Wall -pthread filename.cpp
You instruct the compiler to write the result to a file named -Wall.
You therefore want to use one of these
g++ -Wall -pthread filename.cpp
g++ -Wall -pthread -o filename filename.cpp
The first writes the result to a.out, the second to filename. (Also it enables the warnings)

Huge ammount of errors during compilation of program with Magick++

During the compilation of a program I was making, that uses the Magick++ library, there appeared an incredibily huge ammount of errors.
This is the command line I used for compile it (g++'s version is 4.9.2, running on Ubuntu 12.04):
g++ -std=c++14 -g -fopenmp `Magick++-config --cppflags --cxxflags` main.cpp -o glitch_img2 `Magick++-config --ldflags --libs`
Here is the program's code:
#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <cmath>
#include <string>
#ifdef __OPENMP
#include <omp.h>
#endif
#include <Magick++.h>
double d_max(double a,double b)
{
return (a>b) ? a : b;
}
int ui_clip(int x,int a,int b)
{
return (x<b) ? b : ((x>a) ? a : x);
}
int transform(int x)
{
return ((x*32+1654)%21+x*11+642)%164%33%16;
}
using namespace std;
using namespace Magick;
int main(int argc,char **argv)
{
InitializeMagick(*argv);
Image img1;
img1.read(argv[1]);
int size_x = img1.columns();
int size_y = img1.rows();
int np = size_x*size_y;
Image out;
out.size(Geometry(size_x,size_y));
double *buff_img1 = new double[3*size_x*size_y];
double *buff_out = new double[3*size_x*size_y];
img1.write(0,0,size_x,size_y,"RGB",DoublePixel,buff_img1);
int ix, iy;
#ifdef __OPENMP
#pragma omp for private(ix,iy) schedule(static)
#endif
for (iy=0;iy<size_y;iy++)
{
for (ix=0;ix<size_x;ix++)
{
int loc = (size_x*iy+ix)*3;
double pimg1[3] = {
buff_img1[3*loc ],
buff_img1[3*loc+1],
buff_img1[3*loc+2]
};
int x1 = (ix*(1+transform(ix)))%size_x;
int y1 = (iy*(1+transform(iy)))%size_y;
int loc1 = ui_clip((size_x*y1+x1)%np,0,np-1)*3;
double out_pix[3] = {
buff_img1[3*loc1 ],
buff_img1[3*loc1+1],
buff_img1[3*loc1+2]
};
buff_out[3*loc ] = abs(out_pix[0]-pimg1[0]);
buff_out[3*loc+1] = abs(out_pix[1]-pimg1[1]);
buff_out[3*loc+2] = abs(out_pix[2]-pimg1[2]);
}
}
out.read(size_x,size_y,"RGB",DoublePixel,buff_out);
out.write("Output.png");
}
And those errors are posted here.
What causes such errors and how can they be fixed?
EDIT: The mentioned behaviour dissapears when I remove the Magick++.h header.

How to use dlopen and dlsym when *.so using function from other other *.so

I have following code which use dlopen and dlsym.
main.cpp
#include <stdio.h>
#include <dlfcn.h>
int main(int argc,char** argv) {
void* handler;
handler = dlopen("./libsql.so",RTLD_LAZY);
if(handler){
int (*insert)(const char*);
char* error=NULL;
dlerror(); /* Clear any existing error */
*(void **) (&insert) = dlsym(handler, "openAndInsert");
if ((error = dlerror()) == NULL) {
(*insert)(argv[1]);
}
else {
printf("Error in dlsym\n");
}
}
else {
printf("dlopen error\n");
}
return 0;
}
Compile command:g++ main.cpp -ldl
libsql.cpp
#include <sqlite3.h>
#include <string.h>
#include <stdio.h>
#include "libsql.h"
int openAndInsert(const char* sql) {
sqlite3 *db;
sqlite3_stmt *stmt;
sqlite3_initialize();
int rc = sqlite3_open("./database.db", &db);
if(rc==0){
rc = sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);
if(rc==0) {
if(sqlite3_step(stmt)){
printf("Done\n");
}
else {
printf("execute error\n");
}
sqlite3_finalize(stmt);
}
else {
printf("prepare error\n");
}
sqlite3_close(db);
}
else {
printf("open error\n");
}
sqlite3_shutdown();
}
libsql.h
#ifndef LIBSQL_H_
#define LIBSQL_H_
#ifdef __cplusplus
extern "C" {
#endif
int openAndInsert(const char* sql);
#ifdef __cplusplus
}
#endif
#endif
compile command:g++ -fPIC -shared -o libsql.so libsql.cpp
Now when I run application I get error as below.
./a.out: symbol lookup error: ./libsql.so: undefined symbol: sqlite3_initialize
But libsqlite3 already installed and works fine with other programm.
When I used below command to generate my *.so file Its works fine.
g++ -fPIC -shared -o libsql.so libsql.cpp -lsqlite3

exit(3) hangs in Linux C++

I have a small C++ program that pings other machines on a network and send status information out over another network. The program runs as a daemon, so the startup process forks off a child and then calls exit. This program is cross-compiled to run on two different architectures: x86 and ARM. The GCC versions are 4.4 and 3.5 respectively. I can compile and run the program on x86 and it works flawlessly. However, when I run the program on the ARM, it hangs any time I call exit, not just after the fork. I have no functions registered with atexit or on_exit. The following are my includes:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <set>
#include <vector>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include "telnet_client.h"
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <syslog.h>
#include <customlib1.h>
#include <customlib2.h>
The following are my GCC commands:
arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src -I../include/ -I../include_rms -c can_wifid.cpp -o can_wifid.o
arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src -I../include/ -I../include_rms -c telnet_client.cpp -o telnet_client.o
arm-none-linux-gnueabi-g++ -Wall -DBUILDSTAMP="\"`date '+%F %T'`\"" -g -ggdb -O0 -I/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/include -DEMBEST_ARM -I/usr/local/share/arm/boost/src can_wifid.o telnet_client.o -L/usr/local/arm/arm-2007q1/arm-none-linux-gnueabi/libc/usr/lib -L../lib_embest_arm -L../lib_rms_embest_arm -Wl,-Bdynamic -lutilities -lboost_system -lboost_thread -lcanprovider -lembestcan -o can_wifid
Even just parsing my command line parameters with getopt then calling exit after a version message causes this problem (simplest case in my program). Has anybody ever experienced anything like this where exit just hangs ?
EDIT: Added code for the first part of the main function:
struct canwifid_options
{
public:
bool daemon_mode;
int verbosity;
canwifid_options()
{
this->daemon_mode = false;
this->verbosity = LOG_NOTICE;
}
};
static canwifid_options options;
int main(int argc, char * argv[])
{
int LoggingOptions = LOG_CONS|LOG_NDELAY|LOG_PID;
pid_t Pid;
ParseCommandLine(argc, argv);
if (!options.daemon_mode)
{
LoggingOptions |= LOG_PERROR;
}
openlog("can_wifid", LoggingOptions, LOG_USER);
setlogmask(LOG_UPTO(options.verbosity));
if (options.daemon_mode)
{
Pid = fork();
if (Pid < 0)
{
// couldn't fork off and create a child process
// log it, %m is a special syslog flag
syslog(LOG_CRIT, "Unable to create daemon [Error: %m]");
exit(ESRCH);
}
else if (Pid > 0)
{
// we're the parent, so we're done and out of here
exit(EXIT_SUCCESS);
}
else
{
// we're the child, take control of the session.
setsid();
// change to the root directory so we don't retain unnecessary control
// of any mounted volumes
chdir("/");
// clear our file mode creation mask
umask(0000);
}
}
else
{
// get our process ID
Pid = getpid();
}
syslog(LOG_INFO, "Running as %s", options.daemon_mode ? "daemon" : "standalone");
// Network code here, snipped for clarity
}
And there ParseCommandLine function:
static void ParseCommandLine(int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv, "dhqvDV?")) > 0)
{
switch (c)
{
case 'd':
options.daemon_mode = true;
break;
case 'V':
VersionMessage(argv);
exit(EXIT_SUCCESS);
break;
case 'q':
options.verbosity = LOG_WARNING;
break;
case 'v':
options.verbosity = LOG_INFO;
break;
case 'D':
options.verbosity = LOG_DEBUG;
break;
case 'h':
case '?':
default:
HelpMessage(argv);
exit(EXIT_SUCCESS);
break;
}
}
return; //done
}
An issue I ran into once is that calling exit attempts to exit and calls global destructors WITHOUT trying to unwind the stack or call any destructors for local objects on the stack. This can easily manifest if you have any sort of locks that might be required for global destructors. For example, this program deadlocks in exit (actually in the global dtor):
#include <iostream>
#include <mutex>
std::mutex lock;
class A {
public:
A() {
std::lock_guard<std::mutex> acquire(lock);
std::cout << "ctor A" << std::endl;
}
~A() {
std::lock_guard<std::mutex> acquire(lock);
std::cout << "dtor A" << std::endl;
}
};
A a;
int main()
{
std::lock_guard<std::mutex> acquire(lock);
exit(0);
}
Now your problem may be something completely different, but there's a strong possibility its related to something in a global destructor that is misbehaving because some object on the stack has not been destroyed properly.
If you want to exit while unwinding the stack properly (which is required for RAII structured code), you can't call exit. Instead you need to throw an exception which is caught (only) in main and causes main to return.

Call an overwrite function library

I want to use a personal "pthread_self" function. I want to rewrite the "pthread_self()" and, at the final, call to the real "pthread_self".
is it possible in C/C++?
Example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
pthread_t pthread_self(void)
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
return ::pthread_self(); // This doesn't work
}
main()
{
printf("\nThis is my main thread: %lu\n", pthread_self());
}
the code seems to be C89 without a return type for main. So I suggest you remove the :: operator infront of pthread_self() in the function pthread_self(void) and recompile.
Also call your pthread_self() by some other name such as pthread_self_2(void)
Will it be allowed to overload pthread_self() with a dummy variable (never used)?
pthread_t pthread_self( bool )
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
printf( "%s\n", __PRETTY_FUNCTION__ );
return ::pthread_self(); // This doesn't work
}
int main()
{
printf( "%s\n", __PRETTY_FUNCTION__ );
pthread_self( false );
printf( "%s\n", __PRETTY_FUNCTION__ );
}
produces
$ g++ test.cpp -lpthread
$ ./a.out
int main()
pthread_t pthread_self(bool)
int main()
$
Two other approaches might be:
Write a function my_pthread_self(), use it everywhere, and have it call real pthread_self()
Have a macro PTHREAD_SELF which calls your wrapper which internally calls real pthread_self()
The following is a bit hacky but should work in C. Put the following in a header which you would have to include before or instead of <pthread.h> (but never after pthread.h):
pthread_t _pthread_self(void);
#define pthread_self _pthread_self
And in the corresponding .c file:
#include <pthread>
#include "wrapper.h"
#undef pthread_self // undo the hack locally
pthread_t _pthread_self(void)
{
// Do something else.....
// ...
// And finally call to the real pthread_self():
return pthread_self();
}
Now, when you write pthread_self in some other file than that .c file, it expands to your wrapper function. Within the .c file above, since this hack is not done, the call within the wrapper will call the library function.
This should give you some ideas. If you control the linking of your executable, you don't need to use LD_PRELOAD.
Thanks to all of you.
Based mainly on these two links Intercepting Arbitrary Functions on... and Tutorial: Function Interposition in Linux show by #Carl Norum and #Arkadyi, I show you a possible solution:
I have two source files and a Makefile:
mipthread_self.C:
#include <stdio.h>
#include <pthread.h>
#if defined (__STDC__) || defined (__cplusplus) || defined (c__plusplus)
#if defined (__cplusplus) || defined (c__plusplus)
extern "C" {
#endif
pthread_t __real_pthread_self();
pthread_t __wrap_pthread_self(void)
{
printf("This is mipthread_self %lu\n", __real_pthread_self());
return __real_pthread_self();
}
#if defined (__cplusplus) || defined (c__plusplus)
}
#endif
#endif
test.C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void* start_function(void* value)
{
printf("Thread start function is running for: %u\n", (unsigned int)pthread_self());
sleep(5);
pthread_exit(value);
}
int main()
{
int res;
pthread_t thread1, thread2;
void* threadReturnValue;
res = pthread_create(&thread1, NULL, start_function, (void*)"thread-one");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread1 created with id: %u\n", (unsigned int)thread1);
res = pthread_create(&thread2, NULL, start_function, (void*)"thread-two");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread2 created with id: %u\n", (unsigned int)thread2);
res = pthread_join(thread1, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
res = pthread_join(thread2, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
return 0;
}
And the Makefile:
BIN=test
CFLAGS=-g -m32 -fPIC -Wall $(DEFINES)
TIPO=-m32
PWD=`pwd`
DIR_OBJ=$(PWD)
DIR_BIN=$(DIR_OBJ)
INCLUDES=
LD_LIBRARIES=-L$(DIR_OBJ) -lmipthread -Xlinker --wrap -Xlinker pthread_self -lpthread -lstdc++
$(BIN): libmipthread.a
#echo ""
#echo "Se va a generar el binario $#"
#echo ""
gcc $(CFLAGS) test.C -o $(DIR_BIN)/$# $(LD_LIBRARIES)
libmipthread.a: mipthread_self.o
ar crv $(DIR_OBJ)/$# $(DIR_OBJ)/$<
mipthread_self.o: mipthread_self.C
gcc $(CFLAGS) -c ${PWD}/$< -o $(DIR_OBJ)/$# $(INCLUDES)
clean:
rm $(DIR_OBJ)/*.o
rm $(DIR_OBJ)/*.a
rm $(DIR_OBJ)/test