OpenWiki

Yahm Lib

Palm Notes | Recent Changes | Title Index | User Preferences | Random Page | Help
Difference from prior major revision.
minor diff author diff hide diff

<TableOfContents/>
  
=== Library purpose ===
  
YAHM library was designed for simple migration from ARM-based hack to 
standalone application. With help of YAHMlib you can easily implement syscall 
patching inside your application.
  
=== Library review ===
  
YAHMLib has 3 layers of API. All API's are implemented as m68k functions.
  
  * High layer API is the easiest one. With this API YAHMLib consider your 
application as hack. API allow you to activate and deactivate patches. 
  * Middle layer API. This layer can be used for manual syscall patching. 
  * Low layer API. This layer implements ARM versions of ~SysGetTrapAddress and 
~SysSetTrapAddress functions. 
  
=== The benefits of YAHMLib ===
  * Simple application structure is similar to classic hack database layout.
  * Safe trap chain handling. YAHMLib carefully works with trap chain. If you 
want to deactivate hack from middle of this chain, you can be sure that chain 
remain unbroken. 
  * Processor data and instruction cache issues are solved automagically. 
  * Thumb-awareness support. You can compile patches as pure ARM code. Library 
wrap your code with thumb-aware thunks. 
  * GCC .got sections are processed automatically. 
  
  
Current documentation assumes that reader already knows how to create hack. 
Only YAHMLib API is duscussed below. 
  
=== Library integration ===
YAHM library can be used with both CW and GCC compilers. Just include 
lowlevel.c and trapcontrol5.c sources to your project. yahm_lib.h header 
contains all YAHM API functions. Include 5 arm resources into target 
executable. 
  
Also you can include ~YahmLibrary.rcp into your project:
<code>
#include "yahm_int.h"
  
  
DATA "armc" ID YAHM_INIT_RES_ID "armc270E.bin"
DATA "armc" ID YAHM_SET_TRAP_RES_ID "armc270F.bin"
  
DATA "armc" ID YAHM_FAT_THUNK_RES_ID "fatthunk.bin"
DATA "armc" ID YAHM_SHORT_RES_ID "SHORT.BIN"
DATA "armc" ID  YAHM_SHORT_OLD_RES_ID "shorttoold.bin"
DATA "armc" ID  YAHM_CW_THUNK_RES_ID "cwthunk.bin"
  
</code>
  
=== Error codes ===
  
YAHM library return some custom errors: 
  
  * **hack~ErrWrongTrapInfo** - returned if TRA5 resource wrong 
  * **hack~ErrNoFreeThunk** - library can't find free thunk for patch. Increase 
thunkCount value and restart device. 
  * **hack~ErrNoActiveApp** - library can't detect current application. Avoid 
trap installation from callback-based notification handlers. 
  * **hack~ErrInitializationFailed** - hack initialization function (resource 
armc 999) returns false. 
  * **hack~ErrNoHackResources** - current app have no patch resources. Check 
that all 'armc' and 'TRA5' are added to executable. 
  * **hack~ErrNoLibraryArmlet** - library can't find it's own armlets. Include 
it into application. 
  
  
=== High level API ===
High level API is the simplest one. Just move all resources from hack to 
standalone application. API contains of two functions: one for hack activation 
and one for hack deactivation. 
<code>
Err YAHM_InstallHack(void);
  
Err YAHM_UninstallHack(void);
</code>
  
**YAHM_~InstallHack** install all 'armc' resources from current application. 
Alse initialization 'armc' 999 resource is called before if exists. 
  
**YAHM_~UninstallHack** uninstall patches that were installed with 
YAHM_~InstallHack.
  
Known issues for hack to application migration: 
Check type of application in hack code. Now it's 'appl', not the 'code'. 
Implement configuration screen manually. It's much simple than writing a hack 
configuration panel. 
  
  
=== Middle level API ===
  
Use middle level instead of high level if you want flexible trap patching. High 
level call middle level functions for each 'armc' resource.
  
<code>
Err YAHM_ExecuteInitialization(void *initCodeResource, Boolean init);
// initCodeResource - pointer to initialization arm code
// init - true for initialization, false for deinitialization
  
Err YAHM_InstallTrap(MemHandle hTrapCode, MemHandle hGot, MemHandle hTrapInfo, 
UInt32 creator, UInt16 resId);
// hTrap code - handle for trap arm code chunk (or resource)
// hGot - handle for gcc GOT section, pass NULL for CodeWarrior 
// hTrapInfo - handle for TRA5 resource with YAHM_SyscallInfo5 structure
// creator, resId - those parameters are used for FtrSet(creator, resId, 
oldTrapAddress) 
  
