Line 1:
Line 1:
−
Internally, IOS uses a syscall table that is stored toward the end of the binary. The exact address varies with version of IOS; as a concrete example, boot2's syscall_base is at 0xFFFF7F60.
+
Internally, IOS uses a syscall table that is stored toward the end of the binary. The exact address varies with version of IOS, but there are two methods to locate it:
+
ELF header:
+
+
The second-to-last program header is the syscall table. For example:
+
$ arm-eabi-readelf -l ~/wii/system_updates/boot2.elf | tail -2
+
LOAD 0x0230d5 0xffff7f60 0xffff7f60 0x00a88 0x00a88 RW 0x10
+
LOAD 0x023b5d 0xffff8a00 0xffff8a00 0x00000 0x071e8 RW 0x20
+
+
or
+
elf_header:134C01A0 elf32_phdr < 1, 0x230D5, syscall_base, syscall_base, 0xA88, 0xA88, 6, 0x10>
+
elf_header:134C01C0 elf32_phdr < 1, 0x23B5D, current_thread_context, current_thread_context, 0, 0x71E8, 6, 0x20>
+
+
Syscall Handler:
+
The second vector is the invalid instruction handler, which is used to implement syscalls:
+
+
kernel:FFFF0000 LDR PC, =_reset
+
kernel:FFFF0004 LDR PC, =starlet_syscall_handler
+
+
kernel:FFFF1894 starlet_syscall_handler ; CODE XREF: start�j
+
kernel:FFFF1894 E9 CD 7F FF STMFA SP, {R0-LR}^
+
kernel:FFFF1898 E1 4F 80 00 MRS R8, SPSR
+
kernel:FFFF189C E5 8D 80 00 STR R8, [SP,#arg_0]
+
kernel:FFFF18A0 E5 8D E0 40 STR LR, [SP,#arg_40]
+
kernel:FFFF18A4 E5 1E A0 04 LDR R10, [LR,#-4]
+
kernel:FFFF18A8 E3 CA 9D 7F BIC R9, R10, #0x1FC0
+
kernel:FFFF18AC E5 9F 84 9C LDR R8, =0xE6000010
+
kernel:FFFF18B0 E3 C9 90 20 BIC R9, R9, #0x20
+
kernel:FFFF18B4 E1 59 00 08 CMP R9, R8
+
kernel:FFFF18B8 1A 00 00 1F BNE loc_FFFF193C
+
kernel:FFFF18BC E1 A0 A2 CA MOV R10, R10,ASR#5
+
kernel:FFFF18C0 E2 0A A0 FF AND R10, R10, #0xFF
+
kernel:FFFF18C4 E3 5A 00 75 CMP R10, #0x75 ; 'u'
+
kernel:FFFF18C8 CA 00 00 11 BGT loc_FFFF1914
+
kernel:FFFF18CC E1 A0 80 0D MOV R8, SP
+
kernel:FFFF18D0 E3 A0 B0 1F MOV R11, #0x1F
+
kernel:FFFF18D4 E1 21 F0 0B MSR CPSR_c, R11
+
kernel:FFFF18D8 E5 98 80 44 LDR R8, [R8,#arg_44]
+
kernel:FFFF18DC E5 9F B4 70 LDR R11, =syscall_flags_maybe
+
kernel:FFFF18E0 E7 9B B1 0A LDR R11, [R11,R10,LSL#2]
+
kernel:FFFF18E4 E0 8D D1 0B ADD SP, SP, R11,LSL#2
+
kernel:FFFF18E8
+
kernel:FFFF18E8 loc_FFFF18E8 ; CODE XREF: starlet_syscall_handler+68�j
+
kernel:FFFF18E8 E3 5B 00 00 CMP R11, #0
+
kernel:FFFF18EC 0A 00 00 03 BEQ loc_FFFF1900
+
kernel:FFFF18F0 E5 3D 90 04 LDR R9, [SP,#var_4]!
+
kernel:FFFF18F4 E5 28 90 04 STR R9, [R8,#-4]!
+
kernel:FFFF18F8 E2 4B B0 01 SUB R11, R11, #1
+
kernel:FFFF18FC EA FF FF F9 B loc_FFFF18E8
+
kernel:FFFF1900 loc_FFFF1900 ; CODE XREF: starlet_syscall_handler+58�j
+
kernel:FFFF1900 E1 A0 D0 08 MOV SP, R8
+
kernel:FFFF1904 E5 9F B4 4C LDR R11, =syscall_base
+
kernel:FFFF1908 E7 9B B1 0A LDR R11, [R11,R10,LSL#2]
+
kernel:FFFF190C E1 A0 E0 0F MOV LR, PC
+
kernel:FFFF1910 E1 2F FF 1B BX R11
+
kernel:FFFF1914 loc_FFFF1914 ; CODE XREF: starlet_syscall_handler+34�j
+
kernel:FFFF1914 E3 A0 B0 DB MOV R11, #0xDB ; '¦'
+
kernel:FFFF1918 E1 21 F0 0B MSR CPSR_c, R11
+
kernel:FFFF191C E5 9D B0 00 LDR R11, [SP,#arg_0]
+
kernel:FFFF1920 E1 6F F0 0B MSR SPSR_cxsf, R11
+
kernel:FFFF1924 E1 A0 E0 00 MOV LR, R0
+
kernel:FFFF1928 E9 DD 7F FF LDMED SP, {R0-LR}^
+
kernel:FFFF192C E1 A0 00 00 NOP
+
kernel:FFFF1930 E1 A0 00 0E MOV R0, LR
+
kernel:FFFF1934 E5 9D E0 40 LDR LR, [SP,#arg_40]
+
kernel:FFFF1938 E1 B0 F0 0E MOVS PC, LR
+
kernel:FFFF193C loc_FFFF193C ; CODE XREF: starlet_syscall_handler+24�j
+
kernel:FFFF193C E5 9F D4 18 LDR SP, =current_thread_context
+
kernel:FFFF1940 E5 9D D0 00 LDR SP, [SP,#arg_0]
+
kernel:FFFF1944 E5 8D E0 40 STR LR, [SP,#arg_40]
+
kernel:FFFF1948 E3 A0 E0 06 MOV LR, #6
+
kernel:FFFF194C E5 8D E0 50 STR LR, [SP,#arg_50]
+
kernel:FFFF1950 E2 8D D0 04 ADD SP, SP, #4
+
kernel:FFFF1954 E9 4D 7F FF STMFD SP, {R0-LR}^
+
kernel:FFFF1958 E1 4F B0 00 MRS R11, SPSR
+
kernel:FFFF195C E5 0D B0 04 STR R11, [SP,#-4+arg_0]
+
kernel:FFFF1960 EA 00 00 C9 B schedule
+
kernel:FFFF1960 ; End of function starlet_syscall_handler
+
Syscalls are invoked by way of the invalid instruction handler; syscalls take the form 0xE6000010 | (syscall_num << 5). (E.g. E6000010 is syscall 0, E60006D0 is syscall 0x36, etc.)
Syscalls are invoked by way of the invalid instruction handler; syscalls take the form 0xE6000010 | (syscall_num << 5). (E.g. E6000010 is syscall 0, E60006D0 is syscall 0x36, etc.)