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