1 //===- ELFObjcopy.cpp -----------------------------------------------------===// 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 #include "ELFObjcopy.h" 10 #include "Buffer.h" 11 #include "CopyConfig.h" 12 #include "Object.h" 13 #include "llvm/ADT/BitmaskEnum.h" 14 #include "llvm/ADT/DenseSet.h" 15 #include "llvm/ADT/Optional.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/Twine.h" 20 #include "llvm/BinaryFormat/ELF.h" 21 #include "llvm/MC/MCTargetOptions.h" 22 #include "llvm/Object/Binary.h" 23 #include "llvm/Object/ELFObjectFile.h" 24 #include "llvm/Object/ELFTypes.h" 25 #include "llvm/Object/Error.h" 26 #include "llvm/Option/Option.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/Compression.h" 29 #include "llvm/Support/Errc.h" 30 #include "llvm/Support/Error.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Support/ErrorOr.h" 33 #include "llvm/Support/FileSystem.h" 34 #include "llvm/Support/Memory.h" 35 #include "llvm/Support/Path.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include <algorithm> 38 #include <cassert> 39 #include <cstdlib> 40 #include <functional> 41 #include <iterator> 42 #include <memory> 43 #include <string> 44 #include <system_error> 45 #include <utility> 46 47 namespace llvm { 48 namespace objcopy { 49 namespace elf { 50 51 using namespace object; 52 using namespace ELF; 53 using SectionPred = std::function<bool(const SectionBase &Sec)>; 54 55 static bool isDebugSection(const SectionBase &Sec) { 56 return StringRef(Sec.Name).startswith(".debug") || 57 StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index"; 58 } 59 60 static bool isDWOSection(const SectionBase &Sec) { 61 return StringRef(Sec.Name).endswith(".dwo"); 62 } 63 64 static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { 65 // We can't remove the section header string table. 66 if (&Sec == Obj.SectionNames) 67 return false; 68 // Short of keeping the string table we want to keep everything that is a DWO 69 // section and remove everything else. 70 return !isDWOSection(Sec); 71 } 72 73 uint64_t getNewShfFlags(SectionFlag AllFlags) { 74 uint64_t NewFlags = 0; 75 if (AllFlags & SectionFlag::SecAlloc) 76 NewFlags |= ELF::SHF_ALLOC; 77 if (!(AllFlags & SectionFlag::SecReadonly)) 78 NewFlags |= ELF::SHF_WRITE; 79 if (AllFlags & SectionFlag::SecCode) 80 NewFlags |= ELF::SHF_EXECINSTR; 81 if (AllFlags & SectionFlag::SecMerge) 82 NewFlags |= ELF::SHF_MERGE; 83 if (AllFlags & SectionFlag::SecStrings) 84 NewFlags |= ELF::SHF_STRINGS; 85 if (AllFlags & SectionFlag::SecExclude) 86 NewFlags |= ELF::SHF_EXCLUDE; 87 return NewFlags; 88 } 89 90 static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, 91 uint64_t NewFlags) { 92 // Preserve some flags which should not be dropped when setting flags. 93 // Also, preserve anything OS/processor dependant. 94 const uint64_t PreserveMask = 95 (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER | 96 ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS | 97 ELF::SHF_INFO_LINK) & 98 ~ELF::SHF_EXCLUDE; 99 return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); 100 } 101 102 static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) { 103 Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags)); 104 105 // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule 106 // may promote more non-ALLOC sections than GNU objcopy, but it is fine as 107 // non-ALLOC SHT_NOBITS sections do not make much sense. 108 if (Sec.Type == SHT_NOBITS && 109 (!(Sec.Flags & ELF::SHF_ALLOC) || 110 Flags & (SectionFlag::SecContents | SectionFlag::SecLoad))) 111 Sec.Type = SHT_PROGBITS; 112 } 113 114 static ElfType getOutputElfType(const Binary &Bin) { 115 // Infer output ELF type from the input ELF object 116 if (isa<ELFObjectFile<ELF32LE>>(Bin)) 117 return ELFT_ELF32LE; 118 if (isa<ELFObjectFile<ELF64LE>>(Bin)) 119 return ELFT_ELF64LE; 120 if (isa<ELFObjectFile<ELF32BE>>(Bin)) 121 return ELFT_ELF32BE; 122 if (isa<ELFObjectFile<ELF64BE>>(Bin)) 123 return ELFT_ELF64BE; 124 llvm_unreachable("Invalid ELFType"); 125 } 126 127 static ElfType getOutputElfType(const MachineInfo &MI) { 128 // Infer output ELF type from the binary arch specified 129 if (MI.Is64Bit) 130 return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE; 131 else 132 return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE; 133 } 134 135 static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config, 136 Object &Obj, Buffer &Buf, 137 ElfType OutputElfType) { 138 // Depending on the initial ELFT and OutputFormat we need a different Writer. 139 switch (OutputElfType) { 140 case ELFT_ELF32LE: 141 return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections, 142 Config.OnlyKeepDebug); 143 case ELFT_ELF64LE: 144 return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections, 145 Config.OnlyKeepDebug); 146 case ELFT_ELF32BE: 147 return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections, 148 Config.OnlyKeepDebug); 149 case ELFT_ELF64BE: 150 return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections, 151 Config.OnlyKeepDebug); 152 } 153 llvm_unreachable("Invalid output format"); 154 } 155 156 static std::unique_ptr<Writer> createWriter(const CopyConfig &Config, 157 Object &Obj, Buffer &Buf, 158 ElfType OutputElfType) { 159 switch (Config.OutputFormat) { 160 case FileFormat::Binary: 161 return std::make_unique<BinaryWriter>(Obj, Buf); 162 case FileFormat::IHex: 163 return std::make_unique<IHexWriter>(Obj, Buf); 164 default: 165 return createELFWriter(Config, Obj, Buf, OutputElfType); 166 } 167 } 168 169 template <class ELFT> 170 static Expected<ArrayRef<uint8_t>> 171 findBuildID(const CopyConfig &Config, const object::ELFFile<ELFT> &In) { 172 auto PhdrsOrErr = In.program_headers(); 173 if (auto Err = PhdrsOrErr.takeError()) 174 return createFileError(Config.InputFilename, std::move(Err)); 175 176 for (const auto &Phdr : *PhdrsOrErr) { 177 if (Phdr.p_type != PT_NOTE) 178 continue; 179 Error Err = Error::success(); 180 for (auto Note : In.notes(Phdr, Err)) 181 if (Note.getType() == NT_GNU_BUILD_ID && Note.getName() == ELF_NOTE_GNU) 182 return Note.getDesc(); 183 if (Err) 184 return createFileError(Config.InputFilename, std::move(Err)); 185 } 186 187 return createFileError(Config.InputFilename, 188 createStringError(llvm::errc::invalid_argument, 189 "could not find build ID")); 190 } 191 192 static Expected<ArrayRef<uint8_t>> 193 findBuildID(const CopyConfig &Config, const object::ELFObjectFileBase &In) { 194 if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(&In)) 195 return findBuildID(Config, O->getELFFile()); 196 else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(&In)) 197 return findBuildID(Config, O->getELFFile()); 198 else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(&In)) 199 return findBuildID(Config, O->getELFFile()); 200 else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(&In)) 201 return findBuildID(Config, O->getELFFile()); 202 203 llvm_unreachable("Bad file format"); 204 } 205 206 template <class... Ts> 207 static Error makeStringError(std::error_code EC, const Twine &Msg, 208 Ts &&... Args) { 209 std::string FullMsg = (EC.message() + ": " + Msg).str(); 210 return createStringError(EC, FullMsg.c_str(), std::forward<Ts>(Args)...); 211 } 212 213 #define MODEL_8 "%%%%%%%%" 214 #define MODEL_16 MODEL_8 MODEL_8 215 #define MODEL_32 (MODEL_16 MODEL_16) 216 217 static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink, 218 StringRef Suffix, 219 ArrayRef<uint8_t> BuildIdBytes) { 220 SmallString<128> Path = Config.BuildIdLinkDir; 221 sys::path::append(Path, llvm::toHex(BuildIdBytes[0], /*LowerCase*/ true)); 222 if (auto EC = sys::fs::create_directories(Path)) 223 return createFileError( 224 Path.str(), 225 makeStringError(EC, "cannot create build ID link directory")); 226 227 sys::path::append(Path, 228 llvm::toHex(BuildIdBytes.slice(1), /*LowerCase*/ true)); 229 Path += Suffix; 230 SmallString<128> TmpPath; 231 // create_hard_link races so we need to link to a temporary path but 232 // we want to make sure that we choose a filename that does not exist. 233 // By using 32 model characters we get 128-bits of entropy. It is 234 // unlikely that this string has ever existed before much less exists 235 // on this disk or in the current working directory. 236 // Additionally we prepend the original Path for debugging but also 237 // because it ensures that we're linking within a directory on the same 238 // partition on the same device which is critical. It has the added 239 // win of yet further decreasing the odds of a conflict. 240 sys::fs::createUniquePath(Twine(Path) + "-" + MODEL_32 + ".tmp", TmpPath, 241 /*MakeAbsolute*/ false); 242 if (auto EC = sys::fs::create_hard_link(ToLink, TmpPath)) { 243 Path.push_back('\0'); 244 return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(), 245 Path.data()); 246 } 247 // We then atomically rename the link into place which will just move the 248 // link. If rename fails something is more seriously wrong so just return 249 // an error. 250 if (auto EC = sys::fs::rename(TmpPath, Path)) { 251 Path.push_back('\0'); 252 return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(), 253 Path.data()); 254 } 255 // If `Path` was already a hard-link to the same underlying file then the 256 // temp file will be left so we need to remove it. Remove will not cause 257 // an error by default if the file is already gone so just blindly remove 258 // it rather than checking. 259 if (auto EC = sys::fs::remove(TmpPath)) { 260 TmpPath.push_back('\0'); 261 return makeStringError(EC, "could not remove '%s'", TmpPath.data()); 262 } 263 return Error::success(); 264 } 265 266 static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader, 267 StringRef File, ElfType OutputElfType) { 268 Expected<std::unique_ptr<Object>> DWOFile = Reader.create(false); 269 if (!DWOFile) 270 return DWOFile.takeError(); 271 272 auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) { 273 return onlyKeepDWOPred(**DWOFile, Sec); 274 }; 275 if (Error E = 276 (*DWOFile)->removeSections(Config.AllowBrokenLinks, OnlyKeepDWOPred)) 277 return E; 278 if (Config.OutputArch) { 279 (*DWOFile)->Machine = Config.OutputArch.getValue().EMachine; 280 (*DWOFile)->OSABI = Config.OutputArch.getValue().OSABI; 281 } 282 FileBuffer FB(File); 283 std::unique_ptr<Writer> Writer = 284 createWriter(Config, **DWOFile, FB, OutputElfType); 285 if (Error E = Writer->finalize()) 286 return E; 287 return Writer->write(); 288 } 289 290 static Error dumpSectionToFile(StringRef SecName, StringRef Filename, 291 Object &Obj) { 292 for (auto &Sec : Obj.sections()) { 293 if (Sec.Name == SecName) { 294 if (Sec.Type == SHT_NOBITS) 295 return createStringError(object_error::parse_failed, 296 "cannot dump section '%s': it has no contents", 297 SecName.str().c_str()); 298 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 299 FileOutputBuffer::create(Filename, Sec.OriginalData.size()); 300 if (!BufferOrErr) 301 return BufferOrErr.takeError(); 302 std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr); 303 std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), 304 Buf->getBufferStart()); 305 if (Error E = Buf->commit()) 306 return E; 307 return Error::success(); 308 } 309 } 310 return createStringError(object_error::parse_failed, "section '%s' not found", 311 SecName.str().c_str()); 312 } 313 314 static bool isCompressable(const SectionBase &Sec) { 315 return !(Sec.Flags & ELF::SHF_COMPRESSED) && 316 StringRef(Sec.Name).startswith(".debug"); 317 } 318 319 static Error replaceDebugSections( 320 Object &Obj, SectionPred &RemovePred, 321 function_ref<bool(const SectionBase &)> ShouldReplace, 322 function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) { 323 // Build a list of the debug sections we are going to replace. 324 // We can't call `AddSection` while iterating over sections, 325 // because it would mutate the sections array. 326 SmallVector<SectionBase *, 13> ToReplace; 327 for (auto &Sec : Obj.sections()) 328 if (ShouldReplace(Sec)) 329 ToReplace.push_back(&Sec); 330 331 // Build a mapping from original section to a new one. 332 DenseMap<SectionBase *, SectionBase *> FromTo; 333 for (SectionBase *S : ToReplace) { 334 Expected<SectionBase *> NewSection = AddSection(S); 335 if (!NewSection) 336 return NewSection.takeError(); 337 338 FromTo[S] = *NewSection; 339 } 340 341 // Now we want to update the target sections of relocation 342 // sections. Also we will update the relocations themselves 343 // to update the symbol references. 344 for (auto &Sec : Obj.sections()) 345 Sec.replaceSectionReferences(FromTo); 346 347 RemovePred = [ShouldReplace, RemovePred](const SectionBase &Sec) { 348 return ShouldReplace(Sec) || RemovePred(Sec); 349 }; 350 351 return Error::success(); 352 } 353 354 static bool isUnneededSymbol(const Symbol &Sym) { 355 return !Sym.Referenced && 356 (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && 357 Sym.Type != STT_SECTION; 358 } 359 360 static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) { 361 // TODO: update or remove symbols only if there is an option that affects 362 // them. 363 if (!Obj.SymbolTable) 364 return Error::success(); 365 366 Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { 367 // Common and undefined symbols don't make sense as local symbols, and can 368 // even cause crashes if we localize those, so skip them. 369 if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && 370 ((Config.LocalizeHidden && 371 (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) || 372 Config.SymbolsToLocalize.matches(Sym.Name))) 373 Sym.Binding = STB_LOCAL; 374 375 // Note: these two globalize flags have very similar names but different 376 // meanings: 377 // 378 // --globalize-symbol: promote a symbol to global 379 // --keep-global-symbol: all symbols except for these should be made local 380 // 381 // If --globalize-symbol is specified for a given symbol, it will be 382 // global in the output file even if it is not included via 383 // --keep-global-symbol. Because of that, make sure to check 384 // --globalize-symbol second. 385 if (!Config.SymbolsToKeepGlobal.empty() && 386 !Config.SymbolsToKeepGlobal.matches(Sym.Name) && 387 Sym.getShndx() != SHN_UNDEF) 388 Sym.Binding = STB_LOCAL; 389 390 if (Config.SymbolsToGlobalize.matches(Sym.Name) && 391 Sym.getShndx() != SHN_UNDEF) 392 Sym.Binding = STB_GLOBAL; 393 394 if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding == STB_GLOBAL) 395 Sym.Binding = STB_WEAK; 396 397 if (Config.Weaken && Sym.Binding == STB_GLOBAL && 398 Sym.getShndx() != SHN_UNDEF) 399 Sym.Binding = STB_WEAK; 400 401 const auto I = Config.SymbolsToRename.find(Sym.Name); 402 if (I != Config.SymbolsToRename.end()) 403 Sym.Name = std::string(I->getValue()); 404 405 if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION) 406 Sym.Name = (Config.SymbolsPrefix + Sym.Name).str(); 407 }); 408 409 // The purpose of this loop is to mark symbols referenced by sections 410 // (like GroupSection or RelocationSection). This way, we know which 411 // symbols are still 'needed' and which are not. 412 if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() || 413 !Config.OnlySection.empty()) { 414 for (SectionBase &Sec : Obj.sections()) 415 Sec.markSymbols(); 416 } 417 418 auto RemoveSymbolsPred = [&](const Symbol &Sym) { 419 if (Config.SymbolsToKeep.matches(Sym.Name) || 420 (Config.KeepFileSymbols && Sym.Type == STT_FILE)) 421 return false; 422 423 if ((Config.DiscardMode == DiscardType::All || 424 (Config.DiscardMode == DiscardType::Locals && 425 StringRef(Sym.Name).startswith(".L"))) && 426 Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF && 427 Sym.Type != STT_FILE && Sym.Type != STT_SECTION) 428 return true; 429 430 if (Config.StripAll || Config.StripAllGNU) 431 return true; 432 433 if (Config.StripDebug && Sym.Type == STT_FILE) 434 return true; 435 436 if (Config.SymbolsToRemove.matches(Sym.Name)) 437 return true; 438 439 if ((Config.StripUnneeded || 440 Config.UnneededSymbolsToRemove.matches(Sym.Name)) && 441 (!Obj.isRelocatable() || isUnneededSymbol(Sym))) 442 return true; 443 444 // We want to remove undefined symbols if all references have been stripped. 445 if (!Config.OnlySection.empty() && !Sym.Referenced && 446 Sym.getShndx() == SHN_UNDEF) 447 return true; 448 449 return false; 450 }; 451 452 return Obj.removeSymbols(RemoveSymbolsPred); 453 } 454 455 static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { 456 SectionPred RemovePred = [](const SectionBase &) { return false; }; 457 458 // Removes: 459 if (!Config.ToRemove.empty()) { 460 RemovePred = [&Config](const SectionBase &Sec) { 461 return Config.ToRemove.matches(Sec.Name); 462 }; 463 } 464 465 if (Config.StripDWO || !Config.SplitDWO.empty()) 466 RemovePred = [RemovePred](const SectionBase &Sec) { 467 return isDWOSection(Sec) || RemovePred(Sec); 468 }; 469 470 if (Config.ExtractDWO) 471 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 472 return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); 473 }; 474 475 if (Config.StripAllGNU) 476 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 477 if (RemovePred(Sec)) 478 return true; 479 if ((Sec.Flags & SHF_ALLOC) != 0) 480 return false; 481 if (&Sec == Obj.SectionNames) 482 return false; 483 switch (Sec.Type) { 484 case SHT_SYMTAB: 485 case SHT_REL: 486 case SHT_RELA: 487 case SHT_STRTAB: 488 return true; 489 } 490 return isDebugSection(Sec); 491 }; 492 493 if (Config.StripSections) { 494 RemovePred = [RemovePred](const SectionBase &Sec) { 495 return RemovePred(Sec) || Sec.ParentSegment == nullptr; 496 }; 497 } 498 499 if (Config.StripDebug || Config.StripUnneeded) { 500 RemovePred = [RemovePred](const SectionBase &Sec) { 501 return RemovePred(Sec) || isDebugSection(Sec); 502 }; 503 } 504 505 if (Config.StripNonAlloc) 506 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 507 if (RemovePred(Sec)) 508 return true; 509 if (&Sec == Obj.SectionNames) 510 return false; 511 return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr; 512 }; 513 514 if (Config.StripAll) 515 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { 516 if (RemovePred(Sec)) 517 return true; 518 if (&Sec == Obj.SectionNames) 519 return false; 520 if (StringRef(Sec.Name).startswith(".gnu.warning")) 521 return false; 522 // We keep the .ARM.attribute section to maintain compatibility 523 // with Debian derived distributions. This is a bug in their 524 // patchset as documented here: 525 // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798 526 if (Sec.Type == SHT_ARM_ATTRIBUTES) 527 return false; 528 if (Sec.ParentSegment != nullptr) 529 return false; 530 return (Sec.Flags & SHF_ALLOC) == 0; 531 }; 532 533 if (Config.ExtractPartition || Config.ExtractMainPartition) { 534 RemovePred = [RemovePred](const SectionBase &Sec) { 535 if (RemovePred(Sec)) 536 return true; 537 if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR) 538 return true; 539 return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment; 540 }; 541 } 542 543 // Explicit copies: 544 if (!Config.OnlySection.empty()) { 545 RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) { 546 // Explicitly keep these sections regardless of previous removes. 547 if (Config.OnlySection.matches(Sec.Name)) 548 return false; 549 550 // Allow all implicit removes. 551 if (RemovePred(Sec)) 552 return true; 553 554 // Keep special sections. 555 if (Obj.SectionNames == &Sec) 556 return false; 557 if (Obj.SymbolTable == &Sec || 558 (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec)) 559 return false; 560 561 // Remove everything else. 562 return true; 563 }; 564 } 565 566 if (!Config.KeepSection.empty()) { 567 RemovePred = [&Config, RemovePred](const SectionBase &Sec) { 568 // Explicitly keep these sections regardless of previous removes. 569 if (Config.KeepSection.matches(Sec.Name)) 570 return false; 571 // Otherwise defer to RemovePred. 572 return RemovePred(Sec); 573 }; 574 } 575 576 // This has to be the last predicate assignment. 577 // If the option --keep-symbol has been specified 578 // and at least one of those symbols is present 579 // (equivalently, the updated symbol table is not empty) 580 // the symbol table and the string table should not be removed. 581 if ((!Config.SymbolsToKeep.empty() || Config.KeepFileSymbols) && 582 Obj.SymbolTable && !Obj.SymbolTable->empty()) { 583 RemovePred = [&Obj, RemovePred](const SectionBase &Sec) { 584 if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab()) 585 return false; 586 return RemovePred(Sec); 587 }; 588 } 589 590 if (Config.CompressionType != DebugCompressionType::None) { 591 if (Error Err = replaceDebugSections( 592 Obj, RemovePred, isCompressable, 593 [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> { 594 Expected<CompressedSection> NewSection = 595 CompressedSection::create(*S, Config.CompressionType); 596 if (!NewSection) 597 return NewSection.takeError(); 598 599 return &Obj.addSection<CompressedSection>(std::move(*NewSection)); 600 })) 601 return Err; 602 } else if (Config.DecompressDebugSections) { 603 if (Error Err = replaceDebugSections( 604 Obj, RemovePred, 605 [](const SectionBase &S) { return isa<CompressedSection>(&S); }, 606 [&Obj](const SectionBase *S) { 607 const CompressedSection *CS = cast<CompressedSection>(S); 608 return &Obj.addSection<DecompressedSection>(*CS); 609 })) 610 return Err; 611 } 612 613 return Obj.removeSections(Config.AllowBrokenLinks, RemovePred); 614 } 615 616 // This function handles the high level operations of GNU objcopy including 617 // handling command line options. It's important to outline certain properties 618 // we expect to hold of the command line operations. Any operation that "keeps" 619 // should keep regardless of a remove. Additionally any removal should respect 620 // any previous removals. Lastly whether or not something is removed shouldn't 621 // depend a) on the order the options occur in or b) on some opaque priority 622 // system. The only priority is that keeps/copies overrule removes. 623 static Error handleArgs(const CopyConfig &Config, Object &Obj, 624 const Reader &Reader, ElfType OutputElfType) { 625 if (Config.StripSwiftSymbols) 626 return createStringError(llvm::errc::invalid_argument, 627 "option not supported by llvm-objcopy for ELF"); 628 if (!Config.SplitDWO.empty()) 629 if (Error E = 630 splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType)) 631 return E; 632 633 if (Config.OutputArch) { 634 Obj.Machine = Config.OutputArch.getValue().EMachine; 635 Obj.OSABI = Config.OutputArch.getValue().OSABI; 636 } 637 638 // Dump sections before add/remove for compatibility with GNU objcopy. 639 for (StringRef Flag : Config.DumpSection) { 640 StringRef SectionName; 641 StringRef FileName; 642 std::tie(SectionName, FileName) = Flag.split('='); 643 if (Error E = dumpSectionToFile(SectionName, FileName, Obj)) 644 return E; 645 } 646 647 // It is important to remove the sections first. For example, we want to 648 // remove the relocation sections before removing the symbols. That allows 649 // us to avoid reporting the inappropriate errors about removing symbols 650 // named in relocations. 651 if (Error E = replaceAndRemoveSections(Config, Obj)) 652 return E; 653 654 if (Error E = updateAndRemoveSymbols(Config, Obj)) 655 return E; 656 657 if (!Config.SectionsToRename.empty()) { 658 for (SectionBase &Sec : Obj.sections()) { 659 const auto Iter = Config.SectionsToRename.find(Sec.Name); 660 if (Iter != Config.SectionsToRename.end()) { 661 const SectionRename &SR = Iter->second; 662 Sec.Name = std::string(SR.NewName); 663 if (SR.NewFlags.hasValue()) 664 setSectionFlagsAndType(Sec, SR.NewFlags.getValue()); 665 } 666 } 667 } 668 669 // Add a prefix to allocated sections and their relocation sections. This 670 // should be done after renaming the section by Config.SectionToRename to 671 // imitate the GNU objcopy behavior. 672 if (!Config.AllocSectionsPrefix.empty()) { 673 DenseSet<SectionBase *> PrefixedSections; 674 for (SectionBase &Sec : Obj.sections()) { 675 if (Sec.Flags & SHF_ALLOC) { 676 Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str(); 677 PrefixedSections.insert(&Sec); 678 } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) { 679 // Rename relocation sections associated to the allocated sections. 680 // For example, if we rename .text to .prefix.text, we also rename 681 // .rel.text to .rel.prefix.text. 682 // 683 // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled 684 // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not 685 // .rela.prefix.plt since GNU objcopy does so. 686 const SectionBase *TargetSec = RelocSec->getSection(); 687 if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) { 688 StringRef prefix; 689 switch (Sec.Type) { 690 case SHT_REL: 691 prefix = ".rel"; 692 break; 693 case SHT_RELA: 694 prefix = ".rela"; 695 break; 696 default: 697 llvm_unreachable("not a relocation section"); 698 } 699 700 // If the relocation section comes *after* the target section, we 701 // don't add Config.AllocSectionsPrefix because we've already added 702 // the prefix to TargetSec->Name. Otherwise, if the relocation 703 // section comes *before* the target section, we add the prefix. 704 if (PrefixedSections.count(TargetSec)) 705 Sec.Name = (prefix + TargetSec->Name).str(); 706 else 707 Sec.Name = 708 (prefix + Config.AllocSectionsPrefix + TargetSec->Name).str(); 709 } 710 } 711 } 712 } 713 714 if (!Config.SetSectionAlignment.empty()) { 715 for (SectionBase &Sec : Obj.sections()) { 716 auto I = Config.SetSectionAlignment.find(Sec.Name); 717 if (I != Config.SetSectionAlignment.end()) 718 Sec.Align = I->second; 719 } 720 } 721 722 if (Config.OnlyKeepDebug) 723 for (auto &Sec : Obj.sections()) 724 if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE) 725 Sec.Type = SHT_NOBITS; 726 727 for (const auto &Flag : Config.AddSection) { 728 std::pair<StringRef, StringRef> SecPair = Flag.split("="); 729 StringRef SecName = SecPair.first; 730 StringRef File = SecPair.second; 731 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 732 MemoryBuffer::getFile(File); 733 if (!BufOrErr) 734 return createFileError(File, errorCodeToError(BufOrErr.getError())); 735 std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr); 736 ArrayRef<uint8_t> Data( 737 reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), 738 Buf->getBufferSize()); 739 OwnedDataSection &NewSection = 740 Obj.addSection<OwnedDataSection>(SecName, Data); 741 if (SecName.startswith(".note") && SecName != ".note.GNU-stack") 742 NewSection.Type = SHT_NOTE; 743 } 744 745 if (!Config.AddGnuDebugLink.empty()) 746 Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink, 747 Config.GnuDebugLinkCRC32); 748 749 // If the symbol table was previously removed, we need to create a new one 750 // before adding new symbols. 751 if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty()) 752 if (Error E = Obj.addNewSymbolTable()) 753 return E; 754 755 for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) { 756 SectionBase *Sec = Obj.findSection(SI.SectionName); 757 uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value; 758 Obj.SymbolTable->addSymbol( 759 SI.SymbolName, SI.Bind, SI.Type, Sec, Value, SI.Visibility, 760 Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0); 761 } 762 763 // --set-section-flags works with sections added by --add-section. 764 if (!Config.SetSectionFlags.empty()) { 765 for (auto &Sec : Obj.sections()) { 766 const auto Iter = Config.SetSectionFlags.find(Sec.Name); 767 if (Iter != Config.SetSectionFlags.end()) { 768 const SectionFlagsUpdate &SFU = Iter->second; 769 setSectionFlagsAndType(Sec, SFU.NewFlags); 770 } 771 } 772 } 773 774 if (Config.EntryExpr) 775 Obj.Entry = Config.EntryExpr(Obj.Entry); 776 return Error::success(); 777 } 778 779 static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out, 780 ElfType OutputElfType) { 781 std::unique_ptr<Writer> Writer = 782 createWriter(Config, Obj, Out, OutputElfType); 783 if (Error E = Writer->finalize()) 784 return E; 785 return Writer->write(); 786 } 787 788 Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In, 789 Buffer &Out) { 790 IHexReader Reader(&In); 791 Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 792 if (!Obj) 793 return Obj.takeError(); 794 795 const ElfType OutputElfType = 796 getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); 797 if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) 798 return E; 799 return writeOutput(Config, **Obj, Out, OutputElfType); 800 } 801 802 Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In, 803 Buffer &Out) { 804 uint8_t NewSymbolVisibility = 805 Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT); 806 BinaryReader Reader(&In, NewSymbolVisibility); 807 Expected<std::unique_ptr<Object>> Obj = Reader.create(true); 808 if (!Obj) 809 return Obj.takeError(); 810 811 // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch 812 // (-B<arch>). 813 const ElfType OutputElfType = 814 getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); 815 if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) 816 return E; 817 return writeOutput(Config, **Obj, Out, OutputElfType); 818 } 819 820 Error executeObjcopyOnBinary(const CopyConfig &Config, 821 object::ELFObjectFileBase &In, Buffer &Out) { 822 ELFReader Reader(&In, Config.ExtractPartition); 823 Expected<std::unique_ptr<Object>> Obj = 824 Reader.create(!Config.SymbolsToAdd.empty()); 825 if (!Obj) 826 return Obj.takeError(); 827 // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input. 828 const ElfType OutputElfType = 829 Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue()) 830 : getOutputElfType(In); 831 ArrayRef<uint8_t> BuildIdBytes; 832 833 if (!Config.BuildIdLinkDir.empty()) { 834 auto BuildIdBytesOrErr = findBuildID(Config, In); 835 if (auto E = BuildIdBytesOrErr.takeError()) 836 return E; 837 BuildIdBytes = *BuildIdBytesOrErr; 838 839 if (BuildIdBytes.size() < 2) 840 return createFileError( 841 Config.InputFilename, 842 createStringError(object_error::parse_failed, 843 "build ID is smaller than two bytes")); 844 } 845 846 if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkInput) 847 if (Error E = 848 linkToBuildIdDir(Config, Config.InputFilename, 849 Config.BuildIdLinkInput.getValue(), BuildIdBytes)) 850 return E; 851 852 if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) 853 return createFileError(Config.InputFilename, std::move(E)); 854 855 if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) 856 return createFileError(Config.InputFilename, std::move(E)); 857 if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput) 858 if (Error E = 859 linkToBuildIdDir(Config, Config.OutputFilename, 860 Config.BuildIdLinkOutput.getValue(), BuildIdBytes)) 861 return createFileError(Config.OutputFilename, std::move(E)); 862 863 return Error::success(); 864 } 865 866 } // end namespace elf 867 } // end namespace objcopy 868 } // end namespace llvm 869