1280461Sdim//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//
2280461Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6280461Sdim//
7280461Sdim//===----------------------------------------------------------------------===//
8280461Sdim
9280461Sdim///
10280461Sdim/// \file Converts from in-memory Atoms to in-memory normalized mach-o.
11280461Sdim///
12280461Sdim///                  +------------+
13280461Sdim///                  | normalized |
14280461Sdim///                  +------------+
15280461Sdim///                        ^
16280461Sdim///                        |
17280461Sdim///                        |
18280461Sdim///                    +-------+
19280461Sdim///                    | Atoms |
20280461Sdim///                    +-------+
21280461Sdim
22280461Sdim#include "ArchHandler.h"
23314564Sdim#include "DebugInfo.h"
24321369Sdim#include "MachONormalizedFile.h"
25280461Sdim#include "MachONormalizedFileBinaryUtils.h"
26327952Sdim#include "lld/Common/LLVM.h"
27280461Sdim#include "lld/Core/Error.h"
28280461Sdim#include "llvm/ADT/StringRef.h"
29280461Sdim#include "llvm/ADT/StringSwitch.h"
30321369Sdim#include "llvm/BinaryFormat/MachO.h"
31280461Sdim#include "llvm/Support/Casting.h"
32280461Sdim#include "llvm/Support/Debug.h"
33280461Sdim#include "llvm/Support/ErrorHandling.h"
34280461Sdim#include "llvm/Support/Format.h"
35280461Sdim#include <map>
36280461Sdim#include <system_error>
37314564Sdim#include <unordered_set>
38280461Sdim
39280461Sdimusing llvm::StringRef;
40280461Sdimusing llvm::isa;
41280461Sdimusing namespace llvm::MachO;
42280461Sdimusing namespace lld::mach_o::normalized;
43280461Sdimusing namespace lld;
44280461Sdim
45280461Sdimnamespace {
46280461Sdim
47280461Sdimstruct AtomInfo {
48280461Sdim  const DefinedAtom  *atom;
49280461Sdim  uint64_t            offsetInSection;
50280461Sdim};
51280461Sdim
52280461Sdimstruct SectionInfo {
53280461Sdim  SectionInfo(StringRef seg, StringRef sect, SectionType type,
54293846Sdim              const MachOLinkingContext &ctxt, uint32_t attr,
55293846Sdim              bool relocsToDefinedCanBeImplicit);
56280461Sdim
57280461Sdim  StringRef                 segmentName;
58280461Sdim  StringRef                 sectionName;
59280461Sdim  SectionType               type;
60280461Sdim  uint32_t                  attributes;
61280461Sdim  uint64_t                  address;
62280461Sdim  uint64_t                  size;
63292934Sdim  uint16_t                  alignment;
64293846Sdim
65293846Sdim  /// If this is set, the any relocs in this section which point to defined
66293846Sdim  /// addresses can be implicitly generated.  This is the case for the
67293846Sdim  /// __eh_frame section where references to the function can be implicit if the
68293846Sdim  /// function is defined.
69293846Sdim  bool                      relocsToDefinedCanBeImplicit;
70293846Sdim
71293846Sdim
72280461Sdim  std::vector<AtomInfo>     atomsAndOffsets;
73280461Sdim  uint32_t                  normalizedSectionIndex;
74280461Sdim  uint32_t                  finalSectionIndex;
75280461Sdim};
76280461Sdim
77280461SdimSectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
78293846Sdim                         const MachOLinkingContext &ctxt, uint32_t attrs,
79293846Sdim                         bool relocsToDefinedCanBeImplicit)
80280461Sdim : segmentName(sg), sectionName(sct), type(t), attributes(attrs),
81292934Sdim                 address(0), size(0), alignment(1),
82293846Sdim                 relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit),
83280461Sdim                 normalizedSectionIndex(0), finalSectionIndex(0) {
84292934Sdim  uint16_t align = 1;
85280461Sdim  if (ctxt.sectionAligned(segmentName, sectionName, align)) {
86280461Sdim    alignment = align;
87280461Sdim  }
88280461Sdim}
89280461Sdim
90280461Sdimstruct SegmentInfo {
91280461Sdim  SegmentInfo(StringRef name);
92280461Sdim
93280461Sdim  StringRef                  name;
94280461Sdim  uint64_t                   address;
95280461Sdim  uint64_t                   size;
96303239Sdim  uint32_t                   init_access;
97303239Sdim  uint32_t                   max_access;
98280461Sdim  std::vector<SectionInfo*>  sections;
99280461Sdim  uint32_t                   normalizedSegmentIndex;
100280461Sdim};
101280461Sdim
102280461SdimSegmentInfo::SegmentInfo(StringRef n)
103303239Sdim : name(n), address(0), size(0), init_access(0), max_access(0),
104303239Sdim   normalizedSegmentIndex(0) {
105280461Sdim}
106280461Sdim
107280461Sdimclass Util {
108280461Sdimpublic:
109280461Sdim  Util(const MachOLinkingContext &ctxt)
110292934Sdim      : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr),
111303239Sdim        _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {}
112280461Sdim  ~Util();
113280461Sdim
114303239Sdim  void      processDefinedAtoms(const lld::File &atomFile);
115303239Sdim  void      processAtomAttributes(const DefinedAtom *atom);
116303239Sdim  void      assignAtomToSection(const DefinedAtom *atom);
117280461Sdim  void      organizeSections();
118280461Sdim  void      assignAddressesToSections(const NormalizedFile &file);
119280461Sdim  uint32_t  fileFlags();
120280461Sdim  void      copySegmentInfo(NormalizedFile &file);
121280461Sdim  void      copySectionInfo(NormalizedFile &file);
122280461Sdim  void      updateSectionInfo(NormalizedFile &file);
123280461Sdim  void      buildAtomToAddressMap();
124314564Sdim  llvm::Error synthesizeDebugNotes(NormalizedFile &file);
125303239Sdim  llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
126280461Sdim  void      addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
127280461Sdim  void      addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
128280461Sdim  void      addExportInfo(const lld::File &, NormalizedFile &file);
129280461Sdim  void      addSectionRelocs(const lld::File &, NormalizedFile &file);
130303239Sdim  void      addFunctionStarts(const lld::File &, NormalizedFile &file);
131280461Sdim  void      buildDataInCodeArray(const lld::File &, NormalizedFile &file);
132280461Sdim  void      addDependentDylibs(const lld::File &, NormalizedFile &file);
133280461Sdim  void      copyEntryPointAddress(NormalizedFile &file);
134280461Sdim  void      copySectionContent(NormalizedFile &file);
135280461Sdim
136303239Sdim  bool allSourceFilesHaveMinVersions() const {
137303239Sdim    return _allSourceFilesHaveMinVersions;
138303239Sdim  }
139303239Sdim
140303239Sdim  uint32_t minVersion() const {
141303239Sdim    return _minVersion;
142303239Sdim  }
143303239Sdim
144303239Sdim  LoadCommandType minVersionCommandType() const {
145303239Sdim    return _minVersionCommandType;
146303239Sdim  }
147303239Sdim
148280461Sdimprivate:
149280461Sdim  typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
150280461Sdim  typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
151280461Sdim
152280461Sdim  struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
153280461Sdim  typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
154280461Sdim
155280461Sdim  SectionInfo *sectionForAtom(const DefinedAtom*);
156280461Sdim  SectionInfo *getRelocatableSection(DefinedAtom::ContentType type);
157280461Sdim  SectionInfo *getFinalSection(DefinedAtom::ContentType type);
158280461Sdim  void         appendAtom(SectionInfo *sect, const DefinedAtom *atom);
159280461Sdim  SegmentInfo *segmentForName(StringRef segName);
160280461Sdim  void         layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
161280461Sdim  void         layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
162280461Sdim  void         copySectionContent(SectionInfo *si, ContentBytes &content);
163280461Sdim  uint16_t     descBits(const DefinedAtom* atom);
164280461Sdim  int          dylibOrdinal(const SharedLibraryAtom *sa);
165280461Sdim  void         segIndexForSection(const SectionInfo *sect,
166280461Sdim                             uint8_t &segmentIndex, uint64_t &segmentStartAddr);
167280461Sdim  const Atom  *targetOfLazyPointer(const DefinedAtom *lpAtom);
168280461Sdim  const Atom  *targetOfStub(const DefinedAtom *stubAtom);
169303239Sdim  llvm::Error getSymbolTableRegion(const DefinedAtom* atom,
170303239Sdim                                   bool &inGlobalsRegion,
171303239Sdim                                   SymbolScope &symbolScope);
172280461Sdim  void         appendSection(SectionInfo *si, NormalizedFile &file);
173280461Sdim  uint32_t     sectionIndexForAtom(const Atom *atom);
174326909Sdim  void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
175326909Sdim                           NormalizedFile &file);
176280461Sdim
177280461Sdim  typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
178280461Sdim  struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
179280461Sdim  struct AtomSorter {
180280461Sdim    bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
181280461Sdim  };
182280461Sdim  struct SegmentSorter {
183280461Sdim    bool operator()(const SegmentInfo *left, const SegmentInfo *right);
184280461Sdim    static unsigned weight(const SegmentInfo *);
185280461Sdim  };
186280461Sdim  struct TextSectionSorter {
187280461Sdim    bool operator()(const SectionInfo *left, const SectionInfo *right);
188280461Sdim    static unsigned weight(const SectionInfo *);
189280461Sdim  };
190280461Sdim
191292934Sdim  const MachOLinkingContext &_ctx;
192280461Sdim  mach_o::ArchHandler          &_archHandler;
193280461Sdim  llvm::BumpPtrAllocator        _allocator;
194280461Sdim  std::vector<SectionInfo*>     _sectionInfos;
195280461Sdim  std::vector<SegmentInfo*>     _segmentInfos;
196280461Sdim  TypeToSection                 _sectionMap;
197280461Sdim  std::vector<SectionInfo*>     _customSections;
198280461Sdim  AtomToAddress                 _atomToAddress;
199280461Sdim  DylibPathToInfo               _dylibInfo;
200280461Sdim  const DefinedAtom            *_entryAtom;
201280461Sdim  AtomToIndex                   _atomToSymbolIndex;
202280461Sdim  std::vector<const Atom *>     _machHeaderAliasAtoms;
203292934Sdim  bool                          _hasTLVDescriptors;
204303239Sdim  bool                          _subsectionsViaSymbols;
205303239Sdim  bool                          _allSourceFilesHaveMinVersions = true;
206303239Sdim  LoadCommandType               _minVersionCommandType = (LoadCommandType)0;
207303239Sdim  uint32_t                      _minVersion = 0;
208314564Sdim  std::vector<lld::mach_o::Stab> _stabs;
209280461Sdim};
210280461Sdim
211280461SdimUtil::~Util() {
212280461Sdim  // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs
213280461Sdim  // to be deleted.
214280461Sdim  for (SectionInfo *si : _sectionInfos) {
215280461Sdim    // clear() destroys vector elements, but does not deallocate.
216280461Sdim    // Instead use swap() to deallocate vector buffer.
217280461Sdim    std::vector<AtomInfo> empty;
218280461Sdim    si->atomsAndOffsets.swap(empty);
219280461Sdim  }
220280461Sdim  // The SegmentInfo structs are BumpPtr allocated, but sections needs
221280461Sdim  // to be deleted.
222280461Sdim  for (SegmentInfo *sgi : _segmentInfos) {
223280461Sdim    std::vector<SectionInfo*> empty2;
224280461Sdim    sgi->sections.swap(empty2);
225280461Sdim  }
226280461Sdim}
227280461Sdim
228280461SdimSectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
229280461Sdim  StringRef segmentName;
230280461Sdim  StringRef sectionName;
231280461Sdim  SectionType sectionType;
232280461Sdim  SectionAttr sectionAttrs;
233293846Sdim  bool relocsToDefinedCanBeImplicit;
234280461Sdim
235280461Sdim  // Use same table used by when parsing .o files.
236280461Sdim  relocatableSectionInfoForContentType(type, segmentName, sectionName,
237293846Sdim                                       sectionType, sectionAttrs,
238293846Sdim                                       relocsToDefinedCanBeImplicit);
239280461Sdim  // If we already have a SectionInfo with this name, re-use it.
240280461Sdim  // This can happen if two ContentType map to the same mach-o section.
241280461Sdim  for (auto sect : _sectionMap) {
242280461Sdim    if (sect.second->sectionName.equals(sectionName) &&
243280461Sdim        sect.second->segmentName.equals(segmentName)) {
244280461Sdim      return sect.second;
245280461Sdim    }
246280461Sdim  }
247280461Sdim  // Otherwise allocate new SectionInfo object.
248292934Sdim  auto *sect = new (_allocator)
249293846Sdim      SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs,
250293846Sdim                  relocsToDefinedCanBeImplicit);
251280461Sdim  _sectionInfos.push_back(sect);
252280461Sdim  _sectionMap[type] = sect;
253280461Sdim  return sect;
254280461Sdim}
255280461Sdim
256280461Sdim#define ENTRY(seg, sect, type, atomType) \
257280461Sdim  {seg, sect, type, DefinedAtom::atomType }
258280461Sdim
259280461Sdimstruct MachOFinalSectionFromAtomType {
260280461Sdim  StringRef                 segmentName;
261280461Sdim  StringRef                 sectionName;
262280461Sdim  SectionType               sectionType;
263280461Sdim  DefinedAtom::ContentType  atomType;
264280461Sdim};
265280461Sdim
266280461Sdimconst MachOFinalSectionFromAtomType sectsToAtomType[] = {
267280461Sdim  ENTRY("__TEXT", "__text",           S_REGULAR,          typeCode),
268303239Sdim  ENTRY("__TEXT", "__text",           S_REGULAR,          typeMachHeader),
269280461Sdim  ENTRY("__TEXT", "__cstring",        S_CSTRING_LITERALS, typeCString),
270280461Sdim  ENTRY("__TEXT", "__ustring",        S_REGULAR,          typeUTF16String),
271280461Sdim  ENTRY("__TEXT", "__const",          S_REGULAR,          typeConstant),
272280461Sdim  ENTRY("__TEXT", "__const",          S_4BYTE_LITERALS,   typeLiteral4),
273280461Sdim  ENTRY("__TEXT", "__const",          S_8BYTE_LITERALS,   typeLiteral8),
274280461Sdim  ENTRY("__TEXT", "__const",          S_16BYTE_LITERALS,  typeLiteral16),
275280461Sdim  ENTRY("__TEXT", "__stubs",          S_SYMBOL_STUBS,     typeStub),
276280461Sdim  ENTRY("__TEXT", "__stub_helper",    S_REGULAR,          typeStubHelper),
277280461Sdim  ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),
278280461Sdim  ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),
279280461Sdim  ENTRY("__TEXT", "__unwind_info",    S_REGULAR,          typeProcessedUnwindInfo),
280280461Sdim  ENTRY("__DATA", "__data",           S_REGULAR,          typeData),
281280461Sdim  ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),
282280461Sdim  ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),
283280461Sdim  ENTRY("__DATA", "__la_symbol_ptr",  S_LAZY_SYMBOL_POINTERS,
284280461Sdim                                                          typeLazyPointer),
285280461Sdim  ENTRY("__DATA", "__mod_init_func",  S_MOD_INIT_FUNC_POINTERS,
286280461Sdim                                                          typeInitializerPtr),
287280461Sdim  ENTRY("__DATA", "__mod_term_func",  S_MOD_TERM_FUNC_POINTERS,
288280461Sdim                                                          typeTerminatorPtr),
289280461Sdim  ENTRY("__DATA", "__got",            S_NON_LAZY_SYMBOL_POINTERS,
290280461Sdim                                                          typeGOT),
291303239Sdim  ENTRY("__DATA", "__nl_symbol_ptr",  S_NON_LAZY_SYMBOL_POINTERS,
292303239Sdim                                                          typeNonLazyPointer),
293292934Sdim  ENTRY("__DATA", "__thread_vars",    S_THREAD_LOCAL_VARIABLES,
294292934Sdim                                                          typeThunkTLV),
295292934Sdim  ENTRY("__DATA", "__thread_data",    S_THREAD_LOCAL_REGULAR,
296292934Sdim                                                          typeTLVInitialData),
297292934Sdim  ENTRY("__DATA", "__thread_ptrs",    S_THREAD_LOCAL_VARIABLE_POINTERS,
298292934Sdim                                                          typeTLVInitializerPtr),
299292934Sdim  ENTRY("__DATA", "__thread_bss",     S_THREAD_LOCAL_ZEROFILL,
300292934Sdim                                                         typeTLVInitialZeroFill),
301280461Sdim  ENTRY("__DATA", "__bss",            S_ZEROFILL,         typeZeroFill),
302280461Sdim  ENTRY("__DATA", "__interposing",    S_INTERPOSING,      typeInterposingTuples),
303280461Sdim};
304280461Sdim#undef ENTRY
305280461Sdim
306280461SdimSectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
307280461Sdim  for (auto &p : sectsToAtomType) {
308280461Sdim    if (p.atomType != atomType)
309280461Sdim      continue;
310280461Sdim    SectionAttr sectionAttrs = 0;
311280461Sdim    switch (atomType) {
312303239Sdim    case DefinedAtom::typeMachHeader:
313280461Sdim    case DefinedAtom::typeCode:
314280461Sdim    case DefinedAtom::typeStub:
315280461Sdim    case DefinedAtom::typeStubHelper:
316303239Sdim      sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
317280461Sdim      break;
318292934Sdim    case DefinedAtom::typeThunkTLV:
319292934Sdim      _hasTLVDescriptors = true;
320292934Sdim      break;
321280461Sdim    default:
322280461Sdim      break;
323280461Sdim    }
324280461Sdim    // If we already have a SectionInfo with this name, re-use it.
325280461Sdim    // This can happen if two ContentType map to the same mach-o section.
326280461Sdim    for (auto sect : _sectionMap) {
327280461Sdim      if (sect.second->sectionName.equals(p.sectionName) &&
328280461Sdim          sect.second->segmentName.equals(p.segmentName)) {
329280461Sdim        return sect.second;
330280461Sdim      }
331280461Sdim    }
332280461Sdim    // Otherwise allocate new SectionInfo object.
333292934Sdim    auto *sect = new (_allocator) SectionInfo(
334293846Sdim        p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs,
335293846Sdim        /* relocsToDefinedCanBeImplicit */ false);
336280461Sdim    _sectionInfos.push_back(sect);
337280461Sdim    _sectionMap[atomType] = sect;
338280461Sdim    return sect;
339280461Sdim  }
340280461Sdim  llvm_unreachable("content type not yet supported");
341280461Sdim}
342280461Sdim
343280461SdimSectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
344280461Sdim  if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
345280461Sdim    // Section for this atom is derived from content type.
346280461Sdim    DefinedAtom::ContentType type = atom->contentType();
347280461Sdim    auto pos = _sectionMap.find(type);
348280461Sdim    if ( pos != _sectionMap.end() )
349280461Sdim      return pos->second;
350292934Sdim    bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
351280461Sdim    return rMode ? getRelocatableSection(type) : getFinalSection(type);
352280461Sdim  } else {
353280461Sdim    // This atom needs to be in a custom section.
354280461Sdim    StringRef customName = atom->customSectionName();
355280461Sdim    // Look to see if we have already allocated the needed custom section.
356280461Sdim    for(SectionInfo *sect : _customSections) {
357280461Sdim      const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
358280461Sdim      if (firstAtom->customSectionName().equals(customName)) {
359280461Sdim        return sect;
360280461Sdim      }
361280461Sdim    }
362280461Sdim    // Not found, so need to create a new custom section.
363280461Sdim    size_t seperatorIndex = customName.find('/');
364280461Sdim    assert(seperatorIndex != StringRef::npos);
365280461Sdim    StringRef segName = customName.slice(0, seperatorIndex);
366280461Sdim    StringRef sectName = customName.drop_front(seperatorIndex + 1);
367292934Sdim    auto *sect =
368293846Sdim        new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx,
369293846Sdim                                     0, /* relocsToDefinedCanBeImplicit */ false);
370280461Sdim    _customSections.push_back(sect);
371280461Sdim    _sectionInfos.push_back(sect);
372280461Sdim    return sect;
373280461Sdim  }
374280461Sdim}
375280461Sdim
376280461Sdimvoid Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
377280461Sdim  // Figure out offset for atom in this section given alignment constraints.
378280461Sdim  uint64_t offset = sect->size;
379280461Sdim  DefinedAtom::Alignment atomAlign = atom->alignment();
380292934Sdim  uint64_t align = atomAlign.value;
381280461Sdim  uint64_t requiredModulus = atomAlign.modulus;
382292934Sdim  uint64_t currentModulus = (offset % align);
383280461Sdim  if ( currentModulus != requiredModulus ) {
384280461Sdim    if ( requiredModulus > currentModulus )
385280461Sdim      offset += requiredModulus-currentModulus;
386280461Sdim    else
387292934Sdim      offset += align+requiredModulus-currentModulus;
388280461Sdim  }
389280461Sdim  // Record max alignment of any atom in this section.
390292934Sdim  if (align > sect->alignment)
391292934Sdim    sect->alignment = atomAlign.value;
392280461Sdim  // Assign atom to this section with this offset.
393280461Sdim  AtomInfo ai = {atom, offset};
394280461Sdim  sect->atomsAndOffsets.push_back(ai);
395280461Sdim  // Update section size to include this atom.
396280461Sdim  sect->size = offset + atom->size();
397280461Sdim}
398280461Sdim
399303239Sdimvoid Util::processDefinedAtoms(const lld::File &atomFile) {
400280461Sdim  for (const DefinedAtom *atom : atomFile.defined()) {
401303239Sdim    processAtomAttributes(atom);
402303239Sdim    assignAtomToSection(atom);
403303239Sdim  }
404303239Sdim}
405303239Sdim
406303239Sdimvoid Util::processAtomAttributes(const DefinedAtom *atom) {
407303239Sdim  if (auto *machoFile = dyn_cast<mach_o::MachOFile>(&atom->file())) {
408303239Sdim    // If the file doesn't use subsections via symbols, then make sure we don't
409303239Sdim    // add that flag to the final output file if we have a relocatable file.
410303239Sdim    if (!machoFile->subsectionsViaSymbols())
411303239Sdim      _subsectionsViaSymbols = false;
412303239Sdim
413303239Sdim    // All the source files must have min versions for us to output an object
414303239Sdim    // file with a min version.
415303239Sdim    if (auto v = machoFile->minVersion())
416303239Sdim      _minVersion = std::max(_minVersion, v);
417280461Sdim    else
418303239Sdim      _allSourceFilesHaveMinVersions = false;
419303239Sdim
420303239Sdim    // If we don't have a platform load command, but one of the source files
421303239Sdim    // does, then take the one from the file.
422303239Sdim    if (!_minVersionCommandType)
423303239Sdim      if (auto v = machoFile->minVersionLoadCommandKind())
424303239Sdim        _minVersionCommandType = v;
425280461Sdim  }
426280461Sdim}
427280461Sdim
428303239Sdimvoid Util::assignAtomToSection(const DefinedAtom *atom) {
429303239Sdim  if (atom->contentType() == DefinedAtom::typeMachHeader) {
430303239Sdim    _machHeaderAliasAtoms.push_back(atom);
431303239Sdim    // Assign atom to this section with this offset.
432303239Sdim    AtomInfo ai = {atom, 0};
433303239Sdim    sectionForAtom(atom)->atomsAndOffsets.push_back(ai);
434303239Sdim  } else if (atom->contentType() == DefinedAtom::typeDSOHandle)
435303239Sdim    _machHeaderAliasAtoms.push_back(atom);
436303239Sdim  else
437303239Sdim    appendAtom(sectionForAtom(atom), atom);
438303239Sdim}
439303239Sdim
440280461SdimSegmentInfo *Util::segmentForName(StringRef segName) {
441280461Sdim  for (SegmentInfo *si : _segmentInfos) {
442280461Sdim    if ( si->name.equals(segName) )
443280461Sdim      return si;
444280461Sdim  }
445292934Sdim  auto *info = new (_allocator) SegmentInfo(segName);
446303239Sdim
447303239Sdim  // Set the initial segment protection.
448280461Sdim  if (segName.equals("__TEXT"))
449303239Sdim    info->init_access = VM_PROT_READ | VM_PROT_EXECUTE;
450280461Sdim  else if (segName.equals("__PAGEZERO"))
451303239Sdim    info->init_access = 0;
452303239Sdim  else if (segName.equals("__LINKEDIT"))
453303239Sdim    info->init_access = VM_PROT_READ;
454303239Sdim  else {
455303239Sdim    // All others default to read-write
456303239Sdim    info->init_access = VM_PROT_READ | VM_PROT_WRITE;
457303239Sdim  }
458303239Sdim
459303239Sdim  // Set max segment protection
460303239Sdim  // Note, its overkill to use a switch statement here, but makes it so much
461303239Sdim  // easier to use switch coverage to catch new cases.
462303239Sdim  switch (_ctx.os()) {
463303239Sdim    case lld::MachOLinkingContext::OS::unknown:
464303239Sdim    case lld::MachOLinkingContext::OS::macOSX:
465303239Sdim    case lld::MachOLinkingContext::OS::iOS_simulator:
466303239Sdim      if (segName.equals("__PAGEZERO")) {
467303239Sdim        info->max_access = 0;
468303239Sdim        break;
469303239Sdim      }
470303239Sdim      // All others default to all
471303239Sdim      info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
472303239Sdim      break;
473303239Sdim    case lld::MachOLinkingContext::OS::iOS:
474303239Sdim      // iPhoneOS always uses same protection for max and initial
475303239Sdim      info->max_access = info->init_access;
476303239Sdim      break;
477303239Sdim  }
478280461Sdim  _segmentInfos.push_back(info);
479280461Sdim  return info;
480280461Sdim}
481280461Sdim
482280461Sdimunsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
483280461Sdim return llvm::StringSwitch<unsigned>(seg->name)
484280461Sdim    .Case("__PAGEZERO",  1)
485280461Sdim    .Case("__TEXT",      2)
486280461Sdim    .Case("__DATA",      3)
487280461Sdim    .Default(100);
488280461Sdim}
489280461Sdim
490280461Sdimbool Util::SegmentSorter::operator()(const SegmentInfo *left,
491280461Sdim                                  const SegmentInfo *right) {
492280461Sdim  return (weight(left) < weight(right));
493280461Sdim}
494280461Sdim
495280461Sdimunsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
496280461Sdim return llvm::StringSwitch<unsigned>(sect->sectionName)
497280461Sdim    .Case("__text",         1)
498280461Sdim    .Case("__stubs",        2)
499280461Sdim    .Case("__stub_helper",  3)
500280461Sdim    .Case("__const",        4)
501280461Sdim    .Case("__cstring",      5)
502280461Sdim    .Case("__unwind_info",  98)
503280461Sdim    .Case("__eh_frame",     99)
504280461Sdim    .Default(10);
505280461Sdim}
506280461Sdim
507280461Sdimbool Util::TextSectionSorter::operator()(const SectionInfo *left,
508280461Sdim                                         const SectionInfo *right) {
509280461Sdim  return (weight(left) < weight(right));
510280461Sdim}
511280461Sdim
512280461Sdimvoid Util::organizeSections() {
513293258Sdim  // NOTE!: Keep this in sync with assignAddressesToSections.
514293258Sdim  switch (_ctx.outputMachOType()) {
515280461Sdim    case llvm::MachO::MH_EXECUTE:
516280461Sdim      // Main executables, need a zero-page segment
517280461Sdim      segmentForName("__PAGEZERO");
518280461Sdim      // Fall into next case.
519321369Sdim      LLVM_FALLTHROUGH;
520280461Sdim    case llvm::MachO::MH_DYLIB:
521280461Sdim    case llvm::MachO::MH_BUNDLE:
522280461Sdim      // All dynamic code needs TEXT segment to hold the load commands.
523280461Sdim      segmentForName("__TEXT");
524280461Sdim      break;
525280461Sdim    default:
526280461Sdim      break;
527293258Sdim  }
528303239Sdim  segmentForName("__LINKEDIT");
529303239Sdim
530293258Sdim  // Group sections into segments.
531293258Sdim  for (SectionInfo *si : _sectionInfos) {
532293258Sdim    SegmentInfo *seg = segmentForName(si->segmentName);
533293258Sdim    seg->sections.push_back(si);
534293258Sdim  }
535293258Sdim  // Sort segments.
536293258Sdim  std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
537280461Sdim
538293258Sdim  // Sort sections within segments.
539293258Sdim  for (SegmentInfo *seg : _segmentInfos) {
540293258Sdim    if (seg->name.equals("__TEXT")) {
541293258Sdim      std::sort(seg->sections.begin(), seg->sections.end(),
542293258Sdim                TextSectionSorter());
543280461Sdim    }
544293258Sdim  }
545280461Sdim
546293258Sdim  // Record final section indexes.
547293258Sdim  uint32_t segmentIndex = 0;
548293258Sdim  uint32_t sectionIndex = 1;
549293258Sdim  for (SegmentInfo *seg : _segmentInfos) {
550293258Sdim    seg->normalizedSegmentIndex = segmentIndex++;
551293258Sdim    for (SectionInfo *sect : seg->sections)
552293258Sdim      sect->finalSectionIndex = sectionIndex++;
553280461Sdim  }
554280461Sdim}
555280461Sdim
556280461Sdimvoid Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
557280461Sdim  seg->address = addr;
558280461Sdim  for (SectionInfo *sect : seg->sections) {
559303239Sdim    sect->address = llvm::alignTo(addr, sect->alignment);
560280461Sdim    addr = sect->address + sect->size;
561280461Sdim  }
562303239Sdim  seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
563280461Sdim}
564280461Sdim
565280461Sdim// __TEXT segment lays out backwards so padding is at front after load commands.
566280461Sdimvoid Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
567280461Sdim                                                               uint64_t &addr) {
568280461Sdim  seg->address = addr;
569280461Sdim  // Walks sections starting at end to calculate padding for start.
570280461Sdim  int64_t taddr = 0;
571280461Sdim  for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
572280461Sdim    SectionInfo *sect = *it;
573280461Sdim    taddr -= sect->size;
574292934Sdim    taddr = taddr & (0 - sect->alignment);
575280461Sdim  }
576280461Sdim  int64_t padding = taddr - hlcSize;
577280461Sdim  while (padding < 0)
578292934Sdim    padding += _ctx.pageSize();
579280461Sdim  // Start assigning section address starting at padded offset.
580280461Sdim  addr += (padding + hlcSize);
581280461Sdim  for (SectionInfo *sect : seg->sections) {
582303239Sdim    sect->address = llvm::alignTo(addr, sect->alignment);
583280461Sdim    addr = sect->address + sect->size;
584280461Sdim  }
585303239Sdim  seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
586280461Sdim}
587280461Sdim
588280461Sdimvoid Util::assignAddressesToSections(const NormalizedFile &file) {
589293258Sdim  // NOTE!: Keep this in sync with organizeSections.
590353358Sdim  size_t hlcSize = headerAndLoadCommandsSize(file,
591353358Sdim                                      _ctx.generateFunctionStartsLoadCommand());
592280461Sdim  uint64_t address = 0;
593293258Sdim  for (SegmentInfo *seg : _segmentInfos) {
594293258Sdim    if (seg->name.equals("__PAGEZERO")) {
595293258Sdim      seg->size = _ctx.pageZeroSize();
596293258Sdim      address += seg->size;
597293258Sdim    }
598293258Sdim    else if (seg->name.equals("__TEXT")) {
599293258Sdim      // _ctx.baseAddress()  == 0 implies it was either unspecified or
600293258Sdim      // pageZeroSize is also 0. In either case resetting address is safe.
601293258Sdim      address = _ctx.baseAddress() ? _ctx.baseAddress() : address;
602293258Sdim      layoutSectionsInTextSegment(hlcSize, seg, address);
603293258Sdim    } else
604293258Sdim      layoutSectionsInSegment(seg, address);
605280461Sdim
606303239Sdim    address = llvm::alignTo(address, _ctx.pageSize());
607293258Sdim  }
608293258Sdim  DEBUG_WITH_TYPE("WriterMachO-norm",
609293258Sdim    llvm::dbgs() << "assignAddressesToSections()\n";
610293258Sdim    for (SegmentInfo *sgi : _segmentInfos) {
611293258Sdim      llvm::dbgs()  << "   address=" << llvm::format("0x%08llX", sgi->address)
612293258Sdim                    << ", size="  << llvm::format("0x%08llX", sgi->size)
613293258Sdim                    << ", segment-name='" << sgi->name
614293258Sdim                    << "'\n";
615293258Sdim      for (SectionInfo *si : sgi->sections) {
616293258Sdim        llvm::dbgs()<< "      addr="  << llvm::format("0x%08llX", si->address)
617293258Sdim                    << ", size="  << llvm::format("0x%08llX", si->size)
618293258Sdim                    << ", section-name='" << si->sectionName
619293258Sdim                    << "\n";
620280461Sdim      }
621280461Sdim    }
622293258Sdim  );
623280461Sdim}
624280461Sdim
625280461Sdimvoid Util::copySegmentInfo(NormalizedFile &file) {
626280461Sdim  for (SegmentInfo *sgi : _segmentInfos) {
627280461Sdim    Segment seg;
628280461Sdim    seg.name    = sgi->name;
629280461Sdim    seg.address = sgi->address;
630280461Sdim    seg.size    = sgi->size;
631303239Sdim    seg.init_access  = sgi->init_access;
632303239Sdim    seg.max_access  = sgi->max_access;
633280461Sdim    file.segments.push_back(seg);
634280461Sdim  }
635280461Sdim}
636280461Sdim
637280461Sdimvoid Util::appendSection(SectionInfo *si, NormalizedFile &file) {
638280461Sdim   // Add new empty section to end of file.sections.
639280461Sdim  Section temp;
640280461Sdim  file.sections.push_back(std::move(temp));
641280461Sdim  Section* normSect = &file.sections.back();
642280461Sdim  // Copy fields to normalized section.
643280461Sdim  normSect->segmentName   = si->segmentName;
644280461Sdim  normSect->sectionName   = si->sectionName;
645280461Sdim  normSect->type          = si->type;
646280461Sdim  normSect->attributes    = si->attributes;
647280461Sdim  normSect->address       = si->address;
648280461Sdim  normSect->alignment     = si->alignment;
649280461Sdim  // Record where normalized section is.
650280461Sdim  si->normalizedSectionIndex = file.sections.size()-1;
651280461Sdim}
652280461Sdim
653280461Sdimvoid Util::copySectionContent(NormalizedFile &file) {
654292934Sdim  const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
655280461Sdim
656280461Sdim  // Utility function for ArchHandler to find address of atom in output file.
657280461Sdim  auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
658280461Sdim    auto pos = _atomToAddress.find(&atom);
659280461Sdim    assert(pos != _atomToAddress.end());
660280461Sdim    return pos->second;
661280461Sdim  };
662280461Sdim
663280461Sdim  auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t {
664280461Sdim    for (const SectionInfo *sectInfo : _sectionInfos)
665280461Sdim      for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets)
666280461Sdim        if (atomInfo.atom == &atom)
667280461Sdim          return sectInfo->address;
668280461Sdim    llvm_unreachable("atom not assigned to section");
669280461Sdim  };
670280461Sdim
671280461Sdim  for (SectionInfo *si : _sectionInfos) {
672280461Sdim    Section *normSect = &file.sections[si->normalizedSectionIndex];
673292934Sdim    if (isZeroFillSection(si->type)) {
674280461Sdim      const uint8_t *empty = nullptr;
675280461Sdim      normSect->content = llvm::makeArrayRef(empty, si->size);
676280461Sdim      continue;
677280461Sdim    }
678280461Sdim    // Copy content from atoms to content buffer for section.
679303239Sdim    llvm::MutableArrayRef<uint8_t> sectionContent;
680303239Sdim    if (si->size) {
681303239Sdim      uint8_t *sectContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
682303239Sdim      sectionContent = llvm::MutableArrayRef<uint8_t>(sectContent, si->size);
683303239Sdim      normSect->content = sectionContent;
684303239Sdim    }
685280461Sdim    for (AtomInfo &ai : si->atomsAndOffsets) {
686303239Sdim      if (!ai.atom->size()) {
687303239Sdim        assert(ai.atom->begin() == ai.atom->end() &&
688303239Sdim               "Cannot have references without content");
689303239Sdim        continue;
690303239Sdim      }
691303239Sdim      auto atomContent = sectionContent.slice(ai.offsetInSection,
692303239Sdim                                              ai.atom->size());
693280461Sdim      _archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
694292934Sdim                                       sectionAddrForAtom, _ctx.baseAddress(),
695292934Sdim                                       atomContent);
696280461Sdim    }
697280461Sdim  }
698280461Sdim}
699280461Sdim
700280461Sdimvoid Util::copySectionInfo(NormalizedFile &file) {
701280461Sdim  file.sections.reserve(_sectionInfos.size());
702293258Sdim  // Write sections grouped by segment.
703293258Sdim  for (SegmentInfo *sgi : _segmentInfos) {
704293258Sdim    for (SectionInfo *si : sgi->sections) {
705280461Sdim      appendSection(si, file);
706280461Sdim    }
707280461Sdim  }
708280461Sdim}
709280461Sdim
710280461Sdimvoid Util::updateSectionInfo(NormalizedFile &file) {
711280461Sdim  file.sections.reserve(_sectionInfos.size());
712293258Sdim  // sections grouped by segment.
713293258Sdim  for (SegmentInfo *sgi : _segmentInfos) {
714293258Sdim    Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
715293258Sdim    normSeg->address = sgi->address;
716293258Sdim    normSeg->size = sgi->size;
717293258Sdim    for (SectionInfo *si : sgi->sections) {
718280461Sdim      Section *normSect = &file.sections[si->normalizedSectionIndex];
719280461Sdim      normSect->address = si->address;
720280461Sdim    }
721280461Sdim  }
722280461Sdim}
723280461Sdim
724280461Sdimvoid Util::copyEntryPointAddress(NormalizedFile &nFile) {
725303239Sdim  if (!_entryAtom) {
726303239Sdim    nFile.entryAddress = 0;
727303239Sdim    return;
728303239Sdim  }
729303239Sdim
730292934Sdim  if (_ctx.outputTypeHasEntry()) {
731280461Sdim    if (_archHandler.isThumbFunction(*_entryAtom))
732280461Sdim      nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
733280461Sdim    else
734280461Sdim      nFile.entryAddress = _atomToAddress[_entryAtom];
735280461Sdim  }
736280461Sdim}
737280461Sdim
738280461Sdimvoid Util::buildAtomToAddressMap() {
739280461Sdim  DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
740280461Sdim                   << "assign atom addresses:\n");
741292934Sdim  const bool lookForEntry = _ctx.outputTypeHasEntry();
742280461Sdim  for (SectionInfo *sect : _sectionInfos) {
743280461Sdim    for (const AtomInfo &info : sect->atomsAndOffsets) {
744280461Sdim      _atomToAddress[info.atom] = sect->address + info.offsetInSection;
745280461Sdim      if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
746280461Sdim          (info.atom->size() != 0) &&
747292934Sdim          info.atom->name() == _ctx.entrySymbolName()) {
748280461Sdim        _entryAtom = info.atom;
749280461Sdim      }
750280461Sdim      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
751293258Sdim                      << "   address="
752293258Sdim                      << llvm::format("0x%016X", _atomToAddress[info.atom])
753293258Sdim                      << llvm::format("    0x%09lX", info.atom)
754293258Sdim                      << ", file=#"
755293258Sdim                      << info.atom->file().ordinal()
756293258Sdim                      << ", atom=#"
757293258Sdim                      << info.atom->ordinal()
758293258Sdim                      << ", name="
759293258Sdim                      << info.atom->name()
760293258Sdim                      << ", type="
761293258Sdim                      << info.atom->contentType()
762293258Sdim                      << "\n");
763280461Sdim    }
764280461Sdim  }
765293258Sdim  DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
766293258Sdim                  << "assign header alias atom addresses:\n");
767280461Sdim  for (const Atom *atom : _machHeaderAliasAtoms) {
768292934Sdim    _atomToAddress[atom] = _ctx.baseAddress();
769293258Sdim#ifndef NDEBUG
770293258Sdim    if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
771293258Sdim      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
772293258Sdim                      << "   address="
773293258Sdim                      << llvm::format("0x%016X", _atomToAddress[atom])
774293258Sdim                      << llvm::format("    0x%09lX", atom)
775293258Sdim                      << ", file=#"
776293258Sdim                      << definedAtom->file().ordinal()
777293258Sdim                      << ", atom=#"
778293258Sdim                      << definedAtom->ordinal()
779293258Sdim                      << ", name="
780293258Sdim                      << definedAtom->name()
781293258Sdim                      << ", type="
782293258Sdim                      << definedAtom->contentType()
783293258Sdim                      << "\n");
784293258Sdim    } else {
785293258Sdim      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
786293258Sdim                      << "   address="
787293258Sdim                      << llvm::format("0x%016X", _atomToAddress[atom])
788293258Sdim                      << " atom=" << atom
789293258Sdim                      << " name=" << atom->name() << "\n");
790293258Sdim    }
791293258Sdim#endif
792280461Sdim  }
793280461Sdim}
794280461Sdim
795314564Sdimllvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) {
796314564Sdim
797314564Sdim  // Bail out early if we don't need to generate a debug map.
798314564Sdim  if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap)
799314564Sdim    return llvm::Error::success();
800314564Sdim
801314564Sdim  std::vector<const DefinedAtom*> atomsNeedingDebugNotes;
802314564Sdim  std::set<const mach_o::MachOFile*> filesWithStabs;
803314564Sdim  bool objFileHasDwarf = false;
804314564Sdim  const File *objFile = nullptr;
805314564Sdim
806314564Sdim  for (SectionInfo *sect : _sectionInfos) {
807314564Sdim    for (const AtomInfo &info : sect->atomsAndOffsets) {
808314564Sdim      if (const DefinedAtom *atom = dyn_cast<DefinedAtom>(info.atom)) {
809314564Sdim
810314564Sdim        // FIXME: No stabs/debug-notes for symbols that wouldn't be in the
811314564Sdim        //        symbol table.
812314564Sdim        // FIXME: No stabs/debug-notes for kernel dtrace probes.
813314564Sdim
814314564Sdim        if (atom->contentType() == DefinedAtom::typeCFI ||
815314564Sdim            atom->contentType() == DefinedAtom::typeCString)
816314564Sdim          continue;
817314564Sdim
818314564Sdim        // Whenever we encounter a new file, update the 'objfileHasDwarf' flag.
819314564Sdim        if (&info.atom->file() != objFile) {
820314564Sdim          objFileHasDwarf = false;
821314564Sdim          if (const mach_o::MachOFile *atomFile =
822314564Sdim              dyn_cast<mach_o::MachOFile>(&info.atom->file())) {
823314564Sdim            if (atomFile->debugInfo()) {
824314564Sdim              if (isa<mach_o::DwarfDebugInfo>(atomFile->debugInfo()))
825314564Sdim                objFileHasDwarf = true;
826314564Sdim              else if (isa<mach_o::StabsDebugInfo>(atomFile->debugInfo()))
827314564Sdim                filesWithStabs.insert(atomFile);
828314564Sdim            }
829314564Sdim          }
830314564Sdim        }
831314564Sdim
832314564Sdim        // If this atom is from a file that needs dwarf, add it to the list.
833314564Sdim        if (objFileHasDwarf)
834314564Sdim          atomsNeedingDebugNotes.push_back(info.atom);
835314564Sdim      }
836314564Sdim    }
837314564Sdim  }
838314564Sdim
839314564Sdim  // Sort atoms needing debug notes by file ordinal, then atom ordinal.
840314564Sdim  std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(),
841314564Sdim            [](const DefinedAtom *lhs, const DefinedAtom *rhs) {
842314564Sdim              if (lhs->file().ordinal() != rhs->file().ordinal())
843314564Sdim                return (lhs->file().ordinal() < rhs->file().ordinal());
844314564Sdim              return (lhs->ordinal() < rhs->ordinal());
845314564Sdim            });
846314564Sdim
847314564Sdim  // FIXME: Handle <rdar://problem/17689030>: Add -add_ast_path option to \
848314564Sdim  //        linker which add N_AST stab entry to output
849314564Sdim  // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64.
850314564Sdim
851314564Sdim  StringRef oldFileName = "";
852314564Sdim  StringRef oldDirPath = "";
853314564Sdim  bool wroteStartSO = false;
854314564Sdim  std::unordered_set<std::string> seenFiles;
855314564Sdim  for (const DefinedAtom *atom : atomsNeedingDebugNotes) {
856314564Sdim    const auto &atomFile = cast<mach_o::MachOFile>(atom->file());
857314564Sdim    assert(dyn_cast_or_null<lld::mach_o::DwarfDebugInfo>(atomFile.debugInfo())
858314564Sdim           && "file for atom needing debug notes does not contain dwarf");
859314564Sdim    auto &dwarf = cast<lld::mach_o::DwarfDebugInfo>(*atomFile.debugInfo());
860314564Sdim
861314564Sdim    auto &tu = dwarf.translationUnitSource();
862314564Sdim    StringRef newFileName = tu.name;
863314564Sdim    StringRef newDirPath = tu.path;
864314564Sdim
865314564Sdim    // Add an SO whenever the TU source file changes.
866314564Sdim    if (newFileName != oldFileName || newDirPath != oldDirPath) {
867314564Sdim      // Translation unit change, emit ending SO
868314564Sdim      if (oldFileName != "")
869314564Sdim        _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
870314564Sdim
871314564Sdim      oldFileName = newFileName;
872314564Sdim      oldDirPath = newDirPath;
873314564Sdim
874314564Sdim      // If newDirPath doesn't end with a '/' we need to add one:
875314564Sdim      if (newDirPath.back() != '/') {
876314564Sdim        char *p =
877314564Sdim          file.ownedAllocations.Allocate<char>(newDirPath.size() + 2);
878314564Sdim        memcpy(p, newDirPath.data(), newDirPath.size());
879314564Sdim        p[newDirPath.size()] = '/';
880314564Sdim        p[newDirPath.size() + 1] = '\0';
881314564Sdim        newDirPath = p;
882314564Sdim      }
883314564Sdim
884314564Sdim      // New translation unit, emit start SOs:
885314564Sdim      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath));
886314564Sdim      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName));
887314564Sdim
888314564Sdim      // Synthesize OSO for start of file.
889314564Sdim      char *fullPath = nullptr;
890314564Sdim      {
891314564Sdim        SmallString<1024> pathBuf(atomFile.path());
892314564Sdim        if (auto EC = llvm::sys::fs::make_absolute(pathBuf))
893314564Sdim          return llvm::errorCodeToError(EC);
894314564Sdim        fullPath = file.ownedAllocations.Allocate<char>(pathBuf.size() + 1);
895314564Sdim        memcpy(fullPath, pathBuf.c_str(), pathBuf.size() + 1);
896314564Sdim      }
897314564Sdim
898314564Sdim      // Get mod time.
899314564Sdim      uint32_t modTime = 0;
900314564Sdim      llvm::sys::fs::file_status stat;
901314564Sdim      if (!llvm::sys::fs::status(fullPath, stat))
902314564Sdim        if (llvm::sys::fs::exists(stat))
903314564Sdim          modTime = llvm::sys::toTimeT(stat.getLastModificationTime());
904314564Sdim
905314564Sdim      _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1,
906314564Sdim                                    modTime, fullPath));
907314564Sdim      // <rdar://problem/6337329> linker should put cpusubtype in n_sect field
908314564Sdim      // of nlist entry for N_OSO debug note entries.
909314564Sdim      wroteStartSO = true;
910314564Sdim    }
911314564Sdim
912314564Sdim    if (atom->contentType() == DefinedAtom::typeCode) {
913314564Sdim      // Synthesize BNSYM and start FUN stabs.
914314564Sdim      _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, ""));
915314564Sdim      _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name()));
916314564Sdim      // Synthesize any SOL stabs needed
917314564Sdim      // FIXME: add SOL stabs.
918314564Sdim      _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0,
919314564Sdim                                    atom->rawContent().size(), ""));
920314564Sdim      _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0,
921314564Sdim                                    atom->rawContent().size(), ""));
922314564Sdim    } else {
923314564Sdim      if (atom->scope() == Atom::scopeTranslationUnit)
924314564Sdim        _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name()));
925314564Sdim      else
926314564Sdim        _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name()));
927314564Sdim    }
928314564Sdim  }
929314564Sdim
930314564Sdim  // Emit ending SO if necessary.
931314564Sdim  if (wroteStartSO)
932314564Sdim    _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
933314564Sdim
934314564Sdim  // Copy any stabs from .o file.
935314564Sdim  for (const auto *objFile : filesWithStabs) {
936314564Sdim    const auto &stabsList =
937314564Sdim      cast<mach_o::StabsDebugInfo>(objFile->debugInfo())->stabs();
938314564Sdim    for (auto &stab : stabsList) {
939314564Sdim      // FIXME: Drop stabs whose atoms have been dead-stripped.
940314564Sdim      _stabs.push_back(stab);
941314564Sdim    }
942314564Sdim  }
943314564Sdim
944314564Sdim  return llvm::Error::success();
945314564Sdim}
946314564Sdim
947280461Sdimuint16_t Util::descBits(const DefinedAtom* atom) {
948280461Sdim  uint16_t desc = 0;
949280461Sdim  switch (atom->merge()) {
950280461Sdim  case lld::DefinedAtom::mergeNo:
951280461Sdim  case lld::DefinedAtom::mergeAsTentative:
952280461Sdim    break;
953280461Sdim  case lld::DefinedAtom::mergeAsWeak:
954280461Sdim  case lld::DefinedAtom::mergeAsWeakAndAddressUsed:
955280461Sdim    desc |= N_WEAK_DEF;
956280461Sdim    break;
957280461Sdim  case lld::DefinedAtom::mergeSameNameAndSize:
958280461Sdim  case lld::DefinedAtom::mergeByLargestSection:
959280461Sdim  case lld::DefinedAtom::mergeByContent:
960280461Sdim    llvm_unreachable("Unsupported DefinedAtom::merge()");
961280461Sdim    break;
962280461Sdim  }
963280461Sdim  if (atom->contentType() == lld::DefinedAtom::typeResolver)
964280461Sdim    desc |= N_SYMBOL_RESOLVER;
965303239Sdim  if (atom->contentType() == lld::DefinedAtom::typeMachHeader)
966303239Sdim    desc |= REFERENCED_DYNAMICALLY;
967280461Sdim  if (_archHandler.isThumbFunction(*atom))
968280461Sdim    desc |= N_ARM_THUMB_DEF;
969314564Sdim  if (atom->deadStrip() == DefinedAtom::deadStripNever &&
970314564Sdim      _ctx.outputMachOType() == llvm::MachO::MH_OBJECT) {
971280461Sdim    if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
972280461Sdim     && (atom->contentType() != DefinedAtom::typeTerminatorPtr))
973280461Sdim    desc |= N_NO_DEAD_STRIP;
974280461Sdim  }
975280461Sdim  return desc;
976280461Sdim}
977280461Sdim
978280461Sdimbool Util::AtomSorter::operator()(const AtomAndIndex &left,
979280461Sdim                                  const AtomAndIndex &right) {
980280461Sdim  return (left.atom->name().compare(right.atom->name()) < 0);
981280461Sdim}
982280461Sdim
983303239Sdimllvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
984303239Sdim                                       bool &inGlobalsRegion,
985303239Sdim                                       SymbolScope &scope) {
986292934Sdim  bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
987280461Sdim  switch (atom->scope()) {
988280461Sdim  case Atom::scopeTranslationUnit:
989280461Sdim    scope = 0;
990280461Sdim    inGlobalsRegion = false;
991314564Sdim    return llvm::Error::success();
992280461Sdim  case Atom::scopeLinkageUnit:
993292934Sdim    if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) &&
994292934Sdim        _ctx.exportSymbolNamed(atom->name())) {
995303239Sdim      return llvm::make_error<GenericError>(
996303239Sdim                          Twine("cannot export hidden symbol ") + atom->name());
997280461Sdim    }
998280461Sdim    if (rMode) {
999292934Sdim      if (_ctx.keepPrivateExterns()) {
1000280461Sdim        // -keep_private_externs means keep in globals region as N_PEXT.
1001280461Sdim        scope = N_PEXT | N_EXT;
1002280461Sdim        inGlobalsRegion = true;
1003314564Sdim        return llvm::Error::success();
1004280461Sdim      }
1005280461Sdim    }
1006280461Sdim    // scopeLinkageUnit symbols are no longer global once linked.
1007280461Sdim    scope = N_PEXT;
1008280461Sdim    inGlobalsRegion = false;
1009314564Sdim    return llvm::Error::success();
1010280461Sdim  case Atom::scopeGlobal:
1011292934Sdim    if (_ctx.exportRestrictMode()) {
1012292934Sdim      if (_ctx.exportSymbolNamed(atom->name())) {
1013280461Sdim        scope = N_EXT;
1014280461Sdim        inGlobalsRegion = true;
1015314564Sdim        return llvm::Error::success();
1016280461Sdim      } else {
1017280461Sdim        scope = N_PEXT;
1018280461Sdim        inGlobalsRegion = false;
1019314564Sdim        return llvm::Error::success();
1020280461Sdim      }
1021280461Sdim    } else {
1022280461Sdim      scope = N_EXT;
1023280461Sdim      inGlobalsRegion = true;
1024314564Sdim      return llvm::Error::success();
1025280461Sdim    }
1026280461Sdim    break;
1027280461Sdim  }
1028280461Sdim  llvm_unreachable("atom->scope() unknown enum value");
1029280461Sdim}
1030280461Sdim
1031314564Sdim
1032314564Sdim
1033303239Sdimllvm::Error Util::addSymbols(const lld::File &atomFile,
1034303239Sdim                             NormalizedFile &file) {
1035292934Sdim  bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
1036314564Sdim  // Mach-O symbol table has four regions: stabs, locals, globals, undefs.
1037280461Sdim
1038314564Sdim  // Add all stabs.
1039314564Sdim  for (auto &stab : _stabs) {
1040314564Sdim    Symbol sym;
1041314564Sdim    sym.type = static_cast<NListType>(stab.type);
1042314564Sdim    sym.scope = 0;
1043314564Sdim    sym.sect = stab.other;
1044314564Sdim    sym.desc = stab.desc;
1045314564Sdim    if (stab.atom)
1046314564Sdim      sym.value = _atomToAddress[stab.atom];
1047314564Sdim    else
1048314564Sdim      sym.value = stab.value;
1049314564Sdim    sym.name = stab.str;
1050314564Sdim    file.stabsSymbols.push_back(sym);
1051314564Sdim  }
1052314564Sdim
1053280461Sdim  // Add all local (non-global) symbols in address order
1054280461Sdim  std::vector<AtomAndIndex> globals;
1055280461Sdim  globals.reserve(512);
1056280461Sdim  for (SectionInfo *sect : _sectionInfos) {
1057280461Sdim    for (const AtomInfo &info : sect->atomsAndOffsets) {
1058280461Sdim      const DefinedAtom *atom = info.atom;
1059280461Sdim      if (!atom->name().empty()) {
1060280461Sdim        SymbolScope symbolScope;
1061280461Sdim        bool inGlobalsRegion;
1062280461Sdim        if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
1063280461Sdim          return ec;
1064280461Sdim        }
1065280461Sdim        if (inGlobalsRegion) {
1066280461Sdim          AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
1067280461Sdim          globals.push_back(ai);
1068280461Sdim        } else {
1069280461Sdim          Symbol sym;
1070280461Sdim          sym.name  = atom->name();
1071280461Sdim          sym.type  = N_SECT;
1072280461Sdim          sym.scope = symbolScope;
1073280461Sdim          sym.sect  = sect->finalSectionIndex;
1074280461Sdim          sym.desc  = descBits(atom);
1075280461Sdim          sym.value = _atomToAddress[atom];
1076280461Sdim          _atomToSymbolIndex[atom] = file.localSymbols.size();
1077280461Sdim          file.localSymbols.push_back(sym);
1078280461Sdim        }
1079280461Sdim      } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
1080280461Sdim        // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
1081280461Sdim        static unsigned tempNum = 1;
1082280461Sdim        char tmpName[16];
1083280461Sdim        sprintf(tmpName, "L%04u", tempNum++);
1084280461Sdim        StringRef tempRef(tmpName);
1085280461Sdim        Symbol sym;
1086280461Sdim        sym.name  = tempRef.copy(file.ownedAllocations);
1087280461Sdim        sym.type  = N_SECT;
1088280461Sdim        sym.scope = 0;
1089280461Sdim        sym.sect  = sect->finalSectionIndex;
1090280461Sdim        sym.desc  = 0;
1091280461Sdim        sym.value = _atomToAddress[atom];
1092280461Sdim        _atomToSymbolIndex[atom] = file.localSymbols.size();
1093280461Sdim        file.localSymbols.push_back(sym);
1094280461Sdim      }
1095280461Sdim    }
1096280461Sdim  }
1097280461Sdim
1098280461Sdim  // Sort global symbol alphabetically, then add to symbol table.
1099280461Sdim  std::sort(globals.begin(), globals.end(), AtomSorter());
1100280461Sdim  const uint32_t globalStartIndex = file.localSymbols.size();
1101280461Sdim  for (AtomAndIndex &ai : globals) {
1102280461Sdim    Symbol sym;
1103280461Sdim    sym.name  = ai.atom->name();
1104280461Sdim    sym.type  = N_SECT;
1105280461Sdim    sym.scope = ai.scope;
1106280461Sdim    sym.sect  = ai.index;
1107280461Sdim    sym.desc  = descBits(static_cast<const DefinedAtom*>(ai.atom));
1108280461Sdim    sym.value = _atomToAddress[ai.atom];
1109280461Sdim    _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
1110280461Sdim    file.globalSymbols.push_back(sym);
1111280461Sdim  }
1112280461Sdim
1113280461Sdim  // Sort undefined symbol alphabetically, then add to symbol table.
1114280461Sdim  std::vector<AtomAndIndex> undefs;
1115280461Sdim  undefs.reserve(128);
1116280461Sdim  for (const UndefinedAtom *atom : atomFile.undefined()) {
1117280461Sdim    AtomAndIndex ai = { atom, 0, N_EXT };
1118280461Sdim    undefs.push_back(ai);
1119280461Sdim  }
1120280461Sdim  for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
1121280461Sdim    AtomAndIndex ai = { atom, 0, N_EXT };
1122280461Sdim    undefs.push_back(ai);
1123280461Sdim  }
1124280461Sdim  std::sort(undefs.begin(), undefs.end(), AtomSorter());
1125280461Sdim  const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
1126280461Sdim  for (AtomAndIndex &ai : undefs) {
1127280461Sdim    Symbol sym;
1128280461Sdim    uint16_t desc = 0;
1129280461Sdim    if (!rMode) {
1130292934Sdim      uint8_t ordinal = 0;
1131292934Sdim      if (!_ctx.useFlatNamespace())
1132292934Sdim        ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
1133280461Sdim      llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
1134280461Sdim    }
1135280461Sdim    sym.name  = ai.atom->name();
1136280461Sdim    sym.type  = N_UNDF;
1137280461Sdim    sym.scope = ai.scope;
1138280461Sdim    sym.sect  = 0;
1139280461Sdim    sym.desc  = desc;
1140280461Sdim    sym.value = 0;
1141280461Sdim    _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
1142280461Sdim    file.undefinedSymbols.push_back(sym);
1143280461Sdim  }
1144280461Sdim
1145314564Sdim  return llvm::Error::success();
1146280461Sdim}
1147280461Sdim
1148280461Sdimconst Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
1149280461Sdim  for (const Reference *ref : *lpAtom) {
1150280461Sdim    if (_archHandler.isLazyPointer(*ref)) {
1151280461Sdim      return ref->target();
1152280461Sdim    }
1153280461Sdim  }
1154280461Sdim  return nullptr;
1155280461Sdim}
1156280461Sdim
1157280461Sdimconst Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
1158280461Sdim  for (const Reference *ref : *stubAtom) {
1159280461Sdim    if (const Atom *ta = ref->target()) {
1160280461Sdim      if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
1161280461Sdim        const Atom *target = targetOfLazyPointer(lpAtom);
1162280461Sdim        if (target)
1163280461Sdim          return target;
1164280461Sdim      }
1165280461Sdim    }
1166280461Sdim  }
1167280461Sdim  return nullptr;
1168280461Sdim}
1169280461Sdim
1170280461Sdimvoid Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
1171280461Sdim  for (SectionInfo *si : _sectionInfos) {
1172280461Sdim    Section &normSect = file.sections[si->normalizedSectionIndex];
1173280461Sdim    switch (si->type) {
1174280461Sdim    case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
1175280461Sdim      for (const AtomInfo &info : si->atomsAndOffsets) {
1176280461Sdim        bool foundTarget = false;
1177280461Sdim        for (const Reference *ref : *info.atom) {
1178280461Sdim          const Atom *target = ref->target();
1179280461Sdim          if (target) {
1180280461Sdim            if (isa<const SharedLibraryAtom>(target)) {
1181280461Sdim              uint32_t index = _atomToSymbolIndex[target];
1182280461Sdim              normSect.indirectSymbols.push_back(index);
1183280461Sdim              foundTarget = true;
1184280461Sdim            } else {
1185280461Sdim              normSect.indirectSymbols.push_back(
1186280461Sdim                                            llvm::MachO::INDIRECT_SYMBOL_LOCAL);
1187280461Sdim            }
1188280461Sdim          }
1189280461Sdim        }
1190280461Sdim        if (!foundTarget) {
1191280461Sdim          normSect.indirectSymbols.push_back(
1192280461Sdim                                             llvm::MachO::INDIRECT_SYMBOL_ABS);
1193280461Sdim        }
1194280461Sdim      }
1195280461Sdim      break;
1196280461Sdim    case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
1197280461Sdim      for (const AtomInfo &info : si->atomsAndOffsets) {
1198280461Sdim        const Atom *target = targetOfLazyPointer(info.atom);
1199280461Sdim        if (target) {
1200280461Sdim          uint32_t index = _atomToSymbolIndex[target];
1201280461Sdim          normSect.indirectSymbols.push_back(index);
1202280461Sdim        }
1203280461Sdim      }
1204280461Sdim      break;
1205280461Sdim    case llvm::MachO::S_SYMBOL_STUBS:
1206280461Sdim      for (const AtomInfo &info : si->atomsAndOffsets) {
1207280461Sdim        const Atom *target = targetOfStub(info.atom);
1208280461Sdim        if (target) {
1209280461Sdim          uint32_t index = _atomToSymbolIndex[target];
1210280461Sdim          normSect.indirectSymbols.push_back(index);
1211280461Sdim        }
1212280461Sdim      }
1213280461Sdim      break;
1214280461Sdim    default:
1215280461Sdim      break;
1216280461Sdim    }
1217280461Sdim  }
1218280461Sdim}
1219280461Sdim
1220314564Sdimvoid Util::addDependentDylibs(const lld::File &atomFile,
1221314564Sdim                              NormalizedFile &nFile) {
1222280461Sdim  // Scan all imported symbols and build up list of dylibs they are from.
1223280461Sdim  int ordinal = 1;
1224314564Sdim  for (const auto *dylib : _ctx.allDylibs()) {
1225314564Sdim    DylibPathToInfo::iterator pos = _dylibInfo.find(dylib->installName());
1226280461Sdim    if (pos == _dylibInfo.end()) {
1227280461Sdim      DylibInfo info;
1228314564Sdim      bool flatNamespaceAtom = dylib == _ctx.flatNamespaceFile();
1229292934Sdim
1230292934Sdim      // If we're in -flat_namespace mode (or this atom came from the flat
1231292934Sdim      // namespace file under -undefined dynamic_lookup) then use the flat
1232292934Sdim      // lookup ordinal.
1233292934Sdim      if (flatNamespaceAtom || _ctx.useFlatNamespace())
1234292934Sdim        info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
1235292934Sdim      else
1236292934Sdim        info.ordinal = ordinal++;
1237314564Sdim      info.hasWeak = false;
1238280461Sdim      info.hasNonWeak = !info.hasWeak;
1239314564Sdim      _dylibInfo[dylib->installName()] = info;
1240292934Sdim
1241292934Sdim      // Unless this was a flat_namespace atom, record the source dylib.
1242292934Sdim      if (!flatNamespaceAtom) {
1243292934Sdim        DependentDylib depInfo;
1244314564Sdim        depInfo.path = dylib->installName();
1245292934Sdim        depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
1246314564Sdim        depInfo.currentVersion = _ctx.dylibCurrentVersion(dylib->path());
1247314564Sdim        depInfo.compatVersion = _ctx.dylibCompatVersion(dylib->path());
1248292934Sdim        nFile.dependentDylibs.push_back(depInfo);
1249292934Sdim      }
1250280461Sdim    } else {
1251314564Sdim      pos->second.hasWeak = false;
1252314564Sdim      pos->second.hasNonWeak = !pos->second.hasWeak;
1253280461Sdim    }
1254280461Sdim  }
1255280461Sdim  // Automatically weak link dylib in which all symbols are weak (canBeNull).
1256280461Sdim  for (DependentDylib &dep : nFile.dependentDylibs) {
1257280461Sdim    DylibInfo &info = _dylibInfo[dep.path];
1258280461Sdim    if (info.hasWeak && !info.hasNonWeak)
1259280461Sdim      dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
1260292934Sdim    else if (_ctx.isUpwardDylib(dep.path))
1261280461Sdim      dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB;
1262280461Sdim  }
1263280461Sdim}
1264280461Sdim
1265280461Sdimint Util::dylibOrdinal(const SharedLibraryAtom *sa) {
1266280461Sdim  return _dylibInfo[sa->loadName()].ordinal;
1267280461Sdim}
1268280461Sdim
1269280461Sdimvoid Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
1270280461Sdim                                                  uint64_t &segmentStartAddr) {
1271280461Sdim  segmentIndex = 0;
1272280461Sdim  for (const SegmentInfo *seg : _segmentInfos) {
1273280461Sdim    if ((seg->address <= sect->address)
1274280461Sdim      && (seg->address+seg->size >= sect->address+sect->size)) {
1275280461Sdim      segmentStartAddr = seg->address;
1276280461Sdim      return;
1277280461Sdim    }
1278280461Sdim    ++segmentIndex;
1279280461Sdim  }
1280280461Sdim  llvm_unreachable("section not in any segment");
1281280461Sdim}
1282280461Sdim
1283280461Sdimuint32_t Util::sectionIndexForAtom(const Atom *atom) {
1284280461Sdim  uint64_t address = _atomToAddress[atom];
1285280461Sdim  for (const SectionInfo *si : _sectionInfos) {
1286280461Sdim    if ((si->address <= address) && (address < si->address+si->size))
1287293258Sdim      return si->finalSectionIndex;
1288280461Sdim  }
1289280461Sdim  llvm_unreachable("atom not in any section");
1290280461Sdim}
1291280461Sdim
1292280461Sdimvoid Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
1293292934Sdim  if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
1294280461Sdim    return;
1295280461Sdim
1296280461Sdim  // Utility function for ArchHandler to find symbol index for an atom.
1297280461Sdim  auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
1298280461Sdim    auto pos = _atomToSymbolIndex.find(&atom);
1299280461Sdim    assert(pos != _atomToSymbolIndex.end());
1300280461Sdim    return pos->second;
1301280461Sdim  };
1302280461Sdim
1303280461Sdim  // Utility function for ArchHandler to find section index for an atom.
1304280461Sdim  auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
1305280461Sdim    return sectionIndexForAtom(&atom);
1306280461Sdim  };
1307280461Sdim
1308280461Sdim  // Utility function for ArchHandler to find address of atom in output file.
1309280461Sdim  auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
1310280461Sdim    auto pos = _atomToAddress.find(&atom);
1311280461Sdim    assert(pos != _atomToAddress.end());
1312280461Sdim    return pos->second;
1313280461Sdim  };
1314280461Sdim
1315280461Sdim  for (SectionInfo *si : _sectionInfos) {
1316280461Sdim    Section &normSect = file.sections[si->normalizedSectionIndex];
1317280461Sdim    for (const AtomInfo &info : si->atomsAndOffsets) {
1318280461Sdim      const DefinedAtom *atom = info.atom;
1319280461Sdim      for (const Reference *ref : *atom) {
1320293846Sdim        // Skip emitting relocs for sections which are always able to be
1321293846Sdim        // implicitly regenerated and where the relocation targets an address
1322293846Sdim        // which is defined.
1323293846Sdim        if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target()))
1324293846Sdim          continue;
1325280461Sdim        _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
1326280461Sdim                                              symIndexForAtom,
1327280461Sdim                                              sectIndexForAtom,
1328280461Sdim                                              addressForAtom,
1329280461Sdim                                              normSect.relocations);
1330280461Sdim      }
1331280461Sdim    }
1332280461Sdim  }
1333280461Sdim}
1334280461Sdim
1335303239Sdimvoid Util::addFunctionStarts(const lld::File &, NormalizedFile &file) {
1336303239Sdim  if (!_ctx.generateFunctionStartsLoadCommand())
1337303239Sdim    return;
1338303239Sdim  file.functionStarts.reserve(8192);
1339303239Sdim  // Delta compress function starts, starting with the mach header symbol.
1340303239Sdim  const uint64_t badAddress = ~0ULL;
1341303239Sdim  uint64_t addr = badAddress;
1342303239Sdim  for (SectionInfo *si : _sectionInfos) {
1343303239Sdim    for (const AtomInfo &info : si->atomsAndOffsets) {
1344303239Sdim      auto type = info.atom->contentType();
1345303239Sdim      if (type == DefinedAtom::typeMachHeader) {
1346303239Sdim        addr = _atomToAddress[info.atom];
1347303239Sdim        continue;
1348303239Sdim      }
1349303239Sdim      if (type != DefinedAtom::typeCode)
1350303239Sdim        continue;
1351303239Sdim      assert(addr != badAddress && "Missing mach header symbol");
1352303239Sdim      // Skip atoms which have 0 size.  This is so that LC_FUNCTION_STARTS
1353303239Sdim      // can't spill in to the next section.
1354303239Sdim      if (!info.atom->size())
1355303239Sdim        continue;
1356303239Sdim      uint64_t nextAddr = _atomToAddress[info.atom];
1357303239Sdim      if (_archHandler.isThumbFunction(*info.atom))
1358303239Sdim        nextAddr |= 1;
1359303239Sdim      uint64_t delta = nextAddr - addr;
1360303239Sdim      if (delta) {
1361303239Sdim        ByteBuffer buffer;
1362303239Sdim        buffer.append_uleb128(delta);
1363303239Sdim        file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(),
1364303239Sdim                                   buffer.bytes() + buffer.size());
1365303239Sdim      }
1366303239Sdim      addr = nextAddr;
1367303239Sdim    }
1368303239Sdim  }
1369303239Sdim
1370303239Sdim  // Null terminate, and pad to pointer size for this arch.
1371303239Sdim  file.functionStarts.push_back(0);
1372303239Sdim
1373303239Sdim  auto size = file.functionStarts.size();
1374303239Sdim  for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4);
1375303239Sdim       i != e; ++i)
1376303239Sdim    file.functionStarts.push_back(0);
1377303239Sdim}
1378303239Sdim
1379280461Sdimvoid Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
1380303239Sdim  if (!_ctx.generateDataInCodeLoadCommand())
1381303239Sdim    return;
1382280461Sdim  for (SectionInfo *si : _sectionInfos) {
1383280461Sdim    for (const AtomInfo &info : si->atomsAndOffsets) {
1384280461Sdim      // Atoms that contain data-in-code have "transition" references
1385280461Sdim      // which mark a point where the embedded data starts of ends.
1386280461Sdim      // This needs to be converted to the mach-o format which is an array
1387280461Sdim      // of data-in-code ranges.
1388280461Sdim      uint32_t startOffset = 0;
1389280461Sdim      DataRegionType mode = DataRegionType(0);
1390280461Sdim      for (const Reference *ref : *info.atom) {
1391280461Sdim        if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
1392280461Sdim          continue;
1393280461Sdim        if (_archHandler.isDataInCodeTransition(ref->kindValue())) {
1394280461Sdim          DataRegionType nextMode = (DataRegionType)ref->addend();
1395280461Sdim          if (mode != nextMode) {
1396280461Sdim            if (mode != 0) {
1397280461Sdim              // Found end data range, so make range entry.
1398280461Sdim              DataInCode entry;
1399280461Sdim              entry.offset = si->address + info.offsetInSection + startOffset;
1400280461Sdim              entry.length = ref->offsetInAtom() - startOffset;
1401280461Sdim              entry.kind   = mode;
1402280461Sdim              file.dataInCode.push_back(entry);
1403280461Sdim            }
1404280461Sdim          }
1405280461Sdim          mode = nextMode;
1406280461Sdim          startOffset = ref->offsetInAtom();
1407280461Sdim        }
1408280461Sdim      }
1409280461Sdim      if (mode != 0) {
1410280461Sdim        // Function ends with data (no end transition).
1411280461Sdim        DataInCode entry;
1412280461Sdim        entry.offset = si->address + info.offsetInSection + startOffset;
1413280461Sdim        entry.length = info.atom->size() - startOffset;
1414280461Sdim        entry.kind   = mode;
1415280461Sdim        file.dataInCode.push_back(entry);
1416280461Sdim      }
1417280461Sdim    }
1418280461Sdim  }
1419280461Sdim}
1420280461Sdim
1421280461Sdimvoid Util::addRebaseAndBindingInfo(const lld::File &atomFile,
1422280461Sdim                                                        NormalizedFile &nFile) {
1423292934Sdim  if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
1424280461Sdim    return;
1425280461Sdim
1426280461Sdim  uint8_t segmentIndex;
1427280461Sdim  uint64_t segmentStartAddr;
1428326909Sdim  uint32_t offsetInBindInfo = 0;
1429326909Sdim
1430280461Sdim  for (SectionInfo *sect : _sectionInfos) {
1431280461Sdim    segIndexForSection(sect, segmentIndex, segmentStartAddr);
1432280461Sdim    for (const AtomInfo &info : sect->atomsAndOffsets) {
1433280461Sdim      const DefinedAtom *atom = info.atom;
1434280461Sdim      for (const Reference *ref : *atom) {
1435280461Sdim        uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
1436280461Sdim                                - segmentStartAddr;
1437280461Sdim        const Atom* targ = ref->target();
1438280461Sdim        if (_archHandler.isPointer(*ref)) {
1439280461Sdim          // A pointer to a DefinedAtom requires rebasing.
1440280461Sdim          if (isa<DefinedAtom>(targ)) {
1441280461Sdim            RebaseLocation rebase;
1442280461Sdim            rebase.segIndex = segmentIndex;
1443280461Sdim            rebase.segOffset = segmentOffset;
1444280461Sdim            rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
1445280461Sdim            nFile.rebasingInfo.push_back(rebase);
1446280461Sdim          }
1447280461Sdim          // A pointer to an SharedLibraryAtom requires binding.
1448280461Sdim          if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
1449280461Sdim            BindLocation bind;
1450280461Sdim            bind.segIndex = segmentIndex;
1451280461Sdim            bind.segOffset = segmentOffset;
1452280461Sdim            bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1453280461Sdim            bind.canBeNull = sa->canBeNullAtRuntime();
1454280461Sdim            bind.ordinal = dylibOrdinal(sa);
1455280461Sdim            bind.symbolName = targ->name();
1456280461Sdim            bind.addend = ref->addend();
1457280461Sdim            nFile.bindingInfo.push_back(bind);
1458280461Sdim          }
1459280461Sdim        }
1460280461Sdim        else if (_archHandler.isLazyPointer(*ref)) {
1461280461Sdim          BindLocation bind;
1462280461Sdim          if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
1463280461Sdim            bind.ordinal = dylibOrdinal(sa);
1464280461Sdim          } else {
1465280461Sdim            bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF;
1466280461Sdim          }
1467280461Sdim          bind.segIndex = segmentIndex;
1468280461Sdim          bind.segOffset = segmentOffset;
1469280461Sdim          bind.kind = llvm::MachO::BIND_TYPE_POINTER;
1470280461Sdim          bind.canBeNull = false; //sa->canBeNullAtRuntime();
1471280461Sdim          bind.symbolName = targ->name();
1472280461Sdim          bind.addend = ref->addend();
1473280461Sdim          nFile.lazyBindingInfo.push_back(bind);
1474326909Sdim
1475326909Sdim          // Now that we know the segmentOffset and the ordinal attribute,
1476326909Sdim          // we can fix the helper's code
1477326909Sdim
1478326909Sdim          fixLazyReferenceImm(atom, offsetInBindInfo, nFile);
1479326909Sdim
1480326909Sdim          // 5 bytes for opcodes + variable sizes (target name + \0 and offset
1481326909Sdim          // encode's size)
1482326909Sdim          offsetInBindInfo +=
1483326909Sdim              6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset);
1484326909Sdim          if (bind.ordinal > BIND_IMMEDIATE_MASK)
1485326909Sdim            offsetInBindInfo += llvm::getULEB128Size(bind.ordinal);
1486280461Sdim        }
1487280461Sdim      }
1488280461Sdim    }
1489280461Sdim  }
1490280461Sdim}
1491280461Sdim
1492326909Sdimvoid Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
1493326909Sdim                               NormalizedFile &file) {
1494360784Sdim  for (const Reference *ref : *atom) {
1495326909Sdim    const DefinedAtom *da = dyn_cast<DefinedAtom>(ref->target());
1496326909Sdim    if (da == nullptr)
1497326909Sdim      return;
1498326909Sdim
1499326909Sdim    const Reference *helperRef = nullptr;
1500326909Sdim    for (const Reference *hr : *da) {
1501326909Sdim      if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) {
1502326909Sdim        helperRef = hr;
1503326909Sdim        break;
1504326909Sdim      }
1505326909Sdim    }
1506326909Sdim    if (helperRef == nullptr)
1507326909Sdim      continue;
1508326909Sdim
1509326909Sdim    // TODO: maybe get the fixed atom content from _archHandler ?
1510326909Sdim    for (SectionInfo *sectInfo : _sectionInfos) {
1511326909Sdim      for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) {
1512326909Sdim        if (atomInfo.atom == helperRef->target()) {
1513326909Sdim          auto sectionContent =
1514326909Sdim              file.sections[sectInfo->normalizedSectionIndex].content;
1515326909Sdim          uint8_t *rawb =
1516326909Sdim              file.ownedAllocations.Allocate<uint8_t>(sectionContent.size());
1517326909Sdim          llvm::MutableArrayRef<uint8_t> newContent{rawb,
1518326909Sdim                                                    sectionContent.size()};
1519326909Sdim          std::copy(sectionContent.begin(), sectionContent.end(),
1520326909Sdim                    newContent.begin());
1521326909Sdim          llvm::support::ulittle32_t *loc =
1522326909Sdim              reinterpret_cast<llvm::support::ulittle32_t *>(
1523326909Sdim                  &newContent[atomInfo.offsetInSection +
1524326909Sdim                              helperRef->offsetInAtom()]);
1525326909Sdim          *loc = offset;
1526326909Sdim          file.sections[sectInfo->normalizedSectionIndex].content = newContent;
1527326909Sdim        }
1528326909Sdim      }
1529326909Sdim    }
1530326909Sdim  }
1531326909Sdim}
1532326909Sdim
1533280461Sdimvoid Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
1534292934Sdim  if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
1535280461Sdim    return;
1536280461Sdim
1537280461Sdim  for (SectionInfo *sect : _sectionInfos) {
1538280461Sdim    for (const AtomInfo &info : sect->atomsAndOffsets) {
1539280461Sdim      const DefinedAtom *atom = info.atom;
1540280461Sdim      if (atom->scope() != Atom::scopeGlobal)
1541280461Sdim        continue;
1542292934Sdim      if (_ctx.exportRestrictMode()) {
1543292934Sdim        if (!_ctx.exportSymbolNamed(atom->name()))
1544280461Sdim          continue;
1545280461Sdim      }
1546280461Sdim      Export exprt;
1547280461Sdim      exprt.name = atom->name();
1548292934Sdim      exprt.offset = _atomToAddress[atom] - _ctx.baseAddress();
1549280461Sdim      exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1550280461Sdim      if (atom->merge() == DefinedAtom::mergeAsWeak)
1551280461Sdim        exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1552280461Sdim      else
1553280461Sdim        exprt.flags = 0;
1554280461Sdim      exprt.otherOffset = 0;
1555280461Sdim      exprt.otherName = StringRef();
1556280461Sdim      nFile.exportInfo.push_back(exprt);
1557280461Sdim    }
1558280461Sdim  }
1559280461Sdim}
1560280461Sdim
1561280461Sdimuint32_t Util::fileFlags() {
1562280461Sdim  // FIXME: these need to determined at runtime.
1563292934Sdim  if (_ctx.outputMachOType() == MH_OBJECT) {
1564303239Sdim    return _subsectionsViaSymbols ? MH_SUBSECTIONS_VIA_SYMBOLS : 0;
1565280461Sdim  } else {
1566292934Sdim    uint32_t flags = MH_DYLDLINK;
1567292934Sdim    if (!_ctx.useFlatNamespace())
1568292934Sdim        flags |= MH_TWOLEVEL | MH_NOUNDEFS;
1569292934Sdim    if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE())
1570292934Sdim      flags |= MH_PIE;
1571292934Sdim    if (_hasTLVDescriptors)
1572292934Sdim      flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS);
1573292934Sdim    return flags;
1574280461Sdim  }
1575280461Sdim}
1576280461Sdim
1577280461Sdim} // end anonymous namespace
1578280461Sdim
1579280461Sdimnamespace lld {
1580280461Sdimnamespace mach_o {
1581280461Sdimnamespace normalized {
1582280461Sdim
1583280461Sdim/// Convert a set of Atoms into a normalized mach-o file.
1584303239Sdimllvm::Expected<std::unique_ptr<NormalizedFile>>
1585280461SdimnormalizedFromAtoms(const lld::File &atomFile,
1586280461Sdim                                           const MachOLinkingContext &context) {
1587280461Sdim  // The util object buffers info until the normalized file can be made.
1588280461Sdim  Util util(context);
1589303239Sdim  util.processDefinedAtoms(atomFile);
1590280461Sdim  util.organizeSections();
1591280461Sdim
1592280461Sdim  std::unique_ptr<NormalizedFile> f(new NormalizedFile());
1593280461Sdim  NormalizedFile &normFile = *f.get();
1594280461Sdim  normFile.arch = context.arch();
1595280461Sdim  normFile.fileType = context.outputMachOType();
1596280461Sdim  normFile.flags = util.fileFlags();
1597292934Sdim  normFile.stackSize = context.stackSize();
1598280461Sdim  normFile.installName = context.installName();
1599280461Sdim  normFile.currentVersion = context.currentVersion();
1600280461Sdim  normFile.compatVersion = context.compatibilityVersion();
1601303239Sdim  normFile.os = context.os();
1602303239Sdim
1603303239Sdim  // If we are emitting an object file, then the min version is the maximum
1604303239Sdim  // of the min's of all the source files and the cmdline.
1605303239Sdim  if (normFile.fileType == llvm::MachO::MH_OBJECT)
1606303239Sdim    normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion());
1607303239Sdim  else
1608303239Sdim    normFile.minOSverson = context.osMinVersion();
1609303239Sdim
1610303239Sdim  normFile.minOSVersionKind = util.minVersionCommandType();
1611303239Sdim
1612303239Sdim  normFile.sdkVersion = context.sdkVersion();
1613303239Sdim  normFile.sourceVersion = context.sourceVersion();
1614303239Sdim
1615303239Sdim  if (context.generateVersionLoadCommand() &&
1616303239Sdim      context.os() != MachOLinkingContext::OS::unknown)
1617303239Sdim    normFile.hasMinVersionLoadCommand = true;
1618303239Sdim  else if (normFile.fileType == llvm::MachO::MH_OBJECT &&
1619303239Sdim           util.allSourceFilesHaveMinVersions() &&
1620303239Sdim           ((normFile.os != MachOLinkingContext::OS::unknown) ||
1621303239Sdim            util.minVersionCommandType())) {
1622303239Sdim    // If we emit an object file, then it should contain a min version load
1623303239Sdim    // command if all of the source files also contained min version commands.
1624303239Sdim    // Also, we either need to have a platform, or found a platform from the
1625303239Sdim    // source object files.
1626303239Sdim    normFile.hasMinVersionLoadCommand = true;
1627303239Sdim  }
1628303239Sdim  normFile.generateDataInCodeLoadCommand =
1629303239Sdim    context.generateDataInCodeLoadCommand();
1630280461Sdim  normFile.pageSize = context.pageSize();
1631280461Sdim  normFile.rpaths = context.rpaths();
1632280461Sdim  util.addDependentDylibs(atomFile, normFile);
1633280461Sdim  util.copySegmentInfo(normFile);
1634280461Sdim  util.copySectionInfo(normFile);
1635280461Sdim  util.assignAddressesToSections(normFile);
1636280461Sdim  util.buildAtomToAddressMap();
1637314564Sdim  if (auto err = util.synthesizeDebugNotes(normFile))
1638314564Sdim    return std::move(err);
1639280461Sdim  util.updateSectionInfo(normFile);
1640280461Sdim  util.copySectionContent(normFile);
1641280461Sdim  if (auto ec = util.addSymbols(atomFile, normFile)) {
1642303239Sdim    return std::move(ec);
1643280461Sdim  }
1644280461Sdim  util.addIndirectSymbols(atomFile, normFile);
1645280461Sdim  util.addRebaseAndBindingInfo(atomFile, normFile);
1646280461Sdim  util.addExportInfo(atomFile, normFile);
1647280461Sdim  util.addSectionRelocs(atomFile, normFile);
1648303239Sdim  util.addFunctionStarts(atomFile, normFile);
1649280461Sdim  util.buildDataInCodeArray(atomFile, normFile);
1650280461Sdim  util.copyEntryPointAddress(normFile);
1651280461Sdim
1652280461Sdim  return std::move(f);
1653280461Sdim}
1654280461Sdim
1655280461Sdim} // namespace normalized
1656280461Sdim} // namespace mach_o
1657280461Sdim} // namespace lld
1658