[DWARF] Fix v5 debug_line parsing of prologues with many files

Summary:
The directory_count and file_name_count fields are (section 6.2.4 of
DWARF5 spec) supposed to be uleb128s, not bytes. This bug meant that it
was not possible to correctly parse headers with more than 128 files or
directories.

I've found this bug by code inspection, though the limit is so small
someone would have run into it for real sooner or later. I've verified
that the producer side handles many files correctly, and that we are
able to parse such files after this fix.

Reviewers: dblaikie, jhenderson

Subscribers: aprantl, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D76498
This commit is contained in:
Pavel Labath 2020-03-20 15:27:37 +01:00
parent 7802be4a3d
commit d381b6a8d3
2 changed files with 71 additions and 4 deletions

View File

@ -255,8 +255,8 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
return DirDescriptors.takeError();
// Get the directory entries, according to the format described above.
int DirEntryCount = DebugLineData.getU8(OffsetPtr);
for (int I = 0; I != DirEntryCount; ++I) {
uint64_t DirEntryCount = DebugLineData.getULEB128(OffsetPtr);
for (uint64_t I = 0; I != DirEntryCount; ++I) {
for (auto Descriptor : *DirDescriptors) {
DWARFFormValue Value(Descriptor.Form);
switch (Descriptor.Type) {
@ -283,8 +283,8 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
return FileDescriptors.takeError();
// Get the file entries, according to the format described above.
int FileEntryCount = DebugLineData.getU8(OffsetPtr);
for (int I = 0; I != FileEntryCount; ++I) {
uint64_t FileEntryCount = DebugLineData.getULEB128(OffsetPtr);
for (uint64_t I = 0; I != FileEntryCount; ++I) {
DWARFDebugLine::FileNameEntry FileEntry;
for (auto Descriptor : *FileDescriptors) {
DWARFFormValue Value(Descriptor.Form);

View File

@ -0,0 +1,67 @@
## An object with many files and directories in a single debug_line contribution
## meant to test the handling of directory_count and file_name_count fields.
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
# RUN: llvm-dwarfdump -debug-line %t | FileCheck %s
# CHECK: include_directories[ 0] = "/d000"
# CHECK: include_directories[299] = "/d299"
# CHECK: file_names[ 0]:
# CHECK-NEXT: name: "000.c"
# CHECK-NEXT: dir_index: 0
# CHECK: file_names[299]:
# CHECK-NEXT: name: "299.c"
# CHECK-NEXT: dir_index: 299
.section .debug_line,"",@progbits
.long .Lunit_end0-.Lunit_start0 # Length of Unit
.Lunit_start0:
.short 5 # DWARF version number
.byte 8 # Address Size
.byte 0 # Segment Selector Size
.long .Lunit_header_end0 - .Lunit_params0 # Length of Prologue (invalid)
.Lunit_params0:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
.byte 1 # Default is_stmt
.byte -5 # Line Base
.byte 14 # Line Range
.byte 13 # Opcode Base
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # Standard Opcode Lengths
# Directory table format
.byte 1 # One element per directory entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
# Directory table entries
.uleb128 300 # 300 directories
.irpc a,012
.irpc b,0123456789
.irpc c,0123456789
.byte '/', 'd', '0'+\a, '0'+\b, '0'+\c, 0
.endr
.endr
.endr
# File table format
.byte 2 # 2 elements per file entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
.byte 2 # DW_LNCT_directory_index
.byte 0x05 # DW_FORM_data2
# File table entries
.uleb128 300 # 300 files
.irpc a,012
.irpc b,0123456789
.irpc c,0123456789
.byte '0'+\a, '0'+\b, '0'+\c, '.', 'c', 0 # File name
.word \a*100+\b*10+\c # Dir index
.endr
.endr
.endr
.Lunit_header_end0:
.byte 0, 1, 1 # DW_LNE_end_sequence
.Lunit_end0: