38#include <system_error>
59 if (&Sec == Obj.SectionNames)
84 "section flag SHF_X86_64_LARGE can only be used "
85 "with x86_64 architecture");
102 return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);
156 switch (OutputElfType) {
158 return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.
StripSections,
161 return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.
StripSections,
164 return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.
StripSections,
167 return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.
StripSections,
178 return std::make_unique<BinaryWriter>(Obj, Out, Config);
180 return std::make_unique<IHexWriter>(Obj, Out, Config.
OutputFilename);
182 return std::make_unique<SRECWriter>(Obj, Out, Config.
OutputFilename);
190 for (
auto &Sec : Obj.sections()) {
191 if (Sec.Name == SecName) {
194 "cannot dump section '%s': it has no contents",
195 SecName.
str().c_str());
200 std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
201 llvm::copy(Sec.OriginalData, Buf->getBufferStart());
202 if (
Error E = Buf->commit())
209 "section '%s' not found", SecName.
str().c_str());
219 std::optional<DebugCompressionType> CType;
221 if (Matcher.matches(Sec.Name))
234 if (Sec.ParentSegment)
237 "section '" + Sec.Name +
238 "' within a segment cannot be (de)compressed");
242 ToReplace.emplace_back(
245 ToReplace.emplace_back(&Sec, [=, S = &Sec] {
253 for (
auto [S, Func] : ToReplace)
263 if (!Name.consume_front(
"$x") && !Name.consume_front(
"$d"))
265 return Name.empty() || Name.starts_with(
".");
273 if (!Name.consume_front(
"$a") && !Name.consume_front(
"$d") &&
274 !Name.consume_front(
"$t"))
276 return Name.empty() || Name.starts_with(
".");
281 switch (Obj.Machine) {
294 return !Sym.Referenced &&
303 if (!Obj.SymbolTable)
306 Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
312 if (!Sym.isCommon() && Sym.getShndx() !=
SHN_UNDEF &&
319 if (Matcher.matches(Sym.Name))
320 Sym.Visibility = Visibility;
351 Sym.Name = std::string(
I->getValue());
370 auto RemoveSymbolsPred = [&](
const Symbol &Sym) {
392 if (!Sym.Referenced) {
408 return Obj.removeSymbols(RemoveSymbolsPred);
423 RemovePred = [RemovePred](
const SectionBase &Sec) {
428 RemovePred = [RemovePred, &Obj](
const SectionBase &Sec) {
433 RemovePred = [RemovePred, &Obj](
const SectionBase &Sec) {
438 if (&Sec == Obj.SectionNames)
451 RemovePred = [RemovePred](
const SectionBase &Sec) {
452 return RemovePred(Sec) || Sec.ParentSegment ==
nullptr;
457 RemovePred = [RemovePred](
const SectionBase &Sec) {
463 RemovePred = [RemovePred, &Obj](
const SectionBase &Sec) {
466 if (&Sec == Obj.SectionNames)
468 return (Sec.Flags &
SHF_ALLOC) == 0 && Sec.ParentSegment ==
nullptr;
472 RemovePred = [RemovePred, &Obj](
const SectionBase &Sec) {
475 if (&Sec == Obj.SectionNames)
487 if (Sec.ParentSegment !=
nullptr)
493 RemovePred = [RemovePred](
const SectionBase &Sec) {
498 return (Sec.Flags &
SHF_ALLOC) != 0 && !Sec.ParentSegment;
504 RemovePred = [&Config, RemovePred, &Obj](
const SectionBase &Sec) {
514 if (Obj.SectionNames == &Sec)
516 if (Obj.SymbolTable == &Sec ||
517 (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
526 RemovePred = [&Config, RemovePred](
const SectionBase &Sec) {
531 return RemovePred(Sec);
541 Obj.SymbolTable && !Obj.SymbolTable->empty()) {
542 RemovePred = [&Obj, RemovePred](
const SectionBase &Sec) {
543 if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
545 return RemovePred(Sec);
552 if (
Error E = Obj.compressOrDecompressSections(Config))
566 uint8_t Visibility = DefaultVisibility;
607 Obj.SymbolTable->addSymbol(
613struct RemoveNoteDetail {
614 struct DeletedRange {
619 template <
class ELFT>
620 static std::vector<DeletedRange>
621 findNotesToRemove(ArrayRef<uint8_t>
Data,
size_t Align,
623 static std::vector<uint8_t> updateData(ArrayRef<uint8_t> OldData,
629std::vector<RemoveNoteDetail::DeletedRange>
630RemoveNoteDetail::findNotesToRemove(ArrayRef<uint8_t>
Data,
size_t Align,
632 using Elf_Nhdr =
typename ELFT::Nhdr;
633 using Elf_Note =
typename ELFT::Note;
636 while (CurPos +
sizeof(Elf_Nhdr) <=
Data.size()) {
637 auto Nhdr =
reinterpret_cast<const Elf_Nhdr *
>(
Data.data() + CurPos);
638 size_t FullSize = Nhdr->getSize(Align);
639 if (CurPos + FullSize >
Data.size())
641 Elf_Note
Note(*Nhdr);
648 ToRemove.push_back({CurPos, CurPos + FullSize});
655RemoveNoteDetail::updateData(ArrayRef<uint8_t> OldData,
657 std::vector<uint8_t> NewData;
658 NewData.reserve(OldData.
size());
660 for (
const DeletedRange &RemRange :
ToRemove) {
661 if (CurPos < RemRange.OldFrom) {
662 auto Slice = OldData.
slice(CurPos, RemRange.OldFrom - CurPos);
665 CurPos = RemRange.OldTo;
667 if (CurPos < OldData.
size()) {
668 auto Slice = OldData.
slice(CurPos);
679 for (
Segment &Seg : Obj.segments()) {
688 for (
auto &Sec : Obj.sections()) {
689 if (Sec.Type !=
SHT_NOTE || !Sec.hasContents())
692 if (Sec.ParentSegment) {
696 "cannot remove note(s) from " + Sec.Name +
697 ": sections in segments are not supported")))
702 size_t Align = std::max<size_t>(4, Sec.Align);
706 ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
707 OldData,
Align, NotesToRemove)
708 : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
709 OldData,
Align, NotesToRemove);
711 if (
Error E = Obj.updateSectionData(
712 Sec, RemoveNoteDetail::updateData(OldData,
ToRemove)))
740 if (
Data.size() < 12) {
743 << Name <<
" data must be either empty or at least 12 bytes long";
746 if (
Data.size() % 4 != 0) {
749 << Name <<
" data size must be a multiple of 4 bytes";
763 if (ActualDataSize != ExpectedDataSize) {
767 <<
" data size is incompatible with the content of "
768 "the name and description size fields:"
769 <<
" expecting " << ExpectedDataSize <<
", found " << ActualDataSize;
791 return Obj.removeSections(
793 [&Obj](
const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
820 Sec.Align =
I->second;
825 for (
Segment &Seg : Obj.segments()) {
826 if (Seg.MemSize > 0) {
828 Seg.PAddr > std::numeric_limits<uint64_t>::max() -
833 " cannot be increased by 0x" +
835 ". The result would overflow");
837 Seg.PAddr < std::numeric_limits<uint64_t>::min() -
842 " cannot be decreased by 0x" +
844 ". The result would underflow");
855 "cannot change section address in a non-relocatable file");
860 if (PatternUpdate.SectionPattern.matches(Sec.Name) &&
861 SectionsToUpdateAddress.
try_emplace(Sec.Name, PatternUpdate.Update)
864 Sec.Addr < PatternUpdate.Update.Value) {
868 " cannot be decreased by 0x" +
870 ". The result would underflow");
873 Sec.Addr > std::numeric_limits<uint64_t>::max() -
874 PatternUpdate.Update.Value) {
878 " cannot be increased by 0x" +
880 ". The result would overflow");
883 switch (PatternUpdate.Update.Kind) {
885 Sec.Addr = PatternUpdate.Update.Value;
888 Sec.Addr -= PatternUpdate.Update.Value;
891 Sec.Addr += PatternUpdate.Update.Value;
900 for (
auto &Sec : Obj.sections())
918 if (Name.starts_with(
".note") && Name !=
".note.GNU-stack") {
931 return Obj.updateSection(Name,
Data);
944 if (
Error E = Obj.addNewSymbolTable())
952 for (
auto &Sec : Obj.sections()) {
966 std::vector<RelocationSectionBase *> RelocSections;
973 Sec.Name = std::string(SR.
NewName);
978 RenamedSections.
insert(&Sec);
979 }
else if (RelocSec && !(Sec.Flags &
SHF_ALLOC))
986 RelocSections.push_back(RelocSec);
991 auto Iter = RenamedSections.
find(RelocSec->getSection());
992 if (Iter != RenamedSections.
end())
993 RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str();
1005 PrefixedSections.
insert(&Sec);
1014 const SectionBase *TargetSec = RelocSec->getSection();
1020 if (PrefixedSections.
count(TargetSec))
1021 Sec.Name = (RelocSec->getNamePrefix() + TargetSec->
Name).str();
1038 std::unique_ptr<Writer>
Writer =
1051 return Obj.takeError();
1057 return writeOutput(Config, **Obj, Out, OutputElfType);
1067 return Obj.takeError();
1075 return writeOutput(Config, **Obj, Out, OutputElfType);
1086 return Obj.takeError();
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
static Error removeNotes(Object &Obj, endianness Endianness, ArrayRef< RemoveNoteInfo > NotesToRemove, function_ref< Error(Error)> ErrorCallback)
static Error replaceAndRemoveSections(const CommonConfig &Config, const ELFConfig &ELFConfig, Object &Obj)
static bool isArmMappingSymbol(const Symbol &Sym)
static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig, ElfType OutputElfType, Object &Obj)
static Error handleUserSection(const NewSectionInfo &NewSection, function_ref< Error(StringRef, ArrayRef< uint8_t >)> F)
static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, uint8_t DefaultVisibility)
static Error updateAndRemoveSymbols(const CommonConfig &Config, const ELFConfig &ELFConfig, Object &Obj)
std::function< bool(const SectionBase &Sec)> SectionPred
static Error verifyNoteSection(StringRef Name, endianness Endianness, ArrayRef< uint8_t > Data)
static bool isDWOSection(const SectionBase &Sec)
static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym)
static bool isDebugSection(const SectionBase &Sec)
static Error dumpSectionToFile(StringRef SecName, StringRef Filename, StringRef InputFilename, Object &Obj)
static Error writeOutput(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)
static bool isUnneededSymbol(const Symbol &Sym)
static bool isAArch64MappingSymbol(const Symbol &Sym)
static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec)
static void setSectionType(SectionBase &Sec, uint64_t Type)
static Expected< uint64_t > getNewShfFlags(SectionFlag AllFlags, uint16_t EMachine)
static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags, uint16_t EMachine)
static std::unique_ptr< Writer > createELFWriter(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)
static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, uint64_t NewFlags, uint16_t EMachine)
static std::unique_ptr< Writer > createWriter(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)
static ElfType getOutputElfType(const Binary &Bin)
static cl::opt< std::string > InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"))
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static LLVM_ABI Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
static Twine utohexstr(uint64_t Val)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
iterator find(const_arg_type_t< ValueT > V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An efficient, type-erasing, non-owning reference to a callable.
bool matches(StringRef S) const
SectionTableRef sections() const
T & addSection(Ts &&...Args)
Error compressOrDecompressSections(const CommonConfig &Config)
Error replaceSections(const DenseMap< SectionBase *, SectionBase * > &FromTo)
virtual Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const =0
virtual Error finalize()=0
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr size_t NameSize
LLVM_ABI Error executeObjcopyOnIHex(const CommonConfig &Config, const ELFConfig &ELFConfig, MemoryBuffer &In, raw_ostream &Out)
Apply the transformations described by Config and ELFConfig to In, which must represent an IHex file,...
LLVM_ABI Error executeObjcopyOnBinary(const CommonConfig &Config, const ELFConfig &ELFConfig, object::ELFObjectFileBase &In, raw_ostream &Out)
Apply the transformations described by Config and ELFConfig to In and writes the result into Out.
LLVM_ABI Error executeObjcopyOnRawBinary(const CommonConfig &Config, const ELFConfig &ELFConfig, MemoryBuffer &In, raw_ostream &Out)
Apply the transformations described by Config and ELFConfig to In, which is treated as a raw binary i...
uint32_t read32(const void *P, endianness E)
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
SymInfo contains information about symbol: it's address and section index which is -1LL for absolute ...
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallVector< SectionPatternAddressUpdate, 0 > ChangeSectionAddress
SmallVector< NewSectionInfo, 0 > UpdateSection
NameMatcher SymbolsToGlobalize
int64_t ChangeSectionLMAValAll
StringMap< SectionRename > SectionsToRename
NameMatcher SymbolsToRemove
std::optional< MachineInfo > OutputArch
SmallVector< std::pair< NameMatcher, llvm::DebugCompressionType >, 0 > compressSections
bool ExtractMainPartition
bool DecompressDebugSections
SmallVector< StringRef, 0 > DumpSection
SmallVector< NewSymbolInfo, 0 > SymbolsToAdd
NameMatcher SymbolsToKeep
StringRef AddGnuDebugLink
StringMap< uint64_t > SetSectionAlignment
NameMatcher SymbolsToWeaken
uint32_t GnuDebugLinkCRC32
NameMatcher SymbolsToKeepGlobal
DebugCompressionType CompressionType
std::function< Error(Error)> ErrorCallback
StringMap< SectionFlagsUpdate > SetSectionFlags
NameMatcher SymbolsToSkip
SmallVector< NewSectionInfo, 0 > AddSection
NameMatcher UnneededSymbolsToRemove
StringRef SymbolsPrefixRemove
std::optional< StringRef > ExtractPartition
StringRef AllocSectionsPrefix
StringMap< StringRef > SymbolsToRename
NameMatcher SymbolsToLocalize
StringMap< uint64_t > SetSectionType
std::vector< std::pair< NameMatcher, uint8_t > > SymbolsToSetVisibility
uint8_t NewSymbolVisibility
SmallVector< RemoveNoteInfo, 0 > NotesToRemove
std::function< uint64_t(uint64_t)> EntryExpr
std::shared_ptr< MemoryBuffer > SectionData
std::optional< SectionFlag > NewFlags