~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/ELF/ElfReader.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2012- PPSSPP Project.
 
2
 
 
3
// This program is free software: you can redistribute it and/or modify
 
4
// it under the terms of the GNU General Public License as published by
 
5
// the Free Software Foundation, version 2.0 or later versions.
 
6
 
 
7
// This program is distributed in the hope that it will be useful,
 
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
// GNU General Public License 2.0 for more details.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official git repository and contact information can be found at
 
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
 
17
 
 
18
#include "Core/MemMap.h"
 
19
#include "Core/Reporting.h"
 
20
#include "Core/MIPS/MIPSTables.h"
 
21
#include "ElfReader.h"
 
22
#include "Core/Debugger/Breakpoints.h"
 
23
#include "Core/Debugger/SymbolMap.h"
 
24
#include "Core/HLE/sceKernelMemory.h"
 
25
#include "Core/HLE/sceKernelModule.h"
 
26
 
 
27
#ifdef BLACKBERRY
 
28
using std::strnlen;
 
29
#endif
 
30
 
 
31
const char *ElfReader::GetSectionName(int section) const {
 
32
        if (sections[section].sh_type == SHT_NULL)
 
33
                return 0;
 
34
 
 
35
        int nameOffset = sections[section].sh_name;
 
36
        const char *ptr = (const char *)GetSectionDataPtr(header->e_shstrndx);
 
37
 
 
38
        if (ptr)
 
39
                return ptr + nameOffset;
 
40
        else
 
41
                return 0;
 
42
}
 
43
 
 
44
 
 
45
 
 
46
void addrToHiLo(u32 addr, u16 &hi, s16 &lo)
 
47
{
 
48
        lo = (addr & 0xFFFF);
 
49
        u32 naddr = addr - lo;
 
50
        hi = naddr>>16;
 
51
        u32 test = (hi<<16) + lo;
 
52
        if (test != addr)
 
53
        {
 
54
                WARN_LOG_REPORT(LOADER, "HI16/LO16 relocation failure?");
 
55
        }
 
56
}
 
57
 
 
58
bool ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
 
59
{
 
60
        int numErrors = 0;
 
61
        DEBUG_LOG(LOADER, "Loading %i relocations...", numRelocs);
 
62
        for (int r = 0; r < numRelocs; r++)
 
63
        {
 
64
                // INFO_LOG(LOADER, "Loading reloc %i  (%p)...", r, rels + r);
 
65
                u32 info = rels[r].r_info;
 
66
                u32 addr = rels[r].r_offset;
 
67
 
 
68
                int type = info & 0xf;
 
69
 
 
70
                int readwrite = (info>>8) & 0xff; 
 
71
                int relative  = (info>>16) & 0xff;
 
72
 
 
73
                //0 = code
 
74
                //1 = data
 
75
 
 
76
                if (readwrite >= (int)ARRAY_SIZE(segmentVAddr)) {
 
77
                        if (numErrors < 10) {
 
78
                                ERROR_LOG_REPORT(LOADER, "Bad segment number %i", readwrite);
 
79
                        }
 
80
                        numErrors++;
 
81
                        continue;
 
82
                }
 
83
 
 
84
                addr += segmentVAddr[readwrite];
 
85
 
 
86
                // It appears that misaligned relocations are allowed.
 
87
                // Will they work correctly on big-endian?
 
88
 
 
89
                if (((addr & 3) && type != R_MIPS_32) || !Memory::IsValidAddress(addr)) {
 
90
                        if (numErrors < 10) {
 
91
                                WARN_LOG_REPORT(LOADER, "Suspicious address %08x, skipping reloc, type = %d", addr, type);
 
92
                        } else if (numErrors == 10) {
 
93
                                WARN_LOG(LOADER, "Too many bad relocations, skipping logging");
 
94
                        }
 
95
                        numErrors++;
 
96
                        continue;
 
97
                }
 
98
 
 
99
                u32 op = Memory::Read_Instruction(addr, true).encoding;
 
100
 
 
101
                const bool log = false;
 
102
                //log=true;
 
103
                if (log) {
 
104
                        DEBUG_LOG(LOADER,"rel at: %08x  info: %08x   type: %i",addr, info, type);
 
105
                }
 
106
                u32 relocateTo = segmentVAddr[relative];
 
107
 
 
108
                switch (type) 
 
109
                {
 
110
                case R_MIPS_32:
 
111
                        if (log)
 
112
                                DEBUG_LOG(LOADER,"Full address reloc %08x", addr);
 
113
                        //full address, no problemo
 
114
                        op += relocateTo;
 
115
                        break;
 
116
 
 
117
                case R_MIPS_26: //j, jal
 
118
                        //add on to put in correct address space
 
119
                        if (log)
 
120
                                DEBUG_LOG(LOADER,"j/jal reloc %08x", addr);
 
121
                        op = (op & 0xFC000000) | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFF);
 
122
                        break;
 
123
 
 
124
                case R_MIPS_HI16: //lui part of lui-addiu pairs
 
125
                        {
 
126
                                if (log)
 
127
                                        DEBUG_LOG(LOADER,"HI reloc %08x", addr);
 
128
 
 
129
                                u32 cur = (op & 0xFFFF) << 16;
 
130
                                u16 hi = 0;
 
131
                                bool found = false;
 
132
                                for (int t = r + 1; t<numRelocs; t++)
 
133
                                {
 
134
                                        if ((rels[t].r_info & 0xF) == R_MIPS_LO16) 
 
135
                                        {
 
136
                                                u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
 
137
                                                if (log) {
 
138
                                                        DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr);
 
139
                                                }
 
140
                                                if (Memory::IsValidAddress(corrLoAddr)) {
 
141
                                                        s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
 
142
                                                        cur += lo;
 
143
                                                        cur += relocateTo;
 
144
                                                        addrToHiLo(cur, hi, lo);
 
145
                                                        found = true;
 
146
                                                        break;
 
147
                                                } else {
 
148
                                                        ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr);
 
149
                                                }
 
150
                                        }
 
151
                                }
 
152
                                if (!found) {
 
153
                                        ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16");
 
154
                                }
 
155
                                op = (op & 0xFFFF0000) | (hi);
 
156
                        }
 
