Behold!
I don't think this actually safely works though on x86 at least.
Pretty sure they use the virtual address for instruction caching and
debuggers have to do synchronisation when modifying from a different
address space.
oh well.
On Friday, May 29, 2020 at 9:46:38 AM UTC-7, Steven Stewart-Gallus wrote:
>
> Okay I have an idea.
> I can't shake the idea you could do fun tricks with thread local
> executable pages.
>
> The theoretically fastest way of safepoint polling is inserting a trap
> instruction. But icache overheads dominate. If the icache is based on
> physical addresses and not virtual ones then it should be possible to remap
> the page without doing icache synchronization.
> You should be able to have very fast safepoints by remapping the page.
>
> But I'm not sure there's a fast way to do a call/return from thread local
> storage. And a call/return from a constant page still might not be faster
> than just a load.
>
> TLDR:
> Limited self modifying code without icache syncing stuff could be possible
> with memory management tricks as long as the icache and other stuff is
> based on physical addresses.
>
>
--
You received this message because you are subscribed to the Google Groups
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web, visit
https://groups.google.com/d/msgid/mechanical-sympathy/9ca6f9d0-1b06-44f9-b540-dca4a2d51bc4%40googlegroups.com.
#define _GNU_SOURCE 1
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
extern char __safepoint_start__;
extern char __safepoint_end__;
void __attribute__ ((section (".text.safepoint.hook"))) __attribute__ ((aligned (4096))) __attribute__ ((noinline)) safepoint() {
puts("Should be overwritten always");
}
void __attribute__ ((section (".text.safepoint.functions"))) __attribute__ ((aligned (4096))) __attribute__ ((aligned (4096))) __attribute__ ((noinline)) safepoint_nothing() {
// be very very careful here...
}
void __attribute__ ((section (".text.safepoint.functions"))) __attribute__ ((aligned (4096))) __attribute__ ((aligned (4096))) __attribute__ ((noinline)) safepoint_trap() {
// be very very careful here... can't do nothing..
__builtin_trap();
}
void map_safepoint(int fd, off_t offset)
{
//fixme...
int pagesize = getpagesize();
void *start = safepoint;
start = (void*)( (((uintptr_t)start) / pagesize) * pagesize);
void *result = mmap(start, pagesize, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
if (MAP_FAILED == result) {
perror("mmap");
exit(1);
}
}
int do_nothing_fd;
int do_trap_fd;
void handler(int x) {
puts("yes I know this is unsafe in a signal handler");
// handle safepoint...
map_safepoint(do_nothing_fd, 0);
}
int main() {
do_nothing_fd = memfd_create("do_nothing", MFD_CLOEXEC);
if (do_nothing_fd < 0) {
perror("memfd_create");
return 1;
}
if (write(do_nothing_fd, safepoint_nothing, getpagesize()) < 0) {
perror("write");
return 1;
}
do_trap_fd = memfd_create("do_trap", MFD_CLOEXEC);
if (do_trap_fd < 0) {
perror("memfd_create");
return 1;
}
if (write(do_trap_fd, safepoint_trap, getpagesize()) < 0) {
perror("write");
return 1;
}
map_safepoint(do_nothing_fd, 0);
{
struct sigaction act = {0};
act.sa_handler = handler;
if (sigaction(SIGILL, &act, 0) < 0) {
perror("signal");
return 1;
}
}
safepoint();
map_safepoint(do_trap_fd, 0);
safepoint();
return 0;
}