llvm-project

Форк
0
635 строк · 22.4 Кб
1
//===- llvm-ifs.cpp -------------------------------------------------------===//
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-exception
6
//
7
//===-----------------------------------------------------------------------===/
8

9
#include "ErrorCollector.h"
10
#include "llvm/ADT/StringRef.h"
11
#include "llvm/ADT/StringSwitch.h"
12
#include "llvm/BinaryFormat/ELF.h"
13
#include "llvm/InterfaceStub/ELFObjHandler.h"
14
#include "llvm/InterfaceStub/IFSHandler.h"
15
#include "llvm/InterfaceStub/IFSStub.h"
16
#include "llvm/ObjectYAML/yaml2obj.h"
17
#include "llvm/Option/Arg.h"
18
#include "llvm/Option/ArgList.h"
19
#include "llvm/Option/Option.h"
20
#include "llvm/Support/CommandLine.h"
21
#include "llvm/Support/Debug.h"
22
#include "llvm/Support/Errc.h"
23
#include "llvm/Support/Error.h"
24
#include "llvm/Support/FileOutputBuffer.h"
25
#include "llvm/Support/LLVMDriver.h"
26
#include "llvm/Support/MemoryBuffer.h"
27
#include "llvm/Support/Path.h"
28
#include "llvm/Support/VersionTuple.h"
29
#include "llvm/Support/WithColor.h"
30
#include "llvm/Support/YAMLTraits.h"
31
#include "llvm/Support/raw_ostream.h"
32
#include "llvm/TargetParser/Triple.h"
33
#include "llvm/TextAPI/InterfaceFile.h"
34
#include "llvm/TextAPI/TextAPIReader.h"
35
#include "llvm/TextAPI/TextAPIWriter.h"
36
#include <optional>
37
#include <set>
38
#include <string>
39
#include <vector>
40

41
using namespace llvm;
42
using namespace llvm::yaml;
43
using namespace llvm::MachO;
44
using namespace llvm::ifs;
45

46
#define DEBUG_TYPE "llvm-ifs"
47

48
namespace {
49
const VersionTuple IfsVersionCurrent(3, 0);
50

51
enum class FileFormat { IFS, ELF, TBD };
52
} // end anonymous namespace
53

54
using namespace llvm::opt;
55
enum ID {
56
  OPT_INVALID = 0, // This is not an option ID.
57
#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
58
#include "Opts.inc"
59
#undef OPTION
60
};
61

62
#define PREFIX(NAME, VALUE)                                                    \
63
  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
64
  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