157
                        break;
 
158
 
 
159
                case R_MIPS_LO16: //addiu part of lui-addiu pairs
 
160
                        {
 
161
                                if (log)
 
162
                                        DEBUG_LOG(LOADER,"LO reloc %08x", addr);
 
163
                                u32 cur = op & 0xFFFF;
 
164
                                cur += relocateTo;
 
165
                                cur &= 0xFFFF;
 
166
                                op = (op & 0xFFFF0000) | cur;
 
167
                        }
 
168
                        break;
 
169
 
 
170
                case R_MIPS_GPREL16: //gp
 
171
                        // It seems safe to ignore this, almost a notification of a gp-relative operation?
 
172
                        break;
 
173
 
 
174
                case R_MIPS_16:
 
175
                        {
 
176
                                char temp[256];
 
177
                                op = (op & 0xFFFF0000) | (((int)(op & 0xFFFF) + (int)relocateTo) & 0xFFFF);
 
178
                                MIPSDisAsm(MIPSOpcode(op), 0, temp);
 
179
                        }
 
180
                        break;
 
181
 
 
182
                case R_MIPS_NONE:
 
183
                        // This shouldn't matter, not sure the purpose of it.
 
184
                        break;
 
185
 
 
186
                default:
 
187
                        {
 
188
                                char temp[256];
 
189
                                MIPSDisAsm(MIPSOpcode(op), 0, temp);
 
190
                                ERROR_LOG_REPORT(LOADER,"ARGH IT'S AN UNKNOWN RELOCATION!!!!!!!! %08x, type=%d : %s", addr, type, temp);
 
191
                        }
 
192
                        break;
 
193
                }
 
194
                Memory::Write_U32(op, addr);
 
195
        }
 
196
        if (numErrors) {
 
197
                WARN_LOG(LOADER, "%i bad relocations found!!!", numErrors);
 
198
        }
 
199
        return numErrors == 0;
 
200
}
 
201
 
 
202
 
 
203
void ElfReader::LoadRelocations2(int rel_seg)
 
