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 : 0 : case R_RISCV_SET16:
51 : 0 : return ELF_T_HALF;
52 : 11970 : case R_RISCV_32:
53 : : case R_RISCV_SET32:
54 : 11970 : return ELF_T_WORD;
55 : 168 : case R_RISCV_64:
56 : 168 : 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 : : }
|