void YAHM_UninstallTrap(MemHandle hTrap, UInt32 creator, UInt16 resID);
// hTrap code - handle for trap arm code chunk (or resource)
// creator, resId - those parameters are used for restoring old address from 
FtrGet(creator, resId, &oldTrapAddress) 
  
  
void *YAHM_FixupGccCode(MemHandle hGot, void *pCodeResource, void* *ppGotPtr);
void *YAHM_FixupGccCodeEx(MemHandle hGot, MemHandle  hCodeResource, void* 
*ppGotPtr);
// pCodeResource - pointer to arm code chunk
// hCodeResource - pointer to arm code chunk
// hGotResource - handle for gcc GOT section, pass NULL for CodeWarrior 
// ppGotPtr - pointer to GOT into relocated chunk
// return value - pointer to relocated chunk or codeResource if GOT section is 
absent
  
void YAHM_FreeRelocatedChunk(void *pRelocatedCode);
  
  
</code>
  
**YAHM_~ExecuteInitialization** used for calling 
initialization/deinitialization resouce manually. 
  
Call **YAHM_~InstallTrap** to install trap. Pass handles for code, .got, trap 
info for proper installation. Function save old syscall pointer to feature with 
creator and resId parameters. 
  
Call **YAHM_~UninstallTrap** to uninstall trap. 
  
==== .got section ====
Compilation with arm-gcc creates ELF executable file and extracts code section 
from it. Creating position-independent code (PIC) in ELF executable creates 
additional .got section. Code uses .got section to evaluate function addresses 
and literal strings offsets. build-prc from YAHM SDK includes .got section into 
target .prc file with the same ~ResID as appropriate armc resource has. YAHM 
loads both armc and .got and merge it into single resource in dynamic heap. 
High and Middle levels load .got section too.
**YAHM_~FixupGccCode** and **YAHM_~FixupGccCodeEx** function can be used to 
load resource with .got section manually. Those functions merge code resource 
(passed in h~CodeResorce or p~CodeResource parameters) and .got resource 
(passed in h~GotResource parameter). Function returns an address of relocated 
chunk in dynamic memory or NULL if there are no enough memory. pp~GotPtr 
parameter points to .got section on exit. This parameter value can be used to 
set R10 register for PIC arm code.
  
YAHM_FreeRelocatedChunk**YAHM_~FreeRelocatedChunk** can be used for freeing
relocated code chunk.
  
hGotResourceh~GotResource parameter can be set to NULL. In this case functions
don't make relocation and return p~CodeResource as relocated address value. If
relocated address is found in storage memory, then **YAHM_~FreeRelocatedChunk**
doesn't free chunk. This feature can be used to load and relocate both GCC and
CW resources similary.
  
YAHMLib v1.07+ checks for NVFS manager existence and copies all code resources 
into dynamic heap to avoid problems with NVFS DBCache. 
  
=== Low level API ===
  
Low level API mimics pre-OS5 API. Only two functions for setting and retrieving 
trap handler address. Those functions require deep knowledge of ARM 
programming. 
  
<code>
void *YAHM_GetTrapAddress(UInt32 base, UInt32 offset);
  
void *YAHM_SetTrapAddress(UInt32 base, UInt32 offset, void *trapHandler);
</code>
  
=== User-defined functions ===
YAHMLib requires few user-defined functions to work. Developer should implement 
those simple functions manually. The simplest version are showed below. 
  
Persistent settings
<code>
typedef struct{ // Global YAHM settings. Should be saved in preferences.
        UInt32 protectYAHM; // if true, then YAHM protect application database
        UInt32 thunkCount;        // number of trap slots. allocate at least 
40-50 slots.
}YAHM_persistSettings;
  
// copy persist settings to structure, allocated by YAHM
extern void YAHM_GetPersistSettings(YAHM_persistSettings *pSettings);
  
// implementation sample
void YAHM_GetPersistSettings(YAHM_persistSettings *pSettings){
        pSettings->protectYAHM = true;
        pSettings->thunkCount = 40;
}
</code>
  
YAHMLibrary require persistent setting to work. Developer should implement 
**YAHM_~GetPersistSettings** function for changing library behaviour. Those 
settings can be either set in code or can be changed by user. 
  
  * **protectYAHM** - if this field set to non-zero, library protect current 