65
                                                std::size(NAME##_init) - 1);
66
#include "Opts.inc"
67
#undef PREFIX
68

69
static constexpr opt::OptTable::Info InfoTable[] = {
70
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
71
#include "Opts.inc"
72
#undef OPTION
73
};
74

75
class IFSOptTable : public opt::GenericOptTable {
76
public:
77
  IFSOptTable() : opt::GenericOptTable(InfoTable) {
78
    setGroupedShortOptions(true);
79
  }
80
};
81

82
struct DriverConfig {
83
  std::vector<std::string> InputFilePaths;
84

85
  std::optional<FileFormat> InputFormat;
86
  std::optional<FileFormat> OutputFormat;
87

88
  std::optional<std::string> HintIfsTarget;
89
  std::optional<std::string> OptTargetTriple;
90
  std::optional<IFSArch> OverrideArch;
91
  std::optional<IFSBitWidthType> OverrideBitWidth;
92
  std::optional<IFSEndiannessType> OverrideEndianness;
93

94
  bool StripIfsArch = false;
95
  bool StripIfsBitwidth = false;
96
  bool StripIfsEndianness = false;
97
  bool StripIfsTarget = false;
98
  bool StripNeeded = false;
99
  bool StripSize = false;
100
  bool StripUndefined = false;
101

102
  std::vector<std::string> Exclude;
103

104
  std::optional<std::string> SoName;
105

106
  std::optional<std::string> Output;
107
  std::optional<std::string> OutputElf;
108
  std::optional<std::string> OutputIfs;
109
  std::optional<std::string> OutputTbd;
110

111
  bool WriteIfChanged = false;
112
};
113

114
static std::string getTypeName(IFSSymbolType Type) {
115
  switch (Type) {
116
  case IFSSymbolType::NoType:
117
    return "NoType";
118
  case IFSSymbolType::Func:
119
    return "Func";
120
  case IFSSymbolType::Object:
121
    return "Object";
122
  case IFSSymbolType::TLS:
123
    return "TLS";
124
  case IFSSymbolType::Unknown:
125
    return "Unknown";
126
  }
127
  llvm_unreachable("Unexpected ifs symbol type.");
128
}
129

130
static Expected<std::unique_ptr<IFSStub>>
131
readInputFile(std::optional<FileFormat> &InputFormat, StringRef FilePath) {
132
  // Read in file.
133
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
134
      MemoryBuffer::getFileOrSTDIN(FilePath, /*IsText=*/true);
135
  if (!BufOrError)
136
    return createStringError(BufOrError.getError(), "Could not open `%s`",
137
                             FilePath.data());
138

139
  std::unique_ptr<MemoryBuffer> FileReadBuffer = std::move(*BufOrError);
140
  ErrorCollector EC(/*UseFatalErrors=*/false);
141

142
  // First try to read as a binary (fails fast if not binary).
143
  if (!InputFormat || *InputFormat == FileFormat::ELF) {
144
    Expected<std::unique_ptr<IFSStub>> StubFromELF =
145
        readELFFile(FileReadBuffer->getMemBufferRef());
146
    if (StubFromELF) {
147
      InputFormat = FileFormat::ELF;
148
      (*StubFromELF)->IfsVersion = IfsVersionCurrent;
149
      return std::move(*StubFromELF);
150
    }
151
    EC.addError(StubFromELF.takeError(), "BinaryRead");
152
  }
153

154
  // Fall back to reading as a ifs.
155
  if (!InputFormat || *InputFormat == FileFormat::IFS) {
156
    Expected<std::unique_ptr<IFSStub>> StubFromIFS =
157
        readIFSFromBuffer(FileReadBuffer->getBuffer());
158
    if (StubFromIFS) {
159
      InputFormat = FileFormat::IFS;
160
      if ((*StubFromIFS)->IfsVersion > IfsVersionCurrent)
161
        EC.addError(
162
            createStringError(errc::not_supported,
163
                              "IFS version " +
164
                                  (*StubFromIFS)->IfsVersion.getAsString() +
165
                                  " is unsupported."),
166
            "ReadInputFile");
167
      else
168
        return std::move(*StubFromIFS);
169
    } else {
170
      EC.addError(StubFromIFS.takeError(), "YamlParse");
171
    }
172
  }
173

174
  // If both readers fail, build a new error that includes all information.
175
  EC.addError(createStringError(errc::not_supported,
176
                                "No file readers succeeded reading `%s` "
177
                                "(unsupported/malformed file?)",
178
                                FilePath.data()),
179
              "ReadInputFile");
180
  EC.escalateToFatal();
181
  return EC.makeError();
182
}
183

184
static int writeTbdStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
185
                        const StringRef Format, raw_ostream &Out) {
186

187
  auto PlatformTypeOrError =
188
      [](const llvm::Triple &T) -> llvm::Expected<llvm::MachO::PlatformType> {
189
    if (T.isMacOSX())
190
      return llvm::MachO::PLATFORM_MACOS;
191
    if (T.isTvOS())
192
      return llvm::MachO::PLATFORM_TVOS;
193
    if (T.isWatchOS())
194
      return llvm::MachO::PLATFORM_WATCHOS;
195
    // Note: put isiOS last because tvOS and watchOS are also iOS according
196
    // to the Triple.
197
    if (T.isiOS())
198
      return llvm::MachO::PLATFORM_IOS;
199

200
    return createStringError(errc::not_supported, "Invalid Platform.\n");
201
  }(T);
202

203
  if (!PlatformTypeOrError)
204
    return -1;
205

206
  PlatformType Plat = PlatformTypeOrError.get();
207
  TargetList Targets({Target(llvm::MachO::mapToArchitecture(T), Plat)});
208

209
  InterfaceFile File;
210
  File.setFileType(FileType::TBD_V3); // Only supporting v3 for now.
211
  File.addTargets(Targets);
212

213
  for (const auto &Symbol : Symbols) {
214
    auto Name = Symbol.Name;
215
    auto Kind = EncodeKind::GlobalSymbol;
216
    switch (Symbol.Type) {
217
    default:
218
    case IFSSymbolType::NoType:
219
      Kind = EncodeKind::GlobalSymbol;
220
      break;
221
    case IFSSymbolType::Object:
222
      Kind = EncodeKind::GlobalSymbol;
223
      break;
224
    case IFSSymbolType::Func:
225
      Kind = EncodeKind::GlobalSymbol;
226
      break;
227
    }
228
    if (Symbol.Weak)
229
      File.addSymbol(Kind, Name, Targets, SymbolFlags::WeakDefined);
230
    else
231
      File.addSymbol(Kind, Name, Targets);
232
  }
233

234
  SmallString<4096> Buffer;
235
  raw_svector_ostream OS(Buffer);
236
  if (Error Result = TextAPIWriter::writeToStream(OS, File))
237
    return -1;
238
  Out << OS.str();
239
  return 0;
240
}
241

