| Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 +0000 | [diff] [blame^] | 1 | //===- Symbols.cpp --------------------------------------------------------===// | 
|  | 2 | // | 
|  | 3 | //                             The LLVM Linker | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | #include "InputFiles.h" | 
|  | 11 | #include "Symbols.h" | 
|  | 12 | #include "lld/Core/Error.h" | 
|  | 13 | #include "llvm/ADT/STLExtras.h" | 
|  | 14 | #include "llvm/Support/Debug.h" | 
|  | 15 | #include "llvm/Support/raw_ostream.h" | 
|  | 16 |  | 
|  | 17 | using namespace llvm::object; | 
|  | 18 | using llvm::sys::fs::identify_magic; | 
|  | 19 | using llvm::sys::fs::file_magic; | 
|  | 20 |  | 
|  | 21 | namespace lld { | 
|  | 22 | namespace coff { | 
|  | 23 |  | 
|  | 24 | // Returns 1, 0 or -1 if this symbol should take precedence over the | 
|  | 25 | // Other in the symbol table, tie or lose, respectively. | 
|  | 26 | int Defined::compare(SymbolBody *Other) { | 
|  | 27 | if (!isa<Defined>(Other)) | 
|  | 28 | return 1; | 
|  | 29 | auto *X = dyn_cast<DefinedRegular>(this); | 
|  | 30 | auto *Y = dyn_cast<DefinedRegular>(Other); | 
|  | 31 | if (!X || !Y) | 
|  | 32 | return 0; | 
|  | 33 |  | 
|  | 34 | // Common symbols are weaker than other types of defined symbols. | 
|  | 35 | if (X->isCommon() && Y->isCommon()) | 
|  | 36 | return (X->getCommonSize() < Y->getCommonSize()) ? -1 : 1; | 
|  | 37 | // TODO: we are not sure if regular defined symbol and common | 
|  | 38 | // symbols are allowed to have the same name. | 
|  | 39 | if (X->isCommon()) | 
|  | 40 | return -1; | 
|  | 41 | if (Y->isCommon()) | 
|  | 42 | return 1; | 
|  | 43 |  | 
|  | 44 | if (X->isCOMDAT() && Y->isCOMDAT()) | 
|  | 45 | return 1; | 
|  | 46 | return 0; | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | int Lazy::compare(SymbolBody *Other) { | 
|  | 50 | if (isa<Defined>(Other)) | 
|  | 51 | return -1; | 
|  | 52 |  | 
|  | 53 | // Undefined symbols with weak aliases will turn into defined | 
|  | 54 | // symbols if they remain undefined, so we don't need to resolve | 
|  | 55 | // such symbols. | 
|  | 56 | if (auto *U = dyn_cast<Undefined>(Other)) | 
|  | 57 | if (U->getWeakAlias()) | 
|  | 58 | return -1; | 
|  | 59 | return 1; | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | int Undefined::compare(SymbolBody *Other) { | 
|  | 63 | if (isa<Defined>(Other)) | 
|  | 64 | return -1; | 
|  | 65 | if (isa<Lazy>(Other)) | 
|  | 66 | return getWeakAlias() ? 1 : -1; | 
|  | 67 | if (cast<Undefined>(Other)->getWeakAlias()) | 
|  | 68 | return -1; | 
|  | 69 | return 1; | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() { | 
|  | 73 | auto MBRefOrErr = File->getMember(&Sym); | 
|  | 74 | if (auto EC = MBRefOrErr.getError()) | 
|  | 75 | return EC; | 
|  | 76 | MemoryBufferRef MBRef = MBRefOrErr.get(); | 
|  | 77 |  | 
|  | 78 | // getMember returns an empty buffer if the member was already | 
|  | 79 | // read from the library. | 
|  | 80 | if (MBRef.getBuffer().empty()) | 
|  | 81 | return std::unique_ptr<InputFile>(nullptr); | 
|  | 82 |  | 
|  | 83 | file_magic Magic = identify_magic(MBRef.getBuffer()); | 
|  | 84 | if (Magic == file_magic::coff_import_library) | 
|  | 85 | return std::unique_ptr<InputFile>(new ImportFile(MBRef)); | 
|  | 86 |  | 
|  | 87 | if (Magic != file_magic::coff_object) | 
|  | 88 | return make_dynamic_error_code("unknown file type"); | 
|  | 89 |  | 
|  | 90 | std::unique_ptr<InputFile> Obj(new ObjectFile(MBRef.getBufferIdentifier(), MBRef)); | 
|  | 91 | Obj->setParentName(File->getName()); | 
|  | 92 | return std::move(Obj); | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 | } // namespace coff | 
|  | 96 | } // namespace lld |