|
28 | 28 | #include "llvm/ADT/Triple.h"
|
29 | 29 | #include "llvm/ADT/Twine.h"
|
30 | 30 | #include "llvm/BinaryFormat/COFF.h"
|
| 31 | +#include "llvm/BinaryFormat/ELF.h" |
31 | 32 | #include "llvm/CodeGen/AsmPrinter.h"
|
32 | 33 | #include "llvm/CodeGen/MachineBasicBlock.h"
|
33 | 34 | #include "llvm/CodeGen/MachineFunction.h"
|
|
43 | 44 | #include "llvm/MC/MCContext.h"
|
44 | 45 | #include "llvm/MC/MCInst.h"
|
45 | 46 | #include "llvm/MC/MCInstBuilder.h"
|
| 47 | +#include "llvm/MC/MCSectionELF.h" |
46 | 48 | #include "llvm/MC/MCStreamer.h"
|
47 | 49 | #include "llvm/MC/MCSymbol.h"
|
48 | 50 | #include "llvm/Support/Casting.h"
|
@@ -95,6 +97,10 @@ class AArch64AsmPrinter : public AsmPrinter {
|
95 | 97 | void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
|
96 | 98 | void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
|
97 | 99 |
|
| 100 | + std::map<std::pair<unsigned, uint32_t>, MCSymbol *> HwasanMemaccessSymbols; |
| 101 | + void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI); |
| 102 | + void EmitHwasanMemaccessSymbols(Module &M); |
| 103 | + |
98 | 104 | void EmitSled(const MachineInstr &MI, SledKind Kind);
|
99 | 105 |
|
100 | 106 | /// tblgen'erated driver function for lowering simple MI->MC
|
@@ -229,7 +235,109 @@ void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
|
229 | 235 | recordSled(CurSled, MI, Kind);
|
230 | 236 | }
|
231 | 237 |
|
| 238 | +void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) { |
| 239 | + unsigned Reg = MI.getOperand(0).getReg(); |
| 240 | + uint32_t AccessInfo = MI.getOperand(1).getImm(); |
| 241 | + MCSymbol *&Sym = HwasanMemaccessSymbols[{Reg, AccessInfo}]; |
| 242 | + if (!Sym) { |
| 243 | + // FIXME: Make this work on non-ELF. |
| 244 | + if (!TM.getTargetTriple().isOSBinFormatELF()) |
| 245 | + report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF"); |
| 246 | + |
| 247 | + std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" + |
| 248 | + utostr(AccessInfo); |
| 249 | + Sym = OutContext.getOrCreateSymbol(SymName); |
| 250 | + } |
| 251 | + |
| 252 | + EmitToStreamer(*OutStreamer, |
| 253 | + MCInstBuilder(AArch64::BL) |
| 254 | + .addExpr(MCSymbolRefExpr::create(Sym, OutContext))); |
| 255 | +} |
| 256 | + |
| 257 | +void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) { |
| 258 | + if (HwasanMemaccessSymbols.empty()) |
| 259 | + return; |
| 260 | + |
| 261 | + const Triple &TT = TM.getTargetTriple(); |
| 262 | + assert(TT.isOSBinFormatELF()); |
| 263 | + std::unique_ptr<MCSubtargetInfo> STI( |
| 264 | + TM.getTarget().createMCSubtargetInfo(TT.str(), "", "")); |
| 265 | + |
| 266 | + MCSymbol *HwasanTagMismatchSym = |
| 267 | + OutContext.getOrCreateSymbol("__hwasan_tag_mismatch"); |
| 268 | + |
| 269 | + for (auto &P : HwasanMemaccessSymbols) { |
| 270 | + unsigned Reg = P.first.first; |
| 271 | + uint32_t AccessInfo = P.first.second; |
| 272 | + MCSymbol *Sym = P.second; |
| 273 | + |
| 274 | + OutStreamer->SwitchSection(OutContext.getELFSection( |
| 275 | + ".text.hot", ELF::SHT_PROGBITS, |
| 276 | + ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, |
| 277 | + Sym->getName())); |
| 278 | + |
| 279 | + OutStreamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); |
| 280 | + OutStreamer->EmitSymbolAttribute(Sym, MCSA_Weak); |
| 281 | + OutStreamer->EmitSymbolAttribute(Sym, MCSA_Hidden); |
| 282 | + OutStreamer->EmitLabel(Sym); |
| 283 | + |
| 284 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::UBFMXri) |
| 285 | + .addReg(AArch64::X16) |
| 286 | + .addReg(Reg) |
| 287 | + .addImm(4) |
| 288 | + .addImm(55), |
| 289 | + *STI); |
| 290 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::LDRBBroX) |
| 291 | + .addReg(AArch64::W16) |
| 292 | + .addReg(AArch64::X9) |
| 293 | + .addReg(AArch64::X16) |
| 294 | + .addImm(0) |
| 295 | + .addImm(0), |
| 296 | + *STI); |
| 297 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::UBFMXri) |
| 298 | + .addReg(AArch64::X17) |
| 299 | + .addReg(Reg) |
| 300 | + .addImm(56) |
| 301 | + .addImm(63), |
| 302 | + *STI); |
| 303 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWrs) |
| 304 | + .addReg(AArch64::WZR) |
| 305 | + .addReg(AArch64::W16) |
| 306 | + .addReg(AArch64::W17) |
| 307 | + .addImm(0), |
| 308 | + *STI); |
| 309 | + MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); |
| 310 | + OutStreamer->EmitInstruction( |
| 311 | + MCInstBuilder(AArch64::Bcc) |
| 312 | + .addImm(AArch64CC::NE) |
| 313 | + .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), |
| 314 | + *STI); |
| 315 | + OutStreamer->EmitInstruction( |
| 316 | + MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI); |
| 317 | + |
| 318 | + OutStreamer->EmitLabel(HandleMismatchSym); |
| 319 | + if (Reg != AArch64::X0) |
| 320 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ORRXrs) |
| 321 | + .addReg(AArch64::X0) |
| 322 | + .addReg(AArch64::XZR) |
| 323 | + .addReg(Reg) |
| 324 | + .addImm(0), |
| 325 | + *STI); |
| 326 | + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::MOVZXi) |
| 327 | + .addReg(AArch64::X1) |
| 328 | + .addImm(AccessInfo) |
| 329 | + .addImm(0), |
| 330 | + *STI); |
| 331 | + OutStreamer->EmitInstruction( |
| 332 | + MCInstBuilder(AArch64::B) |
| 333 | + .addExpr(MCSymbolRefExpr::create(HwasanTagMismatchSym, OutContext)), |
| 334 | + *STI); |
| 335 | + } |
| 336 | +} |
| 337 | + |
232 | 338 | void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
|
| 339 | + EmitHwasanMemaccessSymbols(M); |
| 340 | + |
233 | 341 | const Triple &TT = TM.getTargetTriple();
|
234 | 342 | if (TT.isOSBinFormatMachO()) {
|
235 | 343 | // Funny Darwin hack: This flag tells the linker that no global symbols
|
@@ -883,6 +991,10 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
883 | 991 | LowerPATCHABLE_TAIL_CALL(*MI);
|
884 | 992 | return;
|
885 | 993 |
|
| 994 | + case AArch64::HWASAN_CHECK_MEMACCESS: |
| 995 | + LowerHWASAN_CHECK_MEMACCESS(*MI); |
| 996 | + return; |
| 997 | + |
886 | 998 | case AArch64::SEH_StackAlloc:
|
887 | 999 | TS->EmitARM64WinCFIAllocStack(MI->getOperand(0).getImm());
|
888 | 1000 | return;
|
|
0 commit comments