|
19 | 19 | #include "llvm/ADT/Optional.h"
|
20 | 20 | #include "llvm/ADT/StringSwitch.h"
|
21 | 21 | #include "llvm/Object/ArchiveWriter.h"
|
| 22 | +#include "llvm/Object/COFFImportFile.h" |
| 23 | +#include "llvm/Object/COFFModuleDefinition.h" |
22 | 24 | #include "llvm/Option/Arg.h"
|
23 | 25 | #include "llvm/Option/ArgList.h"
|
24 | 26 | #include "llvm/Option/Option.h"
|
|
35 | 37 | #include <future>
|
36 | 38 |
|
37 | 39 | using namespace llvm;
|
| 40 | +using namespace llvm::object; |
38 | 41 | using namespace llvm::COFF;
|
39 | 42 | using llvm::sys::Process;
|
40 | 43 | using llvm::sys::fs::file_magic;
|
@@ -419,6 +422,85 @@ static std::string getMapFile(const opt::InputArgList &Args) {
|
419 | 422 | return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str();
|
420 | 423 | }
|
421 | 424 |
|
| 425 | +static std::string getImplibPath() { |
| 426 | + if (!Config->Implib.empty()) |
| 427 | + return Config->Implib; |
| 428 | + SmallString<128> Out = StringRef(Config->OutputFile); |
| 429 | + sys::path::replace_extension(Out, ".lib"); |
| 430 | + return Out.str(); |
| 431 | +} |
| 432 | + |
| 433 | +std::vector<COFFShortExport> createCOFFShortExportFromConfig() { |
| 434 | + std::vector<COFFShortExport> Exports; |
| 435 | + for (Export &E1 : Config->Exports) { |
| 436 | + COFFShortExport E2; |
| 437 | + // Use SymbolName, which will have any stdcall or fastcall qualifiers. |
| 438 | + E2.Name = E1.SymbolName; |
| 439 | + E2.ExtName = E1.ExtName; |
| 440 | + E2.Ordinal = E1.Ordinal; |
| 441 | + E2.Noname = E1.Noname; |
| 442 | + E2.Data = E1.Data; |
| 443 | + E2.Private = E1.Private; |
| 444 | + E2.Constant = E1.Constant; |
| 445 | + Exports.push_back(E2); |
| 446 | + } |
| 447 | + return Exports; |
| 448 | +} |
| 449 | + |
| 450 | +static void createImportLibrary() { |
| 451 | + std::vector<COFFShortExport> Exports = createCOFFShortExportFromConfig(); |
| 452 | + std::string DLLName = sys::path::filename(Config->OutputFile); |
| 453 | + std::string Path = getImplibPath(); |
| 454 | + writeImportLibrary(DLLName, Path, Exports, Config->Machine); |
| 455 | +} |
| 456 | + |
| 457 | +static void parseModuleDefs(StringRef Path) { |
| 458 | + std::unique_ptr<MemoryBuffer> MB = check( |
| 459 | + MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); |
| 460 | + MemoryBufferRef MBRef = MB->getMemBufferRef(); |
| 461 | + |
| 462 | + Expected<COFFModuleDefinition> Def = |
| 463 | + parseCOFFModuleDefinition(MBRef, Config->Machine); |
| 464 | + if (!Def) |
| 465 | + fatal(errorToErrorCode(Def.takeError()).message()); |
| 466 | + |
| 467 | + COFFModuleDefinition &M = *Def; |
| 468 | + if (Config->OutputFile.empty()) |
| 469 | + Config->OutputFile = Saver.save(M.OutputFile); |
| 470 | + |
| 471 | + if (M.ImageBase) |
| 472 | + Config->ImageBase = M.ImageBase; |
| 473 | + if (M.StackReserve) |
| 474 | + Config->StackReserve = M.StackReserve; |
| 475 | + if (M.StackCommit) |
| 476 | + Config->StackCommit = M.StackCommit; |
| 477 | + if (M.HeapReserve) |
| 478 | + Config->HeapReserve = M.HeapReserve; |
| 479 | + if (M.HeapCommit) |
| 480 | + Config->HeapCommit = M.HeapCommit; |
| 481 | + if (M.MajorImageVersion) |
| 482 | + Config->MajorImageVersion = M.MajorImageVersion; |
| 483 | + if (M.MinorImageVersion) |
| 484 | + Config->MinorImageVersion = M.MinorImageVersion; |
| 485 | + if (M.MajorOSVersion) |
| 486 | + Config->MajorOSVersion = M.MajorOSVersion; |
| 487 | + if (M.MinorOSVersion) |
| 488 | + Config->MinorOSVersion = M.MinorOSVersion; |
| 489 | + |
| 490 | + for (COFFShortExport E1 : M.Exports) { |
| 491 | + Export E2; |
| 492 | + E2.Name = Saver.save(E1.Name); |
| 493 | + if (E1.isWeak()) |
| 494 | + E2.ExtName = Saver.save(E1.ExtName); |
| 495 | + E2.Ordinal = E1.Ordinal; |
| 496 | + E2.Noname = E1.Noname; |
| 497 | + E2.Data = E1.Data; |
| 498 | + E2.Private = E1.Private; |
| 499 | + E2.Constant = E1.Constant; |
| 500 | + Config->Exports.push_back(E2); |
| 501 | + } |
| 502 | +} |
| 503 | + |
422 | 504 | std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) {
|
423 | 505 | std::vector<MemoryBufferRef> V;
|
424 | 506 | Error Err = Error::success();
|
@@ -912,9 +994,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
912 | 994 | // Handle /def
|
913 | 995 | if (auto *Arg = Args.getLastArg(OPT_deffile)) {
|
914 | 996 | // parseModuleDefs mutates Config object.
|
915 |
| - parseModuleDefs( |
916 |
| - takeBuffer(check(MemoryBuffer::getFile(Arg->getValue()), |
917 |
| - Twine("could not open ") + Arg->getValue()))); |
| 997 | + parseModuleDefs(Arg->getValue()); |
918 | 998 | }
|
919 | 999 |
|
920 | 1000 | // Handle /delayload
|
@@ -1034,7 +1114,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
1034 | 1114 | // need to create a .lib file.
|
1035 | 1115 | if (!Config->Exports.empty() || Config->DLL) {
|
1036 | 1116 | fixupExports();
|
1037 |
| - writeImportLibrary(); |
| 1117 | + createImportLibrary(); |
1038 | 1118 | assignExportOrdinals();
|
1039 | 1119 | }
|
1040 | 1120 |
|
|
0 commit comments