9d74206a7a4ff8493dc635b970588f8cd8e167f1
1 /*
2 * dload_api.h
3 *
4 * Dynamic Loader API Specification
5 * --------------------------------
6 *
7 * Client-side of API is assumed to be platform dependent, but object file
8 * format independent.
9 *
10 * Core Loader side of API is assumed to be platform independent, but
11 * object file format dependent and target dependent.
12 *
13 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
14 *
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 *
23 * Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the
26 * distribution.
27 *
28 * Neither the name of Texas Instruments Incorporated nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
42 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 *
44 */
46 #ifndef DLOAD_API_H
47 #define DLOAD_API_H
49 #include <inttypes.h>
50 #include <stdio.h>
51 #include "util.h"
53 /*****************************************************************************/
54 /* Specification of Loader File Descriptor. If client side of the loader */
55 /* supports virtual memory, this may need to be updated to facilitate the */
56 /* use of mmap(). */
57 /*****************************************************************************/
58 /* typedef FILE LOADER_FILE_DESC; - Moved to ewrap.h for ibl */
60 static const int LOADER_SEEK_SET = SEEK_SET;
61 static const int LOADER_SEEK_CUR = SEEK_CUR;
62 static const int LOADER_SEEK_END = SEEK_END;
64 /*****************************************************************************/
65 /* TARGET_ADDRESS - type suitable for storing target memory address values. */
66 /*****************************************************************************/
67 typedef void* TARGET_ADDRESS;
69 /*****************************************************************************/
70 /* Core Loader Provided API Functions (Core Loader Entry Points) */
71 /*****************************************************************************/
73 /*---------------------------------------------------------------------------*/
74 /* DLOAD_version() */
75 /* */
76 /* Return a string constant representation for the version ID of the */
77 /* dynamic loader's core loader source code. */
78 /* */
79 /*---------------------------------------------------------------------------*/
80 #include "version.h"
81 #define DLOAD_version() VERSION
83 /*---------------------------------------------------------------------------*/
84 /* DLOAD_initialize() */
85 /* */
86 /* Construct and initialize data structures internal to the dynamic */
87 /* loader core. */
88 /* */
89 /*---------------------------------------------------------------------------*/
90 void DLOAD_initialize(void);
92 /*---------------------------------------------------------------------------*/
93 /* DLOAD_load_symbols() */
94 /* */
95 /* Load externally visible symbols from the specified file so that they */
96 /* can be linked against when another object file is subsequntly loaded. */
97 /* External symbols will be made available for global symbol linkage. */
98 /* */
99 /*---------------------------------------------------------------------------*/
100 BOOL DLOAD_load_symbols(LOADER_FILE_DESC* fp);
102 /*---------------------------------------------------------------------------*/
103 /* DLOAD_load() */
104 /* */
105 /* Dynamically load the specified file and return a file handle for the */
106 /* loaded file. If the load fails, this function will return a value */
107 /* zero (0). */
108 /* */
109 /* The core loader must have read access to the file pointed by fp. */
110 /* */
111 /*---------------------------------------------------------------------------*/
112 int DLOAD_load(LOADER_FILE_DESC* fp, int argc, char** argv, uint32_t *entry);
114 /*---------------------------------------------------------------------------*/
115 /* DLOAD_unload() */
116 /* */
117 /* Given a file handle ID, unload all object segments associated with */
118 /* the identified file and any of its dependents that are not still in */
119 /* use. */
120 /* */
121 /*---------------------------------------------------------------------------*/
122 BOOL DLOAD_unload(uint32_t pseudopid);
124 /*---------------------------------------------------------------------------*/
125 /* DLOAD_get_entry_names() */
126 /* */
127 /* Given a file handle, build a list of entry point names that are */
128 /* available in the specified file. This can be used when querying */
129 /* the list of global functions available in a shared library. */
130 /* */
131 /*---------------------------------------------------------------------------*/
132 BOOL DLOAD_get_entry_names(uint32_t file_handle, int32_t* entry_pt_cnt,
133 char*** entry_pt_names);
135 /*---------------------------------------------------------------------------*/
136 /* DLOAD_query_symbol() */
137 /* */
138 /* Query the value of a symbol that is defined by an object file that */
139 /* has previously been loaded. Boolean return value will be false if */
140 /* the symbol is not found. */
141 /* */
142 /*---------------------------------------------------------------------------*/
143 BOOL DLOAD_query_symbol(uint32_t file_handle, const char *sym_name,
144 TARGET_ADDRESS *sym_val);
146 /*---------------------------------------------------------------------------*/
147 /* DLOAD_get_entry_point() */
148 /* */
149 /* Given a file handle, return the entry point target address associated */
150 /* with that object file. The entry point address value is written to */
151 /* *sym_val. The return value of the function indicates whether the */
152 /* file with the specified handle was found or not. */
153 /* */
154 /*---------------------------------------------------------------------------*/
155 BOOL DLOAD_get_entry_point(uint32_t file_handle, TARGET_ADDRESS *sym_val);
157 /*****************************************************************************/
158 /* Client Provided API Functions */
159 /*****************************************************************************/
161 /*---------------------------------------------------------------------------*/
162 /* File I/O */
163 /* */
164 /* The client side of the dynamic loader must provide basic file I/O */
165 /* capabilities so that the core loader has random access into any */
166 /* object file that it is asked to load. */
167 /* */
168 /* The client side of the dynamic loader must provide a definition of */
169 /* the LOADER_FILE_DESC in dload_filedefs.h. This allows the core loader */
170 /* to be independent of how the client accesses raw data in an object */
171 /* file. */
172 /* */
173 /*---------------------------------------------------------------------------*/
175 /*---------------------------------------------------------------------------*/
176 /* DLIF_fseek() */
177 /* */
178 /* Seek to a position in a file (accessed via 'stream') based on the */
179 /* values for offset and origin. */
180 /* */
181 /*---------------------------------------------------------------------------*/
182 int DLIF_fseek(LOADER_FILE_DESC *stream, int32_t offset, int origin);
184 /*---------------------------------------------------------------------------*/
185 /* DLIF_ftell() */
186 /* */
187 /* Return the current file position in the file identified in the */
188 /* LOADER_FILE_DESC pointed to by 'stream'. */
189 /* */
190 /*---------------------------------------------------------------------------*/
191 int32_t DLIF_ftell(LOADER_FILE_DESC *stream);
193 /*---------------------------------------------------------------------------*/
194 /* DLIF_fread() */
195 /* */
196 /* Read 'size' * 'nmemb' bytes of data from the file identified in the */
197 /* LOADER_FILE_DESC object pointed to by 'stream', and write that data */
198 /* into the memory accessed via 'ptr'. */
199 /* */
200 /*---------------------------------------------------------------------------*/
201 size_t DLIF_fread(void *ptr, size_t size, size_t nmemb,
202 LOADER_FILE_DESC *stream);
204 /*---------------------------------------------------------------------------*/
205 /* DLIF_fclose() */
206 /* */
207 /* Close a file that was opened on behalf of the core loader. Ownership */
208 /* of the file pointer in question belongs to the core loader, but the */
209 /* client has exclusive access to the file system. */
210 /* */
211 /*---------------------------------------------------------------------------*/
212 int DLIF_fclose(LOADER_FILE_DESC *fd);
214 /*---------------------------------------------------------------------------*/
215 /* Host Memory Management */
216 /* */
217 /* Allocate and free host memory as needed for the dynamic loader's */
218 /* internal data structures. If the dynamic loader resides on the */
219 /* target architecture, then this memory is allocated from a target */
220 /* memory heap that must be managed separately from memory that is */
221 /* allocated for a dynamically loaded object file. */
222 /* */
223 /*---------------------------------------------------------------------------*/
225 /*---------------------------------------------------------------------------*/
226 /* DLIF_malloc() */
227 /* */
228 /* Allocate 'size' bytes of memory space that is usable as scratch space */
229 /* (appropriate for the loader's internal data structures) by the dynamic */
230 /* loader. */
231 /* */
232 /*---------------------------------------------------------------------------*/
233 void* DLIF_malloc(size_t size);
235 /*---------------------------------------------------------------------------*/
236 /* DLIF_free() */
237 /* */
238 /* Free memory space that was previously allocated by DLIF_malloc(). */
239 /* */
240 /*---------------------------------------------------------------------------*/
241 void DLIF_free(void* ptr);
243 /*---------------------------------------------------------------------------*/
244 /* Target Memory Allocator Interface */
245 /* */
246 /* The client side of the dynamic loader must create and maintain an */
247 /* infrastructure to manage target memory. The client must keep track */
248 /* of what target memory is associated with each object segment, */
249 /* allocating target memory for newly loaded objects and release target */
250 /* memory that is associated with objects that are being unloaded from */
251 /* the target architecture. */
252 /* */
253 /* The two client-supplied functions, DLIF_allocate() and DLIF_release(), */
254 /* are used by the core loader to interface into the client side's */
255 /* target memory allocator infrastructure. */
256 /* */
257 /*---------------------------------------------------------------------------*/
259 /*---------------------------------------------------------------------------*/
260 /* DLOAD_SEGMENT_FLAGS - segment characteristics. */
261 /*---------------------------------------------------------------------------*/
262 typedef uint32_t DLOAD_SEGMENT_FLAGS;
263 static const int DLOAD_SF_executable = 0x1; /* Memory must be executable */
264 static const int DLOAD_SF_relocatable = 0x2; /* Segment must be relocatable */
266 /*---------------------------------------------------------------------------*/
267 /* DLOAD_MEMORY_SEGMENT - Define structure to represent placement and size */
268 /* details of a segment to be loaded. */
269 /*---------------------------------------------------------------------------*/
270 struct DLOAD_MEMORY_SEGMENT
271 {
272 uint32_t target_page; /* requested/returned memory page */
273 TARGET_ADDRESS target_address; /* requested/returned address */
274 uint32_t objsz_in_bytes; /* size of init'd part of segment */
275 uint32_t memsz_in_bytes; /* size of memory block for segment */
276 };
278 /*---------------------------------------------------------------------------*/
279 /* DLOAD_MEMORY_REQUEST - Define structure to represent a target memory */
280 /* request made by the core loader on behalf of a segment that the */
281 /* loader needs to relocate and write into target memory. */
282 /*---------------------------------------------------------------------------*/
283 struct DLOAD_MEMORY_REQUEST
284 {
285 LOADER_FILE_DESC *fp; /* file being loaded */
286 struct DLOAD_MEMORY_SEGMENT *segment; /* obj for req/ret alloc */
287 void *host_address; /* ret hst ptr from DLIF_copy()*/
288 BOOL is_loaded; /* returned as true if segment */
289 /* is already in target memory */
290 uint32_t offset; /* file offset of segment's */
291 /* raw data */
292 uint32_t flip_endian; /* endianness of trg opp host */
293 DLOAD_SEGMENT_FLAGS flags; /* allocation request flags */
294 uint32_t align; /* align of trg memory block */
295 };
297 /*---------------------------------------------------------------------------*/
298 /* DLIF_allocate() */
299 /* */
300 /* Given a DLOAD_MEMORY_REQUEST created by the core loader, allocate */
301 /* target memory to fulfill the request using the target memory */
302 /* management infrastrucutre on the client side of the dynamic loader. */
303 /* The contents of the DLOAD_MEMORY_REQUEST will be updated per the */
304 /* details of a successful allocation. The allocated page and address */
305 /* can be found in the DLOAD_MEMORY_SEGMENT attached to the request. */
306 /* The boolean return value reflects whether the allocation was */
307 /* successful or not. */
308 /* */
309 /*---------------------------------------------------------------------------*/
310 BOOL DLIF_allocate(struct DLOAD_MEMORY_REQUEST *req);
312 /*---------------------------------------------------------------------------*/
313 /* DLIF_release() */
314 /* */
315 /* Given a DLOAD_MEMORY_SEGMENT description, free the target memory */
316 /* associated with the segment using the target memory management */
317 /* infrastructure on the client side of the dynamic loader. */
318 /* */
319 /*---------------------------------------------------------------------------*/
320 BOOL DLIF_release(struct DLOAD_MEMORY_SEGMENT* ptr);
322 /*---------------------------------------------------------------------------*/
323 /* Target Memory Access / Write Services */
324 /* */
325 /* The client side's target memory allocator infrastructure communicates */
326 /* with the core loader through the DLOAD_MEMORY_REQUEST and */
327 /* DLOAD_MEMORY_SEGMENT data structures defined above. To complete the */
328 /* loading of an object segment, the segment may need to be relocated */
329 /* before it is actually written to target memory in the space that was */
330 /* allocated for it by DLIF_allocate(). */
331 /* */
332 /* The client side of the dynamic loader provides two functions to help */
333 /* complete the process of loading an object segment, DLIF_copy() and */
334 /* DLIF_write(). */
335 /* */
336 /* These functions help to make the core loader truly independent of */
337 /* whether it is running on the host or target architecture and how the */
338 /* client provides for reading/writing from/to target memory. */
339 /* */
340 /*---------------------------------------------------------------------------*/
341 /*---------------------------------------------------------------------------*/
342 /* DLIF_copy() */
343 /* */
344 /* Copy segment data from the object file described in the 'fp' and */
345 /* 'offset' of the DLOAD_MEMORY_REQUEST into host accessible memory so */
346 /* that it can relocated or otherwise manipulated by the core loader. */
347 /* */
348 /*---------------------------------------------------------------------------*/
349 BOOL DLIF_copy(struct DLOAD_MEMORY_REQUEST* req);
351 /*---------------------------------------------------------------------------*/
352 /* DLIF_write() */
353 /* */
354 /* Once the segment data described in the DLOAD_MEMORY_REQUEST is ready */
355 /* (relocated, if needed), write the segment contents to the target */
356 /* memory identified in the DLOAD_MEMORY_SEGMENT attached to the request. */
357 /* */
358 /* After the segment contents have been written to target memory, the */
359 /* core loader should discard the DLOAD_MEMORY_REQUEST object, but retain */
360 /* the DLOAD_MEMORY_SEGMENT object so that the target memory associated */
361 /* with the segment can be releases when the segment is unloaded. */
362 /* */
363 /*---------------------------------------------------------------------------*/
364 BOOL DLIF_write(struct DLOAD_MEMORY_REQUEST* req);
366 /*---------------------------------------------------------------------------*/
367 /* DLIF_read() */
368 /* */
369 /* Given a host accessible buffer, read content of indicated target */
370 /* memory address into the buffer. */
371 /*---------------------------------------------------------------------------*/
372 BOOL DLIF_read(void *ptr, size_t size, size_t nmemb, TARGET_ADDRESS src);
374 /*---------------------------------------------------------------------------*/
375 /* DLIF_execute() */
376 /* */
377 /* Start execution on the target architecture from given 'exec_addr'. */
378 /* If the dynamic loader is running on the target architecture, this can */
379 /* be effected as a simple function call. */
380 /* */
381 /*---------------------------------------------------------------------------*/
382 int32_t DLIF_execute(TARGET_ADDRESS exec_addr);
384 /*---------------------------------------------------------------------------*/
385 /* Loading and Unloading of Dependent Files */
386 /* */
387 /* The dynamic loader core loader must coordinate loading and unloading */
388 /* dependent object files with the client side of the dynamic loader. */
389 /* This allows the client to keep its bookkeeping information up to date */
390 /* with what is currently loaded on the target architecture. */
391 /* */
392 /* For instance, the client may need to interact with a file system or */
393 /* registry. The client may also need to update debug information in */
394 /* synch with the loading and unloading of shared objects. */
395 /* */
396 /*---------------------------------------------------------------------------*/
397 /*---------------------------------------------------------------------------*/
398 /* DLIF_load_dependent() */
399 /* */
400 /* Ask client to find and open a dependent file identified by the */
401 /* 'so_name' parameter, then, if necessary, initiate a DLOAD_load() */
402 /* call to actually load the shared object onto the target. A */
403 /* successful load will return a file handle ID that the client can */
404 /* associate with the newly loaded file. */
405 /* */
406 /*---------------------------------------------------------------------------*/
407 int DLIF_load_dependent(const char* so_name);
409 /*---------------------------------------------------------------------------*/
410 /* DLIF_unload_dependent() */
411 /* */
412 /* Ask client to unload a dependent file identified by the 'file_handle' */
413 /* parameter. Initiate a call to DLOAD_unload() to actually free up */
414 /* the target memory that was occupied by the object file. */
415 /* */
416 /*---------------------------------------------------------------------------*/
417 void DLIF_unload_dependent(uint32_t handle);
419 /*---------------------------------------------------------------------------*/
420 /* Error/Warning Registration Functions */
421 /* */
422 /* The client will maintain an error/warning log. This will allow the */
423 /* core loader to register errors and warnings in the load during a */
424 /* given dynamic load. The client is required to check the log after */
425 /* each load attempt to report any problems. */
426 /* */
427 /*---------------------------------------------------------------------------*/
429 /*---------------------------------------------------------------------------*/
430 /* Loader Warning Types */
431 /*---------------------------------------------------------------------------*/
432 typedef enum {
433 DLWT_MISC = 0, /* Miscellaneous warning */
434 DLWT_FILE /* Warning missing/invalid file information */
435 } LOADER_WARNING_TYPE;
437 /*---------------------------------------------------------------------------*/
438 /* DLIF_warning() */
439 /* */
440 /* Log a warning message with the client's error/warning handling */
441 /* infrastructure. */
442 /* */
443 /*---------------------------------------------------------------------------*/
444 void DLIF_warning(LOADER_WARNING_TYPE wtype, const char *fmt, ...);
446 /*---------------------------------------------------------------------------*/
447 /* Loader Error Types */
448 /*---------------------------------------------------------------------------*/
449 typedef enum {
450 DLET_MISC = 0, /* Miscellaneous error */
451 DLET_FILE, /* Error reading/processing file */
452 DLET_SYMBOL, /* Symbol resolution error */
453 DLET_RELOC, /* Relocation error */
454 DLET_MEMORY, /* Host memory allocation/free error */
455 DLET_TRGMEM, /* Target memory allocation/free error */
456 DLET_DEBUG /* Shared object or DLL debug error */
457 } LOADER_ERROR_TYPE;
459 /*---------------------------------------------------------------------------*/
460 /* DLIF_error() */
461 /* */
462 /* Log an error message with the client's error/warning handling */
463 /* infrastructure. */
464 /* */
465 /*---------------------------------------------------------------------------*/
466 void DLIF_error(LOADER_ERROR_TYPE etype, const char *fmt, ...);
469 /*---------------------------------------------------------------------------*/
470 /* Dynamic Static Base Table (DSBT) Support Functions */
471 /*---------------------------------------------------------------------------*/
472 #define DSBT_INDEX_INVALID -1
473 #define DSBT_DSBT_BASE_INVALID 0
474 #define DSBT_STATIC_BASE_INVALID 0
476 /*****************************************************************************/
477 /* Core Loader Side of DSBT Support */
478 /*****************************************************************************/
480 /*---------------------------------------------------------------------------*/
481 /* DLOAD_get_dsbt_size() */
482 /* */
483 /* Query the size of the DSBT associated with a specified file. The */
484 /* client will check the size of a module's DSBT before it writes a copy */
485 /* of the master DSBT to the module's DSBT. If the module's DSBT is not */
486 /* big enough, an error will be emitted and the load will fail. */
487 /* */
488 /*---------------------------------------------------------------------------*/
489 uint32_t DLOAD_get_dsbt_size(int32_t file_handle);
491 /*---------------------------------------------------------------------------*/
492 /* DLOAD_get_dsbt_base() */
493 /* */
494 /* Find DSBT address for specified file. The client will query for this */
495 /* address after allocation and symbol relocation has been completed. */
496 /* The client will write a copy of the master DSBT to the returned DSBT */
497 /* address if the module's DSBT size is big enough. */
498 /* */
499 /*---------------------------------------------------------------------------*/
500 BOOL DLOAD_get_dsbt_base(int32_t file_handle, TARGET_ADDRESS *dsbt_base);
502 /*---------------------------------------------------------------------------*/
503 /* DLOAD_get_static_base() */
504 /* */
505 /* Find static base for a specified file. The client will query for this */
506 /* address after allocation and symbol relocation has been completed. */
507 /* The client will use the returned static base value to fill the slot */
508 /* in the master DSBT that is associated with this module. */
509 /* */
510 /*---------------------------------------------------------------------------*/
511 BOOL DLOAD_get_static_base(int32_t file_handle, TARGET_ADDRESS *static_base);
514 /*****************************************************************************/
515 /* Client Side of DSBT Support */
516 /*****************************************************************************/
518 /*---------------------------------------------------------------------------*/
519 /* DLIF_register_dsbt_index_request() */
520 /* */
521 /* Register a request for a DSBT index with the client. A module can */
522 /* make a specific DSBT index request or it can allow the client to */
523 /* assign a DSBT index on its behalf (requested_dsbt_index == -1). The */
524 /* client implementation of this function must check that a specific DSBT */
525 /* index request does not conflict with a previous specific DSBT index */
526 /* request. */
527 /* */
528 /*---------------------------------------------------------------------------*/
529 BOOL DLIF_register_dsbt_index_request(const char *requestor_name,
530 int32_t requestor_file_handle,
531 int32_t requested_dsbt_index);
533 /*---------------------------------------------------------------------------*/
534 /* DLIF_assign_dsbt_indices() */
535 /* */
536 /* Bind each module that registered a request for a DSBT index to a */
537 /* specific slot in the DSBT. Specific requests for DSBT indices will be */
538 /* honored first. Any general requests that remain will be assigned to */
539 /* the first available slot in the DSBT. */
540 /* */
541 /*---------------------------------------------------------------------------*/
542 void DLIF_assign_dsbt_indices(void);
544 /*---------------------------------------------------------------------------*/
545 /* DLIF_get_dsbt_index() */
546 /* */
547 /* Given a module that uses the DSBT model, return the identity of the */
548 /* DSBT slot that was assigned to it by the client. This function can */
549 /* only be called after the client has assigned DSBT indices to all */
550 /* loaded object modules that use the DSBT model. The implementation of */
551 /* this function will check that a proper DSBT index has been assigned to */
552 /* the specified module and an invalid index (-1) if there is a problem. */
553 /* */
554 /*---------------------------------------------------------------------------*/
555 int32_t DLIF_get_dsbt_index(int32_t file_handle);
557 /*---------------------------------------------------------------------------*/
558 /* DLIF_update_all_dsbts() */
559 /* */
560 /* Populate the client's model of the master DSBT with the static base */
561 /* for each assigned slot in the DSBT, then write a copy of the master */
562 /* DSBT to each module's DSBT location. The implementation of this */
563 /* function must check the size of each module's DSBT to make sure that */
564 /* it is large enough to hold a copy of the master DSBT. The function */
565 /* will return FALSE if there is a problem. */
566 /* */
567 /*---------------------------------------------------------------------------*/
568 BOOL DLIF_update_all_dsbts(void);
570 #endif