source: rtems/cpukit/libdl/rtl-mdreloc-mips.c @ 194eb403

5
Last change on this file since 194eb403 was d8c70ba6, checked in by Chris Johns <chrisj@…>, on 01/15/19 at 06:47:41

libdl: Add support for trampolines

  • Trampolines or fixups for veneers provide long jump support for instruciton sets that implement short relative address branches. The linker provides trampolines when creating a static image. This patch adds trampoline support to libdl and the ARM architecture.
  • The dl09 test requires enough memory so modules are outside the relative branch instruction ranges for the architecture.

Updates #3685

  • Property mode set to 100644
File size: 7.2 KB
Line 
1#include <sys/cdefs.h>
2
3#include <errno.h>
4#include <stdio.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7
8#include <rtems/rtl/rtl.h>
9#include "rtl-elf.h"
10#include "rtl-error.h"
11#include <rtems/rtl/rtl-trace.h>
12#include "rtl-unwind.h"
13#include "rtl-unwind-dw2.h"
14
15uint32_t
16rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
17                             const Elf_Shdr*      shdr)
18{
19  return 0;
20}
21
22bool
23rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
24{
25  return true;
26}
27
28size_t
29rtems_rtl_elf_relocate_tramp_max_size (void)
30{
31  /*
32   * Disable by returning 0.
33   */
34  return 0;
35}
36
37bool
38rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
39                                   const Elf_Rela*           rela,
40                                   const rtems_rtl_obj_sect* sect,
41                                   const char*               symname,
42                                   const Elf_Byte            syminfo,
43                                   const Elf_Word            symvalue)
44{
45  (void) obj;
46  (void) rela;
47  (void) sect;
48  (void) symname;
49  (void) syminfo;
50  (void) symvalue;
51  rtems_rtl_set_error (EINVAL, "rela type record not supported");
52  return false;
53}
54
55bool
56rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
57                             const Elf_Rela*           rela,
58                             const rtems_rtl_obj_sect* sect,
59                             const char*               symname,
60                             const Elf_Byte            syminfo,
61                             const Elf_Word            symvalue)
62{
63  (void) obj;
64  (void) rela;
65  (void) sect;
66  (void) symname;
67  (void) syminfo;
68  (void) symvalue;
69  rtems_rtl_set_error (EINVAL, "rela type record not supported");
70  return false;
71}
72
73bool
74rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
75                                  const Elf_Rel*            rel,
76                                  const rtems_rtl_obj_sect* sect,
77                                  const char*               symname,
78                                  const Elf_Byte            syminfo,
79                                  const Elf_Word            symvalue)
80{
81  (void) obj;
82  (void) rel;
83  (void) sect;
84  (void) symname;
85  (void) syminfo;
86  (void) symvalue;
87  return true;
88}
89
90/*
91 * 1. _gp_disp symbol are not considered in this file.
92 * 2. There is a local/external column;
93 * local corresponds to (STB_LOCAL & STT_SECTION) and
94 * all others are external. Because if the type of a
95 * symbol is STT_SECTION, it must be STB_LOCAL. Thus
96 * just consider symtype here.
97 */
98bool
99rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
100                            const Elf_Rel*            rel,
101                            const rtems_rtl_obj_sect* sect,
102                            const char*               symname,
103                            const Elf_Byte            syminfo,
104                            const Elf_Word            symvalue)
105{
106  Elf_Addr *where;
107  Elf_Word  tmp;
108  Elf_Word addend = (Elf_Word)0;
109  Elf_Word local = 0;
110  uint32_t t;
111
112
113  static Elf_Addr *where_hi16;
114  static Elf_Addr ahl;
115
116  where = (Elf_Addr *)(sect->base + rel->r_offset);
117  addend = *where;
118
119  if (syminfo == STT_SECTION)
120    local = 1;
121
122  switch (ELF_R_TYPE(rel->r_info)) {
123    case R_TYPE(NONE):
124      break;
125
126    case R_TYPE(16):
127      tmp = addend & 0xffff;
128      if ((tmp & 0x8000) == 0x8000)
129        tmp |= 0xffff0000; /* Sign extend */
130      tmp = symvalue + (int)tmp;
131      if ((tmp & 0xffff0000) != 0) {
132        printf("R_MIPS_16 Overflow\n");
133        return false;
134      }
135
136      *where = (tmp & 0xffff) | (*where & 0xffff0000);
137
138      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
139        printf ("rtl: R_MIPS_16 %p @ %p in %s\n",
140                (void *)*(where), where, rtems_rtl_obj_oname (obj));
141      break;
142
143    case R_TYPE(32):
144      tmp = symvalue + addend;
145      if (addend != tmp)
146        *where = tmp;
147
148      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
149        printf ("rtl: R_MIPS_32 %p @ %p in %s\n",
150                (void *)*(where), where, rtems_rtl_obj_oname (obj));
151      break;
152
153    case R_TYPE(26):
154
155        addend &= 0x03ffffff;
156        addend <<= 2;
157
158      if (local == 1) { /* STB_LOCAL and STT_SECTION */
159        tmp = symvalue + (((Elf_Addr)where & 0xf0000000) | addend);
160        tmp >>= 2;
161
162      } else { /* external */
163
164        tmp = addend;
165
166        if ((tmp & 0x08000000) == 0x08000000)
167          tmp |= 0xf0000000; /* Sign extened */
168        tmp = ((int)tmp + symvalue) >> 2;
169
170      }
171
172      *where &= ~0x03ffffff;
173      *where |= tmp & 0x03ffffff;
174
175      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
176        printf ("rtl: R_MIPS_26 local=%lu @ %p in %s\n",
177                local, (void *)*(where), rtems_rtl_obj_oname (obj));
178      break;
179
180    case R_TYPE(HI16):
181      ahl = addend << 16;
182      where_hi16 = where;
183
184
185      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
186        printf ("rtl: R_MIPS_HI16 %p @ %p in %s\n",
187                (void *)*(where), where, rtems_rtl_obj_oname (obj));
188      break;
189
190    case R_TYPE(LO16):
191      //ahl += (int16_t)addend;
192      t = ahl + (int16_t)addend;
193      tmp = symvalue;
194      if (tmp == 0)
195        return false;
196
197      addend &= 0xffff0000;
198      addend |= (uint16_t)(t + tmp);
199      *where = addend;
200
201      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
202        printf("*where %lx where %p\n", *where, where);
203
204      addend = *where_hi16;
205      addend &= 0xffff0000;
206      addend |= ((t + tmp) - (int16_t)(t + tmp)) >> 16;
207      *where_hi16 = addend;
208
209      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
210        printf("*where_hi %lx where_hi %p\n", *where_hi16, where_hi16);
211
212      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
213        printf ("rtl: R_MIPS_LO16 %p @ %p in %s\n",
214                (void *)*(where), where, rtems_rtl_obj_oname (obj));
215      break;
216
217    case R_TYPE(PC16):
218      tmp = addend & 0xffff;
219      if ((tmp & 0x8000) == 0x8000)
220        tmp |= 0xffff0000; /* Sign extend */
221      tmp = symvalue + ((int)tmp*4) - (Elf_Addr)where;
222      tmp = (Elf_Sword)tmp >> 2;
223      if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
224        printf("R_MIPS_PC16 Overflow\n");
225        return false;
226      }
227
228      *where = (tmp & 0xffff) | (*where & 0xffff0000);
229
230      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
231        printf ("rtl: R_MIPS_PC16 %p @ %p in %s\n",
232                (void *)*(where), where, rtems_rtl_obj_oname (obj));
233
234      break;
235
236    default:
237      printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
238              "contents = %p\n",
239              ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
240              (void *)rel->r_offset, (void *)*where);
241      rtems_rtl_set_error (EINVAL,
242                           "%s: Unsupported relocation type %ld "
243                           "in non-PLT relocations",
244                           sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
245      return false;
246  }
247
248  return true;
249}
250
251bool
252rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
253                            const char*          name,
254                            uint32_t             flags)
255{
256  return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
257}
258
259bool
260rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj)
261{
262  return rtems_rtl_elf_unwind_dw2_register (obj);
263}
264
265bool
266rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj)
267{
268  return rtems_rtl_elf_unwind_dw2_deregister (obj);
269}
Note: See TracBrowser for help on using the repository browser.