vita-toolchain

git clone https://git.neptards.moe/neptards/vita-toolchain.git
Log | Files | Refs | README | LICENSE

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 *)&section_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 *)&section_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 }