1# 32-bit ABI bugs 2 3## 32-bit `off_t` and `_FILE_OFFSET_BITS=64` 4 5On 32-bit Android, `off_t` is a signed 32-bit integer. This limits functions 6that use `off_t` to working on files no larger than 2GiB. 7 8Android does not require the `_LARGEFILE_SOURCE` macro to be used to make 9`fseeko` and `ftello` available. Instead they're always available from API 10level 24 where they were introduced, and never available before then. 11 12Android also does not require the `_LARGEFILE64_SOURCE` macro to be used 13to make `off64_t` and corresponding functions such as `ftruncate64` available. 14Instead, whatever subset of those functions was available at your target API 15level will be visible. 16 17There are a couple of exceptions to note. Firstly, `off64_t` and the single 18function `lseek64` were available right from the beginning in API 3. Secondly, 19Android has always silently inserted `O_LARGEFILE` into any open call, so if 20all you need are functions like `read` that don't take/return `off_t`, large 21files have always worked. 22 23Android support for `_FILE_OFFSET_BITS=64` (which turns `off_t` into `off64_t` 24and replaces each `off_t` function with its `off64_t` counterpart, such as 25`lseek` in the source becoming `lseek64` at runtime) was added late. Even when 26it became available for the platform, it wasn't available from the NDK until 27r15. Before NDK r15, `_FILE_OFFSET_BITS=64` silently did nothing: all code 28compiled with that was actually using a 32-bit `off_t`. With a new enough NDK, 29the situation becomes complicated. If you're targeting an API before 21, almost 30all functions that take an `off_t` become unavailable. You've asked for their 3164-bit equivalents, and none of them (except `lseek`/`lseek64`) exist. As you 32increase your target API level, you'll have more and more of the functions 33available. API 12 adds some of the `<unistd.h>` functions, API 21 adds `mmap`, 34and by API 24 you have everything including `<stdio.h>`. See the 35[linker map](libc/libc.map.txt) for full details. Note also that in NDK r16 and 36later, if you're using Clang we'll inline an `mmap64` implementation in the 37headers when you target an API before 21 because it's an easy special case 38that's often needed. This means that code using `_FILE_OFFSET_BITS=64` 39and `mmap` (but no other functions that are unavailable at your target 40API level) will always compile. 41 42If your code stops compiling when you move to NDK r15 or later, removing every 43definition of `_FILE_OFFSET_BITS=64` will restore the behavior you used to have: 44you'll have a 32-bit `off_t` and use the 32-bit functions. Make sure you 45grep thoroughly in both your source and your build system: many people 46aren't aware that `_FILE_OFFSET_BITS` is set. You might also have to 47remove references to `__USE_FILE_OFFSET64` --- this is the internal 48flag that should never be set by user code but sometimes is (by zlib, 49for example). If you think you have removed these but your code still 50doesn't compile, you can insert this just before the line that's failing 51to double check: 52``` 53#if _FILE_OFFSET_BITS == 64 54#error "oops, file _FILE_OFFSET_BITS == 64" 55#elif defined(__USE_FILE_OFFSET64) 56#error "oops, __USE_FILE_OFFSET64 is defined" 57#endif 58``` 59 60In the 64-bit ABI, `off_t` is always 64-bit. 61 62For source compatibility, the names containing `64` are also available 63in the 64-bit ABI even though they're identical to the non-`64` names. 64 65 66## `sigset_t` is too small for real-time signals 67 68On 32-bit Android, `sigset_t` is too small for ARM and x86. This means that 69there is no support for real-time signals in 32-bit code. Android P (API 70level 28) adds `sigset64_t` and a corresponding function for every function 71that takes a `sigset_t` (so `sigprocmask64` takes a `sigset64_t` where 72`sigprocmask` takes a `sigset_t`). 73 74On 32-bit Android, `struct sigaction` is also too small because it contains 75a `sigset_t`. We also offer a `struct sigaction64` and `sigaction64` function 76to work around this. 77 78In the 64-bit ABI, `sigset_t` is the correct size for every architecture. 79 80For source compatibility, the names containing `64` are also available 81in the 64-bit ABI even though they're identical to the non-`64` names. 82 83 84## `time_t` is 32-bit on LP32 (y2038) 85 86On 32-bit Android, `time_t` is 32-bit, which will overflow in 2038. 87 88In the 64-bit ABI, `time_t` is 64-bit, which will not overflow until 89long after the death of the star around which we currently circle. 90 91The header `<time64.h>` and type `time64_t` exist as a workaround, 92but the kernel interfaces exposed on 32-bit Android all use the 32-bit 93`time_t` and `struct timespec`/`struct timeval`. Linux 5.x kernels 94do offer extra interfaces so that 32-bit processes can pass 64-bit 95times to/from the kernel, but we do not plan on adding support for 96these to the C library. Convenient use of the new calls would require 97an equivalent to `_FILE_OFFSET_BITS=64`, which we wouldn't be able 98to globally flip for reasons similar to `_FILE_OFFSET_BITS`, mentioned 99above. All apps are already required to offer 64-bit variants, and we 100expect 64-bit-only devices within the next few years. 101 102 103## `pthread_mutex_t` is too small for large pids 104 105This doesn't generally affect Android devices, because on devices 106`/proc/sys/kernel/pid_max` is usually too small to hit our 16-bit limit, 107but 32-bit bionic's `pthread_mutex` is a total of 32 bits, leaving just 10816 bits for the owner thread id. This means bionic isn't able to support 109mutexes for tids that don't fit in 16 bits. This typically manifests as 110a hang in `pthread_mutex_lock` if the libc startup code doesn't detect 111this condition and abort. 112