Back to home page

LXR

 
 

    


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

0001 /*-
0002  * SPDX-License-Identifier: BSD-2-Clause
0003  *
0004  * Copyright (c) 2019 Hesham Almatary
0005  *
0006  * This software was developed by SRI International and the University of
0007  * Cambridge Computer Laboratory (Department of Computer Science and
0008  * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
0009  * DARPA SSITH research programme.
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions
0013  * are met:
0014  * 1. Redistributions of source code must retain the above copyright
0015  *    notice, this list of conditions and the following disclaimer.
0016  * 2. Redistributions in binary form must reproduce the above copyright
0017  *    notice, this list of conditions and the following disclaimer in the
0018  *    documentation and/or other materials provided with the distribution.
0019  *
0020  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0023  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0024  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0025  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0026  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0027  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0029  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0030  * SUCH DAMAGE.
0031  */
0032 
0033 /* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0034  * See https://llvm.org/LICENSE.txt for license information.
0035  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0036  */
0037 
0038 #include <sys/cdefs.h>
0039 
0040 #include <errno.h>
0041 #include <stdio.h>
0042 #include <sys/types.h>
0043 #include <sys/stat.h>
0044 
0045 #include <rtems/rtl/rtl.h>
0046 #include "rtl-elf.h"
0047 #include "rtl-error.h"
0048 #include <rtems/rtl/rtl-trace.h>
0049 #include "rtl-unwind.h"
0050 #include "rtl-unwind-dw2.h"
0051 
0052 uint32_t
0053 rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
0054                              const Elf_Shdr*      shdr) {
0055   return 0;
0056 }
0057 
0058 uint32_t
0059 rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
0060                                   int                  section,
0061                                   const char*          name,
0062                                   const Elf_Shdr*      shdr,
0063                                   const uint32_t       flags) {
0064   (void) obj;
0065   (void) section;
0066   (void) name;
0067   (void) shdr;
0068   return flags;
0069 }
0070 
0071 bool
0072 rtems_rtl_elf_arch_section_alloc (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_arch_section_free (const rtems_rtl_obj* obj,
0081                                  rtems_rtl_obj_sect*  sect) {
0082   (void) obj;
0083   (void) sect;
0084   return false;
0085 }
0086 
0087 bool
0088 rtems_rtl_elf_rel_resolve_sym (Elf_Word type) {
0089   return true;
0090 }
0091 
0092 uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj)
0093 {
0094   (void) obj;
0095   return sizeof(uint32_t);
0096 }
0097 
0098 size_t
0099 rtems_rtl_elf_relocate_tramp_max_size (void) {
0100   /*
0101    * Disable by returning 0.
0102    */
0103   return 0;
0104 }
0105 
0106 rtems_rtl_elf_rel_status
0107 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
0108                                   const Elf_Rel*            rel,
0109                                   const rtems_rtl_obj_sect* sect,
0110                                   const char*               symname,
0111                                   const Elf_Byte            syminfo,
0112                                   const Elf_Word            symvalue) {
0113   (void) obj;
0114   (void) rel;
0115   (void) sect;
0116   (void) symname;
0117   (void) syminfo;
0118   (void) symvalue;
0119   return rtems_rtl_elf_rel_no_error;
0120 }
0121 
0122 // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
0123 static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
0124   return (v & ((1ULL << (begin + 1)) - 1)) >> end;
0125 }
0126 
0127 static int64_t SignExtend64(uint64_t val, unsigned bits) {
0128   return (int64_t )(((int64_t) (val << (64 - bits))) >> (64 - bits));
0129 }
0130 
0131 static void write16le(void *loc, uint16_t val) {
0132   *((uint16_t *) loc) = val;
0133 }
0134 
0135 static void write32le(void *loc, uint32_t val) {
0136   *((uint32_t *) loc) = val;
0137 }
0138 
0139 static void write64le(void *loc, uint64_t val) {
0140   *((uint64_t *) loc) = val;
0141 }
0142 
0143 static uint16_t read16le(void *loc) {
0144   return *((uint16_t *) loc);
0145 }
0146 
0147 static uint32_t read32le(void *loc) {
0148   return *((uint32_t *) loc);
0149 }
0150 
0151 static uint64_t read64le(void *loc) {
0152   return *((uint64_t *) loc);
0153 }
0154 
0155 static rtems_rtl_elf_rel_status
0156 rtems_rtl_elf_reloc_rela (rtems_rtl_obj*      obj,
0157                           const Elf_Rela*           rela,
0158                           const rtems_rtl_obj_sect* sect,
0159                           const char*               symname,
0160                           const Elf_Byte            syminfo,
0161                           const Elf_Word            symvalue,
0162                           const bool parsing) {
0163   Elf_Addr *where;
0164 
0165   char bits = (sizeof(Elf_Word) * 8);
0166   where = (Elf_Addr *)(sect->base + rela->r_offset);
0167 
0168   // Final PCREL value
0169   Elf_Word pcrel_val = symvalue - ((Elf_Word)(uintptr_t) where);
0170 
0171   if (syminfo == STT_SECTION) {
0172     return rtems_rtl_elf_rel_no_error;
0173   }
0174 
0175   if (parsing) {
0176     return rtems_rtl_elf_rel_no_error;
0177   }
0178 
0179   switch (ELF_R_TYPE(rela->r_info)) {
0180   case R_TYPE(NONE):
0181     break;
0182 
0183   case R_TYPE(RVC_BRANCH): {
0184     uint16_t insn = ((*where) & 0xFFFF) & 0xE383;
0185     uint16_t imm8 = extractBits(pcrel_val, 8, 8) << 12;
0186     uint16_t imm4_3 = extractBits(pcrel_val, 4, 3) << 10;
0187     uint16_t imm7_6 = extractBits(pcrel_val, 7, 6) << 5;
0188     uint16_t imm2_1 = extractBits(pcrel_val, 2, 1) << 3;
0189     uint16_t imm5 = extractBits(pcrel_val, 5, 5) << 2;
0190     insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5;
0191 
0192     write16le(where, insn);
0193   }
0194   break;
0195 
0196   case R_TYPE(RVC_JUMP): {
0197     uint16_t insn = ((*where) & 0xFFFF) & 0xE003;
0198     uint16_t imm11 = extractBits(pcrel_val, 11, 11) << 12;
0199     uint16_t imm4 = extractBits(pcrel_val, 4, 4) << 11;
0200     uint16_t imm9_8 = extractBits(pcrel_val, 9, 8) << 9;
0201     uint16_t imm10 = extractBits(pcrel_val, 10, 10) << 8;
0202     uint16_t imm6 = extractBits(pcrel_val, 6, 6) << 7;
0203     uint16_t imm7 = extractBits(pcrel_val, 7, 7) << 6;
0204     uint16_t imm3_1 = extractBits(pcrel_val, 3, 1) << 3;
0205     uint16_t imm5 = extractBits(pcrel_val, 5, 5) << 2;
0206     insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5;
0207 
0208     write16le(where, insn);
0209   }
0210   break;
0211 
0212   case R_TYPE(RVC_LUI): {
0213     int64_t imm = SignExtend64(symvalue + 0x800, bits) >> 12;
0214     if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
0215       write16le(where, (read16le(where) & 0x0F83) | 0x4000);
0216     } else {
0217       uint16_t imm17 = extractBits(symvalue + 0x800, 17, 17) << 12;
0218       uint16_t imm16_12 = extractBits(symvalue + 0x800, 16, 12) << 2;
0219       write16le(where, (read16le(where) & 0xEF83) | imm17 | imm16_12);
0220     }
0221   }
0222   break;
0223 
0224   case R_TYPE(JAL): {
0225     uint32_t insn = read32le(where) & 0xFFF;
0226     uint32_t imm20 = extractBits(pcrel_val, 20, 20) << 31;
0227     uint32_t imm10_1 = extractBits(pcrel_val, 10, 1) << 21;
0228     uint32_t imm11 = extractBits(pcrel_val, 11, 11) << 20;
0229     uint32_t imm19_12 = extractBits(pcrel_val, 19, 12) << 12;
0230     insn |= imm20 | imm10_1 | imm11 | imm19_12;
0231 
0232     write32le(where, insn);
0233   }
0234   break;
0235 
0236   case R_TYPE(BRANCH): {
0237 
0238     uint32_t insn = read32le(where) & 0x1FFF07F;
0239     uint32_t imm12 = extractBits(pcrel_val, 12, 12) << 31;
0240     uint32_t imm10_5 = extractBits(pcrel_val, 10, 5) << 25;
0241     uint32_t imm4_1 = extractBits(pcrel_val, 4, 1) << 8;
0242     uint32_t imm11 = extractBits(pcrel_val, 11, 11) << 7;
0243     insn |= imm12 | imm10_5 | imm4_1 | imm11;
0244 
0245     write32le(where, insn);
0246   }
0247   break;
0248 
0249   case R_TYPE(64):
0250     write64le(where, symvalue);
0251     break;
0252   case R_TYPE(32):
0253     write32le(where, symvalue);
0254     break;
0255 
0256   case R_TYPE(SET6):
0257     *((uint8_t *) where) = (*where & 0xc0) | (symvalue & 0x3f);
0258     break;
0259   case R_TYPE(SET8):
0260     *((uint8_t *) where) = symvalue;
0261     break;
0262   case R_TYPE(SET16):
0263     write16le(where, symvalue);
0264     break;
0265   case R_TYPE(SET32):
0266     write32le(where, symvalue);
0267     break;
0268 
0269   case R_TYPE(ADD8):
0270     *((uint8_t *) where) = *((uint8_t *) where) + symvalue;
0271     break;
0272   case R_TYPE(ADD16):
0273     write16le(where, read16le(where) + symvalue);
0274     break;
0275   case R_TYPE(ADD32):
0276     write32le(where, read32le(where) + symvalue);
0277     break;
0278   case R_TYPE(ADD64):
0279     write64le(where, read64le(where) + symvalue);
0280     break;
0281 
0282   case R_TYPE(SUB6):
0283     *((uint8_t *) where) = (*where & 0xc0) | (((*where & 0x3f) - symvalue) & 0x3f);
0284     break;
0285   case R_TYPE(SUB8):
0286     *((uint8_t *) where) = *((uint8_t *) where) - symvalue;
0287     break;
0288   case R_TYPE(SUB16):
0289     write16le(where, read16le(where) - symvalue);
0290     break;
0291   case R_TYPE(SUB32):
0292     write32le(where, read32le(where) - symvalue);
0293     break;
0294   case R_TYPE(SUB64):
0295     write64le(where, read64le(where) - symvalue);
0296     break;
0297 
0298   case R_TYPE(32_PCREL): {
0299     write32le(where, pcrel_val);
0300 
0301     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0302       printf ("rtl: R_RISCV_32_PCREL %p @ %p in %s\n",
0303               (void *) * (where), where, rtems_rtl_obj_oname (obj));
0304 
0305   }
0306   break;
0307 
0308   case R_TYPE(PCREL_HI20): {
0309     int64_t hi = SignExtend64(pcrel_val + 0x800, bits); //pcrel_val + 0x800;
0310     write32le(where, (read32le(where) & 0xFFF) | (hi & 0xFFFFF000));
0311 
0312   }
0313   break;
0314 
0315   case R_TYPE(GOT_HI20):
0316   case R_TYPE(HI20): {
0317 
0318     uint64_t hi = symvalue + 0x800;
0319     write32le(where, (read32le(where) & 0xFFF) | (hi & 0xFFFFF000));
0320   }
0321   break;
0322 
0323   case R_TYPE(PCREL_LO12_I): {
0324     uint64_t hi = (pcrel_val + 0x800) >> 12;
0325     uint64_t lo = pcrel_val - (hi << 12);
0326     write32le(where, (read32le(where) & 0xFFFFF) | ((lo & 0xFFF) << 20));
0327   }
0328   break;
0329 
0330   case R_TYPE(LO12_I): {
0331 
0332     uint64_t hi = (symvalue + 0x800) >> 12;
0333     uint64_t lo = symvalue - (hi << 12);
0334     write32le(where, (read32le(where) & 0xFFFFF) | ((lo & 0xFFF) << 20));
0335 
0336   }
0337   break;
0338 
0339   case R_TYPE(PCREL_LO12_S): {
0340     uint64_t hi = (pcrel_val + 0x800) >> 12;
0341     uint64_t lo = pcrel_val - (hi << 12);
0342     uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
0343     uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
0344     write32le(where, (read32le(where) & 0x1FFF07F) | imm11_5 | imm4_0);
0345 
0346   }
0347   break;
0348 
0349   case R_TYPE(LO12_S): {
0350     uint64_t hi = (symvalue + 0x800) >> 12;
0351     uint64_t lo = symvalue - (hi << 12);
0352     uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
0353     uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
0354     write32le(where, (read32le(where) & 0x1FFF07F) | imm11_5 | imm4_0);
0355   }
0356   break;
0357 
0358   case R_TYPE(CALL_PLT):
0359   case R_TYPE(CALL): {
0360     int64_t hi = SignExtend64(pcrel_val + 0x800, bits);
0361     write32le(where, (read32le(where) & 0xFFF) | (hi & 0xFFFFF000));
0362     int64_t hi20 = SignExtend64(pcrel_val + 0x800, bits);
0363     int64_t lo = pcrel_val - (hi20 << 12);
0364     write32le(((char *) where) + 4, (read32le(((char *) where) + 4) & 0xFFFFF) | ((lo & 0xFFF) << 20));
0365   }
0366   break;
0367 
0368   default:
0369     rtems_rtl_set_error (EINVAL,
0370                          "%s: Unsupported relocation type %u "
0371                          "in non-PLT relocations",
0372                          sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
0373     return rtems_rtl_elf_rel_failure;
0374   }
0375 
0376   return rtems_rtl_elf_rel_no_error;
0377 }
0378 
0379 rtems_rtl_elf_rel_status
0380 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
0381                              const Elf_Rela*           rela,
0382                              const rtems_rtl_obj_sect* sect,
0383                              const char*               symname,
0384                              const Elf_Byte            syminfo,
0385                              const Elf_Word            symvalue) {
0386   return rtems_rtl_elf_reloc_rela (obj,
0387                                    rela,
0388                                    sect,
0389                                    symname,
0390                                    syminfo,
0391                                    symvalue,
0392                                    false);
0393 }
0394 
0395 rtems_rtl_elf_rel_status
0396 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
0397                                    const Elf_Rela*           rela,
0398                                    const rtems_rtl_obj_sect* sect,
0399                                    const char*               symname,
0400                                    const Elf_Byte            syminfo,
0401                                    const Elf_Word            symvalue) {
0402   return rtems_rtl_elf_reloc_rela (obj,
0403                                    rela,
0404                                    sect,
0405                                    symname,
0406                                    syminfo,
0407                                    symvalue,
0408                                    true);
0409 }
0410 
0411 rtems_rtl_elf_rel_status
0412 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*      obj,
0413                             const Elf_Rel*            rel,
0414                             const rtems_rtl_obj_sect* sect,
0415                             const char*               symname,
0416                             const Elf_Byte            syminfo,
0417                             const Elf_Word            symvalue) {
0418   rtems_rtl_set_error (EINVAL, "rel type record not supported");
0419   return rtems_rtl_elf_rel_failure;
0420 }
0421 
0422 bool
0423 rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
0424                             const char*          name,
0425                             uint32_t             flags) {
0426   return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
0427 }
0428 
0429 bool
0430 rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) {
0431   return rtems_rtl_elf_unwind_dw2_register (obj);
0432 }
0433 
0434 bool
0435 rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) {
0436   return rtems_rtl_elf_unwind_dw2_deregister (obj);
0437 }