204
{
 
205
        Elf32_Phdr *ph;
 
206
        u8 *buf, *end, *flag_table, *type_table;
 
207
        int flag_table_size, type_table_size;
 
208
        int flag_bits, seg_bits, type_bits;
 
209
        int cmd, flag, seg, type;
 
210
        int off_seg = 0, addr_seg, rel_base, rel_offset;
 
211
        int relocate_to, last_type, lo16 = 0;
 
212
        u32 op, addr;
 
213
        int rcount = 0;
 
214
 
 
215
        ph = segments + rel_seg;
 
216
 
 
217
 
 
218
        buf = (u8*)GetSegmentPtr(rel_seg);
 
219
        end = buf+ph->p_filesz;
 
220
 
 
221
        flag_bits = buf[2];
 
222
        type_bits = buf[3];
 
223
 
 
224
        seg_bits = 1;
 
225
        while((1<<seg_bits)<rel_seg)
 
226
                seg_bits += 1;
 
227
 
 
228
        buf += 4;
 
229
 
 
230
        flag_table = buf;
 
231
        flag_table_size = flag_table[0];
 
232
        buf += flag_table_size;
 
233
 
 
234
        type_table = buf;
 
235
        type_table_size = type_table[0];
 
236
        buf += type_table_size;
 
237
 
 
238
        rel_base = 0;
 
239
        last_type = -1;
 
240
        while(buf<end){
 
241
                cmd = *(u16*)(buf);
 
242
                buf += 2;
 
243
 
 
244
                flag = ( cmd<<(16-flag_bits))&0xffff;
 
245
                flag = (flag>>(16-flag_bits))&0xffff;
 
246
                flag = flag_table[flag];
 
247
 
 
248
                seg = (cmd<<(16-seg_bits-flag_bits))&0xffff;
 
249
                seg = (seg>>(16-seg_bits))&0xffff;
 
250
 
 
251
                type = ( cmd<<(16-type_bits-seg_bits-flag_bits))&0xffff;
 
252
                type = (type>>(16-type_bits))&0xffff;
 
253
                type = type_table[type];
 
254
 
 
255
                if((flag&0x01)==0){
 
256
                        off_seg = seg;
 
257
                        if((flag&0x06)==0){
 
258
                                rel_base = cmd>>(seg_bits+flag_bits);
 
259
                        }else if((flag&0x06)==4){
 
260
                                rel_base = buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24);
 
261
                                buf += 4;
 
262
                        }else{
 
263
                                ERROR_LOG_REPORT(LOADER, "Rel2: invalid size flag! %x", flag);
 
264
                                rel_base = 0;
 
265
                        }
 
266
                }else{
 
267
                        addr_seg = seg;
 
268
                        relocate_to = segmentVAddr[addr_seg];
 
269
 
 
270
                        if((flag&0x06)==0x00){
 
271
                                rel_offset = cmd;
 
272
                                if(cmd&0x8000){
 
273
                                        rel_offset |= 0xffff0000;
 
274
                                        rel_offset >>= type_bits+seg_bits+flag_bits;
 
275
                                        rel_offset |= 0xffff0000;
 
276
                                }else{
 
277
                                        rel_offset >>= type_bits+seg_bits+flag_bits;
 
278
                                }
 
279
                                rel_base += rel_offset;
 
280
                        }else if((flag&0x06)==0x02){
 
281
                                rel_offset = cmd;
 
282
                                if(cmd&0x8000)
 
283
                                        rel_offset |= 0xffff0000;
 
284
                                rel_offset >>= type_bits+seg_bits+flag_bits;
 
285
                                rel_offset = (rel_offset<<16) | (buf[0]) | (buf[1]<<8);
 
286
                                buf += 2;
 
287
                                rel_base += rel_offset;
 
288
                        }else if((flag&0x06)==0x04){
 
289
                                rel_base = buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24);
 
290
                                buf += 4;
 
291
                        }else{
 
292
                                ERROR_LOG_REPORT(LOADER, "Rel2: invalid relocat size flag! %x", flag);
 
293
                        }
 
294
 
 
295
 
 
296
                        rel_offset = rel_base+segmentVAddr[off_seg];
 
297
 
 
298
                        if((flag&0x38)==0x00){
 
299
                                lo16 = 0;
 
300
                        }else if((flag&0x38)==0x08){
 
301
                                if(last_type!=0x04)
 
302
                                        lo16 = 0;
 
303
                        }else if((flag&0x38)==0x10){
 
304
                                lo16 = (buf[0]) | (buf[1]<<8);
 
305
                                if(lo16&0x8000)
 
306
                                        lo16 |= 0xffff0000;
 
307
                                buf += 2;
 
308
                        }else{
 
309
                                ERROR_LOG_REPORT(LOADER, "Rel2: invalid lo16 type! %x", flag);
 
310
                        }
 
311
 
 
312
                        op = Memory::Read_Instruction(rel_offset, true).encoding;
 
313
                        DEBUG_LOG(LOADER, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op);
 
314
 
 
315
                        switch(type){
 
316
                        case 0:
 
317
                                continue;
 
318
                        case 2: // R_MIPS_32
 
319
                                op += relocate_to;
 
320
                                break;
 
321
                        case 3: // R_MIPS_26
 
322
                        case 6: // R_MIPS_J26
 
323
                        case 7: // R_MIPS_JAL26
 
324
                                op = (op&0xFC000000) | (((op&0x03FFFFFF)+(relocate_to>>2))&0x03FFFFFF);
 
325
                                // To be safe, let's force it to the specified jump.
 
326
                                if (type == 6)
 
327
                                        op = (op & ~0xFC000000) | 0x08000000;
 
328
                                else if (type == 7)
 
329
                                        op = (op & ~0xFC000000) | 0x0C000000;
 
330
                                break;
 
331
                        case 4: // R_MIPS_HI16
 
332
                                addr = ((op<<16)+lo16)+relocate_to;
 
333
                                if(addr&0x8000)
 
334
                                        addr += 0x00010000;
 
335
                                op = (op&0xffff0000) | (addr>>16 );
 
336
                                break;
 
337
                        case 1:
 
338
                        case 5: // R_MIPS_LO16
 
339
                                op = (op&0xffff0000) | (((op&0xffff)+relocate_to)&0xffff);
 
340
                                break;
 
341
                        default:
 
342
                                ERROR_LOG_REPORT(LOADER, "Rel2: unexpected relocation type! %x", type);
 
343
                                break;
 
344
                        }
 
345
 
 
346
                        Memory::Write_U32(op, rel_offset);
 
347
                        rcount += 1;
 
348
                }
 
