File: | lib/MC/MCWinCOFFStreamer.cpp |
Warning: | line 274, column 1 Potential leak of memory pointed to by 'Fragment' |
[?] Use j/k keys for keyboard navigation
1 | //===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file contains an implementation of a Windows COFF object file streamer. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "llvm/ADT/SmallString.h" | |||
15 | #include "llvm/ADT/SmallVector.h" | |||
16 | #include "llvm/ADT/Triple.h" | |||
17 | #include "llvm/ADT/Twine.h" | |||
18 | #include "llvm/BinaryFormat/COFF.h" | |||
19 | #include "llvm/MC/MCAsmBackend.h" | |||
20 | #include "llvm/MC/MCAssembler.h" | |||
21 | #include "llvm/MC/MCCodeEmitter.h" | |||
22 | #include "llvm/MC/MCContext.h" | |||
23 | #include "llvm/MC/MCExpr.h" | |||
24 | #include "llvm/MC/MCFixup.h" | |||
25 | #include "llvm/MC/MCFragment.h" | |||
26 | #include "llvm/MC/MCObjectFileInfo.h" | |||
27 | #include "llvm/MC/MCObjectStreamer.h" | |||
28 | #include "llvm/MC/MCSection.h" | |||
29 | #include "llvm/MC/MCSymbolCOFF.h" | |||
30 | #include "llvm/MC/MCWinCOFFStreamer.h" | |||
31 | #include "llvm/Support/Casting.h" | |||
32 | #include "llvm/Support/ErrorHandling.h" | |||
33 | #include "llvm/Support/MathExtras.h" | |||
34 | #include "llvm/Support/SMLoc.h" | |||
35 | #include "llvm/Support/raw_ostream.h" | |||
36 | #include <algorithm> | |||
37 | #include <cassert> | |||
38 | #include <cstdint> | |||
39 | ||||
40 | using namespace llvm; | |||
41 | ||||
42 | #define DEBUG_TYPE"WinCOFFStreamer" "WinCOFFStreamer" | |||
43 | ||||
44 | MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, | |||
45 | std::unique_ptr<MCAsmBackend> MAB, | |||
46 | std::unique_ptr<MCCodeEmitter> CE, | |||
47 | raw_pwrite_stream &OS) | |||
48 | : MCObjectStreamer(Context, std::move(MAB), OS, std::move(CE)), | |||
49 | CurSymbol(nullptr) {} | |||
50 | ||||
51 | void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, | |||
52 | const MCSubtargetInfo &STI) { | |||
53 | MCDataFragment *DF = getOrCreateDataFragment(); | |||
54 | ||||
55 | SmallVector<MCFixup, 4> Fixups; | |||
56 | SmallString<256> Code; | |||
57 | raw_svector_ostream VecOS(Code); | |||
58 | getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); | |||
59 | ||||
60 | // Add the fixups and data. | |||
61 | for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { | |||
62 | Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); | |||
63 | DF->getFixups().push_back(Fixups[i]); | |||
64 | } | |||
65 | ||||
66 | DF->getContents().append(Code.begin(), Code.end()); | |||
67 | } | |||
68 | ||||
69 | void MCWinCOFFStreamer::InitSections(bool NoExecStack) { | |||
70 | // FIXME: this is identical to the ELF one. | |||
71 | // This emulates the same behavior of GNU as. This makes it easier | |||
72 | // to compare the output as the major sections are in the same order. | |||
73 | SwitchSection(getContext().getObjectFileInfo()->getTextSection()); | |||
74 | EmitCodeAlignment(4); | |||
75 | ||||
76 | SwitchSection(getContext().getObjectFileInfo()->getDataSection()); | |||
77 | EmitCodeAlignment(4); | |||
78 | ||||
79 | SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); | |||
80 | EmitCodeAlignment(4); | |||
81 | ||||
82 | SwitchSection(getContext().getObjectFileInfo()->getTextSection()); | |||
83 | } | |||
84 | ||||
85 | void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { | |||
86 | auto *Symbol = cast<MCSymbolCOFF>(S); | |||
87 | MCObjectStreamer::EmitLabel(Symbol, Loc); | |||
88 | } | |||
89 | ||||
90 | void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { | |||
91 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 91); | |||
92 | } | |||
93 | ||||
94 | void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { | |||
95 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 95); | |||
96 | } | |||
97 | ||||
98 | bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S, | |||
99 | MCSymbolAttr Attribute) { | |||
100 | auto *Symbol = cast<MCSymbolCOFF>(S); | |||
101 | getAssembler().registerSymbol(*Symbol); | |||
102 | ||||
103 | switch (Attribute) { | |||
104 | default: return false; | |||
105 | case MCSA_WeakReference: | |||
106 | case MCSA_Weak: | |||
107 | Symbol->setIsWeakExternal(); | |||
108 | Symbol->setExternal(true); | |||
109 | break; | |||
110 | case MCSA_Global: | |||
111 | Symbol->setExternal(true); | |||
112 | break; | |||
113 | case MCSA_AltEntry: | |||
114 | llvm_unreachable("COFF doesn't support the .alt_entry attribute")::llvm::llvm_unreachable_internal("COFF doesn't support the .alt_entry attribute" , "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 114); | |||
115 | } | |||
116 | ||||
117 | return true; | |||
118 | } | |||
119 | ||||
120 | void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { | |||
121 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 121); | |||
122 | } | |||
123 | ||||
124 | void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { | |||
125 | auto *Symbol = cast<MCSymbolCOFF>(S); | |||
126 | if (CurSymbol) | |||
127 | Error("starting a new symbol definition without completing the " | |||
128 | "previous one"); | |||
129 | CurSymbol = Symbol; | |||
130 | } | |||
131 | ||||
132 | void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { | |||
133 | if (!CurSymbol) { | |||
134 | Error("storage class specified outside of symbol definition"); | |||
135 | return; | |||
136 | } | |||
137 | ||||
138 | if (StorageClass & ~COFF::SSC_Invalid) { | |||
139 | Error("storage class value '" + Twine(StorageClass) + | |||
140 | "' out of range"); | |||
141 | return; | |||
142 | } | |||
143 | ||||
144 | getAssembler().registerSymbol(*CurSymbol); | |||
145 | cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass); | |||
146 | } | |||
147 | ||||
148 | void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { | |||
149 | if (!CurSymbol) { | |||
150 | Error("symbol type specified outside of a symbol definition"); | |||
151 | return; | |||
152 | } | |||
153 | ||||
154 | if (Type & ~0xffff) { | |||
155 | Error("type value '" + Twine(Type) + "' out of range"); | |||
156 | return; | |||
157 | } | |||
158 | ||||
159 | getAssembler().registerSymbol(*CurSymbol); | |||
160 | cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type); | |||
161 | } | |||
162 | ||||
163 | void MCWinCOFFStreamer::EndCOFFSymbolDef() { | |||
164 | if (!CurSymbol) | |||
165 | Error("ending symbol definition without starting one"); | |||
166 | CurSymbol = nullptr; | |||
167 | } | |||
168 | ||||
169 | void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { | |||
170 | // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is | |||
171 | // unnecessary) on all platforms which use table-based exception dispatch. | |||
172 | if (getContext().getObjectFileInfo()->getTargetTriple().getArch() != | |||
173 | Triple::x86) | |||
174 | return; | |||
175 | ||||
176 | const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol); | |||
177 | if (CSymbol->isSafeSEH()) | |||
178 | return; | |||
179 | ||||
180 | MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); | |||
181 | getAssembler().registerSection(*SXData); | |||
182 | if (SXData->getAlignment() < 4) | |||
183 | SXData->setAlignment(4); | |||
184 | ||||
185 | new MCSymbolIdFragment(Symbol, SXData); | |||
186 | ||||
187 | getAssembler().registerSymbol(*Symbol); | |||
188 | CSymbol->setIsSafeSEH(); | |||
189 | ||||
190 | // The Microsoft linker requires that the symbol type of a handler be | |||
191 | // function. Go ahead and oblige it here. | |||
192 | CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION | |||
193 | << COFF::SCT_COMPLEX_TYPE_SHIFT); | |||
194 | } | |||
195 | ||||
196 | void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) { | |||
197 | visitUsedSymbol(*Symbol); | |||
198 | MCDataFragment *DF = getOrCreateDataFragment(); | |||
199 | const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); | |||
200 | MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); | |||
201 | DF->getFixups().push_back(Fixup); | |||
202 | DF->getContents().resize(DF->getContents().size() + 2, 0); | |||
203 | } | |||
204 | ||||
205 | void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol, | |||
206 | uint64_t Offset) { | |||
207 | visitUsedSymbol(*Symbol); | |||
208 | MCDataFragment *DF = getOrCreateDataFragment(); | |||
209 | // Create Symbol A for the relocation relative reference. | |||
210 | const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); | |||
211 | // Add the constant offset, if given. | |||
212 | if (Offset) | |||
213 | MCE = MCBinaryExpr::createAdd( | |||
214 | MCE, MCConstantExpr::create(Offset, getContext()), getContext()); | |||
215 | // Build the secrel32 relocation. | |||
216 | MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); | |||
217 | // Record the relocation. | |||
218 | DF->getFixups().push_back(Fixup); | |||
219 | // Emit 4 bytes (zeros) to the object file. | |||
220 | DF->getContents().resize(DF->getContents().size() + 4, 0); | |||
221 | } | |||
222 | ||||
223 | void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, | |||
224 | unsigned ByteAlignment) { | |||
225 | auto *Symbol = cast<MCSymbolCOFF>(S); | |||
226 | ||||
227 | const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); | |||
228 | if (T.isKnownWindowsMSVCEnvironment()) { | |||
229 | if (ByteAlignment > 32) | |||
230 | report_fatal_error("alignment is limited to 32-bytes"); | |||
231 | ||||
232 | // Round size up to alignment so that we will honor the alignment request. | |||
233 | Size = std::max(Size, static_cast<uint64_t>(ByteAlignment)); | |||
234 | } | |||
235 | ||||
236 | getAssembler().registerSymbol(*Symbol); | |||
237 | Symbol->setExternal(true); | |||
238 | Symbol->setCommon(Size, ByteAlignment); | |||
239 | ||||
240 | if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) { | |||
241 | SmallString<128> Directive; | |||
242 | raw_svector_ostream OS(Directive); | |||
243 | const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); | |||
244 | ||||
245 | OS << " -aligncomm:\"" << Symbol->getName() << "\"," | |||
246 | << Log2_32_Ceil(ByteAlignment); | |||
247 | ||||
248 | PushSection(); | |||
249 | SwitchSection(MFI->getDrectveSection()); | |||
250 | EmitBytes(Directive); | |||
251 | PopSection(); | |||
252 | } | |||
253 | } | |||
254 | ||||
255 | void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, | |||
256 | unsigned ByteAlignment) { | |||
257 | auto *Symbol = cast<MCSymbolCOFF>(S); | |||
258 | ||||
259 | MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); | |||
260 | getAssembler().registerSection(*Section); | |||
261 | if (Section->getAlignment() < ByteAlignment) | |||
| ||||
262 | Section->setAlignment(ByteAlignment); | |||
263 | ||||
264 | getAssembler().registerSymbol(*Symbol); | |||
265 | Symbol->setExternal(false); | |||
266 | ||||
267 | if (ByteAlignment != 1) | |||
268 | new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0, | |||
269 | ByteAlignment, Section); | |||
270 | ||||
271 | MCFillFragment *Fragment = new MCFillFragment( | |||
272 | /*Value=*/0, Size, Section); | |||
273 | Symbol->setFragment(Fragment); | |||
274 | } | |||
| ||||
275 | ||||
276 | void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, | |||
277 | uint64_t Size, unsigned ByteAlignment) { | |||
278 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 278); | |||
279 | } | |||
280 | ||||
281 | void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, | |||
282 | uint64_t Size, unsigned ByteAlignment) { | |||
283 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 283); | |||
284 | } | |||
285 | ||||
286 | // TODO: Implement this if you want to emit .comment section in COFF obj files. | |||
287 | void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { | |||
288 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 288); | |||
289 | } | |||
290 | ||||
291 | void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) { | |||
292 | llvm_unreachable("not implemented")::llvm::llvm_unreachable_internal("not implemented", "/build/llvm-toolchain-snapshot-6.0~svn321639/lib/MC/MCWinCOFFStreamer.cpp" , 292); | |||
293 | } | |||
294 | ||||
295 | void MCWinCOFFStreamer::FinishImpl() { | |||
296 | MCObjectStreamer::FinishImpl(); | |||
297 | } | |||
298 | ||||
299 | void MCWinCOFFStreamer::Error(const Twine &Msg) const { | |||
300 | getContext().reportError(SMLoc(), Msg); | |||
301 | } |