hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/tools/objtool/special.c
....@@ -1,18 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version 2
7
- * of the License, or (at your option) any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
164 */
175
186 /*
....@@ -23,25 +11,10 @@
2311 #include <stdlib.h>
2412 #include <string.h>
2513
14
+#include "builtin.h"
2615 #include "special.h"
2716 #include "warn.h"
28
-
29
-#define EX_ENTRY_SIZE 12
30
-#define EX_ORIG_OFFSET 0
31
-#define EX_NEW_OFFSET 4
32
-
33
-#define JUMP_ENTRY_SIZE 24
34
-#define JUMP_ORIG_OFFSET 0
35
-#define JUMP_NEW_OFFSET 8
36
-
37
-#define ALT_ENTRY_SIZE 13
38
-#define ALT_ORIG_OFFSET 0
39
-#define ALT_NEW_OFFSET 4
40
-#define ALT_FEATURE_OFFSET 8
41
-#define ALT_ORIG_LEN_OFFSET 10
42
-#define ALT_NEW_LEN_OFFSET 11
43
-
44
-#define X86_FEATURE_POPCNT (4*32+23)
17
+#include "arch_special.h"
4518
4619 struct special_entry {
4720 const char *sec;
....@@ -78,11 +51,22 @@
7851 {},
7952 };
8053
54
+void __weak arch_handle_alternative(unsigned short feature, struct special_alt *alt)
55
+{
56
+}
57
+
58
+static void reloc_to_sec_off(struct reloc *reloc, struct section **sec,
59
+ unsigned long *off)
60
+{
61
+ *sec = reloc->sym->sec;
62
+ *off = reloc->sym->offset + reloc->addend;
63
+}
64
+
8165 static int get_alt_entry(struct elf *elf, struct special_entry *entry,
8266 struct section *sec, int idx,
8367 struct special_alt *alt)
8468 {
85
- struct rela *orig_rela, *new_rela;
69
+ struct reloc *orig_reloc, *new_reloc;
8670 unsigned long offset;
8771
8872 offset = idx * entry->size;
....@@ -102,40 +86,26 @@
10286
10387 feature = *(unsigned short *)(sec->data->d_buf + offset +
10488 entry->feature);
105
-
106
- /*
107
- * It has been requested that we don't validate the !POPCNT
108
- * feature path which is a "very very small percentage of
109
- * machines".
110
- */
111
- if (feature == X86_FEATURE_POPCNT)
112
- alt->skip_orig = true;
89
+ arch_handle_alternative(feature, alt);
11390 }
11491
115
- orig_rela = find_rela_by_dest(sec, offset + entry->orig);
116
- if (!orig_rela) {
117
- WARN_FUNC("can't find orig rela", sec, offset + entry->orig);
118
- return -1;
119
- }
120
- if (orig_rela->sym->type != STT_SECTION) {
121
- WARN_FUNC("don't know how to handle non-section rela symbol %s",
122
- sec, offset + entry->orig, orig_rela->sym->name);
92
+ orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
93
+ if (!orig_reloc) {
94
+ WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
12395 return -1;
12496 }
12597
126
- alt->orig_sec = orig_rela->sym->sec;
127
- alt->orig_off = orig_rela->addend;
98
+ reloc_to_sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off);
12899
129100 if (!entry->group || alt->new_len) {
130
- new_rela = find_rela_by_dest(sec, offset + entry->new);
131
- if (!new_rela) {
132
- WARN_FUNC("can't find new rela",
101
+ new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
102
+ if (!new_reloc) {
103
+ WARN_FUNC("can't find new reloc",
133104 sec, offset + entry->new);
134105 return -1;
135106 }
136107
137
- alt->new_sec = new_rela->sym->sec;
138
- alt->new_off = (unsigned int)new_rela->addend;
108
+ reloc_to_sec_off(new_reloc, &alt->new_sec, &alt->new_off);
139109
140110 /* _ASM_EXTABLE_EX hack */
141111 if (alt->new_off >= 0x7ffffff0)
....@@ -182,7 +152,9 @@
182152 memset(alt, 0, sizeof(*alt));
183153
184154 ret = get_alt_entry(elf, entry, sec, idx, alt);
185
- if (ret)
155
+ if (ret > 0)
156
+ continue;
157
+ if (ret < 0)
186158 return ret;
187159
188160 list_add_tail(&alt->list, alts);