349
        }
 
350
 
 
351
}
 
352
 
 
353
 
 
354
int ElfReader::LoadInto(u32 loadAddress, bool fromTop)
 
355
{
 
356
        DEBUG_LOG(LOADER,"String section: %i", header->e_shstrndx);
 
357
 
 
358
        if (header->e_ident[0] != ELFMAG0 || header->e_ident[1] != ELFMAG1
 
359
                || header->e_ident[2] != ELFMAG2 || header->e_ident[3] != ELFMAG3)
 
360
                return SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE;
 
361
 
 
362
        // technically ELFCLASSNONE would freeze the system, but that's not really desireable
 
363
        if (header->e_ident[EI_CLASS] != ELFCLASS32) {
 
364
                if (header->e_ident[EI_CLASS] != 0) {
 
365
                        return SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
 
366
                }
 
367
 
 
368
                ERROR_LOG(LOADER, "Bad ELF, EI_CLASS (fifth byte) is 0x00, should be 0x01 - would lock up a PSP.");
 
369
        }
 
370
 
 
371
        if (header->e_ident[EI_DATA] != ELFDATA2LSB)
 
372
                return SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
 
373
 
 
374
        // e_ident[EI_VERSION] is ignored
 
375
 
 
376
        sectionOffsets = new u32[GetNumSections()];
 
377
        sectionAddrs = new u32[GetNumSections()];
 
378
 
 
379
        // Should we relocate?
 
380
        bRelocate = (header->e_type != ET_EXEC);
 
381
 
 
382
        // Look for the module info - we need to know whether this is kernel or user.
 
383
        const PspModuleInfo *modInfo = 0;
 
384
        for (int i = 0; i < GetNumSections(); i++) {
 
385
                Elf32_Shdr *s = &sections[i];
 
386
                const char *name = GetSectionName(i);
 
387
                if (name && !strcmp(name, ".rodata.sceModuleInfo")) {
 
388
                        modInfo = (const PspModuleInfo *)GetPtr(s->sh_offset);
 
389
                }
 
390
        }
 
391
        if (!modInfo && GetNumSegments() >= 1) {
 
392
                modInfo = (const PspModuleInfo *)GetPtr(segments[0].p_paddr & 0x7FFFFFFF);
 
393
        }
 
394
 
 
395
        bool kernelModule = modInfo ? (modInfo->moduleAttrs & 0x1000) != 0 : false;
 
396
 
 
397
        std::string modName = "ELF";
 
398
        if (modInfo) {
 
399
                size_t n = strnlen(modInfo->name, 28);
 
400
                modName = "ELF/" + std::string(modInfo->name, n);
 
401
        }
 
402
 
 
403
        entryPoint = header->e_entry;
 
404
        u32 totalStart = 0xFFFFFFFF;
 
405
        u32 totalEnd = 0;
 
406
        for (int i = 0; i < header->e_phnum; i++) {
 
407
                Elf32_Phdr *p = &segments[i];
 
408
                if (p->p_type == PT_LOAD) {
 
409
                        if (p->p_vaddr < totalStart)
 
410
                                totalStart = p->p_vaddr;
 
411
                        if (p->p_vaddr + p->p_memsz > totalEnd)
 
412
                                totalEnd = p->p_vaddr + p->p_memsz;
 
413
                }
 
414
        }
 
415
        totalSize = totalEnd - totalStart;
 
416
 
 
417
        // If a load address is specified that's in regular RAM, override kernel module status
 
418
        bool inUser = totalStart >= PSP_GetUserMemoryBase();
 
419
        BlockAllocator &memblock = (kernelModule && !inUser) ? kernelMemory : userMemory;
 
420
 
 
421
        if (!bRelocate)
 
422
        {
 
423
                // Binary is prerelocated, load it where the first segment starts
 
424
                vaddr = memblock.AllocAt(totalStart, totalSize, modName.c_str());
 
425
        }
 
426
        else if (loadAddress)
 
427
        {
 
428
                // Binary needs to be relocated: add loadAddress to the binary start address
 
429
                vaddr = memblock.AllocAt(loadAddress + totalStart, totalSize, modName.c_str());
 
430
        }
 
431
        else
 
432
        {
 
433
                // Just put it where there is room
 
434
                vaddr = memblock.Alloc(totalSize, fromTop, modName.c_str());
 
435
        }
 
436
 
 
437
        if (vaddr == (u32)-1) {
 
438
                ERROR_LOG_REPORT(LOADER, "Failed to allocate memory for ELF!");
 
439
                return SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED;
 
440
        }
 
441
 
 
442
        if (bRelocate) {
 
443
                DEBUG_LOG(LOADER,"Relocatable module");
 
444
                entryPoint += vaddr;
 
445
        } else {
 
446
                DEBUG_LOG(LOADER,"Prerelocated executable");
 
447
        }
 
448
 
 
449
        DEBUG_LOG(LOADER,"%i segments:", header->e_phnum);
 
450
 
 
451
        // First pass : Get the damn bits into RAM
 
452
        u32 baseAddress = bRelocate?vaddr:0;
 
453
 
 
454
        for (int i=0; i<header->e_phnum; i++)
 
455
        {
 
456
                Elf32_Phdr *p = segments + i;
 
457
                DEBUG_LOG(LOADER, "Type: %08x Vaddr: %08x Filesz: %08x Memsz: %08x ", (int)p->p_type, (u32)p->p_vaddr, (int)p->p_filesz, (int)p->p_memsz);
 
458
 
 
459
                if (p->p_type == PT_LOAD)
 
460
                {
 
461
                        segmentVAddr[i] = baseAddress + p->p_vaddr;
 
462
                        u32 writeAddr = segmentVAddr[i];
 
463
 
 
464
                        u8 *src = GetSegmentPtr(i);
 
465
                        u8 *dst = Memory::GetPointer(writeAddr);
 
466
                        u32 srcSize = p->p_filesz;
 
467
                        u32 dstSize = p->p_memsz;
 
468
 
 
469
                        if (srcSize < dstSize)
 
470
                        {
 
471
                                memset(dst + srcSize, 0, dstSize - srcSize); //zero out bss
 
472
                        }
 
473
 
 
474
                        memcpy(dst, src, srcSize);
 
475
                        CBreakPoints::ExecMemCheck(writeAddr, true, dstSize, currentMIPS->pc);
 
476
                        DEBUG_LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, (u32)p->p_memsz);
 
477
                }
 
478
        }
 
479
        memblock.ListBlocks();
 
480
 
 
481
        DEBUG_LOG(LOADER,"%i sections:", header->e_shnum);
 
482
 
 
483
        for (int i = 0; i < GetNumSections(); i++)
 
484
        {
 
485
                Elf32_Shdr *s = &sections[i];
 
486
                const char *name = GetSectionName(i);
 
487
 
 
488
                u32 writeAddr = s->sh_addr + baseAddress;
 
489
                sectionOffsets[i] = writeAddr - vaddr;
 
490
                sectionAddrs[i] = writeAddr;
 
491
 
 
492
                if (s->sh_flags & SHF_ALLOC)
 
493
                {
 
494
                        DEBUG_LOG(LOADER,"Data Section found: %s     Sitting at %08x, size %08x", name, writeAddr, (u32)s->sh_size);
 
495
                }
 
496
                else
 
497
                {
 
498
                        DEBUG_LOG(LOADER,"NonData Section found: %s     Ignoring (size=%08x) (flags=%08x)", name, (u32)s->sh_size, (u32)s->sh_flags);
 
499
                }
 
500
        }
 
501
 
 
502
        DEBUG_LOG(LOADER,"Relocations:");
 
503
 
 
504
        // Second pass: Do necessary relocations
 
505
        for (int i = 0; i < GetNumSections(); i++)
 
