Access main program from shared library in C - c

After some googling, I got shared libraries working quite well. I can open my module with dlopen and load functions with dlsym. However, this is always running functions from the library in the program, how do I use functions from my program in the library?
My simplified code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int twice(int a){
return a*2;
}
int main(int argc, char ** argv){
char *plugin_name;
void *plugin;
int (*init)();
if(argc<2){
printf("give lib name\n");
return 0;
}
plugin = dlopen (argv[1], RTLD_NOW);
if (!plugin)
{
printf("Cannot load %s: %s\n",argv[1], dlerror ());
return 0;
}
init = dlsym (plugin, "init");
char * result = dlerror ();
if (result)
{
printf("Cannot find init in %s: %s\n", plugin_name, result);
return 0;
}
int res = init();
printf("result: %i\n",res);
return 0;
}
plugin.c
int init()
{
return twice(4);
}
Makefile:
all: main lib
main: main.c
gcc -ldl -o main main.c
lib: plugin.c
gcc -shared -o plugin.so plugin.c
And I run it with:
./main ./plugin.so

With Linux, glibc, and GNU ld you can run -rdynamic to your executable link flags. This will make all symbols in your executable visible to loadable modules, as if it were a shared library.
Note that this is not necessarily portable to other Unix-like systems.

Related

BCM2835_st_read() returns zero - confused

bcm2835 init works fine, as does all the GPIO & bcm2835_delay and the like.
RPi4 & Pi400, Raspbian "Bullseye", bcm2835 1.71, Libcap installed, added the program name etc
And I've compiled with Geany
gcc -Wall -o "%e" "%f" -pthread $(pkg-config gtk+-3.0 --cflags --libs) -export-dynamic -l bcm2835 -l png -DBCM2835_HAVE_LIBCAP
Here's code:
// bcm_timer.c
//
// Example program for bcm2835 library system time
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <bcm2835.h>
uint64_t now = 0;
uint64_t then = 0;
uint rescode = 0;
int main(int argc, char **argv)
{
// Init GPIO
if ( ! bcm2835_init() )
{
printf("Fail 0x%X ", errno);
return -1;
}
then = bcm2835_st_read();
bcm2835_delay(500);
now = bcm2835_st_read();
printf("Then = 0x%lluX, Now = 0x%lluX \n", then, now) ;
bcm2835_close();
return 0;
}
Here's output:
xxx#raspberrypi:~/Develop/c/test $ ./bcm_timer
Then = 0x0X, Now = 0x0X

Multiple dlopen and RTLD_NEXT

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

ppu-ld cannot find -lspe

I am trying to compile the code below, on CELL BE Simulator(mambo).
//hello.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <libspe.h>
#include <sched.h>
extern spe_program_handle_t hello_spu;
spe_gid_t gid;
speid_t speids[8];
int status[8];
int main(int argc, char *argv[]){
int i;
printf("Hello World!\n");
gid = spe_create_group (SCHED_OTHER, 0, 1);
if (gid == NULL) {
fprintf(stderr, "Failed spe_create_group(errno=%d)\n", errno);
return -1;
}
if (spe_group_max (gid) < 8) {
fprintf(stderr, "System doesn't have eight working SPEs. I'm leaving.\n");
return -1;
}
for (i = 0; i < 8; i++) {
speids[i] = spe_create_thread (gid, &hello_spu,NULL, NULL, -1, 0);
if (speids[i] == NULL) {
fprintf (stderr, "FAILED: spe_create_thread(num=%d, errno=%d)\n",i, errno);
exit (3+i);
}
}
for (i=0; i<8; ++i){
spe_wait(speids[i], &status[i], 0);
}
__asm__ __volatile__ ("sync" : : : "memory");
return 0;
}
//Makefile
########################################################################
# Target
########################################################################
PROGRAM_ppu64 = hello
########################################################################
# Local Defines
########################################################################
IMPORTS = ../spu/hello_spu.a -lspe
########################################################################
# make.footer
########################################################################
include /opt/cell/sdk/buildutils/make.footer
After compiling the this, it provides with the following output.
$make
/opt/cell/toolchain/bin/ppu-gcc -W -Wall -Winline -I. -I /opt/cell/sysroot usr/include -I /opt/cell/sysroot/opt/cell/sdk/usr/include -mabi=altivec -maltivec -O3 -c
hello.c
hello.c: In function 'main':
hello.c:12: warning: unused parameter 'argc'
hello.c:12: warning: unused parameter 'argv'
/opt/cell/toolchain/bin/ppu-gcc -o hello hello.o -L/opt/cell/sysroot/usr/lib64 -L/opt/cell/sysroot/opt/cell/sdk/usr/lib64 -R/opt/cell/sdk/usr/lib64 ../spu/hello_spu.a -lspe
/opt/cell/toolchain/bin/ppu-ld: cannot find -lspe
collect2: ld returned 1 exit status
make: *** [hello] Error 1
'ld' cannot find the -lspe library.The "/opt/cell/sysroot/usr/lib" directory contains following libraries and files,
alf, libblas.so, libc_stubs.a, libieee.a, libnetpbm.so.10, libnuma.so.1, libsimdmath.so.3,
crt1.o, libblas.so.1, libdl.a, libm.a, libnetpbm.so.10.35, libpthread.a, libsimdmath.so.3.0.3,
crti.o, libBrokenLocale.a, libdl.so, libmass.a, libnldbl_nonshared.a, libpthread_nonshared.a, libspe2.so,
crtn.o, libBrokenLocale.so, libg.a, libmassv.a, libnsl.a, libpthread.so, libspe2.so.2,
gconv, libbsd.a, libgmp.a, libmcheck.a, libnsl.so, libresolv.a, libspe2.so.2.2.0,
gcrt1.o, libbsd-compat.a, libgmp.so, libmp.a, libnss_compat.so, libresolv.so, libthread_db.so,
libalf.a, libc.a, libgmp.so.3, libmpfr.a, libnss_dns.so, librpcsvc.a, libutil.a,
libalf.so, libcidn.so, libgmp.so.3.3.3, libmp.so, libnss_files.so, librt.a, libutil.so,
libalf.so.3, libc_nonshared.a, libgmpxx.a, libmp.so.3, libnss_hesiod.so, librtkaio.a, Mcrt1.o,
libalf.so.3.0.0, libcrypt.a, libgmpxx.so, libmp.so.3.1.7, libnss_nisplus.so, librt.so, Scrt1.o,
libanl.a, libcrypt.so, libgmpxx.so.3, libm.so, libnss_nis.so, libsimdmath.a,
libanl.so, libc.so, libgmpxx.so.3.0.5, libnetpbm.so, libnuma.so, libsimdmath.so
How do I link libspe2.so to libspe.so?
Please, help.
You don't link those together. They are different things. You either update your makefile to use -lspe2 if that's the version of the library you want or you install the version of the library that installs the libspe.so library.

How to link with linux/gpio.h?

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.

Compilation fails with "error: ‘next_ioctl’ undeclared (first use in this function)" despite I included dlfcn.h

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().

Resources