2012-11-15 00:39:56 +01:00
# include "stdafx.h"
2015-01-29 16:48:05 +01:00
# include "Ini.h"
2014-06-17 17:44:03 +02:00
# include "Utilities/Log.h"
2014-08-25 16:56:13 +02:00
# include "Emu/FS/vfsStream.h"
2014-06-02 19:27:24 +02:00
# include "Emu/Memory/Memory.h"
2012-11-15 00:39:56 +01:00
# include "ELF32.h"
2014-11-19 15:16:30 +01:00
# include "Emu/Cell/SPUThread.h"
# include "Emu/ARMv7/ARMv7Thread.h"
2015-01-21 22:09:37 +01:00
# include "Emu/ARMv7/ARMv7Decoder.h"
2014-12-01 17:34:18 +01:00
# include "Emu/ARMv7/PSVFuncList.h"
2014-11-19 15:16:30 +01:00
# include "Emu/System.h"
2012-11-15 00:39:56 +01:00
2015-01-31 17:44:26 +01:00
extern void armv7_init_tls ( ) ;
2014-11-19 15:16:30 +01:00
namespace loader
2014-03-03 05:48:07 +01:00
{
2014-11-19 15:16:30 +01:00
namespace handlers
2012-11-15 00:39:56 +01:00
{
2014-11-19 15:16:30 +01:00
handler : : error_code elf32 : : init ( vfsStream & stream )
{
2015-02-17 16:27:15 +01:00
m_ehdr = { } ;
m_phdrs . clear ( ) ;
m_shdrs . clear ( ) ;
2014-11-19 15:16:30 +01:00
error_code res = handler : : init ( stream ) ;
2012-11-15 00:39:56 +01:00
2014-11-19 15:16:30 +01:00
if ( res ! = ok )
2015-02-17 16:27:15 +01:00
{
2014-11-19 15:16:30 +01:00
return res ;
2015-02-17 16:27:15 +01:00
}
2013-11-05 19:12:18 +01:00
2014-11-19 15:16:30 +01:00
m_stream - > Read ( & m_ehdr , sizeof ( ehdr ) ) ;
2013-11-09 13:25:12 +01:00
2014-11-19 15:16:30 +01:00
if ( ! m_ehdr . check ( ) )
2013-11-05 19:12:18 +01:00
{
2014-11-19 15:16:30 +01:00
return bad_file ;
2013-11-05 19:12:18 +01:00
}
2014-11-19 15:16:30 +01:00
if ( m_ehdr . data_le . e_phnum & & ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_phentsize : m_ehdr . data_be . e_phentsize ) ! = sizeof ( phdr ) )
2013-07-12 14:42:17 +02:00
{
2014-11-19 15:16:30 +01:00
return broken_file ;
2013-07-12 14:42:17 +02:00
}
2013-07-06 01:49:38 +02:00
2014-11-19 15:16:30 +01:00
if ( m_ehdr . data_le . e_shnum & & ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_shentsize : m_ehdr . data_be . e_shentsize ) ! = sizeof ( shdr ) )
2013-07-12 14:42:17 +02:00
{
2014-11-19 15:16:30 +01:00
return broken_file ;
2013-07-12 14:42:17 +02:00
}
2013-07-06 01:49:38 +02:00
2014-11-21 14:52:01 +01:00
LOG_WARNING ( LOADER , " m_ehdr.e_type = 0x%x " , ( u16 ) ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_type : m_ehdr . data_be . e_type ) ) ;
2014-11-19 15:16:30 +01:00
if ( m_ehdr . data_le . e_phnum )
2012-11-15 00:39:56 +01:00
{
2014-11-19 15:16:30 +01:00
m_phdrs . resize ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_phnum : m_ehdr . data_be . e_phnum ) ;
m_stream - > Seek ( handler : : get_stream_offset ( ) + ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_phoff : m_ehdr . data_be . e_phoff ) ) ;
size_t size = ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_phnum : m_ehdr . data_be . e_phnum ) * sizeof ( phdr ) ;
2014-11-30 23:04:47 +01:00
2014-11-19 15:16:30 +01:00
if ( m_stream - > Read ( m_phdrs . data ( ) , size ) ! = size )
return broken_file ;
2012-11-15 00:39:56 +01:00
}
2014-11-19 15:16:30 +01:00
if ( m_ehdr . data_le . e_shnum )
2013-11-05 19:12:18 +01:00
{
2014-11-30 23:04:47 +01:00
m_shdrs . resize ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_shnum : m_ehdr . data_be . e_shnum ) ;
2014-11-19 15:16:30 +01:00
m_stream - > Seek ( handler : : get_stream_offset ( ) + ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_shoff : m_ehdr . data_be . e_shoff ) ) ;
2014-12-26 08:26:43 +01:00
size_t size = ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_shnum : m_ehdr . data_be . e_shnum ) * sizeof ( shdr ) ;
2013-11-05 19:12:18 +01:00
2014-11-19 15:16:30 +01:00
if ( m_stream - > Read ( m_shdrs . data ( ) , size ) ! = size )
return broken_file ;
2013-11-05 19:12:18 +01:00
}
2014-11-19 15:16:30 +01:00
return ok ;
2012-11-15 00:39:56 +01:00
}
2013-07-12 14:42:17 +02:00
2014-11-19 15:16:30 +01:00
handler : : error_code elf32 : : load ( )
{
Elf_Machine machine ;
switch ( machine = ( Elf_Machine ) ( u16 ) ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_machine : m_ehdr . data_be . e_machine ) )
2013-07-12 14:42:17 +02:00
{
2014-11-19 15:16:30 +01:00
case MACHINE_MIPS : vm : : psp : : init ( ) ; break ;
case MACHINE_ARM : vm : : psv : : init ( ) ; break ;
case MACHINE_SPU : vm : : ps3 : : init ( ) ; break ;
2013-07-12 14:42:17 +02:00
2014-11-19 15:16:30 +01:00
default :
return bad_version ;
2013-07-12 14:42:17 +02:00
}
2014-11-19 15:16:30 +01:00
error_code res = load_data ( 0 ) ;
2013-07-12 14:42:17 +02:00
2014-11-19 15:16:30 +01:00
if ( res ! = ok )
return res ;
2013-07-12 14:42:17 +02:00
2014-11-19 15:16:30 +01:00
switch ( machine )
2013-08-03 11:40:03 +02:00
{
2014-11-19 15:16:30 +01:00
case MACHINE_MIPS : break ;
2014-11-30 23:04:47 +01:00
case MACHINE_ARM :
{
2015-02-01 22:12:40 +01:00
struct psv_libc_param_t
{
u32 size ; // 0x0000001c
u32 unk1 ; // 0x00000000
vm : : psv : : ptr < u32 > sceLibcHeapSize ;
vm : : psv : : ptr < u32 > sceLibcHeapSizeDefault ;
vm : : psv : : ptr < u32 > sceLibcHeapExtendedAlloc ;
vm : : psv : : ptr < u32 > sceLibcHeapDelayedAlloc ;
u32 unk2 ;
2015-02-02 10:14:49 +01:00
u32 unk3 ;
vm : : psv : : ptr < u32 > __sce_libcmallocreplace ;
vm : : psv : : ptr < u32 > __sce_libcnewreplace ;
2015-02-01 22:12:40 +01:00
} ;
struct psv_process_param_t
{
u32 size ; // 0x00000030
u32 unk1 ; // 'PSP2'
u32 unk2 ; // 0x00000005
u32 unk3 ;
vm : : psv : : ptr < const char > sceUserMainThreadName ;
vm : : psv : : ptr < s32 > sceUserMainThreadPriority ;
vm : : psv : : ptr < u32 > sceUserMainThreadStackSize ;
vm : : psv : : ptr < u32 > sceUserMainThreadAttribute ;
vm : : psv : : ptr < const char > sceProcessName ;
vm : : psv : : ptr < u32 > sce_process_preload_disabled ;
vm : : psv : : ptr < u32 > sceUserMainThreadCpuAffinityMask ;
vm : : psv : : ptr < psv_libc_param_t > __sce_libcparam ;
} ;
2015-01-21 15:34:05 +01:00
initialize_psv_modules ( ) ;
2014-12-01 17:34:18 +01:00
2014-11-30 23:04:47 +01:00
auto armv7_thr_stop_data = vm : : psv : : ptr < u32 > : : make ( Memory . PSV . RAM . AllocAlign ( 3 * 4 ) ) ;
2014-12-08 01:35:15 +01:00
armv7_thr_stop_data [ 0 ] = 0xf870 ; // HACK instruction (Thumb)
2015-02-18 22:23:31 +01:00
armv7_thr_stop_data [ 1 ] = SFI_HLE_RETURN ;
2015-02-17 16:27:15 +01:00
Emu . SetCPUThreadStop ( armv7_thr_stop_data . addr ( ) ) ;
2014-11-30 23:04:47 +01:00
2014-12-08 01:35:15 +01:00
u32 entry = 0 ; // actual entry point (ELFs entry point is ignored)
u32 fnid_addr = 0 ;
2015-01-21 22:09:37 +01:00
u32 code_start = 0 ;
u32 code_end = 0 ;
2015-01-29 16:48:05 +01:00
u32 vnid_addr = 0 ;
std : : unordered_map < u32 , u32 > vnid_list ;
2014-12-08 01:35:15 +01:00
2015-04-21 22:26:21 +02:00
vm : : psv : : ptr < psv_process_param_t > proc_param = vm : : null ;
2014-12-08 01:35:15 +01:00
for ( auto & shdr : m_shdrs )
2014-11-30 23:04:47 +01:00
{
2014-12-08 01:35:15 +01:00
// get secton name
//auto name = vm::psv::ptr<const char>::make(sname_base + shdr.data_le.sh_name);
m_stream - > Seek ( handler : : get_stream_offset ( ) + m_shdrs [ m_ehdr . data_le . e_shstrndx ] . data_le . sh_offset + shdr . data_le . sh_name ) ;
std : : string name ;
2015-04-19 15:19:24 +02:00
char c ;
while ( m_stream - > SRead ( c ) & & c )
2014-12-08 01:35:15 +01:00
{
name . push_back ( c ) ;
}
2015-01-21 22:09:37 +01:00
if ( ! strcmp ( name . c_str ( ) , " .text " ) )
2014-12-08 01:35:15 +01:00
{
2015-01-21 22:09:37 +01:00
LOG_NOTICE ( LOADER , " .text analysis... " ) ;
2014-12-08 01:35:15 +01:00
2015-01-21 22:09:37 +01:00
code_start = shdr . data_le . sh_addr ;
code_end = shdr . data_le . sh_size + code_start ;
}
2015-02-01 22:12:40 +01:00
else if ( ! strcmp ( name . c_str ( ) , " .sceExport.rodata " ) )
2014-12-08 01:35:15 +01:00
{
2015-02-01 22:12:40 +01:00
LOG_NOTICE ( LOADER , " .sceExport.rodata analysis... " ) ;
2014-12-08 01:35:15 +01:00
2015-02-01 22:12:40 +01:00
auto enid = vm : : psv : : ptr < const u32 > : : make ( shdr . data_le . sh_addr ) ;
auto edata = vm : : psv : : ptr < const u32 > : : make ( enid . addr ( ) + shdr . data_le . sh_size / 2 ) ;
2014-12-08 01:35:15 +01:00
2015-02-01 22:12:40 +01:00
for ( u32 j = 0 ; j < shdr . data_le . sh_size / 8 ; j + + )
2014-12-08 01:35:15 +01:00
{
2015-02-01 22:12:40 +01:00
switch ( const u32 nid = enid [ j ] )
{
case 0x935cd196 : // set entry point
{
entry = edata [ j ] ;
break ;
}
case 0x6c2224ba : // __sce_moduleinfo
{
// currently nothing, but it should theoretically be the root of analysis instead of section name comparison
break ;
}
2014-12-08 01:35:15 +01:00
2015-02-01 22:12:40 +01:00
case 0x70fba1e7 : // __sce_process_param
2014-12-08 01:35:15 +01:00
{
2015-02-01 22:12:40 +01:00
proc_param . set ( edata [ j ] ) ;
2014-12-08 01:35:15 +01:00
break ;
}
2015-02-01 22:12:40 +01:00
default :
{
LOG_ERROR ( LOADER , " Unknown export 0x%08x (addr=0x%08x) " , nid , edata [ j ] ) ;
}
}
2014-12-08 01:35:15 +01:00
}
}
else if ( ! strcmp ( name . c_str ( ) , " .sceFNID.rodata " ) )
{
LOG_NOTICE ( LOADER , " .sceFNID.rodata analysis... " ) ;
fnid_addr = shdr . data_le . sh_addr ;
}
else if ( ! strcmp ( name . c_str ( ) , " .sceFStub.rodata " ) )
{
LOG_NOTICE ( LOADER , " .sceFStub.rodata analysis... " ) ;
if ( ! fnid_addr )
{
LOG_ERROR ( LOADER , " .sceFNID.rodata address not found, unable to process imports " ) ;
continue ;
}
auto fnid = vm : : psv : : ptr < const u32 > : : make ( fnid_addr ) ;
auto fstub = vm : : psv : : ptr < const u32 > : : make ( shdr . data_le . sh_addr ) ;
for ( u32 j = 0 ; j < shdr . data_le . sh_size / 4 ; j + + )
{
2015-01-29 16:48:05 +01:00
const u32 nid = fnid [ j ] ;
const u32 addr = fstub [ j ] ;
2014-12-08 01:35:15 +01:00
2015-02-18 22:23:31 +01:00
u32 index ;
if ( auto func = get_psv_func_by_nid ( nid , & index ) )
2014-12-08 01:35:15 +01:00
{
if ( func - > module )
2015-01-29 16:48:05 +01:00
{
2015-02-18 22:23:31 +01:00
LOG_NOTICE ( LOADER , " Imported function '%s' in module '%s' (nid=0x%08x, addr=0x%x) " , func - > name , func - > module - > GetName ( ) , nid , addr ) ;
2015-01-29 16:48:05 +01:00
}
2014-12-08 01:35:15 +01:00
else
2015-01-29 16:48:05 +01:00
{
2015-02-18 22:23:31 +01:00
LOG_NOTICE ( LOADER , " Imported function '%s' (nid=0x%08x, addr=0x%x) " , func - > name , nid , addr ) ;
2015-01-29 16:48:05 +01:00
}
2014-12-08 01:35:15 +01:00
}
else
{
2015-01-29 16:48:05 +01:00
LOG_ERROR ( LOADER , " Unknown function 0x%08x (addr=0x%x) " , nid , addr ) ;
2014-12-08 01:35:15 +01:00
2015-02-23 19:54:17 +01:00
// TODO: set correct name if possible
index = add_psv_func ( psv_func ( nid , 0 , nullptr , " UNKNOWN " , nullptr ) ) ;
2014-12-08 01:35:15 +01:00
}
2015-01-21 22:09:37 +01:00
2015-02-24 17:38:10 +01:00
vm : : psv : : write32 ( addr , 0xe0700090 | ( index & 0xfff0 ) < < 4 | ( index & 0xf ) ) ; // HACK instruction (ARM)
2015-02-18 22:23:31 +01:00
2015-01-21 22:09:37 +01:00
code_end = std : : min < u32 > ( addr , code_end ) ;
2014-12-08 01:35:15 +01:00
}
}
2015-01-29 16:48:05 +01:00
else if ( ! strcmp ( name . c_str ( ) , " .sceVNID.rodata " ) )
{
LOG_NOTICE ( LOADER , " .sceVNID.rodata analysis... " ) ;
vnid_addr = shdr . data_le . sh_addr ;
}
else if ( ! strcmp ( name . c_str ( ) , " .sceVStub.rodata " ) )
{
LOG_NOTICE ( LOADER , " .sceVStub.rodata analysis... " ) ;
if ( ! vnid_addr )
{
if ( shdr . data_le . sh_size )
{
LOG_ERROR ( LOADER , " .sceVNID.rodata address not found, unable to process imports " ) ;
}
continue ;
}
auto vnid = vm : : psv : : ptr < const u32 > : : make ( vnid_addr ) ;
auto vstub = vm : : psv : : ptr < const u32 > : : make ( shdr . data_le . sh_addr ) ;
for ( u32 j = 0 ; j < shdr . data_le . sh_size / 4 ; j + + )
{
const u32 nid = vnid [ j ] ;
const u32 addr = vstub [ j ] ;
LOG_ERROR ( LOADER , " Unknown object 0x%08x (ref_addr=0x%x) " , nid , addr ) ;
// TODO: find imported object (vtable, typeinfo or something), assign it to vnid_list[addr]
2014-12-08 01:35:15 +01:00
}
}
2015-01-29 16:48:05 +01:00
else if ( ! strcmp ( name . c_str ( ) , " .tbss " ) )
{
2015-01-31 17:44:26 +01:00
LOG_NOTICE ( LOADER , " .tbss analysis... " ) ;
const u32 img_addr = shdr . data_le . sh_addr ; // start address of TLS initialization image
const u32 img_size = ( & shdr ) [ 1 ] . data_le . sh_addr - img_addr ; // calculate its size as the difference between sections
const u32 tls_size = shdr . data_le . sh_size ; // full size of TLS
2015-01-29 16:48:05 +01:00
2015-01-31 17:44:26 +01:00
LOG_WARNING ( LOADER , " TLS: img_addr=0x%08x, img_size=0x%x, tls_size=0x%x " , img_addr , img_size , tls_size ) ;
Emu . SetTLSData ( img_addr , img_size , tls_size ) ;
2015-01-29 16:48:05 +01:00
}
2014-12-08 01:35:15 +01:00
else if ( ! strcmp ( name . c_str ( ) , " .sceRefs.rodata " ) )
{
LOG_NOTICE ( LOADER , " .sceRefs.rodata analysis... " ) ;
u32 data = 0 ;
for ( auto code = vm : : psv : : ptr < const u32 > : : make ( shdr . data_le . sh_addr ) ; code . addr ( ) < shdr . data_le . sh_addr + shdr . data_le . sh_size ; code + + )
{
switch ( * code )
{
2015-01-29 16:48:05 +01:00
case 0x000000ff : // save address for future use
2014-12-08 01:35:15 +01:00
{
data = * + + code ;
break ;
}
2015-01-29 16:48:05 +01:00
case 0x0000002f : // movw r*,# instruction is replaced
2014-12-08 01:35:15 +01:00
{
2015-01-29 22:42:53 +01:00
if ( ! data ) // probably, imported object
2015-01-29 16:48:05 +01:00
{
auto found = vnid_list . find ( code . addr ( ) ) ;
if ( found ! = vnid_list . end ( ) )
{
data = found - > second ;
}
}
if ( ! data )
{
2015-01-29 22:42:53 +01:00
LOG_ERROR ( LOADER , " .sceRefs: movw writing failed (ref_addr=0x%x, addr=0x%x) " , code , code [ 1 ] ) ;
}
else //if (Ini.HLELogging.GetValue())
{
LOG_NOTICE ( LOADER , " .sceRefs: movw written at 0x%x (ref_addr=0x%x, data=0x%x) " , code [ 1 ] , code , data ) ;
2015-01-29 16:48:05 +01:00
}
2014-12-08 01:35:15 +01:00
const u32 addr = * + + code ;
2015-01-29 16:48:05 +01:00
vm : : psv : : write16 ( addr + 0 , vm : : psv : : read16 ( addr + 0 ) | ( data & 0x800 ) > > 1 | ( data & 0xf000 ) > > 12 ) ;
vm : : psv : : write16 ( addr + 2 , vm : : psv : : read16 ( addr + 2 ) | ( data & 0x700 ) < < 4 | ( data & 0xff ) ) ;
2014-12-08 01:35:15 +01:00
break ;
}
2015-01-29 16:48:05 +01:00
case 0x00000030 : // movt r*,# instruction is replaced
2014-12-08 01:35:15 +01:00
{
2015-01-29 16:48:05 +01:00
if ( ! data )
{
2015-01-29 22:42:53 +01:00
LOG_ERROR ( LOADER , " .sceRefs: movt writing failed (ref_addr=0x%x, addr=0x%x) " , code , code [ 1 ] ) ;
2015-01-29 16:48:05 +01:00
}
2015-01-29 22:42:53 +01:00
else //if (Ini.HLELogging.GetValue())
2015-01-29 16:48:05 +01:00
{
2015-01-29 22:42:53 +01:00
LOG_NOTICE ( LOADER , " .sceRefs: movt written at 0x%x (ref_addr=0x%x, data=0x%x) " , code [ 1 ] , code , data ) ;
2015-01-29 16:48:05 +01:00
}
2015-01-29 22:42:53 +01:00
2014-12-08 01:35:15 +01:00
const u32 addr = * + + code ;
2015-01-29 22:42:53 +01:00
vm : : psv : : write16 ( addr + 0 , vm : : psv : : read16 ( addr + 0 ) | ( data & 0x8000000 ) > > 17 | ( data & 0xf0000000 ) > > 28 ) ;
vm : : psv : : write16 ( addr + 2 , vm : : psv : : read16 ( addr + 2 ) | ( data & 0x7000000 ) > > 12 | ( data & 0xff0000 ) > > 16 ) ;
2014-12-08 01:35:15 +01:00
break ;
}
case 0x00000000 :
{
2015-01-29 16:48:05 +01:00
data = 0 ;
if ( Ini . HLELogging . GetValue ( ) )
{
LOG_NOTICE ( LOADER , " .sceRefs: zero code found " ) ;
}
2014-12-08 01:35:15 +01:00
break ;
}
default :
{
2015-01-29 16:48:05 +01:00
LOG_ERROR ( LOADER , " Unknown code in .sceRefs section (0x%08x) " , * code ) ;
2014-12-08 01:35:15 +01:00
}
}
}
}
2014-11-30 23:04:47 +01:00
}
2015-02-01 22:12:40 +01:00
LOG_NOTICE ( LOADER , " __sce_process_param(addr=0x%x) analysis... " , proc_param ) ;
if ( proc_param - > size ! = 0x30 | | proc_param - > unk1 ! = * ( u32 * ) " PSP2 " | | proc_param - > unk2 ! = 5 )
{
LOG_ERROR ( LOADER , " __sce_process_param: unexpected data found (size=0x%x, 0x%x, 0x%x, 0x%x) " , proc_param - > size , proc_param - > unk1 , proc_param - > unk2 , proc_param - > unk3 ) ;
}
LOG_NOTICE ( LOADER , " *** &sceUserMainThreadName = 0x%x " , proc_param - > sceUserMainThreadName ) ;
LOG_NOTICE ( LOADER , " *** &sceUserMainThreadPriority = 0x%x " , proc_param - > sceUserMainThreadPriority ) ;
LOG_NOTICE ( LOADER , " *** &sceUserMainThreadStackSize = 0x%x " , proc_param - > sceUserMainThreadStackSize ) ;
LOG_NOTICE ( LOADER , " *** &sceUserMainThreadAttribute = 0x%x " , proc_param - > sceUserMainThreadAttribute ) ;
LOG_NOTICE ( LOADER , " *** &sceProcessName = 0x%x " , proc_param - > sceProcessName ) ;
LOG_NOTICE ( LOADER , " *** &sce_process_preload_disabled = 0x%x " , proc_param - > sce_process_preload_disabled ) ;
LOG_NOTICE ( LOADER , " *** &sceUserMainThreadCpuAffinityMask = 0x%x " , proc_param - > sceUserMainThreadCpuAffinityMask ) ;
auto libc_param = proc_param - > __sce_libcparam ;
LOG_NOTICE ( LOADER , " __sce_libcparam(addr=0x%x) analysis... " , libc_param ) ;
if ( libc_param - > size ! = 0x1c | | libc_param - > unk1 )
{
LOG_ERROR ( LOADER , " __sce_libcparam: unexpected data found (size=0x%x, 0x%x, 0x%x) " , libc_param - > size , libc_param - > unk1 , libc_param - > unk2 ) ;
}
LOG_NOTICE ( LOADER , " *** &sceLibcHeapSize = 0x%x " , libc_param - > sceLibcHeapSize ) ;
LOG_NOTICE ( LOADER , " *** &sceLibcHeapSizeDefault = 0x%x " , libc_param - > sceLibcHeapSizeDefault ) ;
LOG_NOTICE ( LOADER , " *** &sceLibcHeapExtendedAlloc = 0x%x " , libc_param - > sceLibcHeapExtendedAlloc ) ;
LOG_NOTICE ( LOADER , " *** &sceLibcHeapDelayedAlloc = 0x%x " , libc_param - > sceLibcHeapDelayedAlloc ) ;
2015-01-31 17:44:26 +01:00
armv7_init_tls ( ) ;
2015-01-21 22:09:37 +01:00
armv7_decoder_initialize ( code_start , code_end ) ;
2015-02-01 22:12:40 +01:00
const std : : string & thread_name = proc_param - > sceUserMainThreadName ? proc_param - > sceUserMainThreadName . get_ptr ( ) : " main_thread " ;
2015-02-02 22:00:05 +01:00
const u32 stack_size = proc_param - > sceUserMainThreadStackSize ? * proc_param - > sceUserMainThreadStackSize : 256 * 1024 ;
const u32 priority = proc_param - > sceUserMainThreadPriority ? * proc_param - > sceUserMainThreadPriority : 160 ;
2015-02-01 22:12:40 +01:00
2015-02-02 10:14:49 +01:00
armv7_thread ( entry , thread_name , stack_size , priority ) . args ( { Emu . GetPath ( ) , " -emu " } ) . run ( ) ;
2014-11-30 23:04:47 +01:00
break ;
}
2014-11-29 18:41:18 +01:00
case MACHINE_SPU : spu_thread ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_entry : m_ehdr . data_be . e_entry , " main_thread " ) . args ( { Emu . GetPath ( ) /*, "-emu"*/ } ) . run ( ) ; break ;
2013-08-03 11:40:03 +02:00
}
2012-11-15 00:39:56 +01:00
2014-11-19 15:16:30 +01:00
return ok ;
2013-07-06 01:49:38 +02:00
}
2014-11-02 00:19:14 +01:00
2015-02-01 21:02:40 +01:00
handler : : error_code elf32 : : load_data ( u32 offset , bool skip_writeable )
2014-11-02 00:19:14 +01:00
{
2014-11-28 19:56:16 +01:00
Elf_Machine machine = ( Elf_Machine ) ( u16 ) ( m_ehdr . is_le ( ) ? m_ehdr . data_le . e_machine : m_ehdr . data_be . e_machine ) ;
2014-11-19 15:16:30 +01:00
for ( auto & phdr : m_phdrs )
2014-11-02 00:19:14 +01:00
{
2014-11-19 15:16:30 +01:00
u32 memsz = m_ehdr . is_le ( ) ? phdr . data_le . p_memsz : phdr . data_be . p_memsz ;
u32 filesz = m_ehdr . is_le ( ) ? phdr . data_le . p_filesz : phdr . data_be . p_filesz ;
u32 vaddr = offset + ( m_ehdr . is_le ( ) ? phdr . data_le . p_vaddr : phdr . data_be . p_vaddr ) ;
u32 offset = m_ehdr . is_le ( ) ? phdr . data_le . p_offset : phdr . data_be . p_offset ;
2014-11-02 00:19:14 +01:00
2014-11-19 15:16:30 +01:00
switch ( m_ehdr . is_le ( ) ? phdr . data_le . p_type : phdr . data_be . p_type )
2014-11-02 00:19:14 +01:00
{
2014-11-19 15:16:30 +01:00
case 0x00000001 : //LOAD
if ( phdr . data_le . p_memsz )
{
2014-11-30 23:04:47 +01:00
if ( machine = = MACHINE_ARM & & ! Memory . PSV . RAM . AllocFixed ( vaddr , memsz ) )
2014-11-19 15:16:30 +01:00
{
LOG_ERROR ( LOADER , " %s(): AllocFixed(0x%llx, 0x%x) failed " , __FUNCTION__ , vaddr , memsz ) ;
return loading_error ;
}
2015-02-01 21:02:40 +01:00
if ( skip_writeable = = true & & ( phdr . data_be . p_flags & 2 /*PF_W*/ ) ! = 0 )
{
continue ;
}
2014-11-19 15:16:30 +01:00
if ( filesz )
{
m_stream - > Seek ( handler : : get_stream_offset ( ) + offset ) ;
m_stream - > Read ( vm : : get_ptr ( vaddr ) , filesz ) ;
}
}
2014-11-05 19:53:54 +01:00
break ;
}
2014-11-02 00:19:14 +01:00
}
2014-11-19 15:16:30 +01:00
return ok ;
2014-11-02 00:19:14 +01:00
}
2012-11-15 00:39:56 +01:00
}
2014-12-26 08:26:43 +01:00
}