242
static void fatalError(Error Err) {
243
  WithColor::defaultErrorHandler(std::move(Err));
244
  exit(1);
245
}
246

247
static void fatalError(Twine T) {
248
  WithColor::error() << T.str() << '\n';
249
  exit(1);
250
}
251

252
/// writeIFS() writes a Text-Based ELF stub to a file using the latest version
253
/// of the YAML parser.
254
static Error writeIFS(StringRef FilePath, IFSStub &Stub, bool WriteIfChanged) {
255
  // Write IFS to memory first.
256
  std::string IFSStr;
257
  raw_string_ostream OutStr(IFSStr);
258
  Error YAMLErr = writeIFSToOutputStream(OutStr, Stub);
259
  if (YAMLErr)
260
    return YAMLErr;
261
  OutStr.flush();
262

263
  if (WriteIfChanged) {
264
    if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
265
            MemoryBuffer::getFile(FilePath)) {
266
      // Compare IFS output with the existing IFS file. If unchanged, avoid
267
      // changing the file.
268
      if ((*BufOrError)->getBuffer() == IFSStr)
269
        return Error::success();
270
    }
271
  }
272
  // Open IFS file for writing.
273
  std::error_code SysErr;
274
  raw_fd_ostream Out(FilePath, SysErr);
275
  if (SysErr)
276
    return createStringError(SysErr, "Couldn't open `%s` for writing",
277
                             FilePath.data());
278
  Out << IFSStr;
279
  return Error::success();
280
}
281

