xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ObjCopy/CommonConfig.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 {
MachineInfoMachineInfo34   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.
MachineInfoMachineInfo37   MachineInfo(uint16_t EM, bool Is64, bool IsLittle)
38       : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {}
39   // Default constructor for unset fields.
MachineInfoMachineInfo40   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 
NameOrPattern(StringRef N)99   NameOrPattern(StringRef N) : Name(N) {}
NameOrPattern(std::shared_ptr<Regex> R)100   NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
NameOrPattern(std::shared_ptr<GlobPattern> G,bool IsPositiveMatch)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 
isPositiveMatch()111   bool isPositiveMatch() const { return IsPositiveMatch; }
getName()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:
addMatcher(Expected<NameOrPattern> Matcher)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   }
matches(StringRef S)144   bool matches(StringRef S) const {
145     return (PosNames.contains(CachedHashStringRef(S)) ||
146             is_contained(PosPatterns, S)) &&
147            !is_contained(NegMatchers, S);
148   }
empty()149   bool empty() const {
150     return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty();
151   }
152 };
153 
154 enum class SymbolFlag {
155   Global,
156   Local,
157   Weak,
158   Default,
159   Hidden,
160   Protected,
161   File,
162   Section,
163   Object,
164   Function,
165   IndirectFunction,
166   Debug,
167   Constructor,
168   Warning,
169   Indirect,
170   Synthetic,
171   UniqueObject,
172 };
173 
174 // Symbol info specified by --add-symbol option. Symbol flags not supported
175 // by a concrete format should be ignored.
176 struct NewSymbolInfo {
177   StringRef SymbolName;
178   StringRef SectionName;
179   uint64_t Value = 0;
180   SmallVector<SymbolFlag, 0> Flags;
181   SmallVector<StringRef, 0> BeforeSyms;
182 };
183 
184 // Specify section name and section body for newly added or updated section.
185 struct NewSectionInfo {
186   NewSectionInfo() = default;
NewSectionInfoNewSectionInfo187   NewSectionInfo(StringRef Name, std::unique_ptr<MemoryBuffer> &&Buffer)
188       : SectionName(Name), SectionData(std::move(Buffer)) {}
189 
190   StringRef SectionName;
191   std::shared_ptr<MemoryBuffer> SectionData;
192 };
193 
194 // Configuration for copying/stripping a single file.
195 struct CommonConfig {
196   // Main input/output options
197   StringRef InputFilename;
198   FileFormat InputFormat = FileFormat::Unspecified;
199   StringRef OutputFilename;
200   FileFormat OutputFormat = FileFormat::Unspecified;
201 
202   // Only applicable when --output-format!=binary (e.g. elf64-x86-64).
203   std::optional<MachineInfo> OutputArch;
204 
205   // Advanced options
206   StringRef AddGnuDebugLink;
207   // Cached gnu_debuglink's target CRC
208   uint32_t GnuDebugLinkCRC32;
209   std::optional<StringRef> ExtractPartition;
210   uint8_t GapFill = 0;
211   uint64_t PadTo = 0;
212   StringRef SplitDWO;
213   StringRef SymbolsPrefix;
214   StringRef SymbolsPrefixRemove;
215   StringRef AllocSectionsPrefix;
216   DiscardType DiscardMode = DiscardType::None;
217 
218   // Repeated options
219   SmallVector<NewSectionInfo, 0> AddSection;
220   SmallVector<StringRef, 0> DumpSection;
221   SmallVector<NewSectionInfo, 0> UpdateSection;
222 
223   // Section matchers
224   NameMatcher KeepSection;
225   NameMatcher OnlySection;
226   NameMatcher ToRemove;
227 
228   // Symbol matchers
229   NameMatcher SymbolsToGlobalize;
230   NameMatcher SymbolsToKeep;
231   NameMatcher SymbolsToLocalize;
232   NameMatcher SymbolsToRemove;
233   NameMatcher UnneededSymbolsToRemove;
234   NameMatcher SymbolsToWeaken;
235   NameMatcher SymbolsToKeepGlobal;
236   NameMatcher SymbolsToSkip;
237 
238   // Map options
239   StringMap<SectionRename> SectionsToRename;
240   StringMap<uint64_t> SetSectionAlignment;
241   StringMap<SectionFlagsUpdate> SetSectionFlags;
242   StringMap<uint64_t> SetSectionType;
243   StringMap<StringRef> SymbolsToRename;
244 
245   // Symbol info specified by --add-symbol option.
246   SmallVector<NewSymbolInfo, 0> SymbolsToAdd;
247 
248   // Integer options
249   int64_t ChangeSectionLMAValAll = 0;
250 
251   // Boolean options
252   bool DeterministicArchives = true;
253   bool ExtractDWO = false;
254   bool ExtractMainPartition = false;
255   bool OnlyKeepDebug = false;
256   bool PreserveDates = false;
257   bool StripAll = false;
258   bool StripAllGNU = false;
259   bool StripDWO = false;
260   bool StripDebug = false;
261   bool StripNonAlloc = false;
262   bool StripSections = false;
263   bool StripUnneeded = false;
264   bool Weaken = false;
265   bool DecompressDebugSections = false;
266 
267   DebugCompressionType CompressionType = DebugCompressionType::None;
268 
269   SmallVector<std::pair<NameMatcher, llvm::DebugCompressionType>, 0>
270       compressSections;
271 };
272 
273 } // namespace objcopy
274 } // namespace llvm
275 
276 #endif // LLVM_OBJCOPY_COMMONCONFIG_H
277