#include <stddef.h> | |
#include <stdio.h> | |
#include <string.h> | |
void *func[8], **pfunc; | |
typedef struct xxx xxx_t; | |
struct xxx { | |
int dummy; | |
void **pfunc; | |
} q; | |
#define XF_strcpy 3 | |
#define XF_printf 4 | |
#define LABEL(x) \ | |
asm volatile ( \ | |
#if defined(__i386__) | |
#define EXPORT_FUNC(x) \ | |
asm volatile ( \ | |
" .globl mon_" #x "\n" \ | |
"mon_" #x ":\n" \ | |
" movl %0, %%eax\n" \ | |
" movl pfunc, %%ecx\n" \ | |
" jmp *(%%ecx,%%eax)\n" \ | |
: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx"); | |
#elif defined(__powerpc__) | |
#define EXPORT_FUNC(x) \ | |
asm volatile ( \ | |
" .globl mon_" #x "\n" \ | |
"mon_" #x ":\n" \ | |
" lwz %%r11, %0(%%r2)\n" \ | |
" lwz %%r11, %1(%%r11)\n" \ | |
" mtctr %%r11\n" \ | |
" bctr\n" \ | |
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "r11", "r2"); | |
#elif defined(__arm__) | |
#define EXPORT_FUNC(x) \ | |
asm volatile ( \ | |
" .globl mon_" #x "\n" \ | |
"mon_" #x ":\n" \ | |
" ldr ip, [r8, %0]\n" \ | |
" ldr pc, [ip, %1]\n" \ | |
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "ip"); | |
#elif defined(__mips__) | |
#define EXPORT_FUNC(x) \ | |
asm volatile ( \ | |
" .globl mon_" #x "\n" \ | |
"mon_" #x ":\n" \ | |
" lw $25, %0($26)\n" \ | |
" lw $25, %1($25)\n" \ | |
" jr $25\n" \ | |
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "t9"); | |
#else | |
#error [No stub code for this arch] | |
#endif | |
void dummy(void) | |
{ | |
EXPORT_FUNC(printf) | |
EXPORT_FUNC(strcpy) | |
} | |
int main(void) | |
{ | |
#if defined(__i386__) | |
xxx_t *pq; | |
#elif defined(__powerpc__) | |
register volatile xxx_t *pq asm("r2"); | |
#elif defined(__arm__) | |
register volatile xxx_t *pq asm("r8"); | |
#elif defined(__mips__) | |
register volatile xxx_t *pq asm("k0"); | |
#endif | |
char buf[32]; | |
func[XF_strcpy] = strcpy; | |
func[XF_printf] = printf; | |
pq = &q; | |
pq->pfunc = pfunc = func; | |
mon_strcpy(buf, "test"); | |
mon_printf("hi %s %d z\n", buf, 444); | |
return 0; | |
} |