draugr.git


draugr

~ single ELF file analysis tool
git clone https://github.com/djnnvx/draugr.git
log | files | refs | archive | README

commit db3aa4ab468d83c316cb60559baffaca0ef23607
parent 22626b6176097330ec27f9458037d7b5bef2ffd9
Author: djnn <[email protected]>
Date: Sat, 5 Sep 2026 06:43:59 +0200

cleaning up comments

Diffstat:
Manalysis/analysis_test.odin | 35-----------------------------------
Manalysis/disasm.odin | 4+---
Manalysis/entropy.odin | 12------------
Manalysis/hexdump.odin | 10+---------
Manalysis/mapper.odin | 9---------
Manalysis/output.odin | 1-
Melf/elf.odin | 20+-------------------
Melf/elf_test.odin | 34+---------------------------------
Melf/loader.odin | 4+---
Melf/printer.odin | 4+---
Mmain.odin | 2--

11 files changed, 6 insertions(+), 129 deletions(-)

diff --git a/analysis/analysis_test.odin b/analysis/analysis_test.odin
@@ -1,4 +1,3 @@
-// analysis/analysis_test.odin - Unit tests for analysis functions
 package analysis
 
 import "core:fmt"
@@ -8,9 +7,7 @@ import "core:testing"
 
 import "../elf"
 
-//------------------------------------------------------------------------------
 // Layout constants - built by doubling so the widths are provable, not counted
-//------------------------------------------------------------------------------
 
 SP1  :: " "
 SP2  :: SP1 + SP1
