LLVM: lib/CodeGen/WindowsSecureHotPatching.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

150

151using namespace llvm;

152

153#define DEBUG_TYPE "windows-secure-hot-patch"

154

155

157 "ms-secure-hotpatch-functions-file", cl::value_desc("filename"),

158 cl::desc("A file containing list of mangled function names to mark for "

159 "Windows Secure Hot-Patching"));

160

161

163 "ms-secure-hotpatch-functions-list", cl::value_desc("list"),

164 cl::desc("A list of mangled function names to mark for Windows Secure "

165 "Hot-Patching"),

167

168namespace {

169

170struct GlobalVariableUse {

171

173 unsigned Op;

174};

175

176class WindowsSecureHotPatching : public ModulePass {

177public:

178 static char ID;

179

180 WindowsSecureHotPatching() : ModulePass(ID) {

182 }

183

184 void getAnalysisUsage(AnalysisUsage &AU) const override {

186 }

187

188 bool doInitialization(Module &) override;

189 bool runOnModule(Module &M) override { return false; }

190

191private:

192 bool

194 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping);

195};

196

197}

198

199char WindowsSecureHotPatching::ID = 0;

200

202 "Mark functions for Windows hot patch support", false, false)

204 return new WindowsSecureHotPatching();

205}

206

207

208

209

210

211

212bool WindowsSecureHotPatching::doInitialization(Module &M) {

213

214

215

216

219 std::vectorstd::string HotPatchFunctionsList;

220

223 if (BufOrErr) {

224 const MemoryBuffer &FileBuffer = **BufOrErr;

226 ++I)

227 HotPatchFunctionsList.push_back(std::string{*I});

228 } else {

229 M.getContext().diagnose(DiagnosticInfoGeneric{

230 Twine("failed to open hotpatch functions file "

231 "(--ms-hotpatch-functions-file): ") +

233 BufOrErr.getError().message()});

234 }

235 }

236

239 HotPatchFunctionsList.push_back(FuncName);

240

241

242

243 SmallSet<StringRef, 16> HotPatchFunctionsSet;

244 for (const auto &FuncName : HotPatchFunctionsList)

245 HotPatchFunctionsSet.insert(StringRef{FuncName});

246

247

248

249 for (auto &F : M.functions()) {

250

251 if (F.isDeclarationForLinker())

252 continue;

253

254 if (HotPatchFunctionsSet.contains(F.getName()))

255 F.addFnAttr("marked_for_windows_hot_patching");

256 }

257 }

258

259 SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping;

260 bool MadeChanges = false;

261 for (auto &F : M.functions()) {

262 if (F.hasFnAttribute("marked_for_windows_hot_patching")) {

264 MadeChanges = true;

265 }

266 }

267 return MadeChanges;

268}

269

273 return true;

274

277

280 for (unsigned I = 0; I < NumElements; ++I) {

282 return true;

283 }

284 }

285 return false;

286 }

287

288 default:

289 return false;

290 }

291}

292

293

295

296

297 if (GV->hasAttribute("allow_direct_access_in_hot_patch_function"))

298 return false;

299

300

303

304

305

306 return false;

307 }

308

309

310 return true;

311 }

312

313

314

315

317}

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

350 if (ReplaceWithRefGV != nullptr) {

351

352 return ReplaceWithRefGV;

353 }

354

355 Module *M = F.getParent();

356

357 const DISubprogram *Subprogram = F.getSubprogram();

358 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;

359 DIFile *File = Subprogram != nullptr ? Subprogram->getFile() : nullptr;

361

363

366

371

372

373

374

375

376

377

378

379

380

381

382

383 RefGV->setSection(".rdata");

384

385

386 DataLayout Layout = M->getDataLayout();

390 Unit, RefGV->getName(), StringRef{}, File,

391 0, DebugType,

392 false);

393 RefGV->addDebugInfo(GVE);

394

395

396 ReplaceWithRefGV = RefGV;

397

398 return RefGV;

399}

400

401

402

403

404

405

406

407

408

412 if (C->getValueID() == Value::GlobalVariableVal) {

415 return GVLoadMap.at(GV);

416 } else {

417 return nullptr;

418 }

419 }

420

421

422

424 bool ReplacedAnyOperands = false;

425

426 unsigned NumOperands = C->getNumOperands();

429 Value *ReplacedValue = nullptr;

432 IRBuilderAtEntry);

433 }

434

435 ReplacedAnyOperands |= ReplacedValue != nullptr;

436 ReplacedValues.push_back(ReplacedValue);

437 }

438

439

440 if (!ReplacedAnyOperands) {

441 return nullptr;

442 }

443

444

445

448 Value *ReplacedValue = ReplacedValues[OpIndex];

449 if (ReplacedValue != nullptr) {

451 }

452 }

453

454

455 IRBuilderAtEntry.Insert(NewInst);

456

457 return NewInst;

458}

459

463

466 GVLoadMap[GV] = nullptr;

467 return true;

468 } else {

469 return false;

470 }

471 }

472

474 unsigned NumOperands = U->getNumOperands();

475 bool FoundAny = false;

478

480 }

481 return FoundAny;

482 } else {

483 return false;

484 }

