source: rtems/cpukit/libdl/rtl-sym.c @ 1c6ac88

Last change on this file since 1c6ac88 was 1c6ac88, checked in by Ryan Long <ryan.long@…>, on 07/19/22 at 16:34:42

cpukit/libdl/rtl-sym.c: Fix increment of variable

In rtems_rtl_symbol_global_add() the loop that gets to the end of the symbol
table used "unsigned long" to increment the index for the table. For most
architectures this resulted in 4, but with AArch64, it results in 8. This
resulted in the symbols being read in wrong. Changing this to void* along with
changing the RISC-V specific code for 8 byte pointers in rtems-tools to work
independent of the architecture.

Updates #4673
Closes #4682

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup rtems_rtl
7 *
8 * @brief RTEMS Run-Time Linker Object File Symbol Table.
9 */
10
11/*
12 *  COPYRIGHT (c) 2012-2014, 2018 Chris Johns <chrisj@rtems.org>
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include <errno.h>
41#include <inttypes.h>
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45
46#include <rtems/rtl/rtl.h>
47#include "rtl-error.h"
48#include <rtems/rtl/rtl-sym.h>
49#include <rtems/rtl/rtl-trace.h>
50
51/**
52 * The single symbol forced into the global symbol table that is used to load a
53 * symbol table from an object file.
54 */
55static rtems_rtl_obj_sym global_sym_add =
56{
57  .name  = "rtems_rtl_base_sym_global_add",
58  .value = (void*) rtems_rtl_base_sym_global_add
59};
60
61static uint_fast32_t
62rtems_rtl_symbol_hash (const char *s)
63{
64  uint_fast32_t h = 5381;
65  unsigned char c;
66  for (c = *s; c != '\0'; c = *++s)
67    h = h * 33 + c;
68  return h & 0xffffffff;
69}
70
71static void
72rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
73                                rtems_rtl_obj_sym* symbol)
74{
75  uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
76  rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
77                      &symbol->node);
78}
79
80bool
81rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
82                             size_t             buckets)
83{
84  symbols->buckets = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
85                                          buckets * sizeof (rtems_chain_control),
86                                          true);
87  if (!symbols->buckets)
88  {
89    rtems_rtl_set_error (ENOMEM, "no memory for global symbol table");
90    return false;
91  }
92  symbols->nbuckets = buckets;
93  for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
94    rtems_chain_initialize_empty (&symbols->buckets[buckets]);
95  rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
96  return true;
97}
98
99void
100rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
101{
102  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
103}
104
105bool
106rtems_rtl_symbol_global_add (rtems_rtl_obj*       obj,
107                             const unsigned char* esyms,
108                             unsigned int         size)
109{
110  rtems_rtl_symbols* symbols;
111  rtems_rtl_obj_sym* sym;
112  size_t             count;
113  size_t             s;
114  uint32_t           marker;
115
116  count = 0;
117  s = 0;
118  while ((s < size) && (esyms[s] != 0))
119  {
120    int l = strlen ((char*) &esyms[s]);
121    if ((esyms[s + l] != '\0') || ((s + l) > size))
122    {
123      rtems_rtl_set_error (EINVAL, "invalid exported symbol table");
124      return false;
125    }
126    ++count;
127    s += l + sizeof (void *) + 1;
128  }
129
130  /*
131   * Check this is the correct end of the table.
132   */
133  marker = esyms[s + 1];
134  marker <<= 8;
135  marker |= esyms[s + 2];
136  marker <<= 8;
137  marker |= esyms[s + 3];
138  marker <<= 8;
139  marker |= esyms[s + 4];
140
141  if (marker != 0xdeadbeefUL)
142  {
143    rtems_rtl_set_error (ENOMEM, "invalid export symbol table");
144    return false;
145  }
146
147  if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
148    printf ("rtl: global symbol add: %zi\n", count);
149
150  obj->global_size = count * sizeof (rtems_rtl_obj_sym);
151  obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
152                                           obj->global_size, true);
153  if (!obj->global_table)
154  {
155    obj->global_size = 0;
156    rtems_rtl_set_error (ENOMEM, "no memory for global symbols");
157    return false;
158  }
159
160  symbols = rtems_rtl_global_symbols ();
161
162  s = 0;
163  sym = obj->global_table;
164
165  while ((s < size) && (esyms[s] != 0))
166  {
167    /*
168     * Copy the void* using a union and memcpy to avoid any strict aliasing or
169     * alignment issues. The variable length of the label and the packed nature
170     * of the table means casting is not suitable.
171     */
172    union {
173      uint8_t data[sizeof (void*)];
174      void*   value;
175    } copy_voidp;
176    int b;
177
178    sym->name = (const char*) &esyms[s];
179    s += strlen (sym->name) + 1;
180    for (b = 0; b < sizeof (void*); ++b, ++s)
181      copy_voidp.data[b] = esyms[s];
182    sym->value = copy_voidp.value;
183    if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
184      printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value);
185    if (rtems_rtl_symbol_global_find (sym->name) == NULL)
186      rtems_rtl_symbol_global_insert (symbols, sym);
187    ++sym;
188  }
189
190  obj->global_syms = count;
191
192  return true;
193}
194
195rtems_rtl_obj_sym*
196rtems_rtl_symbol_global_find (const char* name)
197{
198  rtems_rtl_symbols*   symbols;
199  uint_fast32_t        hash;
200  rtems_chain_control* bucket;
201  rtems_chain_node*    node;
202
203  symbols = rtems_rtl_global_symbols ();
204
205  hash = rtems_rtl_symbol_hash (name);
206  bucket = &symbols->buckets[hash % symbols->nbuckets];
207  node = rtems_chain_first (bucket);
208
209  while (!rtems_chain_is_tail (bucket, node))
210  {
211    rtems_rtl_obj_sym* sym = (rtems_rtl_obj_sym*) node;
212    /*
213     * Use the hash. I could add this to the symbol but it uses more memory.
214     */
215    if (strcmp (name, sym->name) == 0)
216      return sym;
217    node = rtems_chain_next (node);
218  }
219
220  return NULL;
221}
222
223static int
224rtems_rtl_symbol_obj_compare (const void* a, const void* b)
225{
226  const rtems_rtl_obj_sym* sa;
227  const rtems_rtl_obj_sym* sb;
228  sa = (const rtems_rtl_obj_sym*) a;
229  sb = (const rtems_rtl_obj_sym*) b;
230  return strcmp (sa->name, sb->name);
231}
232
233void
234rtems_rtl_symbol_obj_sort (rtems_rtl_obj* obj)
235{
236  qsort (obj->local_table,
237         obj->local_syms,
238         sizeof (rtems_rtl_obj_sym),
239         rtems_rtl_symbol_obj_compare);
240  qsort (obj->global_table,
241         obj->global_syms,
242         sizeof (rtems_rtl_obj_sym),
243         rtems_rtl_symbol_obj_compare);
244}
245
246rtems_rtl_obj_sym*
247rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj, const char* name)
248{
249  /*
250   * Check the object file's symbols first. If not found search the
251   * global symbol table.
252   */
253  if (obj->local_syms)
254  {
255    rtems_rtl_obj_sym* match;
256    rtems_rtl_obj_sym  key = { 0 };
257    key.name = name;
258    match = bsearch (&key, obj->local_table,
259                     obj->local_syms,
260                     sizeof (rtems_rtl_obj_sym),
261                     rtems_rtl_symbol_obj_compare);
262    if (match != NULL)
263      return match;
264  }
265  if (obj->global_syms)
266  {
267    rtems_rtl_obj_sym* match;
268    rtems_rtl_obj_sym  key = { 0 };
269    key.name = name;
270    match = bsearch (&key, obj->global_table,
271                     obj->global_syms,
272                     sizeof (rtems_rtl_obj_sym),
273                     rtems_rtl_symbol_obj_compare);
274    if (match != NULL)
275      return match;
276  }
277  return rtems_rtl_symbol_global_find (name);
278}
279
280void
281rtems_rtl_symbol_obj_add (rtems_rtl_obj* obj)
282{
283  rtems_rtl_symbols* symbols;
284  rtems_rtl_obj_sym* sym;
285  size_t             s;
286
287  symbols = rtems_rtl_global_symbols ();
288
289  for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
290    rtems_rtl_symbol_global_insert (symbols, sym);
291}
292
293void
294rtems_rtl_symbol_obj_erase_local (rtems_rtl_obj* obj)
295{
296  if (obj->local_table)
297  {
298    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
299    obj->local_table = NULL;
300    obj->local_size = 0;
301    obj->local_syms = 0;
302  }
303}
304
305void
306rtems_rtl_symbol_obj_erase (rtems_rtl_obj* obj)
307{
308  rtems_rtl_symbol_obj_erase_local (obj);
309  if (obj->global_table)
310  {
311    rtems_rtl_obj_sym* sym;
312    size_t             s;
313    for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
314        if (!rtems_chain_is_node_off_chain (&sym->node))
315          rtems_chain_extract (&sym->node);
316    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
317    obj->global_table = NULL;
318    obj->global_size = 0;
319    obj->global_syms = 0;
320  }
321}
Note: See TracBrowser for help on using the repository browser.