|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | #include "llvm/Transforms/Utils/ModuleUtils.h"
|
14 |
| -#include "llvm/Analysis/VectorUtils.h" |
15 | 14 | #include "llvm/ADT/SmallString.h"
|
| 15 | +#include "llvm/Analysis/VectorUtils.h" |
16 | 16 | #include "llvm/IR/DerivedTypes.h"
|
17 | 17 | #include "llvm/IR/Function.h"
|
18 | 18 | #include "llvm/IR/IRBuilder.h"
|
|
21 | 21 | #include "llvm/Support/MD5.h"
|
22 | 22 | #include "llvm/Support/raw_ostream.h"
|
23 | 23 | #include "llvm/Support/xxhash.h"
|
| 24 | +#include "llvm/TargetParser/Triple.h" |
24 | 25 |
|
25 | 26 | using namespace llvm;
|
26 | 27 |
|
@@ -208,10 +209,34 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
|
208 | 209 | std::string Type = MangledType.str();
|
209 | 210 | if (M.getModuleFlag("cfi-normalize-integers"))
|
210 | 211 | Type += ".normalized";
|
| 212 | + |
| 213 | + uint32_t OutHash = static_cast<uint32_t>(llvm::xxHash64(Type)); |
| 214 | + auto T = Triple(Twine(M.getTargetTriple())); |
| 215 | + if (T.isX86() && T.isArch64Bit() && T.isOSLinux()) { |
| 216 | + // Estimate the function's arity (i.e., the number of arguments) at the ABI |
| 217 | + // level by counting the number of parameters that are likely to be passed |
| 218 | + // as registers, such as pointers and 64-bit (or smaller) integers. The |
| 219 | + // Linux x86-64 ABI allows up to 6 parameters to be passed in GPRs. |
| 220 | + // Additional parameters or parameters larger than 64 bits may be passed on |
| 221 | + // the stack, in which case the arity is denoted as 7. |
| 222 | + size_t NumParams = F.arg_size(); |
| 223 | + bool MayHaveStackArgs = NumParams > 6; |
| 224 | + |
| 225 | + for (unsigned int i = 0; !MayHaveStackArgs && i < NumParams; ++i) { |
| 226 | + const llvm::Type *PT = F.getArg(i)->getType(); |
| 227 | + if (!(PT->isPointerTy() || PT->getIntegerBitWidth() <= 64)) |
| 228 | + MayHaveStackArgs = true; |
| 229 | + } |
| 230 | + |
| 231 | + // The 3-bit arity is concatenated with the lower 29 bits of the KCFI hash |
| 232 | + // to form an enhanced KCFI type ID. This can prevent, for example, a |
| 233 | + // 3-arity function's ID from ever colliding with a 2-arity function's ID. |
| 234 | + OutHash = (OutHash << 3) | (MayHaveStackArgs ? 7 : NumParams); |
| 235 | + } |
| 236 | + |
211 | 237 | F.setMetadata(LLVMContext::MD_kcfi_type,
|
212 | 238 | MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
|
213 |
| - Type::getInt32Ty(Ctx), |
214 |
| - static_cast<uint32_t>(xxHash64(Type)))))); |
| 239 | + Type::getInt32Ty(Ctx), OutHash)))); |
215 | 240 | // If the module was compiled with -fpatchable-function-entry, ensure
|
216 | 241 | // we use the same patchable-function-prefix.
|
217 | 242 | if (auto *MD = mdconst::extract_or_null<ConstantInt>(
|
|
0 commit comments