|
24 | 24 | #include "llvm/BinaryFormat/GOFF.h" |
25 | 25 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" |
26 | 26 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
| 27 | +#include "llvm/IR/GlobalVariable.h" |
27 | 28 | #include "llvm/IR/Mangler.h" |
28 | 29 | #include "llvm/IR/Module.h" |
29 | 30 | #include "llvm/MC/MCExpr.h" |
| 31 | +#include "llvm/MC/MCInst.h" |
30 | 32 | #include "llvm/MC/MCInstBuilder.h" |
31 | 33 | #include "llvm/MC/MCSectionELF.h" |
32 | 34 | #include "llvm/MC/MCStreamer.h" |
@@ -213,6 +215,16 @@ SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) { |
213 | 215 | return insert(Sym, ADAslotType); |
214 | 216 | } |
215 | 217 |
|
| 218 | +namespace { |
| 219 | +unsigned long getStackGuardOffset(const MachineBasicBlock *MBB) { |
| 220 | + // In the TLS (default) case, AddrReg will contain the thread pointer, so we |
| 221 | + // need to add 40 bytes to get the actual address of the stack guard. |
| 222 | + StringRef GuardType = |
| 223 | + MBB->getParent()->getFunction().getParent()->getStackProtectorGuard(); |
| 224 | + return (GuardType == "global") ? 0 : 40; |
| 225 | +} |
| 226 | +} // namespace |
| 227 | + |
216 | 228 | void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { |
217 | 229 | SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), |
218 | 230 | getSubtargetInfo().getFeatureBits()); |
@@ -740,13 +752,128 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { |
740 | 752 | case SystemZ::EH_SjLj_Setup: |
741 | 753 | return; |
742 | 754 |
|
| 755 | + case SystemZ::LOAD_STACK_GUARD: { |
| 756 | + // If requested, record address of stack guard address load |
| 757 | + if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record")) |
| 758 | + emitStackProtectorLocEntry(); |
| 759 | + Register AddrReg = emitLoadStackGuardAddress(MI); |
| 760 | + LoweredMI = MCInstBuilder(SystemZ::LG) |
| 761 | + .addReg(AddrReg) |
| 762 | + .addImm(getStackGuardOffset(MI->getParent())) |
| 763 | + .addReg(0); |
| 764 | + } break; |
| 765 | + |
| 766 | + case SystemZ::LOAD_STACK_GUARD_ADDRESS: |
| 767 | + // If requested, record address of stack guard address load |
| 768 | + if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record")) |
| 769 | + emitStackProtectorLocEntry(); |
| 770 | + emitLoadStackGuardAddress(MI); |
| 771 | + return; |
| 772 | + |
| 773 | + case SystemZ::COMPARE_STACK_GUARD: |
| 774 | + LoweredMI = MCInstBuilder(SystemZ::CLC) |
| 775 | + .addReg(MI->getOperand(0).getReg()) |
| 776 | + .addImm(MI->getOperand(1).getImm()) |
| 777 | + .addImm(8) |
| 778 | + .addReg(MI->getOperand(2).getReg()) |
| 779 | + .addImm(getStackGuardOffset(MI->getParent())); |
| 780 | + break; |
| 781 | + |
| 782 | + case SystemZ::MOVE_STACK_GUARD: |
| 783 | + LoweredMI = MCInstBuilder(SystemZ::MVC) |
| 784 | + .addReg(MI->getOperand(0).getReg()) |
| 785 | + .addImm(MI->getOperand(1).getImm()) |
| 786 | + .addImm(8) |
| 787 | + .addReg(MI->getOperand(2).getReg()) |
| 788 | + .addImm(getStackGuardOffset(MI->getParent())); |
| 789 | + break; |
| 790 | + |
743 | 791 | default: |
744 | 792 | Lower.lower(MI, LoweredMI); |
745 | 793 | break; |
746 | 794 | } |
747 | 795 | EmitToStreamer(*OutStreamer, LoweredMI); |
748 | 796 | } |
749 | 797 |
|
| 798 | +void SystemZAsmPrinter::emitStackProtectorLocEntry() { |
| 799 | + MCSymbol *Sym = OutContext.createTempSymbol(); |
| 800 | + OutStreamer->pushSection(); |
| 801 | + OutStreamer->switchSection(OutContext.getELFSection( |
| 802 | + "__stack_protector_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); |
| 803 | + OutStreamer->emitSymbolValue(Sym, getDataLayout().getPointerSize()); |
| 804 | + OutStreamer->popSection(); |
| 805 | + OutStreamer->emitLabel(Sym); |
| 806 | +} |
| 807 | + |
| 808 | +// Emit the stack guard address load, depending on guard type. |
| 809 | +// Return the register the stack guard address was loaded into. |
| 810 | +Register SystemZAsmPrinter::emitLoadStackGuardAddress(const MachineInstr *MI) { |
| 811 | + const MachineBasicBlock *MBB = MI->getParent(); |
| 812 | + const MachineFunction &MF = *MBB->getParent(); |
| 813 | + const Register AddrReg = MI->getOperand(0).getReg(); |
| 814 | + const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); |
| 815 | + const Register Reg32 = MRI.getSubReg(AddrReg, SystemZ::subreg_l32); |
| 816 | + |
| 817 | + const Module *M = MF.getFunction().getParent(); |
| 818 | + StringRef GuardType = M->getStackProtectorGuard(); |
| 819 | + |
| 820 | + if (GuardType.empty() || (GuardType == "tls")) { |
| 821 | + // EAR can only load the low subregister so use a shift for %a0 to produce |
| 822 | + // the GR containing %a0 and %a1. |
| 823 | + |
| 824 | + // ear <reg>, %a0 |
| 825 | + MCInst EAR1 = MCInstBuilder(SystemZ::EAR) |
| 826 | + .addReg(Reg32) |
| 827 | + .addReg(SystemZ::A0) |
| 828 | + .addReg(AddrReg); |
| 829 | + |
| 830 | + // sllg <reg>, <reg>, 32 |
| 831 | + MCInst SLLG = MCInstBuilder(SystemZ::SLLG) |
| 832 | + .addReg(AddrReg) |
| 833 | + .addReg(AddrReg) |
| 834 | + .addReg(0) |
| 835 | + .addImm(32); |
| 836 | + |
| 837 | + // ear <reg>, %a1 |
| 838 | + MCInst EAR2 = MCInstBuilder(SystemZ::EAR) |
| 839 | + .addReg(Reg32) |
| 840 | + .addReg(SystemZ::A1) |
| 841 | + .addReg(AddrReg); |
| 842 | + |
| 843 | + EmitToStreamer(*OutStreamer, EAR1); |
| 844 | + EmitToStreamer(*OutStreamer, SLLG); |
| 845 | + EmitToStreamer(*OutStreamer, EAR2); |
| 846 | + } else if (GuardType == "global") { |
| 847 | + // Obtain the global value. |
| 848 | + const auto *GV = M->getGlobalVariable( |
| 849 | + "__stack_chk_guard", PointerType::getUnqual(M->getContext())); |
| 850 | + assert(GV && |
| 851 | + "could not create reference to global variable __stack_chk_guard"); |
| 852 | + auto *Sym = TM.getSymbol(GV); |
| 853 | + // Ref-> |
| 854 | + // Emit the address load. |
| 855 | + MCInst Load; |
| 856 | + if (M->getPICLevel() == PICLevel::NotPIC) { |
| 857 | + Load = MCInstBuilder(SystemZ::LARL) |
| 858 | + .addReg(AddrReg) |
| 859 | + .addExpr(MCSymbolRefExpr::create(Sym, OutContext)); |
| 860 | + } else { |
| 861 | + Load = |
| 862 | + MCInstBuilder(SystemZ::LGRL) |
| 863 | + .addReg(AddrReg) |
| 864 | + .addExpr(MCSymbolRefExpr::create(Sym, SystemZ::S_GOT, OutContext)) |
| 865 | + .addExpr(getGlobalOffsetTable(OutContext)); |
| 866 | + } |
| 867 | + EmitToStreamer(*OutStreamer, Load); |
| 868 | + } else { |
| 869 | + llvm_unreachable( |
| 870 | + (Twine("Unknown stack protector type \"") + GuardType + "\"") |
| 871 | + .str() |
| 872 | + .c_str()); |
| 873 | + } |
| 874 | + return AddrReg; |
| 875 | +} |
| 876 | + |
750 | 877 | // Emit the largest nop instruction smaller than or equal to NumBytes |
751 | 878 | // bytes. Return the size of nop emitted. |
752 | 879 | static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, |
|
0 commit comments