File: | llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp |
Warning: | line 170, column 9 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===// | ||||
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 implements MCELFStreamer for Mips NaCl. It emits .o object files | ||||
10 | // as required by NaCl's SFI sandbox. It inserts address-masking instructions | ||||
11 | // before dangerous control-flow and memory access instructions. It inserts | ||||
12 | // address-masking instructions after instructions that change the stack | ||||
13 | // pointer. It ensures that the mask and the dangerous instruction are always | ||||
14 | // emitted in the same bundle. It aligns call + branch delay to the bundle end, | ||||
15 | // so that return address is always aligned to the start of next bundle. | ||||
16 | // | ||||
17 | //===----------------------------------------------------------------------===// | ||||
18 | |||||
19 | #include "Mips.h" | ||||
20 | #include "MipsELFStreamer.h" | ||||
21 | #include "MipsMCNaCl.h" | ||||
22 | #include "llvm/MC/MCAsmBackend.h" | ||||
23 | #include "llvm/MC/MCAssembler.h" | ||||
24 | #include "llvm/MC/MCCodeEmitter.h" | ||||
25 | #include "llvm/MC/MCELFStreamer.h" | ||||
26 | #include "llvm/MC/MCInst.h" | ||||
27 | #include "llvm/MC/MCObjectWriter.h" | ||||
28 | #include "llvm/Support/ErrorHandling.h" | ||||
29 | #include <cassert> | ||||
30 | |||||
31 | using namespace llvm; | ||||
32 | |||||
33 | #define DEBUG_TYPE"mips-mc-nacl" "mips-mc-nacl" | ||||
34 | |||||
35 | namespace { | ||||
36 | |||||
37 | const unsigned IndirectBranchMaskReg = Mips::T6; | ||||
38 | const unsigned LoadStoreStackMaskReg = Mips::T7; | ||||
39 | |||||
40 | /// Extend the generic MCELFStreamer class so that it can mask dangerous | ||||
41 | /// instructions. | ||||
42 | |||||
43 | class MipsNaClELFStreamer : public MipsELFStreamer { | ||||
44 | public: | ||||
45 | MipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, | ||||
46 | std::unique_ptr<MCObjectWriter> OW, | ||||
47 | std::unique_ptr<MCCodeEmitter> Emitter) | ||||
48 | : MipsELFStreamer(Context, std::move(TAB), std::move(OW), | ||||
49 | std::move(Emitter)) {} | ||||
50 | |||||
51 | ~MipsNaClELFStreamer() override = default; | ||||
52 | |||||
53 | private: | ||||
54 | // Whether we started the sandboxing sequence for calls. Calls are bundled | ||||
55 | // with branch delays and aligned to the bundle end. | ||||
56 | bool PendingCall = false; | ||||
57 | |||||
58 | bool isIndirectJump(const MCInst &MI) { | ||||
59 | if (MI.getOpcode() == Mips::JALR) { | ||||
60 | // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead. | ||||
61 | // JALR is an indirect branch if the link register is $0. | ||||
62 | assert(MI.getOperand(0).isReg())((MI.getOperand(0).isReg()) ? static_cast<void> (0) : __assert_fail ("MI.getOperand(0).isReg()", "/build/llvm-toolchain-snapshot-10~++20200107111111+051c4d5b7bc/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp" , 62, __PRETTY_FUNCTION__)); | ||||
63 | return MI.getOperand(0).getReg() == Mips::ZERO; | ||||
64 | } | ||||
65 | return MI.getOpcode() == Mips::JR; | ||||
66 | } | ||||
67 | |||||
68 | bool isStackPointerFirstOperand(const MCInst &MI) { | ||||
69 | return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() | ||||
70 | && MI.getOperand(0).getReg() == Mips::SP); | ||||
71 | } | ||||
72 | |||||
73 | bool isCall(const MCInst &MI, bool *IsIndirectCall) { | ||||
74 | unsigned Opcode = MI.getOpcode(); | ||||
75 | |||||
76 | *IsIndirectCall = false; | ||||
77 | |||||
78 | switch (Opcode) { | ||||
79 | default: | ||||
80 | return false; | ||||
81 | |||||
82 | case Mips::JAL: | ||||
83 | case Mips::BAL: | ||||
84 | case Mips::BAL_BR: | ||||
85 | case Mips::BLTZAL: | ||||
86 | case Mips::BGEZAL: | ||||
87 | return true; | ||||
88 | |||||
89 | case Mips::JALR: | ||||
90 | // JALR is only a call if the link register is not $0. Otherwise it's an | ||||
91 | // indirect branch. | ||||
92 | assert(MI.getOperand(0).isReg())((MI.getOperand(0).isReg()) ? static_cast<void> (0) : __assert_fail ("MI.getOperand(0).isReg()", "/build/llvm-toolchain-snapshot-10~++20200107111111+051c4d5b7bc/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp" , 92, __PRETTY_FUNCTION__)); | ||||
93 | if (MI.getOperand(0).getReg() == Mips::ZERO) | ||||
94 | return false; | ||||
95 | |||||
96 | *IsIndirectCall = true; | ||||
97 | return true; | ||||
98 | } | ||||
99 | } | ||||
100 | |||||
101 | void emitMask(unsigned AddrReg, unsigned MaskReg, | ||||
102 | const MCSubtargetInfo &STI) { | ||||
103 | MCInst MaskInst; | ||||
104 | MaskInst.setOpcode(Mips::AND); | ||||
105 | MaskInst.addOperand(MCOperand::createReg(AddrReg)); | ||||
106 | MaskInst.addOperand(MCOperand::createReg(AddrReg)); | ||||
107 | MaskInst.addOperand(MCOperand::createReg(MaskReg)); | ||||
108 | MipsELFStreamer::EmitInstruction(MaskInst, STI); | ||||
109 | } | ||||
110 | |||||
111 | // Sandbox indirect branch or return instruction by inserting mask operation | ||||
112 | // before it. | ||||
113 | void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) { | ||||
114 | unsigned AddrReg = MI.getOperand(0).getReg(); | ||||
115 | |||||
116 | EmitBundleLock(false); | ||||
117 | emitMask(AddrReg, IndirectBranchMaskReg, STI); | ||||
118 | MipsELFStreamer::EmitInstruction(MI, STI); | ||||
119 | EmitBundleUnlock(); | ||||
120 | } | ||||
121 | |||||
122 | // Sandbox memory access or SP change. Insert mask operation before and/or | ||||
123 | // after the instruction. | ||||
124 | void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx, | ||||
125 | const MCSubtargetInfo &STI, bool MaskBefore, | ||||
126 | bool MaskAfter) { | ||||
127 | EmitBundleLock(false); | ||||
128 | if (MaskBefore) { | ||||
129 | // Sandbox memory access. | ||||
130 | unsigned BaseReg = MI.getOperand(AddrIdx).getReg(); | ||||
131 | emitMask(BaseReg, LoadStoreStackMaskReg, STI); | ||||
132 | } | ||||
133 | MipsELFStreamer::EmitInstruction(MI, STI); | ||||
134 | if (MaskAfter) { | ||||
135 | // Sandbox SP change. | ||||
136 | unsigned SPReg = MI.getOperand(0).getReg(); | ||||
137 | assert((Mips::SP == SPReg) && "Unexpected stack-pointer register.")(((Mips::SP == SPReg) && "Unexpected stack-pointer register." ) ? static_cast<void> (0) : __assert_fail ("(Mips::SP == SPReg) && \"Unexpected stack-pointer register.\"" , "/build/llvm-toolchain-snapshot-10~++20200107111111+051c4d5b7bc/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp" , 137, __PRETTY_FUNCTION__)); | ||||
138 | emitMask(SPReg, LoadStoreStackMaskReg, STI); | ||||
139 | } | ||||
140 | EmitBundleUnlock(); | ||||
141 | } | ||||
142 | |||||
143 | public: | ||||
144 | /// This function is the one used to emit instruction data into the ELF | ||||
145 | /// streamer. We override it to mask dangerous instructions. | ||||
146 | void EmitInstruction(const MCInst &Inst, | ||||
147 | const MCSubtargetInfo &STI) override { | ||||
148 | // Sandbox indirect jumps. | ||||
149 | if (isIndirectJump(Inst)) { | ||||
| |||||
150 | if (PendingCall) | ||||
151 | report_fatal_error("Dangerous instruction in branch delay slot!"); | ||||
152 | sandboxIndirectJump(Inst, STI); | ||||
153 | return; | ||||
154 | } | ||||
155 | |||||
156 | // Sandbox loads, stores and SP changes. | ||||
157 | unsigned AddrIdx; | ||||
158 | bool IsStore; | ||||
159 | bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx, | ||||
160 | &IsStore); | ||||
161 | bool IsSPFirstOperand = isStackPointerFirstOperand(Inst); | ||||
162 | if (IsMemAccess
| ||||
163 | bool MaskBefore = (IsMemAccess |
20.1 | 'IsMemAccess' is false |
20.2 | 'IsSPFirstOperand' is true |
20.3 | 'MaskBefore' is false |
20.4 | 'MaskAfter' is true |
24 | 2nd function call argument is an uninitialized value |
9.1 | 'IsStore' is non-null |