@@ -54,10 +51,6 @@ HASH50 :: HASH25 + HASH25
 
 TOLERANCE :: 1e-9
 
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
 tmp_path :: proc(name: string) -> string {
 	dir, err := os.temp_directory(context.allocator)
 	if err != nil {
@@ -94,10 +87,6 @@ new_info :: proc() -> elf.ELF_Info {
 // offset 1 -> ".text", offset 7 -> ".data"
 SHSTRTAB := [?]u8{0, '.', 't', 'e', 'x', 't', 0, '.', 'd', 'a', 't', 'a', 0}
 
-//------------------------------------------------------------------------------
-// Tests - open_out / close_out
-//------------------------------------------------------------------------------
-
 @(test)
 test_open_out_empty_path_returns_stdout :: proc(t: ^testing.T) {
 	f, err := open_out("")
@@ -149,10 +138,6 @@ test_open_out_creates_file_and_close_out_persists_it :: proc(t: ^testing.T) {
 	testing.expect_value(t, got, "draugr")
 }
 
-//------------------------------------------------------------------------------
-// Tests - hexdump
-//------------------------------------------------------------------------------
-
 @(test)
 test_hexdump_empty_data :: proc(t: ^testing.T) {
 	path := tmp_path("hexdump_empty")
@@ -271,10 +256,6 @@ test_hexdump_printable_boundaries_are_inclusive :: proc(t: ^testing.T) {
 	testing.expect_value(t, got, "00000000  1f 20 7e 7f" + SP38 + "|. ~." + SP12 + "|\n")
 }
 
-//------------------------------------------------------------------------------
-// Tests - calculate_entropy
-//------------------------------------------------------------------------------
-
 @(test)
 test_calculate_entropy_empty_is_zero :: proc(t: ^testing.T) {
 	expect_near(t, calculate_entropy([]u8{}), 0.0)
@@ -319,10 +300,6 @@ test_calculate_entropy_lopsided_is_between_zero_and_one :: proc(t: ^testing.T) {
 	expect_near(t, entropy, 0.543564443)
 }
 
-//------------------------------------------------------------------------------
-// Tests - entropy_output
-//------------------------------------------------------------------------------
-
 ENTROPY_HEAD :: "Entropy Analysis (block size: 256 bytes)\n" +
                 "Offset" + SP7 + "Size" + SP3 + "Entropy\n" +
                 DASH40 + "\n"
@@ -456,10 +433,6 @@ test_entropy_output_reports_open_failure :: proc(t: ^testing.T) {
 	testing.expect(t, err != "", "unwritable out_path must surface an error")
 }
 
-//------------------------------------------------------------------------------
-// Tests - disasm_output
-//------------------------------------------------------------------------------
-
 DISASM_HEAD :: "Disassembly Analysis\n" +
                "====================\n\n" +
                "Executable Sections:\n" +
@@ -620,10 +593,6 @@ test_disasm_output_skips_preview_for_section_beyond_eof :: proc(t: ^testing.T) {
 		"out-of-file section must not print a preview")
 }
 
-//------------------------------------------------------------------------------
-// Tests - map_output
-//------------------------------------------------------------------------------
-
 MAP_HEAD :: "ELF Memory Map\n" +
             "==============\n\n" +
             "File Layout:\n" +
@@ -835,10 +804,6 @@ test_map_output_reports_open_failure :: proc(t: ^testing.T) {
 	testing.expect(t, err != "", "unwritable out_path must surface an error")
 }
 
-//------------------------------------------------------------------------------
-// Tests - remap_output
-//------------------------------------------------------------------------------
-
 @(test)
 test_remap_output_stub_reaches_out_file :: proc(t: ^testing.T) {
 	path := tmp_path("remap_stub")
diff --git a/analysis/disasm.odin b/analysis/disasm.odin
@@ -1,4 +1,3 @@
-// analysis/disasm.odin - Disassembly (stub/simple)
 package analysis
 
 import "core:fmt"
@@ -55,4 +54,4 @@ disasm_output :: proc(data: []u8, info: ^elf.ELF_Info, out_path: string) -> stri
 	fmt.fprintf(f, "Consider integrating zydis or capstone for x86/x64\n")
 
 	return ""
-}
-\ No newline at end of file
+}
diff --git a/analysis/entropy.odin b/analysis/entropy.odin
@@ -1,27 +1,19 @@
-// analysis/entropy.odin - Shannon entropy analysis
 package analysis
 
 import "core:fmt"
 import "core:math"
 import "core:os"
 
-//------------------------------------------------------------------------------
-// Public API
-//------------------------------------------------------------------------------
-
-// calculate_entropy calculates Shannon entropy for data (0.0 to 8.0)
 calculate_entropy :: proc(data: []u8) -> f64 {
 	if len(data) == 0 {
 		return 0.0
 	}
 	
-	// Count byte frequencies
 	freq: [256]f64
 	for b in data {
 		freq[b] += 1.0
 	}
 	
-	// Calculate entropy
 	total := f64(len(data))
 	entropy := 0.0
 	for i := 0; i < len(freq); i += 1 {
@@ -35,8 +27,6 @@ calculate_entropy :: proc(data: []u8) -> f64 {
 	return entropy
 }
 
-// entropy_output prints entropy analysis for the entire file
-// Uses 256-byte blocks for granular analysis
 entropy_output :: proc(data: []u8, out_path: string) -> string {
 	f, err := open_out(out_path)
 	if err != "" {
@@ -62,11 +52,9 @@ entropy_output :: proc(data: []u8, out_path: string) -> string {
 		fmt.fprintf(f, "0x%08x   %-6s %.4f\n", i, fmt.tprintf("%d", len(block)), entropy)
 	}
 	
-	// Overall entropy
 	overall := calculate_entropy(data)
 	fmt.fprintf(f, "\nOverall entropy: %.4f bits/byte\n", overall)
 	
-	// Classification
 	if overall < 4.0 {
 		fmt.fprintf(f, "Classification: Low entropy (text/code)\n")
 	} else if overall < 7.0 {
diff --git a/analysis/hexdump.odin b/analysis/hexdump.odin
@@ -1,13 +1,8 @@
-// analysis/hexdump.odin - Hex dump functionality
 package analysis
 
 import "core:fmt"
 import "core:os"
 
-//------------------------------------------------------------------------------
-// Public API
-//------------------------------------------------------------------------------
-
 HexdumpConfig :: struct {
 	width       : int,
 	show_offset : bool,
@@ -22,7 +17,6 @@ default_config :: proc() -> HexdumpConfig {
 	}
 }
 
-// hexdump performs a hex dump of data to stdout or file
 // Returns empty string on success, error message on failure
 hexdump :: proc(data: []u8, offset: u64, out_path: string) -> string {
 	cfg := default_config()
@@ -33,7 +27,6 @@ hexdump :: proc(data: []u8, offset: u64, out_path: string) -> string {
 	}
 	defer close_out(f, out_path)
 
-
 	for i := 0; i < len(data); i += cfg.width {
 		if cfg.show_offset {
 			fmt.fprintf(f, "%08x  ", offset + u64(i))
@@ -72,4 +65,4 @@ hexdump :: proc(data: []u8, offset: u64, out_path: string) -> string {
 	}
 	
 	return ""
-}
-\ No newline at end of file
+}
diff --git a/analysis/mapper.odin b/analysis/mapper.odin
@@ -1,4 +1,3 @@
-// analysis/mapper.odin - ELF memory mapping visualization
 package analysis
 
 import "core:fmt"
@@ -6,10 +5,6 @@ import "core:os"
 
 import "../elf"
 
-//------------------------------------------------------------------------------
-// Public API
-//------------------------------------------------------------------------------
-
 map_output :: proc(data: []u8, info: ^elf.ELF_Info, out_path: string) -> string {
 	f, err := open_out(out_path)
 	if err != "" {
@@ -90,10 +85,6 @@ remap_output :: proc(data: []u8, info: ^elf.ELF_Info, proto_path: string, out_pa
 	return ""
 }
 
-//------------------------------------------------------------------------------
-// Internal Helpers
-//------------------------------------------------------------------------------
-
 print_bar :: proc(f: ^os.File, offset: u64, size: u64, total: int) {
 	if total <= 0 {
 		return
diff --git a/analysis/output.odin b/analysis/output.odin
@@ -1,4 +1,3 @@
-// analysis/output.odin - stdout-or-file output handles
 package analysis
 
 import "core:fmt"
diff --git a/elf/elf.odin b/elf/elf.odin
@@ -1,13 +1,8 @@
-// elf/elf.odin - Core ELF Structures
 package elf
 
 import "core:encoding/endian"
 import "core:fmt"
 
-//------------------------------------------------------------------------------
-// Public API - ELF Magic and Constants
-//------------------------------------------------------------------------------
-
 ELF_MAGIC :: [4]u8{0x7f, 'E', 'L', 'F'}
 
 ELF_CLASS_32 :: 1
@@ -113,10 +108,6 @@ STT_FUNC    :: 2
 STT_SECTION :: 3
 STT_FILE    :: 4
 
-//------------------------------------------------------------------------------
-// Public API - ELF Structures
-//------------------------------------------------------------------------------
-
 ELF_Header :: struct {
 	class        : u8,
 	data         : u8,
@@ -182,10 +173,6 @@ ELF_Info :: struct {
 	dynstr        : []u8,
 }
 
-//------------------------------------------------------------------------------
-// Public API - Helper Functions
-//------------------------------------------------------------------------------
-
 // Overflow-safe: no addition that can wrap.
 in_bounds :: proc(data: []u8, offset: u64, size: u64) -> bool {
 	return offset <= u64(len(data)) && size <= u64(len(data)) - offset
@@ -216,10 +203,6 @@ read_u64 :: proc(data: []u8, offset: int, order: Byte_Order) -> u64 {
 	return v
 }
 
-//------------------------------------------------------------------------------
-// Public API - Parsing Functions
-//------------------------------------------------------------------------------
-
 probe :: proc(data: []u8) -> bool {
 	if len(data) < 16 { return false }
 	if data[0] != ELF_MAGIC[0] { return false }
@@ -279,4 +262,4 @@ parse_header :: proc(data: []u8) -> (ELF_Header, string) {
 	}
 
 	return header, ""
-}
-\ No newline at end of file
+}
diff --git a/elf/elf_test.odin b/elf/elf_test.odin
@@ -1,4 +1,3 @@
-// elf/elf_test.odin - Unit tests for ELF parsing
 package elf
 
 import "core:mem"
@@ -302,10 +301,6 @@ test_load_elf32_basic :: proc(t: ^testing.T) {
 	testing.expect(t, info.is_64bit == false, "should be 32-bit")
 }
 
-//------------------------------------------------------------------------------
-// In-memory ELF image builder, parameterised by class and endianness
-//------------------------------------------------------------------------------
-
 TEXT_BLOB     :: "\x55\x89\xe5\x83\xec\x08\xc9\xc3"
 INTERP_BLOB   :: "/lib/ld-linux.so.2\x00"
 SHSTRTAB_BLOB :: "\x00.text\x00.interp\x00.symtab\x00.strtab\x00.dynsym\x00.dynstr\x00.shstrtab\x00"
@@ -628,10 +623,6 @@ build_elf :: proc(class: u8, endian: u8) -> Fixture {
 	return f
 }
 
-//------------------------------------------------------------------------------
-// Full image round-trip across every class/endianness combination
-//------------------------------------------------------------------------------
-
 SECTION_NAMES :: [8]string{"", ".text", ".interp", ".symtab", ".strtab", ".dynsym", ".dynstr", ".shstrtab"}
 SYMBOL_NAMES  :: [4]string{"", "counter", "main", "printf"}
 DYNSYM_NAMES  :: [2]string{"", "puts"}
@@ -736,9 +727,7 @@ test_full_image_elf64_be :: proc(t: ^testing.T) {
 	check_full_image(t, ELF_CLASS_64, ELF_DATA_MSB)
 }
 
-//------------------------------------------------------------------------------
 // Regression: ELF32 header fields must use the 32-bit layout
-//------------------------------------------------------------------------------
 
 build_elf32_header_only :: proc(little: bool, entry: u32, phoff: u32, shoff: u32, flags: u32) -> []u8 {
 	data := make([]u8, 52)
@@ -838,10 +827,6 @@ test_regression_elf32_program_headers_parse :: proc(t: ^testing.T) {
 	}
 }
 
-//------------------------------------------------------------------------------
-// Bounds helpers
-//------------------------------------------------------------------------------
-
 @(test)
 test_in_bounds :: proc(t: ^testing.T) {
 	data := make([]u8, 16)
@@ -930,10 +915,6 @@ test_getters_on_empty_slice :: proc(t: ^testing.T) {
 	testing.expect_value(t, read_u64(empty, 0, .Big), u64(0))
 }
 
-//------------------------------------------------------------------------------
-// is_dynamic detection
-//------------------------------------------------------------------------------
-
 build_elf64_with_segments :: proc(segs: []Program_Header) -> []u8 {
 	ehsize := 64
 	total := ehsize + len(segs) * 56
@@ -1013,10 +994,6 @@ test_is_dynamic_false_for_static :: proc(t: ^testing.T) {
 	testing.expect_value(t, info.interp_offset, u64(0))
 }
 
-//------------------------------------------------------------------------------
-// Allocation hygiene
-//------------------------------------------------------------------------------
-
 @(test)
 test_load_destroy_leaks_nothing :: proc(t: ^testing.T) {
 	track: mem.Tracking_Allocator
@@ -1044,10 +1021,6 @@ test_load_destroy_leaks_nothing :: proc(t: ^testing.T) {
 	testing.expect_value(t, len(track.bad_free_array), 0)
 }
 
-//------------------------------------------------------------------------------
-// Malformed input robustness
-//------------------------------------------------------------------------------
-
 POISON :: [7]u64{
 	0xFF00000000000000,
 	0x8000000000000000,
@@ -1369,10 +1342,6 @@ test_get_symbol_name_bounds :: proc(t: ^testing.T) {
 	testing.expect_value(t, get_symbol_name(nil, 5), "")
 }
 
-//------------------------------------------------------------------------------
-// Printer
-//------------------------------------------------------------------------------
-
 @(test)
 test_printer_strings :: proc(t: ^testing.T) {
 	defer free_all(context.temp_allocator)
@@ -1428,4 +1397,4 @@ test_flags_to_str :: proc(t: ^testing.T) {
 	testing.expect_value(t, flags_to_str(PF_R | PF_W), "RW ")
 	testing.expect_value(t, flags_to_str(PF_R | PF_W | PF_X), "RWX")
 	testing.expect_value(t, flags_to_str(0xFFFFFFFFFFFFFFFF), "RWX")
-}
-\ No newline at end of file
+}
diff --git a/elf/loader.odin b/elf/loader.odin
@@ -1,4 +1,3 @@
-// elf/loader.odin - Full ELF parsing (segments, sections, symbols)
 package elf
 
 load :: proc(data: []u8) -> (ELF_Info, string) {
@@ -266,4 +265,4 @@ parse_symbols :: proc(data: []u8, info: ^ELF_Info) {
 			}
 		}
 	}
-}
-\ No newline at end of file
+}
diff --git a/elf/printer.odin b/elf/printer.odin
@@ -1,4 +1,3 @@
-// elf/printer.odin - ELF info printing
 package elf
 
 import "core:fmt"
@@ -238,4 +237,4 @@ segment_type_str :: proc(t: u32) -> string {
 flags_to_str :: proc(flags: u64) -> string {
 	@static table := [8]string{"   ", "  X", " W ", " WX", "R  ", "R X", "RW ", "RWX"}
 	return table[flags & 7]
-}
-\ No newline at end of file
+}
diff --git a/main.odin b/main.odin
@@ -1,4 +1,3 @@
-// main.odin - draugr: ELF mapping and analysis tool
 package main
 
 import "core:flags"
@@ -136,7 +135,6 @@ section_header :: proc(title: string, out_path: string) {
 	}
 }
 
-
 print_symbols :: proc(info: ^elf.ELF_Info) {
 	print_symbol_table(info.symbols[:])
 	print_symbol_table(info.dyn_symbols[:])