26 October 2009

LabelAddr in a GLL

In two recent posts (here and here) I discussed the problems with subclassing the Gfa_hWnd window in a GLL. In fact, it turned out to be impossible using 'normal' Windows API functions. Another solution was required.
The final solution I developed is based on the MS Detours technique from MS Research Labs. However, not even this highly tricky technique worked for me. The GLL still couldn't be unloaded using the Extension Manager Dialog box. Then, I adapted the Detour technique and configured it in such a way that unloading the GLL isn't a problem anymore. Almost two years ago I first started to study the Detours technique, and finally I came up with a solution to full fill my needs.
The adapted method is based on a GFA-BASIC 32 assembly routine, which is injected into the main window procedure of Gfa_hWnd inside the code of the IDE. To complete my mission I had to figure out the address of a label inside a GFA-BASIC subroutine. The injected code has to jump (jmp) to the label's address. However, the addresses of labels in GLLs (GFA Editor Extensions) are not known in advance.
Both the ProcAddr() and LabelAddr() functions are filled in by the compiler at compile time. In addition, a relocation-table is stored with the compiled program. In contrast with loading an EXE, which is performed by the OS, the addresses in a GLL are relocated by the GFA-BASIC 32 IDE when the GLL is loaded. The IDE is capable of adjusting the ProcAddr addresses inside the GLL, but it doesn't adjust the hardcoded LabelAddr values.
It takes a trick to obtain the relocated address of a label. The GLL is loaded into memory and addresses are calculated using an offset. When we know the offset value the hardcoded label addresses can be calculated. The function Gfa_LabelOffset in the next code, does just this. Since the value is constant for the entire GLL, it is stored in a static variable.
Function Gfa_LabelOffset() As Long
Static LabelOffset% = 0
If LabelOffset% == 0
GetRegs : 1
LabelOffset% = _EIP - LabelAddr(1)
EndIf
Return LabelOffset%
EndFunc


The function can be used to obtain the real location of a label as follows:


Local stubAddr% = LabelAddr(stub) + Gfa_LabelOffset
stub:


The LabelAddr(stub) returns the hardcoded value set by the compiler. The real location is then adjusted by the offset value used to relocate all addresses in the GLL.

No comments:

Post a Comment