| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 } | 
| OLD | NEW | 
|---|