llvm.org GIT mirror llvm / c501cd4
Switch external cvtres.exe for llvm's own resource library. In this patch, I flip the switch in DriverUtils from using the external cvtres.exe tool to using the Windows Resource library in llvm. I also fixed a bug where .rsrc sections were marked as discardable memory and therefore were placed in the wrong order in the final PE. Furthermore, I modified WindowsResource to write the coff directly to a memory buffer instead of to file, also had it use the machine types already declared in COFF.h instead creating my own enum. Finally, I flipped the switch to allow all unit tests that had previously run only on windows due to a winres dependency to run cross-platform. Reviewers: zturner, ruiu Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D34265 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305592 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Beckmann 2 years ago
3 changed file(s) with 47 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
4444
4545 namespace llvm {
4646
47 class FileOutputBuffer;
48
4947 namespace object {
5048
5149 class WindowsResource;
52
53 enum class Machine { UNKNOWN, ARM, X64, X86 };
5450
5551 class ResourceEntryRef {
5652 public:
184180 std::vector> StringTable;
185181 };
186182
187 Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType,
183 Error writeWindowsResourceCOFF(std::unique_ptr &OutputBuffer,
184 llvm::COFF::MachineTypes MachineType,
188185 const WindowsResourceParser &Parser);
189186
190187 } // namespace object
1919 #include
2020 #include
2121 #include
22
23 using namespace llvm;
2224
2325 namespace llvm {
2426 namespace object {
304306
305307 class WindowsResourceCOFFWriter {
306308 public:
307 WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType,
309 WindowsResourceCOFFWriter(std::unique_ptr &OutputBuffer,
310 COFF::MachineTypes MachineType,
308311 const WindowsResourceParser &Parser, Error &E);
309312 Error write();
310313
322325 void writeDirectoryTree();
323326 void writeDirectoryStringTable();
324327 void writeFirstSectionRelocations();
325 std::unique_ptr Buffer;
326 uint8_t *BufferStart;
328 std::unique_ptr &OutputBuffer;
329 char *BufferStart;
327330 uint64_t CurrentOffset = 0;
328 Machine MachineType;
331 COFF::MachineTypes MachineType;
329332 const WindowsResourceParser::TreeNode &Resources;
330333 const ArrayRef> Data;
331334 uint64_t FileSize;
342345 };
343346
344347 WindowsResourceCOFFWriter::WindowsResourceCOFFWriter(
345 StringRef OutputFile, Machine MachineType,
348 std::unique_ptr &OutputBuffer, COFF::MachineTypes MachineType,
346349 const WindowsResourceParser &Parser, Error &E)
347 : MachineType(MachineType), Resources(Parser.getTree()),
348 Data(Parser.getData()), StringTable(Parser.getStringTable()) {
350 : OutputBuffer(OutputBuffer), MachineType(MachineType),
351 Resources(Parser.getTree()), Data(Parser.getData()),
352 StringTable(Parser.getStringTable()) {
349353 performFileLayout();
350354
351 ErrorOr> BufferOrErr =
352 FileOutputBuffer::create(OutputFile, FileSize);
353 if (!BufferOrErr) {
354 E = errorCodeToError(BufferOrErr.getError());
355 return;
356 }
357
358 Buffer = std::move(*BufferOrErr);
355 OutputBuffer = std::move(MemoryBuffer::getNewMemBuffer(FileSize));
359356 }
360357
361358 void WindowsResourceCOFFWriter::performFileLayout() {
420417 }
421418
422419 Error WindowsResourceCOFFWriter::write() {
423 BufferStart = Buffer->getBufferStart();
420 BufferStart = const_cast(OutputBuffer->getBufferStart());
424421
425422 writeCOFFHeader();
426423 writeFirstSectionHeader();
430427 writeSymbolTable();
431428 writeStringTable();
432429
433 if (auto EC = Buffer->commit()) {
434 return errorCodeToError(EC);
435 }
436
437430 return Error::success();
438431 }
439432
442435 auto *Header =
443436 reinterpret_cast(BufferStart);
444437 switch (MachineType) {
445 case Machine::ARM:
438 case COFF::IMAGE_FILE_MACHINE_ARMNT:
446439 Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
447440 break;
448 case Machine::X64:
441 case COFF::IMAGE_FILE_MACHINE_AMD64:
449442 Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
450443 break;
451 case Machine::X86:
444 case COFF::IMAGE_FILE_MACHINE_I386:
452445 Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386;
453446 break;
454447 default:
480473 SectionOneHeader->Characteristics = llvm::COFF::IMAGE_SCN_ALIGN_1BYTES;
481474 SectionOneHeader->Characteristics +=
482475 llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
483 SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;
476 SectionOneHeader->Characteristics +=
477 llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
484478 SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ;
485479 }
486480
714708 Reloc->VirtualAddress = RelocationAddresses[i];
715709 Reloc->SymbolTableIndex = NextSymbolIndex++;
716710 switch (MachineType) {
717 case Machine::ARM:
711 case COFF::IMAGE_FILE_MACHINE_ARMNT:
718712 Reloc->Type = llvm::COFF::IMAGE_REL_ARM_ADDR32NB;
719713 break;
720 case Machine::X64:
714 case COFF::IMAGE_FILE_MACHINE_AMD64:
721715 Reloc->Type = llvm::COFF::IMAGE_REL_AMD64_ADDR32NB;
722716 break;
723 case Machine::X86:
717 case COFF::IMAGE_FILE_MACHINE_I386:
724718 Reloc->Type = llvm::COFF::IMAGE_REL_I386_DIR32NB;
725719 break;
726720 default:
730724 }
731725 }
732726
733 Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType,
727 Error writeWindowsResourceCOFF(std::unique_ptr &OutputBuffer,
728 COFF::MachineTypes MachineType,
734729 const WindowsResourceParser &Parser) {
735730 Error E = Error::success();
736 WindowsResourceCOFFWriter Writer(OutputFile, MachineType, Parser, E);
731 WindowsResourceCOFFWriter Writer(OutputBuffer, MachineType, Parser, E);
737732 if (E)
738733 return E;
739734 return Writer.write();
113113
114114 bool Verbose = InputArgs.hasArg(OPT_VERBOSE);
115115
116 Machine MachineType;
116 COFF::MachineTypes MachineType;
117117
118118 if (InputArgs.hasArg(OPT_MACHINE)) {
119119 std::string MachineString = InputArgs.getLastArgValue(OPT_MACHINE).upper();
120 MachineType = StringSwitch(MachineString)
121 .Case("ARM", Machine::ARM)
122 .Case("X64", Machine::X64)
123 .Case("X86", Machine::X86)
124 .Default(Machine::UNKNOWN);
125 if (MachineType == Machine::UNKNOWN)
120 MachineType = StringSwitch(MachineString)
121 .Case("ARM", COFF::IMAGE_FILE_MACHINE_ARMNT)
122 .Case("X64", COFF::IMAGE_FILE_MACHINE_AMD64)
123 .Case("X86", COFF::IMAGE_FILE_MACHINE_I386)
124 .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
125 if (MachineType == COFF::IMAGE_FILE_MACHINE_UNKNOWN)
126126 reportError("Unsupported machine architecture");
127127 } else {
128128 if (Verbose)
129129 outs() << "Machine architecture not specified; assumed X64.\n";
130 MachineType = Machine::X64;
130 MachineType = COFF::IMAGE_FILE_MACHINE_AMD64;
131131 }
132132
133133 std::vector InputFiles = InputArgs.getAllArgValues(OPT_INPUT);
148148 if (Verbose) {
149149 outs() << "Machine: ";
150150 switch (MachineType) {
151 case Machine::ARM:
151 case COFF::IMAGE_FILE_MACHINE_ARMNT:
152152 outs() << "ARM\n";
153153 break;
154 case Machine::X86:
154 case COFF::IMAGE_FILE_MACHINE_I386:
155155 outs() << "X86\n";
156156 break;
157157 default:
195195 Parser.printTree(errs());
196196 }
197197
198 error(
199 llvm::object::writeWindowsResourceCOFF(OutputFile, MachineType, Parser));
198 std::unique_ptr OutputBuffer;
199 error(llvm::object::writeWindowsResourceCOFF(OutputBuffer, MachineType,
200 Parser));
201 auto FileOrErr =
202 FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize());
203 if (!FileOrErr)
204 reportError(OutputFile, FileOrErr.getError());
205 std::unique_ptr FileBuffer = std::move(*FileOrErr);
206 std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
207 FileBuffer->getBufferStart());
208 error(FileBuffer->commit());
200209
201210 if (Verbose) {
202211 Expected> BinaryOrErr =