File: | build/source/llvm/lib/MC/XCOFFObjectWriter.cpp |
Warning: | line 1405, column 5 Value stored to 'Address' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===// |
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 XCOFF object file writer information. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/BinaryFormat/XCOFF.h" |
14 | #include "llvm/MC/MCAsmBackend.h" |
15 | #include "llvm/MC/MCAsmLayout.h" |
16 | #include "llvm/MC/MCAssembler.h" |
17 | #include "llvm/MC/MCFixup.h" |
18 | #include "llvm/MC/MCFixupKindInfo.h" |
19 | #include "llvm/MC/MCObjectWriter.h" |
20 | #include "llvm/MC/MCSectionXCOFF.h" |
21 | #include "llvm/MC/MCSymbolXCOFF.h" |
22 | #include "llvm/MC/MCValue.h" |
23 | #include "llvm/MC/MCXCOFFObjectWriter.h" |
24 | #include "llvm/MC/StringTableBuilder.h" |
25 | #include "llvm/Support/Casting.h" |
26 | #include "llvm/Support/EndianStream.h" |
27 | #include "llvm/Support/ErrorHandling.h" |
28 | #include "llvm/Support/MathExtras.h" |
29 | |
30 | #include <deque> |
31 | #include <map> |
32 | |
33 | using namespace llvm; |
34 | |
35 | // An XCOFF object file has a limited set of predefined sections. The most |
36 | // important ones for us (right now) are: |
37 | // .text --> contains program code and read-only data. |
38 | // .data --> contains initialized data, function descriptors, and the TOC. |
39 | // .bss --> contains uninitialized data. |
40 | // Each of these sections is composed of 'Control Sections'. A Control Section |
41 | // is more commonly referred to as a csect. A csect is an indivisible unit of |
42 | // code or data, and acts as a container for symbols. A csect is mapped |
43 | // into a section based on its storage-mapping class, with the exception of |
44 | // XMC_RW which gets mapped to either .data or .bss based on whether it's |
45 | // explicitly initialized or not. |
46 | // |
47 | // We don't represent the sections in the MC layer as there is nothing |
48 | // interesting about them at at that level: they carry information that is |
49 | // only relevant to the ObjectWriter, so we materialize them in this class. |
50 | namespace { |
51 | |
52 | constexpr unsigned DefaultSectionAlign = 4; |
53 | constexpr int16_t MaxSectionIndex = INT16_MAX(32767); |
54 | |
55 | // Packs the csect's alignment and type into a byte. |
56 | uint8_t getEncodedType(const MCSectionXCOFF *); |
57 | |
58 | struct XCOFFRelocation { |
59 | uint32_t SymbolTableIndex; |
60 | uint32_t FixupOffsetInCsect; |
61 | uint8_t SignAndSize; |
62 | uint8_t Type; |
63 | }; |
64 | |
65 | // Wrapper around an MCSymbolXCOFF. |
66 | struct Symbol { |
67 | const MCSymbolXCOFF *const MCSym; |
68 | uint32_t SymbolTableIndex; |
69 | |
70 | XCOFF::VisibilityType getVisibilityType() const { |
71 | return MCSym->getVisibilityType(); |
72 | } |
73 | |
74 | XCOFF::StorageClass getStorageClass() const { |
75 | return MCSym->getStorageClass(); |
76 | } |
77 | StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); } |
78 | Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {} |
79 | }; |
80 | |
81 | // Wrapper for an MCSectionXCOFF. |
82 | // It can be a Csect or debug section or DWARF section and so on. |
83 | struct XCOFFSection { |
84 | const MCSectionXCOFF *const MCSec; |
85 | uint32_t SymbolTableIndex; |
86 | uint64_t Address; |
87 | uint64_t Size; |
88 | |
89 | SmallVector<Symbol, 1> Syms; |
90 | SmallVector<XCOFFRelocation, 1> Relocations; |
91 | StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); } |
92 | XCOFF::VisibilityType getVisibilityType() const { |
93 | return MCSec->getVisibilityType(); |
94 | } |
95 | XCOFFSection(const MCSectionXCOFF *MCSec) |
96 | : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} |
97 | }; |
98 | |
99 | // Type to be used for a container representing a set of csects with |
100 | // (approximately) the same storage mapping class. For example all the csects |
101 | // with a storage mapping class of `xmc_pr` will get placed into the same |
102 | // container. |
103 | using CsectGroup = std::deque<XCOFFSection>; |
104 | using CsectGroups = std::deque<CsectGroup *>; |
105 | |
106 | // The basic section entry defination. This Section represents a section entry |
107 | // in XCOFF section header table. |
108 | struct SectionEntry { |
109 | char Name[XCOFF::NameSize]; |
110 | // The physical/virtual address of the section. For an object file these |
111 | // values are equivalent, except for in the overflow section header, where |
112 | // the physical address specifies the number of relocation entries and the |
113 | // virtual address specifies the number of line number entries. |
114 | // TODO: Divide Address into PhysicalAddress and VirtualAddress when line |
115 | // number entries are supported. |
116 | uint64_t Address; |
117 | uint64_t Size; |
118 | uint64_t FileOffsetToData; |
119 | uint64_t FileOffsetToRelocations; |
120 | uint32_t RelocationCount; |
121 | int32_t Flags; |
122 | |
123 | int16_t Index; |
124 | |
125 | // XCOFF has special section numbers for symbols: |
126 | // -2 Specifies N_DEBUG, a special symbolic debugging symbol. |
127 | // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not |
128 | // relocatable. |
129 | // 0 Specifies N_UNDEF, an undefined external symbol. |
130 | // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that |
131 | // hasn't been initialized. |
132 | static constexpr int16_t UninitializedIndex = |
133 | XCOFF::ReservedSectionNum::N_DEBUG - 1; |
134 | |
135 | SectionEntry(StringRef N, int32_t Flags) |
136 | : Name(), Address(0), Size(0), FileOffsetToData(0), |
137 | FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), |
138 | Index(UninitializedIndex) { |
139 | assert(N.size() <= XCOFF::NameSize && "section name too long")(static_cast <bool> (N.size() <= XCOFF::NameSize && "section name too long") ? void (0) : __assert_fail ("N.size() <= XCOFF::NameSize && \"section name too long\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 139, __extension__ __PRETTY_FUNCTION__ )); |
140 | memcpy(Name, N.data(), N.size()); |
141 | } |
142 | |
143 | virtual void reset() { |
144 | Address = 0; |
145 | Size = 0; |
146 | FileOffsetToData = 0; |
147 | FileOffsetToRelocations = 0; |
148 | RelocationCount = 0; |
149 | Index = UninitializedIndex; |
150 | } |
151 | |
152 | virtual ~SectionEntry() = default; |
153 | }; |
154 | |
155 | // Represents the data related to a section excluding the csects that make up |
156 | // the raw data of the section. The csects are stored separately as not all |
157 | // sections contain csects, and some sections contain csects which are better |
158 | // stored separately, e.g. the .data section containing read-write, descriptor, |
159 | // TOCBase and TOC-entry csects. |
160 | struct CsectSectionEntry : public SectionEntry { |
161 | // Virtual sections do not need storage allocated in the object file. |
162 | const bool IsVirtual; |
163 | |
164 | // This is a section containing csect groups. |
165 | CsectGroups Groups; |
166 | |
167 | CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, |
168 | CsectGroups Groups) |
169 | : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) { |
170 | assert(N.size() <= XCOFF::NameSize && "section name too long")(static_cast <bool> (N.size() <= XCOFF::NameSize && "section name too long") ? void (0) : __assert_fail ("N.size() <= XCOFF::NameSize && \"section name too long\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 170, __extension__ __PRETTY_FUNCTION__ )); |
171 | memcpy(Name, N.data(), N.size()); |
172 | } |
173 | |
174 | void reset() override { |
175 | SectionEntry::reset(); |
176 | // Clear any csects we have stored. |
177 | for (auto *Group : Groups) |
178 | Group->clear(); |
179 | } |
180 | |
181 | virtual ~CsectSectionEntry() = default; |
182 | }; |
183 | |
184 | struct DwarfSectionEntry : public SectionEntry { |
185 | // For DWARF section entry. |
186 | std::unique_ptr<XCOFFSection> DwarfSect; |
187 | |
188 | // For DWARF section, we must use real size in the section header. MemorySize |
189 | // is for the size the DWARF section occupies including paddings. |
190 | uint32_t MemorySize; |
191 | |
192 | DwarfSectionEntry(StringRef N, int32_t Flags, |
193 | std::unique_ptr<XCOFFSection> Sect) |
194 | : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)), |
195 | MemorySize(0) { |
196 | assert(DwarfSect->MCSec->isDwarfSect() &&(static_cast <bool> (DwarfSect->MCSec->isDwarfSect () && "This should be a DWARF section!") ? void (0) : __assert_fail ("DwarfSect->MCSec->isDwarfSect() && \"This should be a DWARF section!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 197, __extension__ __PRETTY_FUNCTION__ )) |
197 | "This should be a DWARF section!")(static_cast <bool> (DwarfSect->MCSec->isDwarfSect () && "This should be a DWARF section!") ? void (0) : __assert_fail ("DwarfSect->MCSec->isDwarfSect() && \"This should be a DWARF section!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 197, __extension__ __PRETTY_FUNCTION__ )); |
198 | assert(N.size() <= XCOFF::NameSize && "section name too long")(static_cast <bool> (N.size() <= XCOFF::NameSize && "section name too long") ? void (0) : __assert_fail ("N.size() <= XCOFF::NameSize && \"section name too long\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 198, __extension__ __PRETTY_FUNCTION__ )); |
199 | memcpy(Name, N.data(), N.size()); |
200 | } |
201 | |
202 | DwarfSectionEntry(DwarfSectionEntry &&s) = default; |
203 | |
204 | virtual ~DwarfSectionEntry() = default; |
205 | }; |
206 | |
207 | struct ExceptionTableEntry { |
208 | const MCSymbol *Trap; |
209 | uint64_t TrapAddress = ~0ul; |
210 | unsigned Lang; |
211 | unsigned Reason; |
212 | |
213 | ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason) |
214 | : Trap(Trap), Lang(Lang), Reason(Reason) {} |
215 | }; |
216 | |
217 | struct ExceptionInfo { |
218 | const MCSymbol *FunctionSymbol; |
219 | unsigned FunctionSize; |
220 | std::vector<ExceptionTableEntry> Entries; |
221 | }; |
222 | |
223 | struct ExceptionSectionEntry : public SectionEntry { |
224 | std::map<const StringRef, ExceptionInfo> ExceptionTable; |
225 | bool isDebugEnabled = false; |
226 | |
227 | ExceptionSectionEntry(StringRef N, int32_t Flags) |
228 | : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) { |
229 | assert(N.size() <= XCOFF::NameSize && "Section too long.")(static_cast <bool> (N.size() <= XCOFF::NameSize && "Section too long.") ? void (0) : __assert_fail ("N.size() <= XCOFF::NameSize && \"Section too long.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 229, __extension__ __PRETTY_FUNCTION__ )); |
230 | memcpy(Name, N.data(), N.size()); |
231 | } |
232 | |
233 | virtual ~ExceptionSectionEntry() = default; |
234 | }; |
235 | |
236 | class XCOFFObjectWriter : public MCObjectWriter { |
237 | |
238 | uint32_t SymbolTableEntryCount = 0; |
239 | uint64_t SymbolTableOffset = 0; |
240 | uint16_t SectionCount = 0; |
241 | uint32_t PaddingsBeforeDwarf = 0; |
242 | std::vector<std::pair<std::string, size_t>> FileNames; |
243 | bool HasVisibility = false; |
244 | |
245 | support::endian::Writer W; |
246 | std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter; |
247 | StringTableBuilder Strings; |
248 | |
249 | const uint64_t MaxRawDataSize = |
250 | TargetObjectWriter->is64Bit() ? UINT64_MAX(18446744073709551615UL) : UINT32_MAX(4294967295U); |
251 | |
252 | // Maps the MCSection representation to its corresponding XCOFFSection |
253 | // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into |
254 | // from its containing MCSectionXCOFF. |
255 | DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap; |
256 | |
257 | // Maps the MCSymbol representation to its corrresponding symbol table index. |
258 | // Needed for relocation. |
259 | DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap; |
260 | |
261 | // CsectGroups. These store the csects which make up different parts of |
262 | // the sections. Should have one for each set of csects that get mapped into |
263 | // the same section and get handled in a 'similar' way. |
264 | CsectGroup UndefinedCsects; |
265 | CsectGroup ProgramCodeCsects; |
266 | CsectGroup ReadOnlyCsects; |
267 | CsectGroup DataCsects; |
268 | CsectGroup FuncDSCsects; |
269 | CsectGroup TOCCsects; |
270 | CsectGroup BSSCsects; |
271 | CsectGroup TDataCsects; |
272 | CsectGroup TBSSCsects; |
273 | |
274 | // The Predefined sections. |
275 | CsectSectionEntry Text; |
276 | CsectSectionEntry Data; |
277 | CsectSectionEntry BSS; |
278 | CsectSectionEntry TData; |
279 | CsectSectionEntry TBSS; |
280 | |
281 | // All the XCOFF sections, in the order they will appear in the section header |
282 | // table. |
283 | std::array<CsectSectionEntry *const, 5> Sections{ |
284 | {&Text, &Data, &BSS, &TData, &TBSS}}; |
285 | |
286 | std::vector<DwarfSectionEntry> DwarfSections; |
287 | std::vector<SectionEntry> OverflowSections; |
288 | |
289 | ExceptionSectionEntry ExceptionSection; |
290 | |
291 | CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); |
292 | |
293 | void reset() override; |
294 | |
295 | void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override; |
296 | |
297 | void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *, |
298 | const MCFixup &, MCValue, uint64_t &) override; |
299 | |
300 | uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override; |
301 | |
302 | bool is64Bit() const { return TargetObjectWriter->is64Bit(); } |
303 | bool nameShouldBeInStringTable(const StringRef &); |
304 | void writeSymbolName(const StringRef &); |
305 | |
306 | void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef, |
307 | const XCOFFSection &CSectionRef, |
308 | int16_t SectionIndex, |
309 | uint64_t SymbolOffset); |
310 | void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef, |
311 | int16_t SectionIndex, |
312 | XCOFF::StorageClass StorageClass); |
313 | void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef, |
314 | int16_t SectionIndex); |
315 | void writeFileHeader(); |
316 | void writeAuxFileHeader(); |
317 | void writeSectionHeader(const SectionEntry *Sec); |
318 | void writeSectionHeaderTable(); |
319 | void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout); |
320 | void writeSectionForControlSectionEntry(const MCAssembler &Asm, |
321 | const MCAsmLayout &Layout, |
322 | const CsectSectionEntry &CsectEntry, |
323 | uint64_t &CurrentAddressLocation); |
324 | void writeSectionForDwarfSectionEntry(const MCAssembler &Asm, |
325 | const MCAsmLayout &Layout, |
326 | const DwarfSectionEntry &DwarfEntry, |
327 | uint64_t &CurrentAddressLocation); |
328 | void writeSectionForExceptionSectionEntry( |
329 | const MCAssembler &Asm, const MCAsmLayout &Layout, |
330 | ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation); |
331 | void writeSymbolTable(const MCAsmLayout &Layout); |
332 | void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion, |
333 | uint64_t NumberOfRelocEnt = 0); |
334 | void writeSymbolAuxCsectEntry(uint64_t SectionOrLength, |
335 | uint8_t SymbolAlignmentAndType, |
336 | uint8_t StorageMappingClass); |
337 | void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize, |
338 | uint64_t LineNumberPointer, |
339 | uint32_t EndIndex); |
340 | void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize, |
341 | uint32_t EndIndex); |
342 | void writeSymbolEntry(StringRef SymbolName, uint64_t Value, |
343 | int16_t SectionNumber, uint16_t SymbolType, |
344 | uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1); |
345 | void writeRelocations(); |
346 | void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section); |
347 | |
348 | // Called after all the csects and symbols have been processed by |
349 | // `executePostLayoutBinding`, this function handles building up the majority |
350 | // of the structures in the object file representation. Namely: |
351 | // *) Calculates physical/virtual addresses, raw-pointer offsets, and section |
352 | // sizes. |
353 | // *) Assigns symbol table indices. |
354 | // *) Builds up the section header table by adding any non-empty sections to |
355 | // `Sections`. |
356 | void assignAddressesAndIndices(const MCAsmLayout &); |
357 | // Called after relocations are recorded. |
358 | void finalizeSectionInfo(); |
359 | void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount); |
360 | void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer); |
361 | |
362 | void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, |
363 | unsigned LanguageCode, unsigned ReasonCode, |
364 | unsigned FunctionSize, bool hasDebug) override; |
365 | bool hasExceptionSection() { |
366 | return !ExceptionSection.ExceptionTable.empty(); |
367 | } |
368 | unsigned getExceptionSectionSize(); |
369 | unsigned getExceptionOffset(const MCSymbol *Symbol); |
370 | |
371 | size_t auxiliaryHeaderSize() const { |
372 | // 64-bit object files have no auxiliary header. |
373 | return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0; |
374 | } |
375 | |
376 | public: |
377 | XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, |
378 | raw_pwrite_stream &OS); |
379 | |
380 | void writeWord(uint64_t Word) { |
381 | is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word); |
382 | } |
383 | }; |
384 | |
385 | XCOFFObjectWriter::XCOFFObjectWriter( |
386 | std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) |
387 | : W(OS, support::big), TargetObjectWriter(std::move(MOTW)), |
388 | Strings(StringTableBuilder::XCOFF), |
389 | Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false, |
390 | CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}), |
391 | Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false, |
392 | CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}), |
393 | BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true, |
394 | CsectGroups{&BSSCsects}), |
395 | TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false, |
396 | CsectGroups{&TDataCsects}), |
397 | TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true, |
398 | CsectGroups{&TBSSCsects}), |
399 | ExceptionSection(".except", XCOFF::STYP_EXCEPT) {} |
400 | |
401 | void XCOFFObjectWriter::reset() { |
402 | // Clear the mappings we created. |
403 | SymbolIndexMap.clear(); |
404 | SectionMap.clear(); |
405 | |
406 | UndefinedCsects.clear(); |
407 | // Reset any sections we have written to, and empty the section header table. |
408 | for (auto *Sec : Sections) |
409 | Sec->reset(); |
410 | for (auto &DwarfSec : DwarfSections) |
411 | DwarfSec.reset(); |
412 | for (auto &OverflowSec : OverflowSections) |
413 | OverflowSec.reset(); |
414 | ExceptionSection.reset(); |
415 | |
416 | // Reset states in XCOFFObjectWriter. |
417 | SymbolTableEntryCount = 0; |
418 | SymbolTableOffset = 0; |
419 | SectionCount = 0; |
420 | PaddingsBeforeDwarf = 0; |
421 | Strings.clear(); |
422 | |
423 | MCObjectWriter::reset(); |
424 | } |
425 | |
426 | CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) { |
427 | switch (MCSec->getMappingClass()) { |
428 | case XCOFF::XMC_PR: |
429 | assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain program code." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain program code.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 430, __extension__ __PRETTY_FUNCTION__ )) |
430 | "Only an initialized csect can contain program code.")(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain program code." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain program code.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 430, __extension__ __PRETTY_FUNCTION__ )); |
431 | return ProgramCodeCsects; |
432 | case XCOFF::XMC_RO: |
433 | assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain read only data." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain read only data.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 434, __extension__ __PRETTY_FUNCTION__ )) |
434 | "Only an initialized csect can contain read only data.")(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain read only data." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain read only data.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 434, __extension__ __PRETTY_FUNCTION__ )); |
435 | return ReadOnlyCsects; |
436 | case XCOFF::XMC_RW: |
437 | if (XCOFF::XTY_CM == MCSec->getCSectType()) |
438 | return BSSCsects; |
439 | |
440 | if (XCOFF::XTY_SD == MCSec->getCSectType()) |
441 | return DataCsects; |
442 | |
443 | report_fatal_error("Unhandled mapping of read-write csect to section."); |
444 | case XCOFF::XMC_DS: |
445 | return FuncDSCsects; |
446 | case XCOFF::XMC_BS: |
447 | assert(XCOFF::XTY_CM == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with bss storage class must be " "common type.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with bss storage class must be \" \"common type.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 449, __extension__ __PRETTY_FUNCTION__ )) |
448 | "Mapping invalid csect. CSECT with bss storage class must be "(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with bss storage class must be " "common type.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with bss storage class must be \" \"common type.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 449, __extension__ __PRETTY_FUNCTION__ )) |
449 | "common type.")(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with bss storage class must be " "common type.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with bss storage class must be \" \"common type.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 449, __extension__ __PRETTY_FUNCTION__ )); |
450 | return BSSCsects; |
451 | case XCOFF::XMC_TL: |
452 | assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tdata storage class must be " "an initialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tdata storage class must be \" \"an initialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 454, __extension__ __PRETTY_FUNCTION__ )) |
453 | "Mapping invalid csect. CSECT with tdata storage class must be "(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tdata storage class must be " "an initialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tdata storage class must be \" \"an initialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 454, __extension__ __PRETTY_FUNCTION__ )) |
454 | "an initialized csect.")(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tdata storage class must be " "an initialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tdata storage class must be \" \"an initialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 454, __extension__ __PRETTY_FUNCTION__ )); |
455 | return TDataCsects; |
456 | case XCOFF::XMC_UL: |
457 | assert(XCOFF::XTY_CM == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tbss storage class must be " "an uninitialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tbss storage class must be \" \"an uninitialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 459, __extension__ __PRETTY_FUNCTION__ )) |
458 | "Mapping invalid csect. CSECT with tbss storage class must be "(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tbss storage class must be " "an uninitialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tbss storage class must be \" \"an uninitialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 459, __extension__ __PRETTY_FUNCTION__ )) |
459 | "an uninitialized csect.")(static_cast <bool> (XCOFF::XTY_CM == MCSec->getCSectType () && "Mapping invalid csect. CSECT with tbss storage class must be " "an uninitialized csect.") ? void (0) : __assert_fail ("XCOFF::XTY_CM == MCSec->getCSectType() && \"Mapping invalid csect. CSECT with tbss storage class must be \" \"an uninitialized csect.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 459, __extension__ __PRETTY_FUNCTION__ )); |
460 | return TBSSCsects; |
461 | case XCOFF::XMC_TC0: |
462 | assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain TOC-base." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain TOC-base.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 463, __extension__ __PRETTY_FUNCTION__ )) |
463 | "Only an initialized csect can contain TOC-base.")(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain TOC-base." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain TOC-base.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 463, __extension__ __PRETTY_FUNCTION__ )); |
464 | assert(TOCCsects.empty() &&(static_cast <bool> (TOCCsects.empty() && "We should have only one TOC-base, and it should be the first csect " "in this CsectGroup.") ? void (0) : __assert_fail ("TOCCsects.empty() && \"We should have only one TOC-base, and it should be the first csect \" \"in this CsectGroup.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 466, __extension__ __PRETTY_FUNCTION__ )) |
465 | "We should have only one TOC-base, and it should be the first csect "(static_cast <bool> (TOCCsects.empty() && "We should have only one TOC-base, and it should be the first csect " "in this CsectGroup.") ? void (0) : __assert_fail ("TOCCsects.empty() && \"We should have only one TOC-base, and it should be the first csect \" \"in this CsectGroup.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 466, __extension__ __PRETTY_FUNCTION__ )) |
466 | "in this CsectGroup.")(static_cast <bool> (TOCCsects.empty() && "We should have only one TOC-base, and it should be the first csect " "in this CsectGroup.") ? void (0) : __assert_fail ("TOCCsects.empty() && \"We should have only one TOC-base, and it should be the first csect \" \"in this CsectGroup.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 466, __extension__ __PRETTY_FUNCTION__ )); |
467 | return TOCCsects; |
468 | case XCOFF::XMC_TC: |
469 | case XCOFF::XMC_TE: |
470 | case XCOFF::XMC_TD: |
471 | assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain TC entry." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain TC entry.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 472, __extension__ __PRETTY_FUNCTION__ )) |
472 | "Only an initialized csect can contain TC entry.")(static_cast <bool> (XCOFF::XTY_SD == MCSec->getCSectType () && "Only an initialized csect can contain TC entry." ) ? void (0) : __assert_fail ("XCOFF::XTY_SD == MCSec->getCSectType() && \"Only an initialized csect can contain TC entry.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 472, __extension__ __PRETTY_FUNCTION__ )); |
473 | assert(!TOCCsects.empty() &&(static_cast <bool> (!TOCCsects.empty() && "We should at least have a TOC-base in this CsectGroup." ) ? void (0) : __assert_fail ("!TOCCsects.empty() && \"We should at least have a TOC-base in this CsectGroup.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 474, __extension__ __PRETTY_FUNCTION__ )) |
474 | "We should at least have a TOC-base in this CsectGroup.")(static_cast <bool> (!TOCCsects.empty() && "We should at least have a TOC-base in this CsectGroup." ) ? void (0) : __assert_fail ("!TOCCsects.empty() && \"We should at least have a TOC-base in this CsectGroup.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 474, __extension__ __PRETTY_FUNCTION__ )); |
475 | return TOCCsects; |
476 | default: |
477 | report_fatal_error("Unhandled mapping of csect to section."); |
478 | } |
479 | } |
480 | |
481 | static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) { |
482 | if (XSym->isDefined()) |
483 | return cast<MCSectionXCOFF>(XSym->getFragment()->getParent()); |
484 | return XSym->getRepresentedCsect(); |
485 | } |
486 | |
487 | void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, |
488 | const MCAsmLayout &Layout) { |
489 | for (const auto &S : Asm) { |
490 | const auto *MCSec = cast<const MCSectionXCOFF>(&S); |
491 | assert(!SectionMap.contains(MCSec) && "Cannot add a section twice.")(static_cast <bool> (!SectionMap.contains(MCSec) && "Cannot add a section twice.") ? void (0) : __assert_fail ("!SectionMap.contains(MCSec) && \"Cannot add a section twice.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 491, __extension__ __PRETTY_FUNCTION__ )); |
492 | |
493 | // If the name does not fit in the storage provided in the symbol table |
494 | // entry, add it to the string table. |
495 | if (nameShouldBeInStringTable(MCSec->getSymbolTableName())) |
496 | Strings.add(MCSec->getSymbolTableName()); |
497 | if (MCSec->isCsect()) { |
498 | // A new control section. Its CsectSectionEntry should already be staticly |
499 | // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of |
500 | // the CsectSectionEntry. |
501 | assert(XCOFF::XTY_ER != MCSec->getCSectType() &&(static_cast <bool> (XCOFF::XTY_ER != MCSec->getCSectType () && "An undefined csect should not get registered." ) ? void (0) : __assert_fail ("XCOFF::XTY_ER != MCSec->getCSectType() && \"An undefined csect should not get registered.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 502, __extension__ __PRETTY_FUNCTION__ )) |
502 | "An undefined csect should not get registered.")(static_cast <bool> (XCOFF::XTY_ER != MCSec->getCSectType () && "An undefined csect should not get registered." ) ? void (0) : __assert_fail ("XCOFF::XTY_ER != MCSec->getCSectType() && \"An undefined csect should not get registered.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 502, __extension__ __PRETTY_FUNCTION__ )); |
503 | CsectGroup &Group = getCsectGroup(MCSec); |
504 | Group.emplace_back(MCSec); |
505 | SectionMap[MCSec] = &Group.back(); |
506 | } else if (MCSec->isDwarfSect()) { |
507 | // A new DwarfSectionEntry. |
508 | std::unique_ptr<XCOFFSection> DwarfSec = |
509 | std::make_unique<XCOFFSection>(MCSec); |
510 | SectionMap[MCSec] = DwarfSec.get(); |
511 | |
512 | DwarfSectionEntry SecEntry(MCSec->getName(), |
513 | *MCSec->getDwarfSubtypeFlags(), |
514 | std::move(DwarfSec)); |
515 | DwarfSections.push_back(std::move(SecEntry)); |
516 | } else |
517 | llvm_unreachable("unsupport section type!")::llvm::llvm_unreachable_internal("unsupport section type!", "llvm/lib/MC/XCOFFObjectWriter.cpp" , 517); |
518 | } |
519 | |
520 | for (const MCSymbol &S : Asm.symbols()) { |
521 | // Nothing to do for temporary symbols. |
522 | if (S.isTemporary()) |
523 | continue; |
524 | |
525 | const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S); |
526 | const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym); |
527 | |
528 | if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED) |
529 | HasVisibility = true; |
530 | |
531 | if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) { |
532 | // Handle undefined symbol. |
533 | UndefinedCsects.emplace_back(ContainingCsect); |
534 | SectionMap[ContainingCsect] = &UndefinedCsects.back(); |
535 | if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName())) |
536 | Strings.add(ContainingCsect->getSymbolTableName()); |
537 | continue; |
538 | } |
539 | |
540 | // If the symbol is the csect itself, we don't need to put the symbol |
541 | // into csect's Syms. |
542 | if (XSym == ContainingCsect->getQualNameSymbol()) |
543 | continue; |
544 | |
545 | // Only put a label into the symbol table when it is an external label. |
546 | if (!XSym->isExternal()) |
547 | continue; |
548 | |
549 | assert(SectionMap.contains(ContainingCsect) &&(static_cast <bool> (SectionMap.contains(ContainingCsect ) && "Expected containing csect to exist in map") ? void (0) : __assert_fail ("SectionMap.contains(ContainingCsect) && \"Expected containing csect to exist in map\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 550, __extension__ __PRETTY_FUNCTION__ )) |
550 | "Expected containing csect to exist in map")(static_cast <bool> (SectionMap.contains(ContainingCsect ) && "Expected containing csect to exist in map") ? void (0) : __assert_fail ("SectionMap.contains(ContainingCsect) && \"Expected containing csect to exist in map\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 550, __extension__ __PRETTY_FUNCTION__ )); |
551 | XCOFFSection *Csect = SectionMap[ContainingCsect]; |
552 | // Lookup the containing csect and add the symbol to it. |
553 | assert(Csect->MCSec->isCsect() && "only csect is supported now!")(static_cast <bool> (Csect->MCSec->isCsect() && "only csect is supported now!") ? void (0) : __assert_fail ( "Csect->MCSec->isCsect() && \"only csect is supported now!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 553, __extension__ __PRETTY_FUNCTION__ )); |
554 | Csect->Syms.emplace_back(XSym); |
555 | |
556 | // If the name does not fit in the storage provided in the symbol table |
557 | // entry, add it to the string table. |
558 | if (nameShouldBeInStringTable(XSym->getSymbolTableName())) |
559 | Strings.add(XSym->getSymbolTableName()); |
560 | } |
561 | |
562 | FileNames = Asm.getFileNames(); |
563 | // Emit ".file" as the source file name when there is no file name. |
564 | if (FileNames.empty()) |
565 | FileNames.emplace_back(".file", 0); |
566 | for (const std::pair<std::string, size_t> &F : FileNames) { |
567 | if (nameShouldBeInStringTable(F.first)) |
568 | Strings.add(F.first); |
569 | } |
570 | |
571 | Strings.finalize(); |
572 | assignAddressesAndIndices(Layout); |
573 | } |
574 | |
575 | void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, |
576 | const MCAsmLayout &Layout, |
577 | const MCFragment *Fragment, |
578 | const MCFixup &Fixup, MCValue Target, |
579 | uint64_t &FixedValue) { |
580 | auto getIndex = [this](const MCSymbol *Sym, |
581 | const MCSectionXCOFF *ContainingCsect) { |
582 | // If we could not find the symbol directly in SymbolIndexMap, this symbol |
583 | // could either be a temporary symbol or an undefined symbol. In this case, |
584 | // we would need to have the relocation reference its csect instead. |
585 | return SymbolIndexMap.contains(Sym) |
586 | ? SymbolIndexMap[Sym] |
587 | : SymbolIndexMap[ContainingCsect->getQualNameSymbol()]; |
588 | }; |
589 | |
590 | auto getVirtualAddress = |
591 | [this, &Layout](const MCSymbol *Sym, |
592 | const MCSectionXCOFF *ContainingSect) -> uint64_t { |
593 | // A DWARF section. |
594 | if (ContainingSect->isDwarfSect()) |
595 | return Layout.getSymbolOffset(*Sym); |
596 | |
597 | // A csect. |
598 | if (!Sym->isDefined()) |
599 | return SectionMap[ContainingSect]->Address; |
600 | |
601 | // A label. |
602 | assert(Sym->isDefined() && "not a valid object that has address!")(static_cast <bool> (Sym->isDefined() && "not a valid object that has address!" ) ? void (0) : __assert_fail ("Sym->isDefined() && \"not a valid object that has address!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 602, __extension__ __PRETTY_FUNCTION__ )); |
603 | return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym); |
604 | }; |
605 | |
606 | const MCSymbol *const SymA = &Target.getSymA()->getSymbol(); |
607 | |
608 | MCAsmBackend &Backend = Asm.getBackend(); |
609 | bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & |
610 | MCFixupKindInfo::FKF_IsPCRel; |
611 | |
612 | uint8_t Type; |
613 | uint8_t SignAndSize; |
614 | std::tie(Type, SignAndSize) = |
615 | TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); |
616 | |
617 | const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA)); |
618 | assert(SectionMap.contains(SymASec) &&(static_cast <bool> (SectionMap.contains(SymASec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(SymASec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 619, __extension__ __PRETTY_FUNCTION__ )) |
619 | "Expected containing csect to exist in map.")(static_cast <bool> (SectionMap.contains(SymASec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(SymASec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 619, __extension__ __PRETTY_FUNCTION__ )); |
620 | |
621 | const uint32_t Index = getIndex(SymA, SymASec); |
622 | if (Type == XCOFF::RelocationType::R_POS || |
623 | Type == XCOFF::RelocationType::R_TLS) |
624 | // The FixedValue should be symbol's virtual address in this object file |
625 | // plus any constant value that we might get. |
626 | FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant(); |
627 | else if (Type == XCOFF::RelocationType::R_TLSM) |
628 | // The FixedValue should always be zero since the region handle is only |
629 | // known at load time. |
630 | FixedValue = 0; |
631 | else if (Type == XCOFF::RelocationType::R_TOC || |
632 | Type == XCOFF::RelocationType::R_TOCL) { |
633 | // For non toc-data external symbols, R_TOC type relocation will relocate to |
634 | // data symbols that have XCOFF::XTY_SD type csect. For toc-data external |
635 | // symbols, R_TOC type relocation will relocate to data symbols that have |
636 | // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC |
637 | // entry for them, so the FixedValue should always be 0. |
638 | if (SymASec->getCSectType() == XCOFF::XTY_ER) { |
639 | FixedValue = 0; |
640 | } else { |
641 | // The FixedValue should be the TOC entry offset from the TOC-base plus |
642 | // any constant offset value. |
643 | const int64_t TOCEntryOffset = SectionMap[SymASec]->Address - |
644 | TOCCsects.front().Address + |
645 | Target.getConstant(); |
646 | if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset)) |
647 | report_fatal_error("TOCEntryOffset overflows in small code model mode"); |
648 | |
649 | FixedValue = TOCEntryOffset; |
650 | } |
651 | } else if (Type == XCOFF::RelocationType::R_RBR) { |
652 | MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(Fragment->getParent()); |
653 | assert((SymASec->getMappingClass() == XCOFF::XMC_PR &&(static_cast <bool> ((SymASec->getMappingClass() == XCOFF ::XMC_PR && ParentSec->getMappingClass() == XCOFF:: XMC_PR) && "Only XMC_PR csect may have the R_RBR relocation." ) ? void (0) : __assert_fail ("(SymASec->getMappingClass() == XCOFF::XMC_PR && ParentSec->getMappingClass() == XCOFF::XMC_PR) && \"Only XMC_PR csect may have the R_RBR relocation.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 655, __extension__ __PRETTY_FUNCTION__ )) |
654 | ParentSec->getMappingClass() == XCOFF::XMC_PR) &&(static_cast <bool> ((SymASec->getMappingClass() == XCOFF ::XMC_PR && ParentSec->getMappingClass() == XCOFF:: XMC_PR) && "Only XMC_PR csect may have the R_RBR relocation." ) ? void (0) : __assert_fail ("(SymASec->getMappingClass() == XCOFF::XMC_PR && ParentSec->getMappingClass() == XCOFF::XMC_PR) && \"Only XMC_PR csect may have the R_RBR relocation.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 655, __extension__ __PRETTY_FUNCTION__ )) |
655 | "Only XMC_PR csect may have the R_RBR relocation.")(static_cast <bool> ((SymASec->getMappingClass() == XCOFF ::XMC_PR && ParentSec->getMappingClass() == XCOFF:: XMC_PR) && "Only XMC_PR csect may have the R_RBR relocation." ) ? void (0) : __assert_fail ("(SymASec->getMappingClass() == XCOFF::XMC_PR && ParentSec->getMappingClass() == XCOFF::XMC_PR) && \"Only XMC_PR csect may have the R_RBR relocation.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 655, __extension__ __PRETTY_FUNCTION__ )); |
656 | |
657 | // The address of the branch instruction should be the sum of section |
658 | // address, fragment offset and Fixup offset. |
659 | uint64_t BRInstrAddress = SectionMap[ParentSec]->Address + |
660 | Layout.getFragmentOffset(Fragment) + |
661 | Fixup.getOffset(); |
662 | // The FixedValue should be the difference between SymA csect address and BR |
663 | // instr address plus any constant value. |
664 | FixedValue = |
665 | SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant(); |
666 | } else if (Type == XCOFF::RelocationType::R_REF) |
667 | // The FixedValue should always be 0 since it specifies a nonrelocating |
668 | // reference. |
669 | FixedValue = 0; |
670 | |
671 | assert((Fixup.getOffset() <=(static_cast <bool> ((Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && "Fragment offset + fixup offset is overflowed." ) ? void (0) : __assert_fail ("(Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && \"Fragment offset + fixup offset is overflowed.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 673, __extension__ __PRETTY_FUNCTION__ )) |
672 | MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&(static_cast <bool> ((Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && "Fragment offset + fixup offset is overflowed." ) ? void (0) : __assert_fail ("(Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && \"Fragment offset + fixup offset is overflowed.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 673, __extension__ __PRETTY_FUNCTION__ )) |
673 | "Fragment offset + fixup offset is overflowed.")(static_cast <bool> ((Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && "Fragment offset + fixup offset is overflowed." ) ? void (0) : __assert_fail ("(Fixup.getOffset() <= MaxRawDataSize - Layout.getFragmentOffset(Fragment)) && \"Fragment offset + fixup offset is overflowed.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 673, __extension__ __PRETTY_FUNCTION__ )); |
674 | uint32_t FixupOffsetInCsect = |
675 | Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
676 | |
677 | XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type}; |
678 | MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent()); |
679 | assert(SectionMap.contains(RelocationSec) &&(static_cast <bool> (SectionMap.contains(RelocationSec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(RelocationSec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 680, __extension__ __PRETTY_FUNCTION__ )) |
680 | "Expected containing csect to exist in map.")(static_cast <bool> (SectionMap.contains(RelocationSec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(RelocationSec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 680, __extension__ __PRETTY_FUNCTION__ )); |
681 | SectionMap[RelocationSec]->Relocations.push_back(Reloc); |
682 | |
683 | if (!Target.getSymB()) |
684 | return; |
685 | |
686 | const MCSymbol *const SymB = &Target.getSymB()->getSymbol(); |
687 | if (SymA == SymB) |
688 | report_fatal_error("relocation for opposite term is not yet supported"); |
689 | |
690 | const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB)); |
691 | assert(SectionMap.contains(SymBSec) &&(static_cast <bool> (SectionMap.contains(SymBSec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(SymBSec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 692, __extension__ __PRETTY_FUNCTION__ )) |
692 | "Expected containing csect to exist in map.")(static_cast <bool> (SectionMap.contains(SymBSec) && "Expected containing csect to exist in map.") ? void (0) : __assert_fail ("SectionMap.contains(SymBSec) && \"Expected containing csect to exist in map.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 692, __extension__ __PRETTY_FUNCTION__ )); |
693 | if (SymASec == SymBSec) |
694 | report_fatal_error( |
695 | "relocation for paired relocatable term is not yet supported"); |
696 | |
697 | assert(Type == XCOFF::RelocationType::R_POS &&(static_cast <bool> (Type == XCOFF::RelocationType::R_POS && "SymA must be R_POS here if it's not opposite term or paired " "relocatable term.") ? void (0) : __assert_fail ("Type == XCOFF::RelocationType::R_POS && \"SymA must be R_POS here if it's not opposite term or paired \" \"relocatable term.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 699, __extension__ __PRETTY_FUNCTION__ )) |
698 | "SymA must be R_POS here if it's not opposite term or paired "(static_cast <bool> (Type == XCOFF::RelocationType::R_POS && "SymA must be R_POS here if it's not opposite term or paired " "relocatable term.") ? void (0) : __assert_fail ("Type == XCOFF::RelocationType::R_POS && \"SymA must be R_POS here if it's not opposite term or paired \" \"relocatable term.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 699, __extension__ __PRETTY_FUNCTION__ )) |
699 | "relocatable term.")(static_cast <bool> (Type == XCOFF::RelocationType::R_POS && "SymA must be R_POS here if it's not opposite term or paired " "relocatable term.") ? void (0) : __assert_fail ("Type == XCOFF::RelocationType::R_POS && \"SymA must be R_POS here if it's not opposite term or paired \" \"relocatable term.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 699, __extension__ __PRETTY_FUNCTION__ )); |
700 | const uint32_t IndexB = getIndex(SymB, SymBSec); |
701 | // SymB must be R_NEG here, given the general form of Target(MCValue) is |
702 | // "SymbolA - SymbolB + imm64". |
703 | const uint8_t TypeB = XCOFF::RelocationType::R_NEG; |
704 | XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB}; |
705 | SectionMap[RelocationSec]->Relocations.push_back(RelocB); |
706 | // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA, |
707 | // now we just need to fold "- SymbolB" here. |
708 | FixedValue -= getVirtualAddress(SymB, SymBSec); |
709 | } |
710 | |
711 | void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, |
712 | const MCAsmLayout &Layout) { |
713 | uint64_t CurrentAddressLocation = 0; |
714 | for (const auto *Section : Sections) |
715 | writeSectionForControlSectionEntry(Asm, Layout, *Section, |
716 | CurrentAddressLocation); |
717 | for (const auto &DwarfSection : DwarfSections) |
718 | writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection, |
719 | CurrentAddressLocation); |
720 | writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection, |
721 | CurrentAddressLocation); |
722 | } |
723 | |
724 | uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm, |
725 | const MCAsmLayout &Layout) { |
726 | // We always emit a timestamp of 0 for reproducibility, so ensure incremental |
727 | // linking is not enabled, in case, like with Windows COFF, such a timestamp |
728 | // is incompatible with incremental linking of XCOFF. |
729 | if (Asm.isIncrementalLinkerCompatible()) |
730 | report_fatal_error("Incremental linking not supported for XCOFF."); |
731 | |
732 | finalizeSectionInfo(); |
733 | uint64_t StartOffset = W.OS.tell(); |
734 | |
735 | writeFileHeader(); |
736 | writeAuxFileHeader(); |
737 | writeSectionHeaderTable(); |
738 | writeSections(Asm, Layout); |
739 | writeRelocations(); |
740 | writeSymbolTable(Layout); |
741 | // Write the string table. |
742 | Strings.write(W.OS); |
743 | |
744 | return W.OS.tell() - StartOffset; |
745 | } |
746 | |
747 | bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) { |
748 | return SymbolName.size() > XCOFF::NameSize || is64Bit(); |
749 | } |
750 | |
751 | void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) { |
752 | // Magic, Offset or SymbolName. |
753 | if (nameShouldBeInStringTable(SymbolName)) { |
754 | W.write<int32_t>(0); |
755 | W.write<uint32_t>(Strings.getOffset(SymbolName)); |
756 | } else { |
757 | char Name[XCOFF::NameSize + 1]; |
758 | std::strncpy(Name, SymbolName.data(), XCOFF::NameSize); |
759 | ArrayRef<char> NameRef(Name, XCOFF::NameSize); |
760 | W.write(NameRef); |
761 | } |
762 | } |
763 | |
764 | void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value, |
765 | int16_t SectionNumber, |
766 | uint16_t SymbolType, |
767 | uint8_t StorageClass, |
768 | uint8_t NumberOfAuxEntries) { |
769 | if (is64Bit()) { |
770 | W.write<uint64_t>(Value); |
771 | W.write<uint32_t>(Strings.getOffset(SymbolName)); |
772 | } else { |
773 | writeSymbolName(SymbolName); |
774 | W.write<uint32_t>(Value); |
775 | } |
776 | W.write<int16_t>(SectionNumber); |
777 | W.write<uint16_t>(SymbolType); |
778 | W.write<uint8_t>(StorageClass); |
779 | W.write<uint8_t>(NumberOfAuxEntries); |
780 | } |
781 | |
782 | void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength, |
783 | uint8_t SymbolAlignmentAndType, |
784 | uint8_t StorageMappingClass) { |
785 | W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength); |
786 | W.write<uint32_t>(0); // ParameterHashIndex |
787 | W.write<uint16_t>(0); // TypeChkSectNum |
788 | W.write<uint8_t>(SymbolAlignmentAndType); |
789 | W.write<uint8_t>(StorageMappingClass); |
790 | if (is64Bit()) { |
791 | W.write<uint32_t>(Hi_32(SectionOrLength)); |
792 | W.OS.write_zeros(1); // Reserved |
793 | W.write<uint8_t>(XCOFF::AUX_CSECT); |
794 | } else { |
795 | W.write<uint32_t>(0); // StabInfoIndex |
796 | W.write<uint16_t>(0); // StabSectNum |
797 | } |
798 | } |
799 | |
800 | void XCOFFObjectWriter::writeSymbolAuxDwarfEntry( |
801 | uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) { |
802 | writeWord(LengthOfSectionPortion); |
803 | if (!is64Bit()) |
804 | W.OS.write_zeros(4); // Reserved |
805 | writeWord(NumberOfRelocEnt); |
806 | if (is64Bit()) { |
807 | W.OS.write_zeros(1); // Reserved |
808 | W.write<uint8_t>(XCOFF::AUX_SECT); |
809 | } else { |
810 | W.OS.write_zeros(6); // Reserved |
811 | } |
812 | } |
813 | |
814 | void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel( |
815 | const Symbol &SymbolRef, const XCOFFSection &CSectionRef, |
816 | int16_t SectionIndex, uint64_t SymbolOffset) { |
817 | assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&(static_cast <bool> (SymbolOffset <= MaxRawDataSize - CSectionRef.Address && "Symbol address overflowed.") ? void (0) : __assert_fail ("SymbolOffset <= MaxRawDataSize - CSectionRef.Address && \"Symbol address overflowed.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 818, __extension__ __PRETTY_FUNCTION__ )) |
818 | "Symbol address overflowed.")(static_cast <bool> (SymbolOffset <= MaxRawDataSize - CSectionRef.Address && "Symbol address overflowed.") ? void (0) : __assert_fail ("SymbolOffset <= MaxRawDataSize - CSectionRef.Address && \"Symbol address overflowed.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 818, __extension__ __PRETTY_FUNCTION__ )); |
819 | |
820 | auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName()); |
821 | if (Entry != ExceptionSection.ExceptionTable.end()) { |
822 | writeSymbolEntry(SymbolRef.getSymbolTableName(), |
823 | CSectionRef.Address + SymbolOffset, SectionIndex, |
824 | // In the old version of the 32-bit XCOFF interpretation, |
825 | // symbols may require bit 10 (0x0020) to be set if the |
826 | // symbol is a function, otherwise the bit should be 0. |
827 | is64Bit() ? SymbolRef.getVisibilityType() |
828 | : SymbolRef.getVisibilityType() | 0x0020, |
829 | SymbolRef.getStorageClass(), |
830 | (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2); |
831 | if (is64Bit() && ExceptionSection.isDebugEnabled) { |
832 | // On 64 bit with debugging enabled, we have a csect, exception, and |
833 | // function auxilliary entries, so we must increment symbol index by 4. |
834 | writeSymbolAuxExceptionEntry( |
835 | ExceptionSection.FileOffsetToData + |
836 | getExceptionOffset(Entry->second.FunctionSymbol), |
837 | Entry->second.FunctionSize, |
838 | SymbolIndexMap[Entry->second.FunctionSymbol] + 4); |
839 | } |
840 | // For exception section entries, csect and function auxilliary entries |
841 | // must exist. On 64-bit there is also an exception auxilliary entry. |
842 | writeSymbolAuxFunctionEntry( |
843 | ExceptionSection.FileOffsetToData + |
844 | getExceptionOffset(Entry->second.FunctionSymbol), |
845 | Entry->second.FunctionSize, 0, |
846 | (is64Bit() && ExceptionSection.isDebugEnabled) |
847 | ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4 |
848 | : SymbolIndexMap[Entry->second.FunctionSymbol] + 3); |
849 | } else { |
850 | writeSymbolEntry(SymbolRef.getSymbolTableName(), |
851 | CSectionRef.Address + SymbolOffset, SectionIndex, |
852 | SymbolRef.getVisibilityType(), |
853 | SymbolRef.getStorageClass()); |
854 | } |
855 | writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD, |
856 | CSectionRef.MCSec->getMappingClass()); |
857 | } |
858 | |
859 | void XCOFFObjectWriter::writeSymbolEntryForDwarfSection( |
860 | const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) { |
861 | assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!")(static_cast <bool> (DwarfSectionRef.MCSec->isDwarfSect () && "Not a DWARF section!") ? void (0) : __assert_fail ("DwarfSectionRef.MCSec->isDwarfSect() && \"Not a DWARF section!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 861, __extension__ __PRETTY_FUNCTION__ )); |
862 | |
863 | writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0, |
864 | SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF); |
865 | |
866 | writeSymbolAuxDwarfEntry(DwarfSectionRef.Size); |
867 | } |
868 | |
869 | void XCOFFObjectWriter::writeSymbolEntryForControlSection( |
870 | const XCOFFSection &CSectionRef, int16_t SectionIndex, |
871 | XCOFF::StorageClass StorageClass) { |
872 | writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address, |
873 | SectionIndex, CSectionRef.getVisibilityType(), StorageClass); |
874 | |
875 | writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec), |
876 | CSectionRef.MCSec->getMappingClass()); |
877 | } |
878 | |
879 | void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset, |
880 | uint32_t FunctionSize, |
881 | uint64_t LineNumberPointer, |
882 | uint32_t EndIndex) { |
883 | if (is64Bit()) |
884 | writeWord(LineNumberPointer); |
885 | else |
886 | W.write<uint32_t>(EntryOffset); |
887 | W.write<uint32_t>(FunctionSize); |
888 | if (!is64Bit()) |
889 | writeWord(LineNumberPointer); |
890 | W.write<uint32_t>(EndIndex); |
891 | if (is64Bit()) { |
892 | W.OS.write_zeros(1); |
893 | W.write<uint8_t>(XCOFF::AUX_FCN); |
894 | } else { |
895 | W.OS.write_zeros(2); |
896 | } |
897 | } |
898 | |
899 | void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset, |
900 | uint32_t FunctionSize, |
901 | uint32_t EndIndex) { |
902 | assert(is64Bit() && "Exception auxilliary entries are 64-bit only.")(static_cast <bool> (is64Bit() && "Exception auxilliary entries are 64-bit only." ) ? void (0) : __assert_fail ("is64Bit() && \"Exception auxilliary entries are 64-bit only.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 902, __extension__ __PRETTY_FUNCTION__ )); |
903 | W.write<uint64_t>(EntryOffset); |
904 | W.write<uint32_t>(FunctionSize); |
905 | W.write<uint32_t>(EndIndex); |
906 | W.OS.write_zeros(1); // Pad (unused) |
907 | W.write<uint8_t>(XCOFF::AUX_EXCEPT); |
908 | } |
909 | |
910 | void XCOFFObjectWriter::writeFileHeader() { |
911 | W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32); |
912 | W.write<uint16_t>(SectionCount); |
913 | W.write<int32_t>(0); // TimeStamp |
914 | writeWord(SymbolTableOffset); |
915 | if (is64Bit()) { |
916 | W.write<uint16_t>(auxiliaryHeaderSize()); |
917 | W.write<uint16_t>(0); // Flags |
918 | W.write<int32_t>(SymbolTableEntryCount); |
919 | } else { |
920 | W.write<int32_t>(SymbolTableEntryCount); |
921 | W.write<uint16_t>(auxiliaryHeaderSize()); |
922 | W.write<uint16_t>(0); // Flags |
923 | } |
924 | } |
925 | |
926 | void XCOFFObjectWriter::writeAuxFileHeader() { |
927 | if (!auxiliaryHeaderSize()) |
928 | return; |
929 | W.write<uint16_t>(0); // Magic |
930 | W.write<uint16_t>( |
931 | XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the |
932 | // n_type field in the symbol table entry is |
933 | // used in XCOFF32. |
934 | W.write<uint32_t>(Sections[0]->Size); // TextSize |
935 | W.write<uint32_t>(Sections[1]->Size); // InitDataSize |
936 | W.write<uint32_t>(Sections[2]->Size); // BssDataSize |
937 | W.write<uint32_t>(0); // EntryPointAddr |
938 | W.write<uint32_t>(Sections[0]->Address); // TextStartAddr |
939 | W.write<uint32_t>(Sections[1]->Address); // DataStartAddr |
940 | } |
941 | |
942 | void XCOFFObjectWriter::writeSectionHeader(const SectionEntry *Sec) { |
943 | bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0; |
944 | bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0; |
945 | // Nothing to write for this Section. |
946 | if (Sec->Index == SectionEntry::UninitializedIndex) |
947 | return; |
948 | |
949 | // Write Name. |
950 | ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize); |
951 | W.write(NameRef); |
952 | |
953 | // Write the Physical Address and Virtual Address. |
954 | // We use 0 for DWARF sections' Physical and Virtual Addresses. |
955 | writeWord(IsDwarf ? 0 : Sec->Address); |
956 | // Since line number is not supported, we set it to 0 for overflow sections. |
957 | writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address); |
958 | |
959 | writeWord(Sec->Size); |
960 | writeWord(Sec->FileOffsetToData); |
961 | writeWord(Sec->FileOffsetToRelocations); |
962 | writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet. |
963 | |
964 | if (is64Bit()) { |
965 | W.write<uint32_t>(Sec->RelocationCount); |
966 | W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet. |
967 | W.write<int32_t>(Sec->Flags); |
968 | W.OS.write_zeros(4); |
969 | } else { |
970 | // For the overflow section header, s_nreloc provides a reference to the |
971 | // primary section header and s_nlnno must have the same value. |
972 | // For common section headers, if either of s_nreloc or s_nlnno are set to |
973 | // 65535, the other one must also be set to 65535. |
974 | W.write<uint16_t>(Sec->RelocationCount); |
975 | W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow) |
976 | ? Sec->RelocationCount |
977 | : 0); // NumberOfLineNumbers. Not supported yet. |
978 | W.write<int32_t>(Sec->Flags); |
979 | } |
980 | } |
981 | |
982 | void XCOFFObjectWriter::writeSectionHeaderTable() { |
983 | for (const auto *CsectSec : Sections) |
984 | writeSectionHeader(CsectSec); |
985 | for (const auto &DwarfSec : DwarfSections) |
986 | writeSectionHeader(&DwarfSec); |
987 | for (const auto &OverflowSec : OverflowSections) |
988 | writeSectionHeader(&OverflowSec); |
989 | if (hasExceptionSection()) |
990 | writeSectionHeader(&ExceptionSection); |
991 | } |
992 | |
993 | void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, |
994 | const XCOFFSection &Section) { |
995 | if (Section.MCSec->isCsect()) |
996 | writeWord(Section.Address + Reloc.FixupOffsetInCsect); |
997 | else { |
998 | // DWARF sections' address is set to 0. |
999 | assert(Section.MCSec->isDwarfSect() && "unsupport section type!")(static_cast <bool> (Section.MCSec->isDwarfSect() && "unsupport section type!") ? void (0) : __assert_fail ("Section.MCSec->isDwarfSect() && \"unsupport section type!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 999, __extension__ __PRETTY_FUNCTION__ )); |
1000 | writeWord(Reloc.FixupOffsetInCsect); |
1001 | } |
1002 | W.write<uint32_t>(Reloc.SymbolTableIndex); |
1003 | W.write<uint8_t>(Reloc.SignAndSize); |
1004 | W.write<uint8_t>(Reloc.Type); |
1005 | } |
1006 | |
1007 | void XCOFFObjectWriter::writeRelocations() { |
1008 | for (const auto *Section : Sections) { |
1009 | if (Section->Index == SectionEntry::UninitializedIndex) |
1010 | // Nothing to write for this Section. |
1011 | continue; |
1012 | |
1013 | for (const auto *Group : Section->Groups) { |
1014 | if (Group->empty()) |
1015 | continue; |
1016 | |
1017 | for (const auto &Csect : *Group) { |
1018 | for (const auto Reloc : Csect.Relocations) |
1019 | writeRelocation(Reloc, Csect); |
1020 | } |
1021 | } |
1022 | } |
1023 | |
1024 | for (const auto &DwarfSection : DwarfSections) |
1025 | for (const auto &Reloc : DwarfSection.DwarfSect->Relocations) |
1026 | writeRelocation(Reloc, *DwarfSection.DwarfSect); |
1027 | } |
1028 | |
1029 | void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { |
1030 | // Write C_FILE symbols. |
1031 | // The n_name of a C_FILE symbol is the source file's name when no auxiliary |
1032 | // entries are present. |
1033 | for (const std::pair<std::string, size_t> &F : FileNames) { |
1034 | writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG, |
1035 | /*SymbolType=*/0, XCOFF::C_FILE, |
1036 | /*NumberOfAuxEntries=*/0); |
1037 | } |
1038 | |
1039 | for (const auto &Csect : UndefinedCsects) { |
1040 | writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF, |
1041 | Csect.MCSec->getStorageClass()); |
1042 | } |
1043 | |
1044 | for (const auto *Section : Sections) { |
1045 | if (Section->Index == SectionEntry::UninitializedIndex) |
1046 | // Nothing to write for this Section. |
1047 | continue; |
1048 | |
1049 | for (const auto *Group : Section->Groups) { |
1050 | if (Group->empty()) |
1051 | continue; |
1052 | |
1053 | const int16_t SectionIndex = Section->Index; |
1054 | for (const auto &Csect : *Group) { |
1055 | // Write out the control section first and then each symbol in it. |
1056 | writeSymbolEntryForControlSection(Csect, SectionIndex, |
1057 | Csect.MCSec->getStorageClass()); |
1058 | |
1059 | for (const auto &Sym : Csect.Syms) |
1060 | writeSymbolEntryForCsectMemberLabel( |
1061 | Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym))); |
1062 | } |
1063 | } |
1064 | } |
1065 | |
1066 | for (const auto &DwarfSection : DwarfSections) |
1067 | writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect, |
1068 | DwarfSection.Index); |
1069 | } |
1070 | |
1071 | void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry *Sec, |
1072 | uint64_t RelCount) { |
1073 | // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file |
1074 | // may not contain an overflow section header. |
1075 | if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) { |
1076 | // Generate an overflow section header. |
1077 | SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO); |
1078 | |
1079 | // This field specifies the file section number of the section header that |
1080 | // overflowed. |
1081 | SecEntry.RelocationCount = Sec->Index; |
1082 | |
1083 | // This field specifies the number of relocation entries actually |
1084 | // required. |
1085 | SecEntry.Address = RelCount; |
1086 | SecEntry.Index = ++SectionCount; |
1087 | OverflowSections.push_back(std::move(SecEntry)); |
1088 | |
1089 | // The field in the primary section header is always 65535 |
1090 | // (XCOFF::RelocOverflow). |
1091 | Sec->RelocationCount = XCOFF::RelocOverflow; |
1092 | } else { |
1093 | Sec->RelocationCount = RelCount; |
1094 | } |
1095 | } |
1096 | |
1097 | void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry *Sec, |
1098 | uint64_t &RawPointer) { |
1099 | if (!Sec->RelocationCount) |
1100 | return; |
1101 | |
1102 | Sec->FileOffsetToRelocations = RawPointer; |
1103 | uint64_t RelocationSizeInSec = 0; |
1104 | if (!is64Bit() && |
1105 | Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) { |
1106 | // Find its corresponding overflow section. |
1107 | for (auto &OverflowSec : OverflowSections) { |
1108 | if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) { |
1109 | RelocationSizeInSec = |
1110 | OverflowSec.Address * XCOFF::RelocationSerializationSize32; |
1111 | |
1112 | // This field must have the same values as in the corresponding |
1113 | // primary section header. |
1114 | OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations; |
1115 | } |
1116 | } |
1117 | assert(RelocationSizeInSec && "Overflow section header doesn't exist.")(static_cast <bool> (RelocationSizeInSec && "Overflow section header doesn't exist." ) ? void (0) : __assert_fail ("RelocationSizeInSec && \"Overflow section header doesn't exist.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1117, __extension__ __PRETTY_FUNCTION__ )); |
1118 | } else { |
1119 | RelocationSizeInSec = Sec->RelocationCount * |
1120 | (is64Bit() ? XCOFF::RelocationSerializationSize64 |
1121 | : XCOFF::RelocationSerializationSize32); |
1122 | } |
1123 | |
1124 | RawPointer += RelocationSizeInSec; |
1125 | if (RawPointer > MaxRawDataSize) |
1126 | report_fatal_error("Relocation data overflowed this object file."); |
1127 | } |
1128 | |
1129 | void XCOFFObjectWriter::finalizeSectionInfo() { |
1130 | for (auto *Section : Sections) { |
1131 | if (Section->Index == SectionEntry::UninitializedIndex) |
1132 | // Nothing to record for this Section. |
1133 | continue; |
1134 | |
1135 | uint64_t RelCount = 0; |
1136 | for (const auto *Group : Section->Groups) { |
1137 | if (Group->empty()) |
1138 | continue; |
1139 | |
1140 | for (auto &Csect : *Group) |
1141 | RelCount += Csect.Relocations.size(); |
1142 | } |
1143 | finalizeRelocationInfo(Section, RelCount); |
1144 | } |
1145 | |
1146 | for (auto &DwarfSection : DwarfSections) |
1147 | finalizeRelocationInfo(&DwarfSection, |
1148 | DwarfSection.DwarfSect->Relocations.size()); |
1149 | |
1150 | // Calculate the RawPointer value for all headers. |
1151 | uint64_t RawPointer = |
1152 | (is64Bit() ? (XCOFF::FileHeaderSize64 + |
1153 | SectionCount * XCOFF::SectionHeaderSize64) |
1154 | : (XCOFF::FileHeaderSize32 + |
1155 | SectionCount * XCOFF::SectionHeaderSize32)) + |
1156 | auxiliaryHeaderSize(); |
1157 | |
1158 | // Calculate the file offset to the section data. |
1159 | for (auto *Sec : Sections) { |
1160 | if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual) |
1161 | continue; |
1162 | |
1163 | Sec->FileOffsetToData = RawPointer; |
1164 | RawPointer += Sec->Size; |
1165 | if (RawPointer > MaxRawDataSize) |
1166 | report_fatal_error("Section raw data overflowed this object file."); |
1167 | } |
1168 | |
1169 | if (!DwarfSections.empty()) { |
1170 | RawPointer += PaddingsBeforeDwarf; |
1171 | for (auto &DwarfSection : DwarfSections) { |
1172 | DwarfSection.FileOffsetToData = RawPointer; |
1173 | RawPointer += DwarfSection.MemorySize; |
1174 | if (RawPointer > MaxRawDataSize) |
1175 | report_fatal_error("Section raw data overflowed this object file."); |
1176 | } |
1177 | } |
1178 | |
1179 | if (hasExceptionSection()) { |
1180 | ExceptionSection.FileOffsetToData = RawPointer; |
1181 | RawPointer += ExceptionSection.Size; |
1182 | |
1183 | assert(RawPointer <= MaxRawDataSize &&(static_cast <bool> (RawPointer <= MaxRawDataSize && "Section raw data overflowed this object file.") ? void (0) : __assert_fail ("RawPointer <= MaxRawDataSize && \"Section raw data overflowed this object file.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1184, __extension__ __PRETTY_FUNCTION__ )) |
1184 | "Section raw data overflowed this object file.")(static_cast <bool> (RawPointer <= MaxRawDataSize && "Section raw data overflowed this object file.") ? void (0) : __assert_fail ("RawPointer <= MaxRawDataSize && \"Section raw data overflowed this object file.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1184, __extension__ __PRETTY_FUNCTION__ )); |
1185 | } |
1186 | |
1187 | for (auto *Sec : Sections) { |
1188 | if (Sec->Index != SectionEntry::UninitializedIndex) |
1189 | calcOffsetToRelocations(Sec, RawPointer); |
1190 | } |
1191 | |
1192 | for (auto &DwarfSec : DwarfSections) |
1193 | calcOffsetToRelocations(&DwarfSec, RawPointer); |
1194 | |
1195 | // TODO Error check that the number of symbol table entries fits in 32-bits |
1196 | // signed ... |
1197 | if (SymbolTableEntryCount) |
1198 | SymbolTableOffset = RawPointer; |
1199 | } |
1200 | |
1201 | void XCOFFObjectWriter::addExceptionEntry( |
1202 | const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode, |
1203 | unsigned ReasonCode, unsigned FunctionSize, bool hasDebug) { |
1204 | // If a module had debug info, debugging is enabled and XCOFF emits the |
1205 | // exception auxilliary entry. |
1206 | if (hasDebug) |
1207 | ExceptionSection.isDebugEnabled = true; |
1208 | auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName()); |
1209 | if (Entry != ExceptionSection.ExceptionTable.end()) { |
1210 | Entry->second.Entries.push_back( |
1211 | ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); |
1212 | return; |
1213 | } |
1214 | ExceptionInfo NewEntry; |
1215 | NewEntry.FunctionSymbol = Symbol; |
1216 | NewEntry.FunctionSize = FunctionSize; |
1217 | NewEntry.Entries.push_back( |
1218 | ExceptionTableEntry(Trap, LanguageCode, ReasonCode)); |
1219 | ExceptionSection.ExceptionTable.insert( |
1220 | std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry)); |
1221 | } |
1222 | |
1223 | unsigned XCOFFObjectWriter::getExceptionSectionSize() { |
1224 | unsigned EntryNum = 0; |
1225 | |
1226 | for (auto it = ExceptionSection.ExceptionTable.begin(); |
1227 | it != ExceptionSection.ExceptionTable.end(); ++it) |
1228 | // The size() gets +1 to account for the initial entry containing the |
1229 | // symbol table index. |
1230 | EntryNum += it->second.Entries.size() + 1; |
1231 | |
1232 | return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 |
1233 | : XCOFF::ExceptionSectionEntrySize32); |
1234 | } |
1235 | |
1236 | unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) { |
1237 | unsigned EntryNum = 0; |
1238 | for (auto it = ExceptionSection.ExceptionTable.begin(); |
1239 | it != ExceptionSection.ExceptionTable.end(); ++it) { |
1240 | if (Symbol == it->second.FunctionSymbol) |
1241 | break; |
1242 | EntryNum += it->second.Entries.size() + 1; |
1243 | } |
1244 | return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64 |
1245 | : XCOFF::ExceptionSectionEntrySize32); |
1246 | } |
1247 | |
1248 | void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) { |
1249 | // The symbol table starts with all the C_FILE symbols. |
1250 | uint32_t SymbolTableIndex = FileNames.size(); |
1251 | |
1252 | // Calculate indices for undefined symbols. |
1253 | for (auto &Csect : UndefinedCsects) { |
1254 | Csect.Size = 0; |
1255 | Csect.Address = 0; |
1256 | Csect.SymbolTableIndex = SymbolTableIndex; |
1257 | SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; |
1258 | // 1 main and 1 auxiliary symbol table entry for each contained symbol. |
1259 | SymbolTableIndex += 2; |
1260 | } |
1261 | |
1262 | // The address corrresponds to the address of sections and symbols in the |
1263 | // object file. We place the shared address 0 immediately after the |
1264 | // section header table. |
1265 | uint64_t Address = 0; |
1266 | // Section indices are 1-based in XCOFF. |
1267 | int32_t SectionIndex = 1; |
1268 | bool HasTDataSection = false; |
1269 | |
1270 | for (auto *Section : Sections) { |
1271 | const bool IsEmpty = |
1272 | llvm::all_of(Section->Groups, |
1273 | [](const CsectGroup *Group) { return Group->empty(); }); |
1274 | if (IsEmpty) |
1275 | continue; |
1276 | |
1277 | if (SectionIndex > MaxSectionIndex) |
1278 | report_fatal_error("Section index overflow!"); |
1279 | Section->Index = SectionIndex++; |
1280 | SectionCount++; |
1281 | |
1282 | bool SectionAddressSet = false; |
1283 | // Reset the starting address to 0 for TData section. |
1284 | if (Section->Flags == XCOFF::STYP_TDATA) { |
1285 | Address = 0; |
1286 | HasTDataSection = true; |
1287 | } |
1288 | // Reset the starting address to 0 for TBSS section if the object file does |
1289 | // not contain TData Section. |
1290 | if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection) |
1291 | Address = 0; |
1292 | |
1293 | for (auto *Group : Section->Groups) { |
1294 | if (Group->empty()) |
1295 | continue; |
1296 | |
1297 | for (auto &Csect : *Group) { |
1298 | const MCSectionXCOFF *MCSec = Csect.MCSec; |
1299 | Csect.Address = alignTo(Address, MCSec->getAlign()); |
1300 | Csect.Size = Layout.getSectionAddressSize(MCSec); |
1301 | Address = Csect.Address + Csect.Size; |
1302 | Csect.SymbolTableIndex = SymbolTableIndex; |
1303 | SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; |
1304 | // 1 main and 1 auxiliary symbol table entry for the csect. |
1305 | SymbolTableIndex += 2; |
1306 | |
1307 | for (auto &Sym : Csect.Syms) { |
1308 | bool hasExceptEntry = false; |
1309 | auto Entry = |
1310 | ExceptionSection.ExceptionTable.find(Sym.MCSym->getName()); |
1311 | if (Entry != ExceptionSection.ExceptionTable.end()) { |
1312 | hasExceptEntry = true; |
1313 | for (auto &TrapEntry : Entry->second.Entries) { |
1314 | TrapEntry.TrapAddress = Layout.getSymbolOffset(*(Sym.MCSym)) + |
1315 | TrapEntry.Trap->getOffset(); |
1316 | } |
1317 | } |
1318 | Sym.SymbolTableIndex = SymbolTableIndex; |
1319 | SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex; |
1320 | // 1 main and 1 auxiliary symbol table entry for each contained |
1321 | // symbol. For symbols with exception section entries, a function |
1322 | // auxilliary entry is needed, and on 64-bit XCOFF with debugging |
1323 | // enabled, an additional exception auxilliary entry is needed. |
1324 | SymbolTableIndex += 2; |
1325 | if (hasExceptionSection() && hasExceptEntry) { |
1326 | if (is64Bit() && ExceptionSection.isDebugEnabled) |
1327 | SymbolTableIndex += 2; |
1328 | else |
1329 | SymbolTableIndex += 1; |
1330 | } |
1331 | } |
1332 | } |
1333 | |
1334 | if (!SectionAddressSet) { |
1335 | Section->Address = Group->front().Address; |
1336 | SectionAddressSet = true; |
1337 | } |
1338 | } |
1339 | |
1340 | // Make sure the address of the next section aligned to |
1341 | // DefaultSectionAlign. |
1342 | Address = alignTo(Address, DefaultSectionAlign); |
1343 | Section->Size = Address - Section->Address; |
1344 | } |
1345 | |
1346 | // Start to generate DWARF sections. Sections other than DWARF section use |
1347 | // DefaultSectionAlign as the default alignment, while DWARF sections have |
1348 | // their own alignments. If these two alignments are not the same, we need |
1349 | // some paddings here and record the paddings bytes for FileOffsetToData |
1350 | // calculation. |
1351 | if (!DwarfSections.empty()) |
1352 | PaddingsBeforeDwarf = |
1353 | alignTo(Address, |
1354 | (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) - |
1355 | Address; |
1356 | |
1357 | DwarfSectionEntry *LastDwarfSection = nullptr; |
1358 | for (auto &DwarfSection : DwarfSections) { |
1359 | assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!")(static_cast <bool> ((SectionIndex <= MaxSectionIndex ) && "Section index overflow!") ? void (0) : __assert_fail ("(SectionIndex <= MaxSectionIndex) && \"Section index overflow!\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1359, __extension__ __PRETTY_FUNCTION__ )); |
1360 | |
1361 | XCOFFSection &DwarfSect = *DwarfSection.DwarfSect; |
1362 | const MCSectionXCOFF *MCSec = DwarfSect.MCSec; |
1363 | |
1364 | // Section index. |
1365 | DwarfSection.Index = SectionIndex++; |
1366 | SectionCount++; |
1367 | |
1368 | // Symbol index. |
1369 | DwarfSect.SymbolTableIndex = SymbolTableIndex; |
1370 | SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex; |
1371 | // 1 main and 1 auxiliary symbol table entry for the csect. |
1372 | SymbolTableIndex += 2; |
1373 | |
1374 | // Section address. Make it align to section alignment. |
1375 | // We use address 0 for DWARF sections' Physical and Virtual Addresses. |
1376 | // This address is used to tell where is the section in the final object. |
1377 | // See writeSectionForDwarfSectionEntry(). |
1378 | DwarfSection.Address = DwarfSect.Address = |
1379 | alignTo(Address, MCSec->getAlign()); |
1380 | |
1381 | // Section size. |
1382 | // For DWARF section, we must use the real size which may be not aligned. |
1383 | DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec); |
1384 | |
1385 | Address = DwarfSection.Address + DwarfSection.Size; |
1386 | |
1387 | if (LastDwarfSection) |
1388 | LastDwarfSection->MemorySize = |
1389 | DwarfSection.Address - LastDwarfSection->Address; |
1390 | LastDwarfSection = &DwarfSection; |
1391 | } |
1392 | if (LastDwarfSection) { |
1393 | // Make the final DWARF section address align to the default section |
1394 | // alignment for follow contents. |
1395 | Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size, |
1396 | DefaultSectionAlign); |
1397 | LastDwarfSection->MemorySize = Address - LastDwarfSection->Address; |
1398 | } |
1399 | if (hasExceptionSection()) { |
1400 | ExceptionSection.Index = SectionIndex++; |
1401 | SectionCount++; |
1402 | ExceptionSection.Address = 0; |
1403 | ExceptionSection.Size = getExceptionSectionSize(); |
1404 | Address += ExceptionSection.Size; |
1405 | Address = alignTo(Address, DefaultSectionAlign); |
Value stored to 'Address' is never read | |
1406 | } |
1407 | |
1408 | SymbolTableEntryCount = SymbolTableIndex; |
1409 | } |
1410 | |
1411 | void XCOFFObjectWriter::writeSectionForControlSectionEntry( |
1412 | const MCAssembler &Asm, const MCAsmLayout &Layout, |
1413 | const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) { |
1414 | // Nothing to write for this Section. |
1415 | if (CsectEntry.Index == SectionEntry::UninitializedIndex) |
1416 | return; |
1417 | |
1418 | // There could be a gap (without corresponding zero padding) between |
1419 | // sections. |
1420 | // There could be a gap (without corresponding zero padding) between |
1421 | // sections. |
1422 | assert(((CurrentAddressLocation <= CsectEntry.Address) ||(static_cast <bool> (((CurrentAddressLocation <= CsectEntry .Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry .Flags == XCOFF::STYP_TBSS)) && "CurrentAddressLocation should be less than or equal to section " "address if the section is not TData or TBSS.") ? void (0) : __assert_fail ("((CurrentAddressLocation <= CsectEntry.Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry.Flags == XCOFF::STYP_TBSS)) && \"CurrentAddressLocation should be less than or equal to section \" \"address if the section is not TData or TBSS.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1426, __extension__ __PRETTY_FUNCTION__ )) |
1423 | (CsectEntry.Flags == XCOFF::STYP_TDATA) ||(static_cast <bool> (((CurrentAddressLocation <= CsectEntry .Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry .Flags == XCOFF::STYP_TBSS)) && "CurrentAddressLocation should be less than or equal to section " "address if the section is not TData or TBSS.") ? void (0) : __assert_fail ("((CurrentAddressLocation <= CsectEntry.Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry.Flags == XCOFF::STYP_TBSS)) && \"CurrentAddressLocation should be less than or equal to section \" \"address if the section is not TData or TBSS.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1426, __extension__ __PRETTY_FUNCTION__ )) |
1424 | (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&(static_cast <bool> (((CurrentAddressLocation <= CsectEntry .Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry .Flags == XCOFF::STYP_TBSS)) && "CurrentAddressLocation should be less than or equal to section " "address if the section is not TData or TBSS.") ? void (0) : __assert_fail ("((CurrentAddressLocation <= CsectEntry.Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry.Flags == XCOFF::STYP_TBSS)) && \"CurrentAddressLocation should be less than or equal to section \" \"address if the section is not TData or TBSS.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1426, __extension__ __PRETTY_FUNCTION__ )) |
1425 | "CurrentAddressLocation should be less than or equal to section "(static_cast <bool> (((CurrentAddressLocation <= CsectEntry .Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry .Flags == XCOFF::STYP_TBSS)) && "CurrentAddressLocation should be less than or equal to section " "address if the section is not TData or TBSS.") ? void (0) : __assert_fail ("((CurrentAddressLocation <= CsectEntry.Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry.Flags == XCOFF::STYP_TBSS)) && \"CurrentAddressLocation should be less than or equal to section \" \"address if the section is not TData or TBSS.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1426, __extension__ __PRETTY_FUNCTION__ )) |
1426 | "address if the section is not TData or TBSS.")(static_cast <bool> (((CurrentAddressLocation <= CsectEntry .Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry .Flags == XCOFF::STYP_TBSS)) && "CurrentAddressLocation should be less than or equal to section " "address if the section is not TData or TBSS.") ? void (0) : __assert_fail ("((CurrentAddressLocation <= CsectEntry.Address) || (CsectEntry.Flags == XCOFF::STYP_TDATA) || (CsectEntry.Flags == XCOFF::STYP_TBSS)) && \"CurrentAddressLocation should be less than or equal to section \" \"address if the section is not TData or TBSS.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1426, __extension__ __PRETTY_FUNCTION__ )); |
1427 | |
1428 | CurrentAddressLocation = CsectEntry.Address; |
1429 | |
1430 | // For virtual sections, nothing to write. But need to increase |
1431 | // CurrentAddressLocation for later sections like DWARF section has a correct |
1432 | // writing location. |
1433 | if (CsectEntry.IsVirtual) { |
1434 | CurrentAddressLocation += CsectEntry.Size; |
1435 | return; |
1436 | } |
1437 | |
1438 | for (const auto &Group : CsectEntry.Groups) { |
1439 | for (const auto &Csect : *Group) { |
1440 | if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) |
1441 | W.OS.write_zeros(PaddingSize); |
1442 | if (Csect.Size) |
1443 | Asm.writeSectionData(W.OS, Csect.MCSec, Layout); |
1444 | CurrentAddressLocation = Csect.Address + Csect.Size; |
1445 | } |
1446 | } |
1447 | |
1448 | // The size of the tail padding in a section is the end virtual address of |
1449 | // the current section minus the the end virtual address of the last csect |
1450 | // in that section. |
1451 | if (uint64_t PaddingSize = |
1452 | CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) { |
1453 | W.OS.write_zeros(PaddingSize); |
1454 | CurrentAddressLocation += PaddingSize; |
1455 | } |
1456 | } |
1457 | |
1458 | void XCOFFObjectWriter::writeSectionForDwarfSectionEntry( |
1459 | const MCAssembler &Asm, const MCAsmLayout &Layout, |
1460 | const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) { |
1461 | // There could be a gap (without corresponding zero padding) between |
1462 | // sections. For example DWARF section alignment is bigger than |
1463 | // DefaultSectionAlign. |
1464 | assert(CurrentAddressLocation <= DwarfEntry.Address &&(static_cast <bool> (CurrentAddressLocation <= DwarfEntry .Address && "CurrentAddressLocation should be less than or equal to section " "address.") ? void (0) : __assert_fail ("CurrentAddressLocation <= DwarfEntry.Address && \"CurrentAddressLocation should be less than or equal to section \" \"address.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1466, __extension__ __PRETTY_FUNCTION__ )) |
1465 | "CurrentAddressLocation should be less than or equal to section "(static_cast <bool> (CurrentAddressLocation <= DwarfEntry .Address && "CurrentAddressLocation should be less than or equal to section " "address.") ? void (0) : __assert_fail ("CurrentAddressLocation <= DwarfEntry.Address && \"CurrentAddressLocation should be less than or equal to section \" \"address.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1466, __extension__ __PRETTY_FUNCTION__ )) |
1466 | "address.")(static_cast <bool> (CurrentAddressLocation <= DwarfEntry .Address && "CurrentAddressLocation should be less than or equal to section " "address.") ? void (0) : __assert_fail ("CurrentAddressLocation <= DwarfEntry.Address && \"CurrentAddressLocation should be less than or equal to section \" \"address.\"" , "llvm/lib/MC/XCOFFObjectWriter.cpp", 1466, __extension__ __PRETTY_FUNCTION__ )); |
1467 | |
1468 | if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation) |
1469 | W.OS.write_zeros(PaddingSize); |
1470 | |
1471 | if (DwarfEntry.Size) |
1472 | Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout); |
1473 | |
1474 | CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size; |
1475 | |
1476 | // DWARF section size is not aligned to DefaultSectionAlign. |
1477 | // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign. |
1478 | uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign; |
1479 | uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0; |
1480 | if (TailPaddingSize) |
1481 | W.OS.write_zeros(TailPaddingSize); |
1482 | |
1483 | CurrentAddressLocation += TailPaddingSize; |
1484 | } |
1485 | |
1486 | void XCOFFObjectWriter::writeSectionForExceptionSectionEntry( |
1487 | const MCAssembler &Asm, const MCAsmLayout &Layout, |
1488 | ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation) { |
1489 | for (auto it = ExceptionEntry.ExceptionTable.begin(); |
1490 | it != ExceptionEntry.ExceptionTable.end(); it++) { |
1491 | // For every symbol that has exception entries, you must start the entries |
1492 | // with an initial symbol table index entry |
1493 | W.write<uint32_t>(SymbolIndexMap[it->second.FunctionSymbol]); |
1494 | if (is64Bit()) { |
1495 | // 4-byte padding on 64-bit. |
1496 | W.OS.write_zeros(4); |
1497 | } |
1498 | W.OS.write_zeros(2); |
1499 | for (auto &TrapEntry : it->second.Entries) { |
1500 | writeWord(TrapEntry.TrapAddress); |
1501 | W.write<uint8_t>(TrapEntry.Lang); |
1502 | W.write<uint8_t>(TrapEntry.Reason); |
1503 | } |
1504 | } |
1505 | |
1506 | CurrentAddressLocation += getExceptionSectionSize(); |
1507 | } |
1508 | |
1509 | // Takes the log base 2 of the alignment and shifts the result into the 5 most |
1510 | // significant bits of a byte, then or's in the csect type into the least |
1511 | // significant 3 bits. |
1512 | uint8_t getEncodedType(const MCSectionXCOFF *Sec) { |
1513 | unsigned Log2Align = Log2(Sec->getAlign()); |
1514 | // Result is a number in the range [0, 31] which fits in the 5 least |
1515 | // significant bits. Shift this value into the 5 most significant bits, and |
1516 | // bitwise-or in the csect type. |
1517 | uint8_t EncodedAlign = Log2Align << 3; |
1518 | return EncodedAlign | Sec->getCSectType(); |
1519 | } |
1520 | |
1521 | } // end anonymous namespace |
1522 | |
1523 | std::unique_ptr<MCObjectWriter> |
1524 | llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, |
1525 | raw_pwrite_stream &OS) { |
1526 | return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS); |
1527 | } |