<dlfcn.> fatal error in C code regarding malloc/free - c

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stddef.h>
static int counter = 0;
void* malloc(size_t size) {
void*(*mymalloc)(size_t) = (void* (*)(size_t)) dlsym(RTLD_NEXT, "malloc");
counter++;
}
void free(void* ptr) {
printf(ptr);
counter--;
}
int main(void) {
int* x = (int*) malloc(sizeof(int));
*x = 5;
printf("%d\n", *x);
free(x);
printf(counter);
When I go to compile the program I get an error such as:
mallocfree.c:2:10: fatal error: dlfcn.h: No such file or directory
I am using Visual Studio Code and was wondering if anyone could help me with the problem. Thanks!

Related

Logging memory allocation functions using DLL injection

I have a simple program let's call it a victim:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int *a = malloc(200);
printf("%p\n", a);
}
And I want to inject a shared object into this program that will log all the calls to the malloc function. So it will works like a memory logger:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
void *
malloc(size_t n)
{
static void * (*real_malloc)(size_t) = NULL;
if (real_malloc == NULL) {
real_malloc = dlsym(RTLD_NEXT, "malloc");
if (real_malloc == NULL) {
#if 0
printf("MEMORY FILTER: can't find the real malloc() function: %s\n", dlerror());
#endif
exit(EXIT_FAILURE);
}
}
void *result = real_malloc(n);
#if 0
if (result != NULL)
printf("MEMORY FILTER: allocated %zu bytes at address %p.\n", n, result);
else
printf("MEMORY FILTER: failed to allocate %zu bytes.\n", n);
#endif
return result;
}
And then I run the victim as follows:
$ LD_LIBRARY_PATH=. LD_PRELOAD=libmemlog.so ./victim
0x55e0747792a0
It works fine but when I uncomment #if 0 ... #endif blocks when the printf function is called then I get a segmentation fault. This is happens because printf calls malloc inside itself and we got an endless recursion which eventually crushes.
How can I get logging work in this case?

My C code does not work but another example, something similar to me, works. Why?

My code is not working... But another example that is similar to my code is working. How can I fix?
It seems like pthread_join() is internally change integer value like my code. But mine does not work.
Can anybody help me to fix?
#include <stdio.h>
void test(void **temp) {
int foo = 3;
*temp = foo;
}
int main(void) {
int temp;
test((void **)&temp);
printf("%d\n", temp);
return 0;
}
pthread_join example:
#include <pthread.h>
#include <stdlib.h>
void *test(void *data) {
int i;
int a = *(int *)data;
for (i = 0; i < 10; i++) {
printf("%d\n", i * a);
}
}
int main() {
int a = 100;
pthread_t thread_t;
int status;
if (pthread_create(&thread_t, NULL, test, (void *)&a) < 0) {
perror("thread create error:");
exit(0);
}
pthread_join(thread_t, (void **)&status);
printf("Thread End %d\n", status);
return 1;
}
But mine does not work..
This statement:
pthread_join(thread_t, (void **)&status);
assigns to status the return value of your thread function. But your function doesn't return anything, so you get garbage.
To fix this, make your test function return something.
P.S. Please do turn on compiler warnings (-Wall, -Wextra) -- the compiler should have warned you of the bug already.
P.P.S Please do not name your variables like this: thread_t -- the _t stands for type, and thead_t is not a type.
You are trying to make temp into two void pointers (void**) when you actually only have one pointer to the int temp. Just return the pointer value and you can use this in a similar pthread example.
#include <stdio.h>
#include <stdlib.h>
void *test(void *temp) {
int *ptr = (int*)malloc(sizeof(int));
*ptr = 3;
return ptr;
}
int main(int argc, char *argv[]) {
int *temp = (int*)test(nullptr);
printf("%d\n", *temp);
free(temp);
return 0;
}

Error with two almost identical pieces of code

