vita-elf-create.c (7067B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdint.h> 4 #include <string.h> 5 6 #include <limits.h> 7 8 #include <libelf.h> 9 #include <gelf.h> 10 11 #include "vita-elf.h" 12 #include "vita-import.h" 13 #include "vita-export.h" 14 #include "elf-defs.h" 15 #include "sce-elf.h" 16 #include "elf-utils.h" 17 #include "fail-utils.h" 18 #include "elf-create-argp.h" 19 20 // logging level 21 int g_log = 0; 22 23 #define NONE 0 24 #define VERBOSE 1 25 #define DEBUG 2 26 27 #define TRACEF(lvl, ...) \ 28 do { if (g_log >= lvl) printf(__VA_ARGS__); } while (0) 29 30 void print_stubs(vita_elf_stub_t *stubs, int num_stubs) 31 { 32 int i; 33 34 for (i = 0; i < num_stubs; i++) { 35 TRACEF(VERBOSE, " 0x%06x (%s):\n", stubs[i].addr, stubs[i].symbol ? stubs[i].symbol->name : "unreferenced stub"); 36 TRACEF(VERBOSE, " Flags : %u\n", stubs[i].module ? stubs[i].module->flags : 0); 37 TRACEF(VERBOSE, " Library: %u (%s)\n", stubs[i].module_nid, stubs[i].module ? stubs[i].module->name : "not found"); 38 TRACEF(VERBOSE, " NID : %u (%s)\n", stubs[i].target_nid, stubs[i].target ? stubs[i].target->name : "not found"); 39 } 40 } 41 42 const char *get_scn_name(vita_elf_t *ve, Elf_Scn *scn) 43 { 44 size_t shstrndx; 45 GElf_Shdr shdr; 46 47 elf_getshdrstrndx(ve->elf, &shstrndx); 48 gelf_getshdr(scn, &shdr); 49 return elf_strptr(ve->elf, shstrndx, shdr.sh_name); 50 } 51 52 const char *get_scndx_name(vita_elf_t *ve, int scndx) 53 { 54 return get_scn_name(ve, elf_getscn(ve->elf, scndx)); 55 } 56 57 void print_rtable(vita_elf_rela_table_t *rtable) 58 { 59 vita_elf_rela_t *rela; 60 int num_relas; 61 62 for (num_relas = rtable->num_relas, rela = rtable->relas; num_relas; num_relas--, rela++) { 63 if (rela->symbol) { 64 TRACEF(VERBOSE, " offset %06x: type %s, %s%+d\n", 65 rela->offset, 66 elf_decode_r_type(rela->type), 67 rela->symbol->name, rela->addend); 68 } else if (rela->offset) { 69 TRACEF(VERBOSE, " offset %06x: type %s, absolute %06x\n", 70 rela->offset, 71 elf_decode_r_type(rela->type), 72 (uint32_t)rela->addend); 73 } 74 } 75 } 76 77 void list_rels(vita_elf_t *ve) 78 { 79 vita_elf_rela_table_t *rtable; 80 81 for (rtable = ve->rela_tables; rtable; rtable = rtable->next) { 82 TRACEF(VERBOSE, " Relocations for section %d: %s\n", 83 rtable->target_ndx, get_scndx_name(ve, rtable->target_ndx)); 84 print_rtable(rtable); 85 86 } 87 } 88 89 void list_segments(vita_elf_t *ve) 90 { 91 int i; 92 93 for (i = 0; i < ve->num_segments; i++) { 94 TRACEF(VERBOSE, " Segment %d: vaddr %06x, size 0x%x\n", 95 i, ve->segments[i].vaddr, ve->segments[i].memsz); 96 if (ve->segments[i].memsz) { 97 TRACEF(VERBOSE, " Host address region: %p - %p\n", 98 ve->segments[i].vaddr_top, ve->segments[i].vaddr_bottom); 99 TRACEF(VERBOSE, " 4 bytes into segment (%p): %x\n", 100 ve->segments[i].vaddr_top + 4, vita_elf_host_to_vaddr(ve, ve->segments[i].vaddr_top + 4)); 101 TRACEF(VERBOSE, " addr of 8 bytes into segment (%x): %p\n", 102 ve->segments[i].vaddr + 8, vita_elf_vaddr_to_host(ve, ve->segments[i].vaddr + 8)); 103 TRACEF(VERBOSE, " 12 bytes into segment offset (%p): %d\n", 104 ve->segments[i].vaddr_top + 12, vita_elf_host_to_segoffset(ve, ve->segments[i].vaddr_top + 12, i)); 105 TRACEF(VERBOSE, " addr of 16 bytes into segment (%d): %p\n", 106 16, vita_elf_segoffset_to_host(ve, i, 16)); 107 } 108 } 109 } 110 111 #if defined(_WIN32) && !defined(__CYGWIN__) 112 #define WIN32_LEAN_AND_MEAN 113 #include <windows.h> 114 #define strtok_r strtok_s 115 #elif defined(__linux__) || defined(__CYGWIN__) 116 #include <unistd.h> 117 #elif defined(__APPLE__) 118 #include <mach-o/dyld.h> 119 #elif defined(__FreeBSD__) 120 #include <sys/types.h> 121 #include <sys/sysctl.h> 122 #endif 123 124 static int usage(int argc, char *argv[]) 125 { 126 fprintf(stderr, "usage: %s [-v|vv|vvv] [-n] [-e config.yml] input.elf output.velf\n" 127 "\t-v,-vv,-vvv: logging verbosity (more v is more verbose)\n" 128 "\t-n : allow empty imports\n" 129 "\t-e yml : optional config options\n" 130 "\tinput.elf : input ARM ET_EXEC type ELF\n" 131 "\toutput.velf: output ET_SCE_RELEXEC type ELF\n", argc > 0 ? argv[0] : "vita-elf-create"); 132 return 0; 133 } 134 135 int main(int argc, char *argv[]) 136 { 137 vita_elf_t *ve; 138 sce_module_info_t *module_info; 139 sce_section_sizes_t section_sizes; 140 void *encoded_modinfo; 141 vita_elf_rela_table_t rtable = {}; 142 vita_export_t *exports = NULL; 143 144 int status = EXIT_SUCCESS; 145 146 elf_create_args args = {}; 147 if (parse_arguments(argc, argv, &args) < 0) { 148 usage(argc, argv); 149 return EXIT_FAILURE; 150 } 151 152 g_log = args.log_level; 153 154 if ((ve = vita_elf_load(args.input, args.check_stub_count)) == NULL) 155 return EXIT_FAILURE; 156 157 /* FIXME: save original segment sizes */ 158 Elf32_Word *segment_sizes = malloc(ve->num_segments * sizeof(Elf32_Word)); 159 int idx; 160 for(idx = 0; idx < ve->num_segments; idx++) 161 segment_sizes[idx] = ve->segments[idx].memsz; 162 163 if (args.exports) { 164 exports = vita_exports_load(args.exports, args.input, 0); 165 166 if (!exports) 167 return EXIT_FAILURE; 168 } 169 else { 170 // generate a default export list 171 exports = vita_export_generate_default(args.input); 172 } 173 174 if (!vita_elf_lookup_imports(ve)) 175 status = EXIT_FAILURE; 176 177 if (ve->fstubs_va.count) { 178 TRACEF(VERBOSE, "Function stubs in sections \n"); 179 print_stubs(ve->fstubs, ve->num_fstubs); 180 } 181 if (ve->vstubs_va.count) { 182 TRACEF(VERBOSE, "Variable stubs in sections \n"); 183 print_stubs(ve->vstubs, ve->num_vstubs); 184 } 185 186 TRACEF(VERBOSE, "Relocations:\n"); 187 list_rels(ve); 188 189 TRACEF(VERBOSE, "Segments:\n"); 190 list_segments(ve); 191 192 module_info = sce_elf_module_info_create(ve, exports); 193 194 if (!module_info) 195 return EXIT_FAILURE; 196 197 int total_size = sce_elf_module_info_get_size(module_info, §ion_sizes); 198 int curpos = 0; 199 TRACEF(VERBOSE, "Total SCE data size: %d / %x\n", total_size, total_size); 200 #define PRINTSEC(name) TRACEF(VERBOSE, " .%.*s.%s: %d (%x @ %x)\n", (int)strcspn(#name,"_"), #name, strchr(#name,'_')+1, section_sizes.name, section_sizes.name, curpos+ve->segments[0].vaddr+ve->segments[0].memsz); curpos += section_sizes.name 201 PRINTSEC(sceModuleInfo_rodata); 202 PRINTSEC(sceLib_ent); 203 PRINTSEC(sceExport_rodata); 204 PRINTSEC(sceLib_stubs); 205 PRINTSEC(sceImport_rodata); 206 PRINTSEC(sceFNID_rodata); 207 PRINTSEC(sceFStub_rodata); 208 PRINTSEC(sceVNID_rodata); 209 PRINTSEC(sceVStub_rodata); 210 211 encoded_modinfo = sce_elf_module_info_encode( 212 module_info, ve, §ion_sizes, &rtable); 213 214 TRACEF(VERBOSE, "Relocations from encoded modinfo:\n"); 215 print_rtable(&rtable); 216 217 FILE *outfile; 218 Elf *dest; 219 ASSERT(dest = elf_utils_copy_to_file(args.output, ve->elf, &outfile)); 220 ASSERT(elf_utils_duplicate_shstrtab(dest)); 221 ASSERT(sce_elf_discard_invalid_relocs(ve, ve->rela_tables)); 222 ASSERT(sce_elf_write_module_info(dest, ve, §ion_sizes, encoded_modinfo)); 223 rtable.next = ve->rela_tables; 224 ASSERT(sce_elf_write_rela_sections(dest, ve, &rtable)); 225 ASSERT(sce_elf_rewrite_stubs(dest, ve)); 226 ELF_ASSERT(elf_update(dest, ELF_C_WRITE) >= 0); 227 elf_end(dest); 228 ASSERT(sce_elf_set_headers(outfile, ve)); 229 fclose(outfile); 230 231 /* FIXME: restore original segment sizes */ 232 for(idx = 0; idx < ve->num_segments; idx++) 233 ve->segments[idx].memsz = segment_sizes[idx]; 234 free(segment_sizes); 235 236 sce_elf_module_info_free(module_info); 237 vita_elf_free(ve); 238 239 return status; 240 failure: 241 return EXIT_FAILURE; 242 }