[ae5fe7e6] | 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> |
---|
[8bdbefe] | 10 | #include <inttypes.h> |
---|
[ae5fe7e6] | 11 | #include <stdio.h> |
---|
| 12 | #include <sys/types.h> |
---|
| 13 | #include <sys/stat.h> |
---|
| 14 | |
---|
| 15 | #include <rtems/rtl/rtl.h> |
---|
[6c9f017] | 16 | #include "rtl-bit-alloc.h" |
---|
[ae5fe7e6] | 17 | #include "rtl-elf.h" |
---|
| 18 | #include "rtl-error.h" |
---|
[990adc5] | 19 | #include <rtems/rtl/rtl-trace.h> |
---|
[c6eead1] | 20 | #include "rtl-unwind.h" |
---|
| 21 | #include "rtl-unwind-dw2.h" |
---|
[ae5fe7e6] | 22 | |
---|
| 23 | #define ha(x) ((((u_int32_t)(x) & 0x8000) ? \ |
---|
| 24 | ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) |
---|
| 25 | #define l(x) ((u_int32_t)(x) & 0xffff) |
---|
| 26 | |
---|
[6c9f017] | 27 | /* |
---|
| 28 | * SDATA allocator. |
---|
| 29 | */ |
---|
| 30 | static rtems_rtl_bit_alloc* sdata; |
---|
| 31 | |
---|
| 32 | static Elf_Addr |
---|
| 33 | get_sda_base (void) |
---|
| 34 | { |
---|
| 35 | uint32_t sda_base; |
---|
| 36 | __asm__ volatile (" mr %0, 13\n" : "=r" (sda_base)); |
---|
| 37 | return sda_base; |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | /* |
---|
| 41 | * Access the variables via asm statements to avoid any fix up issues |
---|
| 42 | * generated by the C compiler which thinks they belong in the .sdata |
---|
| 43 | * section. |
---|
| 44 | */ |
---|
| 45 | |
---|
| 46 | #define GET_ADDR(_l, _v) \ |
---|
| 47 | __asm__ volatile (" lis %0, " #_l "@h\n" \ |
---|
| 48 | " ori %0, %0, " #_l "@l\n" : "=r" (_v)) |
---|
| 49 | |
---|
| 50 | static void* |
---|
| 51 | get_sdata_start (void) |
---|
| 52 | { |
---|
[ec1dd51a] | 53 | #if _ARCH_PPC64 |
---|
| 54 | return NULL; |
---|
| 55 | #else |
---|
[6c9f017] | 56 | Elf_Addr addr; |
---|
| 57 | GET_ADDR(__SDATA_START__, addr); |
---|
| 58 | return (void*) addr; |
---|
[ec1dd51a] | 59 | #endif |
---|
[6c9f017] | 60 | } |
---|
| 61 | |
---|
[ec1dd51a] | 62 | #if !_ARCH_PPC64 |
---|
[6c9f017] | 63 | static size_t |
---|
| 64 | get_sdata_sbss_size (void) |
---|
| 65 | { |
---|
| 66 | Elf_Addr sdata_begin; |
---|
| 67 | Elf_Addr sbss_end; |
---|
| 68 | GET_ADDR(bsp_section_sdata_begin, sdata_begin); |
---|
| 69 | GET_ADDR(bsp_section_sbss_end, sbss_end); |
---|
| 70 | return sbss_end - sdata_begin; |
---|
| 71 | } |
---|
| 72 | |
---|
| 73 | static size_t |
---|
| 74 | get_sdata_libdl_size (void) |
---|
| 75 | { |
---|
| 76 | Elf_Addr begin; |
---|
| 77 | Elf_Addr end; |
---|
| 78 | GET_ADDR(bsp_section_sdata_libdl_begin, begin); |
---|
| 79 | GET_ADDR(bsp_section_sdata_libdl_end, end); |
---|
| 80 | return end - begin; |
---|
| 81 | } |
---|
[ec1dd51a] | 82 | #endif |
---|
[6c9f017] | 83 | |
---|
[c6eead1] | 84 | uint32_t |
---|
[f59d435d] | 85 | rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj, |
---|
| 86 | const Elf_Shdr* shdr) |
---|
[c6eead1] | 87 | { |
---|
| 88 | return 0; |
---|
| 89 | } |
---|
[ae5fe7e6] | 90 | |
---|
[6c9f017] | 91 | uint32_t |
---|
| 92 | rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj, |
---|
| 93 | int section, |
---|
| 94 | const char* name, |
---|
| 95 | const Elf_Shdr* shdr, |
---|
| 96 | const uint32_t flags) |
---|
| 97 | { |
---|
[ec1dd51a] | 98 | #if !_ARCH_PPC64 |
---|
[6c9f017] | 99 | struct { |
---|
| 100 | const char* label; |
---|
| 101 | size_t len; |
---|
| 102 | } prefix[] = { |
---|
| 103 | #define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 } |
---|
| 104 | SEPARATED_PREFIX (".sdata"), |
---|
| 105 | SEPARATED_PREFIX (".sbss"), |
---|
| 106 | }; |
---|
| 107 | const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]); |
---|
| 108 | size_t p; |
---|
| 109 | for (p = 0; p < prefixes; ++p) |
---|
| 110 | { |
---|
| 111 | if (strncmp (name, prefix[p].label, prefix[p].len) == 0) |
---|
| 112 | return flags | RTEMS_RTL_OBJ_SECT_ARCH_ALLOC; |
---|
| 113 | } |
---|
[ec1dd51a] | 114 | #endif |
---|
[6c9f017] | 115 | return flags; |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | bool |
---|
| 119 | rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj, |
---|
| 120 | rtems_rtl_obj_sect* sect) |
---|
| 121 | { |
---|
[ec1dd51a] | 122 | #if _ARCH_PPC64 |
---|
| 123 | rtems_rtl_set_error (ENOMEM, ".sdata no supported by ABI"); |
---|
| 124 | return false; |
---|
| 125 | #else |
---|
[6c9f017] | 126 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) |
---|
| 127 | printf ("rtl: section: arch: alloc: name=%s size=%zu flags=%08" PRIx32 \ |
---|
| 128 | " order=%i link=%d info=%d\n", |
---|
| 129 | sect->name, sect->size, sect->flags, sect->load_order, |
---|
| 130 | sect->link, sect->info); |
---|
| 131 | |
---|
| 132 | if (sdata == NULL) |
---|
| 133 | { |
---|
| 134 | sdata = rtems_rtl_bit_alloc_open (get_sdata_start (), |
---|
| 135 | get_sdata_libdl_size (), |
---|
| 136 | sizeof (uint32_t), |
---|
| 137 | get_sdata_sbss_size ()); |
---|
| 138 | if (sdata == NULL) |
---|
| 139 | { |
---|
| 140 | rtems_rtl_set_error (ENOMEM, "no memory for sdata allocator"); |
---|
| 141 | return false; |
---|
| 142 | } |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | sect->base = rtems_rtl_bit_alloc_balloc (sdata, sect->size); |
---|
| 146 | if (sect->base == NULL) |
---|
| 147 | { |
---|
| 148 | rtems_rtl_set_error (ENOMEM, "no .sdata memory: %s", sect->name); |
---|
| 149 | return false; |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | return true; |
---|
[ec1dd51a] | 153 | #endif |
---|
[6c9f017] | 154 | } |
---|
| 155 | |
---|
| 156 | bool |
---|
| 157 | rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj, |
---|
| 158 | rtems_rtl_obj_sect* sect) |
---|
| 159 | { |
---|
[ec1dd51a] | 160 | #if !_ARCH_PPC64 |
---|
[6c9f017] | 161 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) |
---|
| 162 | printf ("rtl: section: arch: free: name=%s size=%zu\n", sect->name, sect->size); |
---|
| 163 | if (sdata != NULL) |
---|
| 164 | rtems_rtl_bit_alloc_bfree (sdata, sect->base, sect->size); |
---|
[ec1dd51a] | 165 | #endif |
---|
[6c9f017] | 166 | return true; |
---|
| 167 | } |
---|
| 168 | |
---|
[ae5fe7e6] | 169 | bool |
---|
| 170 | rtems_rtl_elf_rel_resolve_sym (Elf_Word type) |
---|
| 171 | { |
---|
| 172 | return true; |
---|
| 173 | } |
---|
| 174 | |
---|
[d8c70ba6] | 175 | size_t |
---|
| 176 | rtems_rtl_elf_relocate_tramp_max_size (void) |
---|
| 177 | { |
---|
| 178 | /* |
---|
[6c9f017] | 179 | * We have 4 instructions and each instruction is 32bits. |
---|
[d8c70ba6] | 180 | */ |
---|
[6c9f017] | 181 | return 4 * 4; |
---|
[d8c70ba6] | 182 | } |
---|
| 183 | |
---|
[6c9f017] | 184 | static void* |
---|
| 185 | set_veneer (void* tramopline, Elf_Addr target) |
---|
[d8c70ba6] | 186 | { |
---|
[6c9f017] | 187 | /* |
---|
| 188 | * http://shell-storm.org/online/Online-Assembler-and-Disassembler/ |
---|
| 189 | * |
---|
| 190 | * lis 12,0x1234 |
---|
| 191 | * ori 12,12,0x5678 |
---|
| 192 | * mtctr 12 |
---|
| 193 | * bctr |
---|
| 194 | */ |
---|
| 195 | #if COMPILE_ASM |
---|
| 196 | asm volatile (" lis 12,0x1234\n" \ |
---|
| 197 | " ori 12,12,0x5678\n" \ |
---|
| 198 | " mtctr 12\n" \ |
---|
| 199 | " bctr\n"); |
---|
| 200 | #endif |
---|
| 201 | uint32_t* tramp = (uint32_t*) tramopline; |
---|
| 202 | *tramp++ = 0x3d800000 | (target >> 16); |
---|
| 203 | *tramp++ = 0x618c0000 | (target & 0xffff); |
---|
| 204 | *tramp++ = 0x7d8903a6; |
---|
| 205 | *tramp++ = 0x4e800420; |
---|
| 206 | return tramp; |
---|
[d8c70ba6] | 207 | } |
---|
| 208 | |
---|
[6c9f017] | 209 | static size_t |
---|
| 210 | get_veneer_size (int type) |
---|
| 211 | { |
---|
| 212 | (void) type; |
---|
| 213 | return rtems_rtl_elf_relocate_tramp_max_size (); |
---|
| 214 | } |
---|
| 215 | |
---|
[b36c5209] | 216 | /** |
---|
| 217 | * The offsets in the reloc words. |
---|
| 218 | */ |
---|
| 219 | #define REL_R_OFFSET (0) |
---|
| 220 | #define REL_R_INFO (1) |
---|
| 221 | #define REL_R_ADDEND (2) |
---|
| 222 | |
---|
| 223 | static rtems_rtl_elf_rel_status |
---|
[6c9f017] | 224 | rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj, |
---|
| 225 | const Elf_Rela* rela, |
---|
| 226 | const rtems_rtl_obj_sect* sect, |
---|
| 227 | const char* symname, |
---|
| 228 | const Elf_Byte syminfo, |
---|
| 229 | const Elf_Word symvalue, |
---|
| 230 | const bool parsing) |
---|
[ae5fe7e6] | 231 | { |
---|
| 232 | Elf_Addr* where; |
---|
| 233 | Elf_Word tmp; |
---|
| 234 | uint32_t mask = 0; |
---|
| 235 | uint32_t bits = 0; |
---|
[b36c5209] | 236 | bool needs_tramp = false; |
---|
[ae5fe7e6] | 237 | |
---|
| 238 | where = (Elf_Addr *)(sect->base + rela->r_offset); |
---|
| 239 | switch (ELF_R_TYPE(rela->r_info)) { |
---|
| 240 | case R_TYPE(NONE): |
---|
| 241 | break; |
---|
| 242 | |
---|
| 243 | case R_TYPE(32): |
---|
| 244 | /* |
---|
| 245 | * value:1; Field: word32; Expression: S + A |
---|
| 246 | */ |
---|
[6c9f017] | 247 | if (!parsing) { |
---|
| 248 | *where = symvalue + rela->r_addend; |
---|
| 249 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 250 | printf ("rtl: ADDR32 %p @ %p in %s\n", |
---|
| 251 | (void *)*(where), where, rtems_rtl_obj_oname (obj)); |
---|
| 252 | } |
---|
[ae5fe7e6] | 253 | break; |
---|
| 254 | |
---|
| 255 | case R_TYPE(14): |
---|
| 256 | /* |
---|
| 257 | * value:7; Field: low14*; Expression: (S + A) >> 2 |
---|
| 258 | */ |
---|
| 259 | case R_TYPE(24): |
---|
| 260 | /* |
---|
| 261 | * value:2; Field: low24*; Expression: (S + A) >> 2 |
---|
| 262 | */ |
---|
| 263 | if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) { |
---|
| 264 | bits = 14; |
---|
| 265 | mask = 0xfffc; |
---|
| 266 | } else { |
---|
| 267 | bits = 24; |
---|
| 268 | mask = 0x3fffffc; |
---|
| 269 | } |
---|
[b36c5209] | 270 | |
---|
| 271 | if (parsing && sect->base == 0) { |
---|
| 272 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 273 | printf ("rtl: ADDR14/ADDR24 tramp cache\n"); |
---|
| 274 | return rtems_rtl_elf_rel_tramp_cache; |
---|
| 275 | } |
---|
| 276 | |
---|
[ae5fe7e6] | 277 | tmp = (symvalue + rela->r_addend) >> 2; |
---|
[a5201ea] | 278 | if (tmp > ((1<<bits) - 1 )) { |
---|
[6c9f017] | 279 | Elf_Word tramp_addr; |
---|
| 280 | size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info)); |
---|
| 281 | if (parsing) { |
---|
[b36c5209] | 282 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 283 | printf ("rtl: ADDR14/ADDR24 tramp add\n"); |
---|
| 284 | return rtems_rtl_elf_rel_tramp_add; |
---|
| 285 | } |
---|
| 286 | if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) { |
---|
| 287 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 288 | printf ("rtl: ADDR14/ADDR24 no tramp slot: %s\n", rtems_rtl_obj_oname (obj)); |
---|
| 289 | rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: ADDR14/ADDR24", sect->name); |
---|
| 290 | return rtems_rtl_elf_rel_failure; |
---|
[6c9f017] | 291 | } |
---|
[b36c5209] | 292 | needs_tramp = true; |
---|
[6c9f017] | 293 | tramp_addr = (Elf_Addr) obj->tramp_brk; |
---|
| 294 | obj->tramp_brk = set_veneer(obj->tramp_brk, |
---|
| 295 | symvalue + rela->r_addend); |
---|
| 296 | tmp = *where; |
---|
| 297 | tmp &= ~mask; |
---|
| 298 | tmp |= (tramp_addr + rela->r_addend) & mask; |
---|
| 299 | } |
---|
| 300 | else { |
---|
| 301 | tmp = *where; |
---|
| 302 | tmp &= ~mask; |
---|
| 303 | tmp |= (symvalue + rela->r_addend) & mask; |
---|
| 304 | } |
---|
| 305 | |
---|
| 306 | if (!parsing) { |
---|
| 307 | *where = tmp; |
---|
| 308 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
[b36c5209] | 309 | printf ("rtl: ADDR14/ADDR24%s %p @ %p in %s\n", |
---|
| 310 | needs_tramp ? "(tramp)" : "", |
---|
[6c9f017] | 311 | (void *)*where, where, rtems_rtl_obj_oname (obj)); |
---|
[ae5fe7e6] | 312 | } |
---|
| 313 | break; |
---|
| 314 | |
---|
| 315 | case R_TYPE(16_HA): |
---|
| 316 | /* |
---|
| 317 | * value:6; Field:half16; Expression: #ha(S+A) |
---|
| 318 | */ |
---|
[6c9f017] | 319 | if (!parsing) { |
---|
| 320 | tmp = symvalue + rela->r_addend; |
---|
| 321 | *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff); |
---|
| 322 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 323 | printf ("rtl: 16_HA %p @ %p in %s\n", |
---|
| 324 | (void *)*(where), where, rtems_rtl_obj_oname (obj)); |
---|
| 325 | } |
---|
[ae5fe7e6] | 326 | break; |
---|
| 327 | |
---|
| 328 | case R_TYPE(16_HI): |
---|
| 329 | /* |
---|
| 330 | * value:5; Field:half16; Expression: #hi(S+A) |
---|
| 331 | */ |
---|
[6c9f017] | 332 | if (!parsing) { |
---|
| 333 | *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff; |
---|
| 334 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 335 | printf ("rtl: 16_HI %p @ %p in %s\n", |
---|
| 336 | (void *)*where, where, rtems_rtl_obj_oname (obj)); |
---|
| 337 | } |
---|
[ae5fe7e6] | 338 | break; |
---|
| 339 | case R_TYPE(16_LO): |
---|
| 340 | /* |
---|
| 341 | * value:4; Field:half16; Expression: #lo(S+A) |
---|
| 342 | */ |
---|
[6c9f017] | 343 | if (!parsing) { |
---|
| 344 | *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff; |
---|
| 345 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 346 | printf ("rtl: 16_LO %p @ %p in %s\n", |
---|
| 347 | (void *)*where, where, rtems_rtl_obj_oname (obj)); |
---|
| 348 | } |
---|
[ae5fe7e6] | 349 | break; |
---|
| 350 | |
---|
| 351 | case R_TYPE(REL14): |
---|
| 352 | /* |
---|
| 353 | * value:11; Field:low14*; Expression:(S+A-P)>>2 |
---|
| 354 | */ |
---|
| 355 | case R_TYPE(REL24): |
---|
| 356 | /* |
---|
| 357 | * value:10; Field:low24*; Expression:(S+A-P)>>2 |
---|
| 358 | */ |
---|
| 359 | if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) { |
---|
| 360 | mask = 0x3fffffc; |
---|
| 361 | bits = 24; |
---|
| 362 | } |
---|
| 363 | else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) { |
---|
| 364 | mask = 0xfffc; |
---|
| 365 | bits = 14; |
---|
| 366 | } |
---|
| 367 | |
---|
[b36c5209] | 368 | if (parsing && sect->base == 0) { |
---|
| 369 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 370 | printf ("rtl: REL24/REL14 tramp cache\n"); |
---|
| 371 | return rtems_rtl_elf_rel_tramp_cache; |
---|
| 372 | } |
---|
| 373 | |
---|
[ae5fe7e6] | 374 | tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2; |
---|
| 375 | if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) || |
---|
| 376 | ((Elf_Sword)tmp < -(1<<(bits-1)))) { |
---|
[6c9f017] | 377 | Elf_Word tramp_addr; |
---|
| 378 | size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info)); |
---|
| 379 | if (parsing) { |
---|
[b36c5209] | 380 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 381 | printf ("rtl: REL24/REL14 tramp add\n"); |
---|
| 382 | return rtems_rtl_elf_rel_tramp_add; |
---|
| 383 | } |
---|
| 384 | if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) { |
---|
| 385 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 386 | printf ("rtl: REL24/REL14 no tramp slot: %s\n", rtems_rtl_obj_oname (obj)); |
---|
| 387 | rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: REL24/REL14", sect->name); |
---|
| 388 | return rtems_rtl_elf_rel_failure; |
---|
[6c9f017] | 389 | } |
---|
[b36c5209] | 390 | needs_tramp = true; |
---|
[6c9f017] | 391 | tramp_addr = (Elf_Addr) obj->tramp_brk; |
---|
| 392 | obj->tramp_brk = set_veneer(obj->tramp_brk, |
---|
| 393 | symvalue + rela->r_addend); |
---|
| 394 | tmp = *where; |
---|
| 395 | tmp &= ~mask; |
---|
| 396 | tmp |= (tramp_addr + rela->r_addend - (Elf_Addr)where) & mask; |
---|
| 397 | } |
---|
| 398 | else |
---|
| 399 | { |
---|
| 400 | tmp = *where; |
---|
| 401 | tmp &= ~mask; |
---|
| 402 | tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask; |
---|
[ae5fe7e6] | 403 | } |
---|
| 404 | |
---|
[6c9f017] | 405 | if (!parsing) { |
---|
| 406 | *where = tmp; |
---|
| 407 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
[b36c5209] | 408 | printf ("rtl: REL24/REL14%s %p @ %p in %s\n", |
---|
| 409 | needs_tramp ? "(tramp)" : "", |
---|
[6c9f017] | 410 | (void *)*where, where, rtems_rtl_obj_oname (obj)); |
---|
| 411 | } |
---|
[ae5fe7e6] | 412 | break; |
---|
| 413 | |
---|
| 414 | case R_TYPE(REL32): |
---|
| 415 | /* |
---|
| 416 | * value:26; Field:word32*; Expression:S+A-P |
---|
| 417 | */ |
---|
[6c9f017] | 418 | if (!parsing) { |
---|
| 419 | *where = symvalue + rela->r_addend - (Elf_Addr)where; |
---|
| 420 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 421 | printf ("rtl: REL32 %p @ %p in %s\n", |
---|
| 422 | (void *)*where, where, rtems_rtl_obj_oname (obj)); |
---|
| 423 | } |
---|
[ae5fe7e6] | 424 | break; |
---|
| 425 | |
---|
[c6eead1] | 426 | case R_TYPE(SDAREL16): |
---|
| 427 | /* |
---|
| 428 | * A sign-extended 16 bit value relative to _SDA_BASE_, for use with |
---|
| 429 | * small data items. |
---|
| 430 | */ |
---|
[6c9f017] | 431 | if (!parsing) { |
---|
| 432 | Elf_Addr sda_base = get_sda_base (); |
---|
| 433 | mask = 0xffff; |
---|
| 434 | tmp = *((Elf32_Half*) where); |
---|
| 435 | tmp &= ~mask; |
---|
| 436 | tmp |= (symvalue + rela->r_addend - sda_base) & mask; |
---|
| 437 | *((Elf32_Half*) where) = tmp; |
---|
| 438 | if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) |
---|
| 439 | printf ("rtl: SDAREL16 %p @ %p in %s\n", |
---|
| 440 | (void *) (uintptr_t) *((Elf32_Half*) where), |
---|
| 441 | where, rtems_rtl_obj_oname (obj)); |
---|
| 442 | } |
---|
[c6eead1] | 443 | break; |
---|
| 444 | |
---|
[ae5fe7e6] | 445 | default: |
---|
[6c9f017] | 446 | printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p, " |
---|
[ae5fe7e6] | 447 | "contents = %p\n", |
---|
| 448 | ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info), |
---|
| 449 | (void *)rela->r_offset, (void *)*where); |
---|
| 450 | rtems_rtl_set_error (EINVAL, |
---|
[8bdbefe] | 451 | "%s: Unsupported relocation type %" PRId32 |
---|
[ae5fe7e6] | 452 | "in non-PLT relocations", |
---|
| 453 | sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); |
---|
[b36c5209] | 454 | return rtems_rtl_elf_rel_failure; |
---|
[ae5fe7e6] | 455 | } |
---|
[b36c5209] | 456 | return rtems_rtl_elf_rel_no_error; |
---|
[ae5fe7e6] | 457 | } |
---|
| 458 | |
---|
[b36c5209] | 459 | rtems_rtl_elf_rel_status |
---|
[6c9f017] | 460 | rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, |
---|
| 461 | const Elf_Rela* rela, |
---|
| 462 | const rtems_rtl_obj_sect* sect, |
---|
| 463 | const char* symname, |
---|
| 464 | const Elf_Byte syminfo, |
---|
| 465 | const Elf_Word symvalue) |
---|
| 466 | { |
---|
| 467 | return rtems_rtl_elf_reloc_rela (obj, |
---|
| 468 | rela, |
---|
| 469 | sect, |
---|
| 470 | symname, |
---|
| 471 | syminfo, |
---|
| 472 | symvalue, |
---|
| 473 | true); |
---|
| 474 | } |
---|
| 475 | |
---|
[b36c5209] | 476 | rtems_rtl_elf_rel_status |
---|
[6c9f017] | 477 | rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj, |
---|
| 478 | const Elf_Rela* rela, |
---|
| 479 | const rtems_rtl_obj_sect* sect, |
---|
| 480 | const char* symname, |
---|
| 481 | const Elf_Byte syminfo, |
---|
| 482 | const Elf_Word symvalue) |
---|
| 483 | { |
---|
| 484 | return rtems_rtl_elf_reloc_rela (obj, |
---|
| 485 | rela, |
---|
| 486 | sect, |
---|
| 487 | symname, |
---|
| 488 | syminfo, |
---|
| 489 | symvalue, |
---|
| 490 | false); |
---|
| 491 | } |
---|
| 492 | |
---|
[b36c5209] | 493 | rtems_rtl_elf_rel_status |
---|
[d8c70ba6] | 494 | rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj, |
---|
| 495 | const Elf_Rel* rel, |
---|
| 496 | const rtems_rtl_obj_sect* sect, |
---|
| 497 | const char* symname, |
---|
| 498 | const Elf_Byte syminfo, |
---|
| 499 | const Elf_Word symvalue) |
---|
| 500 | { |
---|
| 501 | (void) obj; |
---|
| 502 | (void) rel; |
---|
| 503 | (void) sect; |
---|
| 504 | (void) symname; |
---|
| 505 | (void) syminfo; |
---|
| 506 | (void) symvalue; |
---|
| 507 | rtems_rtl_set_error (EINVAL, "rel type record not supported"); |
---|
[b36c5209] | 508 | return rtems_rtl_elf_rel_failure; |
---|
[d8c70ba6] | 509 | } |
---|
| 510 | |
---|
[b36c5209] | 511 | rtems_rtl_elf_rel_status |
---|
[d8c70ba6] | 512 | rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, |
---|
[f59d435d] | 513 | const Elf_Rel* rel, |
---|
| 514 | const rtems_rtl_obj_sect* sect, |
---|
| 515 | const char* symname, |
---|
| 516 | const Elf_Byte syminfo, |
---|
| 517 | const Elf_Word symvalue) |
---|
[ae5fe7e6] | 518 | { |
---|
[d8c70ba6] | 519 | (void) obj; |
---|
| 520 | (void) rel; |
---|
| 521 | (void) sect; |
---|
| 522 | (void) symname; |
---|
| 523 | (void) syminfo; |
---|
| 524 | (void) symvalue; |
---|
| 525 | rtems_rtl_set_error (EINVAL, "rel type record not supported"); |
---|
[b36c5209] | 526 | return rtems_rtl_elf_rel_failure; |
---|
[ae5fe7e6] | 527 | } |
---|
[c6eead1] | 528 | |
---|
| 529 | bool |
---|
[f59d435d] | 530 | rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj, |
---|
| 531 | const char* name, |
---|
| 532 | uint32_t flags) |
---|
[c6eead1] | 533 | { |
---|
| 534 | return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); |
---|
| 535 | } |
---|
| 536 | |
---|
| 537 | bool |
---|
[f59d435d] | 538 | rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) |
---|
[c6eead1] | 539 | { |
---|
| 540 | return rtems_rtl_elf_unwind_dw2_register (obj); |
---|
| 541 | } |
---|
| 542 | |
---|
| 543 | bool |
---|
[f59d435d] | 544 | rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) |
---|
[c6eead1] | 545 | { |
---|
| 546 | return rtems_rtl_elf_unwind_dw2_deregister (obj); |
---|
| 547 | } |
---|