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