I have an executable (1) with two shared objects (2 and 3) opened using dlopen(..., RTLD_GLOBAL). All files include the symbol func().
If I use dlsym(RTLD_NEXT, ...) in 1 looking for the next func() symbol, the 2 symbol is returned. But, if in 2 I use dlsym(RTLD_NEXT) again, no symbol is found. I thought that 3 symbol would be returned.
What is the meaning of this?
Update: adding an example
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
typedef void (*next_t) (void);
static char *name[] = { "next" };
static char path[1024];
static next_t linc;
static void dlnext_open(int i)
{
sprintf(path, "./lib%d.so", i);
fprintf(stderr, "loading %d\n", i);
void *handler = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
return;
}
int next()
{
fprintf(stderr, "NEXT %d\n", NUM);
#ifdef DLNUM1
dlnext_open(DLNUM1);
#endif
#ifdef DLNUM2
dlnext_open(DLNUM2);
#endif
linc = dlsym(RTLD_NEXT, name[0]);
if (linc != NULL) {
linc();
fprintf(stderr, "returning to %d\n", NUM);
} else {
fprintf(stderr, "no next\n");
}
}
#if NUM == 1
int main(int argc, char *argv[])
{
next();
return 0;
}
#endif
And the make/exec:
gcc -O0 -shared -fPIC -o lib3.so 1.c -DNUM=3
gcc -O0 -shared -fPIC -o lib2.so 1.c -DNUM=2
gcc -O0 -o 1 1.c -ldl -DNUM=1 -DDLNUM1=2 -DDLNUM2=3
./1
The result:
NEXT 1
loading 2
loading 3
NEXT 2
no next
returning to 1
I am using Yocto project cross-compiler to compile my C code.
But for some reasons I have compilation errors.
This is my C code :
#include <stdio.h>
#include <stdlib.h>
#include "/home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa.hpp"
/* MRAA does not yet understand GPIO-A - GPIO-L */
/* Linaro will add this */
/* What Mraa does understand is pin out numbers so, */
/* pin 23 is GPIO-A and pin 25 is GPIO-C */
#define LED 10
#define BUTTON 29
bool running = true;
bool led_state = false;
int last_touch;
void sig_handler(int signo)
{
if (signo == SIGINT)
running = false;
}
int main(int argc, char* argv[])
{
mraa::Result ret;
int touch;
mraa::Gpio* touch_gpio = new mraa::Gpio(BUTTON);
if (touch_gpio == NULL){
return mraa::ERROR_UNSPECIFIED;
}
mraa::Gpio* led_gpio = new mraa::Gpio(LED);
if (led_gpio == NULL){
return mraa::ERROR_UNSPECIFIED;
}
signal(SIGINT, sig_handler);
if ((ret = touch_gpio->dir(mraa::DIR_IN))!= mraa::SUCCESS){
return ret;
}
if ((ret = led_gpio->dir(mraa::DIR_OUT))!= mraa::SUCCESS){
return ret;
}
led_gpio->write(led_state);
while (running) {
touch = touch_gpio->read();
if (touch == 1 && last_touch == 0) {
led_state = !led_state;
ret = led_gpio->write(led_state);
usleep(100000);
}
last_touch = touch;
usleep(1);
}
delete led_gpio;
delete touch_gpio;
return ret;
}
This is the Makefile :
#CC=arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a5 --sysroot=/opt/poky-atmel/2.5.3/sysroots/cortexa5hf-neon-poky-linux-gnueabi
#CC="gcc"
all: last1.o
${CC} last1.o -o target_bin -lmraa
last1.o: last1.c
${CC} -I . -c last1.c
clean:
rm -rf *.o
rm target_bin
And this is what I get when i run make all :
In file included from
/home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa/common.hpp:28:0,
from /home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa.hpp:27,
from last1.c:4:
/home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa/types.hpp:32:1:
error: unknown type name ‘namespace’ namespace mraa ^~~~~~~~~
/home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa/types.hpp:33:1:
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘{’
token { ^
In file included from
/home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa.hpp:27:0,
from last1.c:4: /home/gaston/linux4sam/poky/build-microchip/tmp/sysroots-components/cortexa5hf-neon/mraa/usr/include/mraa/common.hpp:29:10:
fatal error: string: No such file or directory #include
^~~~~~~~
compilation terminated. Makefile:8: recipe for target 'last1.o' failed
make: *** [last1.o] Error 1
You are compiling your code written in C with a C++ compiler.
Just change your .c files to .cpp files, and compile using g++ rather than gcc if you are on Unix systems.
I want to compile following c file:
#include <stdio.h>
#include <stdlib.h>
#include <../deps/linux/gpio.h>
int main(void) {
int r = gpio_is_valid(31);
if (r == -1) {
perror("GPIO address is invalid.\n");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
My Makefile looks as
build: gpio
LDFLAGS = -Llinux
gpio:
$(CC) -o gpio.o src/gpio.c $(LDFLAGS)
Unfortunately I get "gpio.h not found" as error.
gpio.h is a Linux kernel header. It can not be used for user space programs.
Trying to compile an example of wrapping library from here
I had to include stdio.h and stdlib.h, and came to that code:
#define _GNU_SOURCE
#define _USE_GNU
#include <signal.h>
#include <execinfo.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
static void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printf("[bt] Execution path:\n");
for (i=0; i < trace_size; ++i)
printf("[bt] %s\n", messages[i]);
}
int ioctl(int fd, int request, void *data)
{
char *msg;
if (next_ioctl == NULL) {
fprintf(stderr, "ioctl : wrapping ioctl\n");
fflush(stderr);
// next_ioctl = dlsym((void *) -11, /* RTLD_NEXT, */ "ioctl");
next_ioctl = dlsym(RTLD_NEXT, "ioctl");
fprintf(stderr, "next_ioctl = %p\n", next_ioctl);
fflush(stderr);
if ((msg = dlerror()) != NULL) {
fprintf(stderr, "ioctl: dlopen failed : %s\n", msg);
fflush(stderr);
exit(1);
} else
fprintf(stderr, "ioctl: wrapping done\n");
fflush(stderr);
}
if (request == 1) { /* SCSI_IOCTL_SEND_COMMAND ? */
/* call back trace */
fprintf(stderr, "SCSI_IOCTL_SEND_COMMAND ioctl\n");
fflush(stderr);
show_stackframe();
}
return next_ioctl(fd, request, data);
}
and Makefile
#
# Makefile
#
all: libs test_ioctl
libs: libwrap_ioctl.so
libwrap_ioctl.so: wrap_ioctl.c
rm -f libwrap_ioctl.so*
gcc -fPIC -shared -Wl,-soname,libwrap_ioctl.so.1 -ldl -o libwrap_ioctl.so.1.0 wrap_ioctl.c
ln -s libwrap_ioctl.so.1.0 libwrap_ioctl.so.1
ln -s libwrap_ioctl.so.1 libwrap_ioctl.so
clean:
rm -f libwrap_ioctl.so* test_ioctl
and stuck in these errors, despite dlfcn.h is included.
~/my_src/native/glibc_wrapper > make
rm -f libwrap_ioctl.so*
gcc -fPIC -shared -Wl,-soname,libwrap_ioctl.so.1 -ldl -o libwrap_ioctl.so.1.0 wrap_ioctl.c
wrap_ioctl.c: In function ‘ioctl’:
wrap_ioctl.c:26: error: ‘next_ioctl’ undeclared (first use in this function)
wrap_ioctl.c:26: error: (Each undeclared identifier is reported only once
wrap_ioctl.c:26: error: for each function it appears in.)
make: *** [libwrap_ioctl.so] Ошибка 1
dlfcn.h itself doesn't define any symbol with name next_smth. (In SUS, dlfcn.h only defines several dl* functions and RTLD_ macro: http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html)
You should define this as pointer to function in your program code in explicit way. Something like this: (taken from https://port70.net/svn/misc/remac/remac.c or from https://github.com/itm/forward-sensor/blob/master/preload.c or ... any google search for "next_ioctl"):
static int (*next_ioctl) (int fd, int request, void *data) = NULL;
Or, if you want a collective blog-reading session, there is additional line in the blog post with ioctl overloading: http://scaryreasoner.wordpress.com/2007/11/17/using-ld_preload-libraries-and-glibc-backtrace-function-for-debugging/ (just before first huge code fragment)
Then, declare a function pointer to hold the value
of the “real” ioctl() function from glibc:
static int (*next_ioctl)(int fd, int request, void *data) = NULL;
Then declare your replacement ioctl function:
You missed to declare next_ioctl.
Just add
void * next_ioctl = NULL;
int (*next_ioctl) (int, int, ...) = NULL;
to main().
I have to compile two independent processes-sendfdsock.c and recvfdsock.c using make file. Both the files have there own main function. This means they are independent and I have to compile them as two different binaries. This is my make file:
compileAll:sendfdsock recvfdsock
sendfdsock:sendfdsock.o
gcc -o sendfdsock sendfdsock.o
sendfdsock.o:sendfdsock.c accessories.h
gcc -c sendfdsock.c
recvfdsock.o:recvfdsock.c accessories.h
gcc -c recvfdsock.c
recvfdsock:recvfdsock.o
gcc -o recvfdsock recvfdsock.o
Here I have made a compileAll target which compiles both the files.
Both files need to use accessories.h. As mention in GNU Make Doc - A simple Make file. I wrote this make file.
accessories.h :
#include <malloc.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <error.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <stropts.h>
#define PORT "4444" //port we are listening on
int sendall(int fd, char *buf, int *len);
int recvall(int fd, char *buf, int *len);
void logp(int typ, char* msg);
void errorp(char *where, int boolean, int errn,char *what);
accessories.c :
#include "accessories.h"
void logp(int typ, char* msg) // typ --> type(category) of message [1-Normal Log, 2-Warning(any unexpected thing happened), 3-Error, 4-Debugging Log ]
{
int fd;
time_t now;
ssize_t wlength=0;
char * dat;
char * str;
int size = 45+strlen(msg);//14+24+5+sizeof msg+1
str= (char *) malloc(size);
time(&now);//system time in seconds
dat = ctime(&now); // converting seconds to date-time format
dat = strtok(dat,"\n");
//Appending type of log
switch(typ)
{
case 1:
strcpy(str,"__LOG__ | ");
strcat(str,dat);
break;
case 2:
strcpy(str,"__WARN__ | ");
strcat(str,dat);
break;
case 3:
strcpy(str,"__ERR__ | ");
strcat(str,dat);
break;
case 4:
strcpy(str,"__DEBUG__ | ");
strcat(str,dat);
break;
default:
strcpy(str,"__UNDEF__ | ");
strcat(str,dat);
break;
}
strcat(str," | ");
strcat(str,msg);//appending message
strcat(str,"\n");
fd = open("log", O_WRONLY | O_CREAT | O_APPEND, 0644); // should be opened somewhere else
if (fd == -1)
printf("Could not open log - %s\n",strerror(errno));
else
{//need to add lock to the file and printing error message
while ( wlength < strlen(str) )
{
wlength = write(fd, str,strlen(str));
if (wlength == -1)
{
printf("Error : writing log\n");
break;
}
}
}
}
int sendall(int fd, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = send(fd, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
int recvall(int fd, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = recv(fd, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
void errorp(char *where, int boolean, int errn,char *what)
{
char errmsg[21+strlen(where)];
strcpy(errmsg,"Where - ");
strcat(errmsg,where);
strcat(errmsg," | Error - ");
if(boolean == 1)//we got error number
{
strcat(errmsg,strerror(errn));
//fprintf(stderr,"ERROR - In %s and error is %s\n",where ,strerror(errn));
logp(3,errmsg);
}
else if(boolean == 0)//we got a message
{
strcat(errmsg,what);
//fprintf(stderr,"ERROR - In %s and error is %s\n",where ,what);
logp(3,errmsg);
}
else//we got nothing
{
strcat(errmsg,"No Message");
//fprintf(stderr,"ERROR - In %s\n",where);
logp(3,errmsg);
}
}
Initially everything work fine but when I trid to use any function which is defined in accessories.c compilation give me error.
For example I use the log function in sendfdsock.c :
#include "accessories.h"
#define CONTROLLEN CMSG_LEN(sizeof(int))
static struct cmsghdr *cmptr = NULL; /* malloc'ed first time */
int send_err(int fd, int errcode, const char *msg);
int send_fd(int fd, int fd_to_send);
int main(int argc, char const *argv[])
{
logp(1,"started"); //This function is defined in accessories.c
int fd_to_send;
if((fd_to_send = open("vi",O_RDONLY)) < 0)
printf("vi open failed");
struct sockaddr_un address;
int socket_fd, nbytes;
char buffer[256];
........
Output of the compilation is:
abhi#abhi-me:~/bridge/server$ make compileAll
gcc -c sendfdsock.c
sendfdsock.c: In function ‘send_fd’:
sendfdsock.c:111:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘ssize_t’ [-Wformat]
sendfdsock.c:114:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘ssize_t’ [-Wformat]
gcc -o sendfdsock sendfdsock.o
sendfdsock.o: In function `main':
sendfdsock.c:(.text+0x32): undefined reference to `logp'
collect2: ld returned 1 exit status
make: *** [sendfdsock] Error 1
abhi#abhi-me:~/bridge/server$
Why undefined reference to logp error?
Why I don't write accessories.o in final linking:
But as this example is given in GNU Make Doc:
In this example, all the C files include ‘defs.h’, but
only those defining editing comminclude ‘command.h’, and only
low level files that change the editor buffer include 'buffer.h':
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
Here while linking all the files in edit they don't write defs.o or buffer.o. Means while linking they are not including object files of header files. Also they have not written any target like: defs.o or buffer.o
Why?
You just missed accessories.o in both linking targets. Something like this:
accessories.o: accessories.c
sendfdsock: sendfdsock.o accessories.o
$(CC) -o $# $(CFLAGS) $(LDFLAGS) $+
Also, consider using the built-in rules, just modify their parameters, if needed. See make -p for the full list (and makes infopage)
You misunderstand the relationship between source files, header files and object files.
Suppose I have the following four files:
//foo.h
#define PI 3.1
//bar.h
void func();
//bar.c
#include "foo.h"
#include "bar.h"
void func()
{
...
}
//baz.c
#include "foo.h"
#include "bar.h"
int main()
{
func();
}
(I left out the header guards, I presume you know about those.) I must use the compiler to produce an object file from each source file: bar.c -> bar.o and baz.c -> baz.o. I don't have to make object files from the headers foo.h and bar.h, those will simply be #included by any source file that needs them. Then I link the object files together to form an executable:
baz: bar.o baz.o
gcc -o baz bar.o baz.o
bar.o: bar.c foo.h bar.h
gcc -c bar.c
baz.o: baz.c foo.h bar.h
gcc -c baz.c
If I neglect to link bar.o into the executable, I'll get a linker error when the linker gets to the place where baz calls func() and the linker doesn't know what to put there (because it lacks the definition of func() in bar.o):
baz.o: In function `main':
baz.c:(.text+0x32): undefined reference to `func()'
So the GNU Make doc is correct, and as Alex said, your rule should have:
sendfdsock:sendfdsock.o accessories.o
...
accessories.o: accessories.c accessories.h
...
(Incidentally, once you get this makefile working, we can show you how to make it more concise.)