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(String: 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(V: CachedHashStringRef(*MaybeName)); |
137 | else |
138 | PosPatterns.push_back(Elt: std::move(*Matcher)); |
139 | } else { |
140 | NegMatchers.push_back(Elt: std::move(*Matcher)); |
141 | } |
142 | return Error::success(); |
143 | } |
144 | bool matches(StringRef S) const { |
145 | return (PosNames.contains(V: CachedHashStringRef(S)) || |
146 | is_contained(Range: PosPatterns, Element: S)) && |
147 | !is_contained(Range: NegMatchers, Element: S); |
148 | } |
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; |
187 | 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> ; |
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 | // Boolean options |
249 | bool DeterministicArchives = true; |
250 | bool = false; |
251 | bool ExtractMainPartition = false; |
252 | bool OnlyKeepDebug = false; |
253 | bool PreserveDates = false; |
254 | bool StripAll = false; |
255 | bool StripAllGNU = false; |
256 | bool StripDWO = false; |
257 | bool StripDebug = false; |
258 | bool StripNonAlloc = false; |
259 | bool StripSections = false; |
260 | bool StripUnneeded = false; |
261 | bool Weaken = false; |
262 | bool DecompressDebugSections = false; |
263 | |
264 | DebugCompressionType CompressionType = DebugCompressionType::None; |
265 | |
266 | SmallVector<std::pair<NameMatcher, llvm::DebugCompressionType>, 0> |
267 | compressSections; |
268 | }; |
269 | |
270 | } // namespace objcopy |
271 | } // namespace llvm |
272 | |
273 | #endif // LLVM_OBJCOPY_COMMONCONFIG_H |
274 | |