Bug Summary

File:llvm/lib/MC/XCOFFObjectWriter.cpp
Warning:line 573, column 7
Value stored to 'CurrentAddressLocation' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name XCOFFObjectWriter.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/MC -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/MC -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/MC -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/MC -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/MC/XCOFFObjectWriter.cpp
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/EndianStream.h"
26#include "llvm/Support/Error.h"
27#include "llvm/Support/MathExtras.h"
28
29#include <deque>
30
31using namespace llvm;
32
33// An XCOFF object file has a limited set of predefined sections. The most
34// important ones for us (right now) are:
35// .text --> contains program code and read-only data.
36// .data --> contains initialized data, function descriptors, and the TOC.
37// .bss --> contains uninitialized data.
38// Each of these sections is composed of 'Control Sections'. A Control Section
39// is more commonly referred to as a csect. A csect is an indivisible unit of
40// code or data, and acts as a container for symbols. A csect is mapped
41// into a section based on its storage-mapping class, with the exception of
42// XMC_RW which gets mapped to either .data or .bss based on whether it's
43// explicitly initialized or not.
44//
45// We don't represent the sections in the MC layer as there is nothing
46// interesting about them at at that level: they carry information that is
47// only relevant to the ObjectWriter, so we materialize them in this class.
48namespace {
49
50constexpr unsigned DefaultSectionAlign = 4;
51constexpr int16_t MaxSectionIndex = INT16_MAX(32767);
52
53// Packs the csect's alignment and type into a byte.
54uint8_t getEncodedType(const MCSectionXCOFF *);
55
56struct XCOFFRelocation {
57 uint32_t SymbolTableIndex;
58 uint32_t FixupOffsetInCsect;
59 uint8_t SignAndSize;
60 uint8_t Type;
61};
62
63// Wrapper around an MCSymbolXCOFF.
64struct Symbol {
65 const MCSymbolXCOFF *const MCSym;
66 uint32_t SymbolTableIndex;
67
68 XCOFF::StorageClass getStorageClass() const {
69 return MCSym->getStorageClass();
70 }
71 StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
72 Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
73};
74
75// Wrapper for an MCSectionXCOFF.
76// It can be a Csect or debug section or DWARF section and so on.
77struct XCOFFSection {
78 const MCSectionXCOFF *const MCSec;
79 uint32_t SymbolTableIndex;
80 uint32_t Address;
81 uint32_t Size;
82
83 SmallVector<Symbol, 1> Syms;
84 SmallVector<XCOFFRelocation, 1> Relocations;
85 StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
86 XCOFFSection(const MCSectionXCOFF *MCSec)
87 : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
88};
89
90// Type to be used for a container representing a set of csects with
91// (approximately) the same storage mapping class. For example all the csects
92// with a storage mapping class of `xmc_pr` will get placed into the same
93// container.
94using CsectGroup = std::deque<XCOFFSection>;
95using CsectGroups = std::deque<CsectGroup *>;
96
97// The basic section entry defination. This Section represents a section entry
98// in XCOFF section header table.
99struct SectionEntry {
100 char Name[XCOFF::NameSize];
101 // The physical/virtual address of the section. For an object file
102 // these values are equivalent.
103 uint32_t Address;
104 uint32_t Size;
105 uint32_t FileOffsetToData;
106 uint32_t FileOffsetToRelocations;
107 uint32_t RelocationCount;
108 int32_t Flags;
109
110 int16_t Index;
111
112 // XCOFF has special section numbers for symbols:
113 // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
114 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
115 // relocatable.
116 // 0 Specifies N_UNDEF, an undefined external symbol.
117 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
118 // hasn't been initialized.
119 static constexpr int16_t UninitializedIndex =
120 XCOFF::ReservedSectionNum::N_DEBUG - 1;
121
122 SectionEntry(StringRef N, int32_t Flags)
123 : Name(), Address(0), Size(0), FileOffsetToData(0),
124 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
125 Index(UninitializedIndex) {
126 assert(N.size() <= XCOFF::NameSize && "section name too long")(static_cast<void> (0));
127 memcpy(Name, N.data(), N.size());
128 }
129
130 virtual void reset() {
131 Address = 0;
132 Size = 0;
133 FileOffsetToData = 0;
134 FileOffsetToRelocations = 0;
135 RelocationCount = 0;
136 Index = UninitializedIndex;
137 }
138
139 virtual ~SectionEntry() {}
140};
141
142// Represents the data related to a section excluding the csects that make up
143// the raw data of the section. The csects are stored separately as not all
144// sections contain csects, and some sections contain csects which are better
145// stored separately, e.g. the .data section containing read-write, descriptor,
146// TOCBase and TOC-entry csects.
147struct CsectSectionEntry : public SectionEntry {
148 // Virtual sections do not need storage allocated in the object file.
149 const bool IsVirtual;
150
151 // This is a section containing csect groups.
152 CsectGroups Groups;
153
154 CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
155 CsectGroups Groups)
156 : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
157 assert(N.size() <= XCOFF::NameSize && "section name too long")(static_cast<void> (0));
158 memcpy(Name, N.data(), N.size());
159 }
160
161 void reset() override {
162 SectionEntry::reset();
163 // Clear any csects we have stored.
164 for (auto *Group : Groups)
165 Group->clear();
166 }
167
168 virtual ~CsectSectionEntry() {}
169};
170
171class XCOFFObjectWriter : public MCObjectWriter {
172
173 uint32_t SymbolTableEntryCount = 0;
174 uint32_t SymbolTableOffset = 0;
175 uint16_t SectionCount = 0;
176 uint32_t RelocationEntryOffset = 0;
177
178 support::endian::Writer W;
179 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
180 StringTableBuilder Strings;
181
182 // Maps the MCSection representation to its corresponding XCOFFSection
183 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
184 // from its containing MCSectionXCOFF.
185 DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
186
187 // Maps the MCSymbol representation to its corrresponding symbol table index.
188 // Needed for relocation.
189 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
190
191 // CsectGroups. These store the csects which make up different parts of
192 // the sections. Should have one for each set of csects that get mapped into
193 // the same section and get handled in a 'similar' way.
194 CsectGroup UndefinedCsects;
195 CsectGroup ProgramCodeCsects;
196 CsectGroup ReadOnlyCsects;
197 CsectGroup DataCsects;
198 CsectGroup FuncDSCsects;
199 CsectGroup TOCCsects;
200 CsectGroup BSSCsects;
201 CsectGroup TDataCsects;
202 CsectGroup TBSSCsects;
203
204 // The Predefined sections.
205 CsectSectionEntry Text;
206 CsectSectionEntry Data;
207 CsectSectionEntry BSS;
208 CsectSectionEntry TData;
209 CsectSectionEntry TBSS;
210
211 // All the XCOFF sections, in the order they will appear in the section header
212 // table.
213 std::array<CsectSectionEntry *const, 5> Sections{
214 {&Text, &Data, &BSS, &TData, &TBSS}};
215
216 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
217
218 virtual void reset() override;
219
220 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
221
222 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
223 const MCFixup &, MCValue, uint64_t &) override;
224
225 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
226
227 static bool nameShouldBeInStringTable(const StringRef &);
228 void writeSymbolName(const StringRef &);
229 void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
230 const XCOFFSection &, int16_t,
231 uint64_t);
232 void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t,
233 XCOFF::StorageClass);
234 void writeFileHeader();
235 void writeSectionHeaderTable();
236 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
237 void writeSymbolTable(const MCAsmLayout &Layout);
238 void writeRelocations();
239 void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &CSection);
240
241 // Called after all the csects and symbols have been processed by
242 // `executePostLayoutBinding`, this function handles building up the majority
243 // of the structures in the object file representation. Namely:
244 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
245 // sizes.
246 // *) Assigns symbol table indices.
247 // *) Builds up the section header table by adding any non-empty sections to
248 // `Sections`.
249 void assignAddressesAndIndices(const MCAsmLayout &);
250 void finalizeSectionInfo();
251
252 bool
253 needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
254 return false;
255 }
256
257 // Returns the size of the auxiliary header to be written to the object file.
258 size_t auxiliaryHeaderSize() const {
259 assert(!needsAuxiliaryHeader() &&(static_cast<void> (0))
260 "Auxiliary header support not implemented.")(static_cast<void> (0));
261 return 0;
262 }
263
264public:
265 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
266 raw_pwrite_stream &OS);
267};
268
269XCOFFObjectWriter::XCOFFObjectWriter(
270 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
271 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
272 Strings(StringTableBuilder::XCOFF),
273 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
274 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
275 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
276 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
277 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
278 CsectGroups{&BSSCsects}),
279 TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
280 CsectGroups{&TDataCsects}),
281 TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
282 CsectGroups{&TBSSCsects}) {}
283
284void XCOFFObjectWriter::reset() {
285 // Clear the mappings we created.
286 SymbolIndexMap.clear();
287 SectionMap.clear();
288
289 UndefinedCsects.clear();
290 // Reset any sections we have written to, and empty the section header table.
291 for (auto *Sec : Sections)
292 Sec->reset();
293
294 // Reset states in XCOFFObjectWriter.
295 SymbolTableEntryCount = 0;
296 SymbolTableOffset = 0;
297 SectionCount = 0;
298 RelocationEntryOffset = 0;
299 Strings.clear();
300
301 MCObjectWriter::reset();
302}
303
304CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
305 switch (MCSec->getMappingClass()) {
306 case XCOFF::XMC_PR:
307 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast<void> (0))
308 "Only an initialized csect can contain program code.")(static_cast<void> (0));
309 return ProgramCodeCsects;
310 case XCOFF::XMC_RO:
311 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast<void> (0))
312 "Only an initialized csect can contain read only data.")(static_cast<void> (0));
313 return ReadOnlyCsects;
314 case XCOFF::XMC_RW:
315 if (XCOFF::XTY_CM == MCSec->getCSectType())
316 return BSSCsects;
317
318 if (XCOFF::XTY_SD == MCSec->getCSectType())
319 return DataCsects;
320
321 report_fatal_error("Unhandled mapping of read-write csect to section.");
322 case XCOFF::XMC_DS:
323 return FuncDSCsects;
324 case XCOFF::XMC_BS:
325 assert(XCOFF::XTY_CM == MCSec->getCSectType() &&(static_cast<void> (0))
326 "Mapping invalid csect. CSECT with bss storage class must be "(static_cast<void> (0))
327 "common type.")(static_cast<void> (0));
328 return BSSCsects;
329 case XCOFF::XMC_TL:
330 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast<void> (0))
331 "Mapping invalid csect. CSECT with tdata storage class must be "(static_cast<void> (0))
332 "an initialized csect.")(static_cast<void> (0));
333 return TDataCsects;
334 case XCOFF::XMC_UL:
335 assert(XCOFF::XTY_CM == MCSec->getCSectType() &&(static_cast<void> (0))
336 "Mapping invalid csect. CSECT with tbss storage class must be "(static_cast<void> (0))
337 "an uninitialized csect.")(static_cast<void> (0));
338 return TBSSCsects;
339 case XCOFF::XMC_TC0:
340 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast<void> (0))
341 "Only an initialized csect can contain TOC-base.")(static_cast<void> (0));
342 assert(TOCCsects.empty() &&(static_cast<void> (0))
343 "We should have only one TOC-base, and it should be the first csect "(static_cast<void> (0))
344 "in this CsectGroup.")(static_cast<void> (0));
345 return TOCCsects;
346 case XCOFF::XMC_TC:
347 case XCOFF::XMC_TE:
348 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&(static_cast<void> (0))
349 "Only an initialized csect can contain TC entry.")(static_cast<void> (0));
350 assert(!TOCCsects.empty() &&(static_cast<void> (0))
351 "We should at least have a TOC-base in this CsectGroup.")(static_cast<void> (0));
352 return TOCCsects;
353 case XCOFF::XMC_TD:
354 report_fatal_error("toc-data not yet supported when writing object files.");
355 default:
356 report_fatal_error("Unhandled mapping of csect to section.");
357 }
358}
359
360static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
361 if (XSym->isDefined())
362 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
363 return XSym->getRepresentedCsect();
364}
365
366void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
367 const MCAsmLayout &Layout) {
368 if (TargetObjectWriter->is64Bit())
369 report_fatal_error("64-bit XCOFF object files are not supported yet.");
370
371 for (const auto &S : Asm) {
372 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
373 assert(SectionMap.find(MCSec) == SectionMap.end() &&(static_cast<void> (0))
374 "Cannot add a section twice.")(static_cast<void> (0));
375 assert(XCOFF::XTY_ER != MCSec->getCSectType() &&(static_cast<void> (0))
376 "An undefined csect should not get registered.")(static_cast<void> (0));
377
378 // If the name does not fit in the storage provided in the symbol table
379 // entry, add it to the string table.
380 if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
381 Strings.add(MCSec->getSymbolTableName());
382
383 CsectGroup &Group = getCsectGroup(MCSec);
384 Group.emplace_back(MCSec);
385 SectionMap[MCSec] = &Group.back();
386 }
387
388 for (const MCSymbol &S : Asm.symbols()) {
389 // Nothing to do for temporary symbols.
390 if (S.isTemporary())
391 continue;
392
393 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
394 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
395
396 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
397 // Handle undefined symbol.
398 UndefinedCsects.emplace_back(ContainingCsect);
399 SectionMap[ContainingCsect] = &UndefinedCsects.back();
400 if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
401 Strings.add(ContainingCsect->getSymbolTableName());
402 continue;
403 }
404
405 // If the symbol is the csect itself, we don't need to put the symbol
406 // into csect's Syms.
407 if (XSym == ContainingCsect->getQualNameSymbol())
408 continue;
409
410 // Only put a label into the symbol table when it is an external label.
411 if (!XSym->isExternal())
412 continue;
413
414 assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&(static_cast<void> (0))
415 "Expected containing csect to exist in map")(static_cast<void> (0));
416 XCOFFSection *Csect = SectionMap[ContainingCsect];
417 // Lookup the containing csect and add the symbol to it.
418 assert(Csect->MCSec->isCsect() && "only csect is supported now!")(static_cast<void> (0));
419 Csect->Syms.emplace_back(XSym);
420
421 // If the name does not fit in the storage provided in the symbol table
422 // entry, add it to the string table.
423 if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
424 Strings.add(XSym->getSymbolTableName());
425 }
426
427 Strings.finalize();
428 assignAddressesAndIndices(Layout);
429}
430
431void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
432 const MCAsmLayout &Layout,
433 const MCFragment *Fragment,
434 const MCFixup &Fixup, MCValue Target,
435 uint64_t &FixedValue) {
436 auto getIndex = [this](const MCSymbol *Sym,
437 const MCSectionXCOFF *ContainingCsect) {
438 // If we could not find the symbol directly in SymbolIndexMap, this symbol
439 // could either be a temporary symbol or an undefined symbol. In this case,
440 // we would need to have the relocation reference its csect instead.
441 return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
442 ? SymbolIndexMap[Sym]
443 : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
444 };
445
446 auto getVirtualAddress = [this,
447 &Layout](const MCSymbol *Sym,
448 const MCSectionXCOFF *ContainingCsect) {
449 // If Sym is a csect, return csect's address.
450 // If Sym is a label, return csect's address + label's offset from the csect.
451 return SectionMap[ContainingCsect]->Address +
452 (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
453 };
454
455 const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
456
457 MCAsmBackend &Backend = Asm.getBackend();
458 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
459 MCFixupKindInfo::FKF_IsPCRel;
460
461 uint8_t Type;
462 uint8_t SignAndSize;
463 std::tie(Type, SignAndSize) =
464 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
465
466 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
467
468 if (SymASec->isCsect() && SymASec->getMappingClass() == XCOFF::XMC_TD)
469 report_fatal_error("toc-data not yet supported when writing object files.");
470
471 assert(SectionMap.find(SymASec) != SectionMap.end() &&(static_cast<void> (0))
472 "Expected containing csect to exist in map.")(static_cast<void> (0));
473
474 const uint32_t Index = getIndex(SymA, SymASec);
475 if (Type == XCOFF::RelocationType::R_POS ||
476 Type == XCOFF::RelocationType::R_TLS)
477 // The FixedValue should be symbol's virtual address in this object file
478 // plus any constant value that we might get.
479 FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
480 else if (Type == XCOFF::RelocationType::R_TLSM)
481 // The FixedValue should always be zero since the region handle is only
482 // known at load time.
483 FixedValue = 0;
484 else if (Type == XCOFF::RelocationType::R_TOC ||
485 Type == XCOFF::RelocationType::R_TOCL) {
486 // The FixedValue should be the TOC entry offset from the TOC-base plus any
487 // constant offset value.
488 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
489 TOCCsects.front().Address +
490 Target.getConstant();
491 if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
492 report_fatal_error("TOCEntryOffset overflows in small code model mode");
493
494 FixedValue = TOCEntryOffset;
495 }
496
497 assert((static_cast<void> (0))
498 (TargetObjectWriter->is64Bit() ||(static_cast<void> (0))
499 Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&(static_cast<void> (0))
500 "Fragment offset + fixup offset is overflowed in 32-bit mode.")(static_cast<void> (0));
501 uint32_t FixupOffsetInCsect =
502 Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
503
504 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
505 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
506 assert(SectionMap.find(RelocationSec) != SectionMap.end() &&(static_cast<void> (0))
507 "Expected containing csect to exist in map.")(static_cast<void> (0));
508 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
509
510 if (!Target.getSymB())
511 return;
512
513 const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
514 if (SymA == SymB)
515 report_fatal_error("relocation for opposite term is not yet supported");
516
517 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
518 assert(SectionMap.find(SymBSec) != SectionMap.end() &&(static_cast<void> (0))
519 "Expected containing csect to exist in map.")(static_cast<void> (0));
520 if (SymASec == SymBSec)
521 report_fatal_error(
522 "relocation for paired relocatable term is not yet supported");
523
524 assert(Type == XCOFF::RelocationType::R_POS &&(static_cast<void> (0))
525 "SymA must be R_POS here if it's not opposite term or paired "(static_cast<void> (0))
526 "relocatable term.")(static_cast<void> (0));
527 const uint32_t IndexB = getIndex(SymB, SymBSec);
528 // SymB must be R_NEG here, given the general form of Target(MCValue) is
529 // "SymbolA - SymbolB + imm64".
530 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
531 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
532 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
533 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
534 // now we just need to fold "- SymbolB" here.
535 FixedValue -= getVirtualAddress(SymB, SymBSec);
536}
537
538void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
539 const MCAsmLayout &Layout) {
540 uint32_t CurrentAddressLocation = 0;
541 for (const auto *Section : Sections) {
542 // Nothing to write for this Section.
543 if (Section->Index == SectionEntry::UninitializedIndex ||
544 Section->IsVirtual)
545 continue;
546
547 // There could be a gap (without corresponding zero padding) between
548 // sections.
549 assert(((CurrentAddressLocation <= Section->Address) ||(static_cast<void> (0))
550 (Section->Flags == XCOFF::STYP_TDATA) ||(static_cast<void> (0))
551 (Section->Flags == XCOFF::STYP_TBSS)) &&(static_cast<void> (0))
552 "CurrentAddressLocation should be less than or equal to section "(static_cast<void> (0))
553 "address if the section is not TData or TBSS.")(static_cast<void> (0));
554
555 CurrentAddressLocation = Section->Address;
556
557 for (const auto *Group : Section->Groups) {
558 for (const auto &Csect : *Group) {
559 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
560 W.OS.write_zeros(PaddingSize);
561 if (Csect.Size)
562 Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
563 CurrentAddressLocation = Csect.Address + Csect.Size;
564 }
565 }
566
567 // The size of the tail padding in a section is the end virtual address of
568 // the current section minus the the end virtual address of the last csect
569 // in that section.
570 if (uint32_t PaddingSize =
571 Section->Address + Section->Size - CurrentAddressLocation) {
572 W.OS.write_zeros(PaddingSize);
573 CurrentAddressLocation += PaddingSize;
Value stored to 'CurrentAddressLocation' is never read
574 }
575 }
576}
577
578uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
579 const MCAsmLayout &Layout) {
580 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
581 // linking is not enabled, in case, like with Windows COFF, such a timestamp
582 // is incompatible with incremental linking of XCOFF.
583 if (Asm.isIncrementalLinkerCompatible())
584 report_fatal_error("Incremental linking not supported for XCOFF.");
585
586 if (TargetObjectWriter->is64Bit())
587 report_fatal_error("64-bit XCOFF object files are not supported yet.");
588
589 finalizeSectionInfo();
590 uint64_t StartOffset = W.OS.tell();
591
592 writeFileHeader();
593 writeSectionHeaderTable();
594 writeSections(Asm, Layout);
595 writeRelocations();
596
597 writeSymbolTable(Layout);
598 // Write the string table.
599 Strings.write(W.OS);
600
601 return W.OS.tell() - StartOffset;
602}
603
604bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
605 return SymbolName.size() > XCOFF::NameSize;
606}
607
608void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
609 if (nameShouldBeInStringTable(SymbolName)) {
610 W.write<int32_t>(0);
611 W.write<uint32_t>(Strings.getOffset(SymbolName));
612 } else {
613 char Name[XCOFF::NameSize+1];
614 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
615 ArrayRef<char> NameRef(Name, XCOFF::NameSize);
616 W.write(NameRef);
617 }
618}
619
620void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
621 const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
622 int16_t SectionIndex, uint64_t SymbolOffset) {
623 // Name or Zeros and string table offset
624 writeSymbolName(SymbolRef.getSymbolTableName());
625 assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&(static_cast<void> (0))
626 "Symbol address overflows.")(static_cast<void> (0));
627 W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
628 W.write<int16_t>(SectionIndex);
629 // Basic/Derived type. See the description of the n_type field for symbol
630 // table entries for a detailed description. Since we don't yet support
631 // visibility, and all other bits are either optionally set or reserved, this
632 // is always zero.
633 // TODO FIXME How to assert a symbol's visibilty is default?
634 // TODO Set the function indicator (bit 10, 0x0020) for functions
635 // when debugging is enabled.
636 W.write<uint16_t>(0);
637 W.write<uint8_t>(SymbolRef.getStorageClass());
638 // Always 1 aux entry for now.
639 W.write<uint8_t>(1);
640
641 // Now output the auxiliary entry.
642 W.write<uint32_t>(CSectionRef.SymbolTableIndex);
643 // Parameter typecheck hash. Not supported.
644 W.write<uint32_t>(0);
645 // Typecheck section number. Not supported.
646 W.write<uint16_t>(0);
647 // Symbol type: Label
648 W.write<uint8_t>(XCOFF::XTY_LD);
649 // Storage mapping class.
650 W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
651 // Reserved (x_stab).
652 W.write<uint32_t>(0);
653 // Reserved (x_snstab).
654 W.write<uint16_t>(0);
655}
656
657void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
658 const XCOFFSection &CSectionRef, int16_t SectionIndex,
659 XCOFF::StorageClass StorageClass) {
660 // n_name, n_zeros, n_offset
661 writeSymbolName(CSectionRef.getSymbolTableName());
662 // n_value
663 W.write<uint32_t>(CSectionRef.Address);
664 // n_scnum
665 W.write<int16_t>(SectionIndex);
666 // Basic/Derived type. See the description of the n_type field for symbol
667 // table entries for a detailed description. Since we don't yet support
668 // visibility, and all other bits are either optionally set or reserved, this
669 // is always zero.
670 // TODO FIXME How to assert a symbol's visibilty is default?
671 // TODO Set the function indicator (bit 10, 0x0020) for functions
672 // when debugging is enabled.
673 W.write<uint16_t>(0);
674 // n_sclass
675 W.write<uint8_t>(StorageClass);
676 // Always 1 aux entry for now.
677 W.write<uint8_t>(1);
678
679 // Now output the auxiliary entry.
680 W.write<uint32_t>(CSectionRef.Size);
681 // Parameter typecheck hash. Not supported.
682 W.write<uint32_t>(0);
683 // Typecheck section number. Not supported.
684 W.write<uint16_t>(0);
685 // Symbol type.
686 W.write<uint8_t>(getEncodedType(CSectionRef.MCSec));
687 // Storage mapping class.
688 W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
689 // Reserved (x_stab).
690 W.write<uint32_t>(0);
691 // Reserved (x_snstab).
692 W.write<uint16_t>(0);
693}
694
695void XCOFFObjectWriter::writeFileHeader() {
696 // Magic.
697 W.write<uint16_t>(0x01df);
698 // Number of sections.
699 W.write<uint16_t>(SectionCount);
700 // Timestamp field. For reproducible output we write a 0, which represents no
701 // timestamp.
702 W.write<int32_t>(0);
703 // Byte Offset to the start of the symbol table.
704 W.write<uint32_t>(SymbolTableOffset);
705 // Number of entries in the symbol table.
706 W.write<int32_t>(SymbolTableEntryCount);
707 // Size of the optional header.
708 W.write<uint16_t>(0);
709 // Flags.
710 W.write<uint16_t>(0);
711}
712
713void XCOFFObjectWriter::writeSectionHeaderTable() {
714 for (const auto *Sec : Sections) {
715 // Nothing to write for this Section.
716 if (Sec->Index == SectionEntry::UninitializedIndex)
717 continue;
718
719 // Write Name.
720 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
721 W.write(NameRef);
722
723 // Write the Physical Address and Virtual Address. In an object file these
724 // are the same.
725 W.write<uint32_t>(Sec->Address);
726 W.write<uint32_t>(Sec->Address);
727
728 W.write<uint32_t>(Sec->Size);
729 W.write<uint32_t>(Sec->FileOffsetToData);
730 W.write<uint32_t>(Sec->FileOffsetToRelocations);
731
732 // Line number pointer. Not supported yet.
733 W.write<uint32_t>(0);
734
735 W.write<uint16_t>(Sec->RelocationCount);
736
737 // Line number counts. Not supported yet.
738 W.write<uint16_t>(0);
739
740 W.write<int32_t>(Sec->Flags);
741 }
742}
743
744void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
745 const XCOFFSection &CSection) {
746 W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
747 W.write<uint32_t>(Reloc.SymbolTableIndex);
748 W.write<uint8_t>(Reloc.SignAndSize);
749 W.write<uint8_t>(Reloc.Type);
750}
751
752void XCOFFObjectWriter::writeRelocations() {
753 for (const auto *Section : Sections) {
754 if (Section->Index == SectionEntry::UninitializedIndex)
755 // Nothing to write for this Section.
756 continue;
757
758 for (const auto *Group : Section->Groups) {
759 if (Group->empty())
760 continue;
761
762 for (const auto &Csect : *Group) {
763 for (const auto Reloc : Csect.Relocations)
764 writeRelocation(Reloc, Csect);
765 }
766 }
767 }
768}
769
770void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
771 // Write symbol 0 as C_FILE.
772 // FIXME: support 64-bit C_FILE symbol.
773 //
774 // n_name. The n_name of a C_FILE symbol is the source filename when no
775 // auxiliary entries are present. The source filename is alternatively
776 // provided by an auxiliary entry, in which case the n_name of the C_FILE
777 // symbol is `.file`.
778 // FIXME: add the real source filename.
779 writeSymbolName(".file");
780 // n_value. The n_value of a C_FILE symbol is its symbol table index.
781 W.write<uint32_t>(0);
782 // n_scnum. N_DEBUG is a reserved section number for indicating a special
783 // symbolic debugging symbol.
784 W.write<int16_t>(XCOFF::ReservedSectionNum::N_DEBUG);
785 // n_type. The n_type field of a C_FILE symbol encodes the source language and
786 // CPU version info; zero indicates no info.
787 W.write<uint16_t>(0);
788 // n_sclass. The C_FILE symbol provides source file-name information,
789 // source-language ID and CPU-version ID information and some other optional
790 // infos.
791 W.write<uint8_t>(XCOFF::C_FILE);
792 // n_numaux. No aux entry for now.
793 W.write<uint8_t>(0);
794
795 for (const auto &Csect : UndefinedCsects) {
796 writeSymbolTableEntryForControlSection(Csect,
797 XCOFF::ReservedSectionNum::N_UNDEF,
798 Csect.MCSec->getStorageClass());
799 }
800
801 for (const auto *Section : Sections) {
802 if (Section->Index == SectionEntry::UninitializedIndex)
803 // Nothing to write for this Section.
804 continue;
805
806 for (const auto *Group : Section->Groups) {
807 if (Group->empty())
808 continue;
809
810 const int16_t SectionIndex = Section->Index;
811 for (const auto &Csect : *Group) {
812 // Write out the control section first and then each symbol in it.
813 writeSymbolTableEntryForControlSection(Csect, SectionIndex,
814 Csect.MCSec->getStorageClass());
815
816 for (const auto &Sym : Csect.Syms)
817 writeSymbolTableEntryForCsectMemberLabel(
818 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
819 }
820 }
821 }
822}
823
824void XCOFFObjectWriter::finalizeSectionInfo() {
825 for (auto *Section : Sections) {
826 if (Section->Index == SectionEntry::UninitializedIndex)
827 // Nothing to record for this Section.
828 continue;
829
830 for (const auto *Group : Section->Groups) {
831 if (Group->empty())
832 continue;
833
834 for (auto &Csect : *Group) {
835 const size_t CsectRelocCount = Csect.Relocations.size();
836 if (CsectRelocCount >= XCOFF::RelocOverflow ||
837 Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
838 report_fatal_error(
839 "relocation entries overflowed; overflow section is "
840 "not implemented yet");
841
842 Section->RelocationCount += CsectRelocCount;
843 }
844 }
845 }
846
847 // Calculate the file offset to the relocation entries.
848 uint64_t RawPointer = RelocationEntryOffset;
849 for (auto Sec : Sections) {
850 if (Sec->Index == SectionEntry::UninitializedIndex || !Sec->RelocationCount)
851 continue;
852
853 Sec->FileOffsetToRelocations = RawPointer;
854 const uint32_t RelocationSizeInSec =
855 Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
856 RawPointer += RelocationSizeInSec;
857 if (RawPointer > UINT32_MAX(4294967295U))
858 report_fatal_error("Relocation data overflowed this object file.");
859 }
860
861 // TODO Error check that the number of symbol table entries fits in 32-bits
862 // signed ...
863 if (SymbolTableEntryCount)
864 SymbolTableOffset = RawPointer;
865}
866
867void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
868 // The first symbol table entry (at index 0) is for the file name.
869 uint32_t SymbolTableIndex = 1;
870
871 // Calculate indices for undefined symbols.
872 for (auto &Csect : UndefinedCsects) {
873 Csect.Size = 0;
874 Csect.Address = 0;
875 Csect.SymbolTableIndex = SymbolTableIndex;
876 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
877 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
878 SymbolTableIndex += 2;
879 }
880
881 // The address corrresponds to the address of sections and symbols in the
882 // object file. We place the shared address 0 immediately after the
883 // section header table.
884 uint32_t Address = 0;
885 // Section indices are 1-based in XCOFF.
886 int32_t SectionIndex = 1;
887 bool HasTDataSection = false;
888
889 for (auto *Section : Sections) {
890 const bool IsEmpty =
891 llvm::all_of(Section->Groups,
892 [](const CsectGroup *Group) { return Group->empty(); });
893 if (IsEmpty)
894 continue;
895
896 if (SectionIndex > MaxSectionIndex)
897 report_fatal_error("Section index overflow!");
898 Section->Index = SectionIndex++;
899 SectionCount++;
900
901 bool SectionAddressSet = false;
902 // Reset the starting address to 0 for TData section.
903 if (Section->Flags == XCOFF::STYP_TDATA) {
904 Address = 0;
905 HasTDataSection = true;
906 }
907 // Reset the starting address to 0 for TBSS section if the object file does
908 // not contain TData Section.
909 if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
910 Address = 0;
911
912 for (auto *Group : Section->Groups) {
913 if (Group->empty())
914 continue;
915
916 for (auto &Csect : *Group) {
917 const MCSectionXCOFF *MCSec = Csect.MCSec;
918 Csect.Address = alignTo(Address, MCSec->getAlignment());
919 Csect.Size = Layout.getSectionAddressSize(MCSec);
920 Address = Csect.Address + Csect.Size;
921 Csect.SymbolTableIndex = SymbolTableIndex;
922 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
923 // 1 main and 1 auxiliary symbol table entry for the csect.
924 SymbolTableIndex += 2;
925
926 for (auto &Sym : Csect.Syms) {
927 Sym.SymbolTableIndex = SymbolTableIndex;
928 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
929 // 1 main and 1 auxiliary symbol table entry for each contained
930 // symbol.
931 SymbolTableIndex += 2;
932 }
933 }
934
935 if (!SectionAddressSet) {
936 Section->Address = Group->front().Address;
937 SectionAddressSet = true;
938 }
939 }
940
941 // Make sure the address of the next section aligned to
942 // DefaultSectionAlign.
943 Address = alignTo(Address, DefaultSectionAlign);
944 Section->Size = Address - Section->Address;
945 }
946
947 SymbolTableEntryCount = SymbolTableIndex;
948
949 // Calculate the RawPointer value for each section.
950 uint64_t RawPointer = XCOFF::FileHeaderSize32 + auxiliaryHeaderSize() +
951 SectionCount * XCOFF::SectionHeaderSize32;
952 for (auto *Sec : Sections) {
953 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
954 continue;
955
956 Sec->FileOffsetToData = RawPointer;
957 RawPointer += Sec->Size;
958 if (RawPointer > UINT32_MAX(4294967295U))
959 report_fatal_error("Section raw data overflowed this object file.");
960 }
961
962 RelocationEntryOffset = RawPointer;
963}
964
965// Takes the log base 2 of the alignment and shifts the result into the 5 most
966// significant bits of a byte, then or's in the csect type into the least
967// significant 3 bits.
968uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
969 unsigned Align = Sec->getAlignment();
970 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.")(static_cast<void> (0));
971 unsigned Log2Align = Log2_32(Align);
972 // Result is a number in the range [0, 31] which fits in the 5 least
973 // significant bits. Shift this value into the 5 most significant bits, and
974 // bitwise-or in the csect type.
975 uint8_t EncodedAlign = Log2Align << 3;
976 return EncodedAlign | Sec->getCSectType();
977}
978
979} // end anonymous namespace
980
981std::unique_ptr<MCObjectWriter>
982llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
983 raw_pwrite_stream &OS) {
984 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
985}