backtrace function only got the last frame - c

I want to call backtrace function to get the callchain, the following is my code, this code works good on x86, but can't work on mips
gcc -o hello-x86 hello.c -g -rdynamic -O0 -Wall
./hello-x86
size = 6
0x40095c : ./hello-x86(foo+0x1f) [0x40095c]
0x400a2d : ./hello-x86(b+0x9) [0x400a2d]
0x400a38 : ./hello-x86(a+0x9) [0x400a38]
0x400a4e : ./hello-x86(main+0x14) [0x400a4e]
0x7fee0d003f45 : /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7fee0d003f45]
0x400879 : ./hello-x86() [0x400879]
but on mips, just only got the last frame, how to fix it ?
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL
./hello
size = 1
0x400a04 : ./hello(foo+0x24) [0x400a04]
can't get b and a and main. but i can got full callchain in gdb, why can't got it via backtrace function ?
my toolchain is codesourcery mips-2016.05, the libc version is 2.23
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <execinfo.h>
#define BACKTRACE_SIZ 100
int i = 0;
void foo(void)
{
void *array[BACKTRACE_SIZ];
size_t size, i;
char **strings;
size = backtrace(array, BACKTRACE_SIZ);
strings = backtrace_symbols(array, size);
printf("size = %ld\n", (long)size);
for (i = 0; i < size; ++i) {
printf("%p : %s\n", array[i], strings[i]);
}
free(strings);
while (1) {
i++;
}
}
void b(void)
{
foo();
}
void a(void)
{
b();
}
int main(int argc, char **argv)
{
a();
return 0;
}
i tried -fno-omit-frame-pointer and -fomit-frame-pointer, these two option all can't work.
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL -fomit-frame-pointer
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL -fno-omit-frame-pointer
and i tried on my arm board, it worse, the size is 0 on arm

Related

How to execute a certain part using makefile in C (LINUX)

