aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp112
-rw-r--r--llvm/lib/ObjCopy/ELF/ELFObject.cpp41
-rw-r--r--llvm/lib/ObjCopy/ELF/ELFObject.h7
3 files changed, 144 insertions, 16 deletions
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 4793651..42581af 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -609,6 +609,112 @@ static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
}
+namespace {
+struct RemoveNoteDetail {
+ struct DeletedRange {
+ uint64_t OldFrom;
+ uint64_t OldTo;
+ };
+
+ template <class ELFT>
+ static std::vector<DeletedRange>
+ findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align,
+ ArrayRef<RemoveNoteInfo> NotesToRemove);
+ static std::vector<uint8_t> updateData(ArrayRef<uint8_t> OldData,
+ ArrayRef<DeletedRange> ToRemove);
+};
+} // namespace
+
+template <class ELFT>
+std::vector<RemoveNoteDetail::DeletedRange>
+RemoveNoteDetail::findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align,
+ ArrayRef<RemoveNoteInfo> NotesToRemove) {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT);
+ std::vector<DeletedRange> ToRemove;
+ uint64_t CurPos = 0;
+ while (CurPos + sizeof(Elf_Nhdr) <= Data.size()) {
+ auto Nhdr = reinterpret_cast<const Elf_Nhdr *>(Data.data() + CurPos);
+ size_t FullSize = Nhdr->getSize(Align);
+ if (CurPos + FullSize > Data.size())
+ break;
+ Elf_Note Note(*Nhdr);
+ bool ShouldRemove =
+ llvm::any_of(NotesToRemove, [&Note](const RemoveNoteInfo &NoteInfo) {
+ return NoteInfo.TypeId == Note.getType() &&
+ (NoteInfo.Name.empty() || NoteInfo.Name == Note.getName());
+ });
+ if (ShouldRemove)
+ ToRemove.push_back({CurPos, CurPos + FullSize});
+ CurPos += FullSize;
+ }
+ return ToRemove;
+}
+
+std::vector<uint8_t>
+RemoveNoteDetail::updateData(ArrayRef<uint8_t> OldData,
+ ArrayRef<DeletedRange> ToRemove) {
+ std::vector<uint8_t> NewData;
+ NewData.reserve(OldData.size());
+ uint64_t CurPos = 0;
+ for (const DeletedRange &RemRange : ToRemove) {
+ if (CurPos < RemRange.OldFrom) {
+ auto Slice = OldData.slice(CurPos, RemRange.OldFrom - CurPos);
+ NewData.insert(NewData.end(), Slice.begin(), Slice.end());
+ }
+ CurPos = RemRange.OldTo;
+ }
+ if (CurPos < OldData.size()) {
+ auto Slice = OldData.slice(CurPos);
+ NewData.insert(NewData.end(), Slice.begin(), Slice.end());
+ }
+ return NewData;
+}
+
+static Error removeNotes(Object &Obj, endianness Endianness,
+ ArrayRef<RemoveNoteInfo> NotesToRemove,
+ function_ref<Error(Error)> ErrorCallback) {
+ // TODO: Support note segments.
+ if (ErrorCallback) {
+ for (Segment &Seg : Obj.segments()) {
+ if (Seg.Type == PT_NOTE) {
+ if (Error E = ErrorCallback(createStringError(
+ errc::not_supported, "note segments are not supported")))
+ return E;
+ break;
+ }
+ }
+ }
+ for (auto &Sec : Obj.sections()) {
+ if (Sec.Type != SHT_NOTE || !Sec.hasContents())
+ continue;
+ // TODO: Support note sections in segments.
+ if (Sec.ParentSegment) {
+ if (ErrorCallback)
+ if (Error E = ErrorCallback(createStringError(
+ errc::not_supported,
+ "cannot remove note(s) from " + Sec.Name +
+ ": sections in segments are not supported")))
+ return E;
+ continue;
+ }
+ ArrayRef<uint8_t> OldData = Sec.getContents();
+ size_t Align = std::max<size_t>(4, Sec.Align);
+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
+ // header, so the parsers are the same.
+ auto ToRemove = (Endianness == endianness::little)
+ ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
+ OldData, Align, NotesToRemove)
+ : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
+ OldData, Align, NotesToRemove);
+ if (!ToRemove.empty()) {
+ if (Error E = Obj.updateSectionData(
+ Sec, RemoveNoteDetail::updateData(OldData, ToRemove)))
+ return E;
+ }
+ }
+ return Error::success();
+}
+
static Error
handleUserSection(const NewSectionInfo &NewSection,
function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) {
@@ -799,6 +905,12 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
? endianness::little
: endianness::big;
+ if (!ELFConfig.NotesToRemove.empty()) {
+ if (Error Err =
+ removeNotes(Obj, E, ELFConfig.NotesToRemove, Config.ErrorCallback))
+ return Err;
+ }
+
for (const NewSectionInfo &AddedSection : Config.AddSection) {
auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error {
OwnedDataSection &NewSection =
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 01c2f24..45c7ea4 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2154,37 +2154,46 @@ ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
: Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
OnlyKeepDebug(OnlyKeepDebug) {}
-Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
- auto It = llvm::find_if(Sections,
- [&](const SecPtr &Sec) { return Sec->Name == Name; });
- if (It == Sections.end())
- return createStringError(errc::invalid_argument, "section '%s' not found",
- Name.str().c_str());
-
- auto *OldSec = It->get();
- if (!OldSec->hasContents())
+Error Object::updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data) {
+ if (!Sec->hasContents())
return createStringError(
errc::invalid_argument,
"section '%s' cannot be updated because it does not have contents",
- Name.str().c_str());
+ Sec->Name.c_str());
- if (Data.size() > OldSec->Size && OldSec->ParentSegment)
+ if (Data.size() > Sec->Size && Sec->ParentSegment)
return createStringError(errc::invalid_argument,
"cannot fit data of size %zu into section '%s' "
"with size %" PRIu64 " that is part of a segment",
- Data.size(), Name.str().c_str(), OldSec->Size);
+ Data.size(), Sec->Name.c_str(), Sec->Size);
- if (!OldSec->ParentSegment) {
- *It = std::make_unique<OwnedDataSection>(*OldSec, Data);
+ if (!Sec->ParentSegment) {
+ Sec = std::make_unique<OwnedDataSection>(*Sec, Data);
} else {
// The segment writer will be in charge of updating these contents.
- OldSec->Size = Data.size();
- UpdatedSections[OldSec] = Data;
+ Sec->Size = Data.size();
+ UpdatedSections[Sec.get()] = Data;
}
return Error::success();
}
+Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
+ auto It = llvm::find_if(Sections,
+ [&](const SecPtr &Sec) { return Sec->Name == Name; });
+ if (It == Sections.end())
+ return createStringError(errc::invalid_argument, "section '%s' not found",
+ Name.str().c_str());
+ return updateSectionData(*It, Data);
+}
+
+Error Object::updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data) {
+ auto It = llvm::find_if(Sections,
+ [&](const SecPtr &Sec) { return Sec.get() == &S; });
+ assert(It != Sections.end() && "The section should belong to the object");
+ return updateSectionData(*It, Data);
+}
+
Error Object::removeSections(
bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 6ccf853..d8f79a4 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -549,6 +549,7 @@ public:
virtual void
replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
virtual bool hasContents() const { return false; }
+ virtual ArrayRef<uint8_t> getContents() const { return {}; }
// Notify the section that it is subject to removal.
virtual void onRemove();
@@ -619,6 +620,8 @@ public:
bool hasContents() const override {
return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;
}
+ ArrayRef<uint8_t> getContents() const override { return Contents; }
+
void restoreSymTabLink(SymbolTableSection &SymTab) override;
};
@@ -654,6 +657,7 @@ public:
Error accept(SectionVisitor &Sec) const override;
Error accept(MutableSectionVisitor &Visitor) override;
bool hasContents() const override { return true; }
+ ArrayRef<uint8_t> getContents() const override { return Data; }
};
class CompressedSection : public SectionBase {
@@ -1164,6 +1168,8 @@ private:
return Sec.Flags & ELF::SHF_ALLOC;
};
+ Error updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data);
+
public:
template <class T>
using ConstRange = iterator_range<pointee_iterator<
@@ -1206,6 +1212,7 @@ public:
const auto &getUpdatedSections() const { return UpdatedSections; }
Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);
+ Error updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data);
SectionBase *findSection(StringRef Name) {
auto SecIt =