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