506
        {
 
507
                Elf32_Shdr *s = &sections[i];
 
508
                const char *name = GetSectionName(i);
 
509
 
 
510
                if (s->sh_type == SHT_PSPREL)
 
511
                {
 
512
                        //We have a relocation table!
 
513
                        int sectionToModify = s->sh_info;
 
514
                        if (sectionToModify >= 0)
 
515
                        {
 
516
                                if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
 
517
                                {
 
518
                                        ERROR_LOG_REPORT(LOADER, "Trying to relocate non-loaded section %s", GetSectionName(sectionToModify));
 
519
                                        continue;
 
520
                                }
 
521
 
 
522
                                int numRelocs = s->sh_size / sizeof(Elf32_Rel);
 
523
 
 
524
                                Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
 
525
 
 
526
                                DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s : offset = %08x", name, numRelocs, GetSectionName(sectionToModify), sections[i].sh_offset);
 
527
                                if (!LoadRelocations(rels, numRelocs)) {
 
528
                                        WARN_LOG(LOADER, "LoadInto: Relocs failed, trying anyway");
 
529
                                }                       
 
530
                        }
 
531
                        else
 
532
                        {
 
533
                                WARN_LOG_REPORT(LOADER, "sectionToModify = %i - ignoring PSP relocation sector %i", sectionToModify, i);
 
534
                        }
 
535
                }
 
536
                else if (s->sh_type == SHT_REL)
 
537
                {
 
538
                        DEBUG_LOG(LOADER, "Traditional relocation section found.");
 
539
                        if (!bRelocate)
 
540
                        {
 
541
                                DEBUG_LOG(LOADER, "Binary is prerelocated. Skipping relocations.");
 
542
                        }
 
543
                        else
 
544
                        {
 
545
                                //We have a relocation table!
 
546
                                int sectionToModify = s->sh_info;
 
547
                                if (sectionToModify >= 0)
 
548
                                {
 
549
                                        if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
 
550
                                        {
 
551
                                                ERROR_LOG_REPORT(LOADER, "Trying to relocate non-loaded section %s, ignoring", GetSectionName(sectionToModify));
 
552
                                                continue;
 
553
                                        }
 
554
                                }
 
555
                                else
 
556
                                {
 
557
                                        WARN_LOG_REPORT(LOADER, "sectionToModify = %i - ignoring relocation sector %i", sectionToModify, i);
 
558
                                }
 
559
                                ERROR_LOG_REPORT(LOADER, "Traditional relocations unsupported.");
 
560
                        }
 
561
                }
 
562
        }
 
563
 
 
564
        // Segment relocations (a few games use them)
 
