//===- Symbols.h ------------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines various types of Symbols. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_SYMBOLS_H #define LLD_ELF_SYMBOLS_H #include "Config.h" #include "lld/Common/LLVM.h" #include "lld/Common/Memory.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Object/ELF.h" #include "llvm/Support/Compiler.h" #include <tuple> namespace lld { namespace elf { class Symbol; } // Returns a string representation for a symbol for diagnostics. std::string toString(const elf::Symbol &); namespace elf { class CommonSymbol; class Defined; class OutputSection; class SectionBase; class InputSectionBase; class SharedSymbol; class Symbol; class Undefined; class LazySymbol; class InputFile; void printTraceSymbol(const Symbol &sym, StringRef name); enum { … }; // The base class for real symbol classes. class Symbol { … }; // Represents a symbol that is defined in the current output file. class Defined : public Symbol { … }; // Represents a common symbol. // // On Unix, it is traditionally allowed to write variable definitions // without initialization expressions (such as "int foo;") to header // files. Such definition is called "tentative definition". // // Using tentative definition is usually considered a bad practice // because you should write only declarations (such as "extern int // foo;") to header files. Nevertheless, the linker and the compiler // have to do something to support bad code by allowing duplicate // definitions for this particular case. // // Common symbols represent variable definitions without initializations. // The compiler creates common symbols when it sees variable definitions // without initialization (you can suppress this behavior and let the // compiler create a regular defined symbol by -fno-common). // // The linker allows common symbols to be replaced by regular defined // symbols. If there are remaining common symbols after name resolution is // complete, they are converted to regular defined symbols in a .bss // section. (Therefore, the later passes don't see any CommonSymbols.) class CommonSymbol : public Symbol { … }; class Undefined : public Symbol { … }; class SharedSymbol : public Symbol { … }; // LazySymbol symbols represent symbols in object files between --start-lib and // --end-lib options. LLD also handles traditional archives as if all the files // in the archive are surrounded by --start-lib and --end-lib. // // A special complication is the handling of weak undefined symbols. They should // not load a file, but we have to remember we have seen both the weak undefined // and the lazy. We represent that with a lazy symbol with a weak binding. This // means that code looking for undefined symbols normally also has to take lazy // symbols into consideration. class LazySymbol : public Symbol { … }; // A buffer class that is large enough to hold any Symbol-derived // object. We allocate memory using this class and instantiate a symbol // using the placement new. // It is important to keep the size of SymbolUnion small for performance and // memory usage reasons. 64 bytes is a soft limit based on the size of Defined // on a 64-bit system. This is enforced by a static_assert in Symbols.cpp. SymbolUnion; template <typename... T> Defined *makeDefined(T &&...args) { … } void reportDuplicate(const Symbol &sym, const InputFile *newFile, InputSectionBase *errSec, uint64_t errOffset); void maybeWarnUnorderableSymbol(const Symbol *sym); bool computeIsPreemptible(const Symbol &sym); } // namespace elf } // namespace lld #endif