#![allow(clippy::uninlined_format_args)]
#![allow(unused_variables)]
#![allow(clippy::useless_vec)]
use pretty_assertions::assert_eq;
use rstest::*;
use threatflux_binary_analysis::types::*;
use threatflux_binary_analysis::BinaryAnalyzer;
mod common;
use common::fixtures::*;
#[test]
fn test_elf_dwarf_detection() {
let data = create_elf_with_dwarf_debug();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let dwarf_sections: Vec<_> = sections
.iter()
.filter(|s| s.name.starts_with(".debug_"))
.collect();
if !dwarf_sections.is_empty() {
for dwarf_section in dwarf_sections {
assert_eq!(dwarf_section.section_type, SectionType::Debug);
assert!(dwarf_section.size > 0, "DWARF section should have content");
match dwarf_section.name.as_str() {
".debug_info" => {
assert!(dwarf_section.size > 0, "debug_info should contain DIEs");
}
".debug_line" => {
assert!(
dwarf_section.size > 0,
"debug_line should contain line number info"
);
}
".debug_abbrev" => {
assert!(
dwarf_section.size > 0,
"debug_abbrev should contain abbreviations"
);
}
".debug_str" => {
assert!(
dwarf_section.size > 0,
"debug_str should contain string table"
);
}
_ => {}
}
}
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(!compiler_info.is_empty());
}
}
}
#[rstest]
#[case(".debug_info", SectionType::Debug, "Debug information entries")]
#[case(".debug_line", SectionType::Debug, "Line number information")]
#[case(".debug_abbrev", SectionType::Debug, "Abbreviation tables")]
#[case(".debug_str", SectionType::Debug, "String table")]
#[case(".debug_aranges", SectionType::Debug, "Address range tables")]
#[case(".debug_pubnames", SectionType::Debug, "Public names")]
#[case(".debug_pubtypes", SectionType::Debug, "Public types")]
#[case(".debug_frame", SectionType::Debug, "Call frame information")]
#[case(".debug_loc", SectionType::Debug, "Location lists")]
#[case(".debug_ranges", SectionType::Debug, "Range lists")]
#[case(".debug_macinfo", SectionType::Debug, "Macro information")]
#[case(".debug_macro", SectionType::Debug, "Macro information (DWARF 5)")]
fn test_dwarf_section_types(
#[case] section_name: &str,
#[case] expected_type: SectionType,
#[case] description: &str,
) {
let data = create_elf_with_specific_dwarf_section(section_name);
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let debug_section = sections.iter().find(|s| s.name == section_name);
if let Some(section) = debug_section {
assert_eq!(
section.section_type, expected_type,
"Section type should match for: {}",
description
);
assert!(
section.size > 0,
"Section should have content for: {}",
description
);
assert!(
!section.permissions.execute,
"Debug sections should not be executable"
);
}
}
#[rstest]
#[case(2, "DWARF 2")]
#[case(3, "DWARF 3")]
#[case(4, "DWARF 4")]
#[case(5, "DWARF 5")]
fn test_dwarf_version_detection(#[case] version: u16, #[case] description: &str) {
let data = create_elf_with_dwarf_version(version);
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let debug_info = sections.iter().find(|s| s.name == ".debug_info");
if let Some(debug_section) = debug_info {
assert!(
debug_section.size > 0,
"Should have debug info for: {}",
description
);
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
}
}
}
#[test]
fn test_pe_pdb_detection() {
let data = create_pe_with_pdb_reference();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("PDB") || compiler_info.contains("debug"),
"Should indicate PDB debug info presence"
);
}
let security = &metadata.security_features;
}
#[test]
fn test_pe_codeview_detection() {
let data = create_pe_with_codeview_debug();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(
compiler_info.contains("CodeView")
|| compiler_info.contains("CV")
|| compiler_info.contains("debug"),
"Should detect CodeView debug information"
);
}
}
#[test]
fn test_pe_debug_directory_parsing() {
let data = create_pe_with_comprehensive_debug_directory();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
assert!(!compiler_info.is_empty());
let debug_types = vec!["PDB", "CodeView", "MISC", "FIXUP"];
let has_debug_type = debug_types.iter().any(|&dt| compiler_info.contains(dt));
if has_debug_type {
}
}
}
#[test]
fn test_macho_dsym_detection() {
let data = create_macho_with_dsym_reference();
let result = BinaryAnalyzer::new().analyze(&data);
match result {
Ok(parsed) => {
let metadata = &parsed.metadata;
}
Err(_) => {
}
}
}
#[test]
fn test_macho_dwarf_segment() {
let data = create_macho_with_dwarf_segment();
let result = BinaryAnalyzer::new().analyze(&data);
match result {
Ok(parsed) => {
let sections = &parsed.sections;
let dwarf_sections: Vec<_> = sections
.iter()
.filter(|s| s.name.contains("__DWARF") || s.name.contains("__debug"))
.collect();
if !dwarf_sections.is_empty() {
for dwarf_section in dwarf_sections {
assert_eq!(dwarf_section.section_type, SectionType::Debug);
assert!(dwarf_section.size > 0);
assert!(!dwarf_section.permissions.execute);
}
}
}
Err(_) => {
}
}
}
#[test]
fn test_stripped_binary_detection() {
let test_cases = vec![
("Fully stripped ELF", create_fully_stripped_elf()),
("Partially stripped ELF", create_partially_stripped_elf()),
("Debug stripped PE", create_debug_stripped_pe()),
("Symbol stripped Mach-O", create_symbol_stripped_macho()),
];
for (description, data) in test_cases {
let format = threatflux_binary_analysis::formats::detect_format(&data).unwrap();
let result = match format {
BinaryFormat::Elf => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::Pe => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::MachO => BinaryAnalyzer::new().analyze(&data),
_ => continue,
};
if let Ok(parsed) = result {
let symbols = &parsed.symbols;
let sections = &parsed.sections;
if description.contains("Fully stripped") {
assert!(
symbols.len() < 10,
"Fully stripped should have minimal symbols for: {}",
description
);
}
let debug_sections: Vec<_> = sections
.iter()
.filter(|s| s.section_type == SectionType::Debug)
.collect();
if description.contains("Debug stripped") {
assert!(
debug_sections.is_empty(),
"Debug stripped should have no debug sections for: {}",
description
);
}
}
}
}
#[test]
fn test_debug_language_detection() {
let test_cases = vec![
("C debug info", create_elf_with_c_debug_info(), "C"),
("C++ debug info", create_elf_with_cpp_debug_info(), "C++"),
("Rust debug info", create_elf_with_rust_debug_info(), "Rust"),
("Go debug info", create_elf_with_go_debug_info(), "Go"),
(
"Fortran debug info",
create_elf_with_fortran_debug_info(),
"Fortran",
),
];
for (description, data, expected_language) in test_cases {
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let metadata = &result.metadata;
if let Some(ref compiler_info) = metadata.compiler_info {
if compiler_info
.to_lowercase()
.contains(&expected_language.to_lowercase())
{
} else {
assert!(
!compiler_info.is_empty(),
"Should have some compiler info for: {}",
description
);
}
}
}
}
#[test]
fn test_debug_inlined_functions() {
let data = create_elf_with_inlined_debug_info();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let symbols = &result.symbols;
let function_symbols: Vec<_> = symbols
.iter()
.filter(|s| s.symbol_type == SymbolType::Function)
.collect();
if !function_symbols.is_empty() {
for function in function_symbols {
assert!(!function.name.is_empty());
assert!(function.size > 0 || function.address > 0);
}
}
}
#[test]
fn test_debug_line_numbers() {
let data = create_elf_with_line_number_debug();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let debug_line = sections.iter().find(|s| s.name == ".debug_line");
if let Some(line_section) = debug_line {
assert_eq!(line_section.section_type, SectionType::Debug);
assert!(
line_section.size > 0,
"Line number section should have content"
);
}
}
#[test]
fn test_debug_variable_info() {
let data = create_elf_with_variable_debug_info();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let symbols = &result.symbols;
let variable_symbols: Vec<_> = symbols
.iter()
.filter(|s| s.symbol_type == SymbolType::Object)
.collect();
if !variable_symbols.is_empty() {
for variable in variable_symbols {
assert!(!variable.name.is_empty());
if variable.size > 0 {
}
}
}
}
#[test]
fn test_debug_type_info() {
let data = create_elf_with_type_debug_info();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let type_sections: Vec<_> = sections
.iter()
.filter(|s| s.name == ".debug_info" || s.name == ".debug_types")
.collect();
if !type_sections.is_empty() {
for type_section in type_sections {
assert_eq!(type_section.section_type, SectionType::Debug);
assert!(type_section.size > 0);
}
}
}
#[test]
fn test_compressed_debug_info() {
let data = create_elf_with_compressed_debug();
let result = BinaryAnalyzer::new().analyze(&data).unwrap();
let sections = result.sections;
let compressed_debug: Vec<_> = sections
.iter()
.filter(|s| s.name.starts_with(".zdebug_"))
.collect();
if !compressed_debug.is_empty() {
for compressed_section in compressed_debug {
assert_eq!(compressed_section.section_type, SectionType::Debug);
assert!(compressed_section.size > 0);
}
}
}
#[cfg(feature = "elf")]
#[test]
fn test_debug_info_performance() {
let data = create_large_elf_with_debug_info(100 * 1024 * 1024);
let start = std::time::Instant::now();
let result = BinaryAnalyzer::new().analyze(&data);
let duration = start.elapsed();
assert!(
result.is_ok(),
"Should parse binary with large debug sections"
);
assert!(
duration.as_secs() < 60,
"Debug parsing should be reasonably fast"
);
if let Ok(parsed) = result {
let sections = &parsed.sections;
let debug_sections: Vec<_> = sections
.iter()
.filter(|s| s.section_type == SectionType::Debug)
.collect();
}
}
#[test]
fn test_debug_info_error_handling() {
let error_cases = vec![
("Corrupted DWARF", create_elf_with_corrupted_dwarf()),
("Truncated debug", create_pe_with_truncated_debug()),
(
"Invalid debug directory",
create_pe_with_invalid_debug_directory(),
),
(
"Missing debug sections",
create_macho_with_missing_debug_sections(),
),
];
for (description, data) in error_cases {
let format = threatflux_binary_analysis::formats::detect_format(&data);
if let Ok(format_type) = format {
let result = match format_type {
BinaryFormat::Elf => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::Pe => BinaryAnalyzer::new().analyze(&data),
BinaryFormat::MachO => BinaryAnalyzer::new().analyze(&data),
_ => continue,
};
match result {
Ok(parsed) => {
assert_eq!(
parsed.format, format_type,
"Should maintain basic functionality for: {}",
description
);
}
Err(_) => {
}
}
}
}
}
fn create_elf_with_dwarf_debug() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(131072, 0);
let debug_info_offset = 65536;
data[debug_info_offset..debug_info_offset + 4].copy_from_slice(&[0x04, 0x00, 0x00, 0x00]);
data
}
fn create_elf_with_specific_dwarf_section(section_name: &str) -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(32768, 0);
match section_name {
".debug_info" => {
data.extend_from_slice(b"\x04\x00\x00\x00\x00\x00\x08\x01"); }
".debug_line" => {
data.extend_from_slice(b"\x02\x00\x00\x00\x04\x01\x01\xfb"); }
".debug_str" => {
data.extend_from_slice(b"\x00main\x00printf\x00/usr/include/stdio.h\x00");
}
_ => {
data.extend_from_slice(b"\x00\x01\x02\x03");
}
}
data
}
fn create_elf_with_dwarf_version(version: u16) -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(16384, 0);
let debug_offset = 8192;
let version_bytes = version.to_le_bytes();
data[debug_offset] = version_bytes[0];
data[debug_offset + 1] = version_bytes[1];
data
}
fn create_pe_with_pdb_reference() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(65536, 0);
let pdb_name = b"test.pdb\0";
data.extend_from_slice(pdb_name);
data
}
fn create_pe_with_codeview_debug() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(32768, 0);
data.extend_from_slice(b"RSDS");
data
}
fn create_pe_with_comprehensive_debug_directory() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(98304, 0);
data
}
fn create_macho_with_dsym_reference() -> Vec<u8> {
let mut data = vec![0; 4096];
let header = [
0xfe, 0xed, 0xfa, 0xcf, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[..32].copy_from_slice(&header);
let text_segment = [
0x19, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[32..104].copy_from_slice(&text_segment);
let main_cmd = [
0x28, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[104..128].copy_from_slice(&main_cmd);
let uuid_cmd = [
0x1b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88,
];
data[128..152].copy_from_slice(&uuid_cmd);
data
}
fn create_macho_with_dwarf_segment() -> Vec<u8> {
let mut data = vec![0; 8192];
let header = [
0xfe, 0xed, 0xfa, 0xcf, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[..32].copy_from_slice(&header);
let text_segment = [
0x19, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[32..104].copy_from_slice(&text_segment);
let dwarf_segment = [
0x19, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x44, 0x57, 0x41, 0x52, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[104..176].copy_from_slice(&dwarf_segment);
let debug_section = [
0x5f, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x00, 0x00,
0x00, 0x5f, 0x5f, 0x44, 0x57, 0x41, 0x52, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[176..256].copy_from_slice(&debug_section);
let main_cmd = [
0x28, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[256..280].copy_from_slice(&main_cmd);
if data.len() > 0x1000 {
let dwarf_header = [
0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, ];
data[0x1000..0x1000 + dwarf_header.len()].copy_from_slice(&dwarf_header);
}
data
}
fn create_fully_stripped_elf() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(4096, 0);
data
}
fn create_partially_stripped_elf() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(8192, 0);
data
}
fn create_debug_stripped_pe() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(16384, 0);
data
}
fn create_symbol_stripped_macho() -> Vec<u8> {
let mut data = create_realistic_macho_64();
data.resize(8192, 0);
data
}
fn create_elf_with_c_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(49152, 0);
let debug_offset = 16384;
data[debug_offset] = 0x01;
data
}
fn create_elf_with_cpp_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(65536, 0);
let debug_offset = 16384;
data[debug_offset] = 0x04;
data
}
fn create_elf_with_rust_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(81920, 0);
let debug_offset = 16384;
data[debug_offset] = 0x1c;
data
}
fn create_elf_with_go_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(73728, 0);
let debug_offset = 16384;
data[debug_offset] = 0x16;
data
}
fn create_elf_with_fortran_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(57344, 0);
let debug_offset = 16384;
data[debug_offset] = 0x08;
data
}
fn create_elf_with_inlined_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(114688, 0);
data
}
fn create_elf_with_line_number_debug() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(40960, 0);
data
}
fn create_elf_with_variable_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(61440, 0);
data
}
fn create_elf_with_type_debug_info() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(122880, 0);
data
}
fn create_elf_with_compressed_debug() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(77824, 0);
data
}
#[allow(dead_code)]
fn create_elf_with_large_debug_sections(size: usize) -> Vec<u8> {
let base_size = std::cmp::max(size, 16384); let mut data = vec![0; base_size];
let elf_header = [
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x02, 0x00, 0x40, 0x00, 0x06, 0x00, 0x05, 0x00, ];
data[..64].copy_from_slice(&elf_header);
let ph_load1 = [
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[64..120].copy_from_slice(&ph_load1);
let ph_load2 = [
0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[120..176].copy_from_slice(&ph_load2);
let sections_offset = 3072;
let null_section = [0u8; 64];
data[sections_offset..sections_offset + 64].copy_from_slice(&null_section);
let text_section = [
0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 64..sections_offset + 128].copy_from_slice(&text_section);
let data_section = [
0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 128..sections_offset + 192].copy_from_slice(&data_section);
let debug_size = std::cmp::max(size / 4, 4096); let debug_info_section = [
0x27,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x30,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (debug_size & 0xff) as u8,
((debug_size >> 8) & 0xff) as u8,
((debug_size >> 16) & 0xff) as u8,
((debug_size >> 24) & 0xff) as u8,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sections_offset + 192..sections_offset + 256].copy_from_slice(&debug_info_section);
let debug_line_size = std::cmp::max(size / 8, 2048); let debug_line_section = [
0x33,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, (debug_line_size & 0xff) as u8,
((debug_line_size >> 8) & 0xff) as u8,
((debug_line_size >> 16) & 0xff) as u8,
((debug_line_size >> 24) & 0xff) as u8,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00, 0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00, ];
data[sections_offset + 256..sections_offset + 320].copy_from_slice(&debug_line_section);
let shstrtab_section = [
0x3f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
data[sections_offset + 320..sections_offset + 384].copy_from_slice(&shstrtab_section);
let strtab_offset = 3200;
let string_table =
b"\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.debug_info\0.debug_line\0.shstrtab\0";
if data.len() > strtab_offset + string_table.len() {
data[strtab_offset..strtab_offset + string_table.len()].copy_from_slice(string_table);
}
if data.len() > 0x3000 + 11 {
let dwarf_header = [
0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, ];
data[0x3000..0x3000 + dwarf_header.len()].copy_from_slice(&dwarf_header);
}
if data.len() > 0x4000 + 16 {
let line_header = [
0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xfb, 0x0e, 0x0d, ];
data[0x4000..0x4000 + line_header.len()].copy_from_slice(&line_header);
}
data
}
fn create_elf_with_corrupted_dwarf() -> Vec<u8> {
let mut data = create_realistic_elf_64();
data.resize(32768, 0);
let debug_offset = 16384;
data[debug_offset..debug_offset + 8].copy_from_slice(&[0xff; 8]);
data
}
fn create_pe_with_truncated_debug() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(24576, 0);
data
}
fn create_pe_with_invalid_debug_directory() -> Vec<u8> {
let mut data = create_realistic_pe_64();
data.resize(20480, 0);
data
}
fn create_macho_with_missing_debug_sections() -> Vec<u8> {
let mut data = create_realistic_macho_64();
data.resize(6144, 0);
data
}