**I am new to C so please keep that in mind when answering
I'm currently working on a larger program where I use classes called integer.c (which defines an integer and functions used on it), real.c (which defines a double and functions used on it) and comparator.c (which defines functions used to compare these different data types (each class does have a header as well).
When I try and compile the larger program, I get an error in my comparator.c file stating:
comparator.c:25:23: error: expected expression
return ((integer *) p)->value - ((integer *) q->value);
^
comparator.c:25:14: error: use of undeclared identifier 'integer'
return ((integer *) p)->value - ((integer *) q->value);
^
comparator.c:25:48: error: expected expression
return ((integer *) p)->value - ((integer *) q->value);
^
comparator.c:25:39: error: use of undeclared identifier 'integer'
return ((integer *) p)->value - ((integer *) q->value);
^
comparator.c:23:25: warning: unused parameter 'p' [-Wunused-parameter]
int intComparator(void *p, void *q)
^
comparator.c:23:34: warning: unused parameter 'q' [-Wunused-parameter]
int intComparator(void *p, void *q)
^
Here is my comparator.c class and I want to note how my intComparator functions and realComparator functions are almost identical so I cannot see why I do not get these errors for my realComparator:
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include "comparator.h"
#include "str.h"
#include "integer.h"
#include "real.h"
//returns >0 if p is > q, returns 0 if equal, returns <0 is q is > p
int intComparator(void *p, void *q)
{
return ((integer *) p)->value - ((integer *) q)->value;
}
////returns >0 if p is > q, returns 0 if equal, returns <0 is q is > p
double realComparator(void *p,void *q)
{
return ((real *) p)->value - ((real *) q)->value;
}
int stringComparator(void *p,void *q)
{
int r = strcmp((char *)p, (char *)q);
return r;
}
Here is my integer.c class and real.c class for comparison (please note that any programming style of this program that might seem weird is because it is for a class project where I need to follow style and program outline instructions):
integer.c:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include "integer.h"
extern void Fatal(char *,...);
integer *
newInteger(int x)
{
integer *p = malloc(sizeof(integer));
if (p == 0)
{
fprintf(stderr,"out of memory\n");
exit(-1);
}
p->value = x;
return p;
}
int
getInteger(integer *v)
{
assert(v!=0);
return v->value;
}
void
displayInteger(FILE *fp,void *v)
{
assert(v!=0);
fprintf(fp,"%d",getInteger((integer *) v));
}
void
freeInteger(integer *v)
{
free(v);
}
real.c:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
extern void Fatal(char *,...);
real *
newReal(double x)
{
real *p = malloc(sizeof(real));
if (p == 0)
{
fprintf(stderr,"out of memory\n");
exit(-1);
}
p->value = x;
return p;
}
double
getReal(real *v)
{
assert(v!=0);
return v->value;
}
void
displayReal(FILE *fp,void *v)
{
assert(v!=0);
fprintf(fp,"%f",getReal((real *) v));
}
void
freeReal(real *v)
{
free(v);
}
and here are my integer.h and real.h files:
integer.h:
#include <stdio.h>
#ifndef __INTEGER_INCLUDED__
#define __INTEGER_INCLUDED__
typedef struct integer
{
int value;
} integer;
extern integer *newInteger(int);
extern int getInteger(integer *);
extern void displayInteger(FILE *,void *);
extern void freeInteger(integer *);
#define PINFINITY IN_MAX
#define NINFINITY IN_MIN
#endif
real.h:
#include <stdio.h>
#ifndef __REAL_INCLUDED__
#define __REAL_INCLUDED__
typedef struct real
{
double value;
} real;
extern real *newReal(double);
extern double getReal(real *);
extern void displayReal(FILE *,void *);
extern void freeReal(real *);
#define PINFINITY IN_MAX
#define NINFINITY IN_MIN
#endif
Here is str.h:
#include <stdio.h>
#ifndef __STRING_INCLUDED__
#define __STRING_INCLUDED__
extern char * getString(char *);
extern void displayString(FILE *,void *);
extern void freeString(char *);
#define PINFINITY IN_MAX
#define NINFINITY IN_MIN
#endif
and comparator.h:
#ifndef comparator_h
#define comparator_h
typedef int (*Comparator)(void*,void*);
typedef void (*Printer)(FILE*,void*);
extern int intComparator(void *p, void *q);
extern int realComparator(void *p, void *q);
extern int stringComparator(void *p, void *q);
#endif /* comparator_h */
I've been staring at this for so long and have checked everything multiple times and can't figure out why I'm getting these errors. Any help would be great, thanks.
Look closely at the parenthesis:
return ((integer *) p)->value - ((integer *) q->value);
// ^^^^^^^^^^^^^^
return ((real *) p)->value - ((real *) q)->value;
// ^^^^^^^^^^^
In the first case, you're casting q->value to integer*.
In the second case, you're casting q to real*, then accessing ->value.
I assume that the first case is an error.
I see a couple of issues, but first, I want to suggest a code modification to assist in debugging. You wrote a lot of code in one line. I suggest that you break the code into parts until you understand it. Then when it is working, you can combine it together. Like this:
int intComparator(void *p, void *q)
{
int rval;
int p1;
int q1;
p1 = (int *)p -> value;
q1 = (int *)q -> value;
rval = p1 - q1;
return (rval);
}
Now, here are two issues that I see:
1. You are attempting to cast p and q as pointers to integers. I think you need to cast them as pointers to int, not integer.
2. In realcomparator, you are returning an int but you are working with real numbers, I think. Either you should change the return value to a real, or convert the result to an integer before returning it.

