diff --git a/src/vita-elf-create/sce-elf.c b/src/vita-elf-create/sce-elf.c index 0f6b9c7..5fcee46 100644 --- a/src/vita-elf-create/sce-elf.c +++ b/src/vita-elf-create/sce-elf.c @@ -187,13 +187,18 @@ static int set_module_export(vita_elf_t *ve, sce_module_exports_t *export, vita_ static int set_main_module_export(vita_elf_t *ve, sce_module_exports_t *export, sce_module_info_t *module_info, vita_export_t *export_spec, void *process_param) { + int have_process_param = export_spec->is_process_image != 0 && export_spec->is_image_module == 0; + export->size = sizeof(sce_module_exports_raw); - export->version = 0; - export->flags = 0x8000; // for syslib - export->num_syms_funcs = (export_spec->is_image_module == 0) ? 1 : 0; // Really all modules have module_start? - export->num_syms_vars = 2; // module_info/process_param for default + export->version = 0; + export->flags = 0x8000; // for syslib + export->num_syms_funcs = 0; + export->num_syms_vars = 1; // module_info for default if (export_spec->is_image_module == 0) { + if (export_spec->start) + ++export->num_syms_funcs; + if (export_spec->bootstart) ++export->num_syms_funcs; @@ -204,6 +209,10 @@ static int set_main_module_export(vita_elf_t *ve, sce_module_exports_t *export, ++export->num_syms_funcs; } + if (have_process_param != 0) { + ++export->num_syms_vars; + } + if (ve->module_sdk_version_ptr != 0xFFFFFFFF) { ++export->num_syms_vars; } @@ -270,9 +279,11 @@ static int set_main_module_export(vita_elf_t *ve, sce_module_exports_t *export, export->entry_table[cur_nid] = module_info; ++cur_nid; - export->nid_table[cur_nid] = NID_PROCESS_PARAM; - export->entry_table[cur_nid] = process_param; - ++cur_nid; + if (have_process_param != 0) { + export->nid_table[cur_nid] = NID_PROCESS_PARAM; + export->entry_table[cur_nid] = process_param; + ++cur_nid; + } if (ve->module_sdk_version_ptr != 0xFFFFFFFF) { export->nid_table[cur_nid] = NID_MODULE_SDK_VERSION; @@ -321,13 +332,30 @@ static void set_module_import(vita_elf_t *ve, sce_module_imports_t *import, cons } } -sce_module_params_t *sce_elf_module_params_create(vita_elf_t *ve, int have_libc) +sce_module_params_t *sce_elf_module_params_create(vita_elf_t *ve, vita_export_t *exports, int have_libc) { + ASSERT(ve != NULL); + ASSERT(exports != NULL); + sce_module_params_t *params = calloc(1, sizeof(sce_module_params_t)); ASSERT(params != NULL); params->process_param_version = ve->module_sdk_version; + if (exports->is_process_image == 0 || exports->is_image_module != 0) { + + params->process_param_size = 0; + + sce_process_param_v6_raw *process_param; + + process_param = calloc(1, sizeof(*process_param)); + ASSERT(process_param != NULL); + process_param->size = 0; + params->process_param = process_param; + + return params; + } + if (params->process_param_version >= VITA_TOOLCHAIN_PROCESS_PARAM_NEW_FORMAT_VERSION) { params->process_param_size = sizeof(sce_process_param_v6_raw); @@ -579,6 +607,9 @@ void sce_elf_module_info_free(sce_module_info_t *module_info) rela->addend = addend; \ } \ } while(0) + +#define sce_module_info_alignment_value (4) + void *sce_elf_module_info_encode( const sce_module_info_t *module_info, const vita_elf_t *ve, const sce_section_sizes_t *sizes, vita_elf_rela_table_t *rtable, sce_module_params_t *params) @@ -618,7 +649,7 @@ void *sce_elf_module_info_encode( segment_base = ve->segments[segndx].vaddr; start_offset = ve->segments[segndx].memsz; - start_offset = (start_offset + 0xF) & ~0xF; // align to 16 bytes + start_offset = (start_offset + (sce_module_info_alignment_value - 1)) & ~(sce_module_info_alignment_value - 1); for (i = 0; i < ve->num_segments; i++) { if (i == segndx) @@ -784,7 +815,7 @@ void *sce_elf_module_info_encode( process_param_raw->sce_libc_param = VADDR(sceModuleInfo_rodata) + libc_param_offset + offsetof(sce_libc_param_raw, size); ADDRELA(&process_param_raw->sce_libc_param); } - } else { + } else if(params->process_param_size != 0) { FAILX("Unknown process_param size (0x%lX)", params->process_param_size); } @@ -1028,7 +1059,7 @@ int sce_elf_write_module_info( segment_base = ve->segments[segndx].vaddr; start_segoffset = ve->segments[segndx].memsz; - start_segoffset = (start_segoffset + 0xF) & ~0xF; // align to 16 bytes, same with `sce_elf_module_info_encode` + start_segoffset = (start_segoffset + (sce_module_info_alignment_value - 1)) & ~(sce_module_info_alignment_value - 1); total_size += (start_segoffset - ve->segments[segndx].memsz); // add the padding size start_vaddr = segment_base + start_segoffset; diff --git a/src/vita-elf-create/sce-elf.h b/src/vita-elf-create/sce-elf.h index e4e0dcb..402b061 100644 --- a/src/vita-elf-create/sce-elf.h +++ b/src/vita-elf-create/sce-elf.h @@ -107,7 +107,12 @@ typedef struct { sce_libc_param_t* libc_param; } sce_module_params_t; -sce_module_params_t *sce_elf_module_params_create(vita_elf_t *ve, int have_libc); +/** + * function: sce_elf_module_params_create + * + * Create process_param and libc_param + */ +sce_module_params_t *sce_elf_module_params_create(vita_elf_t *ve, vita_export_t *exports, int have_libc); void sce_elf_module_params_free(sce_module_params_t *params); diff --git a/src/vita-elf-create/vita-elf-create.c b/src/vita-elf-create/vita-elf-create.c index 6c3f7c4..0c152de 100644 --- a/src/vita-elf-create/vita-elf-create.c +++ b/src/vita-elf-create/vita-elf-create.c @@ -497,7 +497,13 @@ int main(int argc, char *argv[]) g_log = args.log_level; - if ((ve = vita_elf_load(args.input, args.check_stub_count)) == NULL) + if (args.exports) { + exports = vita_exports_load(args.exports, args.input, 0); + if (!exports) + return EXIT_FAILURE; + } + + if ((ve = vita_elf_load(args.input, args.check_stub_count, exports)) == NULL) return EXIT_FAILURE; /* FIXME: save original segment sizes */ @@ -506,13 +512,10 @@ int main(int argc, char *argv[]) for(idx = 0; idx < ve->num_segments; idx++) segment_sizes[idx] = ve->segments[idx].memsz; - if (args.exports) { - exports = vita_exports_load(args.exports, args.input, 0); - - if (!exports) - return EXIT_FAILURE; - } - else { + if (!vita_elf_lookup_imports(ve)) + status = EXIT_FAILURE; + + if (!args.exports) { // generate a default export list exports = vita_export_generate_default(args.input); exports->start = args.entrypoint_funcs[0]; @@ -522,9 +525,6 @@ int main(int argc, char *argv[]) vita_elf_generate_exports(ve, exports); } - if (!vita_elf_lookup_imports(ve)) - status = EXIT_FAILURE; - if (ve->fstubs_va.count) { TRACEF(VERBOSE, "Function stubs in sections \n"); print_stubs(ve->fstubs, ve->num_fstubs); @@ -563,12 +563,15 @@ int main(int argc, char *argv[]) || get_variable_by_symbol("sceLibcHeapUnitSize1MiB", ve, NULL) || get_variable_by_symbol("sceLibcHeapDetectOverrun", ve, NULL); - params = sce_elf_module_params_create(ve, have_libc); + if (exports->is_process_image == 0 || exports->is_image_module != 0) { + have_libc = 0; + } + + params = sce_elf_module_params_create(ve, exports, have_libc); if (!params) return EXIT_FAILURE; module_info = sce_elf_module_info_create(ve, exports, params->process_param); - if (!module_info) return EXIT_FAILURE; diff --git a/src/vita-elf-create/vita-elf.c b/src/vita-elf-create/vita-elf.c index c7da9c0..a2c13b9 100644 --- a/src/vita-elf-create/vita-elf.c +++ b/src/vita-elf-create/vita-elf.c @@ -540,7 +540,7 @@ static int is_valid_relsection(vita_elf_t *ve, GElf_Shdr *rel) { return 0; } -vita_elf_t *vita_elf_load(const char *filename, int check_stub_count) +vita_elf_t *vita_elf_load(const char *filename, int check_stub_count, vita_export_t *export) { vita_elf_t *ve = NULL; GElf_Ehdr ehdr; @@ -623,7 +623,7 @@ vita_elf_t *vita_elf_load(const char *filename, int check_stub_count) if (ve->symtab == NULL) FAILX("No symbol table in binary, perhaps stripped out"); - if (ve->rela_tables == NULL) + if (ve->rela_tables == NULL && export != NULL && export->is_image_module == 0) FAILX("No relocation sections in binary; use -Wl,-q while compiling"); if (ve->fstubs_va.count != 0) { diff --git a/src/vita-elf-create/vita-elf.h b/src/vita-elf-create/vita-elf.h index 7823257..f8336db 100644 --- a/src/vita-elf-create/vita-elf.h +++ b/src/vita-elf-create/vita-elf.h @@ -92,7 +92,7 @@ typedef struct vita_elf_t { int num_segments; } vita_elf_t; -vita_elf_t *vita_elf_load(const char *filename, int check_stub_count); +vita_elf_t *vita_elf_load(const char *filename, int check_stub_count, vita_export_t *export); void vita_elf_free(vita_elf_t *ve); void vita_elf_generate_exports(vita_elf_t *ve, vita_export_t *exports); diff --git a/src/vita-export-parse.c b/src/vita-export-parse.c index a13f3e0..e9e98fa 100644 --- a/src/vita-export-parse.c +++ b/src/vita-export-parse.c @@ -483,6 +483,25 @@ int process_module_info(yaml_node *parent, yaml_node *child, vita_export_t *info info->attributes = (uint16_t)attrib32; } + else if (strcmp(key->value, "process_image") == 0) { + + if (!is_scalar(child)) { + fprintf(stderr, "error: line: %zd, column: %zd, expecting process_image to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child)); + return -1; + } + + key = &child->data.scalar; + + if (strcmp(key->value, "true") == 0) { + info->is_process_image = 1; + } else if (strcmp(key->value, "false") == 0) { + info->is_process_image = 0; + } else { + fprintf(stderr, "error: line: %zd, column: %zd, Received unexpected value in process_image, got '%s'. Vaild value is \"true\" or \"false\".\n", child->position.line, child->position.column, key->value); + return -1; + } + } + else if (strcmp(key->value, "imagemodule") == 0) { if (!is_scalar(child)) { @@ -658,6 +677,14 @@ vita_export_t *vita_export_generate_default(const char *elf) return NULL; } + /* + * | is_process_image | is_image_module | + * | 0 | 0 | prx + * | 0 | 1 | bootimage.skprx + * | 1 | 0 | eboot.bin + * | 1 | 1 | undefined + */ + exports->is_process_image = 1; exports->is_image_module = 0; // we don't specify any specific symbols diff --git a/src/vita-export.h b/src/vita-export.h index cfb7c26..132cc93 100644 --- a/src/vita-export.h +++ b/src/vita-export.h @@ -28,6 +28,7 @@ typedef struct { uint8_t ver_minor; uint16_t attributes; uint32_t nid; + int is_process_image; int is_image_module; const char *bootstart; const char *start;