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 AllocSectionsPrefix;
222   DiscardType DiscardMode = DiscardType::None;
223 
224   // Repeated options
225   std::vector<NewSectionInfo> AddSection;
226   std::vector<StringRef> DumpSection;
227   std::vector<NewSectionInfo> UpdateSection;
228 
229   // Section matchers
230   NameMatcher KeepSection;
231   NameMatcher OnlySection;
232   NameMatcher ToRemove;
233 
234   // Symbol matchers
235   NameMatcher SymbolsToGlobalize;
236   NameMatcher SymbolsToKeep;
237   NameMatcher SymbolsToLocalize;
238   NameMatcher SymbolsToRemove;
239   NameMatcher UnneededSymbolsToRemove;
240   NameMatcher SymbolsToWeaken;
241   NameMatcher SymbolsToKeepGlobal;
242 
243   // Map options
244   StringMap<SectionRename> SectionsToRename;
245   StringMap<uint64_t> SetSectionAlignment;
246   StringMap<SectionFlagsUpdate> SetSectionFlags;
247   StringMap<uint64_t> SetSectionType;
248   StringMap<StringRef> SymbolsToRename;
249 
250   // Symbol info specified by --add-symbol option.
251   std::vector<NewSymbolInfo> SymbolsToAdd;
252 
253   // Boolean options
254   bool DeterministicArchives = true;
255   bool ExtractDWO = false;
256   bool ExtractMainPartition = false;
257   bool OnlyKeepDebug = false;
258   bool PreserveDates = false;
259   bool StripAll = false;
260   bool StripAllGNU = false;
261   bool StripDWO = false;
262   bool StripDebug = false;
263   bool StripNonAlloc = false;
264   bool StripSections = false;
265   bool StripUnneeded = false;
266   bool Weaken = false;
267   bool DecompressDebugSections = false;
268 
269   DebugCompressionType CompressionType = DebugCompressionType::None;
270 };
271 
272 } // namespace objcopy
273 } // namespace llvm
274 
275 #endif // LLVM_OBJCOPY_COMMONCONFIG_H
276