282
static DriverConfig parseArgs(int argc, char *const *argv) {
283
  BumpPtrAllocator A;
284
  StringSaver Saver(A);
285
  IFSOptTable Tbl;
286
  StringRef ToolName = argv[0];
287
  llvm::opt::InputArgList Args = Tbl.parseArgs(
288
      argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { fatalError(Msg); });
289
  if (Args.hasArg(OPT_help)) {
290
    Tbl.printHelp(llvm::outs(),
291
                  (Twine(ToolName) + " <input_file> <output_file> [options]")
292
                      .str()
293
                      .c_str(),
294
                  "shared object stubbing tool");
295
    std::exit(0);
296
  }
297
  if (Args.hasArg(OPT_version)) {
298
    llvm::outs() << ToolName << '\n';
299
    cl::PrintVersionMessage();
300
    std::exit(0);
301
  }
302

303
  DriverConfig Config;
304
  for (const opt::Arg *A : Args.filtered(OPT_INPUT))
305
    Config.InputFilePaths.push_back(A->getValue());
306
  if (const opt::Arg *A = Args.getLastArg(OPT_input_format_EQ)) {
307
    Config.InputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
308
                             .Case("IFS", FileFormat::IFS)
309
                             .Case("ELF", FileFormat::ELF)
310
                             .Default(std::nullopt);
311
    if (!Config.InputFormat)
312
      fatalError(Twine("invalid argument '") + A->getValue());
313
  }
314

315
  auto OptionNotFound = [ToolName](StringRef FlagName, StringRef OptionName) {
316
    fatalError(Twine(ToolName) + ": for the " + FlagName +
317
               " option: Cannot find option named '" + OptionName + "'!");
318
  };
319
  if (const opt::Arg *A = Args.getLastArg(OPT_output_format_EQ)) {
320
    Config.OutputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
321
                              .Case("IFS", FileFormat::IFS)
322
                              .Case("ELF", FileFormat::ELF)
323
                              .Case("TBD", FileFormat::TBD)
324
                              .Default(std::nullopt);
325
    if (!Config.OutputFormat)
326
      OptionNotFound("--output-format", A->getValue());
327
  }
328
  if (const opt::Arg *A = Args.getLastArg(OPT_arch_EQ)) {
329
    uint16_t eMachine = ELF::convertArchNameToEMachine(A->getValue());
330
    if (eMachine == ELF::EM_NONE) {
331
      fatalError(Twine("unknown arch '") + A->getValue() + "'");
332
    }
333
    Config.OverrideArch = eMachine;
334
  }
335
  if (const opt::Arg *A = Args.getLastArg(OPT_bitwidth_EQ)) {
336
    size_t Width;
337
    llvm::StringRef S(A->getValue());
338
    if (!S.getAsInteger<size_t>(10, Width) || Width == 64 || Width == 32)
339
      Config.OverrideBitWidth =
340
          Width == 64 ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
341
    else
342
      OptionNotFound("--bitwidth", A->getValue());
343
  }
344
  if (const opt::Arg *A = Args.getLastArg(OPT_endianness_EQ)) {
345
    Config.OverrideEndianness =
346
        StringSwitch<std::optional<IFSEndiannessType>>(A->getValue())
347
            .Case("little", IFSEndiannessType::Little)
348
            .Case("big", IFSEndiannessType::Big)
349
            .Default(std::nullopt);
350
    if (!Config.OverrideEndianness)
351
      OptionNotFound("--endianness", A->getValue());
352
  }
353
  if (const opt::Arg *A = Args.getLastArg(OPT_target_EQ))
354
    Config.OptTargetTriple = A->getValue();
355
  if (const opt::Arg *A = Args.getLastArg(OPT_hint_ifs_target_EQ))
356
    Config.HintIfsTarget = A->getValue();
357

358
  Config.StripIfsArch = Args.hasArg(OPT_strip_ifs_arch);
359
  Config.StripIfsBitwidth = Args.hasArg(OPT_strip_ifs_bitwidth);
360
  Config.StripIfsEndianness = Args.hasArg(OPT_strip_ifs_endianness);
361
  Config.StripIfsTarget = Args.hasArg(OPT_strip_ifs_target);
362
  Config.StripUndefined = Args.hasArg(OPT_strip_undefined);
363
  Config.StripNeeded = Args.hasArg(OPT_strip_needed);
364
  Config.StripSize = Args.hasArg(OPT_strip_size);
365

366
  for (const opt::Arg *A : Args.filtered(OPT_exclude_EQ))
367
    Config.Exclude.push_back(A->getValue());
368
  if (const opt::Arg *A = Args.getLastArg(OPT_soname_EQ))
369
    Config.SoName = A->getValue();
370
  if (const opt::Arg *A = Args.getLastArg(OPT_output_EQ))
371
    Config.Output = A->getValue();
372
  if (const opt::Arg *A = Args.getLastArg(OPT_output_elf_EQ))
373
    Config.OutputElf = A->getValue();
374
  if (const opt::Arg *A = Args.getLastArg(OPT_output_ifs_EQ))
375
    Config.OutputIfs = A->getValue();
376
  if (const opt::Arg *A = Args.getLastArg(OPT_output_tbd_EQ))
377
    Config.OutputTbd = A->getValue();
378
  Config.WriteIfChanged = Args.hasArg(OPT_write_if_changed);
379
  return Config;
380
}
381

