sce-elf.c (32263B)
1 #include <stdlib.h> 2 #include <stddef.h> 3 #include <string.h> 4 5 #include <libelf.h> 6 #include <gelf.h> 7 8 #include "vita-elf.h" 9 #include "vita-export.h" 10 #include "elf-defs.h" 11 #include "elf-utils.h" 12 #include "sce-elf.h" 13 #include "fail-utils.h" 14 #include "varray.h" 15 #include "endian-utils.h" 16 17 const uint32_t sce_elf_stub_func[3] = { 18 0xe3e00000, /* mvn r0, #0 */ 19 0xe12fff1e, /* bx lr */ 20 0xe1a00000 /* mov r0, r0 */ 21 }; 22 23 static const uint32_t sce_elf_stub_var_func[8] = { 24 0xe3000000, /* mov r0, #0 */ 25 0xe3400000, /* movt r0, #0 */ 26 0xe12fff1e, /* bx lr */ 27 0x00000140, /* header for 1 reloc */ 28 0x00002b01, /* short reloc R_ARM_MOVW_ABS_NC */ 29 0x00000000, /* fill with addr */ 30 0x00002c01, /* short reloc R_ARM_MOVT_ABS */ 31 0x00000000, /* fill with addr+4 */ 32 }; 33 34 #define ALIGN_4(size) (((size) + 3) & ~0x3) 35 36 typedef struct { 37 uint32_t nid; 38 vita_imports_module_t *module; 39 40 union { 41 vita_elf_stub_t *functions; 42 varray functions_va; 43 }; 44 45 union { 46 vita_elf_stub_t *variables; 47 varray variables_va; 48 }; 49 } import_module; 50 51 static int _stub_sort(const void *el1, const void *el2) { 52 const vita_elf_stub_t *stub1 = el1, *stub2 = el2; 53 if (stub2->target_nid > stub1->target_nid) 54 return 1; 55 else if (stub2->target_nid < stub1->target_nid) 56 return -1; 57 return 0; 58 } 59 static int _stub_nid_search(const void *key, const void *element) { 60 const uint32_t *nid = key; 61 const vita_elf_stub_t *stub = element; 62 if (stub->target_nid > *nid) 63 return 1; 64 else if (stub->target_nid < *nid) 65 return -1; 66 return 0; 67 } 68 69 static void * _module_init(void *element) 70 { 71 import_module *module = element; 72 if (!varray_init(&module->functions_va, sizeof(vita_elf_stub_t), 8)) return NULL; 73 if (!varray_init(&module->variables_va, sizeof(vita_elf_stub_t), 4)) return NULL; 74 75 module->functions_va.sort_compar = _stub_sort; 76 module->functions_va.search_compar = _stub_nid_search; 77 module->variables_va.sort_compar = _stub_sort; 78 module->variables_va.search_compar = _stub_nid_search; 79 80 return module; 81 } 82 static void _module_destroy(void *element) 83 { 84 import_module *module = element; 85 varray_destroy(&module->functions_va); 86 varray_destroy(&module->variables_va); 87 } 88 89 static int _module_sort(const void *el1, const void *el2) 90 { 91 const import_module *mod1 = el1, *mod2 = el2; 92 if (mod2->nid > mod1->nid) 93 return 1; 94 else if (mod2->nid < mod1->nid) 95 return -1; 96 return 0; 97 } 98 99 static int _module_search(const void *key, const void *element) 100 { 101 const uint32_t *nid = key; 102 const import_module *module = element; 103 if (module->nid > *nid) 104 return 1; 105 else if (module->nid < *nid) 106 return -1; 107 return 0; 108 } 109 110 static int get_function_by_symbol(const char *symbol, vita_elf_t *ve, Elf32_Addr *vaddr) { 111 int i; 112 113 for (i = 0; i < ve->num_symbols; ++i) { 114 if (ve->symtab[i].type != STT_FUNC) 115 continue; 116 117 if (strcmp(ve->symtab[i].name, symbol) == 0) { 118 *vaddr = ve->symtab[i].value; 119 break; 120 } 121 } 122 123 return i != ve->num_symbols; 124 } 125 126 static int get_variable_by_symbol(const char *symbol, vita_elf_t *ve, Elf32_Addr *vaddr) { 127 int i; 128 129 for (i = 0; i < ve->num_symbols; ++i) { 130 if (ve->symtab[i].type != STT_OBJECT) 131 continue; 132 133 if (strcmp(ve->symtab[i].name, symbol) == 0) { 134 *vaddr = ve->symtab[i].value; 135 break; 136 } 137 } 138 139 return i != ve->num_symbols; 140 } 141 142 typedef union { 143 import_module *modules; 144 varray va; 145 } import_module_list; 146 147 static int set_module_export(vita_elf_t *ve, sce_module_exports_t *export, vita_library_export *lib) 148 { 149 export->size = sizeof(sce_module_exports_raw); 150 export->version = 1; 151 export->flags = lib->syscall ? 0x4001 : 0x0001; 152 export->num_syms_funcs = lib->function_n; 153 export->num_syms_vars = lib->variable_n; 154 export->module_name = strdup(lib->name); 155 export->module_nid = lib->nid; 156 157 int total_exports = export->num_syms_funcs + export->num_syms_vars; 158 export->nid_table = calloc(total_exports, sizeof(uint32_t)); 159 export->entry_table = calloc(total_exports, sizeof(void*)); 160 161 int cur_ent = 0; 162 int i; 163 for (i = 0; i < export->num_syms_funcs; ++i) { 164 Elf32_Addr vaddr = 0; 165 vita_export_symbol *sym = lib->functions[i]; 166 167 if (!get_function_by_symbol(sym->name, ve, &vaddr)) { 168 FAILX("Could not find function symbol '%s' for export '%s'", sym->name, lib->name); 169 } 170 171 export->nid_table[cur_ent] = sym->nid; 172 export->entry_table[cur_ent] = vita_elf_vaddr_to_host(ve, vaddr); 173 ++cur_ent; 174 } 175 176 for (i = 0; i < export->num_syms_vars; ++i) { 177 Elf32_Addr vaddr = 0; 178 vita_export_symbol *sym = lib->variables[i]; 179 180 if (!get_variable_by_symbol(sym->name, ve, &vaddr)) { 181 FAILX("Could not find variable symbol '%s' for export '%s'", sym->name, lib->name); 182 } 183 184 export->nid_table[cur_ent] = sym->nid; 185 export->entry_table[cur_ent] = vita_elf_vaddr_to_host(ve, vaddr); 186 ++cur_ent; 187 } 188 189 return 0; 190 191 failure: 192 return -1; 193 } 194 195 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) 196 { 197 export->size = sizeof(sce_module_exports_raw); 198 export->version = 0; 199 export->flags = 0x8000; 200 export->num_syms_funcs = 1; 201 export->num_syms_vars = 2; 202 203 if (export_spec->stop) 204 ++export->num_syms_funcs; 205 206 if (export_spec->exit) 207 ++export->num_syms_funcs; 208 209 int total_exports = export->num_syms_funcs + export->num_syms_vars; 210 export->nid_table = calloc(total_exports, sizeof(uint32_t)); 211 export->entry_table = calloc(total_exports, sizeof(void*)); 212 213 int cur_nid = 0; 214 215 if (export_spec->start) { 216 Elf32_Addr vaddr = 0; 217 if (!get_function_by_symbol(export_spec->start, ve, &vaddr)) { 218 FAILX("Could not find symbol '%s' for main export 'start'", export_spec->start); 219 } 220 221 module_info->module_start = vita_elf_vaddr_to_host(ve, vaddr); 222 } 223 else 224 module_info->module_start = vita_elf_vaddr_to_host(ve, elf32_getehdr(ve->elf)->e_entry); 225 226 export->nid_table[cur_nid] = NID_MODULE_START; 227 export->entry_table[cur_nid] = module_info->module_start; 228 ++cur_nid; 229 230 if (export_spec->stop) { 231 Elf32_Addr vaddr = 0; 232 233 if (!get_function_by_symbol(export_spec->stop, ve, &vaddr)) { 234 FAILX("Could not find symbol '%s' for main export 'stop'", export_spec->stop); 235 } 236 237 export->nid_table[cur_nid] = NID_MODULE_STOP; 238 export->entry_table[cur_nid] = module_info->module_stop = vita_elf_vaddr_to_host(ve, vaddr); 239 ++cur_nid; 240 } 241 242 if (export_spec->exit) { 243 Elf32_Addr vaddr = 0; 244 245 if (!get_function_by_symbol(export_spec->exit, ve, &vaddr)) { 246 FAILX("Could not find symbol '%s' for main export 'exit'", export_spec->exit); 247 } 248 249 export->nid_table[cur_nid] = NID_MODULE_EXIT; 250 export->entry_table[cur_nid] = vita_elf_vaddr_to_host(ve, vaddr); 251 ++cur_nid; 252 } 253 254 export->nid_table[cur_nid] = NID_MODULE_INFO; 255 export->entry_table[cur_nid] = module_info; 256 ++cur_nid; 257 258 export->nid_table[cur_nid] = NID_PROCESS_PARAM; 259 export->entry_table[cur_nid] = &module_info->process_param_size; 260 ++cur_nid; 261 262 return 0; 263 264 failure: 265 return -1; 266 } 267 268 static void set_module_import(vita_elf_t *ve, sce_module_imports_t *import, const import_module *module) 269 { 270 int i; 271 272 import->size = sizeof(sce_module_imports_raw); 273 import->version = 1; 274 import->num_syms_funcs = module->functions_va.count; 275 import->num_syms_vars = module->variables_va.count; 276 import->module_nid = module->nid; 277 import->flags = module->module->flags; 278 279 if (module->module) { 280 import->module_name = module->module->name; 281 } 282 283 import->func_nid_table = calloc(module->functions_va.count, sizeof(uint32_t)); 284 import->func_entry_table = calloc(module->functions_va.count, sizeof(void *)); 285 for (i = 0; i < module->functions_va.count; i++) { 286 import->func_nid_table[i] = module->functions[i].target_nid; 287 import->func_entry_table[i] = vita_elf_vaddr_to_host(ve, module->functions[i].addr); 288 } 289 290 import->var_nid_table = calloc(module->variables_va.count, sizeof(uint32_t)); 291 import->var_entry_table = calloc(module->variables_va.count, sizeof(void *)); 292 for (i = 0; i < module->variables_va.count; i++) { 293 import->var_nid_table[i] = module->variables[i].target_nid; 294 import->var_entry_table[i] = vita_elf_vaddr_to_host(ve, module->variables[i].addr + 12); 295 } 296 } 297 298 sce_module_info_t *sce_elf_module_info_create(vita_elf_t *ve, vita_export_t *exports) 299 { 300 int i; 301 sce_module_info_t *module_info; 302 import_module_list modlist = {0}; 303 vita_elf_stub_t *curstub; 304 import_module *curmodule; 305 306 module_info = calloc(1, sizeof(sce_module_info_t)); 307 ASSERT(module_info != NULL); 308 309 module_info->type = 6; 310 module_info->version = (exports->ver_major << 8) | exports->ver_minor; 311 312 strncpy(module_info->name, exports->name, sizeof(module_info->name) - 1); 313 314 // allocate memory for all libraries + main 315 module_info->export_top = calloc(exports->module_n + 1, sizeof(sce_module_exports_t)); 316 ASSERT(module_info->export_top != NULL); 317 module_info->export_end = module_info->export_top + exports->module_n + 1; 318 319 if (set_main_module_export(ve, module_info->export_top, module_info, exports) < 0) { 320 goto sce_failure; 321 } 322 323 // populate rest of exports 324 for (i = 0; i < exports->module_n; ++i) { 325 vita_library_export *lib = exports->modules[i]; 326 sce_module_exports_t *exp = (sce_module_exports_t *)(module_info->export_top + i + 1); 327 328 // TODO: improve cleanup 329 if (set_module_export(ve, exp, lib) < 0) { 330 goto sce_failure; 331 } 332 } 333 334 ASSERT(varray_init(&modlist.va, sizeof(import_module), 8)); 335 modlist.va.init_func = _module_init; 336 modlist.va.destroy_func = _module_destroy; 337 modlist.va.sort_compar = _module_sort; 338 modlist.va.search_compar = _module_search; 339 340 for (i = 0; i < ve->num_fstubs; i++) { 341 curstub = ve->fstubs + i; 342 curmodule = varray_sorted_search_or_insert(&modlist.va, &curstub->module_nid, NULL); 343 ASSERT(curmodule); 344 curmodule->nid = curstub->module_nid; 345 if (curstub->module) 346 curmodule->module = curstub->module; 347 348 varray_sorted_insert_ex(&curmodule->functions_va, curstub, 0); 349 } 350 351 for (i = 0; i < ve->num_vstubs; i++) { 352 curstub = ve->vstubs + i; 353 curmodule = varray_sorted_search_or_insert(&modlist.va, &curstub->module_nid, NULL); 354 ASSERT(curmodule); 355 curmodule->nid = curstub->module_nid; 356 if (curstub->module) 357 curmodule->module = curstub->module; 358 359 varray_sorted_insert_ex(&curmodule->variables_va, curstub, 0); 360 } 361 362 module_info->import_top = calloc(modlist.va.count, sizeof(sce_module_imports_t)); 363 ASSERT(module_info->import_top != NULL); 364 module_info->import_end = module_info->import_top + modlist.va.count; 365 366 for (i = 0; i < modlist.va.count; i++) { 367 set_module_import(ve, module_info->import_top + i, modlist.modules + i); 368 } 369 370 return module_info; 371 372 failure: 373 varray_destroy(&modlist.va); 374 375 sce_failure: 376 sce_elf_module_info_free(module_info); 377 return NULL; 378 } 379 380 #define INCR(section, size) do { \ 381 sizes->section += (size); \ 382 total_size += (size); \ 383 } while (0) 384 int sce_elf_module_info_get_size(sce_module_info_t *module_info, sce_section_sizes_t *sizes) 385 { 386 int total_size = 0; 387 sce_module_exports_t *export; 388 sce_module_imports_t *import; 389 390 memset(sizes, 0, sizeof(*sizes)); 391 392 INCR(sceModuleInfo_rodata, sizeof(sce_module_info_raw)); 393 for (export = module_info->export_top; export < module_info->export_end; export++) { 394 INCR(sceLib_ent, sizeof(sce_module_exports_raw)); 395 if (export->module_name != NULL) { 396 INCR(sceExport_rodata, ALIGN_4(strlen(export->module_name) + 1)); 397 } 398 INCR(sceExport_rodata, (export->num_syms_funcs + export->num_syms_vars + export->num_syms_unk) * 8); 399 } 400 401 for (import = module_info->import_top; import < module_info->import_end; import++) { 402 INCR(sceLib_stubs, sizeof(sce_module_imports_raw)); 403 if (import->module_name != NULL) { 404 INCR(sceImport_rodata, ALIGN_4(strlen(import->module_name) + 1)); 405 } 406 INCR(sceFNID_rodata, import->num_syms_funcs * 4); 407 INCR(sceFStub_rodata, import->num_syms_funcs * 4); 408 INCR(sceVNID_rodata, import->num_syms_vars * 4); 409 INCR(sceVStub_rodata, import->num_syms_vars * 4); 410 INCR(sceImport_rodata, import->num_syms_unk * 8); 411 } 412 413 return total_size; 414 } 415 #undef INCR 416 417 void sce_elf_module_info_free(sce_module_info_t *module_info) 418 { 419 sce_module_exports_t *export; 420 sce_module_imports_t *import; 421 422 if (module_info == NULL) 423 return; 424 425 for (export = module_info->export_top; export < module_info->export_end; export++) { 426 free(export->nid_table); 427 free(export->entry_table); 428 } 429 free(module_info->export_top); 430 431 for (import = module_info->import_top; import < module_info->import_end; import++) { 432 free(import->func_nid_table); 433 free(import->func_entry_table); 434 free(import->var_nid_table); 435 free(import->var_entry_table); 436 free(import->unk_nid_table); 437 free(import->unk_entry_table); 438 } 439 440 free(module_info->import_top); 441 free(module_info); 442 } 443 444 #define INCR(section, size) do { \ 445 cur_sizes.section += (size); \ 446 if (cur_sizes.section > sizes->section) \ 447 FAILX("Attempted to overrun section %s!", #section); \ 448 section_addrs.section += (size); \ 449 } while (0) 450 #define ADDR(section) (data + section_addrs.section) 451 #define INTADDR(section) (*((uint32_t *)ADDR(section))) 452 #define VADDR(section) (section_addrs.section + segment_base + start_offset) 453 #define OFFSET(section) (section_addrs.section + start_offset) 454 #define CONVERT(variable, member, conversion) variable ## _raw->member = conversion(variable->member) 455 #define CONVERT16(variable, member) CONVERT(variable, member, htole16) 456 #define CONVERT32(variable, member) CONVERT(variable, member, htole32) 457 #define CONVERTOFFSET(variable, member) variable ## _raw->member = htole32(vita_elf_host_to_segoffset(ve,variable->member,segndx)) 458 #define SETLOCALPTR(variable, section) do { \ 459 variable = htole32(VADDR(section)); \ 460 ADDRELA(&variable); \ 461 } while(0) 462 #define ADDRELA(localaddr) do { \ 463 uint32_t addend = le32toh(*((uint32_t *)localaddr)); \ 464 if (addend) { \ 465 vita_elf_rela_t *rela = varray_push(&relas, NULL); \ 466 rela->type = R_ARM_ABS32; \ 467 rela->offset = ((void*)(localaddr)) - data + segment_base + start_offset; \ 468 rela->addend = addend; \ 469 } \ 470 } while(0) 471 void *sce_elf_module_info_encode( 472 const sce_module_info_t *module_info, const vita_elf_t *ve, const sce_section_sizes_t *sizes, 473 vita_elf_rela_table_t *rtable) 474 { 475 void *data; 476 sce_section_sizes_t cur_sizes = {0}; 477 sce_section_sizes_t section_addrs = {0}; 478 int total_size = 0; 479 Elf32_Addr segment_base; 480 Elf32_Word start_offset; 481 int segndx; 482 int i; 483 sce_module_exports_t *export; 484 sce_module_imports_t *import; 485 sce_module_info_raw *module_info_raw; 486 sce_module_exports_raw *export_raw; 487 sce_module_imports_raw *import_raw; 488 varray relas; 489 490 ASSERT(varray_init(&relas, sizeof(vita_elf_rela_t), 16)); 491 492 for (i = 0; i < sizeof(sce_section_sizes_t) / sizeof(Elf32_Word); i++) { 493 ((Elf32_Word *)§ion_addrs)[i] = total_size; 494 total_size += ((Elf32_Word *)sizes)[i]; 495 } 496 497 segndx = vita_elf_host_to_segndx(ve, module_info->module_start); 498 499 segment_base = ve->segments[segndx].vaddr; 500 start_offset = ve->segments[segndx].memsz; 501 start_offset = (start_offset + 0xF) & ~0xF; // align to 16 bytes 502 503 for (i = 0; i < ve->num_segments; i++) { 504 if (i == segndx) 505 continue; 506 if (ve->segments[i].vaddr >= segment_base + start_offset 507 && ve->segments[i].vaddr < segment_base + start_offset + total_size) 508 FAILX("Cannot allocate %d bytes for SCE data at end of segment %d; segment %d overlaps", 509 total_size, segndx, i); 510 } 511 512 data = calloc(1, total_size); 513 ASSERT(data != NULL); 514 515 module_info_raw = (sce_module_info_raw *)ADDR(sceModuleInfo_rodata); 516 INCR(sceModuleInfo_rodata, sizeof(sce_module_info_raw)); 517 CONVERT16(module_info, attributes); 518 CONVERT16(module_info, version); 519 memcpy(module_info_raw->name, module_info->name, 27); 520 module_info_raw->type = module_info->type; 521 module_info_raw->export_top = htole32(OFFSET(sceLib_ent)); 522 module_info_raw->export_end = htole32(OFFSET(sceLib_ent) + sizes->sceLib_ent); 523 module_info_raw->import_top = htole32(OFFSET(sceLib_stubs)); 524 module_info_raw->import_end = htole32(OFFSET(sceLib_stubs) + sizes->sceLib_stubs); 525 CONVERT32(module_info, library_nid); 526 CONVERT32(module_info, field_38); 527 CONVERT32(module_info, field_3C); 528 CONVERT32(module_info, field_40); 529 CONVERTOFFSET(module_info, module_start); 530 CONVERTOFFSET(module_info, module_stop); 531 CONVERTOFFSET(module_info, exidx_top); 532 CONVERTOFFSET(module_info, exidx_end); 533 CONVERTOFFSET(module_info, extab_top); 534 CONVERTOFFSET(module_info, extab_end); 535 module_info_raw->process_param_size = 0x34; 536 memcpy(&module_info_raw->process_param_magic, "PSP2", 4); 537 538 for (export = module_info->export_top; export < module_info->export_end; export++) { 539 int num_syms; 540 uint32_t *raw_nids, *raw_entries; 541 542 export_raw = (sce_module_exports_raw *)ADDR(sceLib_ent); 543 INCR(sceLib_ent, sizeof(sce_module_exports_raw)); 544 545 export_raw->size = htole16(sizeof(sce_module_exports_raw)); 546 CONVERT16(export, version); 547 CONVERT16(export, flags); 548 CONVERT16(export, num_syms_funcs); 549 CONVERT32(export, num_syms_vars); 550 CONVERT32(export, num_syms_unk); 551 CONVERT32(export, module_nid); 552 if (export->module_name != NULL) { 553 SETLOCALPTR(export_raw->module_name, sceExport_rodata); 554 void *dst = ADDR(sceExport_rodata); 555 INCR(sceExport_rodata, ALIGN_4(strlen(export->module_name) + 1)); 556 strcpy(dst, export->module_name); 557 } 558 num_syms = export->num_syms_funcs + export->num_syms_vars + export->num_syms_unk; 559 SETLOCALPTR(export_raw->nid_table, sceExport_rodata); 560 raw_nids = (uint32_t *)ADDR(sceExport_rodata); 561 INCR(sceExport_rodata, num_syms * 4); 562 SETLOCALPTR(export_raw->entry_table, sceExport_rodata); 563 raw_entries = (uint32_t *)ADDR(sceExport_rodata); 564 INCR(sceExport_rodata, num_syms * 4); 565 for (i = 0; i < num_syms; i++) { 566 raw_nids[i] = htole32(export->nid_table[i]); 567 if (export->entry_table[i] == module_info) { /* Special case */ 568 raw_entries[i] = htole32(segment_base + start_offset); 569 } else if (export->entry_table[i] == &module_info->process_param_size) { 570 raw_entries[i] = htole32(segment_base + start_offset + offsetof(sce_module_info_raw, process_param_size)); 571 } else { 572 raw_entries[i] = htole32(vita_elf_host_to_vaddr(ve, export->entry_table[i])); 573 } 574 ADDRELA(raw_entries + i); 575 } 576 } 577 578 for (import = module_info->import_top; import < module_info->import_end; import++) { 579 import_raw = (sce_module_imports_raw *)ADDR(sceLib_stubs); 580 INCR(sceLib_stubs, sizeof(sce_module_imports_raw)); 581 582 import_raw->size = htole16(sizeof(sce_module_imports_raw)); 583 CONVERT16(import, version); 584 CONVERT16(import, flags); 585 CONVERT16(import, num_syms_funcs); 586 CONVERT16(import, num_syms_vars); 587 CONVERT16(import, num_syms_unk); 588 CONVERT32(import, reserved1); 589 CONVERT32(import, reserved2); 590 CONVERT32(import, module_nid); 591 592 if (import->module_name != NULL) { 593 SETLOCALPTR(import_raw->module_name, sceImport_rodata); 594 void *dst = ADDR(sceImport_rodata); 595 INCR(sceImport_rodata, ALIGN_4(strlen(import->module_name) + 1)); 596 strcpy(dst, import->module_name); 597 } 598 if (import->num_syms_funcs) { 599 SETLOCALPTR(import_raw->func_nid_table, sceFNID_rodata); 600 SETLOCALPTR(import_raw->func_entry_table, sceFStub_rodata); 601 for (i = 0; i < import->num_syms_funcs; i++) { 602 INTADDR(sceFNID_rodata) = htole32(import->func_nid_table[i]); 603 INTADDR(sceFStub_rodata) = htole32(vita_elf_host_to_vaddr(ve, import->func_entry_table[i])); 604 ADDRELA(ADDR(sceFStub_rodata)); 605 INCR(sceFNID_rodata, 4); 606 INCR(sceFStub_rodata, 4); 607 } 608 } 609 if (import->num_syms_vars) { 610 SETLOCALPTR(import_raw->var_nid_table, sceVNID_rodata); 611 SETLOCALPTR(import_raw->var_entry_table, sceVStub_rodata); 612 for (i = 0; i < import->num_syms_vars; i++) { 613 INTADDR(sceVNID_rodata) = htole32(import->var_nid_table[i]); 614 INTADDR(sceVStub_rodata) = htole32(vita_elf_host_to_vaddr(ve, import->var_entry_table[i])); 615 ADDRELA(ADDR(sceVStub_rodata)); 616 INCR(sceVNID_rodata, 4); 617 INCR(sceVStub_rodata, 4); 618 } 619 } 620 if (import->num_syms_unk) { 621 SETLOCALPTR(import_raw->unk_nid_table, sceImport_rodata); 622 for (i = 0; i < import->num_syms_unk; i++) { 623 INTADDR(sceImport_rodata) = htole32(import->var_nid_table[i]); 624 INCR(sceImport_rodata, 4); 625 } 626 SETLOCALPTR(import_raw->unk_entry_table, sceImport_rodata); 627 for (i = 0; i < import->num_syms_unk; i++) { 628 INTADDR(sceImport_rodata) = htole32(vita_elf_host_to_vaddr(ve, import->var_entry_table[i])); 629 ADDRELA(ADDR(sceImport_rodata)); 630 INCR(sceImport_rodata, 4); 631 } 632 } 633 } 634 635 for (i = 0; i < sizeof(sce_section_sizes_t) / sizeof(Elf32_Word); i++) { 636 if (((Elf32_Word *)&cur_sizes)[i] != ((Elf32_Word *)sizes)[i]) 637 FAILX("sce_elf_module_info_encode() did not use all space in section %d!", i); 638 } 639 640 rtable->num_relas = relas.count; 641 rtable->relas = varray_extract_array(&relas); 642 643 return data; 644 failure: 645 free(data); 646 return NULL; 647 } 648 #undef INCR 649 #undef ADDR 650 #undef INTADDR 651 #undef VADDR 652 #undef OFFSET 653 #undef CONVERT 654 #undef CONVERT16 655 #undef CONVERT32 656 #undef CONVERTOFFSET 657 #undef SETLOCALPTR 658 #undef ADDRELA 659 660 int sce_elf_write_module_info( 661 Elf *dest, const vita_elf_t *ve, const sce_section_sizes_t *sizes, void *module_info) 662 { 663 /* Corresponds to the order in sce_section_sizes_t */ 664 static const char *section_names[] = { 665 ".sceModuleInfo.rodata", 666 ".sceLib.ent", 667 ".sceExport.rodata", 668 ".sceLib.stubs", 669 ".sceImport.rodata", 670 ".sceFNID.rodata", 671 ".sceFStub.rodata", 672 ".sceVNID.rodata", 673 ".sceVStub.rodata" 674 }; 675 GElf_Ehdr ehdr; 676 GElf_Shdr shdr; 677 GElf_Phdr phdr; 678 Elf_Scn *scn; 679 Elf_Data *data; 680 sce_section_sizes_t section_addrs = {0}; 681 int total_size = 0; 682 Elf32_Addr segment_base, start_vaddr; 683 Elf32_Word start_segoffset, start_foffset; 684 int cur_pos; 685 int segndx; 686 int i; 687 688 for (i = 0; i < sizeof(sce_section_sizes_t) / sizeof(Elf32_Word); i++) { 689 ((Elf32_Word *)§ion_addrs)[i] = total_size; 690 total_size += ((Elf32_Word *)sizes)[i]; 691 } 692 693 ELF_ASSERT(gelf_getehdr(dest, &ehdr)); 694 695 for (segndx = 0; segndx < ve->num_segments; segndx++) { 696 if (ehdr.e_entry >= ve->segments[segndx].vaddr 697 && ehdr.e_entry < ve->segments[segndx].vaddr + ve->segments[segndx].memsz) 698 break; 699 } 700 ASSERT(segndx < ve->num_segments); 701 702 ELF_ASSERT(gelf_getphdr(dest, segndx, &phdr)); 703 704 segment_base = ve->segments[segndx].vaddr; 705 start_segoffset = ve->segments[segndx].memsz; 706 start_segoffset = (start_segoffset + 0xF) & ~0xF; // align to 16 bytes, same with `sce_elf_module_info_encode` 707 total_size += (start_segoffset - ve->segments[segndx].memsz); // add the padding size 708 709 start_vaddr = segment_base + start_segoffset; 710 start_foffset = phdr.p_offset + start_segoffset; 711 cur_pos = 0; 712 713 if (!elf_utils_shift_contents(dest, start_foffset, total_size)) 714 FAILX("Unable to relocate ELF sections"); 715 716 /* Extend in our copy of phdrs so that vita_elf_vaddr_to_segndx can match it */ 717 ve->segments[segndx].memsz += total_size; 718 719 phdr.p_filesz += total_size; 720 phdr.p_memsz += total_size; 721 ELF_ASSERT(gelf_update_phdr(dest, segndx, &phdr)); 722 723 ELF_ASSERT(gelf_getehdr(dest, &ehdr)); 724 ehdr.e_entry = ((segndx & 0x3) << 30) | start_segoffset; 725 ELF_ASSERT(gelf_update_ehdr(dest, &ehdr)); 726 727 for (i = 0; i < sizeof(sce_section_sizes_t) / sizeof(Elf32_Word); i++) { 728 int scn_size = ((Elf32_Word *)sizes)[i]; 729 if (scn_size == 0) 730 continue; 731 732 scn = elf_utils_new_scn_with_name(dest, section_names[i]); 733 ELF_ASSERT(gelf_getshdr(scn, &shdr)); 734 shdr.sh_type = SHT_PROGBITS; 735 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 736 shdr.sh_addr = start_vaddr + cur_pos; 737 shdr.sh_offset = start_foffset + cur_pos; 738 shdr.sh_size = scn_size; 739 shdr.sh_addralign = 4; 740 ELF_ASSERT(gelf_update_shdr(scn, &shdr)); 741 742 ELF_ASSERT(data = elf_newdata(scn)); 743 data->d_buf = module_info + cur_pos; 744 data->d_type = ELF_T_BYTE; 745 data->d_version = EV_CURRENT; 746 data->d_size = scn_size; 747 data->d_off = 0; 748 data->d_align = 1; 749 750 cur_pos += scn_size; 751 } 752 753 return 1; 754 failure: 755 return 0; 756 } 757 758 static int sce_rel_short(SCE_Rel *rel, int symseg, int code, int datseg, int offset, int addend) 759 { 760 if (addend > 1 << 11) 761 return 0; 762 rel->r_short_entry.r_short = 1; 763 rel->r_short_entry.r_symseg = symseg; 764 rel->r_short_entry.r_code = code; 765 rel->r_short_entry.r_datseg = datseg; 766 rel->r_short_entry.r_offset_lo = offset & 0xFFF; 767 rel->r_short_entry.r_offset_hi = offset >> 20; 768 rel->r_short_entry.r_addend = addend; 769 return 1; 770 } 771 772 static int sce_rel_long(SCE_Rel *rel, int symseg, int code, int datseg, int offset, int addend) 773 { 774 rel->r_long_entry.r_short = 0; 775 rel->r_long_entry.r_symseg = symseg; 776 rel->r_long_entry.r_code = code; 777 rel->r_long_entry.r_datseg = datseg; 778 rel->r_long_entry.r_code2 = 0; 779 rel->r_long_entry.r_dist2 = 0; 780 rel->r_long_entry.r_offset = offset; 781 rel->r_long_entry.r_addend = addend; 782 return 1; 783 } 784 785 static int encode_sce_rel(SCE_Rel *rel) 786 { 787 if (rel->r_short_entry.r_short) { 788 rel->r_raw_entry.r_word1 = htole32( 789 (rel->r_short_entry.r_short) | 790 (rel->r_short_entry.r_symseg << 4) | 791 (rel->r_short_entry.r_code << 8) | 792 (rel->r_short_entry.r_datseg << 16) | 793 (rel->r_short_entry.r_offset_lo << 20)); 794 rel->r_raw_entry.r_word2 = htole32( 795 (rel->r_short_entry.r_offset_hi) | 796 (rel->r_short_entry.r_addend << 20)); 797 798 return 8; 799 } else { 800 rel->r_raw_entry.r_word1 = htole32( 801 (rel->r_long_entry.r_short) | 802 (rel->r_long_entry.r_symseg << 4) | 803 (rel->r_long_entry.r_code << 8) | 804 (rel->r_long_entry.r_datseg << 16) | 805 (rel->r_long_entry.r_code2 << 20) | 806 (rel->r_long_entry.r_dist2 << 28)); 807 rel->r_raw_entry.r_word2 = htole32(rel->r_long_entry.r_addend); 808 rel->r_raw_entry.r_word3 = htole32(rel->r_long_entry.r_offset); 809 return 12; 810 } 811 } 812 813 /* We have to check all relocs. If any of the point to a space in ELF that is not contained in any segment, 814 * we should discard this reloc. This should be done before we extend the code segment with modinfo, because otherwise 815 * the invalid addresses may become valid */ 816 int sce_elf_discard_invalid_relocs(const vita_elf_t *ve, vita_elf_rela_table_t *rtable) { 817 vita_elf_rela_table_t *curtable; 818 vita_elf_rela_t *vrela; 819 int i, datseg; 820 for (curtable = rtable; curtable; curtable = curtable->next) { 821 for (i = 0, vrela = curtable->relas; i < curtable->num_relas; i++, vrela++) { 822 if (vrela->type == R_ARM_NONE || (vrela->symbol && vrela->symbol->shndx == 0)) { 823 vrela->type = R_ARM_NONE; 824 continue; 825 } 826 /* We skip relocations that are not real relocations 827 * In all current tested output, we have that the unrelocated value is correct. 828 * However, there is nothing that says this has to be the case. SCE RELS 829 * does not support ABS value relocations anymore, so there's not much 830 * we can do. */ 831 // TODO: Consider a better solution for this. 832 if (vrela->symbol && (vrela->symbol->shndx == SHN_ABS || vrela->symbol->shndx == SHN_COMMON)) { 833 vrela->type = R_ARM_NONE; 834 continue; 835 } 836 datseg = vita_elf_vaddr_to_segndx(ve, vrela->offset); 837 /* We can get -1 here for some debugging-related relocations. 838 * These are done against debug sections that aren't mapped to any segment. 839 * Just ignore these */ 840 if (datseg == -1) 841 vrela->type = R_ARM_NONE; 842 } 843 } 844 return 1; 845 } 846 847 int sce_elf_write_rela_sections( 848 Elf *dest, const vita_elf_t *ve, const vita_elf_rela_table_t *rtable) 849 { 850 int total_relas = 0; 851 const vita_elf_rela_table_t *curtable; 852 const vita_elf_rela_t *vrela; 853 void *encoded_relas = NULL, *curpos; 854 SCE_Rel rel; 855 int relsz; 856 int i; 857 Elf32_Addr symvaddr; 858 Elf32_Word symseg, symoff; 859 Elf32_Word datseg, datoff; 860 int (*sce_rel_func)(SCE_Rel *, int, int, int, int, int); 861 862 Elf_Scn *scn; 863 GElf_Shdr shdr; 864 GElf_Phdr *phdrs; 865 size_t segment_count = 0; 866 867 for (curtable = rtable; curtable; curtable = curtable->next) 868 total_relas += curtable->num_relas; 869 870 ASSERT(encoded_relas = calloc(total_relas, 12)); 871 872 // sce_rel_func = sce_rel_short; 873 sce_rel_func = sce_rel_long; 874 875 encode_relas: 876 curpos = encoded_relas; 877 878 for (curtable = rtable; curtable; curtable = curtable->next) { 879 for (i = 0, vrela = curtable->relas; i < curtable->num_relas; i++, vrela++) { 880 if (vrela->type == R_ARM_NONE) 881 continue; 882 datseg = vita_elf_vaddr_to_segndx(ve, vrela->offset); 883 datoff = vita_elf_vaddr_to_segoffset(ve, vrela->offset, datseg); 884 if (vrela->symbol) { 885 symvaddr = vrela->symbol->value + vrela->addend; 886 } else { 887 symvaddr = vrela->addend; 888 } 889 symseg = vita_elf_vaddr_to_segndx(ve, vrela->symbol ? vrela->symbol->value : vrela->addend); 890 if (symseg == -1) 891 continue; 892 symoff = vita_elf_vaddr_to_segoffset(ve, symvaddr, symseg); 893 if (!sce_rel_func(&rel, symseg, vrela->type, datseg, datoff, symoff)) { 894 sce_rel_func = sce_rel_long; 895 goto encode_relas; 896 } 897 relsz = encode_sce_rel(&rel); 898 memcpy(curpos, &rel, relsz); 899 curpos += relsz; 900 } 901 } 902 903 scn = elf_utils_new_scn_with_data(dest, ".sce.rel", encoded_relas, curpos - encoded_relas); 904 if (scn == NULL) 905 goto failure; 906 encoded_relas = NULL; 907 908 ELF_ASSERT(gelf_getshdr(scn, &shdr)); 909 shdr.sh_type = SHT_SCE_RELA; 910 shdr.sh_flags = 0; 911 shdr.sh_addralign = 4; 912 ELF_ASSERT(gelf_update_shdr(scn, &shdr)); 913 914 ELF_ASSERT((elf_getphdrnum(dest, &segment_count), segment_count > 0)); 915 ASSERT(phdrs = calloc(segment_count + 1, sizeof(GElf_Phdr))); 916 for (i = 0; i < segment_count; i++) { 917 ELF_ASSERT(gelf_getphdr(dest, i, phdrs + i)); 918 } 919 ELF_ASSERT(gelf_newphdr(dest, segment_count + 1)); 920 ELF_ASSERT(gelf_getphdr(dest, segment_count, phdrs + segment_count)); 921 phdrs[segment_count].p_type = PT_SCE_RELA; 922 phdrs[segment_count].p_offset = shdr.sh_offset; 923 phdrs[segment_count].p_filesz = shdr.sh_size; 924 phdrs[segment_count].p_align = 16; 925 for (i = 0; i < segment_count + 1; i++) { 926 ELF_ASSERT(gelf_update_phdr(dest, i, phdrs + i)); 927 } 928 929 return 1; 930 931 failure: 932 free(encoded_relas); 933 return 0; 934 } 935 936 int sce_elf_rewrite_stubs(Elf *dest, const vita_elf_t *ve) 937 { 938 Elf_Scn *scn; 939 GElf_Shdr shdr; 940 Elf_Data *data; 941 size_t shstrndx; 942 void *shstrtab; 943 uint32_t *stubdata; 944 int j; 945 int *cur_ndx; 946 char *sh_name, *stub_name; 947 948 ELF_ASSERT(elf_getshdrstrndx(dest, &shstrndx) == 0); 949 ELF_ASSERT(scn = elf_getscn(dest, shstrndx)); 950 ELF_ASSERT(data = elf_getdata(scn, NULL)); 951 shstrtab = data->d_buf; 952 953 for(j=0;j<ve->fstubs_va.count;j++){ 954 cur_ndx = VARRAY_ELEMENT(&ve->fstubs_va,j); 955 ELF_ASSERT(scn = elf_getscn(dest, *cur_ndx)); 956 ELF_ASSERT(gelf_getshdr(scn, &shdr)); 957 958 sh_name = shstrtab + shdr.sh_name; 959 if (strstr(sh_name, ".vitalink.fstubs.") != sh_name) 960 errx(EXIT_FAILURE, "Your ELF file contains a malformed .vitalink.fstubs section. Please make sure all your stub libraries are up-to-date."); 961 stub_name = strrchr(sh_name, '.'); 962 snprintf(sh_name, strlen(sh_name) + 1, ".text.fstubs%s", stub_name); 963 964 data = NULL; 965 while ((data = elf_getdata(scn, data)) != NULL) { 966 for (stubdata = (uint32_t *)data->d_buf; 967 (void *)stubdata < data->d_buf + data->d_size - 11; stubdata += 4) { 968 stubdata[0] = htole32(sce_elf_stub_func[0]); 969 stubdata[1] = htole32(sce_elf_stub_func[1]); 970 stubdata[2] = htole32(sce_elf_stub_func[2]); 971 stubdata[3] = 0; 972 } 973 } 974 } 975 976 977 /* If the section index is zero, it means that it's nonexistent */ 978 if (ve->vstubs_va.count == 0) { 979 return 1; 980 } 981 982 for(j=0;j<ve->vstubs_va.count;j++){ 983 cur_ndx = VARRAY_ELEMENT(&ve->vstubs_va,j); 984 ELF_ASSERT(scn = elf_getscn(dest, *cur_ndx)); 985 ELF_ASSERT(gelf_getshdr(scn, &shdr)); 986 987 sh_name = shstrtab + shdr.sh_name; 988 if (strstr(sh_name, ".vitalink.vstubs.") != sh_name) 989 errx(EXIT_FAILURE, "Your ELF file contains a malformed .vitalink.vstubs section. Please make sure all your stub libraries are up-to-date."); 990 stub_name = strrchr(sh_name, '.'); 991 snprintf(sh_name, strlen(sh_name) + 1, ".data.vstubs%s", stub_name); 992 993 data = NULL; 994 while ((data = elf_getdata(scn, data)) != NULL) { 995 uint32_t off = shdr.sh_addr + data->d_off; 996 for (stubdata = (uint32_t *)data->d_buf; 997 (void *)stubdata < data->d_buf + data->d_size - 11; stubdata += 8) { 998 stubdata[0] = htole32(sce_elf_stub_var_func[0]); 999 stubdata[1] = htole32(sce_elf_stub_var_func[1]); 1000 stubdata[2] = htole32(sce_elf_stub_var_func[2]); 1001 stubdata[3] = htole32(sce_elf_stub_var_func[3]); 1002 stubdata[4] = htole32(sce_elf_stub_var_func[4]); 1003 stubdata[5] = htole32(off); // addr 1004 stubdata[6] = htole32(sce_elf_stub_var_func[6]); 1005 stubdata[7] = htole32(off + 4); // addr+4 1006 off += 32; 1007 } 1008 } 1009 } 1010 1011 return 1; 1012 failure: 1013 return 0; 1014 } 1015 1016 int sce_elf_set_headers(FILE *destfile, const vita_elf_t *ve) 1017 { 1018 Elf32_Ehdr ehdr; 1019 1020 ehdr.e_type = htole16(ET_SCE_RELEXEC); 1021 1022 SYS_ASSERT(fseek(destfile, offsetof(Elf32_Ehdr, e_type), SEEK_SET)); 1023 SYS_ASSERT(fwrite(&ehdr.e_type, sizeof(ehdr.e_type), 1, destfile)); 1024 1025 return 1; 1026 failure: 1027 return 0; 1028 }