xref: /openbsd-src/gnu/llvm/lld/MachO/ConcatOutputSection.h (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
11cf9926bSpatrick //===- ConcatOutputSection.h ------------------------------------*- C++ -*-===//
21cf9926bSpatrick //
31cf9926bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41cf9926bSpatrick // See https://llvm.org/LICENSE.txt for license information.
51cf9926bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf9926bSpatrick //
71cf9926bSpatrick //===----------------------------------------------------------------------===//
81cf9926bSpatrick 
9*dfe94b16Srobert #ifndef LLD_MACHO_CONCAT_OUTPUT_SECTION_H
10*dfe94b16Srobert #define LLD_MACHO_CONCAT_OUTPUT_SECTION_H
111cf9926bSpatrick 
121cf9926bSpatrick #include "InputSection.h"
131cf9926bSpatrick #include "OutputSection.h"
141cf9926bSpatrick #include "lld/Common/LLVM.h"
151cf9926bSpatrick #include "llvm/ADT/DenseMap.h"
161cf9926bSpatrick #include "llvm/ADT/MapVector.h"
171cf9926bSpatrick 
18*dfe94b16Srobert namespace lld::macho {
191cf9926bSpatrick 
201cf9926bSpatrick class Defined;
211cf9926bSpatrick 
221cf9926bSpatrick // Linking multiple files will inevitably mean resolving sections in different
231cf9926bSpatrick // files that are labeled with the same segment and section name. This class
241cf9926bSpatrick // contains all such sections and writes the data from each section sequentially
251cf9926bSpatrick // in the final binary.
26*dfe94b16Srobert class ConcatOutputSection : public OutputSection {
271cf9926bSpatrick public:
ConcatOutputSection(StringRef name)281cf9926bSpatrick   explicit ConcatOutputSection(StringRef name)
291cf9926bSpatrick       : OutputSection(ConcatKind, name) {}
301cf9926bSpatrick 
firstSection()311cf9926bSpatrick   const ConcatInputSection *firstSection() const { return inputs.front(); }
lastSection()321cf9926bSpatrick   const ConcatInputSection *lastSection() const { return inputs.back(); }
isNeeded()331cf9926bSpatrick   bool isNeeded() const override { return !inputs.empty(); }
341cf9926bSpatrick 
351cf9926bSpatrick   // These accessors will only be valid after finalizing the section
getSize()361cf9926bSpatrick   uint64_t getSize() const override { return size; }
getFileSize()371cf9926bSpatrick   uint64_t getFileSize() const override { return fileSize; }
381cf9926bSpatrick 
39*dfe94b16Srobert   // Assign values to InputSection::outSecOff. In contrast to TextOutputSection,
40*dfe94b16Srobert   // which does this in its implementation of `finalize()`, we can do this
41*dfe94b16Srobert   // without `finalize()`'s sequential guarantees detailed in the block comment
42*dfe94b16Srobert   // of `OutputSection::finalize()`.
43*dfe94b16Srobert   virtual void finalizeContents();
44*dfe94b16Srobert 
451cf9926bSpatrick   void addInput(ConcatInputSection *input);
461cf9926bSpatrick   void writeTo(uint8_t *buf) const override;
471cf9926bSpatrick 
classof(const OutputSection * sec)481cf9926bSpatrick   static bool classof(const OutputSection *sec) {
491cf9926bSpatrick     return sec->kind() == ConcatKind;
501cf9926bSpatrick   }
511cf9926bSpatrick 
521cf9926bSpatrick   static ConcatOutputSection *getOrCreateForInput(const InputSection *);
531cf9926bSpatrick 
54*dfe94b16Srobert   std::vector<ConcatInputSection *> inputs;
551cf9926bSpatrick 
56*dfe94b16Srobert protected:
571cf9926bSpatrick   size_t size = 0;
581cf9926bSpatrick   uint64_t fileSize = 0;
59*dfe94b16Srobert   void finalizeOne(ConcatInputSection *);
60*dfe94b16Srobert 
61*dfe94b16Srobert private:
62*dfe94b16Srobert   void finalizeFlags(InputSection *input);
63*dfe94b16Srobert };
64*dfe94b16Srobert 
65*dfe94b16Srobert // ConcatOutputSections that contain code (text) require special handling to
66*dfe94b16Srobert // support thunk insertion.
67*dfe94b16Srobert class TextOutputSection : public ConcatOutputSection {
68*dfe94b16Srobert public:
TextOutputSection(StringRef name)69*dfe94b16Srobert   explicit TextOutputSection(StringRef name) : ConcatOutputSection(name) {}
finalizeContents()70*dfe94b16Srobert   void finalizeContents() override {}
71*dfe94b16Srobert   void finalize() override;
72*dfe94b16Srobert   bool needsThunks() const;
73*dfe94b16Srobert   void writeTo(uint8_t *buf) const override;
74*dfe94b16Srobert 
75*dfe94b16Srobert private:
76*dfe94b16Srobert   uint64_t estimateStubsInRangeVA(size_t callIdx) const;
77*dfe94b16Srobert 
78*dfe94b16Srobert   std::vector<ConcatInputSection *> thunks;
791cf9926bSpatrick };
801cf9926bSpatrick 
811cf9926bSpatrick // We maintain one ThunkInfo per real function.
821cf9926bSpatrick //
831cf9926bSpatrick // The "active thunk" is represented by the sym/isec pair that
841cf9926bSpatrick // turns-over during finalize(): as the call-site address advances,
851cf9926bSpatrick // the active thunk goes out of branch-range, and we create a new
861cf9926bSpatrick // thunk to take its place.
871cf9926bSpatrick //
881cf9926bSpatrick // The remaining members -- bools and counters -- apply to the
891cf9926bSpatrick // collection of thunks associated with the real function.
901cf9926bSpatrick 
911cf9926bSpatrick struct ThunkInfo {
921cf9926bSpatrick   // These denote the active thunk:
931cf9926bSpatrick   Defined *sym = nullptr;             // private-extern symbol for active thunk
941cf9926bSpatrick   ConcatInputSection *isec = nullptr; // input section for active thunk
951cf9926bSpatrick 
961cf9926bSpatrick   // The following values are cumulative across all thunks on this function
971cf9926bSpatrick   uint32_t callSiteCount = 0;  // how many calls to the real function?
981cf9926bSpatrick   uint32_t callSitesUsed = 0;  // how many call sites processed so-far?
991cf9926bSpatrick   uint32_t thunkCallCount = 0; // how many call sites went to thunk?
1001cf9926bSpatrick   uint8_t sequence = 0;        // how many thunks created so-far?
1011cf9926bSpatrick };
1021cf9926bSpatrick 
1031cf9926bSpatrick NamePair maybeRenameSection(NamePair key);
1041cf9926bSpatrick 
1051cf9926bSpatrick // Output sections are added to output segments in iteration order
1061cf9926bSpatrick // of ConcatOutputSection, so must have deterministic iteration order.
1071cf9926bSpatrick extern llvm::MapVector<NamePair, ConcatOutputSection *> concatOutputSections;
1081cf9926bSpatrick 
1091cf9926bSpatrick extern llvm::DenseMap<Symbol *, ThunkInfo> thunkMap;
1101cf9926bSpatrick 
111*dfe94b16Srobert } // namespace lld::macho
1121cf9926bSpatrick 
1131cf9926bSpatrick #endif
114