382
int llvm_ifs_main(int argc, char **argv, const llvm::ToolContext &) {
383
  DriverConfig Config = parseArgs(argc, argv);
384

385
  if (Config.InputFilePaths.empty())
386
    Config.InputFilePaths.push_back("-");
387

388
  // If input files are more than one, they can only be IFS files.
389
  if (Config.InputFilePaths.size() > 1)
390
    Config.InputFormat = FileFormat::IFS;
391

392
  // Attempt to merge input.
393
  IFSStub Stub;
394
  std::map<std::string, IFSSymbol> SymbolMap;
395
  std::string PreviousInputFilePath;
396
  for (const std::string &InputFilePath : Config.InputFilePaths) {
397
    Expected<std::unique_ptr<IFSStub>> StubOrErr =
398
        readInputFile(Config.InputFormat, InputFilePath);
399
    if (!StubOrErr)
400
      fatalError(StubOrErr.takeError());
401

402
    std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
403
    if (PreviousInputFilePath.empty()) {
404
      Stub.IfsVersion = TargetStub->IfsVersion;
405
      Stub.Target = TargetStub->Target;
406
      Stub.SoName = TargetStub->SoName;
407
      Stub.NeededLibs = TargetStub->NeededLibs;
408
    } else {
409
      if (Stub.IfsVersion != TargetStub->IfsVersion) {
410
        if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
411
          WithColor::error()
412
              << "Interface Stub: IfsVersion Mismatch."
413
              << "\nFilenames: " << PreviousInputFilePath << " "
414
              << InputFilePath << "\nIfsVersion Values: " << Stub.IfsVersion
415
              << " " << TargetStub->IfsVersion << "\n";
416
          return -1;
417
        }
418
        if (TargetStub->IfsVersion > Stub.IfsVersion)
419
          Stub.IfsVersion = TargetStub->IfsVersion;
420
      }
421
      if (Stub.Target != TargetStub->Target && !TargetStub->Target.empty()) {
422
        WithColor::error() << "Interface Stub: Target Mismatch."
423
                           << "\nFilenames: " << PreviousInputFilePath << " "
424
                           << InputFilePath;
425
        return -1;
426
      }
427
      if (Stub.SoName != TargetStub->SoName) {
428
        WithColor::error() << "Interface Stub: SoName Mismatch."
429
                           << "\nFilenames: " << PreviousInputFilePath << " "
430
                           << InputFilePath
431
                           << "\nSoName Values: " << Stub.SoName << " "
432
                           << TargetStub->SoName << "\n";
433
        return -1;
434
      }
435
      if (Stub.NeededLibs != TargetStub->NeededLibs) {
436
        WithColor::error() << "Interface Stub: NeededLibs Mismatch."
437
                           << "\nFilenames: " << PreviousInputFilePath << " "
438
                           << InputFilePath << "\n";
439
        return -1;
440
      }
441
    }
442

443
    for (auto Symbol : TargetStub->Symbols) {
444
      auto SI = SymbolMap.find(Symbol.Name);
445
      if (SI == SymbolMap.end()) {
446
        SymbolMap.insert(
447
            std::pair<std::string, IFSSymbol>(Symbol.Name, Symbol));
448
        continue;
449
      }
450

451
      assert(Symbol.Name == SI->second.Name && "Symbol Names Must Match.");
452

453
      // Check conflicts:
454
      if (Symbol.Type != SI->second.Type) {
455
        WithColor::error() << "Interface Stub: Type Mismatch for "
456
                           << Symbol.Name << ".\nFilename: " << InputFilePath
457
                           << "\nType Values: " << getTypeName(SI->second.Type)
458
                           << " " << getTypeName(Symbol.Type) << "\n";
459

460
        return -1;
461
      }
462
      if (Symbol.Size != SI->second.Size) {
463
        WithColor::error() << "Interface Stub: Size Mismatch for "
464
                           << Symbol.Name << ".\nFilename: " << InputFilePath
465
                           << "\nSize Values: " << SI->second.Size << " "
466
                           << Symbol.Size << "\n";
467

468
        return -1;
469
      }
470
      if (Symbol.Weak != SI->second.Weak) {
471
        Symbol.Weak = false;
472
        continue;
473
      }
474
      // TODO: Not checking Warning. Will be dropped.
475
    }
476

477
    PreviousInputFilePath = InputFilePath;
478
  }
