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 60 additions and 16 deletions

View File

@ -274,7 +274,7 @@ def run_cargo_build(args):
env['TARGET_CC'] = op.join(llvm_bin, 'clang' + EXE_EXT) env['TARGET_CC'] = op.join(llvm_bin, 'clang' + EXE_EXT)
env['RUSTFLAGS'] = '-Clinker-plugin-lto' env['RUSTFLAGS'] = '-Clinker-plugin-lto'
for (arch, triple) in zip(archs, triples): 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 rust_triple = 'thumbv7neon-linux-androideabi' if triple.startswith('armv7') else triple
proc = execv([*cmds, '--target', rust_triple], env) proc = execv([*cmds, '--target', rust_triple], env)
if proc.returncode != 0: if proc.returncode != 0:
@ -479,12 +479,11 @@ def setup_ndk(args):
mv(op.join(ndk_root, f'ondk-{ndk_ver}'), ndk_path) mv(op.join(ndk_root, f'ondk-{ndk_ver}'), ndk_path)
header('* Patching static libs') header('* Patching static libs')
for target in ['aarch64-linux-android', 'arm-linux-androideabi', for target in ['arm-linux-androideabi', 'i686-linux-android']:
'i686-linux-android', 'x86_64-linux-android']:
arch = target.split('-')[0] arch = target.split('-')[0]
lib_dir = op.join( lib_dir = op.join(
ndk_path, 'toolchains', 'llvm', 'prebuilt', f'{os_name}-x86_64', 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): if not op.exists(lib_dir):
continue continue
src_dir = op.join('tools', 'ndk-bins', '21', arch) 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_LDFLAGS := -flto
APP_CPPFLAGS := -std=c++20 APP_CPPFLAGS := -std=c++20
APP_STL := none APP_STL := none
APP_PLATFORM := android-21 APP_PLATFORM := android-23
APP_THIN_ARCHIVE := true APP_THIN_ARCHIVE := true
APP_STRIP_MODE := --strip-all APP_STRIP_MODE := --strip-all

View File

@ -10,11 +10,13 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/stat.h> #include <sys/stat.h>
#if !defined(__LP64__)
extern "C" { extern "C" {
// Original source: https://github.com/freebsd/freebsd/blob/master/contrib/file/src/getline.c // Original source: https://github.com/freebsd/freebsd/blob/master/contrib/file/src/getline.c
// License: BSD, full copyright notice please check original source // License: BSD, full copyright notice please check original source
[[gnu::weak]]
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
char *ptr, *eptr; 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) { ssize_t getline(char **buf, size_t *bufsiz, FILE *fp) {
return getdelim(buf, bufsiz, '\n', fp); return getdelim(buf, bufsiz, '\n', fp);
} }
[[gnu::weak]]
FILE *setmntent(const char *path, const char *mode) { FILE *setmntent(const char *path, const char *mode) {
return fopen(path, mode); return fopen(path, mode);
} }
[[gnu::weak]]
int endmntent(FILE *fp) { int endmntent(FILE *fp) {
if (fp != nullptr) { if (fp != nullptr) {
fclose(fp); fclose(fp);
@ -68,43 +73,53 @@ int endmntent(FILE *fp) {
// Missing system call wrappers // Missing system call wrappers
[[gnu::weak]]
int setns(int fd, int nstype) { int setns(int fd, int nstype) {
return syscall(__NR_setns, fd, nstype); return syscall(__NR_setns, fd, nstype);
} }
[[gnu::weak]]
int unshare(int flags) { int unshare(int flags) {
return syscall(__NR_unshare, flags); return syscall(__NR_unshare, flags);
} }
[[gnu::weak]]
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
return syscall(__NR_accept4, sockfd, addr, addrlen, flags); return syscall(__NR_accept4, sockfd, addr, addrlen, flags);
} }
[[gnu::weak]]
int dup3(int oldfd, int newfd, int flags) { int dup3(int oldfd, int newfd, int flags) {
return syscall(__NR_dup3, oldfd, newfd, flags); return syscall(__NR_dup3, oldfd, newfd, flags);
} }
[[gnu::weak]]
ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) {
return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz); return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
} }
[[gnu::weak]]
int symlinkat(const char *target, int newdirfd, const char *linkpath) { int symlinkat(const char *target, int newdirfd, const char *linkpath) {
return syscall(__NR_symlinkat, target, newdirfd, linkpath); return syscall(__NR_symlinkat, target, newdirfd, linkpath);
} }
[[gnu::weak]]
int linkat(int olddirfd, const char *oldpath, int linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags) { int newdirfd, const char *newpath, int flags) {
return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags); return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags);
} }
[[gnu::weak]]
int inotify_init1(int flags) { int inotify_init1(int flags) {
return syscall(__NR_inotify_init1, flags); return syscall(__NR_inotify_init1, flags);
} }
[[gnu::weak]]
int faccessat(int dirfd, const char *pathname, int mode, int flags) { int faccessat(int dirfd, const char *pathname, int mode, int flags) {
return syscall(__NR_faccessat, dirfd, pathname, mode, flags); return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
} }
[[gnu::weak]]
int mkfifo(const char *path, mode_t mode) { int mkfifo(const char *path, mode_t mode) {
return mknod(path, (mode & ~S_IFMT) | S_IFIFO, 0); return mknod(path, (mode & ~S_IFMT) | S_IFIFO, 0);
} }
@ -113,19 +128,22 @@ int mkfifo(const char *path, mode_t mode) {
#if defined(__arm__) #if defined(__arm__)
// Why the additional 0 is required: https://man7.org/linux/man-pages/man2/syscall.2.html // 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) { int ftruncate64(int fd, off64_t length) {
return syscall(__NR_ftruncate64, fd, 0, SPLIT_64(length)); return syscall(__NR_ftruncate64, fd, 0, SPLIT_64(length));
} }
#elif defined(__i386__) #elif defined(__i386__)
[[gnu::weak]]
int ftruncate64(int fd, off64_t length) { int ftruncate64(int fd, off64_t length) {
return syscall(__NR_ftruncate64, fd, SPLIT_64(length)); return syscall(__NR_ftruncate64, fd, SPLIT_64(length));
} }
#endif #endif
#if !defined(__LP64__) [[gnu::weak]]
void android_set_abort_message(const char *) {} void android_set_abort_message(const char *) {}
// Original source: <android/legacy_signal_inlines.h> // Original source: <android/legacy_signal_inlines.h>
[[gnu::weak]]
int sigaddset(sigset_t *set, int signum) { int sigaddset(sigset_t *set, int signum) {
/* Signal numbers start at 1, but bit positions start at 0. */ /* Signal numbers start at 1, but bit positions start at 0. */
int bit = signum - 1; int bit = signum - 1;
@ -137,6 +155,8 @@ int sigaddset(sigset_t *set, int signum) {
local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
return 0; return 0;
} }
[[gnu::weak]]
int sigemptyset(sigset_t *set) { int sigemptyset(sigset_t *set) {
if (set == nullptr) { if (set == nullptr) {
errno = EINVAL; errno = EINVAL;
@ -150,6 +170,11 @@ int sigemptyset(sigset_t *set) {
#undef snprintf #undef snprintf
#include "fortify.hpp" #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" } // 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); __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) { void* __memcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
__check_count("memcpy", "count", count); __check_count("memcpy", "count", count);
__check_buffer_access("memcpy", "write into", count, dst_len); __check_buffer_access("memcpy", "write into", count, dst_len);
return __call_bypassing_fortify(memcpy)(dst, src, count); return __call_bypassing_fortify(memcpy)(dst, src, count);
} }
[[gnu::weak]]
char* __strcpy_chk(char* dst, const char* src, size_t dst_len) { char* __strcpy_chk(char* dst, const char* src, size_t dst_len) {
// TODO: optimize so we don't scan src twice. // TODO: optimize so we don't scan src twice.
size_t src_len = __builtin_strlen(src) + 1; size_t src_len = __builtin_strlen(src) + 1;
__check_buffer_access("strcpy", "write into", src_len, dst_len); __check_buffer_access("strcpy", "write into", src_len, dst_len);
return __builtin_strcpy(dst, src); return __builtin_strcpy(dst, src);
} }
[[gnu::weak]]
size_t __strlcpy_chk(char* dst, const char* src, size_t __strlcpy_chk(char* dst, const char* src,
size_t supplied_size, size_t dst_len_from_compiler) { size_t supplied_size, size_t dst_len_from_compiler) {
__check_buffer_access("strlcpy", "write into", supplied_size, 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); return __call_bypassing_fortify(strlcpy)(dst, src, supplied_size);
} }
[[gnu::weak]]
char* __strchr_chk(const char* p, int ch, size_t s_len) { char* __strchr_chk(const char* p, int ch, size_t s_len) {
for (;; ++p, s_len--) { for (;; ++p, s_len--) {
if (__predict_false(s_len == 0)) { 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* __strcat_chk(char* dst, const char* src, size_t dst_buf_size) {
char* save = dst; char* save = dst;
size_t dst_len = __strlen_chk(dst, dst_buf_size); 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; return save;
} }
[[gnu::weak]]
size_t __strlen_chk(const char* s, size_t s_len) { 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. // 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 // 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; return ret;
} }
[[gnu::weak]]
int __vsprintf_chk(char* dst, int /*flags*/, int __vsprintf_chk(char* dst, int /*flags*/,
size_t dst_len_from_compiler, const char* format, va_list va) { 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. // 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); __check_buffer_access("vsprintf", "write into", result + 1, dst_len_from_compiler);
return result; return result;
} }
[[gnu::weak]]
mode_t __umask_chk(mode_t mode) { mode_t __umask_chk(mode_t mode) {
if (__predict_false((mode & 0777) != mode)) { if (__predict_false((mode & 0777) != mode)) {
__fortify_fatal("umask: called with invalid mask %o", mode); __fortify_fatal("umask: called with invalid mask %o", mode);
} }
return __umask_real(mode); return __umask_real(mode);
} }
[[gnu::weak]]
ssize_t __read_chk(int fd, void* buf, size_t count, size_t buf_size) { ssize_t __read_chk(int fd, void* buf, size_t count, size_t buf_size) {
__check_count("read", "count", count); __check_count("read", "count", count);
__check_buffer_access("read", "write into", count, buf_size); __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) { static inline int force_O_LARGEFILE(int flags) {
return flags | O_LARGEFILE; return flags | O_LARGEFILE;
} }
[[gnu::weak]]
int __open_2(const char* pathname, int flags) { int __open_2(const char* pathname, int flags) {
if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode"); 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); return __openat_real(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0);
} }
[[gnu::weak]]
int __openat_2(int fd, const char* pathname, int flags) { 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"); 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); 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 <cerrno>
#include <cstdio> #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) { static inline int fexecve(int fd, char* const* argv, char* const* envp) {
syscall(__NR_execveat, fd, "", argv, envp, AT_EMPTY_PATH); syscall(__NR_execveat, fd, "", argv, envp, AT_EMPTY_PATH);
if (errno == ENOSYS) { 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.

Binary file not shown.