source: rtems/cpukit/libdl/rtl-mdreloc-sparc.c @ 7d9455e

5
Last change on this file since 7d9455e was bba48d9, checked in by Chris Johns <chrisj@…>, on 03/30/17 at 00:06:24

libdl: Support link ordered loading of ELF sections.

The ARM C++ exception ABI uses an address ordered index table to
locate the correct frame data and this requires the EXIDX sections are
loaded in the order the order the matching text is loaded.

The EXIDX sections set the SHF_LINK_ORDER flag and link field. This patch
adds support to load those flagged sections in the linked-to section
order.

Updates #2955.
Closes #2959

  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
3 */
4
5/*  $NetBSD: mdreloc.c,v 1.43 2010/01/13 20:17:22 christos Exp $  */
6
7/*-
8 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
9 * All rights reserved.
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Paul Kranenburg and by Charles M. Hannum.
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE 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#include <sys/cdefs.h>
37
38#include <stdio.h>
39
40#include <rtems/rtl/rtl.h>
41#include "rtl-elf.h"
42#include "rtl-error.h"
43#include "rtl-trace.h"
44#include "rtl-unwind.h"
45#include "rtl-unwind-dw2.h"
46
47/*
48 * The following table holds for each relocation type:
49 *  - the width in bits of the memory location the relocation
50 *    applies to (not currently used)
51 *  - the number of bits the relocation value must be shifted to the
52 *    right (i.e. discard least significant bits) to fit into
53 *    the appropriate field in the instruction word.
54 *  - flags indicating whether
55 *    * the relocation involves a symbol
56 *    * the relocation is relative to the current position
57 *    * the relocation is for a GOT entry
58 *    * the relocation is relative to the load address
59 *
60 */
61#define _RF_S     0x80000000           /* Resolve symbol */
62#define _RF_A     0x40000000           /* Use addend */
63#define _RF_P     0x20000000           /* Location relative */
64#define _RF_G     0x10000000           /* GOT offset */
65#define _RF_B     0x08000000           /* Load address relative */
66#define _RF_U     0x04000000           /* Unaligned */
67#define _RF_SZ(s) (((s) & 0xff) << 8)  /* memory target size */
68#define _RF_RS(s) ( (s) & 0xff)        /* right shift */
69
70static const uint32_t reloc_target_flags[] = {
71  0,                                             /* NONE */
72  _RF_S|_RF_A|        _RF_SZ(8)  | _RF_RS(0),    /* RELOC_8 */
73  _RF_S|_RF_A|        _RF_SZ(16) | _RF_RS(0),    /* RELOC_16 */
74  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(0),    /* RELOC_32 */
75  _RF_S|_RF_A|_RF_P|  _RF_SZ(8)  | _RF_RS(0),    /* DISP_8 */
76  _RF_S|_RF_A|_RF_P|  _RF_SZ(16) | _RF_RS(0),    /* DISP_16 */
77  _RF_S|_RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(0),    /* DISP_32 */
78  _RF_S|_RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(2),    /* WDISP_30 */
79  _RF_S|_RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(2),    /* WDISP_22 */
80  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(10),   /* HI22 */
81  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(0),    /* 22 */
82  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(0),    /* 13 */
83  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(0),    /* LO10 */
84  _RF_G|              _RF_SZ(32) | _RF_RS(0),    /* GOT10 */
85  _RF_G|              _RF_SZ(32) | _RF_RS(0),    /* GOT13 */
86  _RF_G|              _RF_SZ(32) | _RF_RS(10),   /* GOT22 */
87  _RF_S|_RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(0),    /* PC10 */
88  _RF_S|_RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(10),   /* PC22 */
89        _RF_A|_RF_P|  _RF_SZ(32) | _RF_RS(2),    /* WPLT30 */
90                      _RF_SZ(32) | _RF_RS(0),    /* COPY */
91  _RF_S|_RF_A|        _RF_SZ(32) | _RF_RS(0),    /* GLOB_DAT */
92                      _RF_SZ(32) | _RF_RS(0),    /* JMP_SLOT */
93        _RF_A|  _RF_B|_RF_SZ(32) | _RF_RS(0),    /* RELATIVE */
94  _RF_S|_RF_A|  _RF_U|_RF_SZ(32) | _RF_RS(0),    /* UA_32 */
95};
96
97#define NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
98#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
99static const char *reloc_names[] = {
100  "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
101  "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
102  "22", "13", "LO10", "GOT10", "GOT13",
103  "GOT22", "PC10", "PC22", "WPLT30", "COPY",
104  "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
105};
106#endif
107
108#define RELOC_RESOLVE_SYMBOL(t)    ((reloc_target_flags[t] & _RF_S) != 0)
109#define RELOC_PC_RELATIVE(t)       ((reloc_target_flags[t] & _RF_P) != 0)
110#define RELOC_BASE_RELATIVE(t)     ((reloc_target_flags[t] & _RF_B) != 0)
111#define RELOC_UNALIGNED(t)         ((reloc_target_flags[t] & _RF_U) != 0)
112#define RELOC_USE_ADDEND(t)        ((reloc_target_flags[t] & _RF_A) != 0)
113#define RELOC_TARGET_SIZE(t)       ((reloc_target_flags[t] >> 8) & 0xff)
114#define RELOC_VALUE_RIGHTSHIFT(t)  (reloc_target_flags[t] & 0xff)
115
116static const int reloc_target_bitmask[] = {
117#define _BM(x)  (~(-(1ULL << (x))))
118  0,        /* NONE */
119  _BM(8),  _BM(16), _BM(32),  /* RELOC_8, _16, _32 */
120  _BM(8),  _BM(16), _BM(32),  /* DISP8, DISP16, DISP32 */
121  _BM(30), _BM(22),           /* WDISP30, WDISP22 */
122  _BM(22), _BM(22),           /* HI22, _22 */
123  _BM(13), _BM(10),           /* RELOC_13, _LO10 */
124  _BM(10), _BM(13), _BM(22),  /* GOT10, GOT13, GOT22 */
125  _BM(10), _BM(22),           /* _PC10, _PC22 */
126  _BM(30), 0,                 /* _WPLT30, _COPY */
127  -1, -1, -1,                 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
128  _BM(32)                     /* _UA32 */
129#undef _BM
130};
131#define RELOC_VALUE_BITMASK(t)  (reloc_target_bitmask[t])
132
133uint32_t
134rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj,
135                             const Elf_Shdr*        shdr)
136{
137  return 0;
138}
139
140bool
141rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
142{
143  return RELOC_RESOLVE_SYMBOL (type) ? true : false;
144}
145
146bool
147rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t*      obj,
148                             const Elf_Rela*             rela,
149                             const rtems_rtl_obj_sect_t* sect,
150                             const char*                 symname,
151                             const Elf_Byte              syminfo,
152                             const Elf_Word              symvalue)
153{
154  Elf_Addr *where;
155  Elf_Word type, value, mask;
156  Elf_Addr tmp = 0;
157
158  where = (Elf_Addr *) (sect->base + rela->r_offset);
159
160  type = ELF_R_TYPE(rela->r_info);
161  if (type == R_TYPE(NONE))
162    return true;
163
164  /* We do JMP_SLOTs in _rtld_bind() below */
165  if (type == R_TYPE(JMP_SLOT))
166    return true;
167
168  /* COPY relocs are also handled elsewhere */
169  if (type == R_TYPE(COPY))
170    return true;
171
172  /*
173   * We use the fact that relocation types are an `enum'
174   * Note: R_SPARC_6 is currently numerically largest.
175   */
176  if (type > R_TYPE(6))
177    return false;
178
179  value = rela->r_addend;
180
181  /*
182   * Handle relative relocs here, as an optimization.
183   */
184  if (type == R_TYPE (RELATIVE)) {
185    *where += (Elf_Addr)(sect->base + value);
186    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
187      printf ("rtl: reloc relative in %s --> %p",
188              rtems_rtl_obj_oname (obj), (void *)*where);
189    return true;
190  }
191
192  if (RELOC_RESOLVE_SYMBOL (type)) {
193    /* Add in the symbol's absolute address */
194    value += symvalue;
195  }
196
197  if (RELOC_PC_RELATIVE (type)) {
198    value -= (Elf_Word)where;
199  }
200
201  if (RELOC_BASE_RELATIVE (type)) {
202    /*
203     * Note that even though sparcs use `Elf_rela'
204     * exclusively we still need the implicit memory addend
205     * in relocations referring to GOT entries.
206     * Undoubtedly, someone f*cked this up in the distant
207     * past, and now we're stuck with it in the name of
208     * compatibility for all eternity..
209     *
210     * In any case, the implicit and explicit should be
211     * mutually exclusive. We provide a check for that
212     * here.
213     */
214#define DIAGNOSTIC
215#ifdef DIAGNOSTIC
216    if (value != 0 && *where != 0) {
217      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
218        printf("rtl: reloc base_rel(%s): where=%p, *where 0x%lx, "
219               "addend=0x%lx, base %p\n",
220               rtems_rtl_obj_oname (obj),
221               where, *where, rela->r_addend, sect->base);
222    }
223#endif
224    value += (Elf_Word)(sect->base + *where);
225  }
226
227  mask = RELOC_VALUE_BITMASK (type);
228  value >>= RELOC_VALUE_RIGHTSHIFT (type);
229  value &= mask;
230
231  if (RELOC_UNALIGNED(type)) {
232    /*
233     * Handle unaligned relocations.
234     */
235    char *ptr = (char*) where;
236    int i, size = RELOC_TARGET_SIZE (type) / 8;
237
238    /* Read it in one byte at a time. */
239    for (i = size - 1; i >= 0; i--)
240      tmp = (tmp << 8) | ptr[i];
241
242    tmp &= ~mask;
243    tmp |= value;
244
245    /* Write it back out. */
246    for (i = size - 1; i >= 0; i--, tmp >>= 8)
247      ptr[i] = tmp & 0xff;
248  } else {
249    *where &= ~mask;
250    *where |= value;
251    tmp = *where;
252  }
253
254  if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
255    printf ("rtl: %s %p @ %p in %s\n",
256            reloc_names[ELF_R_TYPE(rela->r_info)],
257            (void *)tmp, where, rtems_rtl_obj_oname (obj));
258
259  return true;
260}
261
262bool
263rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t*      obj,
264                            const Elf_Rel*              rel,
265                            const rtems_rtl_obj_sect_t* sect,
266                            const char*                 symname,
267                            const Elf_Byte              syminfo,
268                            const Elf_Word              symvalue)
269{
270  printf ("rtl: rel type record not supported; please report\n");
271  return false;
272}
273
274bool
275rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj,
276                            const char*            name,
277                            uint32_t               flags)
278{
279  return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
280}
281
282bool
283rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj)
284{
285  return rtems_rtl_elf_unwind_dw2_register (obj);
286}
287
288bool
289rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj)
290{
291  return rtems_rtl_elf_unwind_dw2_deregister (obj);
292}
Note: See TracBrowser for help on using the repository browser.