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