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 6237 : riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
44 : int *addsub)
45 : {
46 6237 : 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 5985 : case R_RISCV_32:
53 : case R_RISCV_SET32:
54 5985 : return ELF_T_WORD;
55 88 : case R_RISCV_64:
56 88 : return ELF_T_XWORD;
57 44 : case R_RISCV_ADD16:
58 44 : *addsub = 1;
59 44 : return ELF_T_HALF;
60 44 : case R_RISCV_SUB16:
61 44 : *addsub = -1;
62 44 : 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 24 : case R_RISCV_ADD64:
70 24 : *addsub = 1;
71 24 : return ELF_T_XWORD;
72 24 : case R_RISCV_SUB64:
73 24 : *addsub = -1;
74 24 : return ELF_T_XWORD;
75 28 : default:
76 28 : return ELF_T_NUM;
77 : }
78 : }
79 :
80 : /* Check whether machine flags are valid. */
81 : bool
82 1 : riscv_machine_flag_check (GElf_Word flags)
83 : {
84 1 : return ((flags &~ (EF_RISCV_RVC
85 1 : | 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 1 : riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym,
92 : const char *name, const GElf_Shdr *destshdr)
93 : {
94 1 : if (name == NULL)
95 : return false;
96 :
97 1 : size_t shstrndx;
98 1 : if (elf_getshdrstrndx (elf, &shstrndx) != 0)
99 : return false;
100 1 : const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
101 1 : 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 1 : 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 1 : 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 : }
|