1 //===- MipsArchTree.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This file contains a helper function for the Writer.
10 //
11 //===---------------------------------------------------------------------===//
12
13 #include "InputFiles.h"
14 #include "SymbolTable.h"
15 #include "SyntheticSections.h"
16 #include "Writer.h"
17
18 #include "lld/Common/ErrorHandler.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/Object/ELF.h"
21 #include "llvm/Support/MipsABIFlags.h"
22
23 using namespace llvm;
24 using namespace llvm::object;
25 using namespace llvm::ELF;
26
27 using namespace lld;
28 using namespace lld::elf;
29
30 namespace {
31 struct ArchTreeEdge {
32 uint32_t child;
33 uint32_t parent;
34 };
35
36 struct FileFlags {
37 InputFile *file;
38 uint32_t flags;
39 };
40 } // namespace
41
getAbiName(uint32_t flags)42 static StringRef getAbiName(uint32_t flags) {
43 switch (flags) {
44 case 0:
45 return "n64";
46 case EF_MIPS_ABI2:
47 return "n32";
48 case EF_MIPS_ABI_O32:
49 return "o32";
50 case EF_MIPS_ABI_O64:
51 return "o64";
52 case EF_MIPS_ABI_EABI32:
53 return "eabi32";
54 case EF_MIPS_ABI_EABI64:
55 return "eabi64";
56 case EF_MIPS_ABI_CHERIABI:
57 return "purecap";
58 default:
59 return "unknown";
60 }
61 }
62
getNanName(bool isNan2008)63 static StringRef getNanName(bool isNan2008) {
64 return isNan2008 ? "2008" : "legacy";
65 }
66
getFpName(bool isFp64)67 static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
68
checkFlags(ArrayRef<FileFlags> files)69 static void checkFlags(ArrayRef<FileFlags> files) {
70 assert(!files.empty() && "expected non-empty file list");
71
72 uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
73 bool nan = files[0].flags & EF_MIPS_NAN2008;
74 bool fp = files[0].flags & EF_MIPS_FP64;
75
76 for (const FileFlags &f : files) {
77 if (config->is64 && f.flags & EF_MIPS_MICROMIPS)
78 error(toString(f.file) + ": microMIPS 64-bit is not supported");
79
80 uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
81 if (abi != abi2)
82 error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
83 "' is incompatible with target ABI '" + getAbiName(abi) + "'");
84
85 bool nan2 = f.flags & EF_MIPS_NAN2008;
86 if (nan != nan2)
87 error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
88 " is incompatible with target -mnan=" + getNanName(nan));
89
90 bool fp2 = f.flags & EF_MIPS_FP64;
91 if (fp != fp2)
92 error(toString(f.file) + ": -mfp" + getFpName(fp2) +
93 " is incompatible with target -mfp" + getFpName(fp));
94 }
95 }
96
getMiscFlags(ArrayRef<FileFlags> files)97 static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
98 uint32_t ret = 0;
99 for (const FileFlags &f : files)
100 ret |= f.flags &
101 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
102 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
103 return ret;
104 }
105
getPicFlags(ArrayRef<FileFlags> files)106 static uint32_t getPicFlags(ArrayRef<FileFlags> files) {
107 // Check PIC/non-PIC compatibility.
108 bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
109 for (const FileFlags &f : files.slice(1)) {
110 bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
111 if (isPic && !isPic2)
112 warn(toString(f.file) +
113 ": linking non-abicalls code with abicalls code " +
114 toString(files[0].file));
115 if (!isPic && isPic2)
116 warn(toString(f.file) +
117 ": linking abicalls code with non-abicalls code " +
118 toString(files[0].file));
119 }
120
121 // Compute the result PIC/non-PIC flag.
122 uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
123 for (const FileFlags &f : files.slice(1))
124 ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
125
126 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
127 if (ret & EF_MIPS_PIC)
128 ret |= EF_MIPS_CPIC;
129 return ret;
130 }
131
132 static ArchTreeEdge archTree[] = {
133 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
134 // MIPS64R2 extensions.
135 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
136 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
137 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
138 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
139 // MIPS64 extensions.
140 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
141 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
142 {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
143 // MIPS V extensions.
144 {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
145 // R5000 extensions.
146 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
147 // MIPS IV extensions.
148 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
149 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
150 // CHERI is a superset of BERI
151 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_CHERI128, EF_MIPS_ARCH_4 | EF_MIPS_MACH_BERI},
152 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_CHERI256, EF_MIPS_ARCH_4 | EF_MIPS_MACH_BERI},
153 // BERI is a superset of MIPS4
154 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_BERI, EF_MIPS_ARCH_4},
155 {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
156 // VR4100 extensions.
157 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
158 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
159 // MIPS III extensions.
160 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
161 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
162 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
163 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
164 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
165 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
166 {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
167 // MIPS32 extensions.
168 {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
169 // MIPS II extensions.
170 {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
171 {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
172 // MIPS I extensions.
173 {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
174 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
175 };
176
isArchMatched(uint32_t newFlags,uint32_t res)177 static bool isArchMatched(uint32_t newFlags, uint32_t res) {
178 // llvm::errs() << __func__ << ": new=" << utohexstr(newFlags) << " res=" << utohexstr(Res) << "\n";
179 if (newFlags == res)
180 return true;
181 if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
182 return true;
183 if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
184 return true;
185
186 // check for cheri128 vs cheri256 and upgrade non-cheri to cheri
187 uint32_t newMach = (newFlags & EF_MIPS_MACH);
188 uint32_t resMach = (res & EF_MIPS_MACH);
189 if (resMach == EF_MIPS_MACH_CHERI128) {
190 if (newMach != 0 && newMach != EF_MIPS_MACH_CHERI128 && newMach != EF_MIPS_MACH_BERI)
191 return false;
192 return isArchMatched(newFlags & ~EF_MIPS_MACH, res & ~EF_MIPS_MACH);
193 }
194 if (resMach == EF_MIPS_MACH_CHERI256) {
195 if (newMach != 0 && newMach != EF_MIPS_MACH_CHERI256 && newMach != EF_MIPS_MACH_BERI)
196 return false;
197 return isArchMatched(newFlags & ~EF_MIPS_MACH, res & ~EF_MIPS_MACH);
198 }
199
200 for (const auto &edge : archTree) {
201 if (res == edge.child) {
202 res = edge.parent;
203 if (res == newFlags)
204 return true;
205 }
206 }
207 return false;
208 }
209
getMachName(uint32_t flags)210 static StringRef getMachName(uint32_t flags) {
211 switch (flags & EF_MIPS_MACH) {
212 case EF_MIPS_MACH_NONE:
213 return "";
214 case EF_MIPS_MACH_3900:
215 return "r3900";
216 case EF_MIPS_MACH_4010:
217 return "r4010";
218 case EF_MIPS_MACH_4100:
219 return "r4100";
220 case EF_MIPS_MACH_4650:
221 return "r4650";
222 case EF_MIPS_MACH_4120:
223 return "r4120";
224 case EF_MIPS_MACH_4111:
225 return "r4111";
226 case EF_MIPS_MACH_5400:
227 return "vr5400";
228 case EF_MIPS_MACH_5900:
229 return "vr5900";
230 case EF_MIPS_MACH_5500:
231 return "vr5500";
232 case EF_MIPS_MACH_9000:
233 return "rm9000";
234 case EF_MIPS_MACH_LS2E:
235 return "loongson2e";
236 case EF_MIPS_MACH_LS2F:
237 return "loongson2f";
238 case EF_MIPS_MACH_LS3A:
239 return "loongson3a";
240 case EF_MIPS_MACH_OCTEON:
241 return "octeon";
242 case EF_MIPS_MACH_OCTEON2:
243 return "octeon2";
244 case EF_MIPS_MACH_OCTEON3:
245 return "octeon3";
246 case EF_MIPS_MACH_SB1:
247 return "sb1";
248 case EF_MIPS_MACH_XLR:
249 return "xlr";
250 case EF_MIPS_MACH_BERI:
251 return "beri";
252 case EF_MIPS_MACH_CHERI128:
253 return "cheri128";
254 case EF_MIPS_MACH_CHERI256:
255 return "cheri256";
256 default:
257 return "unknown machine";
258 }
259 }
260
getArchName(uint32_t flags)261 static StringRef getArchName(uint32_t flags) {
262 switch (flags & EF_MIPS_ARCH) {
263 case EF_MIPS_ARCH_1:
264 return "mips1";
265 case EF_MIPS_ARCH_2:
266 return "mips2";
267 case EF_MIPS_ARCH_3:
268 return "mips3";
269 case EF_MIPS_ARCH_4:
270 return "mips4";
271 case EF_MIPS_ARCH_5:
272 return "mips5";
273 case EF_MIPS_ARCH_32:
274 return "mips32";
275 case EF_MIPS_ARCH_64:
276 return "mips64";
277 case EF_MIPS_ARCH_32R2:
278 return "mips32r2";
279 case EF_MIPS_ARCH_64R2:
280 return "mips64r2";
281 case EF_MIPS_ARCH_32R6:
282 return "mips32r6";
283 case EF_MIPS_ARCH_64R6:
284 return "mips64r6";
285 default:
286 return "unknown arch";
287 }
288 }
289
getFullArchName(uint32_t flags)290 static std::string getFullArchName(uint32_t flags) {
291 StringRef arch = getArchName(flags);
292 StringRef mach = getMachName(flags);
293 if (mach.empty())
294 return arch.str();
295 return (arch + " (" + mach + ")").str();
296 }
297
isBeriOrCheri(uint32_t flags)298 static inline bool isBeriOrCheri(uint32_t flags) {
299 uint32_t mach = flags & EF_MIPS_MACH;
300 return mach == EF_MIPS_MACH_BERI || mach == EF_MIPS_MACH_CHERI128 ||
301 mach == EF_MIPS_MACH_CHERI256;
302 }
303
304 // There are (arguably too) many MIPS ISAs out there. Their relationships
305 // can be represented as a forest. If all input files have ISAs which
306 // reachable by repeated proceeding from the single child to the parent,
307 // these input files are compatible. In that case we need to return "highest"
308 // ISA. If there are incompatible input files, we show an error.
309 // For example, mips1 is a "parent" of mips2 and such files are compatible.
310 // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
311 // are incompatible because nor mips3 is a parent for misp32, nor mips32
312 // is a parent for mips3.
getArchFlags(ArrayRef<FileFlags> files)313 static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
314 uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
315
316 for (const FileFlags &f : files.slice(1)) {
317 uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
318
319 // Warn about linking BERI/CHERI and non BERI/CHERI
320 // This is required because the default -mcpu=mips4 instruction scheduling
321 // results in lots of pipeline bubbles that prevent MIPS performance from
322 // being comparable to CHERI performance.
323 if (isBeriOrCheri(ret) != isBeriOrCheri(newFlags)) {
324 warn("linking files compiled for BERI/CHERI and non-BERI/CHERI can "
325 "result in surprising performance:\n>>> " +
326 toString(files[0].file) + ": " + getFullArchName(ret) + "\n>>> " +
327 toString(f.file) + ": " + getFullArchName(newFlags));
328 }
329
330 // Check ISA compatibility.
331 if (isArchMatched(newFlags, ret))
332 continue;
333 if (!isArchMatched(ret, newFlags)) {
334 error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
335 getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
336 getFullArchName(newFlags));
337 return 0;
338 }
339 ret = newFlags;
340 }
341 return ret;
342 }
343
calcMipsEFlags()344 template <class ELFT> uint32_t elf::calcMipsEFlags() {
345 std::vector<FileFlags> v;
346 for (InputFile *f : objectFiles)
347 v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
348 if (v.empty()) {
349 // If we don't have any input files, we'll have to rely on the information
350 // we can derive from emulation information, since this at least gets us
351 // ABI.
352 if (config->emulation.empty() || config->is64)
353 return 0;
354 return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
355 }
356 checkFlags(v);
357 return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
358 }
359
compareMipsFpAbi(uint8_t fpA,uint8_t fpB)360 static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
361 if (fpA == fpB)
362 return 0;
363 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
364 return 1;
365 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
366 fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
367 return 1;
368 if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
369 return -1;
370 if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
371 fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
372 fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
373 return 1;
374 return -1;
375 }
376
getMipsFpAbiName(uint8_t fpAbi)377 static StringRef getMipsFpAbiName(uint8_t fpAbi) {
378 switch (fpAbi) {
379 case Mips::Val_GNU_MIPS_ABI_FP_ANY:
380 return "any";
381 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
382 return "-mdouble-float";
383 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
384 return "-msingle-float";
385 case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
386 return "-msoft-float";
387 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
388 return "-mgp32 -mfp64 (old)";
389 case Mips::Val_GNU_MIPS_ABI_FP_XX:
390 return "-mfpxx";
391 case Mips::Val_GNU_MIPS_ABI_FP_64:
392 return "-mgp32 -mfp64";
393 case Mips::Val_GNU_MIPS_ABI_FP_64A:
394 return "-mgp32 -mfp64 -mno-odd-spreg";
395 default:
396 return "unknown";
397 }
398 }
399
getMipsFpAbiFlag(uint8_t oldFlag,StringRef oldFile,uint8_t newFlag,StringRef newFile)400 uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, StringRef oldFile,
401 uint8_t newFlag, StringRef newFile) {
402 if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
403 return newFlag;
404 if (compareMipsFpAbi(oldFlag, newFlag) < 0)
405 error(newFile + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
406 "' is incompatible with target floating point ABI '" +
407 getMipsFpAbiName(oldFlag) + "'");
408 return oldFlag;
409 }
410
getMipsIsaExtName(Mips::AFL_EXT ext)411 static std::string getMipsIsaExtName(Mips::AFL_EXT ext) {
412 switch (ext) {
413 // duplicated from ELFYAML.cpp
414 #define ECase(X) \
415 case Mips::AFL_##X: \
416 return #X
417 ECase(EXT_NONE);
418 ECase(EXT_XLR);
419 ECase(EXT_OCTEON2);
420 ECase(EXT_OCTEONP);
421 ECase(EXT_LOONGSON_3A);
422 ECase(EXT_OCTEON);
423 ECase(EXT_5900);
424 ECase(EXT_4650);
425 ECase(EXT_4010);
426 ECase(EXT_4100);
427 ECase(EXT_3900);
428 ECase(EXT_10000);
429 ECase(EXT_SB1);
430 ECase(EXT_4111);
431 ECase(EXT_4120);
432 ECase(EXT_5400);
433 ECase(EXT_5500);
434 ECase(EXT_LOONGSON_2E);
435 ECase(EXT_LOONGSON_2F);
436 ECase(EXT_OCTEON3);
437 ECase(EXT_CHERI);
438 ECase(EXT_CHERI_ABI_LEGACY);
439 ECase(EXT_CHERI_ABI_PLT);
440 ECase(EXT_CHERI_ABI_PCREL);
441 ECase(EXT_CHERI_ABI_FNDESC);
442 default:
443 return ("<unknown isa_ext (" + Twine(ext) + ")>").str();
444 #undef ECase
445 }
446 }
447
getMipsIsaExt(uint64_t oldExt,StringRef oldFile,uint64_t newExt,StringRef newFile)448 uint8_t elf::getMipsIsaExt(uint64_t oldExt, StringRef oldFile, uint64_t newExt,
449 StringRef newFile) {
450 if (oldExt == newExt)
451 return newExt;
452
453 // ISA_EXT is different, now check if we want to allow this
454 // No ext -> any ext is always fine (XXXAR: well at least for now it is)
455 // TODO: require isa_ext to be set for CHERI purecap programs in the future
456 if (oldExt == Mips::AFL_EXT_NONE)
457 return newExt;
458 if (newExt == Mips::AFL_EXT_NONE)
459 return oldExt;
460 Mips::AFL_EXT cheriABIs[] = {
461 Mips::AFL_EXT_CHERI_ABI_LEGACY,
462 Mips::AFL_EXT_CHERI_ABI_PLT,
463 Mips::AFL_EXT_CHERI_ABI_PCREL,
464 Mips::AFL_EXT_CHERI_ABI_FNDESC,
465 };
466 if (llvm::is_contained(cheriABIs, oldExt) ||
467 llvm::is_contained(cheriABIs, newExt)) {
468 // incompatible cheri purecap ABIs:
469 error("incompatible pure-capability ABIs:\n>>> " + oldFile + " uses " +
470 getMipsIsaExtName((Mips::AFL_EXT)oldExt) + "\n>>> " + newFile +
471 " uses " + getMipsIsaExtName((Mips::AFL_EXT)newExt));
472 // return NewExt to get sensible error messages with multiple mismatches
473 return newExt;
474 }
475 // non-cheri isa_ext -> just return the maximum
476 return std::max(oldExt, newExt);
477 }
478
cheriFlagsToAFL_EXT(uint64_t cheriFlags)479 static Mips::AFL_EXT cheriFlagsToAFL_EXT(uint64_t cheriFlags) {
480 assert(cheriFlags < DF_MIPS_CHERI_ABI_MASK);
481 switch (cheriFlags) {
482 case DF_MIPS_CHERI_ABI_LEGACY:
483 return Mips::AFL_EXT::AFL_EXT_CHERI_ABI_LEGACY;
484 case DF_MIPS_CHERI_ABI_PCREL:
485 return Mips::AFL_EXT::AFL_EXT_CHERI_ABI_PCREL;
486 case DF_MIPS_CHERI_ABI_PLT:
487 return Mips::AFL_EXT::AFL_EXT_CHERI_ABI_PLT;
488 case DF_MIPS_CHERI_ABI_FNDESC:
489 return Mips::AFL_EXT::AFL_EXT_CHERI_ABI_FNDESC;
490 default:
491 llvm_unreachable("Invalid ABI");
492 }
493 return Mips::AFL_EXT::AFL_EXT_NONE;
494 }
495
checkMipsShlibCompatible(InputFile * f,uint64_t inputCheriFlags,uint64_t targetCheriFlags)496 void elf::checkMipsShlibCompatible(InputFile *f, uint64_t inputCheriFlags,
497 uint64_t targetCheriFlags) {
498 const uint32_t targetABI = config->eflags & (EF_MIPS_ABI | EF_MIPS_ABI2);
499 assert(f->emachine == config->emachine);
500 uint32_t abi = f->eflags & (EF_MIPS_ABI | EF_MIPS_ABI2);
501 // Mips can't link against cheriabi and the other way around
502 if ((config->isCheriAbi && abi != EF_MIPS_ABI_CHERIABI) ||
503 (!config->isCheriAbi && abi == EF_MIPS_ABI_CHERIABI)) {
504 // assert(errorCount() && "Should have already caused an errors");
505 // llvm_unreachable("Should have been checked earlier!");
506 if (!errorCount())
507 error(toString(f) + ": ABI '" + getAbiName(abi) +
508 "' is incompatible with target ABI: " + getAbiName(targetABI));
509 } else {
510 uint64_t inputCheriAbi = inputCheriFlags & DF_MIPS_CHERI_ABI_MASK;
511 uint64_t targetCheriAbi = targetCheriFlags & DF_MIPS_CHERI_ABI_MASK;
512 if (inputCheriAbi != targetCheriAbi) {
513 std::string msg = "target pure-capability ABI " +
514 getMipsIsaExtName(cheriFlagsToAFL_EXT(targetCheriAbi)) +
515 " is incompatible with linked shared library\n>>> " +
516 toString(f) + " uses " +
517 getMipsIsaExtName(cheriFlagsToAFL_EXT(inputCheriAbi));
518 // mixing legacy/non-legacy is an error, anything a warning
519 if (inputCheriAbi == DF_MIPS_CHERI_ABI_LEGACY ||
520 targetCheriAbi == DF_MIPS_CHERI_ABI_LEGACY)
521 error(msg);
522 else
523 warn(msg);
524 }
525 }
526 }
527
isN32Abi(const InputFile * f)528 template <class ELFT> static bool isN32Abi(const InputFile *f) {
529 if (auto *ef = dyn_cast<ELFFileBase>(f))
530 return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
531 return false;
532 }
533
isMipsN32Abi(const InputFile * f)534 bool elf::isMipsN32Abi(const InputFile *f) {
535 switch (config->ekind) {
536 case ELF32LEKind:
537 return isN32Abi<ELF32LE>(f);
538 case ELF32BEKind:
539 return isN32Abi<ELF32BE>(f);
540 case ELF64LEKind:
541 return isN32Abi<ELF64LE>(f);
542 case ELF64BEKind:
543 return isN32Abi<ELF64BE>(f);
544 default:
545 llvm_unreachable("unknown Config->EKind");
546 }
547 }
548
isMicroMips()549 bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
550
isMipsR6()551 bool elf::isMipsR6() {
552 uint32_t arch = config->eflags & EF_MIPS_ARCH;
553 return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
554 }
555
556 template uint32_t elf::calcMipsEFlags<ELF32LE>();
557 template uint32_t elf::calcMipsEFlags<ELF32BE>();
558 template uint32_t elf::calcMipsEFlags<ELF64LE>();
559 template uint32_t elf::calcMipsEFlags<ELF64BE>();
560