-
Notifications
You must be signed in to change notification settings - Fork 222
/
Copy pathosloader.c
359 lines (300 loc) · 11.1 KB
/
osloader.c
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/*
* Copyright (c) 2018, United States government as represented by the
* administrator of the National Aeronautics Space Administration.
* All rights reserved. This software was created at NASA Glenn
* Research Center pursuant to government contracts.
*
* This is governed by the NASA Open Source Agreement and may be used,
* distributed and modified only according to the terms of that agreement.
*/
/**
* \file osloader.c
* \author [email protected]
*
* Purpose: This file contains the module loader and symbol lookup functions for the OSAL.
* RTEMS uses the POSIX-style "dl" implementation (even if the rest of the POSIX API
* is disabled).
*/
/****************************************************************************************
INCLUDE FILES
***************************************************************************************/
#define _USING_RTEMS_INCLUDES_
#include "os-rtems.h"
#include <dlfcn.h>
#include <rtems/rtl/rtl.h>
#include <rtems/rtl/rtl-unresolved.h>
/****************************************************************************************
GLOBAL DATA
***************************************************************************************/
/*
* A local lookup table for posix-specific information.
* This is not directly visible to the outside world.
*/
typedef struct
{
/* cppcheck-suppress unusedStructMember */
void *dl_handle;
} OS_impl_module_internal_record_t;
/*
* The storage table is only instantiated when OS_MAX_MODULES is nonzero.
* It is allowed to be zero to save memory in statically linked apps.
* However even in that case it is still relevant to include the
* OS_SymbolLookup_Impl() function for symbol lookups.
*
* If neither loading nor symbol lookups are desired then this file
* shouldn't be used at all -- a no-op version should be used instead.
*/
#if (OS_MAX_MODULES > 0)
OS_impl_module_internal_record_t OS_impl_module_table[OS_MAX_MODULES];
#endif
/****************************************************************************************
INITIALIZATION FUNCTION
***************************************************************************************/
/*----------------------------------------------------------------
*
* Function: OS_Rtems_ModuleAPI_Impl_Init
*
* Purpose: Local helper routine, not part of OSAL API.
*
*-----------------------------------------------------------------*/
int32 OS_Rtems_ModuleAPI_Impl_Init(void)
{
#if (OS_MAX_MODULES > 0)
memset(OS_impl_module_table, 0, sizeof(OS_impl_module_table));
#endif
return(OS_SUCCESS);
} /* end OS_Rtems_ModuleAPI_Impl_Init */
/****************************************************************************************
Symbol table API
***************************************************************************************/
/*----------------------------------------------------------------
*
* Function: OS_SymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_SymbolLookup_Impl( cpuaddr *SymbolAddress, const char *SymbolName )
{
int32 status;
const char *dlError;
void *Function;
/*
* call dlerror() to clear any prior error that might have occured.
*/
dlerror();
Function = dlsym(RTLD_DEFAULT, SymbolName);
dlError = dlerror();
/*
* For the POSIX DL implementation, if the symbol does not exist
* then dlerror() is supposed to return non-null. This is intended
* to differentiate between valid symbols which are actually 0/NULL
* and invalid symbols that do not exist.
*
* RTEMS does _not_ seem to implement this detail, and dlerror()
* still returns NULL after looking up an invalid symbol name.
*
* In practice, all valid symbols should be non-NULL anyway,
* so we check both here.
*/
if( dlError == NULL && Function != NULL )
{
/* considered successful if no error is present -
* note the address itself is allowed to be NULL */
*SymbolAddress = (cpuaddr)Function;
status = OS_SUCCESS;
}
else
{
*SymbolAddress = 0;
status = OS_ERROR;
}
return status;
} /* end OS_SymbolLookup_Impl */
/*----------------------------------------------------------------
*
* Function: OS_SymbolTableDump_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_SymbolTableDump_Impl ( const char *filename, uint32 SizeLimit )
{
return(OS_ERR_NOT_IMPLEMENTED);
} /* end OS_SymbolTableDump_Impl */
/****************************************************************************************
Module Loader API
***************************************************************************************/
/*
* NOTE: The module loading functions are only compiled of OS_MAX_MODULES is >0
* Otherwise stubs will be compiled in place of these (see below)
*/
#if (OS_MAX_MODULES > 0) && defined(OS_INCLUDE_MODULE_LOADER)
/****************************************************************************************
HELPER ROUTINES
***************************************************************************************/
/*----------------------------------------------------------------
*
* Function: OS_rtems_rtl_check_unresolved
*
* Purpose: Local helper routine, not part of OSAL API.
* This callback checks symbols in the RTL unresolved record list
* NOTE: Right now this considers any unresolved items to be a failure.
* This could be fine-tuned later.
*
*-----------------------------------------------------------------*/
static bool OS_rtems_rtl_check_unresolved (rtems_rtl_unresolv_rec_t* rec,
void* data)
{
int32 *status = data;
switch(rec->type)
{
case rtems_rtl_unresolved_name:
OS_DEBUG("unresolved name: %s\n", rec->rec.name.name);
*status = OS_ERROR;
break;
case rtems_rtl_unresolved_reloc:
*status = OS_ERROR;
break;
default:
break;
}
return false;
} /* end OS_rtems_rtl_check_unresolved */
/*----------------------------------------------------------------
*
* Function: OS_ModuleLoad_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleLoad_Impl ( uint32 module_id, const char *translated_path )
{
int32 status = OS_ERROR;
int unresolved;
void *dl_handle;
dlerror();
dl_handle = dlopen(translated_path, RTLD_NOW | RTLD_GLOBAL);
if (dl_handle == NULL)
{
OS_DEBUG("Error loading shared library: %s\n", dlerror());
status = OS_ERROR;
}
else if (dlinfo (dl_handle, RTLD_DI_UNRESOLVED, &unresolved) < 0)
{
/* should never happen */
OS_DEBUG("dlinfo error checking unresolved status\n");
status = OS_ERROR;
}
else if (unresolved)
{
/*
* Note that RTEMS is a little different than traditional POSIX
* in that even with RTLD_NOW specified, dlopen() will still return
* success if there are unresolved symbols. RTEMS has implemented
* it this way to allow cross/circular dependencies.
*
* However, OSAL applications are not anticipated to have circular
* dependencies such as this. So this explicitly checks if unresolved
* symbols are present after loading, and if so, do additional checks.
*
* It is possible that not every unresolved situation indicates failure.
* The "check_unresolved" helper should verify if the condition
* is acceptable. If not acceptable, it sets the status back to an error.
*/
OS_DEBUG("module has has unresolved externals\n");
status = OS_SUCCESS; /* note - not final, probably overridden */
rtems_rtl_unresolved_interate (OS_rtems_rtl_check_unresolved, &status);
}
else
{
status = OS_SUCCESS;
}
if (status == OS_SUCCESS)
{
/* success: save for future use */
OS_impl_module_table[module_id].dl_handle = dl_handle;
}
else if (dl_handle != NULL)
{
/*
* When returning non-success based on one of the
* subsequent verifications, also dlclose() the handle
* to avoid leaking resources.
*/
dlclose(dl_handle);
dl_handle = NULL;
}
return status;
} /* end OS_ModuleLoad_Impl */
/*----------------------------------------------------------------
*
* Function: OS_ModuleUnload_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleUnload_Impl ( uint32 module_id )
{
int32 status = OS_ERROR;
/*
** Attempt to close/unload the module
*/
dlerror();
if (dlclose(OS_impl_module_table[module_id].dl_handle) == 0)
{
OS_impl_module_table[module_id].dl_handle = NULL;
status = OS_SUCCESS;
}
else
{
OS_DEBUG("Error unloading shared library: %s\n", dlerror());
}
return status;
} /* end OS_ModuleUnload_Impl */
#else
/*----------------------------------------------------------------
*
* Function: OS_ModuleLoad_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleLoad_Impl ( uint32 module_id, const char *translated_path )
{
return OS_SUCCESS;
} /* end OS_ModuleLoad_Impl */
/*----------------------------------------------------------------
*
* Function: OS_ModuleUnload_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleUnload_Impl ( uint32 module_id )
{
return OS_SUCCESS;
} /* end OS_ModuleUnload_Impl */
#endif
/*----------------------------------------------------------------
*
* Function: OS_ModuleGetInfo_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype in os-impl.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleGetInfo_Impl ( uint32 module_id, OS_module_prop_t *module_prop )
{
/*
** RTEMS does not specify a way to get these values
** Everything left at zero
*/
return(OS_SUCCESS);
} /* end OS_ModuleGetInfo_Impl */