No more patching libc.a on 64bit platforms

This commit is contained in:
LoveSy 2023-03-30 10:16:53 +08:00 committed by John Wu
parent 23b1b69110
commit 4ff60ef9a9
24 changed files with 61 additions and 17 deletions

View File

@ -274,7 +274,7 @@ def run_cargo_build(args):
env['TARGET_CC'] = op.join(llvm_bin, 'clang' + EXE_EXT)
env['RUSTFLAGS'] = '-Clinker-plugin-lto'
for (arch, triple) in zip(archs, triples):
env['TARGET_CFLAGS'] = f'--target={triple}21'
env['TARGET_CFLAGS'] = f'--target={triple}23'
rust_triple = 'thumbv7neon-linux-androideabi' if triple.startswith('armv7') else triple
proc = execv([*cmds, '--target', rust_triple], env)
if proc.returncode != 0:
@ -479,12 +479,11 @@ def setup_ndk(args):
mv(op.join(ndk_root, f'ondk-{ndk_ver}'), ndk_path)
header('* Patching static libs')
for target in ['aarch64-linux-android', 'arm-linux-androideabi',
'i686-linux-android', 'x86_64-linux-android']:
for target in ['arm-linux-androideabi', 'i686-linux-android']:
arch = target.split('-')[0]
lib_dir = op.join(
ndk_path, 'toolchains', 'llvm', 'prebuilt', f'{os_name}-x86_64',
'sysroot', 'usr', 'lib', f'{target}', '21')
'sysroot', 'usr', 'lib', f'{target}', '23')
if not op.exists(lib_dir):
continue
src_dir = op.join('tools', 'ndk-bins', '21', arch)

View File

@ -4,7 +4,7 @@ APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto
APP_LDFLAGS := -flto
APP_CPPFLAGS := -std=c++20
APP_STL := none
APP_PLATFORM := android-21
APP_PLATFORM := android-23
APP_THIN_ARCHIVE := true
APP_STRIP_MODE := --strip-all

View File

