/src/elfutils/backends/riscv_symbol.c
Line | Count | Source |
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 | | riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type, |
44 | | int *addsub) |
45 | 0 | { |
46 | 0 | switch (type) |
47 | 0 | { |
48 | 0 | case R_RISCV_SET8: |
49 | 0 | return ELF_T_BYTE; |
50 | 0 | case R_RISCV_SET16: |
51 | 0 | return ELF_T_HALF; |
52 | 0 | case R_RISCV_32: |
53 | 0 | case R_RISCV_SET32: |
54 | 0 | return ELF_T_WORD; |
55 | 0 | case R_RISCV_64: |
56 | 0 | return ELF_T_XWORD; |
57 | 0 | case R_RISCV_ADD16: |
58 | 0 | *addsub = 1; |
59 | 0 | return ELF_T_HALF; |
60 | 0 | case R_RISCV_SUB16: |
61 | 0 | *addsub = -1; |
62 | 0 | 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 | 0 | case R_RISCV_ADD64: |
70 | 0 | *addsub = 1; |
71 | 0 | return ELF_T_XWORD; |
72 | 0 | case R_RISCV_SUB64: |
73 | 0 | *addsub = -1; |
74 | 0 | return ELF_T_XWORD; |
75 | 0 | default: |
76 | 0 | return ELF_T_NUM; |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | | /* Check whether machine flags are valid. */ |
81 | | bool |
82 | | riscv_machine_flag_check (GElf_Word flags) |
83 | 0 | { |
84 | 0 | return ((flags &~ (EF_RISCV_RVC |
85 | 0 | | EF_RISCV_FLOAT_ABI)) == 0); |
86 | 0 | } |
87 | | |
88 | | /* Check whether given symbol's st_value and st_size are OK despite failing |
89 | | normal checks. */ |
90 | | bool |
91 | | riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym, |
92 | | const char *name, const GElf_Shdr *destshdr) |
93 | 0 | { |
94 | 0 | if (name == NULL) |
95 | 0 | return false; |
96 | | |
97 | 0 | size_t shstrndx; |
98 | 0 | if (elf_getshdrstrndx (elf, &shstrndx) != 0) |
99 | 0 | return false; |
100 | 0 | const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); |
101 | 0 | if (sname == NULL) |
102 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | return false; |
121 | 0 | } |
122 | | |
123 | | const char * |
124 | | riscv_segment_type_name (int segment, char *buf __attribute__ ((unused)), |
125 | | size_t len __attribute__ ((unused))) |
126 | 0 | { |
127 | 0 | switch (segment) |
128 | 0 | { |
129 | 0 | case PT_RISCV_ATTRIBUTES: |
130 | 0 | return "RISCV_ATTRIBUTES"; |
131 | 0 | } |
132 | 0 | return NULL; |
133 | 0 | } |
134 | | |
135 | | /* Return symbolic representation of section type. */ |
136 | | const char * |
137 | | riscv_section_type_name (int type, |
138 | | char *buf __attribute__ ((unused)), |
139 | | size_t len __attribute__ ((unused))) |
140 | 0 | { |
141 | 0 | switch (type) |
142 | 0 | { |
143 | 0 | case SHT_RISCV_ATTRIBUTES: |
144 | 0 | return "RISCV_ATTRIBUTES"; |
145 | 0 | } |
146 | | |
147 | 0 | return NULL; |
148 | 0 | } |
149 | | |
150 | | const char * |
151 | | riscv_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)), |
152 | | size_t len __attribute__ ((unused))) |
153 | 0 | { |
154 | 0 | switch (tag) |
155 | 0 | { |
156 | 0 | case DT_RISCV_VARIANT_CC: |
157 | 0 | return "RISCV_VARIANT_CC"; |
158 | 0 | } |
159 | 0 | return NULL; |
160 | 0 | } |
161 | | |
162 | | bool |
163 | | riscv_dynamic_tag_check (int64_t tag) |
164 | 0 | { |
165 | 0 | return tag == DT_RISCV_VARIANT_CC; |
166 | 0 | } |