@@ -623,6 +623,58 @@ handleUserSection(const NewSectionInfo &NewSection,
623
623
return F (NewSection.SectionName , Data);
624
624
}
625
625
626
+ static Error verifyNoteSection (StringRef Name, endianness Endianness,
627
+ ArrayRef<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 bytes
632
+ // Name : variable size, padded to a 4 byte boundary
633
+ // Desc : variable size, padded to a 4 byte boundary
634
+
635
+ if (Data.empty ())
636
+ return Error::success ();
637
+
638
+ if (Data.size () < 12 ) {
639
+ std::string msg;
640
+ raw_string_ostream (msg)
641
+ << Name << " data must be either empty or at least 12 bytes long" ;
642
+ return createStringError (errc::invalid_argument, msg);
643
+ }
644
+ if (Data.size () % 4 != 0 ) {
645
+ std::string msg;
646
+ raw_string_ostream (msg)
647
+ << Name << " data size must be a multiple of 4 bytes" ;
648
+ return createStringError (errc::invalid_argument, msg);
649
+ }
650
+ ArrayRef<uint8_t > NameSize = Data.slice (0 , 4 );
651
+ ArrayRef<uint8_t > DescSize = Data.slice (4 , 4 );
652
+
653
+ uint32_t NameSizeValue = *reinterpret_cast <const uint32_t *>(NameSize.data ());
654
+ uint32_t DescSizeValue = *reinterpret_cast <const uint32_t *>(DescSize.data ());
655
+
656
+ if (Endianness != llvm::endianness::native) {
657
+ NameSizeValue = byteswap (NameSizeValue);
658
+ DescSizeValue = byteswap (DescSizeValue);
659
+ }
660
+ uint64_t ExpectedDataSize =
661
+ /* NameSize=*/ 4 + /* DescSize=*/ 4 + /* Type=*/ 4 +
662
+ /* Name=*/ (NameSizeValue + 3 ) / 4 * 4 +
663
+ /* Desc=*/ (DescSizeValue + 3 ) / 4 * 4 ;
664
+ uint64_t ActualDataSize = Data.size ();
665
+ if (ActualDataSize != ExpectedDataSize) {
666
+ std::string msg;
667
+ raw_string_ostream (msg)
668
+ << Name
669
+ << " data size is incompatible with the content of "
670
+ " the name and description size fields:"
671
+ << " expecting " << ExpectedDataSize << " , found " << ActualDataSize;
672
+ return createStringError (errc::invalid_argument, msg);
673
+ }
674
+
675
+ return Error::success ();
676
+ }
677
+
626
678
// This function handles the high level operations of GNU objcopy including
627
679
// handling command line options. It's important to outline certain properties
628
680
// we expect to hold of the command line operations. Any operation that "keeps"
@@ -631,7 +683,7 @@ handleUserSection(const NewSectionInfo &NewSection,
631
683
// depend a) on the order the options occur in or b) on some opaque priority
632
684
// system. The only priority is that keeps/copies overrule removes.
633
685
static Error handleArgs (const CommonConfig &Config, const ELFConfig &ELFConfig,
634
- Object &Obj) {
686
+ ElfType OutputElfType, Object &Obj) {
635
687
if (Config.OutputArch ) {
636
688
Obj.Machine = Config.OutputArch ->EMachine ;
637
689
Obj.OSABI = Config.OutputArch ->OSABI ;
@@ -675,12 +727,19 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
675
727
if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
676
728
Sec.Type = SHT_NOBITS;
677
729
730
+ endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE
731
+ ? endianness::little
732
+ : endianness::big;
733
+
678
734
for (const NewSectionInfo &AddedSection : Config.AddSection ) {
679
- auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) {
735
+ auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) -> Error {
680
736
OwnedDataSection &NewSection =
681
737
Obj.addSection <OwnedDataSection>(Name, Data);
682
- if (Name.starts_with (" .note" ) && Name != " .note.GNU-stack" )
738
+ if (Name.starts_with (" .note" ) && Name != " .note.GNU-stack" ) {
683
739
NewSection.Type = SHT_NOTE;
740
+ if (Config.VerifyNoteSections )
741
+ return verifyNoteSection (Name, E, Data);
742
+ }
684
743
return Error::success ();
685
744
};
686
745
if (Error E = handleUserSection (AddedSection, AddSection))
@@ -813,7 +872,7 @@ Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
813
872
814
873
const ElfType OutputElfType =
815
874
getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
816
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
875
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
817
876
return E;
818
877
return writeOutput (Config, **Obj, Out, OutputElfType);
819
878
}
@@ -831,7 +890,7 @@ Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
831
890
// (-B<arch>).
832
891
const ElfType OutputElfType =
833
892
getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
834
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
893
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
835
894
return E;
836
895
return writeOutput (Config, **Obj, Out, OutputElfType);
837
896
}
@@ -850,7 +909,7 @@ Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
850
909
? getOutputElfType (*Config.OutputArch )
851
910
: getOutputElfType (In);
852
911
853
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
912
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
854
913
return createFileError (Config.InputFilename , std::move (E));
855
914
856
915
if (Error E = writeOutput (Config, **Obj, Out, OutputElfType))
0 commit comments