blob: 81afd14c992ed310544b6f5431deacbb9aed8b7c [file] [log] [blame] [view]
Elliott Hughesa3481742017-11-28 14:47:17 -08001# 32-bit ABI bugs
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -07002
Elliott Hughesa3481742017-11-28 14:47:17 -08003## 32-bit `off_t` and `_FILE_OFFSET_BITS=64`
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -07004
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
Elliott Hughesa3481742017-11-28 14:47:17 -080035[linker map](libc/libc.map.txt) for full details. Note also that in NDK r16 and
Elliott Hughes3d98adf2017-11-28 20:01:57 -080036later, 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.
Elliott Hughesa3481742017-11-28 14:47:17 -080041
Elliott Hughes3d98adf2017-11-28 20:01:57 -080042If your code stops compiling when you move to NDK r15 or later, removing every
Elliott Hughesa3481742017-11-28 14:47:17 -080043definition of `_FILE_OFFSET_BITS=64` will restore the behavior you used to have:
Elliott Hughes3d98adf2017-11-28 20:01:57 -080044you'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```
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070059
60In the 64-bit ABI, `off_t` is always 64-bit.
61
Elliott Hughes3e235912018-02-01 14:21:51 -080062For 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
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070065
Elliott Hughesa3481742017-11-28 14:47:17 -080066## `sigset_t` is too small for real-time signals
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070067
Elliott Hughes56a9fda2020-02-13 22:23:17 -080068On 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`).
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070073
Elliott Hughes3e235912018-02-01 14:21:51 -080074On 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
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070078In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
79
Elliott Hughes3e235912018-02-01 14:21:51 -080080For 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
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070083
Elliott Hughesa3481742017-11-28 14:47:17 -080084## `time_t` is 32-bit
Elliott Hughes0bfcbaf2017-08-28 09:18:34 -070085
86On 32-bit Android, `time_t` is 32-bit. The header `<time64.h>` and type
87`time64_t` exist as a workaround, but the kernel interfaces exposed on 32-bit
88Android all use the 32-bit `time_t`.
89
90In the 64-bit ABI, `time_t` is 64-bit.
Elliott Hughes1d01fe82017-10-23 10:07:55 -070091
Elliott Hughes5905d6f2018-01-30 15:09:51 -080092
Elliott Hughesa3481742017-11-28 14:47:17 -080093## `pthread_mutex_t` is too small for large pids
Elliott Hughes1d01fe82017-10-23 10:07:55 -070094
95This doesn't generally affect Android devices, because on devices
Elliott Hughes5905d6f2018-01-30 15:09:51 -080096`/proc/sys/kernel/pid_max` is usually too small to hit our 16-bit limit,
Elliott Hughes1d01fe82017-10-23 10:07:55 -070097but 32-bit bionic's `pthread_mutex` is a total of 32 bits, leaving just
9816 bits for the owner thread id. This means bionic isn't able to support
99mutexes for tids that don't fit in 16 bits. This typically manifests as
100a hang in `pthread_mutex_lock` if the libc startup code doesn't detect
101this condition and abort.