Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define USE_PRINTF pic_printf
int (*pic_printf)(const char *p, ... );
void adder ( void **start, void **end ) {
if ( start ) {
*start = &&labstart;
*end = &&labend;
} else {
labstart:
USE_PRINTF("In adder\n");
labend:;
}
}
void subber ( void **start, void **end ) {
if ( start ) {
*start = &&labstart;
*end = &&labend;
} else {
labstart:
USE_PRINTF("In subber\n");
labend:;
}
}
size_t calcSize ( void *start, void *end ) {
unsigned char *s = start;
unsigned char *e = end;
return e - s;
}
void copyCode ( char *buff, size_t *dest_offset, size_t dest_size, void *from, size_t from_size ) {
if ( *dest_offset + from_size <= dest_size ) {
memcpy( buff + *dest_offset, from, from_size );
*dest_offset += from_size;
} else {
fprintf( stderr, "oops: Offset=%lu, dest_size=%lu, copy_size=%lu\n",
*dest_offset, dest_size, from_size );
}
}
void dummy ( void ) {
}
#define DUMMY_SIZE 5
#define PROLOGUE_OFFSET 0
#define PROLOGUE_LENGTH 3
#define EPILOGUE_OFFSET 3
#define EPILOGUE_LENGTH 2
#define DUMMY_PTR(x) (void*)(((unsigned char *)dummy)+(x))
int main ( ) {
struct {
void *start;
void *end;
size_t size;
} info[2];
char *buff;
size_t buff_offset = 0;
size_t buff_size;
void (*fnp)(void);
pic_printf = printf;
adder( &info[0].start, &info[0].end );
info[0].size = calcSize( info[0].start, info[0].end );
subber( &info[1].start, &info[1].end );
info[1].size = calcSize( info[1].start, info[1].end );
buff_size = info[0].size * 2 + info[1].size + DUMMY_SIZE; /* add, sub, add */
buff = malloc( buff_size );
copyCode ( buff, &buff_offset, buff_size, DUMMY_PTR(PROLOGUE_OFFSET), PROLOGUE_LENGTH );
copyCode ( buff, &buff_offset, buff_size, info[0].start, info[0].size );
copyCode ( buff, &buff_offset, buff_size, info[1].start, info[1].size );
copyCode ( buff, &buff_offset, buff_size, info[0].start, info[0].size );
copyCode ( buff, &buff_offset, buff_size, DUMMY_PTR(EPILOGUE_OFFSET), EPILOGUE_LENGTH );
fnp = (void(*)(void))buff;
fnp();
free( buff );
return 0;
}
In order to call the thing from C, you need to have the standard prolog/epilog code copied as well.