gnustep / libobjc2

Objective-C runtime library intended for use with Clang.
http://www.gnustep.org/
MIT License
439 stars 118 forks source link

Hard-coded page sizes #271

Open hmelder opened 9 months ago

hmelder commented 9 months ago

On 64-bit POWER platforms, a page is 64 KB in size (at least on Linux by default). Similarly, Asahi Linux uses a 16 KB page size.

Currently, a page size of 4k is hard-coded in the block trampolines and block_to_imp.c. In alloc_trampolines we set PROT_EXEC for rx_buffer, but this assumes that rx_buffer points to the beginning of a 4k page.

There is one proper solution, and one duck tape fix:

  1. Determine page size on runtime. Requires restructuring of block_to_imp.c as struct fields are determined based on PAGE_SIZE.
  2. Determine page size during configuration
hmelder commented 2 weeks ago

Note that this is an issue when targeting Android with 16k pages: https://developer.android.com/guide/practices/page-sizes

Check for code instances that reference specific page sizes Even if your app is 16 KB-aligned, your app can encounter errors if places in your code assume that a device is using a specific page size. To avoid this, complete the following steps:

Remove any hard-coded dependencies that reference the [PAGE_SIZE] (https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/bits/page_size.h;l=34-39) constant or instances in your code logic that assume that a device's page size is 4 KB (4096).

Use getpagesize() or sysconf(_SC_PAGESIZE) instead.

Look for usages of mmap() and other APIs that require page-aligned arguments and replace with alternatives where necessary.

In some cases, if your app uses PAGE_SIZE as a convenient value that isn't tied to the underlying page size, then this won't cause your app to break when used in 16 KB mode. However, if this value is passed to the kernel with mmap without MAP_FIXED, the kernel still uses an entire page, which wastes some memory. For these reasons, PAGE_SIZE is undefined when 16 KB mode is enabled on NDK r27 and higher.

If your app uses PAGE_SIZE in this way and never directly passes this value to the kernel, then instead of using PAGE_SIZE, create a new variable with a new name to reflect that it is used for other purposes and does not reflect a real memory page.