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