1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <dlfcn.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <sys/prctl.h> 9 #include <unistd.h> 10 11 // This is a wrapper to run position independent executables on Android ICS, 12 // where the linker doesn't support PIE. This requires the PIE binaries to be 13 // built with CFLAGS +=-fvisibility=default -fPIE, and LDFLAGS += -rdynamic -pie 14 // such that the main() symbol remains exported and can be dlsym-ed. 15 16 #define ERR_PREFIX "[PIE Loader] " 17 18 typedef int (*main_t)(int, char**); 19 20 21 int main(int argc, char** argv) { 22 if (argc < 2) { 23 printf("Usage: %s path_to_pie_executable [args]\n", argv[0]); 24 return -1; 25 } 26 27 // Shift left the argv[]. argv is what /proc/PID/cmdline prints out. In turn 28 // cmdline is what Android "ps" prints out. In turn "ps" is what many scripts 29 // look for to decide which processes to kill / killall. 30 int i; 31 char* next_argv_start = argv[0]; 32 for (i = 1; i < argc; ++i) { 33 const size_t argv_len = strlen(argv[i]) + 1; 34 memcpy(argv[i - 1], argv[i], argv_len); 35 next_argv_start += argv_len; 36 argv[i] = next_argv_start; 37 } 38 argv[argc - 1] = NULL; // The last argv must be a NULL ptr. 39 40 // Set also the proc name accordingly (/proc/PID/comm). 41 prctl(PR_SET_NAME, (long) argv[0]); 42 43 // dlopen should not fail, unless: 44 // - The target binary does not exists: 45 // - The dependent .so libs cannot be loaded. 46 // In both cases, just bail out with an explicit error message. 47 void* handle = dlopen(argv[0], RTLD_NOW); 48 if (handle == NULL) { 49 printf(ERR_PREFIX "dlopen() failed: %s.\n", dlerror()); 50 return -1; 51 } 52 53 main_t pie_main = (main_t) dlsym(handle, "main"); 54 if (pie_main) { 55 return pie_main(argc - 1, argv); 56 } 57 58 // If we reached this point dlsym failed, very likely because the target 59 // binary has not been compiled with the proper CFLAGS / LDFLAGS. 60 // At this point the most sensible thing to do is running that normally 61 // via exec and hope that the target binary wasn't a PIE. 62 execv(argv[0], argv); 63 64 // exevc is supposed to never return, unless it fails. 65 printf(ERR_PREFIX "Both dlsym() and the execv() fallback failed.\n"); 66 perror("execv"); 67 return -1; 68 } 69