From 44615d519d1fefdefe994cc29be6fff7fec75c37 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 19 May 2019 17:54:33 +1000 Subject: [PATCH] write: don't require comp_dir or comp_name in LineProgram::from comp_dir has been seen missing in practice. comp_name is relatively unimportant, so don't require it either. --- src/write/line.rs | 110 +++++++++++++++++++++++++++++++++++++--------- src/write/mod.rs | 12 ----- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/src/write/line.rs b/src/write/line.rs index ff35cad72..160ec83e7 100644 --- a/src/write/line.rs +++ b/src/write/line.rs @@ -206,7 +206,11 @@ impl LineProgram { /// Panics if `directory` is empty or contains a null byte. pub fn add_directory(&mut self, directory: LineString) -> DirectoryId { if let LineString::String(ref val) = directory { - assert!(!val.is_empty()); + // For DWARF version <= 4, directories must not be empty. + // The first directory isn't emitted so skip the check for it. + if self.encoding.version <= 4 && !self.directories.is_empty() { + assert!(!val.is_empty()); + } assert!(!val.contains(&0)); } let (index, _) = self.directories.insert_full(directory); @@ -853,6 +857,9 @@ impl LineString { match *self { LineString::String(ref val) => { + if encoding.version <= 4 { + debug_assert!(!val.is_empty()); + } w.write(val)?; w.write_u8(0)?; } @@ -972,35 +979,39 @@ mod convert { let mut program = { let from_header = from_program.header(); + let encoding = from_header.encoding(); - let comp_dir = from_header - .directory(0) - .ok_or(ConvertError::MissingCompilationDirectory)?; - let comp_dir = LineString::from(comp_dir, dwarf, line_strings, strings)?; - - let comp_file = from_header - .file(0) - .ok_or(ConvertError::MissingCompilationFile)?; - let comp_name = - LineString::from(comp_file.path_name(), dwarf, line_strings, strings)?; - if comp_file.directory_index() != 0 { - return Err(ConvertError::InvalidDirectoryIndex); - } - let comp_file_info = FileInfo { - timestamp: comp_file.timestamp(), - size: comp_file.size(), - md5: *comp_file.md5(), + let comp_dir = match from_header.directory(0) { + Some(comp_dir) => LineString::from(comp_dir, dwarf, line_strings, strings)?, + None => LineString::new(&[][..], encoding, line_strings), + }; + + let (comp_name, comp_file_info) = match from_header.file(0) { + Some(comp_file) => { + if comp_file.directory_index() != 0 { + return Err(ConvertError::InvalidDirectoryIndex); + } + ( + LineString::from(comp_file.path_name(), dwarf, line_strings, strings)?, + Some(FileInfo { + timestamp: comp_file.timestamp(), + size: comp_file.size(), + md5: *comp_file.md5(), + }), + ) + } + None => (LineString::new(&[][..], encoding, line_strings), None), }; if from_header.line_base() > 0 { return Err(ConvertError::InvalidLineBase); } let mut program = LineProgram::new( - from_header.encoding(), + encoding, from_header.line_encoding(), comp_dir, comp_name, - Some(comp_file_info), + comp_file_info, ); let file_skip; @@ -1879,4 +1890,63 @@ mod tests { } } } + + #[test] + fn test_missing_comp_dir() { + let debug_line_str_offsets = DebugLineStrOffsets::none(); + let debug_str_offsets = DebugStrOffsets::none(); + + for &version in &[2, 3, 4, 5] { + for &address_size in &[4, 8] { + for &format in &[Format::Dwarf32, Format::Dwarf64] { + let encoding = Encoding { + format, + version, + address_size, + }; + let program = LineProgram::new( + encoding, + LineEncoding::default(), + LineString::String(Vec::new()), + LineString::String(Vec::new()), + None, + ); + + let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian)); + let debug_line_offset = program + .write( + &mut debug_line, + encoding, + &debug_line_str_offsets, + &debug_str_offsets, + ) + .unwrap(); + + let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian); + let read_program = read_debug_line + .program( + debug_line_offset, + address_size, + // Testing missing comp_dir/comp_name. + None, + None, + ) + .unwrap(); + + let dwarf = read::Dwarf::default(); + let mut convert_line_strings = LineStringTable::default(); + let mut convert_strings = StringTable::default(); + let convert_address = &|address| Some(Address::Constant(address)); + LineProgram::from( + read_program, + &dwarf, + &mut convert_line_strings, + &mut convert_strings, + convert_address, + ) + .unwrap(); + } + } + } + } } diff --git a/src/write/mod.rs b/src/write/mod.rs index addee46b1..5716a1e72 100644 --- a/src/write/mod.rs +++ b/src/write/mod.rs @@ -300,10 +300,6 @@ mod convert { InvalidDebugInfoOffset, /// An address could not be converted. InvalidAddress, - /// The line number program is missing the compilation directory. - MissingCompilationDirectory, - /// The line number program is missing the compilation file. - MissingCompilationFile, /// Writing this line number instruction is not implemented yet. UnsupportedLineInstruction, /// Writing this form of line string is not implemented yet. @@ -341,14 +337,6 @@ mod convert { "A `.debug_info` reference does not refer to a valid entry." ), InvalidAddress => write!(f, "An address could not be converted."), - MissingCompilationDirectory => write!( - f, - "The line number program is missing the compilation directory." - ), - MissingCompilationFile => write!( - f, - "The line number program is missing the compilation file." - ), UnsupportedLineInstruction => write!( f, "Writing this line number instruction is not implemented yet."