Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 350 lines (338 sloc) 11.171 kb
f9b418b Added load module and resolve external loads.
Yifan Lu authored
1 #include "load.h"
8331c62 Added string function from androids bionic libc and string search fro…
Yifan Lu authored
2 #include "resolve.h"
3 #include "scefuncs.h"
4 #include "utils.h"
9551038 first commit.
Yifan Lu authored
5
79e2bb1 Added doxygen code documentation
Yifan Lu authored
6 /********************************************//**
7 * \brief Loads an supported executable
8 *
9 * This function identifies and loads a
10 * executable at the given file.
11 * Currently supports ELF and SCE executable.
12 * \returns Zero on success, otherwise error
13 ***********************************************/
14 int
15 uvl_load_exe (const char *filename, ///< Absolute path to executable
16 void **entry) ///< Returned pointer to entry pointer
9551038 first commit.
Yifan Lu authored
17 {
18 char magic[4];
f9b418b Added load module and resolve external loads.
Yifan Lu authored
19
20 *entry = NULL;
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
21 IF_DEBUG LOG ("Opening %s for reading.", filename);
9551038 first commit.
Yifan Lu authored
22 SceUID fd = sceIoOpen (filename, SCE_O_RDONLY, SCE_STM_RU);
23 if (fd < 0)
24 {
25 LOG ("Cannot open executable file for loading.");
26 return -1;
27 }
28
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
29 IF_DEBUG LOG ("Reading magic number.");
9551038 first commit.
Yifan Lu authored
30 if (sceIoRead (fd, magic, MAGIC_LEN) < MAGIC_LEN)
31 {
32 LOG ("Cannot read magic number.");
33 return -1;
34 }
35
36 if (magic[0] == ELFMAG0)
37 {
38 if (magic[1] == ELFMAG1 && magic[2] == ELFMAG2 && magic[3] == ELFMAG3)
39 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
40 IF_DEBUG LOG ("Found a ELF, loading.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
41 return uvl_load_elf (fd, 0, entry);
9551038 first commit.
Yifan Lu authored
42 }
43 }
44 else if (magic[0] == SCEMAG0)
45 {
46 if (magic[1] == ELFMAG1 && magic[2] == ELFMAG2 && magic[3] == ELFMAG3)
47 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
48 IF_DEBUG LOG ("Found a SCE, seeking to ELF.");
9551038 first commit.
Yifan Lu authored
49 if (sceIoLseek (fd, SCEHDR_LEN, SCE_SEEK_SET) < 0)
50 {
51 LOG ("Cannot skip SCE header.");
52 return -1;
53 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
54 IF_DEBUG LOG ("Loading ELF.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
55 return uvl_load_elf (fd, SCEHDR_LEN, entry);
9551038 first commit.
Yifan Lu authored
56 }
57 }
58
8813360 Added work on stubs for loader. Work on cleanup.
Yifan Lu authored
59 // close file
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
60 IF_DEBUG LOG ("Closing executable file.");
8813360 Added work on stubs for loader. Work on cleanup.
Yifan Lu authored
61 if (sceIoClose (fd) < 0)
62 {
63 LOG ("Cannot close executable %s after loading.", filename);
64 return -1;
65 }
66
9551038 first commit.
Yifan Lu authored
67 LOG ("Invalid magic.");
68 return -1;
69 }
70
79e2bb1 Added doxygen code documentation
Yifan Lu authored
71 /********************************************//**
72 * \brief Loads an ELF file
73 *
74 * Performs both loading and resolving NIDs
75 * \returns Zero on success, otherwise error
76 ***********************************************/
77 int
78 uvl_load_elf (SceUID fd, ///< File descriptor for ELF
79 SceOff start_offset, ///< Starting position of the ELF in file
80 void **entry) ///< Returned pointer to entry pointer
9551038 first commit.
Yifan Lu authored
81 {
82 Elf32_Ehdr_t elf_hdr;
83 module_info_t mod_info;
f9b418b Added load module and resolve external loads.
Yifan Lu authored
84 Elf32_Phdr_t prog_hdr;
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
85 void *base_address = (void*)(u32_t)-1;
f9b418b Added load module and resolve external loads.
Yifan Lu authored
86 module_imports_t *import;
9551038 first commit.
Yifan Lu authored
87 int i;
f9b418b Added load module and resolve external loads.
Yifan Lu authored
88
89 *entry = NULL;
9551038 first commit.
Yifan Lu authored
90 // get headers
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
91 IF_DEBUG LOG ("Reading headers.");
9551038 first commit.
Yifan Lu authored
92 if (sceIoRead (fd, &elf_hdr, sizeof (Elf32_Ehdr_t)) < sizeof (Elf32_Ehdr_t))
93 {
94 LOG ("Error reading ELF header.");
95 return -1;
96 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
97 IF_DEBUG LOG ("Checking headers.");
9551038 first commit.
Yifan Lu authored
98 if (uvl_check_elf_header (&elf_hdr) < 0)
99 {
100 LOG ("Check header failed.");
101 return -1;
102 }
103 // get mod_info
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
104 IF_DEBUG LOG ("Getting module info.");
9551038 first commit.
Yifan Lu authored
105 if (uvl_get_module_info (fd, start_offset, &elf_hdr, &mod_info) < 0)
106 {
107 LOG ("Cannot find module info section.");
108 return -1;
109 }
f9b418b Added load module and resolve external loads.
Yifan Lu authored
110 // actually load the ELF
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
111 IF_DEBUG LOG ("Found %d program sections.", elf_hdr.e_phnum);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
112 for (i = 0; i < elf_hdr.e_phnum; i++)
113 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
114 IF_DEBUG LOG ("Seeking program header #%d.", i);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
115 if (sceIoLseek (fd, start_offset + elf_hdr.e_phoff + i * elf_hdr.e_phentsize, SCE_SEEK_SET) < 0)
116 {
117 LOG ("Error seeking program header.");
118 return -1;
119 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
120 IF_DEBUG LOG ("Reading program header.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
121 if (sceIoRead (fd, &prog_hdr, elf_hdr.e_phentsize) < elf_hdr.e_phentsize)
122 {
123 LOG ("Error reading program header.");
124 return -1;
125 }
126 if (prog_hdr.p_vaddr < base_address) // lowest number is base address
127 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
128 IF_DEBUG LOG ("Possible base address: 0x%X.", (u32_t)base_address);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
129 base_address = prog_hdr.p_vaddr;
130 }
131 // TODO: Alloc memory to load and set permissions
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
132 IF_DEBUG LOG ("Seeking to program.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
133 if (sceIoLseek (fd, start_offset + prog_hdr.p_offset, SCE_SEEK_SET) < 0)
134 {
135 LOG ("Error seeking to section %d.", i);
136 return -1;
137 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
138 IF_DEBUG LOG ("Loading program to memory at 0x%X.", (u32_t)prog_hdr.p_vaddr);
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
139 if (sceIoRead (fd, prog_hdr.p_vaddr, prog_hdr.p_filesz) < 0)
f9b418b Added load module and resolve external loads.
Yifan Lu authored
140 {
141 LOG ("Error reading program section %d.", i);
142 return -1;
143 }
144 if (prog_hdr.p_memsz > prog_hdr.p_filesz)
145 {
146 // specs say we have to zero out extra bytes
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
147 IF_DEBUG LOG ("Adding %d bytes of padding.", prog_hdr.p_memsz - prog_hdr.p_filesz);
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
148 memset ((char*)prog_hdr.p_vaddr + prog_hdr.p_filesz, 0, prog_hdr.p_memsz - prog_hdr.p_filesz);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
149 }
150 }
151 // resolve NIDs
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
152 IF_DEBUG LOG ("Resolving NID imports.");
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
153 for (import = (module_imports_t*)((char*)base_address + mod_info.stub_top); (void*)import < (void*)((char*)base_address + mod_info.stub_end); import++)
f9b418b Added load module and resolve external loads.
Yifan Lu authored
154 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
155 IF_DEBUG LOG ("Loading required module %s.", import->lib_name);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
156 if (uvl_load_module (import->lib_name) < 0)
157 {
158 LOG ("Error loading required module: %s", import->lib_name);
159 return -1;
160 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
161 IF_DEBUG LOG ("Queuing required importes for module.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
162 if (uvl_add_unresolved_imports (import) < 0)
163 {
164 LOG ("Failed to add imports for module: %s", import->lib_name);
165 return -1;
166 }
167 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
168 IF_DEBUG LOG ("Adding modules' exports to resolve table.");
60c3f2e Added some stuff.
Yifan Lu authored
169 if (uvl_resolve_all_loaded_modules (RESOLVE_MOD_EXPS) < 0)
f9b418b Added load module and resolve external loads.
Yifan Lu authored
170 {
171 LOG ("Failed to resolve module exports.");
172 return -1;
173 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
174 IF_DEBUG LOG ("Attempting to resolve homebrew.");
f9b418b Added load module and resolve external loads.
Yifan Lu authored
175 if (uvl_resolve_all_unresolved () < 0)
176 {
177 LOG ("Failed to resolve app imports.");
178 return -1;
179 }
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
180 *entry = (void*)((u32_t)base_address + (u32_t)elf_hdr.e_entry);
f9b418b Added load module and resolve external loads.
Yifan Lu authored
181 return 0;
9551038 first commit.
Yifan Lu authored
182 }
183
79e2bb1 Added doxygen code documentation
Yifan Lu authored
184 /********************************************//**
185 * \brief Loads a system module by name
186 *
187 * \returns Zero on success, otherwise error
188 ***********************************************/
189 int
190 uvl_load_module (char *name) ///< Name of module to load
191 {
192 // TODO: Get filename for mod name and load module
193 }
194
195 /********************************************//**
196 * \brief Validates ELF header
197 *
198 * Makes sure the ELF is recognized by the
199 * Vita's architecture.
200 * \returns Zero if valid, otherwise invalid
201 ***********************************************/
202 int
203 uvl_check_elf_header (Elf32_Ehdr_t *hdr) ///< ELF header to check
9551038 first commit.
Yifan Lu authored
204 {
205 // magic number
206 if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 && hdr->e_ident[EI_MAG1] == ELFMAG1 && hdr->e_ident[EI_MAG2] == ELFMAG2 && hdr->e_ident[EI_MAG3] == ELFMAG3))
207 {
208 LOG ("Invalid ELF magic number.");
209 return -1;
210 }
211 // class
212 if (!(hdr->e_ident[EI_CLASS] == ELFCLASS32))
213 {
214 LOG ("Not a 32bit executable.");
215 return -1;
216 }
217 // data
218 if (!(hdr->e_ident[EI_DATA] == ELFDATA2LSB))
219 {
220 LOG ("Not a valid ARM executable.");
221 return -1;
222 }
223 // version
224 if (!(hdr->e_ident[EI_VERSION] == EV_CURRENT))
225 {
226 LOG ("Unsupported ELF version.");
227 return -1;
228 }
229 // type
230 if (!(hdr->e_type == ET_EXEC))
231 {
232 LOG ("Only ET_EXEC files can be loaded currently.");
233 return -1;
234 }
235 // machine
236 if (!(hdr->e_machine == EM_ARM))
237 {
238 LOG ("Not an ARM executable.");
239 return -1;
240 }
241 // version
242 if (!(hdr->e_version == EV_CURRENT))
243 {
244 LOG ("Unsupported ELF version.");
245 return -1;
246 }
247 // contains headers
248 if (!(hdr->e_shoff > 0 && hdr->e_phoff > 0))
249 {
250 LOG ("Missing table header(s).");
251 return -1;
252 }
253 // contains strings
254 if (!(hdr->e_shstrndx > 0))
255 {
256 LOG ("Missing strings table.");
257 return -1;
258 }
259 return 0;
260 }
261
79e2bb1 Added doxygen code documentation
Yifan Lu authored
262 /********************************************//**
263 * \brief Finds SCE module info
264 *
265 * This function locates the strings table
266 * and finds the section where the module
267 * information resides. Then it reads the
268 * module information. This function will
269 * move the pointer in the file descriptor.
270 * \returns Zero on success, otherwise error
271 ***********************************************/
272 int
273 uvl_get_module_info (SceUID fd, ///< File descriptor for the ELF
274 SceOff start_offset, ///< Starting position of the ELF in file
275 Elf32_Ehdr_t *elf_hdr, ///< ELF header
276 module_info_t *mod_info) ///< Where to read information to
9551038 first commit.
Yifan Lu authored
277 {
278 Elf32_Shdr_t sec_hdr;
279 // find strings table
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
280 IF_DEBUG LOG ("Seeking to strings table.");
9551038 first commit.
Yifan Lu authored
281 if (sceIoLseek (fd, start_offset + elf_hdr->e_shoff + elf_hdr->e_shstrndx * elf_hdr->e_shentsize, SCE_SEEK_SET) < 0)
282 {
283 LOG ("Error seeking strings table.");
284 return -1;
285 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
286 IF_DEBUG LOG ("Reading strings table header.");
9551038 first commit.
Yifan Lu authored
287 if (sceIoRead (fd, &sec_hdr, sizeof (Elf32_Shdr_t)) < sizeof (Elf32_Shdr_t))
288 {
289 LOG ("Error reading strings table header.");
290 return -1;
291 }
292 char strings[sec_hdr.sh_size];
293 int name_idx;
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
294 IF_DEBUG LOG ("Seeking strings table.");
9551038 first commit.
Yifan Lu authored
295 if (sceIoLseek (fd, start_offset + sec_hdr.sh_offset, SCE_SEEK_SET) < 0)
296 {
297 LOG ("Error seeking strings table.");
298 return -1;
299 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
300 IF_DEBUG LOG ("Reading strings table.");
9551038 first commit.
Yifan Lu authored
301 if (sceIoRead (fd, strings, sec_hdr.sh_size) < 0)
302 {
303 LOG ("Error reading strings table.");
304 return -1;
305 }
306 name_idx = strstr (strings, SEC_MODINFO) - strings;
307 if (name_idx <= 0)
308 {
309 LOG ("Cannot find section %s in string table.", SEC_MODINFO);
310 return -1;
311 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
312 IF_DEBUG LOG ("Found section %s.", name_idx);
9551038 first commit.
Yifan Lu authored
313 // find sceModuleInfo section
314 int i;
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
315 IF_DEBUG LOG ("Seeking sections table.");
9551038 first commit.
Yifan Lu authored
316 if (sceIoLseek (fd, start_offset + elf_hdr->e_shoff, SCE_SEEK_SET) < 0)
317 {
318 LOG ("Error seeking section table.");
319 return -1;
320 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
321 IF_DEBUG LOG ("Reading %d sections.", elf_hdr->e_shnum);
e9b9fbb Fixed all files to be compilable (but not linkable yet).
Yifan Lu authored
322 for (i = 0; i < elf_hdr->e_shnum; i++)
9551038 first commit.
Yifan Lu authored
323 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
324 IF_DEBUG LOG ("Reading section header.");
9551038 first commit.
Yifan Lu authored
325 if (sceIoRead (fd, &sec_hdr, sizeof (Elf32_Shdr_t)) < sizeof (Elf32_Shdr_t))
326 {
327 LOG ("Error reading section header.");
328 return -1;
329 }
330 if (sec_hdr.sh_name == name_idx) // we want this section
331 {
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
332 IF_DEBUG LOG ("Found requested section %s.", name_idx);
333 IF_DEBUG LOG ("Seeking to section.");
9551038 first commit.
Yifan Lu authored
334 if (sceIoLseek (fd, start_offset + sec_hdr.sh_offset, SCE_SEEK_SET) < 0)
335 {
336 LOG ("Error seeking sceModuleInfo table.");
337 return -1;
338 }
fe0dcc4 Reverted hard coded address for resolve table to single pointer so it…
Yifan Lu authored
339 IF_DEBUG LOG ("Reading section.");
9551038 first commit.
Yifan Lu authored
340 if (sceIoRead (fd, mod_info, sec_hdr.sh_size) < 0)
341 {
342 LOG ("Error reading sceModuleInfo.");
343 return -1;
344 }
345 return 0;
346 }
347 }
348 return -1;
349 }
Something went wrong with that request. Please try again.