Binary file

Suppose I have a C file with no external dependency and only a const data section. I would like to compile this file, and then get a binary blob that I can load in another program where the function will be used with the function pointer.

Take an example, here is the finish binary module, f1.c

static const unsigned char mylut[256] = { [0 ... 127] = 0, [128 ... 255] = 1, }; void f1(unsigned char * src, unsigned char * dst, int len) { while(len) { *dst++ = mylut[*src++]; len--; } } 

I would like to compile it for f1.o, then f1.bin and use it like this: in prog.c

 int somefunc() { unsigned char * codedata; f1_type_ptr f1_ptr; /* open f1.bin, and read it into codedata */ /* set function pointer to beginning of loaded data */ f1_ptr =(f1_type_ptr)codedata; /* call !*/ f1_ptr(src, dst, len); } 

I believe the switch from f1.c to f1.o includes -fPIC to get position independence. What are the flags or linker script that I can use go from f1.o to f1.bin?

Clarification:

I know about dynamic linking. dynamic linking is not possible in this case. The binding step should be a func pointer to the loaded data, if possible.

Assume no OS support. If I could, I would, for example, write f1 in the assembly with the address associated with the PC.

+6
source share
2 answers

First of all, like others, you should consider using a DLL or SO.

However, if you really want to do this, you need to replace the script linker. Something like this (not very well tested, but I think it works):

 ENTRY(_dummy_start) SECTIONS { _dummy_start = 0; _GLOBAL_OFFSET_TABLE_ = 0; .all : { _all = .; LONG(f1 - _all); *( .text .text.* .data .data.* .rodata .rodata.* ) } } 

Then compile with:

 $ gcc -c -fPIC test.c 

Link to:

 $ ld -T script.ld test.o -o test.elf 

And extract the binary block with:

 $ objcopy -j .all -O binary test.elf test.bin 

Perhaps some explanation of the script is welcome:

  • ENTRY(_dummy_start) This simply prevents a warning that the program does not have an entry point.
  • _dummy_start = 0; Defines the character used in the previous line. The value is not used.
  • _GLOBAL_OFFSET_TABLE_ = 0; This prevents a different linker error. I don’t think you really need this symbol, so it can be defined as 0.
  • .all This is the name of the section that will collect all the bytes of your blob. This sample will contain all .text , .data and .rodata . You may need some more if you have complex functions, in which case objdump -x test.o is your friend.
  • LONG(f1 - _all) Not necessary, but you want to know the offset of your function in the blob, right? You cannot assume that it will be at offset 0. With this string, the first 4 bytes in the block will be the offset of the character f1 (your function). Change LONG to QUAD if using 64-bit pointers.

UPDATE . And now the quick'n'dirty test (it works!):

 #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> typedef void (*f1_t)(char *a, char *b, int len); f1_t f1; int main() { char *blob = (char*)valloc(4096); FILE *f = fopen("test.bin", "rb"); fread(blob, 1, 4096, f); fclose(f); unsigned offs = *(unsigned*)blob; f1 = (f1_t)(blob + offs); mprotect(blob, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); char txt[] = "Β‘hello world!"; char txt2[sizeof(txt)] = ""; f1(txt, txt2, sizeof(txt) - 1); printf("%s\n%s\n", txt, txt2); return 0; } 
+6
source

You should consider creating a shared library ( .dll for Windows or .so for Linux).

Create lib as follows:

 gcc -c -fPIC test.c gcc -shared test.o -o libtest.so 

If you want to dynamically load a library from your code, look at the dlopen (3) and dlsym (3) functions.

Or , if you want to link the library at compile time, build the program with

 gcc -c main.c gcc main.o -o <binary name> -ltest 

EDIT:

I'm really not sure what I will say here, but this may give you the key to progress in your research ...

If you do not want to use dlopen and dlsym , you can try reading the symbol table from the .o file to find the address of the function, and then the mmap object file in memory with read and execute permissions. Then you can execute the downloaded code at the address you specified. But be careful with other dependencies that you might come across in this code.

You can check the elf(5) man page elf(5)

+2
source

Source: https://habr.com/ru/post/923834/


All Articles