479

480
  if (Stub.IfsVersion != IfsVersionCurrent)
481
    if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
482
      WithColor::error() << "Interface Stub: Bad IfsVersion: "
483
                         << Stub.IfsVersion << ", llvm-ifs supported version: "
484
                         << IfsVersionCurrent << ".\n";
485
      return -1;
486
    }
487

488
  for (auto &Entry : SymbolMap)
489
    Stub.Symbols.push_back(Entry.second);
490

491
  // Change SoName before emitting stubs.
492
  if (Config.SoName)
493
    Stub.SoName = *Config.SoName;
494

495
  Error OverrideError =
496
      overrideIFSTarget(Stub, Config.OverrideArch, Config.OverrideEndianness,
497
                        Config.OverrideBitWidth, Config.OptTargetTriple);
498
  if (OverrideError)
499
    fatalError(std::move(OverrideError));
500

501
  if (Config.StripNeeded)
502
    Stub.NeededLibs.clear();
503

504
  if (Error E = filterIFSSyms(Stub, Config.StripUndefined, Config.Exclude))
505
    fatalError(std::move(E));
506

507
  if (Config.StripSize)
508
    for (IFSSymbol &Sym : Stub.Symbols)
509
      Sym.Size.reset();
510

511
  if (!Config.OutputElf && !Config.OutputIfs && !Config.OutputTbd) {
512
    if (!Config.OutputFormat) {
513
      WithColor::error() << "at least one output should be specified.";
514
      return -1;
515
    }
516
  } else if (Config.OutputFormat) {
517
    WithColor::error() << "'--output-format' cannot be used with "
518
                          "'--output-{FILE_FORMAT}' options at the same time";
519
    return -1;
520
  }
521
  if (Config.OutputFormat) {
522
    // TODO: Remove OutputFormat flag in the next revision.
523
    WithColor::warning() << "--output-format option is deprecated, please use "
524
                            "--output-{FILE_FORMAT} options instead\n";
525
    switch (*Config.OutputFormat) {
526
    case FileFormat::TBD: {
527
      std::error_code SysErr;
528
      raw_fd_ostream Out(*Config.Output, SysErr);
529
      if (SysErr) {
530
        WithColor::error() << "Couldn't open " << *Config.Output
531
                           << " for writing.\n";
532
        return -1;
533
      }
534
      if (!Stub.Target.Triple) {
535
        WithColor::error()
536
            << "Triple should be defined when output format is TBD";
537
        return -1;
538
      }
539
      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
540
                          "TBD", Out);
541
    }
542
    case FileFormat::IFS: {
543
      Stub.IfsVersion = IfsVersionCurrent;
544
      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
545
        std::error_code HintEC(1, std::generic_category());
546
        IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
547
        if (*Stub.Target.Arch != *HintTarget.Arch)
548
          fatalError(make_error<StringError>(
549
              "Triple hint does not match the actual architecture", HintEC));
550
        if (*Stub.Target.Endianness != *HintTarget.Endianness)
551
          fatalError(make_error<StringError>(
552
              "Triple hint does not match the actual endianness", HintEC));
553
        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
554
          fatalError(make_error<StringError>(
555
              "Triple hint does not match the actual bit width", HintEC));
556

557
        stripIFSTarget(Stub, true, false, false, false);
558
        Stub.Target.Triple = *Config.HintIfsTarget;
559
      } else {
560
        stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
561
                       Config.StripIfsEndianness, Config.StripIfsBitwidth);
562
      }
563
      Error IFSWriteError =
564
          writeIFS(*Config.Output, Stub, Config.WriteIfChanged);
565
      if (IFSWriteError)
566
        fatalError(std::move(IFSWriteError));
567
      break;
568
    }
569
    case FileFormat::ELF: {
570
      Error TargetError = validateIFSTarget(Stub, true);
571
      if (TargetError)
572
        fatalError(std::move(TargetError));
573
      Error BinaryWriteError =
574
          writeBinaryStub(*Config.Output, Stub, Config.WriteIfChanged);
575
      if (BinaryWriteError)
576
        fatalError(std::move(BinaryWriteError));
577
      break;
578
    }
579
    }
580
  } else {
581
    // Check if output path for individual format.
582
    if (Config.OutputElf) {
583
      Error TargetError = validateIFSTarget(Stub, true);
584
      if (TargetError)
585
        fatalError(std::move(TargetError));
586
      Error BinaryWriteError =
587
          writeBinaryStub(*Config.OutputElf, Stub, Config.WriteIfChanged);
588
      if (BinaryWriteError)
589
        fatalError(std::move(BinaryWriteError));
590
    }
591
    if (Config.OutputIfs) {
592
      Stub.IfsVersion = IfsVersionCurrent;
593
      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
594
        std::error_code HintEC(1, std::generic_category());
595
        IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
596
        if (*Stub.Target.Arch != *HintTarget.Arch)
597
          fatalError(make_error<StringError>(
598
              "Triple hint does not match the actual architecture", HintEC));
599
        if (*Stub.Target.Endianness != *HintTarget.Endianness)
600
          fatalError(make_error<StringError>(
601
              "Triple hint does not match the actual endianness", HintEC));
602
        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
603
          fatalError(make_error<StringError>(
604
              "Triple hint does not match the actual bit width", HintEC));
605

606
        stripIFSTarget(Stub, true, false, false, false);
607
        Stub.Target.Triple = *Config.HintIfsTarget;
608
      } else {
609
        stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
610
                       Config.StripIfsEndianness, Config.StripIfsBitwidth);
611
      }
612
      Error IFSWriteError =
613
          writeIFS(*Config.OutputIfs, Stub, Config.WriteIfChanged);
614
      if (IFSWriteError)
615
        fatalError(std::move(IFSWriteError));
616
    }
617
    if (Config.OutputTbd) {
618
      std::error_code SysErr;
619
      raw_fd_ostream Out(*Config.OutputTbd, SysErr);
620
      if (SysErr) {
621
        WithColor::error() << "Couldn't open " << *Config.OutputTbd
622
                           << " for writing.\n";
623
        return -1;
624
      }
625
      if (!Stub.Target.Triple) {
626
        WithColor::error()
627
            << "Triple should be defined when output format is TBD";
628
        return -1;
629
      }
630
      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
631
                          "TBD", Out);
632
    }
633
  }
634
  return 0;
635
}
636

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.