1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
{******************************************************************}
{ }
{ Project JEDI }
{ OS independent Dynamic Loading Helpers }
{ }
{ The initial developer of the this code is }
{ Robert Marquardt <robert_marquardt@gmx.de) }
{ }
{ Copyright (C) 2000, 2001 Robert Marquardt. }
{ }
{ Obtained through: }
{ Joint Endeavour of Delphi Innovators (Project JEDI) }
{ }
{ You may retrieve the latest version of this file at the Project }
{ JEDI home page, located at http://delphi-jedi.org }
{ }
{ The contents of this file are used with permission, subject to }
{ the Mozilla Public License Version 1.1 (the "License"); you may }
{ not use this file except in compliance with the License. You may }
{ obtain a copy of the License at }
{ http://www.mozilla.org/NPL/NPL-1_1Final.html }
{ }
{ Software distributed under the License is distributed on an }
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
{ implied. See the License for the specific language governing }
{ rights and limitations under the License. }
{ }
{******************************************************************}
unit ModuleLoader;
interface
{$WEAKPACKAGEUNIT ON}
uses
Libc;
type
// Handle to a loaded .so
TModuleHandle = Pointer;
const
// Value designating an unassigned TModuleHandle od a failed loading
INVALID_MODULEHANDLE_VALUE = TModuleHandle(nil);
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
procedure UnloadModule(var Module: TModuleHandle);
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
implementation
// load the .so file FileName
// the rules for FileName are those of dlopen()
// Returns: True = success, False = failure to load
// Assigns: the handle of the loaded .so to Module
// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
// on entry the function will do nothing but returning success.
function LoadModule(var Module: TModuleHandle; FileName: string): Boolean;
begin
Module := dlopen(PChar(FileName), RTLD_LAZY);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// load the .so file FileName
// dlopen() with flags is used to get better control of the loading
// for the allowed values for flags see "man dlopen".
function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean;
begin
Module := dlopen(PChar(FileName), Flags);
Result := Module <> INVALID_MODULEHANDLE_VALUE;
end;
// unload a .so loaded with LoadModule or LoadModuleEx
// The procedure will not try to unload a handle with
// value INVALID_MODULEHANDLE_VALUE and assigns this value
// to Module after unload.
procedure UnloadModule(var Module: TModuleHandle);
begin
if Module <> INVALID_MODULEHANDLE_VALUE then
dlclose(Module);
Module := INVALID_MODULEHANDLE_VALUE;
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available
function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
end;
// returns the pointer to the symbol named SymbolName
// if it is exported from the .so Module
// nil is returned if the symbol is not available.
// as an extra the boolean variable Accu is updated
// by anding in the success of the function.
// This is very handy for rendering a global result
// when accessing a long list of symbols.
function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer;
begin
Result := nil;
if Module <> INVALID_MODULEHANDLE_VALUE then
Result := dlsym(Module, PChar(SymbolName));
Accu := Accu and (Result <> nil);
end;
// get the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data from the .so.
// Beware! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to read the correct amount of data.
function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Sym^, Buffer, Size);
end;
// set the value of variables exported from a .so Module
// Delphi cannot access variables in a .so directly, so
// this function allows to copy the data to the .so!
// BEWARE! You are accessing the .so memory image directly.
// Be sure to access a variable not a function and be sure
// to write the correct amount of data.
// The changes are not persistent. They get lost when the
// .so is unloaded.
function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean;
var
Sym: Pointer;
begin
Result := True;
Sym := GetModuleSymbolEx(Module, SymbolName, Result);
if Result then
Move(Buffer, Sym^, Size);
end;
end.
|