brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 8ef8d6e Raw
233 lines · cpp
1//===- llvm-cvtres.cpp - Serialize .res files into .obj ---------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Serialize .res files into .obj files.  This is intended to be a10// platform-independent port of Microsoft's cvtres.exe.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/BinaryFormat/Magic.h"15#include "llvm/Object/Binary.h"16#include "llvm/Object/WindowsMachineFlag.h"17#include "llvm/Object/WindowsResource.h"18#include "llvm/Option/Arg.h"19#include "llvm/Option/ArgList.h"20#include "llvm/Option/Option.h"21#include "llvm/Support/BinaryStreamError.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/InitLLVM.h"24#include "llvm/Support/Path.h"25#include "llvm/Support/PrettyStackTrace.h"26#include "llvm/Support/Process.h"27#include "llvm/Support/ScopedPrinter.h"28#include "llvm/Support/Signals.h"29#include "llvm/Support/raw_ostream.h"30 31#include <system_error>32 33using namespace llvm;34using namespace object;35 36namespace {37 38enum ID {39  OPT_INVALID = 0, // This is not an option ID.40#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),41#include "Opts.inc"42#undef OPTION43};44 45#define OPTTABLE_STR_TABLE_CODE46#include "Opts.inc"47#undef OPTTABLE_STR_TABLE_CODE48 49#define OPTTABLE_PREFIXES_TABLE_CODE50#include "Opts.inc"51#undef OPTTABLE_PREFIXES_TABLE_CODE52 53using namespace llvm::opt;54static constexpr opt::OptTable::Info InfoTable[] = {55#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),56#include "Opts.inc"57#undef OPTION58};59 60class CvtResOptTable : public opt::GenericOptTable {61public:62  CvtResOptTable()63      : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,64                             true) {}65};66}67 68[[noreturn]] static void reportError(Twine Msg) {69  errs() << Msg;70  exit(1);71}72 73static void reportError(StringRef Input, std::error_code EC) {74  reportError(Twine(Input) + ": " + EC.message() + ".\n");75}76 77static void error(StringRef Input, Error EC) {78  if (!EC)79    return;80  handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) {81    reportError(Twine(Input) + ": " + EI.message() + ".\n");82  });83}84 85static void error(Error EC) {86  if (!EC)87    return;88  handleAllErrors(std::move(EC),89                  [&](const ErrorInfoBase &EI) { reportError(EI.message()); });90}91 92static uint32_t getTime() {93  std::time_t Now = time(nullptr);94  if (Now < 0 || !isUInt<32>(Now))95    return UINT32_MAX;96  return static_cast<uint32_t>(Now);97}98 99template <typename T> T error(Expected<T> EC) {100  if (!EC)101    error(EC.takeError());102  return std::move(EC.get());103}104 105template <typename T> T error(StringRef Input, Expected<T> EC) {106  if (!EC)107    error(Input, EC.takeError());108  return std::move(EC.get());109}110 111template <typename T> T error(StringRef Input, ErrorOr<T> &&EC) {112  return error(Input, errorOrToExpected(std::move(EC)));113}114 115int main(int Argc, const char **Argv) {116  InitLLVM X(Argc, Argv);117 118  CvtResOptTable T;119  unsigned MAI, MAC;120  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);121  opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);122 123  if (InputArgs.hasArg(OPT_HELP)) {124    T.printHelp(outs(), "llvm-cvtres [options] file...", "Resource Converter");125    return 0;126  }127 128  bool Verbose = InputArgs.hasArg(OPT_VERBOSE);129 130  COFF::MachineTypes MachineType;131 132  if (opt::Arg *Arg = InputArgs.getLastArg(OPT_MACHINE)) {133    MachineType = getMachineType(Arg->getValue());134    if (MachineType == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {135      reportError(Twine("Unsupported machine architecture ") + Arg->getValue() +136                  "\n");137    }138  } else {139    if (Verbose)140      outs() << "Machine architecture not specified; assumed X64.\n";141    MachineType = COFF::IMAGE_FILE_MACHINE_AMD64;142  }143 144  std::vector<std::string> InputFiles = InputArgs.getAllArgValues(OPT_INPUT);145 146  if (InputFiles.size() == 0) {147    reportError("No input file specified.\n");148  }149 150  SmallString<128> OutputFile;151 152  if (opt::Arg *Arg = InputArgs.getLastArg(OPT_OUT)) {153    OutputFile = Arg->getValue();154  } else {155    OutputFile = sys::path::filename(StringRef(InputFiles[0]));156    sys::path::replace_extension(OutputFile, ".obj");157  }158 159  uint32_t DateTimeStamp;160  if (llvm::opt::Arg *Arg = InputArgs.getLastArg(OPT_TIMESTAMP)) {161    StringRef Value(Arg->getValue());162    if (Value.getAsInteger(0, DateTimeStamp))163      reportError(Twine("invalid timestamp: ") + Value +164            ".  Expected 32-bit integer\n");165  } else {166    DateTimeStamp = getTime();167  }168 169  if (Verbose)170    outs() << "Machine: " << machineToStr(MachineType) << '\n';171 172  WindowsResourceParser Parser;173 174  for (const auto &File : InputFiles) {175    std::unique_ptr<MemoryBuffer> Buffer = error(176        File, MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,177                                           /*RequiresNullTerminator=*/false));178    file_magic Type = identify_magic(Buffer->getMemBufferRef().getBuffer());179    if (Type != file_magic::windows_resource)180      reportError(File + ": unrecognized file format.\n");181    std::unique_ptr<WindowsResource> Binary = error(182        File,183        WindowsResource::createWindowsResource(Buffer->getMemBufferRef()));184 185    WindowsResource *RF = Binary.get();186 187    if (Verbose) {188      int EntryNumber = 0;189      ResourceEntryRef Entry = error(RF->getHeadEntry());190      bool End = false;191      while (!End) {192        error(Entry.moveNext(End));193        EntryNumber++;194      }195      outs() << "Number of resources: " << EntryNumber << "\n";196    }197 198    std::vector<std::string> Duplicates;199    error(Parser.parse(RF, Duplicates));200    for (const auto& DupeDiag : Duplicates)201      reportError(DupeDiag);202  }203 204  if (Verbose) {205    Parser.printTree(outs());206  }207 208  std::unique_ptr<MemoryBuffer> OutputBuffer =209      error(llvm::object::writeWindowsResourceCOFF(MachineType, Parser,210                                                   DateTimeStamp));211  auto FileOrErr =212      FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize());213  if (!FileOrErr)214    reportError(OutputFile, errorToErrorCode(FileOrErr.takeError()));215  std::unique_ptr<FileOutputBuffer> FileBuffer = std::move(*FileOrErr);216  std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),217            FileBuffer->getBufferStart());218  error(FileBuffer->commit());219 220  if (Verbose) {221    std::unique_ptr<MemoryBuffer> Buffer =222        error(OutputFile,223              MemoryBuffer::getFileOrSTDIN(OutputFile, /*IsText=*/false,224                                           /*RequiresNullTerminator=*/false));225 226    ScopedPrinter W(errs());227    W.printBinaryBlock("Output File Raw Data",228                       Buffer->getMemBufferRef().getBuffer());229  }230 231  return 0;232}233