@ -10,11 +10,13 @@
#include <sys/syscall.h>
#include <sys/stat.h>
#if !defined(__LP64__)
extern "C" {
// Original source: https://github.com/freebsd/freebsd/blob/master/contrib/file/src/getline.c
// License: BSD, full copyright notice please check original source
[[gnu::weak]]
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
char *ptr, *eptr;
@ -51,14 +53,17 @@ ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
}
}
[[gnu::weak]]
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp) {
return getdelim(buf, bufsiz, '\n', fp);
}
[[gnu::weak]]
FILE *setmntent(const char *path, const char *mode) {
return fopen(path, mode);
}
[[gnu::weak]]
int endmntent(FILE *fp) {
if (fp != nullptr) {
fclose(fp);
@ -68,43 +73,53 @@ int endmntent(FILE *fp) {
// Missing system call wrappers
[[gnu::weak]]
int setns(int fd, int nstype) {
return syscall(__NR_setns, fd, nstype);
}
[[gnu::weak]]
int unshare(int flags) {
return syscall(__NR_unshare, flags);
}
[[gnu::weak]]
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
return syscall(__NR_accept4, sockfd, addr, addrlen, flags);
}
[[gnu::weak]]
int dup3(int oldfd, int newfd, int flags) {
return syscall(__NR_dup3, oldfd, newfd, flags);
}
[[gnu::weak]]
ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) {
return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
}
[[gnu::weak]]
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
return syscall(__NR_symlinkat, target, newdirfd, linkpath);
}
[[gnu::weak]]
int linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags) {
return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags);
}
[[gnu::weak]]
int inotify_init1(int flags) {
return syscall(__NR_inotify_init1, flags);
}
[[gnu::weak]]
int faccessat(int dirfd, const char *pathname, int mode, int flags) {
return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
}
[[gnu::weak]]
int mkfifo(const char *path, mode_t mode) {
return mknod(path, (mode & ~S_IFMT) | S_IFIFO, 0);
}
@ -113,19 +128,22 @@ int mkfifo(const char *path, mode_t mode) {
#if defined(__arm__)
// Why the additional 0 is required: https://man7.org/linux/man-pages/man2/syscall.2.html
[[gnu::weak]]
int ftruncate64(int fd, off64_t length) {
return syscall(__NR_ftruncate64, fd, 0, SPLIT_64(length));
}
#elif defined(__i386__)
[[gnu::weak]]
int ftruncate64(int fd, off64_t length) {
return syscall(__NR_ftruncate64, fd, SPLIT_64(length));
}
#endif
#if !defined(__LP64__)
[[gnu::weak]]
void android_set_abort_message(const char *) {}
// Original source: <android/legacy_signal_inlines.h>
[[gnu::weak]]
int sigaddset(sigset_t *set, int signum) {
/* Signal numbers start at 1, but bit positions start at 0. */
int bit = signum - 1;
@ -137,6 +155,8 @@ int sigaddset(sigset_t *set, int signum) {
local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
return 0;
}
[[gnu::weak]]
int sigemptyset(sigset_t *set) {
if (set == nullptr) {
errno = EINVAL;
@ -150,6 +170,11 @@ int sigemptyset(sigset_t *set) {
#undef snprintf
#include "fortify.hpp"
#endif
extern FILE __sF[];
[[gnu::weak]] FILE* stdin = &__sF[0];
[[gnu::weak]] FILE* stdout = &__sF[1];
[[gnu::weak]] FILE* stderr = &__sF[2];
} // extern "C"
#endif

View File

@ -26,22 +26,30 @@ static inline void __check_buffer_access(const char* fn, const char* action,
__fortify_fatal("%s: prevented %zu-byte %s %zu-byte buffer", fn, claim, action, actual);
}
}
[[gnu::weak]]
void* __memcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
__check_count("memcpy", "count", count);
__check_buffer_access("memcpy", "write into", count, dst_len);
return __call_bypassing_fortify(memcpy)(dst, src, count);
}
[[gnu::weak]]
char* __strcpy_chk(char* dst, const char* src, size_t dst_len) {
// TODO: optimize so we don't scan src twice.
size_t src_len = __builtin_strlen(src) + 1;
__check_buffer_access("strcpy", "write into", src_len, dst_len);
return __builtin_strcpy(dst, src);
}
[[gnu::weak]]
size_t __strlcpy_chk(char* dst, const char* src,
size_t supplied_size, size_t dst_len_from_compiler) {
__check_buffer_access("strlcpy", "write into", supplied_size, dst_len_from_compiler);
return __call_bypassing_fortify(strlcpy)(dst, src, supplied_size);
}
[[gnu::weak]]
char* __strchr_chk(const char* p, int ch, size_t s_len) {
for (;; ++p, s_len--) {
if (__predict_false(s_len == 0)) {
@ -55,6 +63,8 @@ char* __strchr_chk(const char* p, int ch, size_t s_len) {
}
}
}
[[gnu::weak]]
char* __strcat_chk(char* dst, const char* src, size_t dst_buf_size) {
char* save = dst;
size_t dst_len = __strlen_chk(dst, dst_buf_size);
@ -68,6 +78,8 @@ char* __strcat_chk(char* dst, const char* src, size_t dst_buf_size) {
}
return save;
}
[[gnu::weak]]
size_t __strlen_chk(const char* s, size_t s_len) {
// TODO: "prevented" here would be a lie because this strlen can run off the end.
// strlen is too important to be expensive, so we wanted to be able to call the optimized
@ -78,6 +90,8 @@ size_t __strlen_chk(const char* s, size_t s_len) {
}
return ret;
}
[[gnu::weak]]
int __vsprintf_chk(char* dst, int /*flags*/,
size_t dst_len_from_compiler, const char* format, va_list va) {
// The compiler uses SIZE_MAX to mean "no idea", but our vsnprintf rejects sizes that large.
@ -88,12 +102,16 @@ int __vsprintf_chk(char* dst, int /*flags*/,
__check_buffer_access("vsprintf", "write into", result + 1, dst_len_from_compiler);
return result;
}
[[gnu::weak]]
mode_t __umask_chk(mode_t mode) {
if (__predict_false((mode & 0777) != mode)) {
__fortify_fatal("umask: called with invalid mask %o", mode);
}
return __umask_real(mode);
}
[[gnu::weak]]
ssize_t __read_chk(int fd, void* buf, size_t count, size_t buf_size) {
__check_count("read", "count", count);
__check_buffer_access("read", "write into", count, buf_size);
@ -105,11 +123,22 @@ static inline bool needs_mode(int flags) {
static inline int force_O_LARGEFILE(int flags) {
return flags | O_LARGEFILE;
}
[[gnu::weak]]
int __open_2(const char* pathname, int flags) {
if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
return __openat_real(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0);
}
[[gnu::weak]]
int __openat_2(int fd, const char* pathname, int flags) {
if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
return __openat_real(fd, pathname, force_O_LARGEFILE(flags), 0);
}
[[gnu::weak]]
int __vsnprintf_chk(char* dst, size_t supplied_size, int /*flags*/,
size_t dst_len_from_compiler, const char* format, va_list va) {
__check_buffer_access("vsnprintf", "write into", supplied_size, dst_len_from_compiler);
return vsnprintf(dst, supplied_size, format, va);
}

View File

@ -6,15 +6,6 @@
#include <cerrno>
#include <cstdio>
static inline int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
union {
sigset_t set;
sigset64_t set64;
} s{};
s.set = *set;
return syscall(__NR_rt_sigtimedwait, &s.set64, info, timeout, sizeof(s.set64));
}
static inline int fexecve(int fd, char* const* argv, char* const* envp) {
syscall(__NR_execveat, fd, "", argv, envp, AT_EMPTY_PATH);
if (errno == ENOSYS) {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,7 @@
## Prebuilt Static Libraries
These binaries are extracted straight from [Google NDK r10e](https://dl.google.com/android/repository/android-ndk-r10e-linux-x86_64.zip).
API `16` contains the Bionic libc as old as Android Cupcake (!!). API `21` contains the Bionic libc from Lollipop (minimal API with 64-bit support).
It contains the Bionic libc from Lollipop.
Over the years, Bionic has slowly become more and more gigantic as devices became more powerful and Google kept adding new features.
These are the oldest, which also means smallest, Bionic libc Google had ever offered.