1343171Sdim//===- CopyConfig.h -------------------------------------------------------===//
2343171Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343171Sdim//
7343171Sdim//===----------------------------------------------------------------------===//
8343171Sdim
9343171Sdim#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
10343171Sdim#define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
11343171Sdim
12360784Sdim#include "ELF/ELFConfig.h"
13343171Sdim#include "llvm/ADT/ArrayRef.h"
14353358Sdim#include "llvm/ADT/BitmaskEnum.h"
15343171Sdim#include "llvm/ADT/Optional.h"
16343171Sdim#include "llvm/ADT/SmallVector.h"
17343171Sdim#include "llvm/ADT/StringMap.h"
18343171Sdim#include "llvm/ADT/StringRef.h"
19353358Sdim#include "llvm/Object/ELFTypes.h"
20353358Sdim#include "llvm/Support/Allocator.h"
21353358Sdim#include "llvm/Support/Error.h"
22360784Sdim#include "llvm/Support/GlobPattern.h"
23353358Sdim#include "llvm/Support/Regex.h"
24343171Sdim// Necessary for llvm::DebugCompressionType::None
25343171Sdim#include "llvm/Target/TargetOptions.h"
26343171Sdim#include <vector>
27343171Sdim
28343171Sdimnamespace llvm {
29343171Sdimnamespace objcopy {
30343171Sdim
31353358Sdimenum class FileFormat {
32353358Sdim  Unspecified,
33353358Sdim  ELF,
34353358Sdim  Binary,
35353358Sdim  IHex,
36353358Sdim};
37353358Sdim
38343171Sdim// This type keeps track of the machine info for various architectures. This
39343171Sdim// lets us map architecture names to ELF types and the e_machine value of the
40343171Sdim// ELF file.
41343171Sdimstruct MachineInfo {
42353358Sdim  MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle)
43353358Sdim      : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {}
44353358Sdim  // Alternative constructor that defaults to NONE for OSABI.
45353358Sdim  MachineInfo(uint16_t EM, bool Is64, bool IsLittle)
46353358Sdim      : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {}
47353358Sdim  // Default constructor for unset fields.
48353358Sdim  MachineInfo() : MachineInfo(0, 0, false, false) {}
49343171Sdim  uint16_t EMachine;
50353358Sdim  uint8_t OSABI;
51343171Sdim  bool Is64Bit;
52343171Sdim  bool IsLittleEndian;
53343171Sdim};
54343171Sdim
55353358Sdim// Flags set by --set-section-flags or --rename-section. Interpretation of these
56353358Sdim// is format-specific and not all flags are meaningful for all object file
57353358Sdim// formats. This is a bitmask; many section flags may be set.
58353358Sdimenum SectionFlag {
59353358Sdim  SecNone = 0,
60353358Sdim  SecAlloc = 1 << 0,
61353358Sdim  SecLoad = 1 << 1,
62353358Sdim  SecNoload = 1 << 2,
63353358Sdim  SecReadonly = 1 << 3,
64353358Sdim  SecDebug = 1 << 4,
65353358Sdim  SecCode = 1 << 5,
66353358Sdim  SecData = 1 << 6,
67353358Sdim  SecRom = 1 << 7,
68353358Sdim  SecMerge = 1 << 8,
69353358Sdim  SecStrings = 1 << 9,
70353358Sdim  SecContents = 1 << 10,
71353358Sdim  SecShare = 1 << 11,
72353358Sdim  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ SecShare)
73353358Sdim};
74353358Sdim
75343171Sdimstruct SectionRename {
76343171Sdim  StringRef OriginalName;
77343171Sdim  StringRef NewName;
78353358Sdim  Optional<SectionFlag> NewFlags;
79343171Sdim};
80343171Sdim
81353358Sdimstruct SectionFlagsUpdate {
82353358Sdim  StringRef Name;
83353358Sdim  SectionFlag NewFlags;
84353358Sdim};
85353358Sdim
86353358Sdimenum class DiscardType {
87353358Sdim  None,   // Default
88353358Sdim  All,    // --discard-all (-x)
89353358Sdim  Locals, // --discard-locals (-X)
90353358Sdim};
91353358Sdim
92360784Sdimenum class MatchStyle {
93360784Sdim  Literal,  // Default for symbols.
94360784Sdim  Wildcard, // Default for sections, or enabled with --wildcard (-w).
95360784Sdim  Regex,    // Enabled with --regex.
96360784Sdim};
97360784Sdim
98360784Sdimclass NameOrPattern {
99353358Sdim  StringRef Name;
100353358Sdim  // Regex is shared between multiple CopyConfig instances.
101353358Sdim  std::shared_ptr<Regex> R;
102360784Sdim  std::shared_ptr<GlobPattern> G;
103360784Sdim  bool IsPositiveMatch = true;
104353358Sdim
105360784Sdim  NameOrPattern(StringRef N) : Name(N) {}
106360784Sdim  NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
107360784Sdim  NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch)
108360784Sdim      : G(G), IsPositiveMatch(IsPositiveMatch) {}
109360784Sdim
110353358Sdimpublic:
111360784Sdim  // ErrorCallback is used to handle recoverable errors. An Error returned
112360784Sdim  // by the callback aborts the parsing and is then returned by this function.
113360784Sdim  static Expected<NameOrPattern>
114360784Sdim  create(StringRef Pattern, MatchStyle MS,
115360784Sdim         llvm::function_ref<Error(Error)> ErrorCallback);
116360784Sdim
117360784Sdim  bool isPositiveMatch() const { return IsPositiveMatch; }
118360784Sdim  bool operator==(StringRef S) const {
119360784Sdim    return R ? R->match(S) : G ? G->match(S) : Name == S;
120360784Sdim  }
121353358Sdim  bool operator!=(StringRef S) const { return !operator==(S); }
122353358Sdim};
123353358Sdim
124360784Sdim// Matcher that checks symbol or section names against the command line flags
125360784Sdim// provided for that option.
126360784Sdimclass NameMatcher {
127360784Sdim  std::vector<NameOrPattern> PosMatchers;
128360784Sdim  std::vector<NameOrPattern> NegMatchers;
129360784Sdim
130360784Sdimpublic:
131360784Sdim  Error addMatcher(Expected<NameOrPattern> Matcher) {
132360784Sdim    if (!Matcher)
133360784Sdim      return Matcher.takeError();
134360784Sdim    if (Matcher->isPositiveMatch())
135360784Sdim      PosMatchers.push_back(std::move(*Matcher));
136360784Sdim    else
137360784Sdim      NegMatchers.push_back(std::move(*Matcher));
138360784Sdim    return Error::success();
139360784Sdim  }
140360784Sdim  bool matches(StringRef S) const {
141360784Sdim    return is_contained(PosMatchers, S) && !is_contained(NegMatchers, S);
142360784Sdim  }
143360784Sdim  bool empty() const { return PosMatchers.empty() && NegMatchers.empty(); }
144353358Sdim};
145353358Sdim
146343171Sdim// Configuration for copying/stripping a single file.
147343171Sdimstruct CopyConfig {
148360784Sdim  // Format-specific options to be initialized lazily when needed.
149360784Sdim  Optional<elf::ELFCopyConfig> ELF;
150360784Sdim
151343171Sdim  // Main input/output options
152343171Sdim  StringRef InputFilename;
153360784Sdim  FileFormat InputFormat = FileFormat::Unspecified;
154343171Sdim  StringRef OutputFilename;
155360784Sdim  FileFormat OutputFormat = FileFormat::Unspecified;
156343171Sdim
157343171Sdim  // Only applicable when --output-format!=binary (e.g. elf64-x86-64).
158343171Sdim  Optional<MachineInfo> OutputArch;
159343171Sdim
160343171Sdim  // Advanced options
161343171Sdim  StringRef AddGnuDebugLink;
162353358Sdim  // Cached gnu_debuglink's target CRC
163353358Sdim  uint32_t GnuDebugLinkCRC32;
164343171Sdim  StringRef BuildIdLinkDir;
165343171Sdim  Optional<StringRef> BuildIdLinkInput;
166343171Sdim  Optional<StringRef> BuildIdLinkOutput;
167353358Sdim  Optional<StringRef> ExtractPartition;
168343171Sdim  StringRef SplitDWO;
169343171Sdim  StringRef SymbolsPrefix;
170353358Sdim  StringRef AllocSectionsPrefix;
171353358Sdim  DiscardType DiscardMode = DiscardType::None;
172360784Sdim  Optional<StringRef> NewSymbolVisibility;
173343171Sdim
174343171Sdim  // Repeated options
175343171Sdim  std::vector<StringRef> AddSection;
176343171Sdim  std::vector<StringRef> DumpSection;
177360784Sdim  std::vector<StringRef> SymbolsToAdd;
178360784Sdim  std::vector<StringRef> RPathToAdd;
179343171Sdim
180360784Sdim  // Section matchers
181360784Sdim  NameMatcher KeepSection;
182360784Sdim  NameMatcher OnlySection;
183360784Sdim  NameMatcher ToRemove;
184360784Sdim
185360784Sdim  // Symbol matchers
186360784Sdim  NameMatcher SymbolsToGlobalize;
187360784Sdim  NameMatcher SymbolsToKeep;
188360784Sdim  NameMatcher SymbolsToLocalize;
189360784Sdim  NameMatcher SymbolsToRemove;
190360784Sdim  NameMatcher UnneededSymbolsToRemove;
191360784Sdim  NameMatcher SymbolsToWeaken;
192360784Sdim  NameMatcher SymbolsToKeepGlobal;
193360784Sdim
194343171Sdim  // Map options
195343171Sdim  StringMap<SectionRename> SectionsToRename;
196360784Sdim  StringMap<uint64_t> SetSectionAlignment;
197353358Sdim  StringMap<SectionFlagsUpdate> SetSectionFlags;
198343171Sdim  StringMap<StringRef> SymbolsToRename;
199343171Sdim
200353358Sdim  // ELF entry point address expression. The input parameter is an entry point
201353358Sdim  // address in the input ELF file. The entry address in the output file is
202353358Sdim  // calculated with EntryExpr(input_address), when either --set-start or
203353358Sdim  // --change-start is used.
204353358Sdim  std::function<uint64_t(uint64_t)> EntryExpr;
205353358Sdim
206343171Sdim  // Boolean options
207353358Sdim  bool AllowBrokenLinks = false;
208343171Sdim  bool DeterministicArchives = true;
209343171Sdim  bool ExtractDWO = false;
210353358Sdim  bool ExtractMainPartition = false;
211343171Sdim  bool KeepFileSymbols = false;
212343171Sdim  bool LocalizeHidden = false;
213343171Sdim  bool OnlyKeepDebug = false;
214343171Sdim  bool PreserveDates = false;
215343171Sdim  bool StripAll = false;
216343171Sdim  bool StripAllGNU = false;
217343171Sdim  bool StripDWO = false;
218343171Sdim  bool StripDebug = false;
219343171Sdim  bool StripNonAlloc = false;
220343171Sdim  bool StripSections = false;
221343171Sdim  bool StripUnneeded = false;
222343171Sdim  bool Weaken = false;
223343171Sdim  bool DecompressDebugSections = false;
224343171Sdim  DebugCompressionType CompressionType = DebugCompressionType::None;
225360784Sdim
226360784Sdim  // parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on
227360784Sdim  // success or returns an Error otherwise.
228360784Sdim  Error parseELFConfig() {
229360784Sdim    if (!ELF) {
230360784Sdim      Expected<elf::ELFCopyConfig> ELFConfig = elf::parseConfig(*this);
231360784Sdim      if (!ELFConfig)
232360784Sdim        return ELFConfig.takeError();
233360784Sdim      ELF = *ELFConfig;
234360784Sdim    }
235360784Sdim    return Error::success();
236360784Sdim  }
237343171Sdim};
238343171Sdim
239343171Sdim// Configuration for the overall invocation of this tool. When invoked as
240343171Sdim// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
241343171Sdim// will contain one or more CopyConfigs.
242343171Sdimstruct DriverConfig {
243343171Sdim  SmallVector<CopyConfig, 1> CopyConfigs;
244353358Sdim  BumpPtrAllocator Alloc;
245343171Sdim};
246343171Sdim
247343171Sdim// ParseObjcopyOptions returns the config and sets the input arguments. If a
248343171Sdim// help flag is set then ParseObjcopyOptions will print the help messege and
249360784Sdim// exit. ErrorCallback is used to handle recoverable errors. An Error returned
250360784Sdim// by the callback aborts the parsing and is then returned by this function.
251360784SdimExpected<DriverConfig>
252360784SdimparseObjcopyOptions(ArrayRef<const char *> ArgsArr,
253360784Sdim                    llvm::function_ref<Error(Error)> ErrorCallback);
254343171Sdim
255360784Sdim// ParseInstallNameToolOptions returns the config and sets the input arguments.
256360784Sdim// If a help flag is set then ParseInstallNameToolOptions will print the help
257360784Sdim// messege and exit.
258360784SdimExpected<DriverConfig>
259360784SdimparseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
260360784Sdim
261343171Sdim// ParseStripOptions returns the config and sets the input arguments. If a
262343171Sdim// help flag is set then ParseStripOptions will print the help messege and
263353358Sdim// exit. ErrorCallback is used to handle recoverable errors. An Error returned
264353358Sdim// by the callback aborts the parsing and is then returned by this function.
265353358SdimExpected<DriverConfig>
266353358SdimparseStripOptions(ArrayRef<const char *> ArgsArr,
267360784Sdim                  llvm::function_ref<Error(Error)> ErrorCallback);
268343171Sdim} // namespace objcopy
269343171Sdim} // namespace llvm
270343171Sdim
271343171Sdim#endif
272