Make system use patchoat to relocate during runtime.
Make installd understand a patchoat directive and carry it out.
Bug: 15358152
(cherry picked from commit 7365a10689
)
Change-Id: Id84a15e626ddde63876914068d3d9aa037abc65b
This commit is contained in:
parent
d671f98a27
commit
43c5d30795
@ -570,7 +570,6 @@ done:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
|
int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -633,6 +632,46 @@ static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
|
|||||||
ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
|
ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
|
||||||
|
const char* output_file_name, const char *pkgname, const char *instruction_set)
|
||||||
|
{
|
||||||
|
static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
|
||||||
|
static const unsigned int MAX_INSTRUCTION_SET_LEN = 32;
|
||||||
|
|
||||||
|
static const char* PATCHOAT_BIN = "/system/bin/patchoat";
|
||||||
|
if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
|
||||||
|
ALOGE("Instruction set %s longer than max length of %d",
|
||||||
|
instruction_set, MAX_INSTRUCTION_SET_LEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
|
||||||
|
char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
|
||||||
|
char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
|
||||||
|
char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
|
||||||
|
const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
|
||||||
|
// The caller has already gotten all the locks we need.
|
||||||
|
const char* no_lock_arg = "--no-lock-output";
|
||||||
|
sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
|
||||||
|
sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
|
||||||
|
sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
|
||||||
|
ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
|
||||||
|
PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
|
||||||
|
|
||||||
|
/* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
|
||||||
|
char* argv[7];
|
||||||
|
argv[0] = (char*) PATCHOAT_BIN;
|
||||||
|
argv[1] = (char*) patched_image_location_arg;
|
||||||
|
argv[2] = (char*) no_lock_arg;
|
||||||
|
argv[3] = instruction_set_arg;
|
||||||
|
argv[4] = output_oat_fd_arg;
|
||||||
|
argv[5] = input_oat_fd_arg;
|
||||||
|
argv[6] = NULL;
|
||||||
|
|
||||||
|
execv(PATCHOAT_BIN, (char* const *)argv);
|
||||||
|
ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
|
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
|
||||||
const char* output_file_name, const char *pkgname, const char *instruction_set)
|
const char* output_file_name, const char *pkgname, const char *instruction_set)
|
||||||
{
|
{
|
||||||
@ -769,14 +808,17 @@ static int wait_child(pid_t pid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dexopt(const char *apk_path, uid_t uid, int is_public,
|
int dexopt(const char *apk_path, uid_t uid, int is_public,
|
||||||
const char *pkgname, const char *instruction_set)
|
const char *pkgname, const char *instruction_set,
|
||||||
|
int is_patchoat)
|
||||||
{
|
{
|
||||||
struct utimbuf ut;
|
struct utimbuf ut;
|
||||||
struct stat apk_stat, dex_stat;
|
struct stat input_stat, dex_stat;
|
||||||
char out_path[PKG_PATH_MAX];
|
char out_path[PKG_PATH_MAX];
|
||||||
char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
|
char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
|
||||||
char *end;
|
char *end;
|
||||||
int res, zip_fd=-1, out_fd=-1;
|
const char *input_file;
|
||||||
|
char in_odex_path[PKG_PATH_MAX];
|
||||||
|
int res, input_fd=-1, out_fd=-1;
|
||||||
|
|
||||||
if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
|
if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -785,12 +827,20 @@ int dexopt(const char *apk_path, uid_t uid, int is_public,
|
|||||||
/* The command to run depend on the value of persist.sys.dalvik.vm.lib */
|
/* The command to run depend on the value of persist.sys.dalvik.vm.lib */
|
||||||
property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so");
|
property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so");
|
||||||
|
|
||||||
|
if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) {
|
||||||
|
/* We may only patch if we are libart */
|
||||||
|
ALOGE("Patching is only supported in libart\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Before anything else: is there a .odex file? If so, we have
|
/* Before anything else: is there a .odex file? If so, we have
|
||||||
* precompiled the apk and there is nothing to do here.
|
* precompiled the apk and there is nothing to do here.
|
||||||
|
*
|
||||||
|
* We skip this if we are doing a patchoat.
|
||||||
*/
|
*/
|
||||||
strcpy(out_path, apk_path);
|
strcpy(out_path, apk_path);
|
||||||
end = strrchr(out_path, '.');
|
end = strrchr(out_path, '.');
|
||||||
if (end != NULL) {
|
if (end != NULL && !is_patchoat) {
|
||||||
strcpy(end, ".odex");
|
strcpy(end, ".odex");
|
||||||
if (stat(out_path, &dex_stat) == 0) {
|
if (stat(out_path, &dex_stat) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -801,12 +851,33 @@ int dexopt(const char *apk_path, uid_t uid, int is_public,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&apk_stat, 0, sizeof(apk_stat));
|
if (is_patchoat) {
|
||||||
stat(apk_path, &apk_stat);
|
/* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */
|
||||||
|
strcpy(in_odex_path, apk_path);
|
||||||
|
end = strrchr(in_odex_path, '/');
|
||||||
|
if (end == NULL) {
|
||||||
|
ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/');
|
||||||
|
strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0
|
||||||
|
strcat(in_odex_path, apk_end);
|
||||||
|
end = strrchr(in_odex_path, '.');
|
||||||
|
if (end == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strcpy(end + 1, "odex");
|
||||||
|
input_file = in_odex_path;
|
||||||
|
} else {
|
||||||
|
input_file = apk_path;
|
||||||
|
}
|
||||||
|
|
||||||
zip_fd = open(apk_path, O_RDONLY, 0);
|
memset(&input_stat, 0, sizeof(input_stat));
|
||||||
if (zip_fd < 0) {
|
stat(input_file, &input_stat);
|
||||||
ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path);
|
|
||||||
|
input_fd = open(input_file, O_RDONLY, 0);
|
||||||
|
if (input_fd < 0) {
|
||||||
|
ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,7 +904,7 @@ int dexopt(const char *apk_path, uid_t uid, int is_public,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
|
ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@ -863,9 +934,13 @@ int dexopt(const char *apk_path, uid_t uid, int is_public,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
|
if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
|
||||||
run_dexopt(zip_fd, out_fd, apk_path, out_path);
|
run_dexopt(input_fd, out_fd, input_file, out_path);
|
||||||
} else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
|
} else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
|
||||||
run_dex2oat(zip_fd, out_fd, apk_path, out_path, pkgname, instruction_set);
|
if (is_patchoat) {
|
||||||
|
run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
|
||||||
|
} else {
|
||||||
|
run_dex2oat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */
|
exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */
|
||||||
}
|
}
|
||||||
@ -873,19 +948,19 @@ int dexopt(const char *apk_path, uid_t uid, int is_public,
|
|||||||
} else {
|
} else {
|
||||||
res = wait_child(pid);
|
res = wait_child(pid);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
|
ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
|
||||||
} else {
|
} else {
|
||||||
ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res);
|
ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut.actime = apk_stat.st_atime;
|
ut.actime = input_stat.st_atime;
|
||||||
ut.modtime = apk_stat.st_mtime;
|
ut.modtime = input_stat.st_mtime;
|
||||||
utime(out_path, &ut);
|
utime(out_path, &ut);
|
||||||
|
|
||||||
close(out_fd);
|
close(out_fd);
|
||||||
close(zip_fd);
|
close(input_fd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -893,8 +968,8 @@ fail:
|
|||||||
close(out_fd);
|
close(out_fd);
|
||||||
unlink(out_path);
|
unlink(out_path);
|
||||||
}
|
}
|
||||||
if (zip_fd >= 0) {
|
if (input_fd >= 0) {
|
||||||
close(zip_fd);
|
close(input_fd);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ static int do_install(char **arg, char reply[REPLY_MAX])
|
|||||||
static int do_dexopt(char **arg, char reply[REPLY_MAX])
|
static int do_dexopt(char **arg, char reply[REPLY_MAX])
|
||||||
{
|
{
|
||||||
/* apk_path, uid, is_public, pkgname, instruction_set */
|
/* apk_path, uid, is_public, pkgname, instruction_set */
|
||||||
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4]);
|
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_move_dex(char **arg, char reply[REPLY_MAX])
|
static int do_move_dex(char **arg, char reply[REPLY_MAX])
|
||||||
@ -151,6 +151,10 @@ static int do_prune_dex_cache(char **arg __attribute__((unused)),
|
|||||||
return prune_dex_cache(arg[0] /* subdirectory name */);
|
return prune_dex_cache(arg[0] /* subdirectory name */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_patchoat(char **arg, char reply[REPLY_MAX]) {
|
||||||
|
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 1);
|
||||||
|
}
|
||||||
|
|
||||||
struct cmdinfo {
|
struct cmdinfo {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned numargs;
|
unsigned numargs;
|
||||||
@ -179,6 +183,7 @@ struct cmdinfo cmds[] = {
|
|||||||
{ "idmap", 3, do_idmap },
|
{ "idmap", 3, do_idmap },
|
||||||
{ "restorecondata", 3, do_restorecon_data },
|
{ "restorecondata", 3, do_restorecon_data },
|
||||||
{ "prunedexcache", 1, do_prune_dex_cache },
|
{ "prunedexcache", 1, do_prune_dex_cache },
|
||||||
|
{ "patchoat", 5, do_patchoat },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int readx(int s, void *_buf, int count)
|
static int readx(int s, void *_buf, int count)
|
||||||
|
@ -217,7 +217,7 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, const ch
|
|||||||
int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
|
int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
|
||||||
int free_cache(int64_t free_size);
|
int free_cache(int64_t free_size);
|
||||||
int dexopt(const char *apk_path, uid_t uid, int is_public, const char *pkgName,
|
int dexopt(const char *apk_path, uid_t uid, int is_public, const char *pkgName,
|
||||||
const char *instruction_set);
|
const char *instruction_set, int should_relocate);
|
||||||
int movefiles();
|
int movefiles();
|
||||||
int linklib(const char* target, const char* source, int userId);
|
int linklib(const char* target, const char* source, int userId);
|
||||||
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
|
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
|
||||||
|
Loading…
Reference in New Issue
Block a user