Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
35266 views
//===- ELFObjcopy.cpp -----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ObjCopy/ELF/ELFObjcopy.h"9#include "ELFObject.h"10#include "llvm/ADT/BitmaskEnum.h"11#include "llvm/ADT/DenseSet.h"12#include "llvm/ADT/STLExtras.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/Twine.h"16#include "llvm/BinaryFormat/ELF.h"17#include "llvm/MC/MCTargetOptions.h"18#include "llvm/ObjCopy/CommonConfig.h"19#include "llvm/ObjCopy/ELF/ELFConfig.h"20#include "llvm/Object/Binary.h"21#include "llvm/Object/ELFObjectFile.h"22#include "llvm/Object/ELFTypes.h"23#include "llvm/Object/Error.h"24#include "llvm/Option/Option.h"25#include "llvm/Support/Casting.h"26#include "llvm/Support/Compression.h"27#include "llvm/Support/Errc.h"28#include "llvm/Support/Error.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/ErrorOr.h"31#include "llvm/Support/FileSystem.h"32#include "llvm/Support/Memory.h"33#include "llvm/Support/Path.h"34#include "llvm/Support/raw_ostream.h"35#include <algorithm>36#include <cassert>37#include <cstdlib>38#include <functional>39#include <iterator>40#include <memory>41#include <string>42#include <system_error>43#include <utility>4445using namespace llvm;46using namespace llvm::ELF;47using namespace llvm::objcopy;48using namespace llvm::objcopy::elf;49using namespace llvm::object;5051using SectionPred = std::function<bool(const SectionBase &Sec)>;5253static bool isDebugSection(const SectionBase &Sec) {54return StringRef(Sec.Name).starts_with(".debug") || Sec.Name == ".gdb_index";55}5657static bool isDWOSection(const SectionBase &Sec) {58return StringRef(Sec.Name).ends_with(".dwo");59}6061static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {62// We can't remove the section header string table.63if (&Sec == Obj.SectionNames)64return false;65// Short of keeping the string table we want to keep everything that is a DWO66// section and remove everything else.67return !isDWOSection(Sec);68}6970static Expected<uint64_t> getNewShfFlags(SectionFlag AllFlags,71uint16_t EMachine) {72uint64_t NewFlags = 0;73if (AllFlags & SectionFlag::SecAlloc)74NewFlags |= ELF::SHF_ALLOC;75if (!(AllFlags & SectionFlag::SecReadonly))76NewFlags |= ELF::SHF_WRITE;77if (AllFlags & SectionFlag::SecCode)78NewFlags |= ELF::SHF_EXECINSTR;79if (AllFlags & SectionFlag::SecMerge)80NewFlags |= ELF::SHF_MERGE;81if (AllFlags & SectionFlag::SecStrings)82NewFlags |= ELF::SHF_STRINGS;83if (AllFlags & SectionFlag::SecExclude)84NewFlags |= ELF::SHF_EXCLUDE;85if (AllFlags & SectionFlag::SecLarge) {86if (EMachine != EM_X86_64)87return createStringError(errc::invalid_argument,88"section flag SHF_X86_64_LARGE can only be used "89"with x86_64 architecture");90NewFlags |= ELF::SHF_X86_64_LARGE;91}92return NewFlags;93}9495static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags,96uint64_t NewFlags,97uint16_t EMachine) {98// Preserve some flags which should not be dropped when setting flags.99// Also, preserve anything OS/processor dependant.100const uint64_t PreserveMask =101(ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |102ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS |103ELF::SHF_INFO_LINK) &104~ELF::SHF_EXCLUDE &105~(EMachine == EM_X86_64 ? (uint64_t)ELF::SHF_X86_64_LARGE : 0UL);106return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);107}108109static void setSectionType(SectionBase &Sec, uint64_t Type) {110// If Sec's type is changed from SHT_NOBITS due to --set-section-flags,111// Offset may not be aligned. Align it to max(Align, 1).112if (Sec.Type == ELF::SHT_NOBITS && Type != ELF::SHT_NOBITS)113Sec.Offset = alignTo(Sec.Offset, std::max(Sec.Align, uint64_t(1)));114Sec.Type = Type;115}116117static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags,118uint16_t EMachine) {119Expected<uint64_t> NewFlags = getNewShfFlags(Flags, EMachine);120if (!NewFlags)121return NewFlags.takeError();122Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, *NewFlags, EMachine);123124// In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule125// may promote more non-ALLOC sections than GNU objcopy, but it is fine as126// non-ALLOC SHT_NOBITS sections do not make much sense.127if (Sec.Type == SHT_NOBITS &&128(!(Sec.Flags & ELF::SHF_ALLOC) ||129Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))130setSectionType(Sec, ELF::SHT_PROGBITS);131132return Error::success();133}134135static ElfType getOutputElfType(const Binary &Bin) {136// Infer output ELF type from the input ELF object137if (isa<ELFObjectFile<ELF32LE>>(Bin))138return ELFT_ELF32LE;139if (isa<ELFObjectFile<ELF64LE>>(Bin))140return ELFT_ELF64LE;141if (isa<ELFObjectFile<ELF32BE>>(Bin))142return ELFT_ELF32BE;143if (isa<ELFObjectFile<ELF64BE>>(Bin))144return ELFT_ELF64BE;145llvm_unreachable("Invalid ELFType");146}147148static ElfType getOutputElfType(const MachineInfo &MI) {149// Infer output ELF type from the binary arch specified150if (MI.Is64Bit)151return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE;152else153return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;154}155156static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,157Object &Obj, raw_ostream &Out,158ElfType OutputElfType) {159// Depending on the initial ELFT and OutputFormat we need a different Writer.160switch (OutputElfType) {161case ELFT_ELF32LE:162return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections,163Config.OnlyKeepDebug);164case ELFT_ELF64LE:165return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections,166Config.OnlyKeepDebug);167case ELFT_ELF32BE:168return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections,169Config.OnlyKeepDebug);170case ELFT_ELF64BE:171return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections,172Config.OnlyKeepDebug);173}174llvm_unreachable("Invalid output format");175}176177static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,178Object &Obj, raw_ostream &Out,179ElfType OutputElfType) {180switch (Config.OutputFormat) {181case FileFormat::Binary:182return std::make_unique<BinaryWriter>(Obj, Out, Config);183case FileFormat::IHex:184return std::make_unique<IHexWriter>(Obj, Out, Config.OutputFilename);185case FileFormat::SREC:186return std::make_unique<SRECWriter>(Obj, Out, Config.OutputFilename);187default:188return createELFWriter(Config, Obj, Out, OutputElfType);189}190}191192static Error dumpSectionToFile(StringRef SecName, StringRef Filename,193Object &Obj) {194for (auto &Sec : Obj.sections()) {195if (Sec.Name == SecName) {196if (Sec.Type == SHT_NOBITS)197return createStringError(object_error::parse_failed,198"cannot dump section '%s': it has no contents",199SecName.str().c_str());200Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =201FileOutputBuffer::create(Filename, Sec.OriginalData.size());202if (!BufferOrErr)203return BufferOrErr.takeError();204std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);205std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),206Buf->getBufferStart());207if (Error E = Buf->commit())208return E;209return Error::success();210}211}212return createStringError(object_error::parse_failed, "section '%s' not found",213SecName.str().c_str());214}215216Error Object::compressOrDecompressSections(const CommonConfig &Config) {217// Build a list of sections we are going to replace.218// We can't call `addSection` while iterating over sections,219// because it would mutate the sections array.220SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0>221ToReplace;222for (SectionBase &Sec : sections()) {223std::optional<DebugCompressionType> CType;224for (auto &[Matcher, T] : Config.compressSections)225if (Matcher.matches(Sec.Name))226CType = T;227// Handle --compress-debug-sections and --decompress-debug-sections, which228// apply to non-ALLOC debug sections.229if (!(Sec.Flags & SHF_ALLOC) && StringRef(Sec.Name).starts_with(".debug")) {230if (Config.CompressionType != DebugCompressionType::None)231CType = Config.CompressionType;232else if (Config.DecompressDebugSections)233CType = DebugCompressionType::None;234}235if (!CType)236continue;237238if (Sec.ParentSegment)239return createStringError(240errc::invalid_argument,241"section '" + Sec.Name +242"' within a segment cannot be (de)compressed");243244if (auto *CS = dyn_cast<CompressedSection>(&Sec)) {245if (*CType == DebugCompressionType::None)246ToReplace.emplace_back(247&Sec, [=] { return &addSection<DecompressedSection>(*CS); });248} else if (*CType != DebugCompressionType::None) {249ToReplace.emplace_back(&Sec, [=, S = &Sec] {250return &addSection<CompressedSection>(251CompressedSection(*S, *CType, Is64Bits));252});253}254}255256DenseMap<SectionBase *, SectionBase *> FromTo;257for (auto [S, Func] : ToReplace)258FromTo[S] = Func();259return replaceSections(FromTo);260}261262static bool isAArch64MappingSymbol(const Symbol &Sym) {263if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||264Sym.getShndx() == SHN_UNDEF)265return false;266StringRef Name = Sym.Name;267if (!Name.consume_front("$x") && !Name.consume_front("$d"))268return false;269return Name.empty() || Name.starts_with(".");270}271272static bool isArmMappingSymbol(const Symbol &Sym) {273if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||274Sym.getShndx() == SHN_UNDEF)275return false;276StringRef Name = Sym.Name;277if (!Name.consume_front("$a") && !Name.consume_front("$d") &&278!Name.consume_front("$t"))279return false;280return Name.empty() || Name.starts_with(".");281}282283// Check if the symbol should be preserved because it is required by ABI.284static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) {285switch (Obj.Machine) {286case EM_AARCH64:287// Mapping symbols should be preserved for a relocatable object file.288return Obj.isRelocatable() && isAArch64MappingSymbol(Sym);289case EM_ARM:290// Mapping symbols should be preserved for a relocatable object file.291return Obj.isRelocatable() && isArmMappingSymbol(Sym);292default:293return false;294}295}296297static bool isUnneededSymbol(const Symbol &Sym) {298return !Sym.Referenced &&299(Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&300Sym.Type != STT_SECTION;301}302303static Error updateAndRemoveSymbols(const CommonConfig &Config,304const ELFConfig &ELFConfig, Object &Obj) {305// TODO: update or remove symbols only if there is an option that affects306// them.307if (!Obj.SymbolTable)308return Error::success();309310Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {311if (Config.SymbolsToSkip.matches(Sym.Name))312return;313314// Common and undefined symbols don't make sense as local symbols, and can315// even cause crashes if we localize those, so skip them.316if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&317((ELFConfig.LocalizeHidden &&318(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||319Config.SymbolsToLocalize.matches(Sym.Name)))320Sym.Binding = STB_LOCAL;321322for (auto &[Matcher, Visibility] : ELFConfig.SymbolsToSetVisibility)323if (Matcher.matches(Sym.Name))324Sym.Visibility = Visibility;325326// Note: these two globalize flags have very similar names but different327// meanings:328//329// --globalize-symbol: promote a symbol to global330// --keep-global-symbol: all symbols except for these should be made local331//332// If --globalize-symbol is specified for a given symbol, it will be333// global in the output file even if it is not included via334// --keep-global-symbol. Because of that, make sure to check335// --globalize-symbol second.336if (!Config.SymbolsToKeepGlobal.empty() &&337!Config.SymbolsToKeepGlobal.matches(Sym.Name) &&338Sym.getShndx() != SHN_UNDEF)339Sym.Binding = STB_LOCAL;340341if (Config.SymbolsToGlobalize.matches(Sym.Name) &&342Sym.getShndx() != SHN_UNDEF)343Sym.Binding = STB_GLOBAL;344345// SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE.346if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL)347Sym.Binding = STB_WEAK;348349if (Config.Weaken && Sym.Binding != STB_LOCAL &&350Sym.getShndx() != SHN_UNDEF)351Sym.Binding = STB_WEAK;352353const auto I = Config.SymbolsToRename.find(Sym.Name);354if (I != Config.SymbolsToRename.end())355Sym.Name = std::string(I->getValue());356357if (!Config.SymbolsPrefixRemove.empty() && Sym.Type != STT_SECTION)358if (Sym.Name.compare(0, Config.SymbolsPrefixRemove.size(),359Config.SymbolsPrefixRemove) == 0)360Sym.Name = Sym.Name.substr(Config.SymbolsPrefixRemove.size());361362if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)363Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();364});365366// The purpose of this loop is to mark symbols referenced by sections367// (like GroupSection or RelocationSection). This way, we know which368// symbols are still 'needed' and which are not.369if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||370!Config.OnlySection.empty() || Config.DiscardMode != DiscardType::None) {371for (SectionBase &Sec : Obj.sections())372Sec.markSymbols();373}374375auto RemoveSymbolsPred = [&](const Symbol &Sym) {376if (Config.SymbolsToKeep.matches(Sym.Name) ||377(ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE))378return false;379380if (Config.SymbolsToRemove.matches(Sym.Name))381return true;382383if (Config.StripAll || Config.StripAllGNU)384return true;385386if (isRequiredByABISymbol(Obj, Sym))387return false;388389if (Config.StripDebug && Sym.Type == STT_FILE)390return true;391392if ((Config.StripUnneeded ||393Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&394(!Obj.isRelocatable() || isUnneededSymbol(Sym)))395return true;396397if (!Sym.Referenced) {398if ((Config.DiscardMode == DiscardType::All ||399(Config.DiscardMode == DiscardType::Locals &&400StringRef(Sym.Name).starts_with(".L"))) &&401Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&402Sym.Type != STT_FILE && Sym.Type != STT_SECTION)403return true;404// We want to remove undefined symbols if all references have been405// stripped.406if (!Config.OnlySection.empty() && Sym.getShndx() == SHN_UNDEF)407return true;408}409410return false;411};412413return Obj.removeSymbols(RemoveSymbolsPred);414}415416static Error replaceAndRemoveSections(const CommonConfig &Config,417const ELFConfig &ELFConfig, Object &Obj) {418SectionPred RemovePred = [](const SectionBase &) { return false; };419420// Removes:421if (!Config.ToRemove.empty()) {422RemovePred = [&Config](const SectionBase &Sec) {423return Config.ToRemove.matches(Sec.Name);424};425}426427if (Config.StripDWO)428RemovePred = [RemovePred](const SectionBase &Sec) {429return isDWOSection(Sec) || RemovePred(Sec);430};431432if (Config.ExtractDWO)433RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {434return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);435};436437if (Config.StripAllGNU)438RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {439if (RemovePred(Sec))440return true;441if ((Sec.Flags & SHF_ALLOC) != 0)442return false;443if (&Sec == Obj.SectionNames)444return false;445switch (Sec.Type) {446case SHT_SYMTAB:447case SHT_REL:448case SHT_RELA:449case SHT_STRTAB:450return true;451}452return isDebugSection(Sec);453};454455if (Config.StripSections) {456RemovePred = [RemovePred](const SectionBase &Sec) {457return RemovePred(Sec) || Sec.ParentSegment == nullptr;458};459}460461if (Config.StripDebug || Config.StripUnneeded) {462RemovePred = [RemovePred](const SectionBase &Sec) {463return RemovePred(Sec) || isDebugSection(Sec);464};465}466467if (Config.StripNonAlloc)468RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {469if (RemovePred(Sec))470return true;471if (&Sec == Obj.SectionNames)472return false;473return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;474};475476if (Config.StripAll)477RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {478if (RemovePred(Sec))479return true;480if (&Sec == Obj.SectionNames)481return false;482if (StringRef(Sec.Name).starts_with(".gnu.warning"))483return false;484if (StringRef(Sec.Name).starts_with(".gnu_debuglink"))485return false;486// We keep the .ARM.attribute section to maintain compatibility487// with Debian derived distributions. This is a bug in their488// patchset as documented here:489// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798490if (Sec.Type == SHT_ARM_ATTRIBUTES)491return false;492if (Sec.ParentSegment != nullptr)493return false;494return (Sec.Flags & SHF_ALLOC) == 0;495};496497if (Config.ExtractPartition || Config.ExtractMainPartition) {498RemovePred = [RemovePred](const SectionBase &Sec) {499if (RemovePred(Sec))500return true;501if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)502return true;503return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;504};505}506507// Explicit copies:508if (!Config.OnlySection.empty()) {509RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {510// Explicitly keep these sections regardless of previous removes.511if (Config.OnlySection.matches(Sec.Name))512return false;513514// Allow all implicit removes.515if (RemovePred(Sec))516return true;517518// Keep special sections.519if (Obj.SectionNames == &Sec)520return false;521if (Obj.SymbolTable == &Sec ||522(Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))523return false;524525// Remove everything else.526return true;527};528}529530if (!Config.KeepSection.empty()) {531RemovePred = [&Config, RemovePred](const SectionBase &Sec) {532// Explicitly keep these sections regardless of previous removes.533if (Config.KeepSection.matches(Sec.Name))534return false;535// Otherwise defer to RemovePred.536return RemovePred(Sec);537};538}539540// This has to be the last predicate assignment.541// If the option --keep-symbol has been specified542// and at least one of those symbols is present543// (equivalently, the updated symbol table is not empty)544// the symbol table and the string table should not be removed.545if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) &&546Obj.SymbolTable && !Obj.SymbolTable->empty()) {547RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {548if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())549return false;550return RemovePred(Sec);551};552}553554if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))555return E;556557if (Error E = Obj.compressOrDecompressSections(Config))558return E;559560return Error::success();561}562563// Add symbol to the Object symbol table with the specified properties.564static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,565uint8_t DefaultVisibility) {566SectionBase *Sec = Obj.findSection(SymInfo.SectionName);567uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value;568569uint8_t Bind = ELF::STB_GLOBAL;570uint8_t Type = ELF::STT_NOTYPE;571uint8_t Visibility = DefaultVisibility;572573for (SymbolFlag FlagValue : SymInfo.Flags)574switch (FlagValue) {575case SymbolFlag::Global:576Bind = ELF::STB_GLOBAL;577break;578case SymbolFlag::Local:579Bind = ELF::STB_LOCAL;580break;581case SymbolFlag::Weak:582Bind = ELF::STB_WEAK;583break;584case SymbolFlag::Default:585Visibility = ELF::STV_DEFAULT;586break;587case SymbolFlag::Hidden:588Visibility = ELF::STV_HIDDEN;589break;590case SymbolFlag::Protected:591Visibility = ELF::STV_PROTECTED;592break;593case SymbolFlag::File:594Type = ELF::STT_FILE;595break;596case SymbolFlag::Section:597Type = ELF::STT_SECTION;598break;599case SymbolFlag::Object:600Type = ELF::STT_OBJECT;601break;602case SymbolFlag::Function:603Type = ELF::STT_FUNC;604break;605case SymbolFlag::IndirectFunction:606Type = ELF::STT_GNU_IFUNC;607break;608default: /* Other flag values are ignored for ELF. */609break;610};611612Obj.SymbolTable->addSymbol(613SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility,614Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);615}616617static Error618handleUserSection(const NewSectionInfo &NewSection,619function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) {620ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>(621NewSection.SectionData->getBufferStart()),622NewSection.SectionData->getBufferSize());623return F(NewSection.SectionName, Data);624}625626static Error verifyNoteSection(StringRef Name, endianness Endianness,627ArrayRef<uint8_t> Data) {628// An ELF note has the following structure:629// Name Size: 4 bytes (integer)630// Desc Size: 4 bytes (integer)631// Type : 4 bytes632// Name : variable size, padded to a 4 byte boundary633// Desc : variable size, padded to a 4 byte boundary634635if (Data.empty())636return Error::success();637638if (Data.size() < 12) {639std::string msg;640raw_string_ostream(msg)641<< Name << " data must be either empty or at least 12 bytes long";642return createStringError(errc::invalid_argument, msg);643}644if (Data.size() % 4 != 0) {645std::string msg;646raw_string_ostream(msg)647<< Name << " data size must be a multiple of 4 bytes";648return createStringError(errc::invalid_argument, msg);649}650ArrayRef<uint8_t> NameSize = Data.slice(0, 4);651ArrayRef<uint8_t> DescSize = Data.slice(4, 4);652653uint32_t NameSizeValue = support::endian::read32(NameSize.data(), Endianness);654uint32_t DescSizeValue = support::endian::read32(DescSize.data(), Endianness);655656uint64_t ExpectedDataSize =657/*NameSize=*/4 + /*DescSize=*/4 + /*Type=*/4 +658/*Name=*/alignTo(NameSizeValue, 4) +659/*Desc=*/alignTo(DescSizeValue, 4);660uint64_t ActualDataSize = Data.size();661if (ActualDataSize != ExpectedDataSize) {662std::string msg;663raw_string_ostream(msg)664<< Name665<< " data size is incompatible with the content of "666"the name and description size fields:"667<< " expecting " << ExpectedDataSize << ", found " << ActualDataSize;668return createStringError(errc::invalid_argument, msg);669}670671return Error::success();672}673674// This function handles the high level operations of GNU objcopy including675// handling command line options. It's important to outline certain properties676// we expect to hold of the command line operations. Any operation that "keeps"677// should keep regardless of a remove. Additionally any removal should respect678// any previous removals. Lastly whether or not something is removed shouldn't679// depend a) on the order the options occur in or b) on some opaque priority680// system. The only priority is that keeps/copies overrule removes.681static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,682ElfType OutputElfType, Object &Obj) {683if (Config.OutputArch) {684Obj.Machine = Config.OutputArch->EMachine;685Obj.OSABI = Config.OutputArch->OSABI;686}687688if (!Config.SplitDWO.empty() && Config.ExtractDWO) {689return Obj.removeSections(690ELFConfig.AllowBrokenLinks,691[&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });692}693694// Dump sections before add/remove for compatibility with GNU objcopy.695for (StringRef Flag : Config.DumpSection) {696StringRef SectionName;697StringRef FileName;698std::tie(SectionName, FileName) = Flag.split('=');699if (Error E = dumpSectionToFile(SectionName, FileName, Obj))700return E;701}702703// It is important to remove the sections first. For example, we want to704// remove the relocation sections before removing the symbols. That allows705// us to avoid reporting the inappropriate errors about removing symbols706// named in relocations.707if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj))708return E;709710if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj))711return E;712713if (!Config.SetSectionAlignment.empty()) {714for (SectionBase &Sec : Obj.sections()) {715auto I = Config.SetSectionAlignment.find(Sec.Name);716if (I != Config.SetSectionAlignment.end())717Sec.Align = I->second;718}719}720721if (Config.ChangeSectionLMAValAll != 0) {722for (Segment &Seg : Obj.segments()) {723if (Seg.FileSize > 0) {724if (Config.ChangeSectionLMAValAll > 0 &&725Seg.PAddr > std::numeric_limits<uint64_t>::max() -726Config.ChangeSectionLMAValAll) {727return createStringError(728errc::invalid_argument,729"address 0x" + Twine::utohexstr(Seg.PAddr) +730" cannot be increased by 0x" +731Twine::utohexstr(Config.ChangeSectionLMAValAll) +732". The result would overflow");733} else if (Config.ChangeSectionLMAValAll < 0 &&734Seg.PAddr < std::numeric_limits<uint64_t>::min() -735Config.ChangeSectionLMAValAll) {736return createStringError(737errc::invalid_argument,738"address 0x" + Twine::utohexstr(Seg.PAddr) +739" cannot be decreased by 0x" +740Twine::utohexstr(std::abs(Config.ChangeSectionLMAValAll)) +741". The result would underflow");742}743Seg.PAddr += Config.ChangeSectionLMAValAll;744}745}746}747748if (Config.OnlyKeepDebug)749for (auto &Sec : Obj.sections())750if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)751Sec.Type = SHT_NOBITS;752753endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE754? endianness::little755: endianness::big;756757for (const NewSectionInfo &AddedSection : Config.AddSection) {758auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error {759OwnedDataSection &NewSection =760Obj.addSection<OwnedDataSection>(Name, Data);761if (Name.starts_with(".note") && Name != ".note.GNU-stack") {762NewSection.Type = SHT_NOTE;763if (ELFConfig.VerifyNoteSections)764return verifyNoteSection(Name, E, Data);765}766return Error::success();767};768if (Error E = handleUserSection(AddedSection, AddSection))769return E;770}771772for (const NewSectionInfo &NewSection : Config.UpdateSection) {773auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) {774return Obj.updateSection(Name, Data);775};776if (Error E = handleUserSection(NewSection, UpdateSection))777return E;778}779780if (!Config.AddGnuDebugLink.empty())781Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,782Config.GnuDebugLinkCRC32);783784// If the symbol table was previously removed, we need to create a new one785// before adding new symbols.786if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty())787if (Error E = Obj.addNewSymbolTable())788return E;789790for (const NewSymbolInfo &SI : Config.SymbolsToAdd)791addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility);792793// --set-section-{flags,type} work with sections added by --add-section.794if (!Config.SetSectionFlags.empty() || !Config.SetSectionType.empty()) {795for (auto &Sec : Obj.sections()) {796const auto Iter = Config.SetSectionFlags.find(Sec.Name);797if (Iter != Config.SetSectionFlags.end()) {798const SectionFlagsUpdate &SFU = Iter->second;799if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, Obj.Machine))800return E;801}802auto It2 = Config.SetSectionType.find(Sec.Name);803if (It2 != Config.SetSectionType.end())804setSectionType(Sec, It2->second);805}806}807808if (!Config.SectionsToRename.empty()) {809std::vector<RelocationSectionBase *> RelocSections;810DenseSet<SectionBase *> RenamedSections;811for (SectionBase &Sec : Obj.sections()) {812auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec);813const auto Iter = Config.SectionsToRename.find(Sec.Name);814if (Iter != Config.SectionsToRename.end()) {815const SectionRename &SR = Iter->second;816Sec.Name = std::string(SR.NewName);817if (SR.NewFlags) {818if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, Obj.Machine))819return E;820}821RenamedSections.insert(&Sec);822} else if (RelocSec && !(Sec.Flags & SHF_ALLOC))823// Postpone processing relocation sections which are not specified in824// their explicit '--rename-section' commands until after their target825// sections are renamed.826// Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be827// renamed only explicitly. Otherwise, renaming, for example, '.got.plt'828// would affect '.rela.plt', which is not desirable.829RelocSections.push_back(RelocSec);830}831832// Rename relocation sections according to their target sections.833for (RelocationSectionBase *RelocSec : RelocSections) {834auto Iter = RenamedSections.find(RelocSec->getSection());835if (Iter != RenamedSections.end())836RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str();837}838}839840// Add a prefix to allocated sections and their relocation sections. This841// should be done after renaming the section by Config.SectionToRename to842// imitate the GNU objcopy behavior.843if (!Config.AllocSectionsPrefix.empty()) {844DenseSet<SectionBase *> PrefixedSections;845for (SectionBase &Sec : Obj.sections()) {846if (Sec.Flags & SHF_ALLOC) {847Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();848PrefixedSections.insert(&Sec);849} else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {850// Rename relocation sections associated to the allocated sections.851// For example, if we rename .text to .prefix.text, we also rename852// .rel.text to .rel.prefix.text.853//854// Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled855// above, e.g., .rela.plt is renamed to .prefix.rela.plt, not856// .rela.prefix.plt since GNU objcopy does so.857const SectionBase *TargetSec = RelocSec->getSection();858if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {859// If the relocation section comes *after* the target section, we860// don't add Config.AllocSectionsPrefix because we've already added861// the prefix to TargetSec->Name. Otherwise, if the relocation862// section comes *before* the target section, we add the prefix.863if (PrefixedSections.count(TargetSec))864Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str();865else866Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix +867TargetSec->Name)868.str();869}870}871}872}873874if (ELFConfig.EntryExpr)875Obj.Entry = ELFConfig.EntryExpr(Obj.Entry);876return Error::success();877}878879static Error writeOutput(const CommonConfig &Config, Object &Obj,880raw_ostream &Out, ElfType OutputElfType) {881std::unique_ptr<Writer> Writer =882createWriter(Config, Obj, Out, OutputElfType);883if (Error E = Writer->finalize())884return E;885return Writer->write();886}887888Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,889const ELFConfig &ELFConfig,890MemoryBuffer &In, raw_ostream &Out) {891IHexReader Reader(&In);892Expected<std::unique_ptr<Object>> Obj = Reader.create(true);893if (!Obj)894return Obj.takeError();895896const ElfType OutputElfType =897getOutputElfType(Config.OutputArch.value_or(MachineInfo()));898if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))899return E;900return writeOutput(Config, **Obj, Out, OutputElfType);901}902903Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,904const ELFConfig &ELFConfig,905MemoryBuffer &In,906raw_ostream &Out) {907BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility);908Expected<std::unique_ptr<Object>> Obj = Reader.create(true);909if (!Obj)910return Obj.takeError();911912// Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch913// (-B<arch>).914const ElfType OutputElfType =915getOutputElfType(Config.OutputArch.value_or(MachineInfo()));916if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))917return E;918return writeOutput(Config, **Obj, Out, OutputElfType);919}920921Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,922const ELFConfig &ELFConfig,923object::ELFObjectFileBase &In,924raw_ostream &Out) {925ELFReader Reader(&In, Config.ExtractPartition);926Expected<std::unique_ptr<Object>> Obj =927Reader.create(!Config.SymbolsToAdd.empty());928if (!Obj)929return Obj.takeError();930// Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.931const ElfType OutputElfType = Config.OutputArch932? getOutputElfType(*Config.OutputArch)933: getOutputElfType(In);934935if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))936return createFileError(Config.InputFilename, std::move(E));937938if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))939return createFileError(Config.InputFilename, std::move(E));940941return Error::success();942}943944945