1 //===- InputSection.cpp ---------------------------------------------------===//
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 #include "InputSection.h"
10 #include "InputFiles.h"
11 #include "OutputSegment.h"
12 #include "Symbols.h"
13 #include "Target.h"
14 #include "Writer.h"
15 #include "lld/Common/Memory.h"
16 #include "llvm/Support/Endian.h"
17 
18 using namespace llvm;
19 using namespace llvm::MachO;
20 using namespace llvm::support;
21 using namespace lld;
22 using namespace lld::macho;
23 
24 std::vector<InputSection *> macho::inputSections;
25 
26 uint64_t InputSection::getFileOffset() const {
27   return parent->fileOff + outSecFileOff;
28 }
29 
30 uint64_t InputSection::getFileSize() const {
31   return isZeroFill(flags) ? 0 : getSize();
32 }
33 
34 uint64_t InputSection::getVA() const { return parent->addr + outSecOff; }
35 
36 void InputSection::writeTo(uint8_t *buf) {
37   if (getFileSize() == 0)
38     return;
39 
40   memcpy(buf, data.data(), data.size());
41 
42   for (Reloc &r : relocs) {
43     uint64_t referentVA = 0;
44     if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
45       referentVA =
46           target->resolveSymbolVA(buf + r.offset, *referentSym, r.type);
47 
48       if (isThreadLocalVariables(flags)) {
49         // References from thread-local variable sections are treated as offsets
50         // relative to the start of the thread-local data memory area, which
51         // is initialized via copying all the TLV data sections (which are all
52         // contiguous).
53         if (isa<Defined>(referentSym))
54           referentVA -= firstTLVDataSection->addr;
55       }
56     } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {
57       referentVA = referentIsec->getVA();
58     }
59 
60     uint64_t referentVal = referentVA + r.addend;
61     if (r.pcrel)
62       referentVal -= getVA() + r.offset;
63     target->relocateOne(buf + r.offset, r, referentVal);
64   }
65 }
66 
67 bool macho::isCodeSection(InputSection *isec) {
68   uint32_t type = isec->flags & MachO::SECTION_TYPE;
69   if (type != S_REGULAR && type != S_COALESCED)
70     return false;
71 
72   uint32_t attr = isec->flags & MachO::SECTION_ATTRIBUTES_USR;
73   if (attr == S_ATTR_PURE_INSTRUCTIONS)
74     return true;
75 
76   if (isec->segname == segment_names::text)
77     return StringSwitch<bool>(isec->name)
78         .Cases("__textcoal_nt", "__StaticInit", true)
79         .Default(false);
80 
81   return false;
82 }
83 
84 std::string lld::toString(const InputSection *isec) {
85   return (toString(isec->file) + ":(" + isec->name + ")").str();
86 }
87