Branch data Line data Source code
1 : : /* RISC-V specific symbolic name handling. 2 : : This file is part of elfutils. 3 : : 4 : : This file is free software; you can redistribute it and/or modify 5 : : it under the terms of either 6 : : 7 : : * the GNU Lesser General Public License as published by the Free 8 : : Software Foundation; either version 3 of the License, or (at 9 : : your option) any later version 10 : : 11 : : or 12 : : 13 : : * the GNU General Public License as published by the Free 14 : : Software Foundation; either version 2 of the License, or (at 15 : : your option) any later version 16 : : 17 : : or both in parallel, as here. 18 : : 19 : : elfutils is distributed in the hope that it will be useful, but 20 : : WITHOUT ANY WARRANTY; without even the implied warranty of 21 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 : : General Public License for more details. 23 : : 24 : : You should have received copies of the GNU General Public License and 25 : : the GNU Lesser General Public License along with this program. If 26 : : not, see <http://www.gnu.org/licenses/>. */ 27 : : 28 : : #ifdef HAVE_CONFIG_H 29 : : # include <config.h> 30 : : #endif 31 : : 32 : : #include <assert.h> 33 : : #include <elf.h> 34 : : #include <stddef.h> 35 : : #include <string.h> 36 : : 37 : : #define BACKEND riscv_ 38 : : #include "libebl_CPU.h" 39 : : 40 : : 41 : : /* Check for the simple reloc types. */ 42 : : Elf_Type 43 : 12442 : riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type, 44 : : int *addsub) 45 : : { 46 [ - + + + : 12442 : switch (type) + - - + + + - ] 47 : : { 48 : : case R_RISCV_SET8: 49 : : return ELF_T_BYTE; 50 : : case R_RISCV_SET16: 51 : : return ELF_T_HALF; 52 : : case R_RISCV_32: 53 : : case R_RISCV_SET32: 54 : : return ELF_T_WORD; 55 : : case R_RISCV_64: 56 : : return ELF_T_XWORD; 57 : 88 : case R_RISCV_ADD16: 58 : 88 : *addsub = 1; 59 : 88 : return ELF_T_HALF; 60 : 88 : case R_RISCV_SUB16: 61 : 88 : *addsub = -1; 62 : 88 : return ELF_T_HALF; 63 : 0 : case R_RISCV_ADD32: 64 : 0 : *addsub = 1; 65 : 0 : return ELF_T_WORD; 66 : 0 : case R_RISCV_SUB32: 67 : 0 : *addsub = -1; 68 : 0 : return ELF_T_WORD; 69 : 48 : case R_RISCV_ADD64: 70 : 48 : *addsub = 1; 71 : 48 : return ELF_T_XWORD; 72 : 48 : case R_RISCV_SUB64: 73 : 48 : *addsub = -1; 74 : 48 : return ELF_T_XWORD; 75 : 32 : default: 76 : 32 : return ELF_T_NUM; 77 : : } 78 : : } 79 : : 80 : : /* Check whether machine flags are valid. */ 81 : : bool 82 : 2 : riscv_machine_flag_check (GElf_Word flags) 83 : : { 84 : 2 : return ((flags &~ (EF_RISCV_RVC 85 : 2 : | EF_RISCV_FLOAT_ABI)) == 0); 86 : : } 87 : : 88 : : /* Check whether given symbol's st_value and st_size are OK despite failing 89 : : normal checks. */ 90 : : bool 91 : 2 : riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym, 92 : : const char *name, const GElf_Shdr *destshdr) 93 : : { 94 [ - + ]: 2 : if (name == NULL) 95 : : return false; 96 : : 97 : 2 : size_t shstrndx; 98 [ - + ]: 2 : if (elf_getshdrstrndx (elf, &shstrndx) != 0) 99 : : return false; 100 : 2 : const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); 101 [ - + ]: 2 : if (sname == NULL) 102 : : return false; 103 : : 104 : : /* _GLOBAL_OFFSET_TABLE_ points to the start of the .got section, but it 105 : : is preceded by the .got.plt section in the output .got section. */ 106 [ - + ]: 2 : if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) 107 : 0 : return (strcmp (sname, ".got") == 0 108 [ # # ]: 0 : && sym->st_value >= destshdr->sh_addr 109 [ # # # # ]: 0 : && sym->st_value < destshdr->sh_addr + destshdr->sh_size); 110 : : 111 : : /* __global_pointer$ points to the .sdata section with an offset of 112 : : 0x800. It might however fall in the .got section, in which case we 113 : : cannot check the offset. The size always should be zero. */ 114 [ + - ]: 2 : if (strcmp (name, "__global_pointer$") == 0) 115 : 0 : return (((strcmp (sname, ".sdata") == 0 116 [ # # ]: 0 : && sym->st_value == destshdr->sh_addr + 0x800) 117 [ # # ]: 0 : || strcmp (sname, ".got") == 0) 118 [ # # # # ]: 0 : && sym->st_size == 0); 119 : : 120 : : return false; 121 : : } 122 : : 123 : : const char * 124 : 0 : riscv_segment_type_name (int segment, char *buf __attribute__ ((unused)), 125 : : size_t len __attribute__ ((unused))) 126 : : { 127 [ # # ]: 0 : switch (segment) 128 : : { 129 : : case PT_RISCV_ATTRIBUTES: 130 : : return "RISCV_ATTRIBUTES"; 131 : : } 132 : 0 : return NULL; 133 : : } 134 : : 135 : : /* Return symbolic representation of section type. */ 136 : : const char * 137 : 114 : riscv_section_type_name (int type, 138 : : char *buf __attribute__ ((unused)), 139 : : size_t len __attribute__ ((unused))) 140 : : { 141 [ + - ]: 114 : switch (type) 142 : : { 143 : : case SHT_RISCV_ATTRIBUTES: 144 : : return "RISCV_ATTRIBUTES"; 145 : : } 146 : : 147 : 114 : return NULL; 148 : : } 149 : : 150 : : const char * 151 : 0 : riscv_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)), 152 : : size_t len __attribute__ ((unused))) 153 : : { 154 [ # # ]: 0 : switch (tag) 155 : : { 156 : : case DT_RISCV_VARIANT_CC: 157 : : return "RISCV_VARIANT_CC"; 158 : : } 159 : 0 : return NULL; 160 : : } 161 : : 162 : : bool 163 : 60 : riscv_dynamic_tag_check (int64_t tag) 164 : : { 165 : 60 : return tag == DT_RISCV_VARIANT_CC; 166 : : }