Update QNX IPC loader to RIDL 2.1.0
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / procMgr / hlos / knl / loaders / Elf / Qnx / DLOAD / DLOAD_SYM / symtab.c
1 /*
2 * symtab.c
3 *
4 * Symbol table creation, maintenance, and management.  This module also
5 * contains implementations of local and global symbol table lookup
6 * algorithms, as appropriate for the platform that we are running on
7 * (assumed to be DSP Bridge or Linux model, indicated by
8 * direct_dependent_only flag in a given Module).
9 *
10 * Copyright (C) 2009-2015 Texas Instruments Incorporated - http://www.ti.com/
11 *
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 */
43 #include "elf32.h"
44 #include "ArrayList.h"
46 /*---------------------------------------------------------------------------*/
47 /* Set up a Queue of Int32 type data objects.                                */
48 /*---------------------------------------------------------------------------*/
49 #include "Queue.h"
50 TYPE_QUEUE_DEFINITION(int32_t, Int32)
51 TYPE_QUEUE_IMPLEMENTATION(int32_t, Int32)
53 #include "symtab.h"
54 #include "dload_api.h"
55 #include <string.h>
57 /*---------------------------------------------------------------------------*/
58 /* Holds the handle of the ET_EXEC-type mmodule loaded, if any.              */
59 /*---------------------------------------------------------------------------*/
60 int32_t DLIMP_application_handle = 0;
62 /*---------------------------------------------------------------------------*/
63 /* Function prototypes                                                       */
64 /*---------------------------------------------------------------------------*/
65 BOOL DLSYM_lookup_global_symtab(const char *sym_name, struct Elf32_Sym *symtab,
66                                 Elf32_Word symnum, Elf32_Addr *sym_value);
68 /*****************************************************************************/
69 /* DLSYM_COPY_GLOBALS() - Copy global symbols from the dynamic module's      */
70 /*      symbol table to the loader's global symbol table.                    */
71 /*****************************************************************************/
72 void DLSYM_copy_globals(DLIMP_Dynamic_Module *dyn_module)
73 {
74    Elf32_Word i, global_index, global_symnum;
75    DLIMP_Loaded_Module *module = dyn_module->loaded_module;
77 #if LOADER_DEBUG
78    if (debugging_on)
79       DLIF_trace("DLSYM_copy_globals:\n");
80 #endif
82    /*------------------------------------------------------------------------*/
83    /* The dynamic symbol table is sorted so that the local symbols come      */
84    /* before the global symbols. gsymtab_offset points to the address where   */
85    /* the first global symbol starts. Only the global symbols need to be     */
86    /* copied into the persistent info.                                       */
87    /*------------------------------------------------------------------------*/
88    global_index  = dyn_module->gsymtab_offset / sizeof(struct Elf32_Sym);
89    global_symnum = dyn_module->symnum - global_index;
91    /*------------------------------------------------------------------------*/
92    /* Create space for the new global symbol table.                          */
93    /*------------------------------------------------------------------------*/
95    if (module->gsymtab)
96    {
97        DLIF_free(module->gsymtab);
98        module->gsymtab = NULL;
99    }
101    if (global_symnum > 0)
102    {
103       module->gsymtab = DLIF_malloc(sizeof(struct Elf32_Sym) * global_symnum);
105       memcpy(module->gsymtab,
106              &dyn_module->symtab[global_index],
107              sizeof(struct Elf32_Sym) * global_symnum);
108    }
109    module->gsymnum = global_symnum;
111    /*------------------------------------------------------------------------*/
112    /* Copy the string table part that contains the global symbol names.      */
113    /*------------------------------------------------------------------------*/
114    if (module->gstrtab)
115    {
116        DLIF_free(module->gstrtab);
117        module->gstrtab = NULL;
118    }
120    module->gstrsz  = dyn_module->strsz - dyn_module->gstrtab_offset;
121    if (module->gstrsz)
122    {
123       module->gstrtab = DLIF_malloc(module->gstrsz);
125       memcpy(module->gstrtab,
126              dyn_module->strtab + dyn_module->gstrtab_offset,
127              module->gstrsz);
128    }
130    /*------------------------------------------------------------------------*/
131    /* Update the symbol names of the global symbol entries to point to       */
132    /* the symbol names in the string table.                                  */
133    /* NOTE: Note that we don't set the offset into the string table. We      */
134    /* instead set the full address so that the st_name field can be accessed */
135    /* as char *.                                                             */
136    /*------------------------------------------------------------------------*/
137    for (i = 0; i < global_symnum; i++)
138    {
140       Elf32_Word old_offset = dyn_module->symtab[i + global_index].st_name -
141                               (Elf32_Addr) dyn_module->strtab;
142       Elf32_Word new_offset = old_offset - dyn_module->gstrtab_offset;
143       struct Elf32_Sym *sym = &((struct Elf32_Sym*)(module->gsymtab))[i];
144       sym->st_name = new_offset + (Elf32_Addr)module->gstrtab;
146 #if LOADER_DEBUG
147       if (debugging_on) DLIF_trace("Copying symbol: %s\n",
148                           (char*)dyn_module->symtab[i + global_index].st_name);
149 #endif
150    }
153 /*****************************************************************************/
154 /* BREADTH_FIRST_LOOKUP() - Perform a breadth-first search of the Module     */
155 /*     dependency graph to find specified symbol name (sym_name).            */
156 /*****************************************************************************/
157 static BOOL breadth_first_lookup(DLOAD_HANDLE phandle,
158                                  const char* sym_name,
159                                  int handle,
160                                  Elf32_Addr *sym_value)
162    /*------------------------------------------------------------------------*/
163    /* We start this function by putting the specified file handle on the     */
164    /* file_handle_queue.                                                     */
165    /*------------------------------------------------------------------------*/
166    LOADER_OBJECT *dHandle = (LOADER_OBJECT *)phandle;
167    Int32_Queue file_handle_queue = TYPE_QUEUE_INITIALIZER;
168    Int32_enqueue(&file_handle_queue, handle);
170    /*------------------------------------------------------------------------*/
171    /* While the queue is not empty, keep looking for the symbol.             */
172    /*------------------------------------------------------------------------*/
173    while(file_handle_queue.size)
174    {
175       int i;
177       /*---------------------------------------------------------------------*/
178       /* Set up a pointer to front of the list of loaded files so that we    */
179       /* can be sure that dependent files will be searched in load order.    */
180       /*---------------------------------------------------------------------*/
181       loaded_module_ptr_Queue_Node* mod_node =
182                                      dHandle->DLIMP_loaded_objects.front_ptr;
183       int* dependencies = (int*)(mod_node->value->dependencies.buf);
185       /*---------------------------------------------------------------------*/
186       /* Pluck off the file handle at the front of the file_handle_queue.    */
187       /* We will search this file next.                                      */
188       /*---------------------------------------------------------------------*/
189       handle = Int32_dequeue(&file_handle_queue);
191       /*---------------------------------------------------------------------*/
192       /* Locate the Module associated with the current file handle.          */
193       /*---------------------------------------------------------------------*/
194       while (mod_node->value->file_handle != handle) mod_node++;
196       /*---------------------------------------------------------------------*/
197       /* Search the symbol table of the current file handle's Module.        */
198       /* If the symbol was found, then we're finished.                       */
199       /*---------------------------------------------------------------------*/
200       if (DLSYM_lookup_global_symtab(sym_name,
201                                      mod_node->value->gsymtab,
202                                      mod_node->value->gsymnum,
203                                      sym_value))
204          return TRUE;
206       /*---------------------------------------------------------------------*/
207       /* If our symbol was not in the current Module, then add this Module's */
208       /* dependents to the end of the file_handle_queue.                     */
209       /*---------------------------------------------------------------------*/
210       for (i = 0; i < mod_node->value->dependencies.size; i++)
211          Int32_enqueue(&file_handle_queue, dependencies[i]);
212    }
214    /*------------------------------------------------------------------------*/
215    /* We didn't find our symbol; return FALSE.                               */
216    /*------------------------------------------------------------------------*/
217    return FALSE;
220 /*****************************************************************************/
221 /* DLSYM_global_lookup() - Search the global symbol table to find the        */
222 /*                         definition of the given symbol name.              */
223 /*****************************************************************************/
224 BOOL DLSYM_global_lookup(DLOAD_HANDLE handle,
225                          const char    *sym_name,
226                          DLIMP_Loaded_Module *loaded_module,
227                          Elf32_Addr    *sym_value)
229    int i = 0;
230    loaded_module_ptr_Queue_Node* node;
231    LOADER_OBJECT *dHandle = (LOADER_OBJECT *)handle;
233 #if LOADER_DEBUG
234    if (debugging_on)
235       DLIF_trace("DLSYM_global_lookup: %s\n", sym_name);
236 #endif
238    /*------------------------------------------------------------------------*/
239    /* We will choose a different lookup algorithm based on what kind of      */
240    /* platform we are supporting.  In the Braveheart case, the global symbol */
241    /* lookup algorithm searches the base image first, followed by the        */
242    /* explicit children of the specified Module.                             */
243    /*------------------------------------------------------------------------*/
244    if (loaded_module->direct_dependent_only)
245    {
246       int* child_handle = (int*)(loaded_module->dependencies.buf);
248       /*---------------------------------------------------------------------*/
249       /* Spin through list of this Module's dependencies (anything on its    */
250       /* DT_NEEDED list), searching through each dependent's symbol table    */
251       /* to find the symbol we are after.                                    */
252       /*---------------------------------------------------------------------*/
253       for (i = 0; i < loaded_module->dependencies.size; i++)
254       {
255          for (node = dHandle->DLIMP_loaded_objects.front_ptr;
256            node->value->file_handle != child_handle[i];
257            node=node->next_ptr);
259          /*------------------------------------------------------------------*/
260          /* Return true if we find the symbol.                               */
261          /*------------------------------------------------------------------*/
262          if (DLSYM_lookup_global_symtab(sym_name,
263                                         node->value->gsymtab,
264                                         node->value->gsymnum,
265                                         sym_value))
266             return TRUE;
267       }
268    }
270    /*------------------------------------------------------------------------*/
271    /* In the LINUX model, we will use a breadth-first global symbol lookup   */
272    /* algorithm.  First, the application's global symbol table is searched,  */
273    /* followed by its children, followed by their children, and so on.       */
274    /* It is up to the client of this module to set the application handle.   */
275    /*------------------------------------------------------------------------*/
276    else
277    {
278       if (breadth_first_lookup(handle, sym_name, DLIMP_application_handle,
279                                sym_value))
280          return TRUE;
281    }
283    /*------------------------------------------------------------------------*/
284    /* If we got this far, then symbol was not found.                         */
285    /*------------------------------------------------------------------------*/
286    DLIF_error(DLET_SYMBOL, "Could not resolve symbol %s!\n", sym_name);
288    return FALSE;
291 /*****************************************************************************/
292 /* DLSYM_lookup_symtab() - Lookup the symbol name in the given symbol table. */
293 /*                         Symbol must have specified binding. Return the    */
294 /*                         value in sym_value and return TRUE if the lookup  */
295 /*                         succeeds.                                         */
296 /*****************************************************************************/
297 static BOOL DLSYM_lookup_symtab(const char *sym_name, struct Elf32_Sym *symtab,
298                                 Elf32_Word symnum, Elf32_Addr *sym_value,
299                                 BOOL require_local_binding)
301    Elf32_Addr sym_idx;
303 #if LOADER_DEBUG
304       if (debugging_on)
305          DLIF_trace("DLSYM_lookup_symtab, sym to find : %s\n", sym_name);
306 #endif
308    for (sym_idx = 0; sym_idx < symnum; sym_idx++)
309    {
310 #if LOADER_DEBUG
311       if (debugging_on)
312          DLIF_trace("\tPotential symbol match : %s\n",
313                  (char*)symtab[sym_idx].st_name);
314 #endif
316       if ((symtab[sym_idx].st_shndx != SHN_UNDEF) && ((require_local_binding &&
317           (ELF32_ST_BIND(symtab[sym_idx].st_info) == STB_LOCAL)) ||
318       (!require_local_binding &&
319       (ELF32_ST_BIND(symtab[sym_idx].st_info) != STB_LOCAL))) &&
320           !strcmp(sym_name,(char*)(symtab[sym_idx].st_name)))
321       {
322          if (sym_value) *sym_value = symtab[sym_idx].st_value;
323          return TRUE;
325       }
326    }
327    if (sym_value) *sym_value = 0;
328    return FALSE;
331 /*****************************************************************************/
332 /* DLSYM_lookup_global_symtab() - Lookup the symbol name in the given symbol */
333 /*                               table. Symbol must have global binding.     */
334 /*                               Return the value in sym_value and return    */
335 /*                               TRUE if the lookup succeeds.                */
336 /*****************************************************************************/
337 BOOL DLSYM_lookup_global_symtab(const char *sym_name, struct Elf32_Sym *symtab,
338                                 Elf32_Word symnum, Elf32_Addr *sym_value)
340    return DLSYM_lookup_symtab(sym_name, symtab, symnum, sym_value, FALSE);
343 /*****************************************************************************/
344 /* DLSYM_lookup_local_symtab() - Lookup the symbol name in the given symbol  */
345 /*                               table. Symbol must have local binding.      */
346 /*                               Return the value in sym_value and return    */
347 /*                               TRUE if the lookup succeeds.                */
348 /*****************************************************************************/
349 BOOL DLSYM_lookup_local_symtab(const char *sym_name, struct Elf32_Sym *symtab,
350                                Elf32_Word symnum, Elf32_Addr *sym_value)
352    return DLSYM_lookup_symtab(sym_name, symtab, symnum, sym_value, TRUE);
355 /*****************************************************************************/
356 /* CANONICAL_SYMBOL_LOOKUP() - Find the symbol definition. Look up the local */
357 /*                             symbol table to find the symbol. If it is a   */
358 /*                             definition and cannot be pre-empted, return   */
359 /*                             it. Otherwise, do a look up in the global     */
360 /*                             symbol table that contains the symbol tables  */
361 /*                             from all the necessary modules.               */
362 /*****************************************************************************/
363 BOOL DLSYM_canonical_lookup(DLOAD_HANDLE handle, int sym_index,
364                             DLIMP_Dynamic_Module *dyn_module,
365                             Elf32_Addr *sym_value)
367    /*------------------------------------------------------------------------*/
368    /* Lookup the symbol table to get the symbol characteristics.             */
369    /*------------------------------------------------------------------------*/
370    struct Elf32_Sym *sym = &dyn_module->symtab[sym_index];
371    int32_t           st_bind = ELF32_ST_BIND(sym->st_info);
372    int32_t           st_vis  = ELF32_ST_VISIBILITY(sym->st_other);
373    BOOL              is_def  = (sym->st_shndx != SHN_UNDEF &&
374                                (sym->st_shndx < SHN_LORESERVE ||
375                                 sym->st_shndx == SHN_ABS ||
376                                 sym->st_shndx == SHN_COMMON ||
377                                 sym->st_shndx == SHN_XINDEX));
378    const char *sym_name = (char *)sym->st_name;
380 #if LOADER_DEBUG
381    if (debugging_on)
382       DLIF_trace("DLSYM_canonical_lookup: %d, %s\n", sym_index, sym_name);
383 #endif
385    /*------------------------------------------------------------------------*/
386    /* Local symbols and symbol definitions that cannot be pre-empted         */
387    /* are resolved by the definition in the same module.                     */
388    /*------------------------------------------------------------------------*/
389    if (st_bind == STB_LOCAL || st_vis != STV_DEFAULT)
390    {
391       /*---------------------------------------------------------------------*/
392       /* If it is a local symbol or non-local that cannot be preempted,      */
393       /* the definition should be found in the same module. If we don't      */
394       /* find the definition it is an error.                                 */
395       /*---------------------------------------------------------------------*/
396       if (!is_def)
397       {
398          DLIF_error(DLET_SYMBOL,
399                     "Local/non-imported symbol %s definition is not found "
400                     "in module %s!\n", sym_name, dyn_module->name);
401          return FALSE;
402       }
403       else
404       {
405          if (sym_value) *sym_value = sym->st_value;
406          return TRUE;
407       }
408    }
409    /*------------------------------------------------------------------------*/
410    /* Else we have either pre-emptable defintion or undef symbol. We need    */
411    /* to do global look up.                                                  */
412    /*------------------------------------------------------------------------*/
413    else
414    {
415       return DLSYM_global_lookup(handle, sym_name, dyn_module->loaded_module,
416                                  sym_value);
417    }