source: rtems/cpukit/libdl/rtl-mdreloc-powerpc.c @ 4408603

Last change on this file since 4408603 was f59d435d, checked in by Chris Johns <chrisj@…>, on Apr 12, 2018 at 7:46:49 AM

libdl: Remove _t from all structures as this is reserved for the standards

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
3 */
4
5/*  $NetBSD: ppc_reloc.c,v 1.44 2010/01/13 20:17:22 christos Exp $  */
6
7#include <sys/cdefs.h>
8
9#include <errno.h>
10#include <inttypes.h>
11#include <stdio.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14
15#include <rtems/rtl/rtl.h>
16#include "rtl-elf.h"
17#include "rtl-error.h"
18#include <rtems/rtl/rtl-trace.h>
19#include "rtl-unwind.h"
20#include "rtl-unwind-dw2.h"
21
22#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
23                 ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
24#define l(x) ((u_int32_t)(x) & 0xffff)
25
26uint32_t
27rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
28                             const Elf_Shdr*      shdr)
29{
30  return 0;
31}
32
33bool
34rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
35{
36  return true;
37}
38
39bool
40rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
41                             const Elf_Rela*           rela,
42                             const rtems_rtl_obj_sect* sect,
43                             const char*               symname,
44                             const Elf_Byte            syminfo,
45                             const Elf_Word            symvalue)
46{
47  Elf_Addr* where;
48  Elf_Word tmp;
49  uint32_t mask = 0;
50  uint32_t bits = 0;
51
52  where = (Elf_Addr *)(sect->base + rela->r_offset);
53  switch (ELF_R_TYPE(rela->r_info)) {
54    case R_TYPE(NONE):
55      break;
56
57    case R_TYPE(32):
58      /*
59       * value:1; Field: word32; Expression: S + A
60       */
61      *where = symvalue + rela->r_addend;
62      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
63        printf ("rtl: ADDR32 %p @ %p in %s\n",
64                (void *)*(where), where, rtems_rtl_obj_oname (obj));
65      break;
66
67    case R_TYPE(14):
68      /*
69       * value:7; Field: low14*; Expression: (S + A) >> 2
70       */
71    case R_TYPE(24):
72      /*
73       * value:2; Field: low24*; Expression: (S + A) >> 2
74       */
75      if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) {
76        bits = 14;
77        mask = 0xfffc;
78      } else {
79        bits = 24;
80        mask = 0x3fffffc;
81      }
82      tmp = (symvalue + rela->r_addend) >> 2;
83      if (tmp > ((1<<bits) - 1 )) {
84        printf("Overflow ADDR14/ADDR24\n");
85        return false;
86      }
87      tmp = *where;
88      tmp &= ~mask;
89      tmp |= (symvalue + rela->r_addend) & mask;
90      *where = tmp;
91      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
92        printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
93                (void *)*where, where, rtems_rtl_obj_oname (obj));
94      break;
95
96    case R_TYPE(16_HA):
97      /*
98       * value:6; Field:half16; Expression: #ha(S+A)
99       */
100
101      tmp = symvalue + rela->r_addend;
102      *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
103      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
104        printf ("rtl: 16_HA %p @ %p in %s\n",
105                (void *)*(where), where, rtems_rtl_obj_oname (obj));
106      break;
107
108    case R_TYPE(16_HI):
109      /*
110       * value:5; Field:half16; Expression: #hi(S+A)
111       */
112      *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
113      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
114        printf ("rtl: 16_HI %p @ %p in %s\n",
115                (void *)*where, where, rtems_rtl_obj_oname (obj));
116      break;
117    case R_TYPE(16_LO):
118      /*
119       * value:4; Field:half16; Expression: #lo(S+A)
120       */
121      *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
122      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
123        printf ("rtl: 16_LO %p @ %p in %s\n",
124                (void *)*where, where, rtems_rtl_obj_oname (obj));
125      break;
126
127    case R_TYPE(REL14):
128      /*
129       * value:11; Field:low14*; Expression:(S+A-P)>>2
130       */
131    case R_TYPE(REL24):
132      /*
133       * value:10; Field:low24*; Expression:(S+A-P)>>2
134       */
135      if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) {
136        mask = 0x3fffffc;
137        bits = 24;
138      }
139      else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) {
140        mask = 0xfffc;
141        bits = 14;
142      }
143
144      tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
145      if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
146          ((Elf_Sword)tmp < -(1<<(bits-1)))) {
147        printf("Overflow REL14/REL24\n");
148        return false;
149      }
150
151      tmp = *where;
152      tmp &= ~mask;
153      tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
154      *where = tmp;
155      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
156        printf ("rtl: REL24/REL14 %p @ %p in %s\n",
157                (void *)*where, where, rtems_rtl_obj_oname (obj));
158      break;
159
160    case R_TYPE(REL32):
161      /*
162       * value:26; Field:word32*; Expression:S+A-P
163       */
164      *where = symvalue + rela->r_addend - (Elf_Addr)where;
165      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
166        printf ("rtl: REL32 %p @ %p in %s\n",
167                (void *)*where, where, rtems_rtl_obj_oname (obj));
168      break;
169
170    case R_TYPE(SDAREL16):
171      /*
172       * A sign-extended 16 bit value relative to _SDA_BASE_, for use with
173       * small data items.
174       */
175      mask = 0xffff;
176      tmp = *((Elf32_Half*) where);
177      tmp &= ~mask;
178      tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
179      *((Elf32_Half*) where) = tmp;
180      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
181        printf ("rtl: SDAREL16 %p @ %p in %s\n",
182                (void *) (uintptr_t) *((Elf32_Half*) where),
183                where, rtems_rtl_obj_oname (obj));
184      break;
185
186    default:
187      printf ("rtl: reloc unknown: sym = %lu, type = %" PRIu32 ", offset = %p, "
188              "contents = %p\n",
189              ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
190              (void *)rela->r_offset, (void *)*where);
191      rtems_rtl_set_error (EINVAL,
192                           "%s: Unsupported relocation type %" PRId32
193                           "in non-PLT relocations",
194                           sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
195      return false;
196  }
197  return true;
198}
199
200bool
201rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
202                            const Elf_Rel*            rel,
203                            const rtems_rtl_obj_sect* sect,
204                            const char*               symname,
205                            const Elf_Byte            syminfo,
206                            const Elf_Word            symvalue)
207{
208  printf ("rtl: rel type record not supported; please report\n");
209  return false;
210}
211
212bool
213rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
214                            const char*          name,
215                            uint32_t             flags)
216{
217  return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
218}
219
220bool
221rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj)
222{
223  return rtems_rtl_elf_unwind_dw2_register (obj);
224}
225
226bool
227rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj)
228{
229  return rtems_rtl_elf_unwind_dw2_deregister (obj);
230}
Note: See TracBrowser for help on using the repository browser.