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