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
27namespace llvm {
28namespace objcopy {
29
30enum 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.
40struct 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.
57enum 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
76struct SectionRename {
77  StringRef OriginalName;
78  StringRef NewName;
79  std::optional<SectionFlag> NewFlags;
80};
81
82struct SectionFlagsUpdate {
83  StringRef Name;
84  SectionFlag NewFlags;
85};
86
87enum class DiscardType {
88  None,   // Default
89  All,    // --discard-all (-x)
90  Locals, // --discard-locals (-X)
91};
92
93enum class MatchStyle {
94  Literal,  // Default for symbols.
95  Wildcard, // Default for sections, or enabled with --wildcard (-w).
96  Regex,    // Enabled with --regex.
97};
98
99class 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
106  NameOrPattern(StringRef N) : Name(N) {}
107  NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
108  NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch)
109      : G(G), IsPositiveMatch(IsPositiveMatch) {}
110
111public:
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
118  bool isPositiveMatch() const { return IsPositiveMatch; }
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.
132class NameMatcher {
133  DenseSet<CachedHashStringRef> PosNames;
134  std::vector<NameOrPattern> PosPatterns;
135  std::vector<NameOrPattern> NegMatchers;
136
137public:
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  }
151  bool matches(StringRef S) const {
152    return (PosNames.contains(CachedHashStringRef(S)) ||
153            is_contained(PosPatterns, S)) &&
154           !is_contained(NegMatchers, S);
155  }
156  bool empty() const {
157    return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty();
158  }
159};
160
161enum 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.
183struct 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.
192struct NewSectionInfo {
193  NewSectionInfo() = default;
194  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.
202struct 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