How do I make an FFI call with a char** pointer? - c

I'm trying to make an FFI call but I get a segmentation fault inside the function called by ffi_call (gtk_init in this case). I'm not sure where I screwed up.
/*
* gtk_init.cc
*/
#include <ffi.h>
#include <gtk/gtk.h>
void test();
int main(int argc, char *argv[]) {
test();
return 0;
}
void test() {
ffi_cif cif;
ffi_type *arg_types[2];
void *arg_values[2];
ffi_status status;
ffi_arg result;
arg_types[0] = &ffi_type_uint;
arg_types[1] = &ffi_type_pointer;
status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_void, arg_types);
if (status != FFI_OK) {
printf("Failed to prep_ffi\n");
return;
}
int argc = 4;
char **argv = (char**)malloc(sizeof(char*) * argc);
argv[0] = strcpy((char*)malloc(sizeof(char) * 6), "test");
argv[1] = strcpy((char*)malloc(sizeof(char) * 13), "--gtk-debug");
argv[2] = strcpy((char*)malloc(sizeof(char) * 6), "misc");
argv[3] = strcpy((char*)malloc(sizeof(char) * 6), "last");
arg_values[0] = &argc;
arg_values[1] = &argv;
ffi_call(&cif, FFI_FN(gtk_init), &result, arg_values);
// gtk_init(&argc, &argv);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
free(argv[i]);
}
free(argv);
}
The complete gist can be found here.

The problem is that ffi_call() take the address of the argument as gtk_init() take int * and char *** you need to take the address of these so that give int ** and char ****, fun ?
As said in comment gtk_init() also expect argv to be NULL terminated.
And the final problem is that ffi_type_uint is the wrong type you must use ffi_type_pointer in this case (and by the way int need ffi_type_sint).
So the final fixed code is:
#include <ffi.h>
#include <gtk/gtk.h>
void test(void);
int main(void) { test(); }
void test(void) {
ffi_type *arg_types[] = {&ffi_type_pointer, &ffi_type_pointer};
ffi_cif cif;
ffi_status status =
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, sizeof arg_types / sizeof *arg_types,
&ffi_type_void, arg_types);
if (status != FFI_OK) {
printf("Failed to prep_ffi\n");
return;
}
// bad we don't check malloc() !!! ;)
int argc = 4;
char **argv = malloc(sizeof *argv * (argc + 1));
#define X(x) strcpy(malloc(sizeof x), x);
argv[0] = X("test");
argv[1] = X("--gtk-debug");
argv[2] = X("misc");
argv[3] = X("last");
argv[4] = NULL;
#undef X
int *p_argc = &argc; // This is what expect gtk_init
char ***p_argv = &argv;
void *arg_values[] = {&p_argc, &p_argv}; // so ffi need their address
ffi_arg result;
ffi_call(&cif, FFI_FN(&gtk_init), &result, arg_values);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
free(argv[i]);
}
free(argv);
}
Disclaimer: Not tested.

Related

Passing an int to a pthread

Can't get the pthread's last parameter to pass through as an actual int. I would like to be able to access the 1 that is put in the last parameter of pthread_create. Any help would be greatly appreciated!
#include <pthread.h>
#include <unistd.h>
#include <malloc.h>
#define MAX 5
int arr[MAX];
int p0 = 0;
int p1 = 0;
int p2 = 0;
int p3 = 0;
int p4 = 0;
void *process(void *arg);
int main(int argc, char *argv[]) {
if(argc != 7) {
printf("must be 6 ints");
return -1;
}
int quantum = atoi(argv[1]);
p0 = atoi(argv[2]);
p1 = atoi(argv[3]);
p2 = atoi(argv[4]);
p3 = atoi(argv[5]);
p4 = atoi(argv[6]);
This below is the pthread I am referring to.
int *pointer0 = malloc(sizeof(*pointer0));
*pointer0 = p0;
/* intialize thread 1 */
pthread_t tid0;
pthread_attr_t attr0;
pthread_attr_init(&attr0);
pthread_create(&tid0, &attr0, process, 1);
pthread_join(tid0, NULL);
//if the time remaining of process is not zero, run process[i] again
return 0;
}
void *process(void *arg) {
//char **pointer = (char**) arg;
//int burst = **pointer;
int burst = 0;
//int i = atoi(arg);
printf("%ls", (int *)arg);
pthread_exit(NULL);
}
If you read the manual pages of pthread_create() function, you will notice that you are passing an int instead of a void* in the last argument.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
To solve this problem, create a variable to store the int value and pass it through the pthread_create() function using its address. Then, in the process() function, cast the argument to an int.
int main () {
// (...)
int arg = 1;
pthread_create(&tid0, &attr0, process, &arg);
// (...)
return 0;
}
void *process (void *arg) {
int arg = *((int *) arg);
// (...)
return NULL;
}
Now, notice that the variable arg I just declared in the main() function will be always available, once the program only exits the main() function at the end. If the pthread_create() function is called inside another function, it is highly recommended that you allocate the memory dynamically to ensure it is always available even if the function is exited. Do not forget to free the memory before exiting the process() function.
int foo () {
// (...)
int *arg = malloc( sizeof(int) );
if ( !arg ) {
fprintf(stderr, "error: allocating memory");
return 0;
}
*arg = 1;
pthread_create(&tid0, &attr0, process, arg);
// (...)
return 0;
}
void *process (void *arg) {
int value = *((int *) arg);
// (...)
free(arg);
return NULL;
}
If you want to pass more variables trough the pthread_create() function, declare a struct and repeat the same process.
typedef struct {
char name[50];
char surname[50];
int age;
} person_t;
int foo () {
// (...)
person_t *arg = malloc( sizeof(person_t) );
if ( !arg ) {
fprintf(stderr, "error: allocating memory");
return 0;
}
sprintf( arg->name , "Miguel" );
sprintf( arg->name , "Carvalho" );
arg->age = 22;
pthread_create(&tid0, &attr0, process, arg);
// (...)
return 0;
}
void *process (void *arg) {
person_t person = *((person_t *) arg);
printf( "%s; %s; %d\n", person.name, person.surname, person.age);
// (...)
free(arg);
return NULL;
}

