@@ -609,6 +609,112 @@ static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
609609 Sec ? (uint16_t )SYMBOL_SIMPLE_INDEX : (uint16_t )SHN_ABS, 0 );
610610}
611611
612+ namespace {
613+ struct RemoveNoteDetail {
614+ struct DeletedRange {
615+ uint64_t OldFrom;
616+ uint64_t OldTo;
617+ };
618+
619+ template <class ELFT >
620+ static std::vector<DeletedRange>
621+ findNotesToRemove (ArrayRef<uint8_t > Data, size_t Align,
622+ ArrayRef<RemoveNoteInfo> NotesToRemove);
623+ static std::vector<uint8_t > updateData (ArrayRef<uint8_t > OldData,
624+ ArrayRef<DeletedRange> ToRemove);
625+ };
626+ } // namespace
627+
628+ template <class ELFT >
629+ std::vector<RemoveNoteDetail::DeletedRange>
630+ RemoveNoteDetail::findNotesToRemove (ArrayRef<uint8_t > Data, size_t Align,
631+ ArrayRef<RemoveNoteInfo> NotesToRemove) {
632+ LLVM_ELF_IMPORT_TYPES_ELFT (ELFT);
633+ std::vector<DeletedRange> ToRemove;
634+ uint64_t CurPos = 0 ;
635+ while (CurPos + sizeof (Elf_Nhdr) <= Data.size ()) {
636+ auto Nhdr = reinterpret_cast <const Elf_Nhdr *>(Data.data () + CurPos);
637+ size_t FullSize = Nhdr->getSize (Align);
638+ if (CurPos + FullSize > Data.size ())
639+ break ;
640+ Elf_Note Note (*Nhdr);
641+ bool ShouldRemove =
642+ llvm::any_of (NotesToRemove, [&Note](const RemoveNoteInfo &NoteInfo) {
643+ return NoteInfo.TypeId == Note.getType () &&
644+ (NoteInfo.Name .empty () || NoteInfo.Name == Note.getName ());
645+ });
646+ if (ShouldRemove)
647+ ToRemove.push_back ({CurPos, CurPos + FullSize});
648+ CurPos += FullSize;
649+ }
650+ return ToRemove;
651+ }
652+
653+ std::vector<uint8_t >
654+ RemoveNoteDetail::updateData (ArrayRef<uint8_t > OldData,
655+ ArrayRef<DeletedRange> ToRemove) {
656+ std::vector<uint8_t > NewData;
657+ NewData.reserve (OldData.size ());
658+ uint64_t CurPos = 0 ;
659+ for (const DeletedRange &RemRange : ToRemove) {
660+ if (CurPos < RemRange.OldFrom ) {
661+ auto Slice = OldData.slice (CurPos, RemRange.OldFrom - CurPos);
662+ NewData.insert (NewData.end (), Slice.begin (), Slice.end ());
663+ }
664+ CurPos = RemRange.OldTo ;
665+ }
666+ if (CurPos < OldData.size ()) {
667+ auto Slice = OldData.slice (CurPos);
668+ NewData.insert (NewData.end (), Slice.begin (), Slice.end ());
669+ }
670+ return NewData;
671+ }
672+
673+ static Error removeNotes (Object &Obj, endianness Endianness,
674+ ArrayRef<RemoveNoteInfo> NotesToRemove,
675+ function_ref<Error(Error)> ErrorCallback) {
676+ // TODO: Support note segments.
677+ if (ErrorCallback) {
678+ for (Segment &Seg : Obj.segments ()) {
679+ if (Seg.Type == PT_NOTE) {
680+ if (Error E = ErrorCallback (createStringError (
681+ errc::not_supported, " note segments are not supported" )))
682+ return E;
683+ break ;
684+ }
685+ }
686+ }
687+ for (auto &Sec : Obj.sections ()) {
688+ if (Sec.Type != SHT_NOTE || !Sec.hasContents ())
689+ continue ;
690+ // TODO: Support note sections in segments.
691+ if (Sec.ParentSegment ) {
692+ if (ErrorCallback)
693+ if (Error E = ErrorCallback (createStringError (
694+ errc::not_supported,
695+ " cannot remove note(s) from " + Sec.Name +
696+ " : sections in segments are not supported" )))
697+ return E;
698+ continue ;
699+ }
700+ ArrayRef<uint8_t > OldData = Sec.getContents ();
701+ size_t Align = std::max<size_t >(4 , Sec.Align );
702+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
703+ // header, so the parsers are the same.
704+ auto ToRemove = (Endianness == endianness::little)
705+ ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
706+ OldData, Align, NotesToRemove)
707+ : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
708+ OldData, Align, NotesToRemove);
709+ if (!ToRemove.empty ()) {
710+ if (Error E = Obj.updateSectionData (
711+ Sec, RemoveNoteDetail::updateData (OldData, ToRemove)))
712+ return E;
713+ }
714+ }
715+ return Error::success ();
716+ }
717+
612718static Error
613719handleUserSection (const NewSectionInfo &NewSection,
614720 function_ref<Error(StringRef, ArrayRef<uint8_t >)> F) {
@@ -799,6 +905,12 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
799905 ? endianness::little
800906 : endianness::big;
801907
908+ if (!ELFConfig.NotesToRemove .empty ()) {
909+ if (Error Err =
910+ removeNotes (Obj, E, ELFConfig.NotesToRemove , Config.ErrorCallback ))
911+ return Err;
912+ }
913+
802914 for (const NewSectionInfo &AddedSection : Config.AddSection ) {
803915 auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) -> Error {
804916 OwnedDataSection &NewSection =
0 commit comments