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/Compiler.h" 20 #include "llvm/Support/Compression.h" 21 #include "llvm/Support/GlobPattern.h" 22 #include "llvm/Support/MemoryBuffer.h" 23 #include "llvm/Support/Regex.h" 24 #include <optional> 25 26 namespace llvm { 27 namespace objcopy { 28 29 enum class FileFormat { Unspecified, ELF, Binary, IHex, SREC }; 30 31 // This type keeps track of the machine info for various architectures. This 32 // lets us map architecture names to ELF types and the e_machine value of the 33 // ELF file. 34 struct MachineInfo { MachineInfoMachineInfo35 MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle) 36 : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {} 37 // Alternative constructor that defaults to NONE for OSABI. MachineInfoMachineInfo38 MachineInfo(uint16_t EM, bool Is64, bool IsLittle) 39 : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {} 40 // Default constructor for unset fields. MachineInfoMachineInfo41 MachineInfo() : MachineInfo(0, 0, false, false) {} 42 uint16_t EMachine; 43 uint8_t OSABI; 44 bool Is64Bit; 45 bool IsLittleEndian; 46 }; 47 48 // Flags set by --set-section-flags or --rename-section. Interpretation of these 49 // is format-specific and not all flags are meaningful for all object file 50 // formats. This is a bitmask; many section flags may be set. 51 enum SectionFlag { 52 SecNone = 0, 53 SecAlloc = 1 << 0, 54 SecLoad = 1 << 1, 55 SecNoload = 1 << 2, 56 SecReadonly = 1 << 3, 57 SecDebug = 1 << 4, 58 SecCode = 1 << 5, 59 SecData = 1 << 6, 60 SecRom = 1 << 7, 61 SecMerge = 1 << 8, 62 SecStrings = 1 << 9, 63 SecContents = 1 << 10, 64 SecShare = 1 << 11, 65 SecExclude = 1 << 12, 66 SecLarge = 1 << 13, 67 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecLarge) 68 }; 69 70 struct SectionRename { 71 StringRef OriginalName; 72 StringRef NewName; 73 std::optional<SectionFlag> NewFlags; 74 }; 75 76 struct SectionFlagsUpdate { 77 StringRef Name; 78 SectionFlag NewFlags; 79 }; 80 81 enum class DiscardType { 82 None, // Default 83 All, // --discard-all (-x) 84 Locals, // --discard-locals (-X) 85 }; 86 87 enum class MatchStyle { 88 Literal, // Default for symbols. 89 Wildcard, // Default for sections, or enabled with --wildcard (-w). 90 Regex, // Enabled with --regex. 91 }; 92 93 class NameOrPattern { 94 StringRef Name; 95 // Regex is shared between multiple CommonConfig instances. 96 std::shared_ptr<Regex> R; 97 std::shared_ptr<GlobPattern> G; 98 bool IsPositiveMatch = true; 99 NameOrPattern(StringRef N)100 NameOrPattern(StringRef N) : Name(N) {} NameOrPattern(std::shared_ptr<Regex> R)101 NameOrPattern(std::shared_ptr<Regex> R) : R(R) {} NameOrPattern(std::shared_ptr<GlobPattern> G,bool IsPositiveMatch)102 NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch) 103 : G(G), IsPositiveMatch(IsPositiveMatch) {} 104 105 public: 106 // ErrorCallback is used to handle recoverable errors. An Error returned 107 // by the callback aborts the parsing and is then returned by this function. 108 LLVM_ABI static Expected<NameOrPattern> 109 create(StringRef Pattern, MatchStyle MS, 110 llvm::function_ref<Error(Error)> ErrorCallback); 111 isPositiveMatch()112 bool isPositiveMatch() const { return IsPositiveMatch; } getName()113 std::optional<StringRef> getName() const { 114 if (!R && !G) 115 return Name; 116 return std::nullopt; 117 } 118 bool operator==(StringRef S) const { 119 return R ? R->match(S) : G ? G->match(S) : Name == S; 120 } 121 bool operator!=(StringRef S) const { return !operator==(S); } 122 }; 123 124 // Matcher that checks symbol or section names against the command line flags 125 // provided for that option. 126 class NameMatcher { 127 DenseSet<CachedHashStringRef> PosNames; 128 SmallVector<NameOrPattern, 0> PosPatterns; 129 SmallVector<NameOrPattern, 0> NegMatchers; 130 131 public: addMatcher(Expected<NameOrPattern> Matcher)132 Error addMatcher(Expected<NameOrPattern> Matcher) { 133 if (!Matcher) 134 return Matcher.takeError(); 135 if (Matcher->isPositiveMatch()) { 136 if (std::optional<StringRef> MaybeName = Matcher->getName()) 137 PosNames.insert(CachedHashStringRef(*MaybeName)); 138 else 139 PosPatterns.push_back(std::move(*Matcher)); 140 } else { 141 NegMatchers.push_back(std::move(*Matcher)); 142 } 143 return Error::success(); 144 } matches(StringRef S)145 bool matches(StringRef S) const { 146 return (PosNames.contains(CachedHashStringRef(S)) || 147 is_contained(PosPatterns, S)) && 148 !is_contained(NegMatchers, S); 149 } empty()150 bool empty() const { 151 return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty(); 152 } 153 }; 154 155 enum class AdjustKind { Set, Add, Subtract }; 156 157 struct AddressUpdate { 158 uint64_t Value = 0; 159 AdjustKind Kind = AdjustKind::Add; 160 }; 161 162 struct SectionPatternAddressUpdate { 163 NameMatcher SectionPattern; 164 AddressUpdate Update; 165 }; 166 167 enum class SymbolFlag { 168 Global, 169 Local, 170 Weak, 171 Default, 172 Hidden, 173 Protected, 174 File, 175 Section, 176 Object, 177 Function, 178 IndirectFunction, 179 Debug, 180 Constructor, 181 Warning, 182 Indirect, 183 Synthetic, 184 UniqueObject, 185 }; 186 187 // Symbol info specified by --add-symbol option. Symbol flags not supported 188 // by a concrete format should be ignored. 189 struct NewSymbolInfo { 190 StringRef SymbolName; 191 StringRef SectionName; 192 uint64_t Value = 0; 193 SmallVector<SymbolFlag, 0> Flags; 194 SmallVector<StringRef, 0> BeforeSyms; 195 }; 196 197 // Specify section name and section body for newly added or updated section. 198 struct NewSectionInfo { 199 NewSectionInfo() = default; NewSectionInfoNewSectionInfo200 NewSectionInfo(StringRef Name, std::unique_ptr<MemoryBuffer> &&Buffer) 201 : SectionName(Name), SectionData(std::move(Buffer)) {} 202 203 StringRef SectionName; 204 std::shared_ptr<MemoryBuffer> SectionData; 205 }; 206 207 // Configuration for copying/stripping a single file. 208 struct CommonConfig { 209 // Main input/output options 210 StringRef InputFilename; 211 FileFormat InputFormat = FileFormat::Unspecified; 212 StringRef OutputFilename; 213 FileFormat OutputFormat = FileFormat::Unspecified; 214 215 // Only applicable when --output-format!=binary (e.g. elf64-x86-64). 216 std::optional<MachineInfo> OutputArch; 217 218 // Advanced options 219 StringRef AddGnuDebugLink; 220 // Cached gnu_debuglink's target CRC 221 uint32_t GnuDebugLinkCRC32; 222 std::optional<StringRef> ExtractPartition; 223 uint8_t GapFill = 0; 224 uint64_t PadTo = 0; 225 StringRef SplitDWO; 226 StringRef SymbolsPrefix; 227 StringRef SymbolsPrefixRemove; 228 StringRef AllocSectionsPrefix; 229 DiscardType DiscardMode = DiscardType::None; 230 231 // Repeated options 232 SmallVector<NewSectionInfo, 0> AddSection; 233 SmallVector<StringRef, 0> DumpSection; 234 SmallVector<NewSectionInfo, 0> UpdateSection; 235 SmallVector<SectionPatternAddressUpdate, 0> ChangeSectionAddress; 236 237 // Section matchers 238 NameMatcher KeepSection; 239 NameMatcher OnlySection; 240 NameMatcher ToRemove; 241 242 // Symbol matchers 243 NameMatcher SymbolsToGlobalize; 244 NameMatcher SymbolsToKeep; 245 NameMatcher SymbolsToLocalize; 246 NameMatcher SymbolsToRemove; 247 NameMatcher UnneededSymbolsToRemove; 248 NameMatcher SymbolsToWeaken; 249 NameMatcher SymbolsToKeepGlobal; 250 NameMatcher SymbolsToSkip; 251 252 // Map options 253 StringMap<SectionRename> SectionsToRename; 254 StringMap<uint64_t> SetSectionAlignment; 255 StringMap<SectionFlagsUpdate> SetSectionFlags; 256 StringMap<uint64_t> SetSectionType; 257 StringMap<StringRef> SymbolsToRename; 258 259 // Symbol info specified by --add-symbol option. 260 SmallVector<NewSymbolInfo, 0> SymbolsToAdd; 261 262 // Integer options 263 int64_t ChangeSectionLMAValAll = 0; 264 265 // Boolean options 266 bool DeterministicArchives = true; 267 bool ExtractDWO = false; 268 bool ExtractMainPartition = false; 269 bool OnlyKeepDebug = false; 270 bool PreserveDates = false; 271 bool StripAll = false; 272 bool StripAllGNU = false; 273 bool StripDWO = false; 274 bool StripDebug = false; 275 bool StripNonAlloc = false; 276 bool StripSections = false; 277 bool StripUnneeded = false; 278 bool Weaken = false; 279 bool DecompressDebugSections = false; 280 281 DebugCompressionType CompressionType = DebugCompressionType::None; 282 283 SmallVector<std::pair<NameMatcher, llvm::DebugCompressionType>, 0> 284 compressSections; 285 286 // ErrorCallback is used to handle recoverable errors. An Error returned 287 // by the callback aborts the execution and is then returned to the caller. 288 // If the callback is not set, the errors are not issued. 289 std::function<Error(Error)> ErrorCallback; 290 }; 291 292 } // namespace objcopy 293 } // namespace llvm 294 295 #endif // LLVM_OBJCOPY_COMMONCONFIG_H 296