@@ -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, llvm::endianness E,
627
+ ArrayRef<uint8_t > Data) {
628
+
629
+ // An ELF note have the following structure:
630
+ // Name Size: 4 bytes (integer)
631
+ // Desc Size: 4 bytes (integer)
632
+ // Type : 4 bytes
633
+ // Name : variable size, padded to a 4 byte boundary
634
+ // Desc : variable size, padded to a 4 byte boundary
635
+
636
+ if (Data.empty ())
637
+ return Error::success ();
638
+
639
+ if (Data.size () < 12 ) {
640
+ std::string msg;
641
+ raw_string_ostream (msg)
642
+ << Name << " data must be either empty or at least 12 bytes long." ;
643
+ return createStringError (errc::invalid_argument, msg);
644
+ }
645
+ if (Data.size () % 4 != 0 ) {
646
+ std::string msg;
647
+ raw_string_ostream (msg)
648
+ << Name << " data size must be a multiple of 4 bytes." ;
649
+ return createStringError (errc::invalid_argument, msg);
650
+ }
651
+ ArrayRef<uint8_t > NameSize = Data.slice (0 , 4 );
652
+ ArrayRef<uint8_t > DescSize = Data.slice (4 , 4 );
653
+
654
+ uint32_t NameSizeValue, DescSizeValue;
655
+ std::memcpy (&NameSizeValue, NameSize.data (), 4 );
656
+ std::memcpy (&DescSizeValue, DescSize.data (), 4 );
657
+
658
+ if (llvm::endianness::native != E) {
659
+ NameSizeValue = byteswap (NameSizeValue);
660
+ DescSizeValue = byteswap (DescSizeValue);
661
+ }
662
+ uint64_t ExpectedDataSize =
663
+ 4 + 4 + 4 + (NameSizeValue + 3 ) / 4 * 4 + (DescSizeValue + 3 ) / 4 * 4 ;
664
+ uint64_t ActualDataSize = Data.size ();
665
+ if (ActualDataSize != ExpectedDataSize) {
666
+ std::string msg;
667
+ raw_string_ostream (msg) << Name
668
+ << " data size is incompatible with the content of "
669
+ " the name and description size fields:"
670
+ << " expecting " << ExpectedDataSize << " , found "
671
+ << 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,18 @@ 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
+ return verifyNoteSection (Name, E, Data);
741
+ }
684
742
return Error::success ();
685
743
};
686
744
if (Error E = handleUserSection (AddedSection, AddSection))
@@ -813,7 +871,7 @@ Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
813
871
814
872
const ElfType OutputElfType =
815
873
getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
816
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
874
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
817
875
return E;
818
876
return writeOutput (Config, **Obj, Out, OutputElfType);
819
877
}
@@ -831,7 +889,7 @@ Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
831
889
// (-B<arch>).
832
890
const ElfType OutputElfType =
833
891
getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
834
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
892
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
835
893
return E;
836
894
return writeOutput (Config, **Obj, Out, OutputElfType);
837
895
}
@@ -850,7 +908,7 @@ Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
850
908
? getOutputElfType (*Config.OutputArch )
851
909
: getOutputElfType (In);
852
910
853
- if (Error E = handleArgs (Config, ELFConfig, **Obj))
911
+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
854
912
return createFileError (Config.InputFilename , std::move (E));
855
913
856
914
if (Error E = writeOutput (Config, **Obj, Out, OutputElfType))
0 commit comments