Please consider the below code
shared.c
#include <stdio.h>
void printCharArray(char *someArray){
if (!someArray){
printf("someArray is null!\n");
} else {
printf("Array is %s\n", someArray);
}
}
and question.c:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB "/tmp/some.so"
void *handle = 0;
void localfunc();
int main(){
handle = dlopen(LIB, RTLD_LAZY);
if (!handle){
fprintf(stderr, "dlopen err\n");
exit(1);
}
dlerror();
void (*printCharArray)() = dlsym(handle, "printCharArray");
char *err = dlerror();
if (err){
fprintf(stderr, "%s\n", err);
exit(1);
}
printCharArray(); // some work
localfunc();
}
void localfunc(){
puts("localfunc");
dlerror();
void (*printCharArray)() = dlsym(handle, "printCharArray"); // <- This
char *err = dlerror();
if (err){
fprintf(stderr, "%s\n", err);
exit(1);
}
printCharArray(); // do some work in localfunc
}
Compile and run
2035 gcc -shared -o /tmp/some.so shared.c -fPIC
2036 gcc -ldl question.c
$ ./a.out
someArray is null!
localfunc
someArray is null!
Notice how in localfunc I call dlsym again to import "printCharArray" which was previously done in main(). I am looking to avoid this - how can I make this method available after the 1st import? (iow, how can I make my 1st import to be available as a fn prototype for use anywhere in question.c?)
Declare the function pointer as a global variable, rather than local to main().
Give it the correct parameter declaration so the call matches the definition. And then call it with an argument.
There's no point in calling dlerror() before calling dlsym(). And it doesn't do anything useful if you don't assign the result to something.
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB "/tmp/some.so"
void *handle = 0;
void localfunc();
void (*printCharArray)(char *);
int main(){
handle = dlopen(LIB, RTLD_LAZY);
if (!handle){
fprintf(stderr, "dlopen err: %s\n", dlerror());
exit(1);
}
printCharArray = dlsym(handle, "printCharArray");
if (!printCharArray) {
char *err = dlerror();
printf(stderr, "%s\n", err);
exit(1);
}
printCharArray(NULL); // some work
localfunc();
}
void localfunc(){
puts("localfunc");
printCharArray("something"); // do some work in localfunc
}
Related
I wrote a simple ebpf so I opened it with obj = bpf_object__open_file(filename, NULL);
then when I do prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");
This function returns NULL and prints message that printf("finding a prog in obj file failed\n");. so basically my function or program could not be found in object file, I like to know what might be the reason for this so I also found after the call to bpf_object__open_file my errno got set to 2 so I like to know what is exactly happening why my errno set to 2 right after bpf_object__open_file and I made sure that file does exists
this condition is also not fullfilling
if (libbpf_get_error(obj)) {
printf("ERROR: opening BPF object file failed\n");
This is a loader program
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <sys/resource.h>
#include <errno.h>
//#include "trace_helpers.h"
#ifdef __mips__
#define MAX_ENTRIES 6000 /* MIPS n64 syscalls start at 5000 */
#else
#define MAX_ENTRIES 1024
#endif
/* install fake seccomp program to enable seccomp code path inside the kernel,
* so that our kprobe attached to seccomp_phase1() can be triggered
*/
static void install_accept_all_seccomp(void)
{
struct sock_filter filter[] = {
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_SECCOMP, 2, &prog))
perror("prctl");
}
int main(int ac, char **argv)
{
struct bpf_link *link = NULL;
struct bpf_program *prog;
struct bpf_object *obj;
int key, fd, progs_fd;
const char *section;
char filename[256]="/home/fawad/bpf/linux-5.13.1/samples/bpf/kern5.o";
printf("%s\n",filename);
FILE *f;
//snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
printf("errono before %d\n",errno);
obj = bpf_object__open_file(filename, NULL);
printf("errono after %d\n",errno);
if (libbpf_get_error(obj)) {
printf("ERROR: opening BPF object file failed\n");
return 0;
}
printf("errno before %d\n",errno);
prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");
printf("errno after %d\n",errno);
if (!prog) {
printf("finding a prog in obj file failed\n");
goto cleanup;
}
/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}
progs_fd = bpf_object__find_map_fd_by_name(obj, "progs");
if (progs_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}
bpf_object__for_each_program(prog, obj) {
section = bpf_program__section_name(prog);
/* register only syscalls to PROG_ARRAY */
if (sscanf(section, "kprobe/%d", &key) != 1)
continue;
fd = bpf_program__fd(prog);
bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY);
}
install_accept_all_seccomp();
f = popen("dd if=/dev/zero of=/dev/null count=5", "r");
(void) f;
// read_trace_pipe();
cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return 0;
}
and this is ebpf program
/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
//#include "syscall_nrs.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
#ifdef __mips__
__uint(max_entries, 6000); /* MIPS n64 syscalls start at 5000 */
#else
__uint(max_entries, 1024);
#endif
} progs SEC(".maps");
/*SEC("kprobe/SYS__NR_write")
int bpf_prog2(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] == 512) {
char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}*/
SEC("kprobe/__seccomp_filter")
int bpf_prog1(struct pt_regs *ctx)
{
int sc_nr = (int)PT_REGS_PARM1(ctx);
/* dispatch into next BPF program depending on syscall number */
bpf_tail_call(ctx, &progs, sc_nr);
/* fall through -> unknown syscall */
if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) {
char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n";
bpf_trace_printk(fmt, sizeof(fmt), sc_nr);
}
return 0;
}
SEC("kprobe/__x64_sys_write")
/* we jump here when syscall number == __NR_write */
//PROG(SYS__NR_write)(struct pt_regs *ctx)
int __x64_sys_write(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] == 512) {
char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}
/*
PROG(SYS__NR_read)(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] > 128 && sd.args[2] <= 1024) {
char fmt[] = "read(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}
#ifdef __NR_mmap2
PROG(SYS__NR_mmap2)(struct pt_regs *ctx)
{
char fmt[] = "mmap2\n";
bpf_trace_printk(fmt, sizeof(fmt));
return 0;
}
#endif
#ifdef __NR_mmap
PROG(SYS__NR_mmap)(struct pt_regs *ctx)
{
char fmt[] = "mmap\n";
bpf_trace_printk(fmt, sizeof(fmt));
return 0;
}
#endif
*/
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
compiling userspace loader like
clang -L /usr/lib/usr/lib64/ -I /usr/include/ -I /usr/lib/usr/include/ tracex5_user.c -o user1.o -lbpf
compiling kernel ebpf program like
sudo clang -Wall -O2 -g -target bpf -I /usr/lib/usr/include -I /usr/include/x86_64-linux-gnu/ -I /usr/include/linux/ -c syscall_tp_kern.c -o kern5.o
Please try this command
bpftool prog load bpf_test.o /sys/fs/bpf/vfs_create
In my scenario, I got the error:
libbpf: failed to find BTF for extern 'PT_REGS_PARM2': -3
I have this little program that I took from some example around the web:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int
main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libzapi_v2.so.1", RTLD_LAZY);
if (!handle) {
printf("no handle \n");
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
fprintf(stderr, "handle is here \n");
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
I compile it with gcc -rdynamic -o np np.c and then when I run with ./np
I get the following error:
ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/rtld.c:1046
Abort (core dumped)
I search and searched for people with similar issues, but can't find anything. Can anyone offer some troubleshooting suggestions ?
This is on latest freebsd.
I am having trouble compiling my program.
The error message is: undefined reference to `_fcloseall', I think it could be a missing library file at the beginning. It might be also useful to know that I am programming on Windows 8.1 + Cygwin. Which library could be missing or do you see any other mistake?
Here is the code:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void cleanup1();
void cleanup2();
int main(int argc, char *argv[])
{
FILE * file;
if(argc < 2){
printf("\ncommand bsp10085 <file>");
exit(1);
}
assert(atexit(cleanup1) == 0);
assert(atexit(cleanup2) == 0);
if((datei = fopen(argv[1], "r")) != NULL){
printf("\nfile %s is being processed ..",argv[1]);
fclose(datei);
}
else
printf("\nfile '%s' is missing. ", argv[1]);
}
void cleanup1(){
printf("\nCleanup the rest");
}
void cleanup2(){
printf("\nClose all open files");
fflush(NULL);
_fcloseall();
}
I tried to compile your code (in ubuntu though) and i also got a warning: warning: implicit declaration of function ‘fcloseall’ [-Wimplicit-function-declaration] fcloseall();
I think that if you add
#define _GNU_SOURCE
before
#include<stdio.h>
your program should work fine. This is your code after i changed some other warnings as well:
#define _GNU_SOURCE
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void cleanup1();
void cleanup2();
int main(int argc, char *argv[])
{
FILE *datei;
if(argc < 2){
printf("\ncommand bsp10085 <file>");
exit(1);
}
assert(atexit(cleanup1) == 0);
assert(atexit(cleanup2) == 0);
if((datei = fopen(argv[1], "r")) != NULL){
printf("\nfile %s is being processed ..",argv[1]);
fclose(datei);
}
else
printf("\nfile '%s' is missing. ", argv[1]);
return 0;
}
void cleanup1(){
printf("\nCleanup the rest");
}
void cleanup2(){
printf("\nClose all open files");
fflush(NULL);
fcloseall();
}
I am trying to test out using papi, but I am getting some errors that I don't understand why they're occurring. I couldn't find anything online for them. The code is below
I am using PAPI and C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <memory.h>
#include <malloc.h>
#include "papi.h"
#define INDEX 100
static void test_fail(char *file, int line, char *call, int retval);
int main(int argc, char **argv) {
extern void dummy(void *);
float matrixa[INDEX][INDEX], matrixb[INDEX][INDEX], mresult[INDEX] [INDEX];
float real_time, proc_time, mflops;
long long flpins;
int retval, status = 0;
int i,j,k;
long_long values[1];
FILE *file;
file = fopen("output.txt","w");
retval = PAPI_library_init(PAPI_VER_CURRENT);
int EventSet = PAPI_NULL;
PAPI_create_eventset(&EventSet);
if(PAPI_add_event(EventSet, PAPI_LD_INS) != PAPI_OK)
{
fprintf(file,"PAPI failed to add Load/Store instructions\n");
}
if (PAPI_state(EventSet, &status) != PAPI_OK)
fprintf(file,"state fail\n");
fprintf(file, "State is now %d\n", status);
if (PAPI_start(EventSet) != PAPI_OK)
fprintf(file,"start fail\n");
if (PAPI_state(EventSet, &status) != PAPI_OK)
fprintf(file,"state2 fail\n");
fprintf(file, "State is now %d\n", status);
/* Initialize the Matrix arrays */
for ( i=0; i<INDEX; i++ ){
mresult[0][i] = 0.0;
matrixa[0][i] = matrixb[0][i] = rand()*(float)1.1; }
if((retval=PAPI_flops( &real_time, &proc_time, &flpins, &mflops))<PAPI_OK)
fprintf(file,"retval failed\n");
for (i=0;i<INDEX;i++)
{
for(j=0;j<INDEX;j++)
{
for(k=0;k<INDEX;k++)
{
mresult[i][j]=mresult[i][j] + matrixa[i][k]*matrixb[k][j];
}
}
}
if((retval=PAPI_flops( &real_time, &proc_time, &flpins, &mflops)) <PAPI_OK)
{
fprintf(infile,"ret2 failed\n");
}
fprintf(file,"Real_time:\t%f\nProc_time:\t%f\nTotal flpins:\t%lld \nMFLOPS:\t\t%f\n",
real_time, proc_time, flpins, mflops);
fflush(file);
fprintf(file,"%s\tPASSED\n", __FILE__);
fflush(file);
if (PAPI_read(EventSet, values) != PAPI_OK)
{fprintf(file,"read fail\n");}
if (PAPI_stop(EventSet, values) != PAPI_OK)
{fprintf(file,"stop fail\n");}
if (PAPI_cleanup_eventset(&EventSet) != PAPI_OK)
{fprintf(file,"cleanup fail\n");}
if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
{fprintf(file,"destroy fail\n");}
fprintf(file,"\nValues is %f\n", values[0]);
fflush(file);
fclose(file);
PAPI_shutdown();
exit(0);
}
In the output file, I just see the below:
State is now 1
State is now 2
retval failed
ret2 failed
Real_time: 0.000000
Proc_time: 0.000000
Total flpins: 99
MFLOPS: 0.000000
PAPI_flops.c PASSED
cleanup fail
destroy fail
I don't understand why ret, ret2, cleanup and destroy failed. Why?
You can use the PAPI_perror or PAPI_strerror functions to get the error message associated with an error return value. This may help track down why, for example, PAPI_flops is failing. (It could be that there is no support on your system for the required events.)
The reason why PAPI_cleanup_eventset is failing though is because it takes just the integer EventSet, not a pointer to it.
I'd strongly recommend emitting the error return value strings, and also compiling with warnings on — the latter would likely have found the issue with the wrong parameter type.
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().