I am attempting to create a function in C that is called from Fortran. First things first. The fortran code is being compiled with f77, and the c is compiled with gcc. Both are compiled into .so libraries. The c function is going to read the memory on a device at an address, and size, specified by the fortran. I am able to see the address, and size being passed to the c, but I am having trouble filling the data in the c function and returning it to the fortran. See the relevant code below. My assumption is that there is something wrong in the memory allocation or pointer syntax for the data variable.
C
void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{
int i;
printf("addr %x \n", *addr);
printf("size %i \n", *size);
for ( i = 0; i<*size; i++)
{
*data[i] = i;
printf("memory %i \n",*data[i]);
}
}
Fortran
integer memory(4)
call copymemory(z'dead', 4, memory)
DO i = 1,memsize
call printf(memory(i))
END DO
I have several points to your code.
Please, supply compilable code and describe the output of that exact code!
That includes the #include for standard headers, if you want people to debug your code, make it easy for them so that they don't have to search which lines did you omit because they seemed "obvious" to you. Just paste everything. The code should compile when copied from here!
Even the executable part of your code does not compile in my compiler. I had to change the *data to data. Are you sure you copied your actual code?
cfun.c: In function ‘copymemory_’:
cfun.c:13:9: error: invalid type argument of unary ‘*’ (have ‘int’)
*data[i] = i;
^
cfun.c:14:31: error: invalid type argument of unary ‘*’ (have ‘int’)
printf("memory %i \n",*data[i]);
^
Your Fortran code contains a call to some printf subroutine. Where is this defined? Is it present in your actual code? I doubt so. Please copy to StackOverflow always a complete and compilable code.
So after fixing the obvious your present code is:
#include <stdio.h>
#include <stdint.h>
void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{
int i;
printf("addr %x \n", *addr);
printf("size %i \n", *size);
for ( i = 0; i<*size; i++)
{
data[i] = i;
printf("memory %i \n",data[i]);
}
}
implicit none
integer :: memsize = 4
integer memory(4)
integer i
call copymemory(z'dead', 4, memory)
DO i = 1,memsize
print *, (memory(i))
END DO
END
It does not crash but memory in Fortran contains garbage. It has to, because it is integer and you are treating it as int8_t in C.
So either treat it as an array of four integers in C or copy it byte by byte, but then you must pass the correct number of bytes to copy. From your description it is not clear which one is your intention so I will show just one possibility:
void copymemory_( uint32_t *addr, int *size, uint32_t *data )
The output is correct then:
> gfortran-4.10 -fsanitize=address cfun.c ffun.f90
> ./a.out
addr dead
size 4
memory 0
memory 1
memory 2
memory 3
0
1
2
3
Related
Below is the program:
#include <stdio.h>
#include<stdlib.h>
int *glob_var;
int* copy(void *a,int size)
{
int *t=(int *)calloc(1,sizeof(int));
int i;
int *glob_var=(int *)calloc(size,sizeof(int));
printf("glob_var=%p\n",glob_var);
printf("a=%p\n",a);
t=glob_var;
for(i=0;i<size;i++)
{
*glob_var=*(int *)a;
glob_var++;
(int *)a++;
// printf("a=%p\n",a);
}
glob_var=t;
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
glob_var=t;
printf("\n%p\n",glob_var);
return t;
}
int main() {
// Write C code here
int a=0x123456,i;
int *var=(int *)calloc(10,sizeof(int));
int *temp;
temp=var;
for(i=0;i<10;i++)
{
*var=i;
var++;
}
var=temp;
for(i=0;i<10;i++)
{
printf("%d\n",*var);
var++;
}
var=temp;
printf("var=%p\n",var);
glob_var=copy(var,10);
printf("%p\n",glob_var);
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
return 0;
}
However, the output I got is :
0 16777216 65536 256 1 33554432 131072 512 2 50331648
I was expecting: 0 1 2 3 4 5 6 7 8 9.
But, in the copy() function, if I replace (int *)a++; with a=(int *)a+1; it is working.
My question is: What is wrong with the current program?
Arithmetic on a pointer-to-void (void*) is not allowed in C1 and your compiler should warn you about that (at the very least) in the following line:
(int *)a++;
When I compile your code (using the clang-cl compiler in Visual Studio), I do, indeed, get two warnings for that line:
warning : arithmetic on a pointer to void is a GNU extension [-Wpointer-arith]
warning : expression result unused [-Wunused-value]
The first of these addresses the issue mentioned in my opening line (and discussed in the footnote) but it is the second that should be ringing alarm bells. That shows that the cast isn't working as intended – it is actually applied to the result of the a++ operation, because the cast has lower precedence than the post-increment.
However, when you use a = (int *)a + 1;, then all is working as intended, because the a pointer is cast to an int* before the arithmetic is performed (and then implicitly cast back to a void* for the assignment).
(There are other issues in your code, like the re-declaration of glob_var in your function, and the use of non-void pointers as arguments for the %p format specifier in several printf calls – but these are not really related to your reported problem. Also, this is worth a read: Do I cast the result of malloc?)
1 Some C compilers, such as GCC, do allow arithmetic on void* pointers, but I do not know what the 'base unit size' is for such operations. One would have to read the GCC manual to determine that, but it may very well by just 1, rather than the sizeof(int) required for your program, as presented, to work. Indeed, if that assumption is correct, and sizeof(int) is 4 on your platform, it would explain the three "garbage values" between successive 'real' data in your output.
I am trying to implement a unit cache structure and use calloc method(dynamic allocation) to give it memory space. I used the type-defined cache_unit as the type of the pointer to receive casted return type from calloc. Normally after calloc, all the bits in the allocated area should be 0. However my output is like random numbers instead of 0 and there're two warning messages.
Here's my code:
#include<stdio.h>
#include<stdlib.h>
#include <cstdint>
int main() {
typedef struct {
bool enabled;
uint8_t block[10];
int access_time;
} cache_unit;
cache_unit* cache = (cache_unit*) calloc(2, sizeof(cache_unit));
printf("%x ", *cache);
return 0;
}
Here are the warning messages on printf:
With printf("%x ", *cache);, "%x" expects a matching unsigned, not a cache_unit.
Try
printf("%d\n", cache->access_time);
I am working through "The Standard C Library" by P.J. Plauger which was written based on the ANSI C Standard. I am having some trouble with the following problem in the book:
"Write a (correct) program that contains the line:
x: ((struct x *)x)->x = x(5);
Now, I know that I would never want to have a line of code like that in my code, but for the sake of learning something new I decided to try it out. I have written the following code in an attempt to make it work:
#include <stdio.h>
#include <stdint.h>
struct x
{
uint16_t x;
};
uint16_t x (uint16_t number)
{
return number;
}
int main (void)
{
intptr_t x;
struct x my_struct;
x = (intptr_t)&my_struct;
x: ((struct x *)x)->x = x(5);
if (my_struct.x == 6)
{
goto x;
}
printf("my_struct.x: %d", my_struct.x);
return 0;
}
However, I get the following error when compiled with mingw32-gcc -Wall -g:
error: called object 'x' is not a function
If I change the function uint16_t x (uint16_t number) to uint16_t y (uint16_t number) and call it as such, then the compiler is happy and my program runs properly. Based on the above, it looks to me like I am redefining the function x() locally as intptr_t x.
Is there a point that I am just missing or was this a construct that was allowed in ANSI C but not in later standards?
Use:
#define x(n) n
instead of:
uint16_t x (uint16_t number)
{
return number;
}
and you program will be valid.
If you look at C Standard (e.g., 6.2.3p1 in C99), there are 4 different name spaces, for: labels, structure / union members, tags and ordinary identifiers. Your function identifier and the object identifier were living in the same name space.
The local variable name will hide the global function name. This is standard behavior and not something new.
The author of the book is looking for a solution that circumvents this problem.
Here is a system specific, hacky program in which the expression appears, without any preprocessor macro being used. The function called by x(5) multiplies its argument by 5, and we see that the resulting 25 ends up in the x structure member:
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct x {
char array[1024];
int x;
};
int func(int arg)
{
return 5 * arg;
}
void after(void)
{
}
int foo(int (*x)(int))
{
x: ((struct x *)x)->x = x(5);
}
int main(void)
{
struct x *xs = mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_SHARED, -1, 0);
memcpy(xs, (void *) func, (char *) after - (char *) func);
foo((int (*)(int)) xs);
printf("xs->x = %d\n", xs->x);
return 0;
}
Output:
xs->x = 25
The trick is that we copy the function into the structure, so that the address of the structure is a pointer to the machine code; a de facto pointer to a function. For this to work in the given environment (Ubuntu GNU/Linux), we need to allocate some memory and make it executable.
The program isn't "incorrect"; it is just nonportable. "correct" in programming means "adhering to a specification". Even a program which exhibits undefined behavior can be correct, if it is specified that way. For instance, we can't avoid a division by zero in a program for which the requirement specification says: "develop a program which explores the consequences of an integer division by zero on such and such a machine and operating system".
In this case, the requirement specification, if interpreted earnestly, requires us to have a value which can be directly used as a function pointer and also as a structure pointer if suitably cast, so we can hardly get away from a hack of this sort.
Note that if we are allowed to use preprocessor hacks or other cheats, then these are valid solutions:
#if 0
x: ((struct x *)x)->x = x(5);
#endif
The program still "contains the line": the problem doesn't say it has to be a line which is retained after the preprocessing translation phases. Also, comments contain lines too:
/*
x: ((struct x *)x)->x = x(5);
*/
This is the first code:
#include <stdio.h>
#include <stdlib.h>
void test(int,int);
int main()
{
int p=23,f=24;
test(&p,&f);
printf("%d %d\n",p,f);
return 0;
}
void test(int q,int g)
{
q=q+q;
g=g+g;
}
This code generates TYPE MISMATCH ERROR maybe due to the fact that I have passed address of variable as argument during function calling and the formal parameters are not pointers.
This is the second code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int p=23,f=24,q,g;
q=&p;
g=&f;
printf("%d %d\n",q,g);
return 0;
}
The output of second code is
1638220 1638228
In this code, q and g are not pointers. So why are they giving correct output, not the error?
Note:
Your comment: "The second code prints the correct addresses of p and f where as first code gives error" is wrong on various levels.
You claim your printf statement prints the memory addresses of the variables? Wrong, it does no such thing. Can't. Impossible. Not going to happen.
To print the memory addresses of variables, a printf statement should look like this:
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);//one of few cases where you SHOULD cast
You're printing just a number:
printf("%d %d", p, f);
Those are not the same thing. Just take a look at the example at the bottom of this answer, but read the bit in the middle, too
Well, you declared q and g as ints, and assigned them the memory addresses of p and f. It's undefined behaviour (ie the standard doesn't determine what to do with this, so it may vary depending on the compiler, WCS: your application crashes). In your case, I'd say this happens:
Basically, a memory address looks something like this:
0x213ABC
A hexadecimal value, which can be interpreted as a number, so there's nothing stopping your from assigning it to a char, or size_t or whatever.
HOWEVER, if you compile your code with -Wall, you should get a warning about the implicit conversion from type int * to int. Aside from that, you're "safe". Mind your: the program's output will be unpredictable and therefore rather pointless.
The first snippet contains a bigger problem: you're passing a value to a function that simply does not exist! The test function cannot handle what you're passing, because its prototype shows it expects 2 ints, not 2 pointers
test(&p,&f);
//to:
test((int) &p,(int) &f);
However, it does compile, as you can see here, however the results are unpredictable (undefined behaviour).
When calling test(&p, &f) you are calling a function that should look like this:
void test(int *, int *)
However, this signature/prototype is nowhere to be found, so the compiler can't continue. Casting the memory addresses to ints changes all that, and lets the compiler know that the function looks like void test (int, int), and that function does exist, hence it compiles.
Think of it like this:
You: What's your phone-number?
Me: abc
you: That's not a phone number
Me: I meant 1-11-111 (number keys for text messages, those were the days)
That's what you're doing here:
test(&p, &f);
//compiler: can't find function test(int *, int *)
//you: I expect you to call test(int, int), and implicitly cast the pointers to ints
That's not how C works.
Note:
As pointed out to me in the coments: Assigning/casting pointer to int is undefined behaviour (ie: the result of these actions are not defined by the standard)
The example program that prints pointers, and unsigned long and ints as they should be printed:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int p = 2, f = 4, q;
q = (int) &f;
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);
//int is too small for 64bit address, use unsigned long here
printf("%d != %ul != %p\n", q, &f, (void *) &f);
return EXIT_SUCCESS;
}
When I ran it through this codepad, I got the following output:
p # 0xbf70e1d8
f # 0xbf70e1d4
-1083121196 != 3211846100l != 0xbf70e1d4
Consider the following code that takes the function f(), copies the function itself in its entirety to a buffer, modifies its code and runs the altered function. In practice, the original function that returns number 22 is cloned and modified to return number 42.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENOUGH 1000
#define MAGICNUMBER 22
#define OTHERMAGICNUMBER 42
int f(void)
{
return MAGICNUMBER;
}
int main(void)
{
int i,k;
char buffer[ENOUGH];
/* Pointer to original function f */
int (*srcfptr)(void) = f;
/* Pointer to hold the manipulated function */
int (*dstfptr)(void) = (void*)buffer;
char* byte;
memcpy(dstfptr, srcfptr, ENOUGH);
/* Replace magic number inside the function with another */
for (i=0; i < ENOUGH; i++) {
byte = ((char*)dstfptr)+i;
if (*byte == MAGICNUMBER) {
*byte = OTHERMAGICNUMBER;
}
}
k = dstfptr();
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
The code now relies on just guessing that the function will fit in the 1000 byte buffer. It also violates rules by copying too much to the buffer, since the function f() will be most likely a lot shorter than 1000 bytes.
This brings us to the question: Is there a method to figure out the size of any given function in C? Some methods include looking into intermediate linker output, and guessing based on the instructions in the function, but that's just not quite enough. Is there any way to be sure?
Please note: It compiles and works on my system but doesn't quite adhere to standards because conversions between function pointers and void* aren't exactly allowed:
$ gcc -Wall -ansi -pedantic fptr.c -o fptr
fptr.c: In function 'main':
fptr.c:21: warning: ISO C forbids initialization between function pointer and 'void *'
fptr.c:23: warning: ISO C forbids passing argument 1 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:23: warning: ISO C forbids passing argument 2 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'const void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:26: warning: ISO C forbids conversion of function pointer to object pointer type
$ ./fptr
Hello 42!
$
Please note: on some systems executing from writable memory is not possible and this code will crash. It has been tested with gcc 4.4.4 on Linux running on x86_64 architecture.
You cannot do this in C. Even if you knew the length, the address of a function matters, because function calls and accesses to certain types of data will use program-counter-relative addressing. Thus, a copy of the function located at a different address will not do the same thing as the original. Of course there are many other issues too.
In the C standard, there is no notion of introspection or reflection, thus you'd need to devise a method yourself, as you have done, some other safer methods exists however.
There are two ways:
Disassemble the function (at runtime) till you hit the final RETN/JMP/etc, while accounting for switch/jump tables. This of course requires some heavy analysis of the function you disassemble (using an engine like beaEngine), this is of course the most reliable, but its slow and heavy.
Abuse compilation units, this is very risky, and not fool proof, but if you know you compiler generates functions sequentially in their compilation unit, you can do something along these lines:
void MyFunc()
{
//...
}
void MyFuncSentinel()
{
}
//somewhere in code
size_t z = (uintptr_t)MyFuncSentinel - (uintptr_t)MyFunc;
uint8_t* buf = (uint8_t*)malloc(z);
memcpy(buf,(char*)MyFunc,z);
this will have some extra padding, but it will be minimal (and unreachable). although highly risky, its a lot faster that the disassemble method.
note: both methods will require that the target code has read permissions.
#R.. raises a very good point, your code won't be relocatable unless its PIC or you reassasmble it in-place to adjust the addresses etc.
Here is a standards compliant way of achieving the result you want:
int f(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = f(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
Now, you may have lots of uses of f() all over the place with no arguments and not want to go through your code changing every one, so you could do this instead
int f()
{
return newf(MAGICNUMBER);
}
int newf(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = newf(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
I'm not suggesting this is a direct answer to your problem but that what you are doing is so horrible, you need to rethink your design.
Well, you can obtain the length of a function at runtime using labels:
int f()
{
int length;
start:
length = &&end - &&start + 11; // 11 is the length of function prologue
// and epilogue, got with gdb
printf("Magic number: %d\n", MagicNumber);
end:
return length;
}
After executing this function we know its length, so we can malloc for the right length, copy and editing the code, then executing it.
int main()
{
int (*pointerToF)(), (*newFunc)(), length, i;
char *buffer, *byte;
length = f();
buffer = malloc(length);
if(!buffer) {
printf("can't malloc\n");
return 0;
}
pointerToF = f;
newFunc = (void*)buffer;
memcpy(newFunc, pointerToF, length);
for (i=0; i < length; i++) {
byte = ((char*)newFunc)+i;
if (*byte == MagicNumber) {
*byte = CrackedNumber;
}
}
newFunc();
}
Now there's another bigger problem though, the one #R. mentioned. Using this function once modified (correctly) results in segmentation fault when calling printf because the call instruction has to specify an offset which will be wrong. You can see this with gdb, using disassemble f to see the original code and x/15i buffer to see the edited one.
By the way, both my code and yours compile without warnings but crash on my machine (gcc 4.4.3) when calling the edited function.