xref: /llvm-project/llvm/include/llvm/ObjCopy/CommonConfig.h (revision 10772807ab72ce2b68d76816f8753219b2acbac3)
1f75da0c8SAlexey Lapshin //===- CommonConfig.h -------------------------------------------*- C++ -*-===//
2f75da0c8SAlexey Lapshin //
3f75da0c8SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f75da0c8SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
5f75da0c8SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f75da0c8SAlexey Lapshin //
7f75da0c8SAlexey Lapshin //===----------------------------------------------------------------------===//
8f75da0c8SAlexey Lapshin 
9f75da0c8SAlexey Lapshin #ifndef LLVM_OBJCOPY_COMMONCONFIG_H
10f75da0c8SAlexey Lapshin #define LLVM_OBJCOPY_COMMONCONFIG_H
11f75da0c8SAlexey Lapshin 
12f75da0c8SAlexey Lapshin #include "llvm/ADT/ArrayRef.h"
13f75da0c8SAlexey Lapshin #include "llvm/ADT/CachedHashString.h"
14f75da0c8SAlexey Lapshin #include "llvm/ADT/DenseSet.h"
15f75da0c8SAlexey Lapshin #include "llvm/ADT/SmallVector.h"
16f75da0c8SAlexey Lapshin #include "llvm/ADT/StringMap.h"
17f75da0c8SAlexey Lapshin #include "llvm/ADT/StringRef.h"
18f75da0c8SAlexey Lapshin #include "llvm/Object/ELFTypes.h"
190d98582cSFangrui Song #include "llvm/Support/Compression.h"
20f75da0c8SAlexey Lapshin #include "llvm/Support/GlobPattern.h"
21a6f3fedcSAlexey Lapshin #include "llvm/Support/MemoryBuffer.h"
22f75da0c8SAlexey Lapshin #include "llvm/Support/Regex.h"
23316372f8SKazu Hirata #include <optional>
24f75da0c8SAlexey Lapshin 
25f75da0c8SAlexey Lapshin namespace llvm {
26f75da0c8SAlexey Lapshin namespace objcopy {
27f75da0c8SAlexey Lapshin 
287ddc3205Squic-areg enum class FileFormat { Unspecified, ELF, Binary, IHex, SREC };
29f75da0c8SAlexey Lapshin 
30f75da0c8SAlexey Lapshin // This type keeps track of the machine info for various architectures. This
31f75da0c8SAlexey Lapshin // lets us map architecture names to ELF types and the e_machine value of the
32f75da0c8SAlexey Lapshin // ELF file.
33f75da0c8SAlexey Lapshin struct MachineInfo {
34f75da0c8SAlexey Lapshin   MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle)
35f75da0c8SAlexey Lapshin       : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {}
36f75da0c8SAlexey Lapshin   // Alternative constructor that defaults to NONE for OSABI.
37f75da0c8SAlexey Lapshin   MachineInfo(uint16_t EM, bool Is64, bool IsLittle)
38f75da0c8SAlexey Lapshin       : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {}
39f75da0c8SAlexey Lapshin   // Default constructor for unset fields.
40f75da0c8SAlexey Lapshin   MachineInfo() : MachineInfo(0, 0, false, false) {}
41f75da0c8SAlexey Lapshin   uint16_t EMachine;
42f75da0c8SAlexey Lapshin   uint8_t OSABI;
43f75da0c8SAlexey Lapshin   bool Is64Bit;
44f75da0c8SAlexey Lapshin   bool IsLittleEndian;
45f75da0c8SAlexey Lapshin };
46f75da0c8SAlexey Lapshin 
47f75da0c8SAlexey Lapshin // Flags set by --set-section-flags or --rename-section. Interpretation of these
48f75da0c8SAlexey Lapshin // is format-specific and not all flags are meaningful for all object file
49f75da0c8SAlexey Lapshin // formats. This is a bitmask; many section flags may be set.
50f75da0c8SAlexey Lapshin enum SectionFlag {
51f75da0c8SAlexey Lapshin   SecNone = 0,
52f75da0c8SAlexey Lapshin   SecAlloc = 1 << 0,
53f75da0c8SAlexey Lapshin   SecLoad = 1 << 1,
54f75da0c8SAlexey Lapshin   SecNoload = 1 << 2,
55f75da0c8SAlexey Lapshin   SecReadonly = 1 << 3,
56f75da0c8SAlexey Lapshin   SecDebug = 1 << 4,
57f75da0c8SAlexey Lapshin   SecCode = 1 << 5,
58f75da0c8SAlexey Lapshin   SecData = 1 << 6,
59f75da0c8SAlexey Lapshin   SecRom = 1 << 7,
60f75da0c8SAlexey Lapshin   SecMerge = 1 << 8,
61f75da0c8SAlexey Lapshin   SecStrings = 1 << 9,
62f75da0c8SAlexey Lapshin   SecContents = 1 << 10,
63f75da0c8SAlexey Lapshin   SecShare = 1 << 11,
64f75da0c8SAlexey Lapshin   SecExclude = 1 << 12,
656f1395a1SThomas Köppe   SecLarge = 1 << 13,
666f1395a1SThomas Köppe   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecLarge)
67f75da0c8SAlexey Lapshin };
68f75da0c8SAlexey Lapshin 
69f75da0c8SAlexey Lapshin struct SectionRename {
70f75da0c8SAlexey Lapshin   StringRef OriginalName;
71f75da0c8SAlexey Lapshin   StringRef NewName;
72316372f8SKazu Hirata   std::optional<SectionFlag> NewFlags;
73f75da0c8SAlexey Lapshin };
74f75da0c8SAlexey Lapshin 
75f75da0c8SAlexey Lapshin struct SectionFlagsUpdate {
76f75da0c8SAlexey Lapshin   StringRef Name;
77f75da0c8SAlexey Lapshin   SectionFlag NewFlags;
78f75da0c8SAlexey Lapshin };
79f75da0c8SAlexey Lapshin 
80f75da0c8SAlexey Lapshin enum class DiscardType {
81f75da0c8SAlexey Lapshin   None,   // Default
82f75da0c8SAlexey Lapshin   All,    // --discard-all (-x)
83f75da0c8SAlexey Lapshin   Locals, // --discard-locals (-X)
84f75da0c8SAlexey Lapshin };
85f75da0c8SAlexey Lapshin 
86f75da0c8SAlexey Lapshin enum class MatchStyle {
87f75da0c8SAlexey Lapshin   Literal,  // Default for symbols.
88f75da0c8SAlexey Lapshin   Wildcard, // Default for sections, or enabled with --wildcard (-w).
89f75da0c8SAlexey Lapshin   Regex,    // Enabled with --regex.
90f75da0c8SAlexey Lapshin };
91f75da0c8SAlexey Lapshin 
92f75da0c8SAlexey Lapshin class NameOrPattern {
93f75da0c8SAlexey Lapshin   StringRef Name;
94f75da0c8SAlexey Lapshin   // Regex is shared between multiple CommonConfig instances.
95f75da0c8SAlexey Lapshin   std::shared_ptr<Regex> R;
96f75da0c8SAlexey Lapshin   std::shared_ptr<GlobPattern> G;
97f75da0c8SAlexey Lapshin   bool IsPositiveMatch = true;
98f75da0c8SAlexey Lapshin 
99f75da0c8SAlexey Lapshin   NameOrPattern(StringRef N) : Name(N) {}
100f75da0c8SAlexey Lapshin   NameOrPattern(std::shared_ptr<Regex> R) : R(R) {}
101f75da0c8SAlexey Lapshin   NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch)
102f75da0c8SAlexey Lapshin       : G(G), IsPositiveMatch(IsPositiveMatch) {}
103f75da0c8SAlexey Lapshin 
104f75da0c8SAlexey Lapshin public:
105f75da0c8SAlexey Lapshin   // ErrorCallback is used to handle recoverable errors. An Error returned
106f75da0c8SAlexey Lapshin   // by the callback aborts the parsing and is then returned by this function.
107f75da0c8SAlexey Lapshin   static Expected<NameOrPattern>
108f75da0c8SAlexey Lapshin   create(StringRef Pattern, MatchStyle MS,
109f75da0c8SAlexey Lapshin          llvm::function_ref<Error(Error)> ErrorCallback);
110f75da0c8SAlexey Lapshin 
111f75da0c8SAlexey Lapshin   bool isPositiveMatch() const { return IsPositiveMatch; }
112ec941432SFangrui Song   std::optional<StringRef> getName() const {
113f75da0c8SAlexey Lapshin     if (!R && !G)
114f75da0c8SAlexey Lapshin       return Name;
115aadaafacSKazu Hirata     return std::nullopt;
116f75da0c8SAlexey Lapshin   }
117f75da0c8SAlexey Lapshin   bool operator==(StringRef S) const {
118f75da0c8SAlexey Lapshin     return R ? R->match(S) : G ? G->match(S) : Name == S;
119f75da0c8SAlexey Lapshin   }
120f75da0c8SAlexey Lapshin   bool operator!=(StringRef S) const { return !operator==(S); }
121f75da0c8SAlexey Lapshin };
122f75da0c8SAlexey Lapshin 
123f75da0c8SAlexey Lapshin // Matcher that checks symbol or section names against the command line flags
124f75da0c8SAlexey Lapshin // provided for that option.
125f75da0c8SAlexey Lapshin class NameMatcher {
126f75da0c8SAlexey Lapshin   DenseSet<CachedHashStringRef> PosNames;
12753613044SFangrui Song   SmallVector<NameOrPattern, 0> PosPatterns;
12853613044SFangrui Song   SmallVector<NameOrPattern, 0> NegMatchers;
129f75da0c8SAlexey Lapshin 
130f75da0c8SAlexey Lapshin public:
131f75da0c8SAlexey Lapshin   Error addMatcher(Expected<NameOrPattern> Matcher) {
132f75da0c8SAlexey Lapshin     if (!Matcher)
133f75da0c8SAlexey Lapshin       return Matcher.takeError();
134f75da0c8SAlexey Lapshin     if (Matcher->isPositiveMatch()) {
135ec941432SFangrui Song       if (std::optional<StringRef> MaybeName = Matcher->getName())
136f75da0c8SAlexey Lapshin         PosNames.insert(CachedHashStringRef(*MaybeName));
137f75da0c8SAlexey Lapshin       else
138f75da0c8SAlexey Lapshin         PosPatterns.push_back(std::move(*Matcher));
139f75da0c8SAlexey Lapshin     } else {
140f75da0c8SAlexey Lapshin       NegMatchers.push_back(std::move(*Matcher));
141f75da0c8SAlexey Lapshin     }
142f75da0c8SAlexey Lapshin     return Error::success();
143f75da0c8SAlexey Lapshin   }
144f75da0c8SAlexey Lapshin   bool matches(StringRef S) const {
145f75da0c8SAlexey Lapshin     return (PosNames.contains(CachedHashStringRef(S)) ||
146f75da0c8SAlexey Lapshin             is_contained(PosPatterns, S)) &&
147f75da0c8SAlexey Lapshin            !is_contained(NegMatchers, S);
148f75da0c8SAlexey Lapshin   }
149f75da0c8SAlexey Lapshin   bool empty() const {
150f75da0c8SAlexey Lapshin     return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty();
151f75da0c8SAlexey Lapshin   }
152f75da0c8SAlexey Lapshin };
153f75da0c8SAlexey Lapshin 
1542b2f4ae0SEleanor Bonnici enum class AdjustKind { Set, Add, Subtract };
1552b2f4ae0SEleanor Bonnici 
1562b2f4ae0SEleanor Bonnici struct AddressUpdate {
1572b2f4ae0SEleanor Bonnici   uint64_t Value = 0;
1582b2f4ae0SEleanor Bonnici   AdjustKind Kind = AdjustKind::Add;
1592b2f4ae0SEleanor Bonnici };
1602b2f4ae0SEleanor Bonnici 
1612b2f4ae0SEleanor Bonnici struct SectionPatternAddressUpdate {
1622b2f4ae0SEleanor Bonnici   NameMatcher SectionPattern;
1632b2f4ae0SEleanor Bonnici   AddressUpdate Update;
1642b2f4ae0SEleanor Bonnici };
1652b2f4ae0SEleanor Bonnici 
166f75da0c8SAlexey Lapshin enum class SymbolFlag {
167f75da0c8SAlexey Lapshin   Global,
168f75da0c8SAlexey Lapshin   Local,
169f75da0c8SAlexey Lapshin   Weak,
170f75da0c8SAlexey Lapshin   Default,
171f75da0c8SAlexey Lapshin   Hidden,
172f75da0c8SAlexey Lapshin   Protected,
173f75da0c8SAlexey Lapshin   File,
174f75da0c8SAlexey Lapshin   Section,
175f75da0c8SAlexey Lapshin   Object,
176f75da0c8SAlexey Lapshin   Function,
177f75da0c8SAlexey Lapshin   IndirectFunction,
178f75da0c8SAlexey Lapshin   Debug,
179f75da0c8SAlexey Lapshin   Constructor,
180f75da0c8SAlexey Lapshin   Warning,
181f75da0c8SAlexey Lapshin   Indirect,
182f75da0c8SAlexey Lapshin   Synthetic,
183f75da0c8SAlexey Lapshin   UniqueObject,
184f75da0c8SAlexey Lapshin };
185f75da0c8SAlexey Lapshin 
186f75da0c8SAlexey Lapshin // Symbol info specified by --add-symbol option. Symbol flags not supported
187f75da0c8SAlexey Lapshin // by a concrete format should be ignored.
188f75da0c8SAlexey Lapshin struct NewSymbolInfo {
189f75da0c8SAlexey Lapshin   StringRef SymbolName;
190f75da0c8SAlexey Lapshin   StringRef SectionName;
191f75da0c8SAlexey Lapshin   uint64_t Value = 0;
19253613044SFangrui Song   SmallVector<SymbolFlag, 0> Flags;
19353613044SFangrui Song   SmallVector<StringRef, 0> BeforeSyms;
194f75da0c8SAlexey Lapshin };
195f75da0c8SAlexey Lapshin 
196a6f3fedcSAlexey Lapshin // Specify section name and section body for newly added or updated section.
197a6f3fedcSAlexey Lapshin struct NewSectionInfo {
198a6f3fedcSAlexey Lapshin   NewSectionInfo() = default;
199a6f3fedcSAlexey Lapshin   NewSectionInfo(StringRef Name, std::unique_ptr<MemoryBuffer> &&Buffer)
200a6f3fedcSAlexey Lapshin       : SectionName(Name), SectionData(std::move(Buffer)) {}
201a6f3fedcSAlexey Lapshin 
202a6f3fedcSAlexey Lapshin   StringRef SectionName;
203a6f3fedcSAlexey Lapshin   std::shared_ptr<MemoryBuffer> SectionData;
204a6f3fedcSAlexey Lapshin };
205a6f3fedcSAlexey Lapshin 
206f75da0c8SAlexey Lapshin // Configuration for copying/stripping a single file.
207f75da0c8SAlexey Lapshin struct CommonConfig {
208f75da0c8SAlexey Lapshin   // Main input/output options
209f75da0c8SAlexey Lapshin   StringRef InputFilename;
210f75da0c8SAlexey Lapshin   FileFormat InputFormat = FileFormat::Unspecified;
211f75da0c8SAlexey Lapshin   StringRef OutputFilename;
212f75da0c8SAlexey Lapshin   FileFormat OutputFormat = FileFormat::Unspecified;
213f75da0c8SAlexey Lapshin 
214f75da0c8SAlexey Lapshin   // Only applicable when --output-format!=binary (e.g. elf64-x86-64).
215316372f8SKazu Hirata   std::optional<MachineInfo> OutputArch;
216f75da0c8SAlexey Lapshin 
217f75da0c8SAlexey Lapshin   // Advanced options
218f75da0c8SAlexey Lapshin   StringRef AddGnuDebugLink;
219f75da0c8SAlexey Lapshin   // Cached gnu_debuglink's target CRC
220f75da0c8SAlexey Lapshin   uint32_t GnuDebugLinkCRC32;
221ec941432SFangrui Song   std::optional<StringRef> ExtractPartition;
2224070dffdSquic-akaryaki   uint8_t GapFill = 0;
2234070dffdSquic-akaryaki   uint64_t PadTo = 0;
224f75da0c8SAlexey Lapshin   StringRef SplitDWO;
225f75da0c8SAlexey Lapshin   StringRef SymbolsPrefix;
2261b87ebceSYi Kong   StringRef SymbolsPrefixRemove;
227f75da0c8SAlexey Lapshin   StringRef AllocSectionsPrefix;
228f75da0c8SAlexey Lapshin   DiscardType DiscardMode = DiscardType::None;
229f75da0c8SAlexey Lapshin 
230f75da0c8SAlexey Lapshin   // Repeated options
23153613044SFangrui Song   SmallVector<NewSectionInfo, 0> AddSection;
23253613044SFangrui Song   SmallVector<StringRef, 0> DumpSection;
23353613044SFangrui Song   SmallVector<NewSectionInfo, 0> UpdateSection;
2342b2f4ae0SEleanor Bonnici   SmallVector<SectionPatternAddressUpdate, 0> ChangeSectionAddress;
235f75da0c8SAlexey Lapshin 
236f75da0c8SAlexey Lapshin   // Section matchers
237f75da0c8SAlexey Lapshin   NameMatcher KeepSection;
238f75da0c8SAlexey Lapshin   NameMatcher OnlySection;
239f75da0c8SAlexey Lapshin   NameMatcher ToRemove;
240f75da0c8SAlexey Lapshin 
241f75da0c8SAlexey Lapshin   // Symbol matchers
242f75da0c8SAlexey Lapshin   NameMatcher SymbolsToGlobalize;
243f75da0c8SAlexey Lapshin   NameMatcher SymbolsToKeep;
244f75da0c8SAlexey Lapshin   NameMatcher SymbolsToLocalize;
245f75da0c8SAlexey Lapshin   NameMatcher SymbolsToRemove;
246f75da0c8SAlexey Lapshin   NameMatcher UnneededSymbolsToRemove;
247f75da0c8SAlexey Lapshin   NameMatcher SymbolsToWeaken;
248f75da0c8SAlexey Lapshin   NameMatcher SymbolsToKeepGlobal;
2494946cc37SIlia Kuklin   NameMatcher SymbolsToSkip;
250f75da0c8SAlexey Lapshin 
251f75da0c8SAlexey Lapshin   // Map options
252f75da0c8SAlexey Lapshin   StringMap<SectionRename> SectionsToRename;
253f75da0c8SAlexey Lapshin   StringMap<uint64_t> SetSectionAlignment;
254f75da0c8SAlexey Lapshin   StringMap<SectionFlagsUpdate> SetSectionFlags;
255b28412d5SFangrui Song   StringMap<uint64_t> SetSectionType;
256f75da0c8SAlexey Lapshin   StringMap<StringRef> SymbolsToRename;
257f75da0c8SAlexey Lapshin 
258f75da0c8SAlexey Lapshin   // Symbol info specified by --add-symbol option.
25953613044SFangrui Song   SmallVector<NewSymbolInfo, 0> SymbolsToAdd;
260f75da0c8SAlexey Lapshin 
26133200363SEleanor Bonnici   // Integer options
26233200363SEleanor Bonnici   int64_t ChangeSectionLMAValAll = 0;
26333200363SEleanor Bonnici 
264f75da0c8SAlexey Lapshin   // Boolean options
265f75da0c8SAlexey Lapshin   bool DeterministicArchives = true;
266f75da0c8SAlexey Lapshin   bool ExtractDWO = false;
267f75da0c8SAlexey Lapshin   bool ExtractMainPartition = false;
268f75da0c8SAlexey Lapshin   bool OnlyKeepDebug = false;
269f75da0c8SAlexey Lapshin   bool PreserveDates = false;
270f75da0c8SAlexey Lapshin   bool StripAll = false;
271f75da0c8SAlexey Lapshin   bool StripAllGNU = false;
272f75da0c8SAlexey Lapshin   bool StripDWO = false;
273f75da0c8SAlexey Lapshin   bool StripDebug = false;
274f75da0c8SAlexey Lapshin   bool StripNonAlloc = false;
275f75da0c8SAlexey Lapshin   bool StripSections = false;
276f75da0c8SAlexey Lapshin   bool StripUnneeded = false;
277f75da0c8SAlexey Lapshin   bool Weaken = false;
278f75da0c8SAlexey Lapshin   bool DecompressDebugSections = false;
279f75da0c8SAlexey Lapshin 
280f75da0c8SAlexey Lapshin   DebugCompressionType CompressionType = DebugCompressionType::None;
28107942987SFangrui Song 
28207942987SFangrui Song   SmallVector<std::pair<NameMatcher, llvm::DebugCompressionType>, 0>
28307942987SFangrui Song       compressSections;
284*10772807SIgor Kudrin 
285*10772807SIgor Kudrin   // ErrorCallback is used to handle recoverable errors. An Error returned
286*10772807SIgor Kudrin   // by the callback aborts the execution and is then returned to the caller.
287*10772807SIgor Kudrin   // If the callback is not set, the errors are not issued.
288*10772807SIgor Kudrin   std::function<Error(Error)> ErrorCallback;
289f75da0c8SAlexey Lapshin };
290f75da0c8SAlexey Lapshin 
291f75da0c8SAlexey Lapshin } // namespace objcopy
292f75da0c8SAlexey Lapshin } // namespace llvm
293f75da0c8SAlexey Lapshin 
294f75da0c8SAlexey Lapshin #endif // LLVM_OBJCOPY_COMMONCONFIG_H
295