User Tools

Site Tools


syslinkerstub
// структура и прототип взяты из sdk от mobile-stream

typedef struct {
	UInt32		dbType;
	UInt32		dbCreator;
	UInt32		revision;
	UInt32		entries;
	UInt32		rsrcTypeData0;
	UInt32		rsrcTypeCode0;
	UInt32		rsrcTypeCode1;
	UInt16		rsrcIDData0;
	UInt16		rsrcIDCode0;
	UInt16		rsrcIDCode1;
	UInt16		reserved;
} SysModuleDescriptorType;


void SysLinkerStub(const SysModuleDescriptorType *moduleP, UInt32 clientID, void **dispatchTablePP);

/*
 * Вызов процедуры при неявном связывании происходит в три этапа. Инфраструктуру
 * строит специальный препроцессор, используя библиотеку экспорта библиотеки.
 * Каждый этап является законченным фрагментом кода. Первый фрагмент генерируется 
 * для каждой функции, второй  - для каждой билиотеки, а третий - один на все вызовы.
 * 
 * Неявное связывание происходит при первом вызове функции из модуля. Этот вызов загружает
 * библиотеку и записывает в определенное место в памяти адрес таблицы экспорта.
 * Все последующие вызовы вызывают функции напрямую.
 *
 * Список модифицируемых команд в функциях
 * 1. В ExportedFunction1 
 * 1.1 LDR     R12, [R12,#CURRENT_MODULE_INDEX]
 *     вписывается индекс текущего модуля
 * 1.2 LDR     R12, [R12,#LIB1_DISPATCH_ADDRESS_OFFSET_IN_GLOBALS]
 *     вписывается смещение глобальной переменной с адресом таблицы экспорта
 * 1.3 ADDNE   PC, R12, #EXPORTED_FUNCTION1_ORDINAL
 *     вписывается смещение функции в таблице экспорта (номер функции * 4)
 * 2. В LoadLib1
 * 2.1 Формируется структура lib1Desc
 * 3. В функции ImplicitLoadLibrary
 * 3.1 LDR     R2, [R2,#CURRENT_MODULE_INDEX]
 *     вписывается индекс текущего модуля
 */

#define CURRENT_MODULE_INDEX					0x200
#define LIB1_DISPATCH_ADDRESS_OFFSET_IN_GLOBALS 0x10
#define EXPORTED_FUNCTION1_OFFSET				(20 * 4)

Err ExportedFunction1(UInt32 param0, UInt32 param1, UInt32 param2, UInt32 param3, UInt32 param4, UInt32 param5, UInt32 param6){
	// загрузить в R12 указатель на сегмент данных используемого модуля
	_asm LDR     R12, [R9]
ExportedFunction1_LabelWithCurrentModuleIndexAddr:
	_asm LDR     R12, [R12,#CURRENT_MODULE_INDEX]
ExportedFunction1_LabelWithDispatchAddr:
	// загрузить в R12 адрес таблицы экспорта вызываемого модуля
	_asm LDR     R12, [R12,#LIB1_DISPATCH_ADDRESS_OFFSET_IN_GLOBALS]
	// проверить, что библиотека уже загружена (адрес != 0), 
	_asm CMP     R12, #0
	// если билиотека загружена, то перейти на функцию по смещению в библиотеке
	_asm ADDNE   PC, R12, #EXPORTED_FUNCTION1_OFFSET
	// если функция не загружена, то перейти ко второй фазе,
	// предварительно сохранив в стеке адрес метки ExportedFunction1_Addr
	// для повторного вызова после загрузки библиотеки
	_asm STMFD   SP!, {PC}
	_asm B       LoadLib1
ExportedFunction1_BackAddr:
}

Err LoadLib1(UInt32 param0, UInt32 param1, UInt32 param2, UInt32 param3, UInt32 param4, UInt32 *backAddr, UInt32 param5, UInt32 param6){
	_asm ADR     R12, lib1Desc
	_asm STMFD   SP!, {R12}
	_asm B       ImplicitLoadLibrary
}


// константный дескриптор следует в коде сразу после функции
const SysModuleDescriptorType lib1Desc = {'aexo', 'HsEx', 1, 0x6E, 'amdd', 'amdi', 'amdc', 0, 0, 0, 0};


Err ImplicitLoadLibrary(UInt32 param0, UInt32 param1, UInt32 param2, UInt32 param3, UInt32 param4, 
			  SysModuleDescriptorType *pDescr, UInt32 *backAddr, UInt32 param5, UInt32 param6){

/* сохранить регистры.
 * после операции в стеке располагаются:
 * SP + 00 R0
 * SP + 04 R1
 * SP + 08 R2
 * SP + 0C R3
 * SP + 10 LR
 * SP + 14 pDescr
 * SP + 18 backAddr
 * SP + 1C param5
 * SP + 20 param6
*/
	_asm STMFD   SP!, {R0-R3,LR}
	// R1 = ImplicitLoadLibrary_Label0 (ImplicitLoadLibrary_Label1 - 4)
	_asm SUB     R1, PC, #4
	// R2 = ImplicitLoadLibrary_Label2
ImplicitLoadLibrary_Label0:
	_asm STMFD   SP!, {PC}
ImplicitLoadLibrary_Label1:
	_asm LDMFD   SP!, {R2}
ImplicitLoadLibrary_Label2:
	// R2 = ImplicitLoadLibrary_Label2 - ImplicitLoadLibrary_Label0 + 0x14 (0x1C)
	_asm SUB     R2, R2, R1
	_asm ADD     R2, R2, #0x14
	// *backAddr -=  ImplicitLoadLibrary_Label2 - ImplicitLoadLibrary_Label0 + 0x14 (0x1C)
	// скорректировать backAddr дабы он указывал на ExportedFunction1
	_asm LDR     R1, [SP,#0x18]
	_asm SUB     R1, R1, R2
	_asm STR     R1, [SP,#0x18]
	// R0 = *(ExportedFunction1_LabelWithDispatchAddr)
	// R0 = "LDR     R12, [R12,#LIB1_DISPATCH_ADDRESS_OFFSET_IN_GLOBALS]"
	_asm LDR     R0, [R1,#8]
	// R3 = 0xFFF
	_asm MOV     R3, #0x1000
	_asm SUB     R3, R3, #1
	// R0 = LIB1_DISPATCH_ADDRESS_OFFSET_IN_GLOBALS
	_asm AND     R0, R0, R3
	// загрузить в R12 указатель на сегмент данных используемого модуля
	_asm LDR     R2, [R9]
	_asm LDR     R2, [R2,#CURRENT_MODULE_INDEX]
	// загрузить в R2 адрес таблицы экспорта вызываемого модуля
	_asm ADD     R2, R2, R0
	// R0 = *ExportedFunction1_LabelWithCurrentModuleIndexAddr
	// R0 = "LDR     R12, [R12,#CURRENT_MODULE_INDEX]"
	_asm LDR     R0, [R1,#4]
	// R1 = CURRENT_MODULE_INDEX / 4
	_asm AND     R1, R0, R3
	_asm MOV     R1, R1,LSR#2
	_asm LDR     R0, [SP,#0x14]
	_asm BL      SysLinkerStub
	// восстановить регистры
	_asm LDMFD   SP!, {R0-R3,LR}
	// выкинуть из стека pDescr
	_asm LDMFD   SP!, {R12}
	// R12 = backAddr
	_asm LDMFD   SP!, {R12}
	// перейти на backAddr
	_asm MOV     PC, R12
}
syslinkerstub.txt · Last modified: 2005/07/20 15:34 by 127.0.0.1