@@ -609,6 +609,113 @@ 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+ using Elf_Nhdr = typename ELFT::Nhdr;
633+ using Elf_Note = typename ELFT::Note;
634+ std::vector<DeletedRange> ToRemove;
635+ uint64_t CurPos = 0 ;
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 ())
640+ break ;
641+ Elf_Note Note (*Nhdr);
642+ bool ShouldRemove =
643+ llvm::any_of (NotesToRemove, [&Note](const RemoveNoteInfo &NoteInfo) {
644+ return NoteInfo.TypeId == Note.getType () &&
645+ (NoteInfo.Name .empty () || NoteInfo.Name == Note.getName ());
646+ });
647+ if (ShouldRemove)
648+ ToRemove.push_back ({CurPos, CurPos + FullSize});
649+ CurPos += FullSize;
650+ }
651+ return ToRemove;
652+ }
653+
654+ std::vector<uint8_t >
655+ RemoveNoteDetail::updateData (ArrayRef<uint8_t > OldData,
656+ ArrayRef<DeletedRange> ToRemove) {
657+ std::vector<uint8_t > NewData;
658+ NewData.reserve (OldData.size ());
659+ uint64_t CurPos = 0 ;
660+ for (const DeletedRange &RemRange : ToRemove) {
661+ if (CurPos < RemRange.OldFrom ) {
662+ auto Slice = OldData.slice (CurPos, RemRange.OldFrom - CurPos);
663+ NewData.insert (NewData.end (), Slice.begin (), Slice.end ());
664+ }
665+ CurPos = RemRange.OldTo ;
666+ }
667+ if (CurPos < OldData.size ()) {
668+ auto Slice = OldData.slice (CurPos);
669+ NewData.insert (NewData.end (), Slice.begin (), Slice.end ());
670+ }
671+ return NewData;
672+ }
673+
674+ static Error removeNotes (Object &Obj, endianness Endianness,
675+ ArrayRef<RemoveNoteInfo> NotesToRemove,
676+ function_ref<Error(Error)> ErrorCallback) {
677+ // TODO: Support note segments.
678+ if (ErrorCallback) {
679+ for (Segment &Seg : Obj.segments ()) {
680+ if (Seg.Type == PT_NOTE) {
681+ if (Error E = ErrorCallback (createStringError (
682+ errc::not_supported, " note segments are not supported" )))
683+ return E;
684+ break ;
685+ }
686+ }
687+ }
688+ for (auto &Sec : Obj.sections ()) {
689+ if (Sec.Type != SHT_NOTE || !Sec.hasContents ())
690+ continue ;
691+ // TODO: Support note sections in segments.
692+ if (Sec.ParentSegment ) {
693+ if (ErrorCallback)
694+ if (Error E = ErrorCallback (createStringError (
695+ errc::not_supported,
696+ " cannot remove note(s) from " + Sec.Name +
697+ " : sections in segments are not supported" )))
698+ return E;
699+ continue ;
700+ }
701+ ArrayRef<uint8_t > OldData = Sec.getContents ();
702+ size_t Align = std::max<size_t >(4 , Sec.Align );
703+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
704+ // header, so the parsers are the same.
705+ auto ToRemove = (Endianness == endianness::little)
706+ ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
707+ OldData, Align, NotesToRemove)
708+ : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
709+ OldData, Align, NotesToRemove);
710+ if (!ToRemove.empty ()) {
711+ if (Error E = Obj.updateSectionData (
712+ Sec, RemoveNoteDetail::updateData (OldData, ToRemove)))
713+ return E;
714+ }
715+ }
716+ return Error::success ();
717+ }
718+
612719static Error
613720handleUserSection (const NewSectionInfo &NewSection,
614721 function_ref<Error(StringRef, ArrayRef<uint8_t >)> F) {
@@ -799,6 +906,12 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
799906 ? endianness::little
800907 : endianness::big;
801908
909+ if (!ELFConfig.NotesToRemove .empty ()) {
910+ if (Error Err =
911+ removeNotes (Obj, E, ELFConfig.NotesToRemove , Config.ErrorCallback ))
912+ return Err;
913+ }
914+
802915 for (const NewSectionInfo &AddedSection : Config.AddSection ) {
803916 auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) -> Error {
804917 OwnedDataSection &NewSection =
0 commit comments