When I'm trying to use the DYLD_INSERT_LIBRARIES environmental variable to insert a .dylib file to a running process on macOS Mojave, I'm encountering a segmentation fault.
System version:
macOS 14.4.4
Compiler version:
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
debug_malloc.c (compiles to the dylib file):
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };
void* pMalloc(size_t size) //would be nice if I didn't have to rename my function..
{
printf("Allocated: %zu\n", size);
return malloc(size);
}
DYLD_INTERPOSE(pMalloc, malloc);
The running process is a test program written in C, which does nothing except calling malloc once:
test.c (compiles to test)
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
printf("before malloc\n");
void *a= malloc(900);
return 0;
}
Compile & execute commands
gcc -odbg.dylib -dynamiclib ./debug_malloc.c
gcc -otest ./test.c
DYLD_INSERT_LIBRARIES=./dbg.dylib ./test
Running the last command yields
Segmentation fault: 11
Whereas just running test without dylib preload works fine.
Related
I want to to run a simple program, using vs code, which includes three files: main.c item.c item.h.
I understand that I there is a way to link things together, but I don't know how. Can you explain me how to do it?
I've tried also to add the extension to make a project, but I didn't understand how to.
Here's the code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "item.h"
int main () {
int a = 2;
int b = 3;
int res;
res = prod(a,b);
printf("%d ", res);
return 0;
}
item.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "item.h"
int prod(int a, int b) {
return a*b;
}
item .h
#ifndef ITEM_H
#define ITEM_H
int prod(int a, int b);
#endif
I don't know if you are using Windows or Linux or Mac, I'm going to explain it for Linux but the method is similar for the others.
First of you go on VS Code, then you click on new file and rename it "makefile", then you write this:
link: item.o main.o
gcc item.o main.o -o programName
main.o:
gcc -c main.c
item.o:
gcc -c item.c
clear:
rm -f item.o main.o programName //this one is to delete files faster
Once you wrote the makefile you write in the terminal the command make and you get the executable file for your program.
However in item.c you aren't using any of the library you included, you only need to include item.h; last thing, I don't know why you are doing the #ifndef thing but it seems a waste.
I used search.h for my c program, where I need to put #define _GNU_SOURCE to the first line in order to introduce multiple hash tables. But after that, errors like undefined reference to 'log10' and undefined reference to 'PQntuples' popped up. I certainly need all the packages there, how should I now compile the program? Any help would be deeply appreciated! Thanks.
The headers:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <string.h>
// library for psql
#include <libpq-fe.h>
#include <unistd.h>
#include <time.h>
#include <search.h>
int main(void){
char host[] = "localhost";
char port[] = "5432";
char db_name[] = "db_name";
char user[] = "test_usr";
char password[] = "123456";
sprintf(db_str, "host=%s port=%s dbname=%s user=%s password=%s",
host, port, db_name, user, password);
PGconn *db_connection = DBConnect(db_str);
struct hsearch_data htab;
hcreate_r(10, &htb);
ENTRY e, *ep;
e.key = "test";
e.data = (void *) 1;
hsearch_r(e, ENTER, &ep, &htab);
}
And this was how I compile the file:
gcc -Wall -Wextra -I/home/userX/postgresql/include -L/home/userX/postgresql/lib -lm -lpq -g my_program.c
Specifiy the libraries at the end of the command line
gcc -Wall -Wextra -I/home/userX/postgresql/include \
-L/home/userX/postgresql/lib -g my_program.c -lpq -lm
// ^^^^^^^^
gcc looks at required symbols left to right on the command line.
With the libraries before the source files, when gcc processes the -llib argument it does not have any requirements and therefore does not "extract" any function from the library.
I just started to learn Linux kernel programming, and one of the tutorials use the linux/init.h and the linux/module.h. and init.h holds the printk function, but init.h does not exists.
#include <linux/module.h>
#include <linux/init.h> // source file does not exists
int main(int argc, char const *argv[])
{
printk(); // undefined
return 0;
}
// gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)
Is there a replacement for that?
Has anybody tried using the i2c_smbus_write_byte or any similar function on Raspberry Pi 4?
I can't get it compile it fails at the linking with not finding it.
I'm using it as described here: http://synfare.com/599N105E/hwdocs/rpi/rpii2c.html
All the headers recommended are there is and also the -li2c in the Makefile.
Can anybody tell what the problem can be? I have no clue at the moment.
Might be worth checking to see if libi2c-dev is present on your system.
sudo apt-get install libi2c-dev
may be all that you need.
The page you are linking to says:
With the Buster version, as of june 2019, the necessary details for
using i2c_smbus_write_byte_data() and siblings, require the following
include statements:
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
Using fgrep you can confirm that the function is declared in the /usr/include/i2c/smbus.h:
# cd /usr/include; fgrep -R i2c_smbus_write_byte *
i2c/smbus.h:extern __s32 i2c_smbus_write_byte(int file, __u8 value);
i2c/smbus.h:extern __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
So this should work:
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
int main(void) {
int i2c = open("/dev/i2c-1", O_RDWR);
i2c_smbus_write_byte(i2c, 1);
close(i2c);
return 0;
}
I tested that this example compiles successfully in the latest Raspbian Buster Lite:
gcc test.c -otest -li2c
If you are using g++ instead of gcc, then you should wrap the include directives with extern "C":
extern "C" {
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
}
i kept the essential.
caller.exe loads the dll, then calls the function dll_init declared inside the dll.
this last function calls the function "get_ptr" declared in the common library which should return a pointer to the global variable.
the issue is:
whenever caller.exe calls "get_ptr" it returns a valid pointer same as the one which was previously allocated on caller.exe start fine.
whenever the dll thru it function "dll_init" (after bein called by
caller.exe) calls "get_ptr" (knowing that the dll is linked to the
static lib) it return NULL pointer.
what i am missing ?
libcommon.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/***************header****************/
int *get_ptr(void);
int set_ptr(void);
/**********************************/
int *global=NULL;
//extern __declspec(dllimport) int *global; doesnt work
int set_ptr() {
global = (int *) malloc(sizeof(int));
printf("global allocated to %p\n",global);
*global=485; //random value
return 0;
}
int *get_ptr() {
return global;
}
here is compiling commands (makefile simplified):
gcc.exe -c libcommon.c -o libcommon.o -m32
ar r libcommon.a libcommon.o
ranlib libcommon.a
module.c
#include <windows.h>
#include <stdio.h>
#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif
DLLIMPORT int dll_init(void) {
int *ptr=(int *) get_ptr();
puts("dll run");
printf("from dll global: %p\n",ptr);
puts("dll end");
return 0;
}
compiling:
gcc.exe -c module.c -o module.o -m32 -DBUILDING_DLL=1
gcc.exe -shared module.o -o module.dll -static-libgcc -lws2_32 -m32 -s -L"." -lcommon -Wl,--output-def,libmodule.def,--out-implib,libmodule.a,--add-stdcall-alias
caller.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef void(voidfunc)(void);
voidfunc *fct_ptr;
int test(int a) {
printf("%d",a++);
}
int main() {
set_ptr();
printf("::%p\n",get_ptr());
/* Load the dll then call dll_init */
HMODULE dllptr = LoadLibrary("module.dll");
if (dllptr != NULL) {
fct_ptr = (voidfunc *) GetProcAddress(dllptr, "dll_init");
puts("loaded");
if (fct_ptr != NULL)
fct_ptr();
FreeLibrary(dllptr);
}
}
compiling:
gcc.exe caller.c -o caller.exe -m32 -static-libgcc -lws2_32 -L. -lcommon -m32
I believe you have 2 different places in memory named global. One is
in caller since you compiled it statically with lcommon. Data is set
there via set_ptr. Second is in module space (for the same reasons),
but you never called set_ptr() there. Check memory address of global
inside dll_init and in main. If they are not the same, you then need
to call set_ptr in your `dll_init``
he's right, i think the common static library linked with both exe and dll was a wrong idea.
the solution is here: .dll Plugin that uses functions defined in the main executable
Any other suggestions are welcome