| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 1 | //===- lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp -------------------===// | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 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 |  | 
| Rui Ueyama | fd50283 | 2013-07-24 22:53:23 +0000 | [diff] [blame] | 10 | #include "Atoms.h" | 
| Rui Ueyama | 991f42c | 2013-06-19 17:46:57 +0000 | [diff] [blame] | 11 | #include "GroupedSectionsPass.h" | 
| Rui Ueyama | c8a5379 | 2013-07-11 08:46:21 +0000 | [diff] [blame] | 12 | #include "IdataPass.h" | 
| Rui Ueyama | 908606d | 2013-08-09 04:44:15 +0000 | [diff] [blame] | 13 | #include "LinkerGeneratedSymbolFile.h" | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 14 |  | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/SmallString.h" | 
| Rui Ueyama | fd50283 | 2013-07-24 22:53:23 +0000 | [diff] [blame] | 16 | #include "llvm/Support/Allocator.h" | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 17 | #include "llvm/Support/Path.h" | 
| Rui Ueyama | d95a155 | 2013-06-17 16:59:54 +0000 | [diff] [blame] | 18 | #include "lld/Core/PassManager.h" | 
|  | 19 | #include "lld/Passes/LayoutPass.h" | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 20 | #include "lld/ReaderWriter/PECOFFLinkingContext.h" | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 21 | #include "lld/ReaderWriter/Reader.h" | 
| Rui Ueyama | fd50283 | 2013-07-24 22:53:23 +0000 | [diff] [blame] | 22 | #include "lld/ReaderWriter/Simple.h" | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 23 | #include "lld/ReaderWriter/Writer.h" | 
|  | 24 |  | 
| Rui Ueyama | 9149181 | 2013-09-23 19:52:35 +0000 | [diff] [blame] | 25 | #include <bitset> | 
| Rui Ueyama | 863931c | 2013-10-26 00:46:57 +0000 | [diff] [blame] | 26 | #include <set> | 
| Rui Ueyama | 9149181 | 2013-09-23 19:52:35 +0000 | [diff] [blame] | 27 |  | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 28 | namespace lld { | 
|  | 29 |  | 
| Shankar Easwaran | e44104b | 2013-08-21 22:57:10 +0000 | [diff] [blame] | 30 | namespace {} // anonymous namespace | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 31 |  | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 32 | bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) { | 
| Rui Ueyama | eb0cc96 | 2013-06-08 03:59:00 +0000 | [diff] [blame] | 33 | if (_stackReserve < _stackCommit) { | 
|  | 34 | diagnostics << "Invalid stack size: reserve size must be equal to or " | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 35 | << "greater than commit size, but got " << _stackCommit | 
|  | 36 | << " and " << _stackReserve << ".\n"; | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 37 | return false; | 
| Rui Ueyama | eb0cc96 | 2013-06-08 03:59:00 +0000 | [diff] [blame] | 38 | } | 
|  | 39 |  | 
| Rui Ueyama | 9dd08d9 | 2013-06-08 22:59:10 +0000 | [diff] [blame] | 40 | if (_heapReserve < _heapCommit) { | 
|  | 41 | diagnostics << "Invalid heap size: reserve size must be equal to or " | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 42 | << "greater than commit size, but got " << _heapCommit | 
|  | 43 | << " and " << _heapReserve << ".\n"; | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 44 | return false; | 
| Rui Ueyama | 9dd08d9 | 2013-06-08 22:59:10 +0000 | [diff] [blame] | 45 | } | 
|  | 46 |  | 
| Rui Ueyama | 530488c | 2013-09-03 22:57:00 +0000 | [diff] [blame] | 47 | // It's an error if the base address is not multiple of 64K. | 
|  | 48 | if (_baseAddress & 0xffff) { | 
|  | 49 | diagnostics << "Base address have to be multiple of 64K, but got " | 
|  | 50 | << _baseAddress << "\n"; | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 51 | return false; | 
| Rui Ueyama | 530488c | 2013-09-03 22:57:00 +0000 | [diff] [blame] | 52 | } | 
|  | 53 |  | 
| Rui Ueyama | 9149181 | 2013-09-23 19:52:35 +0000 | [diff] [blame] | 54 | std::bitset<64> alignment(_sectionAlignment); | 
|  | 55 | if (alignment.count() != 1) { | 
|  | 56 | diagnostics << "Section alignment must be a power of 2, but got " | 
|  | 57 | << _sectionAlignment << "\n"; | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 58 | return false; | 
| Rui Ueyama | 9149181 | 2013-09-23 19:52:35 +0000 | [diff] [blame] | 59 | } | 
|  | 60 |  | 
| Rui Ueyama | 98896ed | 2013-09-12 19:46:53 +0000 | [diff] [blame] | 61 | // Architectures other than i386 is not supported yet. | 
|  | 62 | if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386) { | 
|  | 63 | diagnostics << "Machine type other than x86 is not supported.\n"; | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 64 | return false; | 
| Rui Ueyama | 98896ed | 2013-09-12 19:46:53 +0000 | [diff] [blame] | 65 | } | 
|  | 66 |  | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 67 | _reader = createReaderPECOFF(*this); | 
|  | 68 | _writer = createWriterPECOFF(*this); | 
| Rui Ueyama | 8db1edd | 2013-09-24 23:26:34 +0000 | [diff] [blame] | 69 | return true; | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 70 | } | 
|  | 71 |  | 
| Shankar Easwaran | a96f3a3 | 2013-10-07 02:47:09 +0000 | [diff] [blame] | 72 | std::unique_ptr<File> PECOFFLinkingContext::createEntrySymbolFile() const { | 
| Shankar Easwaran | d26c8e3 | 2013-08-31 05:27:38 +0000 | [diff] [blame] | 73 | if (entrySymbolName().empty()) | 
|  | 74 | return nullptr; | 
|  | 75 | std::unique_ptr<SimpleFile> entryFile( | 
|  | 76 | new SimpleFile(*this, "command line option /entry")); | 
|  | 77 | entryFile->addAtom( | 
|  | 78 | *(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName()))); | 
|  | 79 | return std::move(entryFile); | 
|  | 80 | } | 
| Rui Ueyama | 908606d | 2013-08-09 04:44:15 +0000 | [diff] [blame] | 81 |  | 
| Shankar Easwaran | a96f3a3 | 2013-10-07 02:47:09 +0000 | [diff] [blame] | 82 | std::unique_ptr<File> PECOFFLinkingContext::createUndefinedSymbolFile() const { | 
| Shankar Easwaran | d26c8e3 | 2013-08-31 05:27:38 +0000 | [diff] [blame] | 83 | if (_initialUndefinedSymbols.empty()) | 
|  | 84 | return nullptr; | 
|  | 85 | std::unique_ptr<SimpleFile> undefinedSymFile( | 
|  | 86 | new SimpleFile(*this, "command line option /c (or) /include")); | 
|  | 87 | for (auto undefSymStr : _initialUndefinedSymbols) | 
|  | 88 | undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom( | 
|  | 89 | *undefinedSymFile, undefSymStr))); | 
|  | 90 | return std::move(undefinedSymFile); | 
|  | 91 | } | 
|  | 92 |  | 
| Shankar Easwaran | a96f3a3 | 2013-10-07 02:47:09 +0000 | [diff] [blame] | 93 | bool PECOFFLinkingContext::createImplicitFiles( | 
|  | 94 | std::vector<std::unique_ptr<File> > &) const { | 
|  | 95 | std::unique_ptr<SimpleFileNode> fileNode( | 
|  | 96 | new SimpleFileNode("Implicit Files")); | 
|  | 97 | std::unique_ptr<File> linkerGeneratedSymFile( | 
|  | 98 | new coff::LinkerGeneratedSymbolFile(*this)); | 
|  | 99 | fileNode->appendInputFile(std::move(linkerGeneratedSymFile)); | 
|  | 100 | inputGraph().insertOneElementAt(std::move(fileNode), | 
|  | 101 | InputGraph::Position::END); | 
|  | 102 | return true; | 
| Rui Ueyama | fd50283 | 2013-07-24 22:53:23 +0000 | [diff] [blame] | 103 | } | 
|  | 104 |  | 
| Rui Ueyama | 863931c | 2013-10-26 00:46:57 +0000 | [diff] [blame] | 105 | /// Returns the section name in the resulting executable. | 
|  | 106 | /// | 
|  | 107 | /// Sections in object files are usually output to the executable with the same | 
|  | 108 | /// name, but you can rename by command line option. /merge:from=to makes the | 
|  | 109 | /// linker to combine "from" section contents to "to" section in the | 
|  | 110 | /// executable. We have a mapping for the renaming. This method looks up the | 
|  | 111 | /// table and returns a new section name if renamed. | 
|  | 112 | StringRef | 
|  | 113 | PECOFFLinkingContext::getFinalSectionName(StringRef sectionName) const { | 
|  | 114 | auto it = _renamedSections.find(sectionName); | 
|  | 115 | if (it == _renamedSections.end()) | 
|  | 116 | return sectionName; | 
|  | 117 | return getFinalSectionName(it->second); | 
|  | 118 | } | 
|  | 119 |  | 
|  | 120 | /// Adds a mapping to the section renaming table. This method will be used for | 
|  | 121 | /// /merge command line option. | 
|  | 122 | bool PECOFFLinkingContext::addSectionRenaming(raw_ostream &diagnostics, | 
|  | 123 | StringRef from, StringRef to) { | 
|  | 124 | auto it = _renamedSections.find(from); | 
|  | 125 | if (it != _renamedSections.end()) { | 
|  | 126 | if (it->second == to) | 
|  | 127 | // There's already the same mapping. | 
|  | 128 | return true; | 
|  | 129 | diagnostics << "Section \"" << from << "\" is already mapped to \"" | 
|  | 130 | << it->second << ", so it cannot be mapped to \"" << to << "\"."; | 
|  | 131 | return true; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | // Add a mapping, and check if there's no cycle in the renaming mapping. The | 
|  | 135 | // cycle detection algorithm we use here is naive, but that's OK because the | 
|  | 136 | // number of mapping is usually less than 10. | 
|  | 137 | _renamedSections[from] = to; | 
|  | 138 | for (auto elem : _renamedSections) { | 
|  | 139 | StringRef sectionName = elem.first; | 
|  | 140 | std::set<StringRef> visited; | 
|  | 141 | visited.insert(sectionName); | 
|  | 142 | for (;;) { | 
|  | 143 | auto it = _renamedSections.find(sectionName); | 
|  | 144 | if (it == _renamedSections.end()) | 
|  | 145 | break; | 
|  | 146 | if (visited.count(it->second)) { | 
|  | 147 | diagnostics << "/merge:" << from << "=" << to << " makes a cycle"; | 
|  | 148 | return false; | 
|  | 149 | } | 
|  | 150 | sectionName = it->second; | 
|  | 151 | visited.insert(sectionName); | 
|  | 152 | } | 
|  | 153 | } | 
|  | 154 | return true; | 
|  | 155 | } | 
|  | 156 |  | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 157 | /// Try to find the input library file from the search paths and append it to | 
|  | 158 | /// the input file list. Returns true if the library file is found. | 
| Shankar Easwaran | e44104b | 2013-08-21 22:57:10 +0000 | [diff] [blame] | 159 | StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const { | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 160 | // Current directory always takes precedence over the search paths. | 
| Shankar Easwaran | e44104b | 2013-08-21 22:57:10 +0000 | [diff] [blame] | 161 | if (llvm::sys::path::is_absolute(filename) || llvm::sys::fs::exists(filename)) | 
|  | 162 | return filename; | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 163 | // Iterate over the search paths. | 
|  | 164 | for (StringRef dir : _inputSearchPaths) { | 
|  | 165 | SmallString<128> path = dir; | 
|  | 166 | llvm::sys::path::append(path, filename); | 
| Shankar Easwaran | e44104b | 2013-08-21 22:57:10 +0000 | [diff] [blame] | 167 | if (llvm::sys::fs::exists(path.str())) | 
| Shankar Easwaran | c48b959 | 2013-08-22 15:37:09 +0000 | [diff] [blame] | 168 | return allocateString(path.str()); | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 169 | } | 
| Shankar Easwaran | e44104b | 2013-08-21 22:57:10 +0000 | [diff] [blame] | 170 | return filename; | 
| Rui Ueyama | 2897feb | 2013-07-19 02:18:25 +0000 | [diff] [blame] | 171 | } | 
|  | 172 |  | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 173 | Writer &PECOFFLinkingContext::writer() const { return *_writer; } | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 174 |  | 
| Shankar Easwaran | 53bae6f | 2013-10-26 19:38:31 +0000 | [diff] [blame] | 175 | #define LLD_CASE(name) .Case(#name, llvm::COFF::name) | 
|  | 176 |  | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 177 | ErrorOr<Reference::Kind> | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 178 | PECOFFLinkingContext::relocKindFromString(StringRef str) const { | 
| Shankar Easwaran | 53bae6f | 2013-10-26 19:38:31 +0000 | [diff] [blame] | 179 | int32_t ret = llvm::StringSwitch<int32_t>(str) | 
|  | 180 | LLD_CASE(IMAGE_REL_I386_ABSOLUTE) | 
|  | 181 | LLD_CASE(IMAGE_REL_I386_DIR32) | 
|  | 182 | LLD_CASE(IMAGE_REL_I386_DIR32NB) | 
|  | 183 | LLD_CASE(IMAGE_REL_I386_REL32) | 
|  | 184 | .Default(-1); | 
|  | 185 | if (ret == -1) | 
|  | 186 | return make_error_code(YamlReaderError::illegal_value); | 
|  | 187 | return ret; | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 188 | } | 
|  | 189 |  | 
| Shankar Easwaran | 53bae6f | 2013-10-26 19:38:31 +0000 | [diff] [blame] | 190 | #undef LLD_CASE | 
|  | 191 |  | 
|  | 192 | #define LLD_CASE(name)                                                         \ | 
|  | 193 | case llvm::COFF::name:                                                        \ | 
|  | 194 | return std::string(#name); | 
|  | 195 |  | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 196 | ErrorOr<std::string> | 
| Rui Ueyama | 0ca149f | 2013-08-06 22:31:59 +0000 | [diff] [blame] | 197 | PECOFFLinkingContext::stringFromRelocKind(Reference::Kind kind) const { | 
| Shankar Easwaran | 53bae6f | 2013-10-26 19:38:31 +0000 | [diff] [blame] | 198 | switch (kind) { | 
|  | 199 | LLD_CASE(IMAGE_REL_I386_ABSOLUTE) | 
|  | 200 | LLD_CASE(IMAGE_REL_I386_DIR32) | 
|  | 201 | LLD_CASE(IMAGE_REL_I386_DIR32NB) | 
|  | 202 | LLD_CASE(IMAGE_REL_I386_REL32) | 
|  | 203 | } | 
| Rui Ueyama | c6015f6 | 2013-10-09 00:57:22 +0000 | [diff] [blame] | 204 | return make_error_code(YamlReaderError::illegal_value); | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 205 | } | 
|  | 206 |  | 
| Shankar Easwaran | 2bc2492 | 2013-10-29 05:12:14 +0000 | [diff] [blame^] | 207 | void PECOFFLinkingContext::addPasses(PassManager &pm) { | 
| Rui Ueyama | 991f42c | 2013-06-19 17:46:57 +0000 | [diff] [blame] | 208 | pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass())); | 
| Rui Ueyama | 3ee2bf6 | 2013-09-15 22:33:15 +0000 | [diff] [blame] | 209 | pm.add(std::unique_ptr<Pass>(new pecoff::IdataPass(*this))); | 
| Rui Ueyama | d95a155 | 2013-06-17 16:59:54 +0000 | [diff] [blame] | 210 | pm.add(std::unique_ptr<Pass>(new LayoutPass())); | 
|  | 211 | } | 
| Rui Ueyama | 9e56839 | 2013-05-28 18:13:31 +0000 | [diff] [blame] | 212 | } // end namespace lld |