git-svn-id: https://svn.code.sf.net/p/kolmck/code@42 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
This commit is contained in:
@ -1,838 +0,0 @@
|
|||||||
{ *********************************************************************** }
|
|
||||||
{ }
|
|
||||||
{ Delphi / Kylix Cross-Platform Runtime Library }
|
|
||||||
{ System Initialization Unit }
|
|
||||||
{ }
|
|
||||||
{ Copyright (c) 1997-2005 Borland Software Corporation }
|
|
||||||
{ }
|
|
||||||
{ *********************************************************************** }
|
|
||||||
|
|
||||||
unit SysInit;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
{$H+,I-,R-,S-,O+,W-}
|
|
||||||
{$WARN SYMBOL_PLATFORM OFF}
|
|
||||||
{$WARN UNSAFE_TYPE OFF}
|
|
||||||
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
const
|
|
||||||
ExeBaseAddress = Pointer($8048000) platform;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
var
|
|
||||||
ModuleIsLib: Boolean; { True if this module is a dll (a library or a package) }
|
|
||||||
ModuleIsPackage: Boolean; { True if this module is a package }
|
|
||||||
ModuleIsCpp: Boolean; { True if this module is compiled using C++ Builder }
|
|
||||||
TlsIndex: Integer = -1; { Thread local storage index }
|
|
||||||
TlsLast: Byte; { Set by linker so its offset is last in TLS segment }
|
|
||||||
HInstance: LongWord; { Handle of this instance }
|
|
||||||
{$EXTERNALSYM HInstance}
|
|
||||||
(*$HPPEMIT 'namespace Sysinit' *)
|
|
||||||
(*$HPPEMIT '{' *)
|
|
||||||
(*$HPPEMIT 'extern PACKAGE HINSTANCE HInstance;' *)
|
|
||||||
(*$HPPEMIT '} /* namespace Sysinit */' *)
|
|
||||||
DllProc: TDLLProc; { Called whenever DLL entry point is called }
|
|
||||||
{ DllProcEx passes the Reserved param provided by WinNT on DLL load & exit }
|
|
||||||
DllProcEx: TDLLProcEx absolute DllProc;
|
|
||||||
DataMark: Integer = 0; { Used to find the virtual base of DATA seg }
|
|
||||||
CoverageLibraryName: array [0..128] of Char = '*'; { initialized by the linker! }
|
|
||||||
{$IFDEF ELF}
|
|
||||||
TypeImportsTable: array [0..0] of Pointer platform; { VMT and RTTI imports table for exes }
|
|
||||||
_GLOBAL_OFFSET_TABLE_: ARRAY [0..2] OF Cardinal platform;
|
|
||||||
(* _DYNAMIC: ARRAY [0..0] OF Elf32_Dyn; *)
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
TextStartAdj: Byte platform; { See GetTextStart }
|
|
||||||
CodeSegSize: Byte platform; { See GetTextStart }
|
|
||||||
function GetTextStart : LongInt; platform;
|
|
||||||
{$ENDIF}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
const
|
|
||||||
PtrToNil: Pointer = nil; // provides pointer to nil for compiler codegen
|
|
||||||
|
|
||||||
function _GetTls: Pointer;
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
procedure _InitLib(Context: PInitContext);
|
|
||||||
procedure _GetCallerEIP;
|
|
||||||
procedure _InitExe(InitTable: Pointer; Argc: Integer; Argp: Pointer);
|
|
||||||
procedure _start; cdecl;
|
|
||||||
function _ExitLib: Integer; cdecl;
|
|
||||||
function _InitPkg: LongBool;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
procedure _InitLib;
|
|
||||||
procedure _InitExe(InitTable: Pointer);
|
|
||||||
function _InitPkg(Hinst: Integer; Reason: Integer; Resvd: Pointer): LongBool; stdcall;
|
|
||||||
{$ENDIF}
|
|
||||||
procedure _PackageLoad(const Table: PackageInfo);
|
|
||||||
procedure _PackageUnload(const Table: PackageInfo);
|
|
||||||
|
|
||||||
{ Invoked by C++ startup code to allow initialization of VCL global vars }
|
|
||||||
procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl;
|
|
||||||
procedure VclExit; cdecl;
|
|
||||||
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
function GetThisModuleHandle: LongWord;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
const
|
|
||||||
kernel = 'kernel32.dll';
|
|
||||||
|
|
||||||
function FreeLibrary(ModuleHandle: Longint): LongBool; stdcall;
|
|
||||||
external kernel name 'FreeLibrary';
|
|
||||||
|
|
||||||
function GetModuleFileName(Module: Integer; Filename: PChar; Size: Integer): Integer; stdcall;
|
|
||||||
external kernel name 'GetModuleFileNameA';
|
|
||||||
|
|
||||||
function GetModuleHandle(ModuleName: PChar): Integer; stdcall;
|
|
||||||
external kernel name 'GetModuleHandleA';
|
|
||||||
|
|
||||||
//function LocalAlloc(flags, size: Integer): Pointer; stdcall;
|
|
||||||
// external kernel name 'LocalAlloc';
|
|
||||||
|
|
||||||
//function LocalFree(addr: Pointer): Pointer; stdcall;
|
|
||||||
// external kernel name 'LocalFree';
|
|
||||||
|
|
||||||
function TlsAlloc: Integer; stdcall;
|
|
||||||
external kernel name 'TlsAlloc';
|
|
||||||
|
|
||||||
function TlsFree(TlsIndex: Integer): Boolean; stdcall;
|
|
||||||
external kernel name 'TlsFree';
|
|
||||||
|
|
||||||
function TlsGetValue(TlsIndex: Integer): Pointer; stdcall;
|
|
||||||
external kernel name 'TlsGetValue';
|
|
||||||
|
|
||||||
function TlsSetValue(TlsIndex: Integer; TlsValue: Pointer): Boolean; stdcall;
|
|
||||||
external kernel name 'TlsSetValue';
|
|
||||||
|
|
||||||
function GetCommandLine: PChar; stdcall;
|
|
||||||
external kernel name 'GetCommandLineA';
|
|
||||||
|
|
||||||
const
|
|
||||||
tlsArray = $2C; { offset of tls array from FS: }
|
|
||||||
LMEM_ZEROINIT = $40;
|
|
||||||
|
|
||||||
function AllocTlsBuffer(Size: Integer): Pointer;
|
|
||||||
begin
|
|
||||||
//Result := LocalAlloc(LMEM_ZEROINIT, Size);
|
|
||||||
GetMem(Result, Size);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
tlsBuffer: Pointer; // RTM32 DOS support
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
|
|
||||||
{$IFDEF PIC}
|
|
||||||
function GetGOT: Pointer; export;
|
|
||||||
begin
|
|
||||||
asm
|
|
||||||
MOV Result,EBX
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
const
|
|
||||||
RTLD_LAZY = 1;
|
|
||||||
RTLD_NOW = 2;
|
|
||||||
RTLD_BINDING_MASK = RTLD_LAZY or RTLD_NOW;
|
|
||||||
RTLD_GLOBAL = $100;
|
|
||||||
RTLD_LOCAL = 0;
|
|
||||||
RTLD_NEXT = Pointer(-1);
|
|
||||||
RTLD_DEFAULT = nil;
|
|
||||||
|
|
||||||
type
|
|
||||||
TDLInfo = record
|
|
||||||
Filename: PChar;
|
|
||||||
BaseAddress: Pointer;
|
|
||||||
NearestSymbolName: PChar;
|
|
||||||
NearestSymbolAddr: Pointer;
|
|
||||||
end;
|
|
||||||
|
|
||||||
const
|
|
||||||
libcmodulename = 'libc.so.6';
|
|
||||||
libdlmodulename = 'libdl.so.2';
|
|
||||||
libpthreadmodulename = 'libpthread.so.0';
|
|
||||||
tlsSizeName = '@Sysinit@tlsSize';
|
|
||||||
|
|
||||||
function malloc(Size: LongWord): Pointer; cdecl;
|
|
||||||
external libcmodulename name 'malloc';
|
|
||||||
|
|
||||||
procedure free(P: Pointer); cdecl;
|
|
||||||
external libcmodulename name 'free';
|
|
||||||
|
|
||||||
function dlopen(Filename: PChar; Flag: Integer): LongWord; cdecl;
|
|
||||||
external libdlmodulename name 'dlopen';
|
|
||||||
|
|
||||||
function dlerror: PChar; cdecl;
|
|
||||||
external libdlmodulename name 'dlerror';
|
|
||||||
|
|
||||||
function dlsym(Handle: LongWord; Symbol: PChar): Pointer; cdecl;
|
|
||||||
external libdlmodulename name 'dlsym';
|
|
||||||
|
|
||||||
function dlclose(Handle: LongWord): Integer; cdecl;
|
|
||||||
external libdlmodulename name 'dlclose';
|
|
||||||
|
|
||||||
function FreeLibrary(Handle: LongWord): Integer; cdecl;
|
|
||||||
external libdlmodulename name 'dlclose';
|
|
||||||
|
|
||||||
function dladdr(Address: Pointer; var Info: TDLInfo): Integer; cdecl;
|
|
||||||
external libdlmodulename name 'dladdr';
|
|
||||||
|
|
||||||
type
|
|
||||||
TInitOnceProc = procedure; cdecl;
|
|
||||||
TKeyValueDestructor = procedure(ValueInKey: Pointer); cdecl;
|
|
||||||
|
|
||||||
function pthread_once(var InitOnceSemaphore: Integer; InitOnceProc: TInitOnceProc): Integer; cdecl;
|
|
||||||
external libpthreadmodulename name 'pthread_once';
|
|
||||||
|
|
||||||
function pthread_key_create(var Key: Integer; KeyValueDestructor: TKeyValueDestructor): Integer; cdecl;
|
|
||||||
external libpthreadmodulename name 'pthread_key_create';
|
|
||||||
|
|
||||||
function pthread_key_delete(Key: Integer): Integer; cdecl;
|
|
||||||
external libpthreadmodulename name 'pthread_key_delete';
|
|
||||||
|
|
||||||
function TlsGetValue(Key: Integer): Pointer; cdecl;
|
|
||||||
external libpthreadmodulename name 'pthread_getspecific';
|
|
||||||
|
|
||||||
function TlsSetValue(Key: Integer; Ptr: Pointer): Integer; cdecl;
|
|
||||||
external libpthreadmodulename name 'pthread_setspecific';
|
|
||||||
|
|
||||||
function AllocTlsBuffer(Size: Cardinal): Pointer;
|
|
||||||
begin
|
|
||||||
// The C++ rtl handles all tls in a C++ module
|
|
||||||
if ModuleIsCpp then
|
|
||||||
RunError(226);
|
|
||||||
|
|
||||||
Result := malloc(Size);
|
|
||||||
if Result <> nil then
|
|
||||||
FillChar(Result^, Size, 0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure FreeTLSBuffer(ValueInKey: Pointer); export cdecl;
|
|
||||||
begin
|
|
||||||
// The C++ rtl handles all tls in a C++ module
|
|
||||||
if ModuleIsCpp then
|
|
||||||
RunError(226);
|
|
||||||
free(ValueInKey);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure AllocTlsIndex; cdecl export;
|
|
||||||
begin
|
|
||||||
// guaranteed to reach here only once per process
|
|
||||||
// The C++ rtl handles all tls in a C++ module
|
|
||||||
if ModuleIsCpp then
|
|
||||||
RunError(226);
|
|
||||||
if pthread_key_create(TlsIndex, FreeTLSBuffer) <> 0 then
|
|
||||||
begin
|
|
||||||
TlsIndex := -1;
|
|
||||||
RunError(226);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetThisModuleHandle: LongWord;
|
|
||||||
var
|
|
||||||
Info: TDLInfo;
|
|
||||||
begin
|
|
||||||
if (dladdr(@GetThisModuleHandle, Info) = 0) or (Info.BaseAddress = ExeBaseAddress) then
|
|
||||||
Info.FileName := nil; // if we're not in a library, we must be main exe
|
|
||||||
Result := LongWord(dlopen(Info.Filename, RTLD_LAZY));
|
|
||||||
if Result <> 0 then
|
|
||||||
dlclose(Result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
InitOnceSemaphore: Integer;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
var
|
|
||||||
Module: TLibModule = (
|
|
||||||
Next: nil;
|
|
||||||
Instance: 0;
|
|
||||||
CodeInstance: 0;
|
|
||||||
DataInstance: 0;
|
|
||||||
ResInstance: 0;
|
|
||||||
Reserved: 0
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
; InstanceVar: nil;
|
|
||||||
GOT: 0;
|
|
||||||
CodeSegStart: 0;
|
|
||||||
CodeSegEnd: 0
|
|
||||||
);
|
|
||||||
{$ELSE}
|
|
||||||
);
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
function GetTlsSize: Integer;
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
asm
|
|
||||||
MOV EAX, offset TlsLast
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
begin
|
|
||||||
Result := Integer(@TlsLast);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
procedure InitThreadTLS;
|
|
||||||
var
|
|
||||||
p: Pointer;
|
|
||||||
tlsSize: Integer;
|
|
||||||
begin
|
|
||||||
tlsSize := GetTlsSize;
|
|
||||||
if tlsSize = 0 then Exit;
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
pthread_once(InitOnceSemaphore, AllocTlsIndex);
|
|
||||||
{$ENDIF}
|
|
||||||
if TlsIndex = -1 then RunError(226);
|
|
||||||
p := AllocTlsBuffer(tlsSize);
|
|
||||||
if p = nil then
|
|
||||||
RunError(226)
|
|
||||||
else
|
|
||||||
TlsSetValue(TlsIndex, p);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
procedure InitProcessTLS;
|
|
||||||
begin
|
|
||||||
if @TlsLast = nil then
|
|
||||||
Exit;
|
|
||||||
TlsIndex := TlsAlloc;
|
|
||||||
InitThreadTLS;
|
|
||||||
tlsBuffer := TlsGetValue(TlsIndex); // RTM32 DOS support
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ExitThreadTLS;
|
|
||||||
var
|
|
||||||
p: Pointer;
|
|
||||||
begin
|
|
||||||
if @TlsLast = nil then
|
|
||||||
Exit;
|
|
||||||
if TlsIndex <> -1 then begin
|
|
||||||
p := TlsGetValue(TlsIndex);
|
|
||||||
if p <> nil then begin
|
|
||||||
//LocalFree(p);
|
|
||||||
FreeMem(p);
|
|
||||||
TlsSetValue(TlsIndex, nil);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ExitProcessTLS;
|
|
||||||
begin
|
|
||||||
if @TlsLast = nil then
|
|
||||||
Exit;
|
|
||||||
ExitThreadTLS;
|
|
||||||
if TlsIndex <> -1 then
|
|
||||||
TlsFree(TlsIndex);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
const
|
|
||||||
DLL_PROCESS_DETACH = 0;
|
|
||||||
DLL_PROCESS_ATTACH = 1;
|
|
||||||
DLL_THREAD_ATTACH = 2;
|
|
||||||
DLL_THREAD_DETACH = 3;
|
|
||||||
|
|
||||||
function _GetTls: Pointer;
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
begin
|
|
||||||
Result := TlsGetValue(TlsIndex);
|
|
||||||
if Result = nil then
|
|
||||||
begin
|
|
||||||
InitThreadTLS;
|
|
||||||
Result := TlsGetValue(TlsIndex);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
asm
|
|
||||||
MOV CL,ModuleIsLib
|
|
||||||
MOV EAX,TlsIndex
|
|
||||||
TEST CL,CL
|
|
||||||
JNE @@isDll
|
|
||||||
MOV EDX,FS:tlsArray
|
|
||||||
MOV EAX,[EDX+EAX*4]
|
|
||||||
RET
|
|
||||||
|
|
||||||
@@initTls:
|
|
||||||
CALL InitThreadTLS
|
|
||||||
MOV EAX,TlsIndex
|
|
||||||
PUSH EAX
|
|
||||||
CALL TlsGetValue
|
|
||||||
TEST EAX,EAX
|
|
||||||
JE @@RTM32
|
|
||||||
RET
|
|
||||||
|
|
||||||
@@RTM32:
|
|
||||||
MOV EAX, tlsBuffer
|
|
||||||
RET
|
|
||||||
|
|
||||||
@@isDll:
|
|
||||||
PUSH EAX
|
|
||||||
CALL TlsGetValue
|
|
||||||
TEST EAX,EAX
|
|
||||||
JE @@initTls
|
|
||||||
end;
|
|
||||||
|
|
||||||
const
|
|
||||||
TlsProc: array [DLL_PROCESS_DETACH..DLL_THREAD_DETACH] of procedure =
|
|
||||||
(ExitProcessTLS,InitProcessTLS,InitThreadTLS,ExitThreadTLS);
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
const
|
|
||||||
UNWINDFI_TOPOFSTACK = $BE00EF00;
|
|
||||||
|
|
||||||
{
|
|
||||||
The linker sets the value of TextStartAdj to be the delta between GetTextStart
|
|
||||||
and the start of the text segment. This allows us to get the pointer to the
|
|
||||||
start of the text segment in a position independent fashion.
|
|
||||||
}
|
|
||||||
function GetTextStart : LongInt;
|
|
||||||
asm
|
|
||||||
CALL @@label1
|
|
||||||
@@label1:
|
|
||||||
POP EAX
|
|
||||||
SUB EAX, 5 + offset TextStartAdj
|
|
||||||
end;
|
|
||||||
|
|
||||||
{
|
|
||||||
The linker sets the value of CodeSegSize to the length of the text segment,
|
|
||||||
excluding the PC map. This allows us to get the pointer to the exception
|
|
||||||
information that we need at runtime, also in a position independent fashion.
|
|
||||||
}
|
|
||||||
function GetTextEnd : LongInt;
|
|
||||||
asm
|
|
||||||
CALL GetTextStart
|
|
||||||
ADD EAX, offset CodeSegSize
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
procedure InitializeModule;
|
|
||||||
begin
|
|
||||||
RegisterModule(@Module);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure UninitializeModule;
|
|
||||||
begin
|
|
||||||
UnregisterModule(@Module);
|
|
||||||
if (Module.ResInstance <> Module.Instance) and (Module.ResInstance <> 0) then
|
|
||||||
FreeLibrary(Module.ResInstance);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl;
|
|
||||||
begin
|
|
||||||
ModuleIsLib := isDLL;
|
|
||||||
ModuleIsPackage := isPkg;
|
|
||||||
IsLibrary := isDLL and not isPkg;
|
|
||||||
HInstance := hInst;
|
|
||||||
Module.Instance := hInst;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
ModuleIsCpp := True;
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
if ModuleIsLib then
|
|
||||||
Module.InstanceVar := @HInstance;
|
|
||||||
{$IFDEF PIC}
|
|
||||||
Module.GOT := LongWord(GetGot);
|
|
||||||
{$ENDIF}
|
|
||||||
{ Module.CodeSegStart, Module.CodeSegEnd not used: the C++
|
|
||||||
rtl will feed the unwinder. }
|
|
||||||
{$ENDIF}
|
|
||||||
InitializeModule;
|
|
||||||
if not ModuleIsLib then
|
|
||||||
begin
|
|
||||||
Module.CodeInstance := FindHInstance(@VclInit);
|
|
||||||
Module.DataInstance := FindHInstance(@DataMark);
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
{X CmdLine := GetCommandLine; - converted to a function }
|
|
||||||
IsConsole := not isGui;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure VclExit; cdecl;
|
|
||||||
var
|
|
||||||
P: procedure;
|
|
||||||
begin
|
|
||||||
if not ModuleIsLib then
|
|
||||||
while ExitProc <> nil do
|
|
||||||
begin
|
|
||||||
@P := ExitProc;
|
|
||||||
ExitProc := nil;
|
|
||||||
P;
|
|
||||||
end;
|
|
||||||
UnInitializeModule;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
procedure RegisterPCMap;
|
|
||||||
begin
|
|
||||||
SysRegisterIPLookup(GetTextStart,
|
|
||||||
GetTextEnd,
|
|
||||||
Pointer(GetTextEnd),
|
|
||||||
LongWord(@_Global_Offset_Table_));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure UnregisterPCMap;
|
|
||||||
begin
|
|
||||||
SysUnregisterIPLookup(GetTextStart);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
function _InitPkg(Hinst: Longint; Reason: Integer; Resvd: Pointer): Longbool; stdcall;
|
|
||||||
begin
|
|
||||||
ModuleIsLib := True;
|
|
||||||
ModuleIsPackage := True;
|
|
||||||
Module.Instance := Hinst;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
HInstance := Hinst;
|
|
||||||
if @TlsLast <> nil then
|
|
||||||
TlsProc[Reason];
|
|
||||||
if Reason = DLL_PROCESS_ATTACH then
|
|
||||||
InitializeModule
|
|
||||||
else if Reason = DLL_PROCESS_DETACH then
|
|
||||||
UninitializeModule;
|
|
||||||
_InitPkg := True;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
function _InitPkg: LongBool;
|
|
||||||
begin
|
|
||||||
{$IFDEF DEBUG_STARTUP}
|
|
||||||
asm
|
|
||||||
INT 3
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
RegisterPCMap;
|
|
||||||
{$ENDIF}
|
|
||||||
TlsIndex := -1;
|
|
||||||
ModuleIsLib := True;
|
|
||||||
ModuleIsPackage := True;
|
|
||||||
Module.Instance := GetThisModuleHandle;
|
|
||||||
Module.InstanceVar := @HInstance;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
Module.GOT := LongWord(@_Global_Offset_Table_);
|
|
||||||
Module.CodeSegStart := GetTextStart;
|
|
||||||
Module.CodeSegEnd := GetTextEnd;
|
|
||||||
HInstance := Module.Instance;
|
|
||||||
InitializeModule;
|
|
||||||
_InitPkg := True;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
procedure _PackageLoad(const Table: PackageInfo);
|
|
||||||
begin
|
|
||||||
System._PackageLoad(Table, @Module);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure _PackageUnload(const Table: PackageInfo);
|
|
||||||
begin
|
|
||||||
System._PackageUnload(Table, @Module);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
procedure _InitLib;
|
|
||||||
asm
|
|
||||||
{ -> EAX Inittable }
|
|
||||||
{ [EBP+8] Hinst }
|
|
||||||
{ [EBP+12] Reason }
|
|
||||||
{ [EBP+16] Resvd }
|
|
||||||
|
|
||||||
MOV EDX,offset Module
|
|
||||||
CMP dword ptr [EBP+12],DLL_PROCESS_ATTACH
|
|
||||||
JNE @@notInit
|
|
||||||
|
|
||||||
PUSH EAX
|
|
||||||
PUSH EDX
|
|
||||||
MOV ModuleIsLib,1
|
|
||||||
MOV ECX,[EBP+8]
|
|
||||||
MOV HInstance,ECX
|
|
||||||
MOV [EDX].TLibModule.Instance,ECX
|
|
||||||
MOV [EDX].TLibModule.CodeInstance,0
|
|
||||||
MOV [EDX].TLibModule.DataInstance,0
|
|
||||||
CALL InitializeModule
|
|
||||||
POP EDX
|
|
||||||
POP EAX
|
|
||||||
|
|
||||||
@@notInit:
|
|
||||||
PUSH DllProc
|
|
||||||
MOV ECX,offset TlsProc
|
|
||||||
CALL _StartLib
|
|
||||||
end;
|
|
||||||
|
|
||||||
// ExitLib is the same as InitLib in Windows.
|
|
||||||
|
|
||||||
{$ENDIF MSWINDOWS}
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
procedure _InitLib(Context: PInitContext);
|
|
||||||
begin
|
|
||||||
{$IFDEF DEBUG_STARTUP}
|
|
||||||
asm
|
|
||||||
INT 3
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
asm
|
|
||||||
PUSH UNWINDFI_TOPOFSTACK
|
|
||||||
end;
|
|
||||||
Context.DLLInitState := DLL_PROCESS_ATTACH;
|
|
||||||
TlsIndex := -1;
|
|
||||||
ModuleIsLib := True;
|
|
||||||
HInstance := GetThisModuleHandle;
|
|
||||||
Module.Instance := HInstance;
|
|
||||||
Module.InstanceVar := @HInstance;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
Module.GOT := LongWord(@_Global_Offset_Table_);
|
|
||||||
Module.CodeSegStart := GetTextStart;
|
|
||||||
Module.CodeSegEnd := GetTextEnd;
|
|
||||||
InitializeModule;
|
|
||||||
RegisterPCMap;
|
|
||||||
_StartLib(Context, @Module, DLLProcEx);
|
|
||||||
asm
|
|
||||||
ADD ESP, 4
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// InnerExitLib provides GOT fixup and global var addressing
|
|
||||||
function InnerExitLib(Context: PInitContext): Integer;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
if ModuleIsPackage then
|
|
||||||
begin
|
|
||||||
UninitializeModule;
|
|
||||||
UnregisterPCMap;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
_StartLib(Context, @Module, DLLProcEx);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function _ExitLib: Integer; cdecl;
|
|
||||||
asm
|
|
||||||
{$IFDEF DEBUG_STARTUP}
|
|
||||||
INT 3
|
|
||||||
{$ENDIF}
|
|
||||||
PUSH EBP
|
|
||||||
MOV EBP,ESP
|
|
||||||
PUSH UNWINDFI_TOPOFSTACK
|
|
||||||
XOR EAX,EAX
|
|
||||||
PUSH DLL_PROCESS_DETACH // InitContext.DLLInitState
|
|
||||||
PUSH EDI
|
|
||||||
PUSH ESI
|
|
||||||
PUSH EBX
|
|
||||||
PUSH EBP
|
|
||||||
PUSH EAX // InitContext.Module
|
|
||||||
PUSH EAX // InitContext.InitCount
|
|
||||||
PUSH EAX // InitContext.InitTable (filled in later)
|
|
||||||
PUSH EAX // InitContext.OuterContext
|
|
||||||
MOV EAX,ESP
|
|
||||||
CALL InnerExitLib;
|
|
||||||
ADD ESP, 16
|
|
||||||
POP EBP
|
|
||||||
POP EBX
|
|
||||||
POP ESI
|
|
||||||
POP EDI
|
|
||||||
MOV ESP,EBP
|
|
||||||
POP EBP
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure _GetCallerEIP;
|
|
||||||
asm
|
|
||||||
MOV EBX, [ESP]
|
|
||||||
end;
|
|
||||||
{$ENDIF LINUX}
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
procedure _InitExe(InitTable: Pointer);
|
|
||||||
begin
|
|
||||||
TlsIndex := 0;
|
|
||||||
HInstance := GetModuleHandle(nil);
|
|
||||||
Module.Instance := HInstance;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
InitializeModule;
|
|
||||||
_StartExe(InitTable, @Module);
|
|
||||||
end;
|
|
||||||
{$ENDIF MSWINDOWS}
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
procedure InitVmtImports;
|
|
||||||
var
|
|
||||||
P: ^Integer;
|
|
||||||
begin
|
|
||||||
P := @TypeImportsTable;
|
|
||||||
if P = nil then Exit;
|
|
||||||
while P^ <> 0 do
|
|
||||||
begin
|
|
||||||
P^ := Integer(dlsym(0, PChar(P^)));
|
|
||||||
Inc(P);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure _InitExe(InitTable: Pointer; Argc: Integer; Argp: Pointer); export;
|
|
||||||
begin
|
|
||||||
{$IFDEF DEBUG_STARTUP}
|
|
||||||
asm
|
|
||||||
INT 3
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
HInstance := GetThisModuleHandle;
|
|
||||||
Module.Instance := HInstance;
|
|
||||||
Module.InstanceVar := @HInstance;
|
|
||||||
Module.CodeInstance := 0;
|
|
||||||
Module.DataInstance := 0;
|
|
||||||
InitializeModule;
|
|
||||||
InitThreadTLS;
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
RegisterPCMap();
|
|
||||||
{$ENDIF}
|
|
||||||
InitVmtImports;
|
|
||||||
_StartExe(InitTable, @Module, Argc, Argp);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
var
|
|
||||||
InitAddr: Pointer;
|
|
||||||
|
|
||||||
function _main(argc: Integer; argv: Pointer; envp: Pointer): Integer; export cdecl;
|
|
||||||
type
|
|
||||||
TInitFunction = function (argc: Integer; argv, envp: Pointer): Integer; cdecl;
|
|
||||||
TExternalInit = function (argc: Integer; argv, envp: Pointer; InitExe: TInitFunction): Integer; cdecl;
|
|
||||||
var
|
|
||||||
ExternalInit: TExternalInit;
|
|
||||||
InitFunc: TInitFunction;
|
|
||||||
begin
|
|
||||||
@ExternalInit := dlsym(GetThisModuleHandle, 'ExternalInit');
|
|
||||||
@InitFunc := InitAddr;
|
|
||||||
System.envp := envp;
|
|
||||||
if @ExternalInit <> nil then
|
|
||||||
ExternalInit(argc, argv, envp, InitFunc);
|
|
||||||
Result := InitFunc(argc, argv, envp);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function __libc_start_main (Main: Pointer; Argc: Integer; Argv: Pointer;
|
|
||||||
Init, Fini, rtld_Fini: Pointer; StackEnd: Pointer)
|
|
||||||
: Integer;
|
|
||||||
cdecl;
|
|
||||||
external libcmodulename name '__libc_start_main';
|
|
||||||
|
|
||||||
{ Program entry point }
|
|
||||||
procedure _start;
|
|
||||||
asm
|
|
||||||
{$IFDEF DEBUG_STARTUP}
|
|
||||||
INT 3
|
|
||||||
{$ENDIF}
|
|
||||||
{ Mark outermost frame, suggested by ELF i386 ABI. }
|
|
||||||
xor ebp,ebp
|
|
||||||
|
|
||||||
{ Get data passed on stack }
|
|
||||||
pop eax { argc }
|
|
||||||
mov ecx,esp { argv }
|
|
||||||
|
|
||||||
{ Align stack }
|
|
||||||
and esp,0fffffff8h
|
|
||||||
{$IFDEF PC_MAPPED_EXCEPTIONS}
|
|
||||||
{ Mark the top of the stack with a signature }
|
|
||||||
push UNWINDFI_TOPOFSTACK
|
|
||||||
{$ENDIF}
|
|
||||||
push ebp { padding }
|
|
||||||
push esp { crt1.o does this, don't know why }
|
|
||||||
push edx { function to be registered with
|
|
||||||
atexit(), passed by loader }
|
|
||||||
push offset @@ret { _fini dummy }
|
|
||||||
push offset @@ret { _init dummy }
|
|
||||||
push ecx { argv }
|
|
||||||
push eax { argc }
|
|
||||||
{ We need a symbol for the Pascal entry point (main unit's
|
|
||||||
body). An external symbol `main' fixed up by the linker
|
|
||||||
would be fine. Alas, external declarations can't do that;
|
|
||||||
they must be resolved either in the same file with a $L
|
|
||||||
directive, or in a shared object. Hack: use a bogus,
|
|
||||||
distinctive symbol to mark the fixup, find and patch it
|
|
||||||
in the linker. }
|
|
||||||
{$IFDEF PIC}
|
|
||||||
call GetGOT
|
|
||||||
mov ebx, eax
|
|
||||||
add [esp+12],ebx
|
|
||||||
add [esp+8],ebx
|
|
||||||
// Linker will replace _GLOBAL_OFFSET_TABLE_ address with main program block
|
|
||||||
mov eax, offset _GLOBAL_OFFSET_TABLE_
|
|
||||||
add eax, ebx
|
|
||||||
mov [ebx].InitAddr, eax
|
|
||||||
mov eax, offset _main
|
|
||||||
add eax, ebx
|
|
||||||
push eax
|
|
||||||
{$ELSE}
|
|
||||||
// Linker will replace _GLOBAL_OFFSET_TABLE_ address with main program block
|
|
||||||
push offset _GLOBAL_OFFSET_TABLE_
|
|
||||||
pop InitAddr
|
|
||||||
push offset _main
|
|
||||||
{$ENDIF}
|
|
||||||
call __libc_start_main
|
|
||||||
hlt { they never come back }
|
|
||||||
|
|
||||||
@@ret:
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF LINUX}
|
|
||||||
{ Procedure body not generated on Windows currently }
|
|
||||||
procedure OpenEdition;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure GPLInfected;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$IFDEF TRIAL_EDITION}
|
|
||||||
procedure Evaluation;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
procedure Copyright;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
const
|
|
||||||
sOpenEdition = 'This application was built with Borland Kylix Open Edition(tm).'; // do not localize
|
|
||||||
sGPLMessage = 'This module must be distributed under the terms of the GNU General ' // do not localize
|
|
||||||
+ 'Public License (GPL), version 2. A copy of this license can be found at:' // do not localize
|
|
||||||
+ 'http://www.borland.com/kylix/gpl.html.'; // do not localize
|
|
||||||
|
|
||||||
exports
|
|
||||||
{$IF Declared(GPL)}
|
|
||||||
OpenEdition name sOpenEdition,
|
|
||||||
GPLInfected name sGPLMessage,
|
|
||||||
{$IFEND}
|
|
||||||
{$IFDEF TRIAL_EDITION}
|
|
||||||
Evaluation name 'This module was compiled with an evaluation version of Borland Delphi', // do not localize
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
Copyright name 'Portions Copyright (c) 1983,2002 Borland Software Corporation'; // do not localize
|
|
||||||
|
|
||||||
|
|
||||||
{$IF Declared(GPL)}
|
|
||||||
initialization
|
|
||||||
if IsConsole and not ModuleIsLib then
|
|
||||||
begin
|
|
||||||
TTextRec(Output).Mode := fmClosed;
|
|
||||||
writeln(sGPLMessage);
|
|
||||||
end;
|
|
||||||
{$IFEND}
|
|
||||||
{$ENDIF}
|
|
||||||
end.
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user