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/GlobPattern.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/Regex.h"
22 // Necessary for llvm::DebugCompressionType::None
23 #include "llvm/Target/TargetOptions.h"
24 #include <optional>
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 {
MachineInfoMachineInfo41   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.
MachineInfoMachineInfo44   MachineInfo(uint16_t EM, bool Is64, bool IsLittle)
45       : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {}
46   // Default constructor for unset fields.
MachineInfoMachineInfo47   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   SecLarge = 1 << 13,
73   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecLarge)
74 };
75 
76 struct SectionRename {
77   StringRef OriginalName;
78   StringRef NewName;
79   std::optional<SectionFlag> NewFlags;
80 };
81 
82 struct SectionFlagsUpdate {
83   StringRef Name;
84   SectionFlag NewFlags;
85 };
86 
87 enum class DiscardType {
88   None,   // Default
89   All,    // --discard-all (-x)
90   Locals, // --discard-locals (-X)
91 };
92 
93 enum class MatchStyle {
94   Literal,  // Default for symbols.
95   Wildcard, // Default for sections, or enabled with --wildcard (-w).
96   Regex,    // Enabled with --regex.
97 };
98 
99 class NameOrPattern {
100   StringRef Name;
101   // Regex is shared between multiple CommonConfig instances.
102   std::shared_ptr<Regex> R;
103   std::shared_ptr<GlobPattern> G;
104   bool IsPositiveMatch = true;
105 
NameOrPattern(StringRef N)106   NameOrPattern(StringRef N) : Name(N) {}
NameOrPattern(std::shared_ptr<Regex> R)107   NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
NameOrPattern(std::shared_ptr<GlobPattern> G,bool IsPositiveMatch)108   NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch)
109       : G(G), IsPositiveMatch(IsPositiveMatch) {}
110 
111 public:
112   // ErrorCallback is used to handle recoverable errors. An Error returned
113   // by the callback aborts the parsing and is then returned by this function.
114   static Expected<NameOrPattern>
115   create(StringRef Pattern, MatchStyle MS,
116          llvm::function_ref<Error(Error)> ErrorCallback);
117 
isPositiveMatch()118   bool isPositiveMatch() const { return IsPositiveMatch; }
getName()119   std::optional<StringRef> getName() const {
120     if (!R && !G)
121       return Name;
122     return std::nullopt;
123   }
124   bool operator==(StringRef S) const {
125     return R ? R->match(S) : G ? G->match(S) : Name == S;
126   }
127   bool operator!=(StringRef S) const { return !operator==(S); }
128 };
129 
130 // Matcher that checks symbol or section names against the command line flags
131 // provided for that option.
132 class NameMatcher {
133   DenseSet<CachedHashStringRef> PosNames;
134   std::vector<NameOrPattern> PosPatterns;
135   std::vector<NameOrPattern> NegMatchers;
136 
137 public:
addMatcher(Expected<NameOrPattern> Matcher)138   Error addMatcher(Expected<NameOrPattern> Matcher) {
139     if (!Matcher)
140       return Matcher.takeError();
141     if (Matcher->isPositiveMatch()) {
142       if (std::optional<StringRef> MaybeName = Matcher->getName())
143         PosNames.insert(CachedHashStringRef(*MaybeName));
144       else
145         PosPatterns.push_back(std::move(*Matcher));
146     } else {
147       NegMatchers.push_back(std::move(*Matcher));
148     }
149     return Error::success();
150   }
matches(StringRef S)151   bool matches(StringRef S) const {
152     return (PosNames.contains(CachedHashStringRef(S)) ||
153             is_contained(PosPatterns, S)) &&
154            !is_contained(NegMatchers, S);
155   }
empty()156   bool empty() const {
157     return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty();
158   }
159 };
160 
161 enum class SymbolFlag {
162   Global,
163   Local,
164   Weak,
165   Default,
166   Hidden,
167   Protected,
168   File,
169   Section,
170   Object,
171   Function,
172   IndirectFunction,
173   Debug,
174   Constructor,
175   Warning,
176   Indirect,
177   Synthetic,
178   UniqueObject,
179 };
180 
181 // Symbol info specified by --add-symbol option. Symbol flags not supported
182 // by a concrete format should be ignored.
183 struct NewSymbolInfo {
184   StringRef SymbolName;
185   StringRef SectionName;
186   uint64_t Value = 0;
187   std::vector<SymbolFlag> Flags;
188   std::vector<StringRef> BeforeSyms;
189 };
190 
191 // Specify section name and section body for newly added or updated section.
192 struct NewSectionInfo {
193   NewSectionInfo() = default;
NewSectionInfoNewSectionInfo194   NewSectionInfo(StringRef Name, std::unique_ptr<MemoryBuffer> &&Buffer)
195       : SectionName(Name), SectionData(std::move(Buffer)) {}
196 
197   StringRef SectionName;
198   std::shared_ptr<MemoryBuffer> SectionData;
199 };
200 
201 // Configuration for copying/stripping a single file.
202 struct CommonConfig {
203   // Main input/output options
204   StringRef InputFilename;
205   FileFormat InputFormat = FileFormat::Unspecified;
206   StringRef OutputFilename;
207   FileFormat OutputFormat = FileFormat::Unspecified;
208 
209   // Only applicable when --output-format!=binary (e.g. elf64-x86-64).
210   std::optional<MachineInfo> OutputArch;
211 
212   // Advanced options
213   StringRef AddGnuDebugLink;
214   // Cached gnu_debuglink's target CRC
215   uint32_t GnuDebugLinkCRC32;
216   std::optional<StringRef> ExtractPartition;
217   uint8_t GapFill = 0;
218   uint64_t PadTo = 0;
219   StringRef SplitDWO;
220   StringRef SymbolsPrefix;
221   StringRef SymbolsPrefixRemove;
222   StringRef AllocSectionsPrefix;
223   DiscardType DiscardMode = DiscardType::None;
224 
225   // Repeated options
226   std::vector<NewSectionInfo> AddSection;
227   std::vector<StringRef> DumpSection;
228   std::vector<NewSectionInfo> UpdateSection;
229 
230   // Section matchers
231   NameMatcher KeepSection;
232   NameMatcher OnlySection;
233   NameMatcher ToRemove;
234 
235   // Symbol matchers
236   NameMatcher SymbolsToGlobalize;
237   NameMatcher SymbolsToKeep;
238   NameMatcher SymbolsToLocalize;
239   NameMatcher SymbolsToRemove;
240   NameMatcher UnneededSymbolsToRemove;
241   NameMatcher SymbolsToWeaken;
242   NameMatcher SymbolsToKeepGlobal;
243 
244   // Map options
245   StringMap<SectionRename> SectionsToRename;
246   StringMap<uint64_t> SetSectionAlignment;
247   StringMap<SectionFlagsUpdate> SetSectionFlags;
248   StringMap<uint64_t> SetSectionType;
249   StringMap<StringRef> SymbolsToRename;
250 
251   // Symbol info specified by --add-symbol option.
252   std::vector<NewSymbolInfo> SymbolsToAdd;
253 
254   // Boolean options
255   bool DeterministicArchives = true;
256   bool ExtractDWO = false;
257   bool ExtractMainPartition = false;
258   bool OnlyKeepDebug = false;
259   bool PreserveDates = false;
260   bool StripAll = false;
261   bool StripAllGNU = false;
262   bool StripDWO = false;
263   bool StripDebug = false;
264   bool StripNonAlloc = false;
265   bool StripSections = false;
266   bool StripUnneeded = false;
267   bool Weaken = false;
268   bool DecompressDebugSections = false;
269 
270   DebugCompressionType CompressionType = DebugCompressionType::None;
271 };
272 
273 } // namespace objcopy
274 } // namespace llvm
275 
276 #endif // LLVM_OBJCOPY_COMMONCONFIG_H
277