diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -43,8 +43,8 @@ OS.write(reinterpret_cast(&Integer), sizeof(T)); } -static void writeVariableSizedInteger(uint64_t Integer, size_t Size, - raw_ostream &OS, bool IsLittleEndian) { +static Error writeVariableSizedInteger(uint64_t Integer, size_t Size, + raw_ostream &OS, bool IsLittleEndian) { if (8 == Size) writeInteger((uint64_t)Integer, OS, IsLittleEndian); else if (4 == Size) @@ -54,7 +54,10 @@ else if (1 == Size) writeInteger((uint8_t)Integer, OS, IsLittleEndian); else - assert(false && "Invalid integer write size."); + return createStringError(errc::not_supported, + "invalid integer write size: %zu", Size); + + return Error::success(); } static void ZeroFillBytes(raw_ostream &OS, size_t Size) { @@ -75,8 +78,10 @@ bool IsLittleEndian) { bool IsDWARF64 = Format == dwarf::DWARF64; if (IsDWARF64) - writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS, IsLittleEndian); - writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian); + cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS, + IsLittleEndian)); + cantFail( + writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian)); } Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { @@ -123,10 +128,13 @@ ZeroFillBytes(OS, FirstDescriptor - HeaderSize); for (auto Descriptor : Range.Descriptors) { - writeVariableSizedInteger(Descriptor.Address, Range.AddrSize, OS, - DI.IsLittleEndian); - writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS, - DI.IsLittleEndian); + if (Error Err = writeVariableSizedInteger( + Descriptor.Address, Range.AddrSize, OS, DI.IsLittleEndian)) + return createStringError(errc::not_supported, + "unable to write debug_aranges address: %s", + toString(std::move(Err)).c_str()); + cantFail(writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS, + DI.IsLittleEndian)); } ZeroFillBytes(OS, Range.AddrSize * 2); } @@ -155,10 +163,14 @@ else AddrSize = DI.Is64bit ? 8 : 4; for (auto Entry : DebugRanges.Entries) { - writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS, - DI.IsLittleEndian); - writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS, - DI.IsLittleEndian); + if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS, + DI.IsLittleEndian)) + return createStringError( + errc::not_supported, + "unable to write debug_ranges address offset: %s", + toString(std::move(Err)).c_str()); + cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS, + DI.IsLittleEndian)); } ZeroFillBytes(OS, AddrSize * 2); ++EntryIndex; @@ -272,8 +284,8 @@ DI.IsLittleEndian); uint64_t SizeOfPrologueLength = LineTable.Format == dwarf::DWARF64 ? 8 : 4; writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian); - writeVariableSizedInteger(LineTable.PrologueLength, SizeOfPrologueLength, - OS, DI.IsLittleEndian); + cantFail(writeVariableSizedInteger( + LineTable.PrologueLength, SizeOfPrologueLength, OS, DI.IsLittleEndian)); writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian); if (LineTable.Version >= 4) writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian); @@ -303,8 +315,10 @@ switch (Op.SubOpcode) { case dwarf::DW_LNE_set_address: case dwarf::DW_LNE_set_discriminator: - writeVariableSizedInteger(Op.Data, DI.CompileUnits[0].AddrSize, OS, - DI.IsLittleEndian); + // TODO: Test this error. + if (Error Err = writeVariableSizedInteger( + Op.Data, DI.CompileUnits[0].AddrSize, OS, DI.IsLittleEndian)) + return Err; break; case dwarf::DW_LNE_define_file: emitFileEntry(OS, Op.FileEntry); @@ -375,11 +389,18 @@ for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) { if (TableEntry.SegSelectorSize != 0) - writeVariableSizedInteger(Pair.Segment, TableEntry.SegSelectorSize, OS, - DI.IsLittleEndian); + if (Error Err = writeVariableSizedInteger(Pair.Segment, + TableEntry.SegSelectorSize, + OS, DI.IsLittleEndian)) + return createStringError(errc::not_supported, + "unable to write debug_addr segment: %s", + toString(std::move(Err)).c_str()); if (AddrSize != 0) - writeVariableSizedInteger(Pair.Address, AddrSize, OS, - DI.IsLittleEndian); + if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS, + DI.IsLittleEndian)) + return createStringError(errc::not_supported, + "unable to write debug_addr address: %s", + toString(std::move(Err)).c_str()); } } diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-addr.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-addr.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-addr.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-addr.yaml @@ -592,3 +592,53 @@ debug_addr: - Version: 5 Entries: [] + +## l) Test that yaml2obj still generates a .debug_addr section if we assign an invalid value +## to 'AddressSize' or 'SegmentSelectorSize' when the 'Entries' list is empty. + +# RUN: yaml2obj --docnum=10 -DSIZENAME=AddressSize %s -o %t10.addr.o +# RUN: llvm-readelf --hex-dump=.debug_addr %t10.addr.o | \ +# RUN: FileCheck -DADDRSIZE=03 -DSEGSIZE=00 %s --check-prefix=ADDR-SEG-SIZE + +# RUN: yaml2obj --docnum=10 -DSIZENAME=SegmentSelectorSize %s -o %t10.seg.o +# RUN: llvm-readelf --hex-dump=.debug_addr %t10.seg.o | \ +# RUN: FileCheck -DADDRSIZE=08 -DSEGSIZE=03 %s --check-prefix=ADDR-SEG-SIZE + +# ADDR-SEG-SIZE: Hex dump of section '.debug_addr': +# ADDR-SEG-SIZE-NEXT: 0x00000000 04000000 0500[[ADDRSIZE]][[SEGSIZE]] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_addr: + - Version: 5 + [[SIZENAME]]: 3 + Entries: [] + +## m) Test that yaml2obj emits an error message if we try to assign an invalid value to +## 'AddressSize' or 'SegmentSelectorSize' when the 'Entries' list isn't empty. + +# RUN: not yaml2obj --docnum=11 -DSIZENAME=AddressSize %s 2>&1 | \ +# RUN: FileCheck -DFIELD=address %s --check-prefix=INVALID-SIZE + +# RUN: not yaml2obj --docnum=11 -DSIZENAME=SegmentSelectorSize %s 2>&1 | \ +# RUN: FileCheck -DFIELD=segment %s --check-prefix=INVALID-SIZE + +# INVALID-SIZE: yaml2obj: error: unable to write debug_addr [[FIELD]]: invalid integer write size: 3 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_addr: + - Version: 5 + [[SIZENAME]]: 3 + Entries: + - Address: 0x1234 diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-aranges.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-aranges.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-aranges.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-aranges.yaml @@ -406,3 +406,55 @@ Descriptors: - Address: 0x0000000000001234 Length: 0x20 + +## h) Test that yaml2obj still generates a .debug_aranges section if we assign an invalid value +## to 'AddrSize' when the 'Descriptors' list is empty. + +# RUN: yaml2obj --docnum=8 %s -o %t8.o +# RUN: llvm-readelf --hex-dump=.debug_aranges %t8.o | \ +# RUN: FileCheck %s --check-prefix=ADDR-SIZE + +# ADDR-SIZE: Hex dump of section '.debug_aranges': +# ADDR-SIZE-NEXT: 0x00000000 2c000000 02000000 00000700 00000000 +## ^~ address_size (1-byte) 0x07 +# ADDR-SIZE-NEXT: 0x00000010 00000000 00000000 00000000 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_aranges: + - Length: 0x2c + Version: 2 + CuOffset: 0 + AddrSize: 0x07 ## Invalid address_size. + SegSize: 0 + Descriptors: [] + +## i) Test that yaml2obj emits an error message if we try to assign an invalid value to +## 'AddrSize' when the 'Descriptors' list isn't empty. + +# RUN: not yaml2obj --docnum=9 %s 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-SIZE + +# INVALID-SIZE: yaml2obj: error: unable to write debug_aranges address: invalid integer write size: 7 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_aranges: + - Length: 0x2c + Version: 2 + CuOffset: 0 + AddrSize: 0x07 ## Invalid address_size. + SegSize: 0 + Descriptors: + - Address: 0x1234 + Length: 0x1000 diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-ranges.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-ranges.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-ranges.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-ranges.yaml @@ -375,3 +375,46 @@ Entries: - LowOffset: 0x01 HighOffset: 0x02 + +## j) Test that yaml2obj still generates a .debug_ranges section if we assign an invalid value +## to 'AddrSize' when the 'Entries' list is empty. + +# RUN: yaml2obj --docnum=10 %s -o %t10.o +# RUN: llvm-readelf --hex-dump=.debug_ranges %t10.o | \ +# RUN: FileCheck %s --check-prefix=ADDRSIZE + +# ADDRSIZE: Hex dump of section '.debug_ranges': +# ADDRSIZE-NEXT: 0x00000000 00000000 00000000 00000000 0000 +## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ terminating entry (2*AddrSize=14-byte) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_ranges: + - AddrSize: 0x07 + Entries: [] + +## k) Test that yaml2obj emits an error message if we try to assign an invalid value to +## 'AddrSize' when the 'Entries' list isn't empty. + +# RUN: not yaml2obj --docnum=11 %s 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-SIZE + +# INVALID-SIZE: yaml2obj: error: unable to write debug_ranges address offset: invalid integer write size: 7 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_ranges: + - AddrSize: 0x07 + Entries: + - LowOffset: 0x1234 + HighOffset: 0x5678