application against deletion when traps are set. Current application checks 
with ~SysCurAppDatabase syscall. Only YAHM_~InstallHack and YAHM_~UninstallHack 
function use this value. 
  * **thunkCount**. This field is used for thunk array allocation. YAHM 
allocates one thunk per active syscall patch. Usually patch deactivation frees 
thunk, but sometimes patch deactivation require leaving thunk in 
"used" state to support patch linked list integrity. If your code 
require reset for deactivation, you can make thunkCount equal to number of 
patched traps. Else, especially if ~EvtGetEvent is patched or your app 
deactivates on each hotsync, allocate 40-50 thunks. 
  
Runtime settings
<code>
typedef struct{ // Runtime YAHM settings. They are valid on single YAHM 
execution. Should be saved in feature pointer
        UInt32 activeHacksCount;
        void *pPool;
}YAHM_runtimeSettings;
  
extern void YAHM_SetRuntimeSettings(YAHM_runtimeSettings *pSettings);
// return ptr to runtime settings structure.
extern YAHM_runtimeSettings *YAHM_GetRuntimeSettingsPtr(void);
  
// callback function. 
extern void YAHM_warnAboutIncompatibleUpdate(void);
  
  
// sample implementation
void YAHM_SetRuntimeSettings(YAHM_runtimeSettings *pSettings)
{
         FtrSet(MY_CRID, YAHM_FTR_ID, (UInt32)pSettings);
}
  
YAHM_runtimeSettings *YAHM_GetRuntimeSettingsPtr(void)
{
        YAHM_runtimeSettings *pSet = NULL;
        FtrGet(CRID, YAHM_FTR_ID, (UInt32 *)&pSet);
        if (pSet == NULL){
                pSet = MemPtrNew(sizeof(YAHM_runtimeSettings));
                YAHM_SetRuntimeSettings(pSet);
                MemPtrSetOwner(pSet, 0);
                MemSet(pSet, sizeof(YAHM_runtimeSettings), 0);
        }
        return pSet;
}
</code>
  
  
Developer is responsible for allocating and saving YAHM library runtime 
settings. **YAHM_~GetRuntimeSettingsPtr** function should return pointer to 
persistent structure. For the first time this function should allocate memory 
chunk for settings. The best way is saving pointer to structure in feature 
memory. Runtime settings should be valid from the first hack activation up to 
device reset. You can share one runtime settings between different programs. 
  
Function **YAHM_warn~AboutIncompatibleUpdate** is called when several programs 
(or two different program versions) are used different versions of YAHM 
Library. This function usually should call ~SysFatalAlert. 
  
=== The meaning of thunk types ===
Thunk is a piece of code and data that sits between syscall table and your 
patch code. Thunk was introduced to solve two problems: to prevent patch chain 
breaks and to execute runtime startup.
  
Different thunk types require different code configurations. Currently YAHMLib 
supports three type of thunks.
  
==== Thunks for GCC ====
  * THUNK_COMMON. It's the easiest one. This thunk saves registers on own stack 
and completely transparent for GCC compiler. This is the slowest kind of thunk. 
It can be used as most common thunk type. This thunk support .got relocation
  * THUNK_FAST. The fastest thunk. GCC users can use it for time critical 
syscalls. This thunk don't support .got relocation.
  * THUNK_CW. Thunk for ~CodeWarrior compiler. Can be used with GCC. Saves two 
registers on stack and cause "5th parameter shift". Search for 
details in CodeWarrior hack samples. This thunk support .got relocation
  
==== Thunks for CodeWarrior ====
  * THUNK_COMMON. It's the easiest one. This thunk saves registers on different 
stack. This thunk require __ARMlet_Startup__ function to be called first for 
~CodeWarior users. Patch function have name ARMlet_Main.  This is the slowest 
kind of thunk.
  * THUNK_FAST. The fastest thunk. CodeWarrior users can't use it.
  * THUNK_CW. This thunk save registers and prepare R10 like 
__ARMlet_Startup__. You can use this thunk instead of __ARMlet_Startup__. Just 
set this type of stack in TRA5 resource and remove ARMlet_Startup.c from 
project. Don't forget to rename patch function to __ARMlet_Startup__
  
  
  

Palm Notes | Recent Changes | Title Index | User Preferences | Random Page | Help
Edit this page | View other revisions
Print this page | View XML
Find page by browsing, searching or an index
Edited November 20, 2005 (hide diff)