From 1affb91f173c964e778930df9321e6f1183b76fa Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 13 Jul 2018 05:41:29 +0800 Subject: [PATCH] Support compiling against lower SDK Reduce even more size for static binaries --- build.py | 47 ++++++++++++++++++------------------ native/jni/Application.mk | 3 ++- native/jni/core/bootstages.c | 2 +- native/jni/core/magiskinit.c | 6 ++--- native/jni/include/utils.h | 11 ++++++++- native/jni/utils/file.c | 35 +++++++++++++-------------- native/jni/utils/img.c | 10 ++++---- native/jni/utils/xwrap.c | 44 +++++++++++++++++++++++++++------ 8 files changed, 99 insertions(+), 59 deletions(-) diff --git a/build.py b/build.py index 305c51b47..83f9b3447 100755 --- a/build.py +++ b/build.py @@ -114,7 +114,7 @@ def build_binary(args): if 'magisk' in targets: # Magisk is special case as it is a dependency of magiskinit - proc = subprocess.run('{} -C native {} B_MAGISK=1 -j{}'.format(ndk_build, base_flags, cpu_count), shell=True) + proc = subprocess.run('{} -C native {} B_MAGISK=1 -j{}'.format(ndk_build, base_flags, cpu_count), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build Magisk binary failed!') collect_binary() @@ -126,15 +126,6 @@ def build_binary(args): flags += ' B_BXZ=1' old_platform = True - if old_platform: - proc = subprocess.run('{} -C native OLD_PLAT=1 {} -j{}'.format(ndk_build, flags, cpu_count), shell=True) - if proc.returncode != 0: - error('Build binaries failed!') - collect_binary() - - other = False - flags = base_flags - if 'magiskinit' in targets: for arch in archs: bin_file = os.path.join('native', 'out', arch, 'magisk') @@ -153,18 +144,27 @@ def build_binary(args): xz_dump(src, out, 'manager_xz') flags += ' B_INIT=1' - other = True + old_platform = True if 'magiskboot' in targets: flags += ' B_BOOT=1' - other = True + old_platform = True + + if old_platform: + proc = subprocess.run('{} -C native OLD_PLAT=1 {} -j{}'.format(ndk_build, flags, cpu_count), shell=True, stdout=STDOUT) + if proc.returncode != 0: + error('Build binaries failed!') + collect_binary() + + other = False + flags = base_flags if 'busybox' in targets: flags += ' B_BB=1' other = True if other: - proc = subprocess.run('{} -C native {} -j{}'.format(ndk_build, flags, cpu_count), shell=True) + proc = subprocess.run('{} -C native {} -j{}'.format(ndk_build, flags, cpu_count), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build binaries failed!') collect_binary() @@ -203,7 +203,7 @@ def build_apk(args): if not os.path.exists('release-key.jks'): error('Please generate a java keystore and place it in \'release-key.jks\'') - proc = subprocess.run('{} app:assembleRelease'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True) + proc = subprocess.run('{} app:assembleRelease'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build Magisk Manager failed!') @@ -219,7 +219,7 @@ def build_apk(args): header('Output: ' + release) rm(unsigned) else: - proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True) + proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build Magisk Manager failed!') @@ -234,7 +234,7 @@ def build_apk(args): header('Output: ' + target) def build_snet(args): - proc = subprocess.run('{} snet:assembleRelease'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True) + proc = subprocess.run('{} snet:assembleRelease'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build snet extention failed!') source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk') @@ -390,7 +390,7 @@ def sign_adjust_zip(unsigned, output): if not os.path.exists(jarsigner): header('* Building ' + signer_name) - proc = subprocess.run('{} utils:shadowJar'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True) + proc = subprocess.run('{} utils:shadowJar'.format(os.path.join('.', 'gradlew.bat' if os.name == 'nt' else 'gradlew')), shell=True, stdout=STDOUT) if proc.returncode != 0: error('Build {} failed!'.format(signer_name)) @@ -408,12 +408,12 @@ def cleanup(args): if 'native' in args.target: header('* Cleaning native') - subprocess.run(ndk_build + ' -C native B_MAGISK=1 B_INIT=1 B_BOOT=1 B_BXZ=1 B_BB=1 clean', shell=True) + subprocess.run(ndk_build + ' -C native B_MAGISK=1 B_INIT=1 B_BOOT=1 B_BXZ=1 B_BB=1 clean', shell=True, stdout=STDOUT) shutil.rmtree(os.path.join('native', 'out'), ignore_errors=True) if 'java' in args.target: header('* Cleaning java') - subprocess.run('{} app:clean snet:clean utils:clean'.format(os.path.join('.', 'gradlew')), shell=True) + subprocess.run('{} app:clean snet:clean utils:clean'.format(os.path.join('.', 'gradlew')), shell=True, stdout=STDOUT) def parse_config(): c = {} @@ -446,13 +446,14 @@ def parse_config(): config = parse_config() parser = argparse.ArgumentParser(description='Magisk build script') -parser.add_argument('--release', action='store_true', help='compile Magisk for release') +parser.add_argument('-r', '--release', action='store_true', help='compile Magisk for release') +parser.add_argument('-v', '--verbose', action='store_true', help='verbose output') subparsers = parser.add_subparsers(title='actions') all_parser = subparsers.add_parser('all', help='build everything (binaries/apks/zips)') all_parser.set_defaults(func=build_all) -binary_parser = subparsers.add_parser('binary', help='build binaries. target: magisk magiskinit magiskboot busybox b64xz') +binary_parser = subparsers.add_parser('binary', help='build binaries. Target: magisk magiskinit magiskboot busybox b64xz') binary_parser.add_argument('target', nargs='*') binary_parser.set_defaults(func=build_binary) @@ -468,7 +469,7 @@ zip_parser.set_defaults(func=zip_main) uninstaller_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller') uninstaller_parser.set_defaults(func=zip_uninstaller) -clean_parser = subparsers.add_parser('clean', help='cleanup. target: binary java zip') +clean_parser = subparsers.add_parser('clean', help='cleanup. Target: native java') clean_parser.add_argument('target', nargs='*') clean_parser.set_defaults(func=cleanup) @@ -477,5 +478,5 @@ if len(sys.argv) == 1: sys.exit(1) args = parser.parse_args() - +STDOUT = None if args.verbose else subprocess.DEVNULL args.func(args) diff --git a/native/jni/Application.mk b/native/jni/Application.mk index df3c77e35..d8f23ecf7 100644 --- a/native/jni/Application.mk +++ b/native/jni/Application.mk @@ -4,7 +4,8 @@ APP_CFLAGS := -std=gnu99 ${MAGISK_DEBUG} \ APP_CPPFLAGS := -std=c++11 APP_SHORT_COMMANDS := true ifdef OLD_PLAT -APP_PLATFORM := android-9 +APP_PLATFORM := android-16 +APP_CFLAGS += -Wno-implicit-function-declaration else APP_PLATFORM := android-21 endif diff --git a/native/jni/core/bootstages.c b/native/jni/core/bootstages.c index c714d81c5..ef1d855e8 100644 --- a/native/jni/core/bootstages.c +++ b/native/jni/core/bootstages.c @@ -579,7 +579,7 @@ void startup() { while((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; snprintf(buf, PATH_MAX, "/root/%s", entry->d_name); - symlinkat(buf, sbin, entry->d_name); + xsymlinkat(buf, sbin, entry->d_name); } close(sbin); diff --git a/native/jni/core/magiskinit.c b/native/jni/core/magiskinit.c index d5c5cf781..7d59e807a 100644 --- a/native/jni/core/magiskinit.c +++ b/native/jni/core/magiskinit.c @@ -382,9 +382,9 @@ int main(int argc, char *argv[]) { mknod("/null", S_IFCHR | 0666, makedev(1, 3)); int null = open("/null", O_RDWR | O_CLOEXEC); unlink("/null"); - dup3(null, STDIN_FILENO, O_CLOEXEC); - dup3(null, STDOUT_FILENO, O_CLOEXEC); - dup3(null, STDERR_FILENO, O_CLOEXEC); + xdup3(null, STDIN_FILENO, O_CLOEXEC); + xdup3(null, STDOUT_FILENO, O_CLOEXEC); + xdup3(null, STDERR_FILENO, O_CLOEXEC); if (null > STDERR_FILENO) close(null); diff --git a/native/jni/include/utils.h b/native/jni/include/utils.h index ec0a340f4..311508688 100644 --- a/native/jni/include/utils.h +++ b/native/jni/include/utils.h @@ -19,6 +19,13 @@ // xwrap.c +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC O_CLOEXEC +#endif +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK O_NONBLOCK +#endif + FILE *xfopen(const char *pathname, const char *mode); FILE *xfdopen(int fd, const char *mode); #define GET_MACRO(_1, _2, _3, NAME, ...) NAME @@ -51,9 +58,12 @@ int xsocketpair(int domain, int type, int protocol, int sv[2]); int xstat(const char *pathname, struct stat *buf); int xlstat(const char *pathname, struct stat *buf); int xdup2(int oldfd, int newfd); +int xdup3(int oldfd, int newfd, int flags); ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz); ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); int xsymlink(const char *target, const char *linkpath); +int xsymlinkat(const char *target, int newdirfd, const char *linkpath); +int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags); int xmount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); @@ -105,7 +115,6 @@ struct file_attr { char con[128]; }; -int fd_getpath(int fd, char *path, size_t size); int mkdirs(const char *pathname, mode_t mode); void in_order_walk(int dirfd, void (*callback)(int, struct dirent*)); void rm_rf(const char *path); diff --git a/native/jni/utils/file.c b/native/jni/utils/file.c index fd3f420e3..c18fcee2e 100644 --- a/native/jni/utils/file.c +++ b/native/jni/utils/file.c @@ -28,11 +28,16 @@ static int is_excl(const char *name) { return 0; } -int fd_getpath(int fd, char *path, size_t size) { +static int fd_getpath(int fd, char *path, size_t size) { snprintf(path, size, "/proc/self/fd/%d", fd); - if (xreadlink(path, path, size) == -1) - return -1; - return 0; + return xreadlink(path, path, size) == -1; +} + +static int fd_getpathat(int dirfd, const char *name, char *path, size_t size) { + if (fd_getpath(dirfd, path, size)) + return 1; + snprintf(path, size, "%s/%s", path, name); + return 0; } int mkdirs(const char *pathname, mode_t mode) { @@ -220,7 +225,7 @@ void clone_dir(int src, int dest) { break; case DT_LNK: xreadlinkat(src, entry->d_name, buf, sizeof(buf)); - symlinkat(buf, dest, entry->d_name); + xsymlinkat(buf, dest, entry->d_name); setattrat(dest, entry->d_name, &a); break; } @@ -249,7 +254,7 @@ void link_dir(int src, int dest) { close(newsrc); close(newdest); } else { - linkat(src, entry->d_name, dest, entry->d_name, 0); + xlinkat(src, entry->d_name, dest, entry->d_name, 0); } } } @@ -270,12 +275,9 @@ int getattr(const char *path, struct file_attr *a) { } int getattrat(int dirfd, const char *pathname, struct file_attr *a) { - int fd = xopenat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) - return -1; - int ret = fgetattr(fd, a); - close(fd); - return ret; + char path[PATH_MAX]; + fd_getpathat(dirfd, pathname, path, sizeof(path)); + return getattr(path, a); } int fgetattr(int fd, struct file_attr *a) { @@ -304,12 +306,9 @@ int setattr(const char *path, struct file_attr *a) { } int setattrat(int dirfd, const char *pathname, struct file_attr *a) { - int fd = xopenat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) - return -1; - int ret = fsetattr(fd, a); - close(fd); - return ret; + char path[PATH_MAX]; + fd_getpathat(dirfd, pathname, path, sizeof(path)); + return setattr(path, a); } int fsetattr(int fd, struct file_attr *a) { diff --git a/native/jni/utils/img.c b/native/jni/utils/img.c index 9d7673e93..b10b9b3c1 100644 --- a/native/jni/utils/img.c +++ b/native/jni/utils/img.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include @@ -70,12 +70,12 @@ static char *loopsetup(const char *img) { static void check_filesystem(struct fs_info *info, const char *img, const char *mount) { struct stat st; - struct statvfs vfs; + struct statfs fs; stat(img, &st); - statvfs(mount, &vfs); + statfs(mount, &fs); info->size = st.st_size / 1048576; - info->free = vfs.f_bfree * vfs.f_frsize / 1048576; - info->used = (vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize / 1048576; + info->free = fs.f_bfree * (uint64_t)fs.f_frsize / 1048576; + info->used = (fs.f_blocks - fs.f_bfree) * (uint64_t)fs.f_frsize / 1048576; } static void usage() { diff --git a/native/jni/utils/xwrap.c b/native/jni/utils/xwrap.c index c74d149d3..72ee47026 100644 --- a/native/jni/utils/xwrap.c +++ b/native/jni/utils/xwrap.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "logging.h" #include "utils.h" @@ -100,7 +101,7 @@ int xpipe2(int pipefd[2], int flags) { } int xsetns(int fd, int nstype) { - int ret = setns(fd, nstype); + int ret = (int) syscall(__NR_setns, fd, nstype); if (ret == -1) { PLOGE("setns"); } @@ -165,9 +166,14 @@ int xlisten(int sockfd, int backlog) { } int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - int fd = accept4(sockfd, addr, addrlen, flags); +#ifndef __NR_accept4 +#ifdef __i386__ +#define __NR_accept4 364 +#endif +#endif + int fd = (int) syscall(__NR_accept4, sockfd, addr, addrlen, flags); if (fd == -1) { - PLOGE("accept"); + PLOGE("accept4"); } return fd; } @@ -212,8 +218,8 @@ ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags) { return rec; } -int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg) { +int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) { errno = pthread_create(thread, attr, start_routine, arg); if (errno) { PLOGE("pthread_create"); @@ -245,6 +251,14 @@ int xdup2(int oldfd, int newfd) { return ret; } +int xdup3(int oldfd, int newfd, int flags) { + int ret = (int) syscall(__NR_dup3, oldfd, newfd, flags); + if (ret == -1) { + PLOGE("dup3"); + } + return ret; +} + ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) { ssize_t ret = readlink(pathname, buf, bufsiz); if (ret == -1) { @@ -256,7 +270,7 @@ ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) { } ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { - ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); + ssize_t ret = syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz); if (ret == -1) { PLOGE("readlinkat %s", pathname); } else { @@ -273,10 +287,26 @@ int xsymlink(const char *target, const char *linkpath) { return ret; } +int xsymlinkat(const char *target, int newdirfd, const char *linkpath) { + int ret = (int) syscall(__NR_symlinkat, target, newdirfd, linkpath); + if (ret == -1) { + PLOGE("symlinkat %s->%s", target, linkpath); + } + return ret; +} + +int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) { + int ret = (int) syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags); + if (ret == -1) { + PLOGE("linkat %s->%s", oldpath, newpath); + } + return ret; +} + int xmount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { - int ret = mount(source, target, filesystemtype, MS_SILENT | mountflags, data); + int ret = mount(source, target, filesystemtype, mountflags, data); if (ret == -1) { PLOGE("mount %s->%s", source, target); }