Skip to content

Instantly share code, notes, and snippets.

@scottt
Last active September 19, 2024 06:22
Show Gist options
  • Save scottt/d005413493399ff445a57c959e25862c to your computer and use it in GitHub Desktop.
Save scottt/d005413493399ff445a57c959e25862c to your computer and use it in GitHub Desktop.
scanf to printf on AArch64
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
int main()
{
mprotect((void *)((unsigned long)main & (~0xfff)), 4096,
PROT_EXEC|PROT_WRITE);
{ // gcc and clang puts the "0:", "1:" etc labels below at different places
char *p;
__asm__("adr %[p], 0f\n"
: /* ouputs */ [p] "=r" (p)
: /* inputs */
: /* clobbers */ "x10"
);
printf("0f: 0x%p\n", p);
__asm__("adr %[p], 1f\n"
: /* ouputs */ [p] "=r" (p)
: /* inputs */
: /* clobbers */ "x10"
);
printf("1f: 0x%p\n", p);
__asm__("adr %[p], 2f\n"
: /* ouputs */ [p] "=r" (p)
: /* inputs */
: /* clobbers */ "x10"
);
printf("2f: 0x%p\n", p);
}
#if defined(__clang__)
#define HELLO1_LABEL "0f"
#define HELLO2_LABEL "1f"
#elif defined(__GNUC__)
#define HELLO1_LABEL "(1f-4)"
#define HELLO2_LABEL "(2f-4)"
#endif
uint32_t dst;
__asm__("ldr %w[dst], " HELLO1_LABEL "\n"
: /* ouputs */ [dst] "=r" (dst)
: /* inputs */
: /* clobbers */
);
// bl PCREL26
printf("dst: 0x%0x\n", dst);
dst = ((int32_t)(dst << 6)) >> 4;
printf("dst: %d\n", dst);
__asm__(
"sub %w[dst], %w[dst], " HELLO2_LABEL "-" HELLO1_LABEL "\n"
: /* ouputs */ [dst] "+r" (dst)
: /* inputs */
: /* clobbers */
);
printf("dst: %d\n", dst);
dst = 0x94000000 | (((uint32_t)(dst >> 2)) & (0x03ffffff));
printf("dst: 0x%0x\n", dst);
__asm__ volatile (
"adr x10, " HELLO2_LABEL "\n"
"str %w[dst], [x10]\n"
: /* ouputs */
: /* inputs */ [dst] "r" (dst)
: /* clobbers */ "x10", "memory"
);
// Write back and invalidate data and instruction caches
__builtin___clear_cache((char*)main, (char*)main+1024);
// Jump to target after codegen.
__asm__ volatile ("b 0f");
__asm__("0:");
// In practice, the code works on Apple M2 and Amazon Graviton
// without "__builtin___clear_cache()" and "b 0f" above.
printf("Hello 1\n");
__asm__ volatile ("1:");
scanf("Hello 2\n");
__asm__ volatile ("2:");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment