CopyConfig.h revision 360784
1//===- CopyConfig.h -------------------------------------------------------===//
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#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
10#define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
11
12#include "ELF/ELFConfig.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/BitmaskEnum.h"
15#include "llvm/ADT/Optional.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Object/ELFTypes.h"
20#include "llvm/Support/Allocator.h"
21#include "llvm/Support/Error.h"
22#include "llvm/Support/GlobPattern.h"
23#include "llvm/Support/Regex.h"
24// Necessary for llvm::DebugCompressionType::None
25#include "llvm/Target/TargetOptions.h"
26#include <vector>
27
28namespace llvm {
29namespace objcopy {
30
31enum class FileFormat {
32  Unspecified,
33  ELF,
34  Binary,
35  IHex,
36};
37
38// This type keeps track of the machine info for various architectures. This
39// lets us map architecture names to ELF types and the e_machine value of the
40// ELF file.
41struct MachineInfo {
42  MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle)
43      : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {}
44  // Alternative constructor that defaults to NONE for OSABI.
45  MachineInfo(uint16_t EM, bool Is64, bool IsLittle)
46      : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {}
47  // Default constructor for unset fields.
48  MachineInfo() : MachineInfo(0, 0, false, false) {}
49  uint16_t EMachine;
50  uint8_t OSABI;
51  bool Is64Bit;
52  bool IsLittleEndian;
53};
54
55// Flags set by --set-section-flags or --rename-section. Interpretation of these
56// is format-specific and not all flags are meaningful for all object file
57// formats. This is a bitmask; many section flags may be set.
58enum SectionFlag {
59  SecNone = 0,
60  SecAlloc = 1 << 0,
61  SecLoad = 1 << 1,
62  SecNoload = 1 << 2,
63  SecReadonly = 1 << 3,
64  SecDebug = 1 << 4,
65  SecCode = 1 << 5,
66  SecData = 1 << 6,
67  SecRom = 1 << 7,
68  SecMerge = 1 << 8,
69  SecStrings = 1 << 9,
70  SecContents = 1 << 10,
71  SecShare = 1 << 11,
72  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ SecShare)
73};
74
75struct SectionRename {
76  StringRef OriginalName;
77  StringRef NewName;
78  Optional<SectionFlag> NewFlags;
79};
80
81struct SectionFlagsUpdate {
82  StringRef Name;
83  SectionFlag NewFlags;
84};
85
86enum class DiscardType {
87  None,   // Default
88  All,    // --discard-all (-x)
89  Locals, // --discard-locals (-X)
90};
91
92enum class MatchStyle {
93  Literal,  // Default for symbols.
94  Wildcard, // Default for sections, or enabled with --wildcard (-w).
95  Regex,    // Enabled with --regex.
96};
97
98class NameOrPattern {
99  StringRef Name;
100  // Regex is shared between multiple CopyConfig instances.
101  std::shared_ptr<Regex> R;
102  std::shared_ptr<GlobPattern> G;
103  bool IsPositiveMatch = true;
104
105  NameOrPattern(StringRef N) : Name(N) {}
106  NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
107  NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch)
108      : G(G), IsPositiveMatch(IsPositiveMatch) {}
109
110public:
111  // ErrorCallback is used to handle recoverable errors. An Error returned
112  // by the callback aborts the parsing and is then returned by this function.
113  static Expected<NameOrPattern>
114  create(StringRef Pattern, MatchStyle MS,
115         llvm::function_ref<Error(Error)> ErrorCallback);
116
117  bool isPositiveMatch() const { return IsPositiveMatch; }
118  bool operator==(StringRef S) const {
119    return R ? R->match(S) : G ? G->match(S) : Name == S;
120  }
121  bool operator!=(StringRef S) const { return !operator==(S); }
122};
123
124// Matcher that checks symbol or section names against the command line flags
125// provided for that option.
126class NameMatcher {
127  std::vector<NameOrPattern> PosMatchers;
128  std::vector<NameOrPattern> NegMatchers;
129
130public:
131  Error addMatcher(Expected<NameOrPattern> Matcher) {
132    if (!Matcher)
133      return Matcher.takeError();
134    if (Matcher->isPositiveMatch())
135      PosMatchers.push_back(std::move(*Matcher));
136    else
137      NegMatchers.push_back(std::move(*Matcher));
138    return Error::success();
139  }
140  bool matches(StringRef S) const {
141    return is_contained(PosMatchers, S) && !is_contained(NegMatchers, S);
142  }
143  bool empty() const { return PosMatchers.empty() && NegMatchers.empty(); }
144};
145
146// Configuration for copying/stripping a single file.
147struct CopyConfig {
148  // Format-specific options to be initialized lazily when needed.
149  Optional<elf::ELFCopyConfig> ELF;
150
151  // Main input/output options
152  StringRef InputFilename;
153  FileFormat InputFormat = FileFormat::Unspecified;
154  StringRef OutputFilename;
155  FileFormat OutputFormat = FileFormat::Unspecified;
156
157  // Only applicable when --output-format!=binary (e.g. elf64-x86-64).
158  Optional<MachineInfo> OutputArch;
159
160  // Advanced options
161  StringRef AddGnuDebugLink;
162  // Cached gnu_debuglink's target CRC
163  uint32_t GnuDebugLinkCRC32;
164  StringRef BuildIdLinkDir;
165  Optional<StringRef> BuildIdLinkInput;
166  Optional<StringRef> BuildIdLinkOutput;
167  Optional<StringRef> ExtractPartition;
168  StringRef SplitDWO;
169  StringRef SymbolsPrefix;
170  StringRef AllocSectionsPrefix;
171  DiscardType DiscardMode = DiscardType::None;
172  Optional<StringRef> NewSymbolVisibility;
173
174  // Repeated options
175  std::vector<StringRef> AddSection;
176  std::vector<StringRef> DumpSection;
177  std::vector<StringRef> SymbolsToAdd;
178  std::vector<StringRef> RPathToAdd;
179
180  // Section matchers
181  NameMatcher KeepSection;
182  NameMatcher OnlySection;
183  NameMatcher ToRemove;
184
185  // Symbol matchers
186  NameMatcher SymbolsToGlobalize;
187  NameMatcher SymbolsToKeep;
188  NameMatcher SymbolsToLocalize;
189  NameMatcher SymbolsToRemove;
190  NameMatcher UnneededSymbolsToRemove;
191  NameMatcher SymbolsToWeaken;
192  NameMatcher SymbolsToKeepGlobal;
193
194  // Map options
195  StringMap<SectionRename> SectionsToRename;
196  StringMap<uint64_t> SetSectionAlignment;
197  StringMap<SectionFlagsUpdate> SetSectionFlags;
198  StringMap<StringRef> SymbolsToRename;
199
200  // ELF entry point address expression. The input parameter is an entry point
201  // address in the input ELF file. The entry address in the output file is
202  // calculated with EntryExpr(input_address), when either --set-start or
203  // --change-start is used.
204  std::function<uint64_t(uint64_t)> EntryExpr;
205
206  // Boolean options
207  bool AllowBrokenLinks = false;
208  bool DeterministicArchives = true;
209  bool ExtractDWO = false;
210  bool ExtractMainPartition = false;
211  bool KeepFileSymbols = false;
212  bool LocalizeHidden = false;
213  bool OnlyKeepDebug = false;
214  bool PreserveDates = false;
215  bool StripAll = false;
216  bool StripAllGNU = false;
217  bool StripDWO = false;
218  bool StripDebug = false;
219  bool StripNonAlloc = false;
220  bool StripSections = false;
221  bool StripUnneeded = false;
222  bool Weaken = false;
223  bool DecompressDebugSections = false;
224  DebugCompressionType CompressionType = DebugCompressionType::None;
225
226  // parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on
227  // success or returns an Error otherwise.
228  Error parseELFConfig() {
229    if (!ELF) {
230      Expected<elf::ELFCopyConfig> ELFConfig = elf::parseConfig(*this);
231      if (!ELFConfig)
232        return ELFConfig.takeError();
233      ELF = *ELFConfig;
234    }
235    return Error::success();
236  }
237};
238
239// Configuration for the overall invocation of this tool. When invoked as
240// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
241// will contain one or more CopyConfigs.
242struct DriverConfig {
243  SmallVector<CopyConfig, 1> CopyConfigs;
244  BumpPtrAllocator Alloc;
245};
246
247// ParseObjcopyOptions returns the config and sets the input arguments. If a
248// help flag is set then ParseObjcopyOptions will print the help messege and
249// exit. ErrorCallback is used to handle recoverable errors. An Error returned
250// by the callback aborts the parsing and is then returned by this function.
251Expected<DriverConfig>
252parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
253                    llvm::function_ref<Error(Error)> ErrorCallback);
254
255// ParseInstallNameToolOptions returns the config and sets the input arguments.
256// If a help flag is set then ParseInstallNameToolOptions will print the help
257// messege and exit.
258Expected<DriverConfig>
259parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
260
261// ParseStripOptions returns the config and sets the input arguments. If a
262// help flag is set then ParseStripOptions will print the help messege and
263// exit. ErrorCallback is used to handle recoverable errors. An Error returned
264// by the callback aborts the parsing and is then returned by this function.
265Expected<DriverConfig>
266parseStripOptions(ArrayRef<const char *> ArgsArr,
267                  llvm::function_ref<Error(Error)> ErrorCallback);
268} // namespace objcopy
269} // namespace llvm
270
271#endif
272