He used Kiel arm tools - I doubt that Kiel provide them for free and I'm not aware of a sh4 version.
So let's use the power of gnu tools, it is sufficient.
Reimplementing of whole C function
It is a little bit heavy-weight patching. You have to analyze more code and dependencies.
It pays of for shorter functions, because you can comfortably write in C
and you get full control what function do. Another advantage particularly in sh4 exeDSP
is that you get usually enough space for your new code: original code is compiled
without optimization(!!) and you can use -Os option (optimize for size)
You should tell gcc you want the function in extra code segment:
Code: Select all
int STMovie_SetDisplaySize(int fit)
__attribute__ ((section("patch1STMovie_SetDisplaySize")));
int STMovie_SetDisplaySize(int fit)
{
// your code
int iw = videoInputWidth;
STVID_GetInputWindowMode(handle, &mode, &pi);
}
Assembly language
Of course you can use assembly language to replace shorter fragment of code.
On sh4 there is a limitation that segment is always aligned to even word.
If you need start at odd word, you have to include one instruction preceding your change.
Unfortunately gnu linker cannot compute sh4 relative jumps to different segment,
so if you want to use them, awkward math is necessary:
Code: Select all
.equ PatchStartLoc, 0xd167c8
.equ CheckPositiveLoc, 0xd16840
.section patch2ChangeToNextZoomOption,"ax",@progbits
PatchStart:
cmp/pl r0
bt CheckPositiveLoc + PatchStart - PatchStartLoc /*instead of CheckPositive, which you could use if it were in same segment*/
.section patch3ChangeToNextZoomOption,"ax",@progbits
CheckPositive:
Linking
You should tell the linker where your new code will reside.
Use option
Code: Select all
--section-start=patch1STMovie_SetDisplaySize=0x56f43c
In the script you can also check if your replaced function fits in limited space:
Code: Select all
OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
OUTPUT_ARCH(sh)
SECTIONS
{
.patch1 0x56f43c : { *(patch1STMovie_SetDisplaySize) *(.rodata*) }
ASSERT( . <= 0x56fa28, "STMovie_SetDisplaySize is too big to fit into exeDSP")
.patch2 0xd167c8 : { *(patch2ChangeToNextZoomOption) }
...
If your exeDSP has symbols like arm versions, the easy way is use it for linking
Code: Select all
--just-symbols=exeDSP
Then you can use option
Code: Select all
--defsym=videoInputWidth=0x221020c
Code: Select all
STVID_GetInputWindowMode = 0x9a6168;
Code: Select all
-nostartfiles -nostdlib
You've just compiled and linked your shiny patch. Got elf binary. What now?
Traditional way is convert it to hex by objcopy utility and patch exeDSP somehow.
gdb can load a patch
If you used gdb/gdbserver for getting info from exeDSP, just stop the program, load the elf
and then jump to last address of program execution. Continue will not work
as it use 'start address' of just loaded elf.
elfpatcher
Users of your patch don't want to start gdb - they don't know what the hell it is.
That's why I take a programmers exercise and write this short program.
It is 3-in-one function actually.
1) You can patch running program in memory using ptrace() call in similar way as gdb does.
Actually program is stopped for couple of miliseconds while elfpatcher is changing it.
Ideal for testing without worries of TV bricking.
2) You can patch elf binary without fiddling with address offset.
If exeDSP is on writable filesystem, elfpatcher works directly in TV (you should stop exeDSP first). Tested in my LE46A956
On linux PC can be used to prepatch firmware.
3) Additional functions like checking if patch is applied and hexedecimal output of original
and new data.
Code: Select all
$ build/tmp/work/i686-linux/elfpatcher-native-1.0-r1/elfpatcher
elfpatcher 1.0
Takes one or more elf32 files and writes the content of segments named .patch*
Patching a binary file is potentially dangerous, use solely at your own risk
Usage:
elfpatcher [-v] -p pid elf-patch-file...
elfpatcher [-v] [-c] -e original-elf-file elf-patch-file...
-p pid.... stops running process using PTRACE, patches text or data
in process memory and continues the process
-e file... writes patches to appropriate segments of elf32 file
-c........ do not write, just check if patches are applied
-v........ verbose: shows hex representation of patch
-v -v..... double verbose: shows original data before applying patches too
Hope it helps even to the arm powered majority.