source: rtems/cpukit/libdl/rtl-allocator.c @ b36c5209

Last change on this file since b36c5209 was b36c5209, checked in by Chris Johns <chrisj@…>, on May 3, 2019 at 12:15:20 AM

libdl: Do not access the ELF file while the allocator is locked.

  • Load symbols before allocation.
  • Parse reloc records and place any reloc recs in a cache to use while the allocator is locked.
  • Relocate symbols after section allocation.
  • Split section loading into allocation/locating and loading.
  • Update all arch back-ends with a new reloc interface to control tramp handling.
  • Add -a and -t to the object list shell command.

Closes #3741

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtl
12 *
13 * @brief RTEMS Run-Time Linker Allocator
14 */
15
16#include <stdio.h>
17#include <string.h>
18
19#include <rtems/rtl/rtl.h>
20#include "rtl-alloc-heap.h"
21#include <rtems/rtl/rtl-trace.h>
22
23/**
24 * Tags as symbols for tracing.
25 */
26#if RTEMS_RTL_TRACE
27static const char* tag_labels[6] =
28{
29  "OBJECT",
30  "SYMBOL",
31  "EXTERNAL",
32  "READ",
33  "READ_WRITE",
34  "READ_EXEC",
35};
36#define rtems_rtl_trace_tag_label(_l) tag_labels[_l]
37#else
38#define rtems_rtl_trace_tag_label(_l) ""
39#endif
40
41void
42rtems_rtl_alloc_initialise (rtems_rtl_alloc_data* data)
43{
44  int c;
45  data->allocator = rtems_rtl_alloc_heap;
46  for (c = 0; c < RTEMS_RTL_ALLOC_TAGS; ++c)
47    rtems_chain_initialize_empty (&data->indirects[c]);
48}
49
50void*
51rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero)
52{
53  rtems_rtl_data* rtl = rtems_rtl_lock ();
54  void*           address = NULL;
55
56  /*
57   * Obtain memory from the allocator. The address field is set by the
58   * allocator.
59   */
60  if (rtl != NULL)
61    rtl->allocator.allocator (RTEMS_RTL_ALLOC_NEW, tag, &address, size);
62
63  rtems_rtl_unlock ();
64
65  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
66    printf ("rtl: alloc: new: %s addr=%p size=%zu\n",
67            rtems_rtl_trace_tag_label (tag), address, size);
68
69  /*
70   * Only zero the memory if asked to and the allocation was successful.
71   */
72  if (address != NULL && zero)
73    memset (address, 0, size);
74
75  return address;
76}
77
78void
79rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address)
80{
81  rtems_rtl_data* rtl = rtems_rtl_lock ();
82
83  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
84    printf ("rtl: alloc: del: %s addr=%p\n",
85            rtems_rtl_trace_tag_label (tag), address);
86
87  if (rtl != NULL && address != NULL)
88    rtl->allocator.allocator (RTEMS_RTL_ALLOC_DEL, tag, &address, 0);
89
90  rtems_rtl_unlock ();
91}
92
93void
94rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address)
95{
96  rtems_rtl_data* rtl = rtems_rtl_lock ();
97
98  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
99    printf ("rtl: alloc: wr-enable: addr=%p\n", address);
100
101  if (rtl != NULL && address != NULL)
102    rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_ENABLE,
103                              tag,
104                              address,
105                              0);
106
107  rtems_rtl_unlock ();
108}
109
110void
111rtems_rtl_alloc_lock (void)
112{
113  rtems_rtl_data* rtl = rtems_rtl_lock ();
114
115  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
116    printf ("rtl: alloc: lock\n");
117
118  if (rtl != NULL)
119    rtl->allocator.allocator (RTEMS_RTL_ALLOC_LOCK,
120                              RTEMS_RTL_ALLOC_OBJECT, /* should be ignored */
121                              NULL,
122                              0);
123
124  rtems_rtl_unlock ();
125}
126
127
128void
129rtems_rtl_alloc_unlock (void)
130{
131  rtems_rtl_data* rtl = rtems_rtl_lock ();
132
133  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
134    printf ("rtl: alloc: unlock\n");
135
136  if (rtl != NULL)
137    rtl->allocator.allocator (RTEMS_RTL_ALLOC_UNLOCK,
138                              RTEMS_RTL_ALLOC_OBJECT, /* should be ignored */
139                              NULL,
140                              0);
141
142  rtems_rtl_unlock ();
143}
144void
145rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address)
146{
147  rtems_rtl_data* rtl = rtems_rtl_lock ();
148
149  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
150    printf ("rtl: alloc: wr-disable: addr=%p\n", address);
151
152  if (rtl != NULL && address != NULL)
153    rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE,
154                              tag,
155                              address,
156                              0);
157
158  rtems_rtl_unlock ();
159}
160
161rtems_rtl_allocator
162rtems_rtl_alloc_hook (rtems_rtl_allocator handler)
163{
164  rtems_rtl_data*     rtl = rtems_rtl_lock ();
165  rtems_rtl_allocator previous = rtl->allocator.allocator;
166  rtl->allocator.allocator = handler;
167  rtems_rtl_unlock ();
168  return previous;
169}
170
171void
172rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag tag,
173                              rtems_rtl_ptr*      handle,
174                              size_t              size)
175{
176  rtems_rtl_data* rtl = rtems_rtl_lock ();
177
178  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
179  {
180    if (!rtems_rtl_ptr_null (handle))
181      printf ("rtl: alloc: inew: %s handle=%p: not null\n",
182              rtems_rtl_trace_tag_label (tag), handle);
183    printf ("rtl: alloc: inew: %s handle=%p size=%zd\n",
184            rtems_rtl_trace_tag_label (tag), handle, size);
185  }
186
187  if (rtl)
188  {
189    rtems_rtl_alloc_data* allocator = &rtl->allocator;
190    handle->pointer = rtems_rtl_alloc_new (tag, size, false);
191    if (!rtems_rtl_ptr_null (handle))
192      rtems_chain_append_unprotected (&allocator->indirects[tag],
193                                      &handle->node);
194  }
195
196  rtems_rtl_unlock ();
197}
198
199void
200rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag tag,
201                              rtems_rtl_ptr*      handle)
202{
203  rtems_rtl_data* rtl = rtems_rtl_lock ();
204
205  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
206  {
207    if (rtems_rtl_ptr_null (handle))
208      printf ("rtl: alloc: idel: %s handle=%p: is null\n",
209              rtems_rtl_trace_tag_label (tag), handle);
210    printf ("rtl: alloc: idel: %s handle=%p\n",
211            rtems_rtl_trace_tag_label (tag), handle);
212  }
213
214  if (rtl && !rtems_rtl_ptr_null (handle))
215  {
216    rtems_chain_extract_unprotected (&handle->node);
217    rtems_rtl_alloc_del (tag, &handle->pointer);
218  }
219}
220
221rtems_rtl_alloc_tag
222rtems_rtl_alloc_text_tag (void)
223{
224  return RTEMS_RTL_ALLOC_READ_EXEC;
225}
226
227rtems_rtl_alloc_tag
228rtems_rtl_alloc_const_tag (void)
229{
230  return RTEMS_RTL_ALLOC_READ;
231}
232
233rtems_rtl_alloc_tag
234rtems_rtl_alloc_eh_tag (void)
235{
236  return RTEMS_RTL_ALLOC_READ;
237}
238
239rtems_rtl_alloc_tag
240rtems_rtl_alloc_data_tag (void)
241{
242  return RTEMS_RTL_ALLOC_READ_WRITE;
243}
244
245rtems_rtl_alloc_tag
246rtems_rtl_alloc_bss_tag (void)
247{
248  return RTEMS_RTL_ALLOC_READ_WRITE;
249}
250
251bool
252rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
253                            void** const_base, size_t const_size,
254                            void** eh_base, size_t eh_size,
255                            void** data_base, size_t data_size,
256                            void** bss_base, size_t bss_size)
257{
258  *text_base = *const_base = *data_base = *bss_base = NULL;
259
260  if (text_size)
261  {
262    *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (),
263                                      text_size, false);
264    if (!*text_base)
265    {
266      return false;
267    }
268  }
269
270  if (const_size)
271  {
272    *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (),
273                                       const_size, false);
274    if (!*const_base)
275    {
276      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
277                                  data_base, bss_base);
278      return false;
279    }
280  }
281
282  if (eh_size)
283  {
284    *eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (),
285                                    eh_size, false);
286    if (!*eh_base)
287    {
288      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
289                                  data_base, bss_base);
290      return false;
291    }
292  }
293
294  if (data_size)
295  {
296    *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (),
297                                      data_size, false);
298    if (!*data_base)
299    {
300      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
301                                  data_base, bss_base);
302      return false;
303    }
304  }
305
306  if (bss_size)
307  {
308    *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (),
309                                     bss_size, false);
310    if (!*bss_base)
311    {
312      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
313                                  data_base, bss_base);
314      return false;
315    }
316  }
317
318  return true;
319}
320
321void
322rtems_rtl_alloc_module_del (void** text_base,
323                            void** const_base,
324                            void** eh_base,
325                            void** data_base,
326                            void** bss_base)
327{
328  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base);
329  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base);
330  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *eh_base);
331  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base);
332  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base);
333  *text_base = *const_base = *eh_base = *data_base = *bss_base = NULL;
334}
Note: See TracBrowser for help on using the repository browser.