Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:16

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #include <sys/cdefs.h>
0029 
0030 #include <errno.h>
0031 #include <stdio.h>
0032 #include <sys/types.h>
0033 #include <sys/stat.h>
0034 
0035 #include <rtems/rtl/rtl.h>
0036 #include "rtl-elf.h"
0037 #include "rtl-error.h"
0038 #include <rtems/rtl/rtl-trace.h>
0039 #include "rtl-unwind.h"
0040 #include "rtl-unwind-dw2.h"
0041 
0042 uint32_t
0043 rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
0044                              const Elf_Shdr*      shdr) {
0045   (void) obj;
0046   (void) shdr;
0047   return 0;
0048 }
0049 
0050 uint32_t
0051 rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
0052                                   int                  section,
0053                                   const char*          name,
0054                                   const Elf_Shdr*      shdr,
0055                                   const uint32_t       flags) {
0056   (void) obj;
0057   (void) section;
0058   (void) name;
0059   (void) shdr;
0060   return flags;
0061 }
0062 
0063 bool
0064 rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
0065                                   rtems_rtl_obj_sect*  sect) {
0066   (void) obj;
0067   (void) sect;
0068   return false;
0069 }
0070 
0071 bool
0072 rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
0073                                  rtems_rtl_obj_sect*  sect) {
0074   (void) obj;
0075   (void) sect;
0076   return false;
0077 }
0078 
0079 bool
0080 rtems_rtl_elf_rel_resolve_sym (Elf_Word type) {
0081   return type != 0;
0082 }
0083 
0084 uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj)
0085 {
0086   (void) obj;
0087   return sizeof(uint32_t);
0088 }
0089 
0090 size_t
0091 rtems_rtl_elf_relocate_tramp_max_size (void) {
0092   /*
0093    * Disable by returning 0.
0094    */
0095   return 0;
0096 }
0097 
0098 rtems_rtl_elf_rel_status
0099 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
0100                                   const Elf_Rel*            rel,
0101                                   const rtems_rtl_obj_sect* sect,
0102                                   const char*               symname,
0103                                   const Elf_Byte            syminfo,
0104                                   const Elf_Word            symvalue) {
0105   (void) obj;
0106   (void) rel;
0107   (void) sect;
0108   (void) symname;
0109   (void) syminfo;
0110   (void) symvalue;
0111   return rtems_rtl_elf_rel_no_error;
0112 }
0113 
0114 static void write16le(void *loc, uint16_t val) {
0115   *((uint16_t *) loc) = val;
0116 }
0117 
0118 static void write32le(void *loc, uint32_t val) {
0119   *((uint32_t *) loc) = val;
0120 }
0121 
0122 static uint16_t read16le(void *loc) {
0123   return *((uint16_t *) loc);
0124 }
0125 
0126 static uint32_t read32le(void *loc) {
0127   return *((uint32_t *) loc);
0128 }
0129 
0130 static rtems_rtl_elf_rel_status
0131 rtems_rtl_elf_reloc_rela (rtems_rtl_obj*            obj,
0132                           const Elf_Rela*           rela,
0133                           const rtems_rtl_obj_sect* sect,
0134                           const char*               symname,
0135                           const Elf_Byte            syminfo,
0136                           const Elf_Word            symvalue,
0137                           const bool                parsing) {
0138   Elf_Word *where;
0139   Elf_Word addend = (Elf_Word)rela->r_addend;
0140   Elf_Addr target;
0141 
0142   where = (Elf_Addr *)(sect->base + rela->r_offset);
0143 
0144   /* Target value */
0145   target = (Elf_Addr)symvalue + addend;
0146   /* Final PCREL value */
0147   Elf_Word pcrel_val = target - ((Elf_Word)where);
0148 
0149   if (parsing) {
0150     return rtems_rtl_elf_rel_no_error;
0151   }
0152 
0153   switch (ELF_R_TYPE(rela->r_info)) {
0154   case R_TYPE(NONE):
0155     break;
0156 
0157   case R_TYPE(64):
0158     /* Set the lower 16 bits of where to the upper 16 bits of target */
0159     write16le(where,
0160               (read16le(where) & 0xFFFF0000) | (target >> 16));
0161     /* Set the lower 16 bits of where + 4 to the lower 16 bits of target */
0162     write16le(where + 1,
0163               (read16le(where + 1) & 0xFFFF0000) | (target & 0xFFFF));
0164     break;
0165 
0166   case R_TYPE(32):
0167     {
0168       uintptr_t addr = (uintptr_t)where;
0169       if ((uintptr_t)where & 3) {
0170         /* `where` is not aligned to a 4-byte boundary. */
0171         uintptr_t addr_down = addr & ~3;
0172         uintptr_t addr_up = (addr + 3) & ~3;
0173 
0174         uint32_t value_down = read32le((void*)addr_down);
0175         uint32_t value_up = read32le((void*)addr_up);
0176 
0177         /*
0178          * Calculate how many bytes `where` is offset from the previous 4-byte
0179          * boundary.
0180          */
0181         unsigned offset = addr & 3;
0182 
0183         /*
0184          * Combine `target` with `value_down` and `value_up` to form the new
0185          * values to write.
0186          */
0187         uint32_t new_value_down = (value_down & ((1 << (offset * 8)) - 1)) |
0188           (target << (offset * 8));
0189         uint32_t new_value_up = (value_up & ~((1 << (offset * 8)) - 1)) |
0190           (target >> ((4 - offset) * 8));
0191 
0192         write32le((void*)addr_down, new_value_down);
0193         write32le((void*)addr_up, new_value_up);
0194       } else {
0195         write32le(where, target);
0196       }
0197     }
0198     break;
0199 
0200   case R_TYPE(32_PCREL):
0201     write32le(where, pcrel_val);
0202 
0203     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0204       printf ("rtl: R_MICROBLAZE_32_PCREL %p @ %p in %s\n",
0205               (void *) * (where), where, rtems_rtl_obj_oname (obj));
0206     break;
0207 
0208   case R_TYPE(64_PCREL):
0209     /*
0210      * Compensate for the fact that the PC is 4 bytes ahead of the instruction
0211      */
0212     pcrel_val -= 4;
0213     /* Set the lower 16 bits of where to the upper 16 bits of target */
0214     write16le(where,
0215               (read16le(where) & 0xFFFF0000) | (pcrel_val >> 16));
0216     /* Set the lower 16 bits of where + 4 to the lower 16 bits of target */
0217     write16le(where + 1,
0218               (read16le(where + 1) & 0xFFFF0000) | (pcrel_val & 0xFFFF));
0219 
0220     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0221       printf ("rtl: R_MICROBLAZE_64_PCREL %p @ %p in %s\n",
0222               (void *) * (where), where, rtems_rtl_obj_oname (obj));
0223     break;
0224 
0225   case R_TYPE(32_PCREL_LO):
0226     write16le(where, (read16le(where) & 0xFFFF0000) | (pcrel_val & 0xFFFF));
0227     break;
0228 
0229   default:
0230     rtems_rtl_set_error (EINVAL,
0231                          "%s: Unsupported relocation type %d "
0232                          "in non-PLT relocations",
0233                          sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
0234     return rtems_rtl_elf_rel_failure;
0235   }
0236 
0237   return rtems_rtl_elf_rel_no_error;
0238 }
0239 
0240 rtems_rtl_elf_rel_status
0241 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
0242                              const Elf_Rela*           rela,
0243                              const rtems_rtl_obj_sect* sect,
0244                              const char*               symname,
0245                              const Elf_Byte            syminfo,
0246                              const Elf_Word            symvalue) {
0247   return rtems_rtl_elf_reloc_rela (obj,
0248                                    rela,
0249                                    sect,
0250                                    symname,
0251                                    syminfo,
0252                                    symvalue,
0253                                    false);
0254 }
0255 
0256 rtems_rtl_elf_rel_status
0257 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
0258                                    const Elf_Rela*           rela,
0259                                    const rtems_rtl_obj_sect* sect,
0260                                    const char*               symname,
0261                                    const Elf_Byte            syminfo,
0262                                    const Elf_Word            symvalue) {
0263   return rtems_rtl_elf_reloc_rela (obj,
0264                                    rela,
0265                                    sect,
0266                                    symname,
0267                                    syminfo,
0268                                    symvalue,
0269                                    true);
0270 }
0271 
0272 rtems_rtl_elf_rel_status
0273 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
0274                             const Elf_Rel*            rel,
0275                             const rtems_rtl_obj_sect* sect,
0276                             const char*               symname,
0277                             const Elf_Byte            syminfo,
0278                             const Elf_Word            symvalue) {
0279   rtems_rtl_set_error (EINVAL, "rel type record not supported");
0280   return rtems_rtl_elf_rel_failure;
0281 }
0282 
0283 bool
0284 rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
0285                             const char*          name,
0286                             uint32_t             flags) {
0287   return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
0288 }
0289 
0290 bool
0291 rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) {
0292   return rtems_rtl_elf_unwind_dw2_register (obj);
0293 }
0294 
0295 bool
0296 rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) {
0297   return rtems_rtl_elf_unwind_dw2_deregister (obj);
0298 }