gcc "multiple definition of " error

So I have these three files
Main.c
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include "support.h"
int main( void ) {
int* num1 = malloc(100);
printf("num1: %p", &num1);
}
Support.c
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "support.h"
void *malloc(size_t size) {
struct block_meta *block;
if (size <= 0) {
return NULL;
}
if (!global_base) { // First call.
block = request_space(NULL, size);
if (!block) {
return NULL;
}
global_base = block;
} else {
struct block_meta *last = global_base;
block = find_free_block(&last, size);
if (!block) { // Failed to find free block.
block = request_space(last, size);
if (!block) {
return NULL;
}
} else { // Found free block
block->free = 0;
block->magic = 0x77777777;
}
}
return(block+1);
}
void free(void *ptr) {
if (!ptr) {
return;
}
struct block_meta* block_ptr = get_block_ptr(ptr);
assert(block_ptr->free == 0);
assert(block_ptr->magic == 0x77777777 || block_ptr->magic == 0x12345678);
block_ptr->free = 1;
block_ptr->magic = 0x55555555;
}
void *realloc(void *ptr, size_t size) {
if (!ptr) {
// NULL ptr. realloc should act like malloc.
return malloc(size);
}
struct block_meta* block_ptr = get_block_ptr(ptr);
if (block_ptr->size >= size) {
// We have enough space. Could free some once we implement split.
return ptr;
}
// Need to really realloc. Malloc new space and free old space.
// Then copy old data to new space.
void *new_ptr;
new_ptr = malloc(size);
if (!new_ptr) {
return NULL; // TODO: set errno on failure.
}
memcpy(new_ptr, ptr, block_ptr->size);
free(ptr);
return new_ptr;
}
void *calloc(size_t nelem, size_t elsize) {
size_t size = nelem * elsize; // TODO: check for overflow.
void *ptr = malloc(size);
memset(ptr, 0, size);
return ptr;
}
Support.h
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
struct block_meta {
size_t size;
struct block_meta *next;
int free;
int magic; // For debugging only. TODO: remove this in non-debug mode.
};
#define META_SIZE sizeof(struct block_meta)
void *global_base = NULL;
struct block_meta *find_free_block(struct block_meta **last, size_t size) {
struct block_meta *current = global_base;
while (current && !(current->free && current->size >= size)) {
*last = current;
current = current->next;
}
return current;
}
struct block_meta *request_space(struct block_meta* last, size_t size) {
struct block_meta *block;
block = sbrk(0);
void *request = sbrk(size + META_SIZE);
assert((void*)block == request); // Not thread safe.
if (request == (void*) -1) {
return NULL; // sbrk failed.
}
if (last) { // NULL on first request.
last->next = block;
}
block->size = size;
block->next = NULL;
block->free = 0;
block->magic = 0x12345678;
return block;
}
struct block_meta *get_block_ptr(void *ptr) {
return (struct block_meta*)ptr - 1;
}
However when I attempt to compile using
gcc -o asgn2 main.c support.c
I get the error
/tmp/ccscmcbS.o:(.bss+0x0): multiple definition of `global_base'
/tmp/ccyjhjQC.o:(.bss+0x0): first defined here
/tmp/ccscmcbS.o: In function `find_free_block':
support.c:(.text+0x0): multiple definition of `find_free_block'
/tmp/ccyjhjQC.o:main.c:(.text+0x0): first defined here
/tmp/ccscmcbS.o: In function `request_space':
support.c:(.text+0x55): multiple definition of `request_space'
/tmp/ccyjhjQC.o:main.c:(.text+0x55): first defined here
/tmp/ccscmcbS.o: In function `get_block_ptr':
support.c:(.text+0xfe): multiple definition of `get_block_ptr'
/tmp/ccyjhjQC.o:main.c:(.text+0xfe): first defined here
collect2: error: ld returned 1 exit status
I dont believe that I declared those methods more than once, also it is in a much different format than I am usually given. Not quite sure what it means.
The problem is that you have functions and globals defined (as opposed to declared) in your header file. Therefore, those functions are pulled into both main.c and support.c when they are compiled. Then during the linking phase, the linker sees multiple definitions.
Even if you had include guards, it wouldn't help in this case because that only defends against multiple definitions in a single compilation unit, not across multiple units.
Take the definitions of those function out of the header file, replace them with declarations, and put them either in support.c or in a separate .c file.
You can use the -fcommon option for gcc.
Make sure that the header is included only once, so add something like the following to the headers source code:
#ifndef _HAVE_SUPPORT_H
#define _HAVE_SUPPORT_H
// ...
// YOUR HEADER SOURCE CODE
// ...
#endif //_HAVE_SUPPORT_H
As I said this makes sure that the header is included only once, because then it defines _HAVE_SUPPORT_H. If now another source tries to include it, it will not do anything because _HAVE_SUPPRORT_H is already defined.
It also helps if you have only function declarations in the header and your 'real' functions will be in another *.c file.
Edit:
The second parts is the most important for your problem as #kaylum noticed
For me the solution was simple, downgrade to previous GCC version.
Here is comparison gcc installed on two different Ubuntu version.
GCC for ubuntu 20.04: https://packages.ubuntu.com/focal/gcc (gcc 9)
GCC for ubuntu 22.04: https://packages.ubuntu.com/jammy/gcc (gcc 11)
Because on my case, code was legacy code from about 20 years ago, then it makes sense for me to keep using old compiler.

How to compile multiple C files in code blocks

So I was originally writing my code in code blocks but when I'd try to compile it would always give me errors saying that it wasn't understanding the references i was making to functions in other files.At which point I starting using atom, but it's come to the point where I need to use he debugging tool in code blocks and I'm still getting the same errors even though my code compiles when I run it through gcc. Can someone help please?? These are the errors I'm getting.
||=== Build: Debug in A2 (compiler: GNU GCC Compiler) ===|
obj\Debug\main.o||In function main':|
main.c|18|undefined reference tocreateMyVector'|
main.c|29|undefined reference to PathInit'|
main.c|30|undefined reference toAllPathsRec'|
main.c|31|undefined reference to `PathPrint'|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
#include "path.h"
#define BUFFERSIZE 20
int main()
{
Vector *leVector;
unsigned int size;
char leArray[BUFFERSIZE];
scanf("%u\n",&size);
fgets(leArray,sizeof(leArray),stdin);
leVector = createMyVector(size);
char *element = strtok(leArray, " ");
int i;
for(i=0;i<size;i++){
*(leVector->item + i) = atoi(element);
element = strtok(NULL," ");
}
Path Solution;
PathInit(&Solution,size);
AllPathsRec(0,leVector,&Solution);
PathPrint(&Solution);
return 0;
}
vector.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
void vectorRead(Vector * V){
printf("Size of the array is: %d\n",V->size);
int i;
for(i = 0; i < V->size; i++){
if(i == V->size)
printf("%d\n ",*(V->item+i));
else
printf("%d ",*(V->item+i));
}
}
Vector * createMyVector(int size){
Vector * vect = (Vector *)malloc(sizeof(Vector));
vect->size = size;
vect->item = (int *)malloc(sizeof(int)*size);
return vect;
}
path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"
#include "path.h"
void PathInit(Path *P, int vsize){
P->size = vsize;
P->item = (int *)malloc(sizeof(int)*vsize);
P->top = -1;
}
int AllPathsRec(int position, Vector *V, Path *Solution){
PathAddEntry(Solution,position);
position += *(V->item + position);
while(Solution->top != V->size -1){
AllPathsRec(position, V, Solution);
}
return 0;
}
int PathAddEntry(Path *P, int entry){
if(P->top >= P->size - 1){
printf("ERROR: STACK OVERFLOW\n");
return 1;
}
P->top++;
*(P->item + P->top) = entry;
return 0;
}
int PathRemoveEntry(Path *P){
if(P->top <= -1){
printf("\nERROR: NO ELEMENT TO REMOVE\n");
return 1;
}
P->top--;
return 0;
}
void PathPrint(Path *P){
printf("Size of the Solution array is: %d\n",P->size);
int i;
for(i = 0;i <= P->top; i++){
if(i == P->top)
printf("%d\n ", *(P->item+i));
else
printf("%d ", *(P->item+i));
}
}
vector.h
#ifndef VECTOR_H
#define VECTOR_H
typedef struct {
int size;
int *item;
}Vector;
Vector * createMyVector(int size);
void vectorRead(Vector * V);
#endif
path.h
#ifndef PATH_H
#define PATH_H
typedef struct{
int size;
int top;
int *item;
}Path;
void PathInit(Path *P, int size);
int AllPathsRec(int position, Vector *V, Path *Solution);
int PathAddEntry(Path *P, int entry);
int PathRemoveEntry(Path *P);
void PathPrint(Path *P);
#endif

Resources