485}

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507bool WindowsSecureHotPatching::runOnFunction(

508 Function &F,

509 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) {

510

511

512

513

514

515

516

517 SmallDenseMap<GlobalVariable *, Value *> GVLoadMap;

519

521 unsigned NumOperands = I.getNumOperands();

524

525 bool FoundAnyGVUses = false;

526

527 switch (V->getValueID()) {

528 case Value::GlobalVariableVal: {

529

532 GVLoadMap.insert(std::make_pair(GV, nullptr));

533 FoundAnyGVUses = true;

534 }

535 break;

536 }

537

538 case Value::ConstantExprVal: {

541 FoundAnyGVUses = true;

542 }

543 break;

544 }

545

546 default:

547 break;

548 }

549

550 if (FoundAnyGVUses) {

552 }

553 }

554 }

555

556

557

558 if (GVUses.empty()) {

559 return false;

560 }

561

562

563

564

565

566

567

568

569

570

571

572

573 auto &EntryBlock = F.getEntryBlock();

574 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin());

575

576 for (auto &[GV, LoadValue] : GVLoadMap) {

577 assert(LoadValue == nullptr);

579 LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->getValueType(), RefGV);

580 }

581

582 const DISubprogram *Subprogram = F.getSubprogram();

583 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr;

585

586

587

588

589

590 for (auto &GVUse : GVUses) {

591 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op);

592 Value *NewOperandValue;

593

594 switch (OldOperandValue->getValueID()) {

595 case Value::GlobalVariableVal: {

596

597 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);

599 NewOperandValue = GVLoadMap.at(GV);

600 break;

601 }

602

603 case Value::ConstantExprVal: {

604

605

606

607

608 Value *OperandValue = GVUse.User->getOperand(GVUse.Op);

610 NewOperandValue =

612 assert(NewOperandValue != nullptr);

613 break;

614 }

615

616 default:

617

618

620 "unexpected Value in second pass of hot-patching");

621 break;

622 }

623

624 GVUse.User->setOperand(GVUse.Op, NewOperandValue);

625 }

626

627 return true;

628}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Expand Atomic instructions

This file contains the simple types necessary to represent the attributes associated with functions a...

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static bool runOnFunction(Function &F, bool PostInlining)

Module.h This file contains the declarations for the Module class.

Machine Check Debug Module

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

This file defines the SmallSet class.

static GlobalVariable * getOrCreateRefVariable(Function &F, SmallDenseMap< GlobalVariable *, GlobalVariable * > &RefMapping, GlobalVariable *GV)

Definition WindowsSecureHotPatching.cpp:346

static bool globalVariableNeedsRedirect(GlobalVariable *GV)

Definition WindowsSecureHotPatching.cpp:294

static cl::list< std::string > LLVMMSSecureHotPatchFunctionsList("ms-secure-hotpatch-functions-list", cl::value_desc("list"), cl::desc("A list of mangled function names to mark for Windows Secure " "Hot-Patching"), cl::CommaSeparated)

static bool searchConstantExprForGlobalVariables(Value *V, SmallDenseMap< GlobalVariable *, Value * > &GVLoadMap, SmallVector< GlobalVariableUse > &GVUses)

Definition WindowsSecureHotPatching.cpp:460

static Value * rewriteGlobalVariablesInConstant(Constant *C, SmallDenseMap< GlobalVariable *, Value * > &GVLoadMap, IRBuilder<> &IRBuilderAtEntry)

Definition WindowsSecureHotPatching.cpp:409

static bool TypeContainsPointers(Type *ty)

Definition WindowsSecureHotPatching.cpp:270

static cl::opt< std::string > LLVMMSSecureHotPatchFunctionsFile("ms-secure-hotpatch-functions-file", cl::value_desc("filename"), cl::desc("A file containing list of mangled function names to mark for " "Windows Secure Hot-Patching"))

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)

Getelementptr form.

This is an important base class in LLVM.

A pair of DIGlobalVariable and DIExpression.

Subprogram description. Uses SubclassData1.

A parsed version of the target data layout string in and methods for querying it.

TypeSize getTypeSizeInBits(Type *Ty) const

Size examples:

ValueT & at(const_arg_type_t< KeyT > Val)

at - Return the entry for the specified key, or abort if no such entry exists.

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

@ LinkOnceAnyLinkage

Keep one copy of function when linking (inline)

Type * getValueType() const

bool hasAttribute(Attribute::AttrKind Kind) const

Return true if the attribute exists.

bool isConstant() const

If the value is a global constant, its value is immutable throughout the runtime execution of the pro...

InstTy * Insert(InstTy *I, const Twine &Name="") const

Insert and return the specified instruction.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

MemoryBufferRef getMemBufferRef() const

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

A Module instance is used to store all the information related to an LLVM module.

static LLVM_ABI PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)

This constructs a pointer to an object of the specified type in a numbered address space.

bool contains(const T &V) const

Check if the SmallSet contains the given element.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI Type * getStructElementType(unsigned N) const

Type * getArrayElementType() const

LLVM_ABI unsigned getStructNumElements() const

TypeID getTypeID() const

Return the type id for the type.

void setOperand(unsigned i, Value *Val)

LLVM Value Representation.

unsigned getValueID() const

Return an ID for the concrete type of this object.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

@ C

The default llvm calling convention, compatible with C.

@ CE

Windows NT (Windows on ARM)

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)

Returns a concatenated range across two or more ranges.

LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)

This function calls abort(), and prints the optional message to stderr.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

LLVM_ABI void initializeWindowsSecureHotPatchingPass(PassRegistry &)

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI ModulePass * createWindowsSecureHotPatchingPass()

Creates Windows Secure Hot Patch pass.