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