PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
elf_loader_reader.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "elf_loader_common.h"
12
13#include <string.h>
14
15void elf_loader_reader_read_elf_file(elf_loader_reader_info_t *info)
16{
17 void *ptr;
18 int ret;
19 ptrdiff_t cur_alloc_block_size;
20
21 ret = -10;
22 cur_alloc_block_size = 0;
23 ptr = info->m_alloc_callback(
24 info->m_userdata,
25 NULL,
26 0,
27 sizeof(elf_loader_elf32_ehdr_t) + (sizeof(elf_loader_elf32_phdr_t) * ELF_LOADER_MAX_PROGRAM_HEADERS));
28 if ( ptr )
29 {
30 elf_loader_reader_segment_info_t elf_segment_info[1];
31
32 ret = -11;
33 cur_alloc_block_size =
34 sizeof(elf_loader_elf32_phdr_t) + (sizeof(elf_loader_elf32_phdr_t) * ELF_LOADER_MAX_PROGRAM_HEADERS);
35 elf_segment_info[0].m_segment_addr = ptr;
36 elf_segment_info[0].m_segment_offset = 0;
37 elf_segment_info[0].m_segment_size = cur_alloc_block_size;
38
39 if ( !info->m_read_callback(
40 info->m_userdata,
41 ELF_LOADER_READER_STAGE_ELF_HEADER,
42 &elf_segment_info[0],
43 sizeof(elf_segment_info) / sizeof(elf_segment_info[0])) )
44 ptr = info->m_alloc_callback(info->m_userdata, ptr, cur_alloc_block_size, 0);
45 }
46 if ( ptr )
47 {
48 int ret;
49
50 ret = elf_loader_is_elf_ehdr_valid(ptr);
51 if ( ret )
52 ptr = info->m_alloc_callback(info->m_userdata, ptr, cur_alloc_block_size, 0);
53 }
54 if ( ptr )
55 {
56 elf_loader_elf32_ehdr_t *elf_header;
57 elf_loader_reader_segment_info_t elf_segment_info[1];
58 u32 phoff;
59
60 ret = -12;
61 elf_header = (void *)ptr;
62 elf_header->e_shoff = 0;
63 elf_header->e_shentsize = 0;
64 elf_header->e_shnum = 0;
65 elf_header->e_shstrndx = 0;
66 phoff = elf_header->e_phoff;
67 elf_header->e_phoff = sizeof(elf_loader_elf32_ehdr_t);
68
69 elf_segment_info[0].m_segment_addr = ((u8 *)ptr) + elf_header->e_phoff;
70 elf_segment_info[0].m_segment_offset = phoff;
71 elf_segment_info[0].m_segment_size = sizeof(elf_loader_elf32_phdr_t) * elf_header->e_phnum;
72
73 if ( !info->m_read_callback(
74 info->m_userdata,
75 ELF_LOADER_READER_STAGE_PROGRAM_HEADERS,
76 &elf_segment_info[0],
77 sizeof(elf_segment_info) / sizeof(elf_segment_info[0])) )
78 ptr = info->m_alloc_callback(info->m_userdata, ptr, cur_alloc_block_size, 0);
79 }
80 if ( ptr )
81 {
82 elf_loader_elf32_ehdr_t *elf_header;
83 elf_loader_elf32_phdr_t *elf_pheader;
84 int i;
85 u32 offs_sum;
86
87 ret = -13;
88 elf_header = (void *)ptr;
89 elf_pheader = (void *)(((u8 *)ptr) + elf_header->e_phoff);
90 offs_sum = 0;
91 // Remove any unused program headers
92 for ( i = 0; i < elf_header->e_phnum; i += 1 )
93 {
94 while ( i < elf_header->e_phnum && (elf_pheader[i].p_type != 1 || elf_pheader[i].p_filesz == 0) )
95 {
96 elf_header->e_phnum -= 1;
97 memmove(&elf_pheader[i], &elf_pheader[i + 1], sizeof(elf_loader_elf32_phdr_t) * (elf_header->e_phnum - i));
98 }
99 }
100 // Sort program headers by address
101 for ( i = 1; i < elf_header->e_phnum; i += 1 )
102 {
103 int j;
105
106 memcpy(&phdr_tmp, &elf_pheader[i], sizeof(elf_loader_elf32_phdr_t));
107 for ( j = i - 1; j >= 0 && phdr_tmp.p_vaddr < elf_pheader[j].p_vaddr; j -= 1 )
108 {
109 memcpy(&elf_pheader[j + 1], &elf_pheader[j], sizeof(elf_loader_elf32_phdr_t));
110 }
111 memcpy(&elf_pheader[j + 1], &phdr_tmp, sizeof(elf_loader_elf32_phdr_t));
112 }
113 offs_sum = sizeof(elf_loader_elf32_ehdr_t) + (sizeof(elf_loader_elf32_phdr_t) * elf_header->e_phnum);
114 for ( i = 0; i < elf_header->e_phnum; i += 1 )
115 {
116 offs_sum += elf_pheader[i].p_filesz;
117 }
118 ptr = info->m_alloc_callback(info->m_userdata, ptr, cur_alloc_block_size, offs_sum);
119 cur_alloc_block_size = offs_sum;
120 }
121 if ( ptr )
122 {
123 elf_loader_elf32_ehdr_t *elf_header;
124 elf_loader_elf32_phdr_t *elf_pheader;
125 elf_loader_reader_segment_info_t elf_segment_info[ELF_LOADER_MAX_PROGRAM_HEADERS];
126 int i;
127 u32 offs_sum;
128
129 ret = -14;
130 elf_header = (void *)ptr;
131 elf_pheader = (void *)(((u8 *)ptr) + elf_header->e_phoff);
132 offs_sum = sizeof(elf_loader_elf32_ehdr_t) + (sizeof(elf_loader_elf32_phdr_t) * elf_header->e_phnum);
133 for ( i = 0; i < elf_header->e_phnum; i += 1 )
134 {
135 elf_segment_info[i].m_segment_addr = ((u8 *)ptr) + offs_sum;
136 elf_segment_info[i].m_segment_offset = elf_pheader[i].p_offset;
137 elf_segment_info[i].m_segment_size = elf_pheader[i].p_filesz;
138 elf_pheader[i].p_offset = offs_sum;
139 offs_sum += elf_segment_info[i].m_segment_size;
140 }
141 // Sort segment info by offset in file
142 for ( i = 1; i < elf_header->e_phnum; i += 1 )
143 {
144 int j;
145 elf_loader_reader_segment_info_t segment_info_tmp;
146
147 memcpy(&segment_info_tmp, &elf_segment_info[i], sizeof(elf_loader_reader_segment_info_t));
148 for ( j = i - 1; j >= 0 && segment_info_tmp.m_segment_offset < elf_segment_info[j].m_segment_offset; j -= 1 )
149 {
150 memcpy(&elf_segment_info[j + 1], &elf_segment_info[j], sizeof(elf_loader_reader_segment_info_t));
151 }
152 memcpy(&elf_segment_info[j + 1], &segment_info_tmp, sizeof(elf_loader_reader_segment_info_t));
153 }
154 if ( !info->m_read_callback(
155 info->m_userdata, ELF_LOADER_READER_STAGE_SEGMENTS, &elf_segment_info[0], elf_header->e_phnum) )
156 ptr = info->m_alloc_callback(info->m_userdata, ptr, cur_alloc_block_size, 0);
157 }
158 if ( ptr )
159 {
160 ret = 0;
161 }
162 info->m_result_callback(info->m_userdata, ptr, cur_alloc_block_size, ret);
163}