diff --git a/pkg/mmap/lib/mmap.dart b/pkg/mmap/lib/mmap.dart index 0af3035cd17..90ba9856005 100644 --- a/pkg/mmap/lib/mmap.dart +++ b/pkg/mmap/lib/mmap.dart @@ -12,8 +12,8 @@ import 'src/mmap_impl.dart'; /// Whether memory mapping files is supported. /// -/// Currently we only support linux-x64. -final bool supportsMMap = Platform.isLinux && sizeOf() == 8; +/// Currently we only support Linux. +final bool supportsMMap = finalizerCode[Abi.current()] != null; class MemoryMappedFile { /// The memory mapped region of the address space as bytes. diff --git a/pkg/mmap/lib/src/mmap_impl.dart b/pkg/mmap/lib/src/mmap_impl.dart index f3021b56bf4..531402b08dc 100644 --- a/pkg/mmap/lib/src/mmap_impl.dart +++ b/pkg/mmap/lib/src/mmap_impl.dart @@ -15,11 +15,11 @@ import 'dart:typed_data'; import 'package:ffi/ffi.dart'; // int open(const char *path, int oflag, ...); -@Native, Int32)>(symbol: "open") +@Native, Int)>(symbol: "open") external int open(Pointer filename, int flags); // int close(int fd); -@Native(symbol: "close") +@Native(symbol: "close") external int close(int fd); // void* mmap(void* addr, size_t length, @@ -27,12 +27,12 @@ external int close(int fd); // int fd, off_t offset) @FfiNative< Pointer Function( - Pointer, IntPtr, Int32, Int32, Int32, IntPtr)>("mmap") + Pointer, Size, Int, Int, Int, IntPtr)>("mmap") external Pointer mmap( Pointer address, int len, int prot, int flags, int fd, int offset); // int munmap(void *addr, size_t length) -@Native address, IntPtr len)>(symbol: "munmap") +@Native address, Size len)>(symbol: "munmap") external int munmap(Pointer address, int len); final DynamicLibrary processSymbols = DynamicLibrary.process(); @@ -41,7 +41,7 @@ final closeNative = processSymbols.lookup('close'); final freeNative = processSymbols.lookup('free'); // int mprotect(void *addr, size_t len, int prot) -@Native, IntPtr, Int32)>(symbol: "mprotect") +@Native, Size, Int)>(symbol: "mprotect") external int mprotect(Pointer addr, int len, int prot); // DART_EXPORT Dart_Handle @@ -52,7 +52,7 @@ external int mprotect(Pointer addr, int len, int prot); // intptr_t external_allocation_size, // Dart_HandleFinalizer callback) typedef Dart_NewExternalTypedDataWithFinalizerNative = Handle Function( - Int32, Pointer, IntPtr, Pointer, IntPtr, Pointer); + Int, Pointer, IntPtr, Pointer, IntPtr, Pointer); typedef Dart_NewExternalTypedDataWithFinalizerDart = Object Function( int, Pointer, int, Pointer, int, Pointer); final Dart_NewExternalTypedDataWithFinalizer = processSymbols.lookupFunction< @@ -68,38 +68,74 @@ const int kMapPrivate = 2; const int kMapAnon = 0x20; const int kMapFailed = -1; -// We need to attach the finalizer which calls close() and +// #include +// #include +// +// struct PeerData { +// int (*close)(int); +// int (*munmap)(void*, size_t); +// int (*free)(void*); +// void* mapping; +// intptr_t size; +// intptr_t fd; +// }; +// +// extern "C" void finalizer(void* callback_data, void* peer) { +// auto data = static_cast(peer); +// data->munmap(data->mapping, data->size); +// data->close(data->fd); +// data->free(peer); +// } +// +// riscv64-linux-gnu-g++ -O2 -c -o a.o a.cc +// riscv64-linux-gnu-objcopy -O binary --only-section=.text a.o a.bin +// xxd -i a.bin +const finalizerCode = >{ + Abi.linuxX64: [ + 0x53, 0x48, 0x89, 0xf3, 0x48, 0x8b, 0x76, 0x20, 0x48, 0x8b, 0x7b, 0x18, // + 0xff, 0x53, 0x08, 0x8b, 0x7b, 0x28, 0xff, 0x13, 0x48, 0x8b, 0x43, 0x10, // + 0x48, 0x89, 0xdf, 0x5b, 0xff, 0xe0, // + ], + Abi.linuxIA32: [ + 0x53, 0x83, 0xec, 0x10, 0x8b, 0x5c, 0x24, 0x1c, 0xff, 0x73, 0x10, 0xff, // + 0x73, 0x0c, 0xff, 0x53, 0x04, 0x58, 0xff, 0x73, 0x14, 0xff, 0x13, 0x89, // + 0x5c, 0x24, 0x20, 0x8b, 0x43, 0x08, 0x83, 0xc4, 0x18, 0x5b, 0xff, 0xe0, // + ], + Abi.linuxArm64: [ + 0xfd, 0x7b, 0xbe, 0xa9, 0xfd, 0x03, 0x00, 0x91, 0x22, 0x04, 0x40, 0xf9, // + 0xf3, 0x0b, 0x00, 0xf9, 0xf3, 0x03, 0x01, 0xaa, 0x20, 0x84, 0x41, 0xa9, // + 0x40, 0x00, 0x3f, 0xd6, 0x61, 0x02, 0x40, 0xf9, 0x60, 0x2a, 0x40, 0xb9, // + 0x20, 0x00, 0x3f, 0xd6, 0x61, 0x0a, 0x40, 0xf9, 0xe0, 0x03, 0x13, 0xaa, // + 0xf3, 0x0b, 0x40, 0xf9, 0xf0, 0x03, 0x01, 0xaa, 0xfd, 0x7b, 0xc2, 0xa8, // + 0x00, 0x02, 0x1f, 0xd6, // + ], + Abi.linuxArm: [ + 0x10, 0x40, 0x2d, 0xe9, 0x01, 0x40, 0xa0, 0xe1, 0x10, 0x10, 0x91, 0xe5, // + 0x04, 0x30, 0x94, 0xe5, 0x0c, 0x00, 0x94, 0xe5, 0x33, 0xff, 0x2f, 0xe1, // + 0x00, 0x30, 0x94, 0xe5, 0x14, 0x00, 0x94, 0xe5, 0x33, 0xff, 0x2f, 0xe1, // + 0x08, 0x30, 0x94, 0xe5, 0x04, 0x00, 0xa0, 0xe1, 0x10, 0x40, 0xbd, 0xe8, // + 0x13, 0xff, 0x2f, 0xe1, // + ], + Abi.linuxRiscv64: [ + 0x41, 0x11, 0x22, 0xe0, 0x2e, 0x84, 0x1c, 0x64, 0x8c, 0x71, 0x08, 0x6c, // + 0x06, 0xe4, 0x82, 0x97, 0x1c, 0x60, 0x08, 0x54, 0x82, 0x97, 0x1c, 0x68, // + 0x22, 0x85, 0x02, 0x64, 0xa2, 0x60, 0x41, 0x01, 0x82, 0x87, // + ], + Abi.linuxRiscv32: [ + 0x41, 0x11, 0x22, 0xc4, 0x2e, 0x84, 0x5c, 0x40, 0x8c, 0x49, 0x48, 0x44, // + 0x06, 0xc6, 0x82, 0x97, 0x1c, 0x40, 0x48, 0x48, 0x82, 0x97, 0x1c, 0x44, // + 0x22, 0x85, 0x22, 0x44, 0xb2, 0x40, 0x41, 0x01, 0x82, 0x87, // + ], +}; +// We need to attach the finalizer which calls close() and munmap(). final finalizerAddress = () { final Pointer finalizerStub = mmap(nullptr, kPageSize, kProtRead | kProtWrite, kMapPrivate | kMapAnon, -1, 0); - finalizerStub.cast().asTypedList(kPageSize).setAll(0, [ -// Regenerate by running dart mmap.dart gen -// ASM_START -// #include -// #include -// -// struct PeerData { -// int (*close)(int); -// int (*munmap)(void*, size_t); -// int (*free)(void*); -// void* mapping; -// intptr_t size; -// intptr_t fd; -// }; -// -// extern "C" void finalizer(void* callback_data, void* peer) { -// auto data = static_cast(peer); -// data->munmap(data->mapping, data->size); -// data->close(data->fd); -// data->free(peer); -// } -// - 0x55, 0x48, 0x89, 0xf5, 0x48, 0x8b, 0x76, 0x20, 0x48, 0x8b, 0x7d, 0x18, // - 0xff, 0x55, 0x08, 0x8b, 0x7d, 0x28, 0xff, 0x55, 0x00, 0x48, 0x8b, 0x45, // - 0x10, 0x48, 0x89, 0xef, 0x5d, 0xff, 0xe0, // -// ASM_END - ]); + finalizerStub + .cast() + .asTypedList(kPageSize) + .setAll(0, finalizerCode[Abi.current()]!); if (mprotect(finalizerStub, kPageSize, kProtRead | kProtExec) != 0) { throw 'Failed to write executable code to the memory.'; }