1 //===- CopyConfig.h -------------------------------------------------------===// 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_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H 10 #define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H 11 12 #include "ELF/ELFConfig.h" 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/BitmaskEnum.h" 15 #include "llvm/ADT/DenseSet.h" 16 #include "llvm/ADT/Optional.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringMap.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Object/ELFTypes.h" 21 #include "llvm/Support/Allocator.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/GlobPattern.h" 24 #include "llvm/Support/Regex.h" 25 // Necessary for llvm::DebugCompressionType::None 26 #include "llvm/Target/TargetOptions.h" 27 #include <vector> 28 29 namespace llvm { 30 namespace objcopy { 31 32 enum class FileFormat { 33 Unspecified, 34 ELF, 35 Binary, 36 IHex, 37 }; 38 39 // This type keeps track of the machine info for various architectures. This 40 // lets us map architecture names to ELF types and the e_machine value of the 41 // ELF file. 42 struct MachineInfo { MachineInfoMachineInfo43 MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle) 44 : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {} 45 // Alternative constructor that defaults to NONE for OSABI. MachineInfoMachineInfo46 MachineInfo(uint16_t EM, bool Is64, bool IsLittle) 47 : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {} 48 // Default constructor for unset fields. MachineInfoMachineInfo49 MachineInfo() : MachineInfo(0, 0, false, false) {} 50 uint16_t EMachine; 51 uint8_t OSABI; 52 bool Is64Bit; 53 bool IsLittleEndian; 54 }; 55 56 // Flags set by --set-section-flags or --rename-section. Interpretation of these 57 // is format-specific and not all flags are meaningful for all object file 58 // formats. This is a bitmask; many section flags may be set. 59 enum SectionFlag { 60 SecNone = 0, 61 SecAlloc = 1 << 0, 62 SecLoad = 1 << 1, 63 SecNoload = 1 << 2, 64 SecReadonly = 1 << 3, 65 SecDebug = 1 << 4, 66 SecCode = 1 << 5, 67 SecData = 1 << 6, 68 SecRom = 1 << 7, 69 SecMerge = 1 << 8, 70 SecStrings = 1 << 9, 71 SecContents = 1 << 10, 72 SecShare = 1 << 11, 73 SecExclude = 1 << 12, 74 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecExclude) 75 }; 76 77 struct SectionRename { 78 StringRef OriginalName; 79 StringRef NewName; 80 Optional<SectionFlag> NewFlags; 81 }; 82 83 struct SectionFlagsUpdate { 84 StringRef Name; 85 SectionFlag NewFlags; 86 }; 87 88 enum class DiscardType { 89 None, // Default 90 All, // --discard-all (-x) 91 Locals, // --discard-locals (-X) 92 }; 93 94 enum class MatchStyle { 95 Literal, // Default for symbols. 96 Wildcard, // Default for sections, or enabled with --wildcard (-w). 97 Regex, // Enabled with --regex. 98 }; 99 100 class NameOrPattern { 101 StringRef Name; 102 // Regex is shared between multiple CopyConfig instances. 103 std::shared_ptr<Regex> R; 104 std::shared_ptr<GlobPattern> G; 105 bool IsPositiveMatch = true; 106 NameOrPattern(StringRef N)107 NameOrPattern(StringRef N) : Name(N) {} NameOrPattern(std::shared_ptr<Regex> R)108 NameOrPattern(std::shared_ptr<Regex> R) : R(R) {} NameOrPattern(std::shared_ptr<GlobPattern> G,bool IsPositiveMatch)109 NameOrPattern(std::shared_ptr<GlobPattern> G, bool IsPositiveMatch) 110 : G(G), IsPositiveMatch(IsPositiveMatch) {} 111 112 public: 113 // ErrorCallback is used to handle recoverable errors. An Error returned 114 // by the callback aborts the parsing and is then returned by this function. 115 static Expected<NameOrPattern> 116 create(StringRef Pattern, MatchStyle MS, 117 llvm::function_ref<Error(Error)> ErrorCallback); 118 isPositiveMatch()119 bool isPositiveMatch() const { return IsPositiveMatch; } 120 bool operator==(StringRef S) const { 121 return R ? R->match(S) : G ? G->match(S) : Name == S; 122 } 123 bool operator!=(StringRef S) const { return !operator==(S); } 124 }; 125 126 // Matcher that checks symbol or section names against the command line flags 127 // provided for that option. 128 class NameMatcher { 129 std::vector<NameOrPattern> PosMatchers; 130 std::vector<NameOrPattern> NegMatchers; 131 132 public: addMatcher(Expected<NameOrPattern> Matcher)133 Error addMatcher(Expected<NameOrPattern> Matcher) { 134 if (!Matcher) 135 return Matcher.takeError(); 136 if (Matcher->isPositiveMatch()) 137 PosMatchers.push_back(std::move(*Matcher)); 138 else 139 NegMatchers.push_back(std::move(*Matcher)); 140 return Error::success(); 141 } matches(StringRef S)142 bool matches(StringRef S) const { 143 return is_contained(PosMatchers, S) && !is_contained(NegMatchers, S); 144 } empty()145 bool empty() const { return PosMatchers.empty() && NegMatchers.empty(); } 146 }; 147 148 // Configuration for copying/stripping a single file. 149 struct CopyConfig { 150 // Format-specific options to be initialized lazily when needed. 151 Optional<elf::ELFCopyConfig> ELF; 152 153 // Main input/output options 154 StringRef InputFilename; 155 FileFormat InputFormat = FileFormat::Unspecified; 156 StringRef OutputFilename; 157 FileFormat OutputFormat = FileFormat::Unspecified; 158 159 // Only applicable when --output-format!=binary (e.g. elf64-x86-64). 160 Optional<MachineInfo> OutputArch; 161 162 // Advanced options 163 StringRef AddGnuDebugLink; 164 // Cached gnu_debuglink's target CRC 165 uint32_t GnuDebugLinkCRC32; 166 StringRef BuildIdLinkDir; 167 Optional<StringRef> BuildIdLinkInput; 168 Optional<StringRef> BuildIdLinkOutput; 169 Optional<StringRef> ExtractPartition; 170 StringRef SplitDWO; 171 StringRef SymbolsPrefix; 172 StringRef AllocSectionsPrefix; 173 DiscardType DiscardMode = DiscardType::None; 174 Optional<StringRef> NewSymbolVisibility; 175 176 // Repeated options 177 std::vector<StringRef> AddSection; 178 std::vector<StringRef> DumpSection; 179 std::vector<StringRef> SymbolsToAdd; 180 std::vector<StringRef> RPathToAdd; 181 std::vector<StringRef> RPathToPrepend; 182 DenseMap<StringRef, StringRef> RPathsToUpdate; 183 DenseMap<StringRef, StringRef> InstallNamesToUpdate; 184 DenseSet<StringRef> RPathsToRemove; 185 186 // install-name-tool's id option 187 Optional<StringRef> SharedLibId; 188 189 // Section matchers 190 NameMatcher KeepSection; 191 NameMatcher OnlySection; 192 NameMatcher ToRemove; 193 194 // Symbol matchers 195 NameMatcher SymbolsToGlobalize; 196 NameMatcher SymbolsToKeep; 197 NameMatcher SymbolsToLocalize; 198 NameMatcher SymbolsToRemove; 199 NameMatcher UnneededSymbolsToRemove; 200 NameMatcher SymbolsToWeaken; 201 NameMatcher SymbolsToKeepGlobal; 202 203 // Map options 204 StringMap<SectionRename> SectionsToRename; 205 StringMap<uint64_t> SetSectionAlignment; 206 StringMap<SectionFlagsUpdate> SetSectionFlags; 207 StringMap<StringRef> SymbolsToRename; 208 209 // ELF entry point address expression. The input parameter is an entry point 210 // address in the input ELF file. The entry address in the output file is 211 // calculated with EntryExpr(input_address), when either --set-start or 212 // --change-start is used. 213 std::function<uint64_t(uint64_t)> EntryExpr; 214 215 // Boolean options 216 bool AllowBrokenLinks = false; 217 bool DeterministicArchives = true; 218 bool ExtractDWO = false; 219 bool ExtractMainPartition = false; 220 bool KeepFileSymbols = false; 221 bool LocalizeHidden = false; 222 bool OnlyKeepDebug = false; 223 bool PreserveDates = false; 224 bool StripAll = false; 225 bool StripAllGNU = false; 226 bool StripDWO = false; 227 bool StripDebug = false; 228 bool StripNonAlloc = false; 229 bool StripSections = false; 230 bool StripSwiftSymbols = false; 231 bool StripUnneeded = false; 232 bool Weaken = false; 233 bool DecompressDebugSections = false; 234 // install-name-tool's --delete_all_rpaths 235 bool RemoveAllRpaths = false; 236 237 DebugCompressionType CompressionType = DebugCompressionType::None; 238 239 // parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on 240 // success or returns an Error otherwise. parseELFConfigCopyConfig241 Error parseELFConfig() { 242 if (!ELF) { 243 Expected<elf::ELFCopyConfig> ELFConfig = elf::parseConfig(*this); 244 if (!ELFConfig) 245 return ELFConfig.takeError(); 246 ELF = *ELFConfig; 247 } 248 return Error::success(); 249 } 250 }; 251 252 // Configuration for the overall invocation of this tool. When invoked as 253 // objcopy, will always contain exactly one CopyConfig. When invoked as strip, 254 // will contain one or more CopyConfigs. 255 struct DriverConfig { 256 SmallVector<CopyConfig, 1> CopyConfigs; 257 BumpPtrAllocator Alloc; 258 }; 259 260 // ParseObjcopyOptions returns the config and sets the input arguments. If a 261 // help flag is set then ParseObjcopyOptions will print the help messege and 262 // exit. ErrorCallback is used to handle recoverable errors. An Error returned 263 // by the callback aborts the parsing and is then returned by this function. 264 Expected<DriverConfig> 265 parseObjcopyOptions(ArrayRef<const char *> ArgsArr, 266 llvm::function_ref<Error(Error)> ErrorCallback); 267 268 // ParseInstallNameToolOptions returns the config and sets the input arguments. 269 // If a help flag is set then ParseInstallNameToolOptions will print the help 270 // messege and exit. 271 Expected<DriverConfig> 272 parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr); 273 274 // ParseBitcodeStripOptions returns the config and sets the input arguments. 275 // If a help flag is set then ParseBitcodeStripOptions will print the help 276 // messege and exit. 277 Expected<DriverConfig> parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr); 278 279 // ParseStripOptions returns the config and sets the input arguments. If a 280 // help flag is set then ParseStripOptions will print the help messege and 281 // exit. ErrorCallback is used to handle recoverable errors. An Error returned 282 // by the callback aborts the parsing and is then returned by this function. 283 Expected<DriverConfig> 284 parseStripOptions(ArrayRef<const char *> ArgsArr, 285 llvm::function_ref<Error(Error)> ErrorCallback); 286 } // namespace objcopy 287 } // namespace llvm 288 289 #endif 290