565
        if (GetNumSections() == 0) {
 
566
                for (int i = 0; i < header->e_phnum; i++)
 
567
                {
 
568
                        Elf32_Phdr *p = &segments[i];
 
569
                        if (p->p_type == PT_PSPREL1) {
 
570
                                INFO_LOG(LOADER,"Loading segment relocations");
 
571
                                int numRelocs = p->p_filesz / sizeof(Elf32_Rel);
 
572
 
 
573
                                Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i);
 
574
                                if (!LoadRelocations(rels, numRelocs)) {
 
575
                                        ERROR_LOG(LOADER, "LoadInto: Relocs failed, trying anyway (2)");
 
576
                                }
 
577
                        } else if (p->p_type == PT_PSPREL2) {
 
578
                                INFO_LOG(LOADER,"Loading segment relocations2");
 
579
                                LoadRelocations2(i);
 
580
                        }
 
581
                }
 
582
        }
 
583
 
 
584
        return SCE_KERNEL_ERROR_OK;
 
585
}
 
586
 
 
587
 
 
588
SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const
 
589
{
 
590
        for (int i = firstSection; i < header->e_shnum; i++)
 
591
        {
 
592
                const char *secname = GetSectionName(i);
 
593
 
 
594
                if (secname != 0 && strcmp(name, secname) == 0)
 
595
                {
 
596
                        return i;
 
597
                }
 
598
        }
 
599
        return -1;
 
600
}
 
601
 
 
602
u32 ElfReader::GetTotalTextSize() const {
 
603
        u32 total = 0;
 
604
        for (int i = 0; i < GetNumSections(); ++i) {
 
605
                if (!(sections[i].sh_flags & SHF_WRITE) && (sections[i].sh_flags & SHF_ALLOC) && !(sections[i].sh_flags & SHF_STRINGS)) {
 
606
                        total += sections[i].sh_size;
 
607
                }
 
608
        }
 
609
        return total;
 
610
}
 
611
 
 
612
u32 ElfReader::GetTotalDataSize() const {
 
613
        u32 total = 0;
 
614
        for (int i = 0; i < GetNumSections(); ++i) {
 
615
                if ((sections[i].sh_flags & SHF_WRITE) && (sections[i].sh_flags & SHF_ALLOC) && !(sections[i].sh_flags & SHF_MASKPROC)) {
 
616
                        total += sections[i].sh_size;
 
617
                }
 
618
        }
 
619
        return total;
 
620
}
 
621
 
 
622
u32 ElfReader::GetTotalSectionSizeByPrefix(const std::string &prefix) const {
 
623
        u32 total = 0;
 
624
        for (int i = 0; i < GetNumSections(); ++i) {
 
625
                const char *secname = GetSectionName(i);
 
626
                if (secname && !strncmp(secname, prefix.c_str(), prefix.length())) {
 
627
                        total += sections[i].sh_size;
 
628
                }
 
629
        }
 
630
        return total;
 
631
}
 
632
 
 
633
bool ElfReader::LoadSymbols()
 
634
{
 
635
        bool hasSymbols = false;
 
636
        SectionID sec = GetSectionByName(".symtab");
 
637
        if (sec != -1)
 
638
        {
 
639
                int stringSection = sections[sec].sh_link;
 
640
 
 
641
                const char *stringBase = (const char*)GetSectionDataPtr(stringSection);
 
642
 
 
643
                //We have a symbol table!
 
644
                Elf32_Sym *symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
 
645
 
 
646
                int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
 
647
                
 
648
                for (int sym = 0; sym<numSymbols; sym++)
 
649
                {
 
650
                        int size = symtab[sym].st_size;
 
651
                        if (size == 0)
 
652
                                continue;
 
653
 
 
654
                        int bind = symtab[sym].st_info >> 4;
 
655
                        int type = symtab[sym].st_info & 0xF;
 
656
                        int sectionIndex = symtab[sym].st_shndx;
 
657
                        int value = symtab[sym].st_value;
 
658
                        const char *name = stringBase + symtab[sym].st_name;
 
659
 
 
660
                        if (bRelocate)
 
661
                                value += sectionAddrs[sectionIndex];
 
662
 
 
663
                        switch (type)
 
664
                        {
 
665
                        case STT_OBJECT:
 
666
                                g_symbolMap->AddData(value,size,DATATYPE_BYTE);
 
667
                                break;
 
668
                        case STT_FUNC:
 
669
                                g_symbolMap->AddFunction(name,value,size);
 
670
                                break;
 
671
                        default:
 
672
                                continue;
 
673
                        }
 
674
                        hasSymbols = true;
 
675
                        //...
 
676
                }
 
677
        }
 
678
        return hasSymbols;
 
679
}