My program only works when I declare an extra array

I'm building a simple shell for a class. There are two programs in my shell directory, called "alomundo" and "echo". "./alomundo" prints "Alo mundo!" to console, and ./echo executes the ubuntu echo with given args.
The thing is my program only works if I declare the char aux[15]. Notice I don't use it aux for nothing. Can anyone understand whats wrong?
An example input would be
./shell echo a b, alomundo, echo abc
The correct output is
a b
Alo mundo!
abc
The output when char aux[15] is not declared is just:
Alo mundo!
abc
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char aux[15]; // <---- GRRRR
int child; // will hold the childs PID after fork()
int i = 0; // counter to loop through this mains *argv[]
int t = 0; // auxiliar counter to loops
int arg_len; // will hold the length of each argument while the argument is being processed
int args = 0; // current number of arguments in the argv1 vector
int send = 0; // boolean to check if the command should be executed in the current loop or not
char *command; // string to hold the main command name
char *argv1[15]; // vector to hold the arguments passed to execve
for(i=1; i<argc; i++) {
arg_len = strlen(argv[i]);
argv1[args] = (char *) malloc(sizeof(char) * 25);
for(t=0; t<25; t++) {
argv1[args][t] = '\0';
}
if (argv[i][arg_len-1] == ',') {
argv[i][arg_len-1] = '\0';
send = 1;
}
else if (i == (argc-1)) {
send = 1;
}
if (args == 0) {
command = (char *) malloc(sizeof(char) * 255);
strcpy(command, "./");
strcpy(argv1[args], "./");
strcat(command, argv[i]);
}
strcat(argv1[args], argv[i]);
args++;
if (send) {
child = fork();
if (child == 0) {
argv1[args+1] = 0;
execve(command, &argv1[0], envp);
return 0;
}
else {
waitpid(child);
free(command);
for (t=0; t<args; t++) {
free(argv1[t]);
argv1[t] = NULL;
}
args = 0;
send = 0;
}
}
}
return 0;
}
waitpid(child) seems wrong. Try:
// ...
#include <sys/wait.h>
// ...
pid_t child;
int wstatus;
// ...
else {
wait(&wstatus);
envp is not declared. Try:
// ...
int main(int argc, char *argv[], char *envp[]) {
// ...
Off-by-one error in argv1 processing. Try:
// ...
if (child == 0) {
argv1[args] = 0;
execve(command, argv1, envp); // why use &argv1[0] ?
// ...
I think (3) is the culprit.
Compiling with different levels of optimisation (-O, etc) seems to affect whether or not the erroneous +1 causes a problem.

C: Finding duplicate string values in a file

So I have a file containing lets say:
cat
dog
cat
I am trying to go through the file, have it recognize there are two cat elements and one dog element, and then have in the same file edited as:
cat - 2
dog - 1
I already have all the words saved in an array of strings, char **wordList, and I am trying to sort them with qsort and then put it in the format as described above. My qsort functions are:
stringcmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
void wordSort(char **wordlist)
{
size_t strings_len = numwords - 1;
qsort(wordlist, strings_len, sizeof(char*), stringcmp);
wordFile(wordlist);
}
void wordFile(char **wordlist)
{
if((outFilePtr2 = fopen(outWords, "w")) != NULL)
{
for(x = 1; x < numwords; x++)
{
fputs(wordlist[x], outFilePtr2);
fputs("\n", outFilePtr2);
}
fclose(outFilePtr2);
}
else
{
printf("File\"%s\" could not be opened.\n", outWords);
}
}
It is not sorting anything in order though. How do I fix it?
The following program works with your definition of stringcmp (which seems correct):
int main (int argc, char *argv[]) {
int i;
qsort(argv, argc, sizeof(char *), &stringcmp);
for (i = 0; i != argc; i++) printf("%s\n", argv[i]);
}
Thus I suspect that you have a problem with the definition of char **wordList.
UPDATE
This version slightly modified/completed version of your program works for me:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *outWords = "outWords.txt";
char *wordList[] = { "cat", "dog", "cat" };
#define numwords (sizeof(wordList) / sizeof(wordList[0]))
FILE *outFilePtr2;
int x;
int stringcmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
void wordSort(char **wordlist)
{
qsort(wordlist, numwords, sizeof(char*), stringcmp);
wordFile(wordlist);
}
void wordFile(char **wordlist)
{
if((outFilePtr2 = fopen(outWords, "w")) != NULL)
{
for(x = 0; x < numwords; x++)
{
fputs(wordlist[x], outFilePtr2);
fputs("\n", outFilePtr2);
}
fclose(outFilePtr2);
}
else
{
printf("File\"%s\" could not be opened.\n", outWords);
}
}
int main() {
wordSort(wordList);
wordFile(wordList);
return 0;
}
I adapted the second argument of qsort (else the last string pointer would not be considered, and left unchanged). I also adapted the initialization x=0 of the for-loop in wordFile for the first string to be printed, too.
You may have defined **wordList in some other way causing a problem, you did not provide the code for it.

How declare function to pass one argument argv[i] at a time? In C

While debugging when I jump to function parseLayerFile filename is (char **) 0x40a04e <_Jv_RegisterClasses+4235342>... How to correct the declaration to get valid filename value?
void parseArgs(WRAPPER_t *w, int argc, char *argv[])
{
int i;
for (i=1 ;i<argc ;i++) {
if (strcmp(argv[i],"-layers") == 0) {
i++;
parseLayerFile(argv[i]);
}
} // for
}
int parseLayerFile(WRAPPER_t * w, char*filename[]){
unsigned char * buffer; size_t size;
size = get_fileContent(filename, &buffer);
}
int main(int argc, char **argv)
{
WRAPPER_t * w;
w = create_wrapper(); // w - main object
threads_init(w);
parseArgs(w, argc, argv);
return 0;
}
int parseLayerFile(WRAPPER_t * w, char*filename[])
expects two parameters.
You are calling it with only one parameter:
parseLayerFile(argv[i]);
As none of the argument suit your needs, fix the function as follows:
int parseLayerFile(const char * filename)
{
unsigned char * buffer;
size_t size = get_fileContent(filename, &buffer);
}

how to pass argument to constructor on library load?

I am trying to create a shared library in Linux. How can I pass an argument to function my_load() when library is loaded? In my C application, I make a call to test_func() then it automatically executes my_load() first before the called function then lastly it executes my_unload()
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
Your dynamic library can always read /proc/self/cmdline to see what the command-line parameters used to execute the current executable are. example.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
static char **get_argv(int *const argcptr)
{
char **argv;
char *data = NULL;
size_t size = 0; /* Allocated to data */
size_t used = 0;
size_t argc, i;
ssize_t bytes;
int fd;
if (argcptr)
*argcptr = 0;
do {
fd = open("/proc/self/cmdline", O_RDONLY | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd == -1)
return NULL;
while (1) {
if (used >= size) {
char *old_data = data;
size = (used | 4095) + 4096;
data = realloc(data, size + 1);
if (data == NULL) {
free(old_data);
close(fd);
errno = ENOMEM;
return NULL;
}
}
do {
bytes = read(fd, data + used, size - used);
} while (bytes == (ssize_t)-1 && errno == EINTR);
if (bytes < (ssize_t)0) {
free(data);
close(fd);
errno = EIO;
return NULL;
} else
if (bytes == (ssize_t)0)
break;
else
used += bytes;
}
if (close(fd)) {
free(data);
errno = EIO;
return NULL;
}
/* Let's be safe and overallocate one pointer here. */
argc = 1;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argc++;
/* Reallocate to accommodate both pointers and data. */
argv = realloc(data, (argc + 1) * sizeof (char *) + used + 1);
if (argv == NULL) {
free(data);
errno = ENOMEM;
return NULL;
}
data = (char *)(argv + argc + 1);
memmove(data, argv, used);
/* In case the input lacked a trailing NUL byte. */
data[used] = '\0';
/* Assign the pointers. */
argv[0] = data;
argc = 0;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argv[++argc] = data + i + 1;
/* Final pointer points to past data. Make it end the array. */
argv[argc] = NULL;
if (argcptr)
*argcptr = (int)argc;
return argv;
}
/* Example standard error functions, that avoid the use of stdio.h.
*/
static void wrerr(const char *p)
{
if (p != NULL) {
const char *const q = p + strlen(p);
ssize_t n;
while (p < q) {
n = write(STDERR_FILENO, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1)
return;
else
if (errno != EINTR)
return;
}
}
}
static void wrerrint(const int i)
{
char buffer[32];
char *p = buffer + sizeof buffer;
unsigned int u;
if (i < 0)
u = (unsigned int)(-i);
else
u = (unsigned int)i;
*(--p) = '\0';
do {
*(--p) = '0' + (u % 10U);
u /= 10U;
} while (u > 0U);
if (i < 0)
*(--p) = '-';
wrerr(p);
}
static void init(void) __attribute__((constructor));
static void init(void)
{
int argc, i, saved_errno;
char **argv;
saved_errno = errno;
argv = get_argv(&argc);
if (argv == NULL) {
const char *const errmsg = strerror(errno);
wrerr("libexample.so: get_argv() failed: ");
wrerr(errmsg);
wrerr(".\n");
errno = saved_errno;
return;
}
for (i = 0; i < argc; i++) {
wrerr("libexample.so: argv[");
wrerrint((int)i);
wrerr("] = '");
wrerr(argv[i]);
wrerr("'\n");
}
free(argv);
errno = saved_errno;
return;
}
Compile using e.g.
gcc -Wall -fPIC -shared example.c -ldl -Wl,-soname,libexample.so -o libexample.so
and test using e.g.
LD_PRELOAD=./libexample.so /bin/echo foo bar baz baaz
(Note that plain echo is a shell built-in, and you need to execute another binary like /bin/echo to load the preload library.)
However, most dynamic libraries take arguments in environment variables instead; for example, YOURLIB_MEM for some memory size hint, or YOURLIB_DEBUG for enabling verbose debugging output during runtime.
(My example code does not use stdio.h output, because not all binaries use it, especially if written in some other language. Instead, the wrerr() and wrerrint() are small stupid helper functions that use low-level unistd.h I/O to write directly to standard error; this always works, and causes minimal side effects at run time.)
Questions?
You can't.
__attribute__((constructor)) simply doesn't support this.
There doesn't seem to be any reason you can't just call my_load(argc, argv) at the very beginning of main().
You can use atexit to register a function to be called when your program exits normally, or returns from main.
int main(int argc, char **argv)
{
my_load(argc, argv);
atexit(my_unload);
// ...
}
AFAIK, there is no way to pass arguments to gcc constructor and destructor functions. The best you can do is to use global variables.
In you example, you could try :
In main :
int Argc;
char *Argv[];
int main(int argc, char *argv[]) {
Argc = argc;
Argv = argv;
...
}
In shared library :
extern int Argc;
...
void __attribute__ ((constructor)) my_load();
...
void my_load() {
printf("my_load: %d\n", Argc);
}
But anyway, it can only work if you explicitely load the shared library through dlopen. It it is directly referenced at link time, the constructor function will be called before first instruction in main and you will always find the original value or 0 in Argc.
Sorry to resurrect an oldie here but I just tested this on both Linux and Mac OS:
$ gcc -x c -o test_prog -
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
int main() { return 0; }
And it prints this result on both systems:
$ ./test_prog foo bar baz
my_load: 4
my_unload
In order for it to work as a shared library I did have to add the linker option -Wl,--no-gc-sections because it otherwise aggressively removed the constructor & destructor. But otherwise yeah this works already.
This doesn’t use the __attribute__ ((constructor)) syntax, but if you specify a custom _init function, you can do so:
// foo.c
#include <stdio.h>
void my_constructor(int argc, char**argv) {
printf("my_constructor init: %s\n", argv[1]);
}
To do so you need to pass ld -init my_constructor or gcc -Wl,-init,my_constructor, e.g.
gcc foo.c -shared -o libfoo.so -Wl,-init,my_constructor

Resources