I am developing a C program that calls 2 functions, func1() and func2().
Here is the code
void func1(void){/*...*/}
void func2(void){/*...*/}
int main(){
func1();
func2();
return 0;
}
Is there a way that when I compile the program using make and a certain flag, it just executes func1() and if I compile using another flag then it only executes func2()?
How to make such a makefile? Can anyone provide me with a makefile that does this job?
You can use the -D flag of the compiler:
cc -o demo demo.c -Dfunc=func1
then
#include <stdio.h>
void func1(void) { puts("1"); }
void func2(void) { puts("2"); }
int main(void)
{
func();
return 0;
}
Output:
1
You can also pass the function as an argument to make:
CC = gcc
CFLAGS = -std=c11 -Wpedantic -Wall
action: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Dfunc=$(argument)
clean:
rm -f demo
call make using:
make action argument=func1
or
make action argument=func2
But if you really want to do that:
int main(){
func1();
func2();
call both functions inside main, you should use another approach (although this solution seems quite sticky to me):
#include <stdio.h>
void func0(void) { /* do nothing */ }
void func1(void) { puts("1"); }
void func2(void) { puts("2"); }
#ifdef delete_func1
#define func1 func0
#endif
#ifdef delete_func2
#define func2 func0
#endif
int main(void)
{
func1();
func2();
return 0;
}
compile using:
cc -o demo demo.c -Ddelete_func1
or
cc -o demo demo.c -Ddelete_func2
then the Makefile should look like:
CC = gcc
CFLAGS = -std=c11 -Wpedantic -Wall
func1: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Ddelete_func2
func2: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Ddelete_func1
clean:
rm -f demo
call it using:
make func1
or
make func2
you can delete both functions using -D twice:
cc -o demo demo.c -Ddelete_func1 -Ddelete_func2

Create a static libary and link against it

Hello beautiful people,
i'm trying to create a static libary and to compile against it.
I've allready created a small static libary and a header for it.
Header (math.h):
int add (int a, int b);
int sub (int a, int b);
add.c:
int add (int a, int b) { return a + b; }
sub.c:
int sub (int a, int b) { return a - b; }
I've created my static libary with the following commands:
gcc -c add.c
gcc -c sub.c
ar rcs libmymath.a add.o sub.o
Now my main.c
#include <stdio.h>
#include "math.h"
int main( int argc, char **argv ) {
printf("Result : %d\n", add(5,7) );
return 0;
}
I can compile it with the following command:
gcc main.c libmymath.a -o main
But if i compile it the following way, it fails.
gcc main.c -lmymath -L. -o main
It fails with the following error:
/usr/bin/ld: cannot find -lmymath collect2:
error: ld returned 1 exit status
even a change to
gcc main.c -llibmymath -L. -o main
fails and even if i include the header mymath.h to gcc
Can you help me ?
gcc understood -lmymath by libmath.so or libmath.a already. So when you add lib word in -llibmymath. This case the gcc understood your library name being liblibmymath.a. So, please replace this command
gcc main.c -llibmymath -L. -o main
by
gcc main.c -o main -L. -lmymath
It should work.

I redefine a standard C library function in a dynamic library, but I can't use it

There is a simple example to describe my problem:
I have 3 files, main, level1.so and level2.so. (My OS is solaris11.3, gcc version is 3.4.3)
In main, it calls execute() from level1.so. And the execute() calls run() from level2.so. And the run() calls fcloseall() which is redefined in level2.so.
fcloseall() is redefined to do nothing (it will close all opened fds include stdout, stdin and stderr originally).
Now I want print something around execute() in main, but only the message before execute() is printed.
The codes are shown below:
The level2.so is compiled from level2.c and level2depend.c.
level2.c:
#include <stdio.h>
int run()
{
fcloseall();
return 0;
}
level2depend.c:
#include <stdio.h>
int fcloseall() //redefine the std c function fcloseall
{
printf("in redefined fcloseall\n");
return 0;
}
The level1.so is compiled from level1.c.
level1.c
#include <dlfcn.h>
int execute()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel2.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"run");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
int ret = sofunc();
dlclose(lib_handle);
return 0;
}
The main is compiled from main.c.
main.c
#include <dlfcn.h>
#include <stdio.h>
int main()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel1.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"execute");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
printf("before\n");
int ret = sofunc();
printf("after\n");
dlclose(lib_handle);
return 0;
}
The makefile is:
all:
gcc level2depend.c -o level2depend.o -c -g -fPIC
gcc level2.c -o level2.o -c -g -fPIC
gcc -shared -g level2.o level2depend.o -o liblevel2.so -fPIC
gcc level1.c -o level1.o -c -g -fPIC
gcc level1.o -o liblevel1.so -shared -fPIC
gcc main.c -o main -g -ldl
clean:
rm level2depend.o level1.o liblevel1.so level2.o liblevel2.so main
I execute main and the result is:
root#solaris#./main
before
If I change the makefile as gcc main.c -o main -g -ldl -llevel2, the result is:
root#solaris#./main
before
in redefined fcloseall
after
And this is what I want.
I want know why this happen. Thanks!
You can use the wrap function provided by ld.
gcc -Wl,-wrap,fcloseall ....
and in your source code,
int __wrap_fcloseall(void)
{...}

LD_PRELOAD and weak references minimal example doesn't work

This is probably going to be embarrassing:
I am using library prelaoding in other projects, but I cannot get this minimal example to work:
weakref.h:
void f_weak() __attribute__((weak));
weakref.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("f_weak()\n");
fflush(stdout);
}
test_weakref.c:
#include <stdio.h>
#include "weakref.h"
int main(void)
{
if (f_weak) {
printf("main: f_weak()\n");
}
else {
printf("main: ---\n");
}
fflush(stdout);
return 0;
}
Here is what I do:
$ gcc weakref.c -shared -fPIC -o libweakref.so
$ nm libweakref.so | grep f_weak
0000000000000708 W f_weak
$ gcc test_weakref.c -o test_weakref
$ ./test_weakref
main: ---
$ LD_PRELOAD=./libweakref.so ./test_weakref
main: ---
The expected output of the last command is
main: f_weak()
What am I missing?
As far as I know, external functions are resolved only when you call them. So, your test if (f_weak) will always fail. If you do it the following way, you can see that it works:
weakref.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("original\n");
fflush(stdout);
}
weak2.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("overridden\n");
fflush(stdout);
}
test_weakref.c:
#include <stdio.h>
#include "weakref.h"
int main(void)
{
f_weak();
fflush(stdout);
return 0;
}
and then:
tmp> gcc weakref.c -shared -fPIC -o libweakref.so
tmp> gcc weak2.c -shared -fPIC -o libweak2.so
tmp> gcc -o test_weakref test_weakref.c ./libweakref.so
tmp> ./test_weakref
original
tmp> LD_PRELOAD=./libweak2.so !.
LD_PRELOAD=./libweak2.so ./test_weakref
overridden
I found the solution in an old Makefile: the program has also to be compiled with the -fPIC flag.
$ gcc weakref.c -shared -fPIC -o libweakref.so
$ nm libweakref.so | grep f_weak
0000000000000708 W f_weak
$ gcc test_weakref.c -o test_weakref -fPIC
$ ./test_weakref
main: ---
$ LD_PRELOAD=./libweakref.so ./test_weakref
main: f_weak()

