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