Difference between getting function pointers from shared library

The question is how I can get function address from shared library (UNIX/LINUX)?
I had written some testcases in C (see below), compiled and run on Ubuntu 10.04 (amd64) and FreeBSD-8.2 (amd64). I hadn't feel any difference but I want to know more about possible troubles.
Here they are:
Test 1
lib.c
char* f0(void) {
return "Hello, World!";
}
main.c
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void *hlib, *addr;
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if ( !(hlib = dlopen("./lib.so", RTLD_LAZY)) )
return 1;
if ( !(addr = foo = dlsym(hlib, "f0")) )
return 2;
s = foo();
printf("%p => %s\n", addr, s);
return 0;
}
Now build it:
gcc -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so -shared -nostartfiles lib.o
gcc -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
This prints the address of library function f0() and the result of execution.
Test 2
lib.h (define here the standard interface of dynamically linking libraries)
#ifndef __LIB_H__
#define __LIB_H__
typedef struct __syminfo {
char* name; // function name
void* addr; // function address
} syminfo_t;
typedef struct __libinfo {
int num; // number of exported functions
syminfo_t sym[1]; // vector of exported function information
} libinfo_t;
extern int (*__getinfo)(libinfo_t**);
#endif
/* __LIB_H__
*/
lib.c (the library itself)
#include <stdlib.h>
#include <lib.h>
static libinfo_t* li;
char* foo(void);
__attribute__((constructor)) void __init() {
if ( (li = calloc(1, sizeof(libinfo_t))) ) {
li->num = 1;
li->sym[0].name = "foo";
li->sym[0].addr = &foo;
}
}
__attribute__((destructor)) void __free() {
if (li)
free(li);
}
int getinfo(libinfo_t** inf) {
if (!inf)
return -1;
*inf = li;
return 0;
}
char* foo(void) {
return "Hello, World!";
}
main.c
#include <stdio.h>
#include <dlfcn.h>
#include <lib.h>
libinfo_t* inf;
void* hlib;
int (*__getinfo)(libinfo_t**);
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if ( !(hlib = dlopen("./lib.so", RTLD_LAZY)) )
return 1;
if ( !(__getinfo = dlsym(hlib, "getinfo")) )
return 2;
if (__getinfo(&inf))
return 3;
if ( !(foo = inf->sym[0].addr) )
return 4;
s = foo();
printf("%p => %s\n", inf->sym[0].addr, s);
return 0;
}
Now compile it (without -nostartfiles):
gcc -I. -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so lib.o -shared
gcc -I. -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
This printf the same as Test 1: the address of library function foo() and the result of its execution.
I tried to show how can I get shared library function address, but am I right in the second test? Shall I have got some troubles with it?
NOTE: in FreeBSD-8.2 there is no need to use -ldl argument, all dlfcn.h routines are in libc library.
Respectively waithing for any explanations.
That looks fairly standard to me. The only thing that you're using that could pose some problems is that you're using gcc attributes to create a constructor and destructor for your shared library. That may not be entirely portable; it depends on what platforms you care about.
Note that in this specific case there's no need to do something this complicated. The information that you're returning from the shared library in your second example is all known at compile time, so you can just create a static struct with that information and either retrieve the address of the struct with dlsym and poke around in it from the main program or call a known function to return the struct. (The latter is slightly more flexible in some corner cases, but both are fairly flexible.)

Resources