Skip to content

Commit

Permalink
crashreport prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
shevernitskiy committed May 12, 2023
1 parent bd75249 commit 78bde77
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
/src/macro/target
/src/macro/target
/.vscode/tasks.json
80 changes: 80 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ toml = "0.7.3"
lazy_static = "1.4.0"
exe = "0.5.6"
walkdir = "2.3.3"
backtrace = "0.3.67"
chrono = "0.4.24"
20 changes: 18 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use exe::{VecPE, PE};
use toml::{map::Map, Table, Value};
use walkdir::WalkDir;

use crate::utils;

static EXE_FILE: &str = "./Dwarf Fortress.exe";
static CONFIG_FILE: &str = "./dfint_data/dfint_config.toml";
static OFFSETS_DIR: &str = "./dfint_data/offsets/";
Expand Down Expand Up @@ -42,6 +44,7 @@ pub struct Settings {
}

pub struct Offset {
pub version: String,
pub checksum: u32,
pub string_copy: usize,
pub string_copy_n: usize,
Expand Down Expand Up @@ -83,7 +86,7 @@ impl Config {
settings: main_config.settings,
offset: offsets,
}),
Err(_) => Err("Config Error".into()), // rework to WinMessageBox
Err(_) => Err("Config Error".into()),
}
}

Expand Down Expand Up @@ -113,7 +116,19 @@ impl Config {
}
}

Err("Unable to find offsets file".into())
unsafe {
utils::message_box(
format!(
"unable to find offsets file for current version of DF\nchecksum: 0x{:x}",
target_timestamp
)
.as_str(),
"dfint hook error",
utils::MessageIconType::Error,
);
}
std::process::exit(2);
// Err("Unable to find offsets file".into())
}

fn parse_config(path: &Path) -> Result<MainConfig, Box<dyn Error>> {
Expand Down Expand Up @@ -143,6 +158,7 @@ impl Config {
let metadata = root["metadata"].as_table().unwrap();
let offsets = root["offsets"].as_table().unwrap();
Ok(Offset {
version: String::from(metadata["version"].as_str().unwrap_or("none")),
checksum: u32::try_from(metadata["checksum"].as_integer().unwrap())?,
string_copy: usize::try_from(offsets["string_copy"].as_integer().unwrap())?,
string_copy_n: usize::try_from(offsets["string_copy_n"].as_integer().unwrap())?,
Expand Down
126 changes: 126 additions & 0 deletions src/crash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use backtrace;
use chrono::prelude::*;
use log::error;
use winapi::um::errhandlingapi::SetUnhandledExceptionFilter;
use winapi::um::minwinbase as ErrorCode;
use winapi::um::winnt::{EXCEPTION_POINTERS, LONG};

use std::fs::File;
use std::io::Write;
use std::writeln;

use crate::config::CONFIG;
use crate::utils;

#[allow(dead_code)]
enum CrashResult {
ExecuteHandler = 1,
ContinueSearch = 0,
ContinueExecution = -1,
}

pub unsafe fn install() {
SetUnhandledExceptionFilter(Some(handler));
}

pub unsafe extern "system" fn handler(exception_info: *mut EXCEPTION_POINTERS) -> LONG {
let record = *(*exception_info).ExceptionRecord;

if record.ExceptionCode == ErrorCode::EXCEPTION_STACK_OVERFLOW {
utils::message_box(
"StackOverflow!",
"dfint hook error",
utils::MessageIconType::Error,
);
return CrashResult::ContinueExecution as LONG;
}

let stack = stacktrace(Some(record.ExceptionAddress as usize));
let dt: DateTime<Utc> = Utc::now();
let cr_filename = format!("cr_{}.txt", dt.format("%Y-%m-%d-%H-%M-%S"));
let mut file = File::create(format!(
"{}{}",
CONFIG.settings.crash_report_dir, cr_filename
))
.unwrap();
writeln!(&mut file, "Version: {}", CONFIG.offset.version).unwrap();
writeln!(&mut file, "Cheksum: {:x}", CONFIG.offset.checksum).unwrap();
writeln!(&mut file, "Error: {}", code_to_str(record.ExceptionCode)).unwrap();
writeln!(&mut file, "Address: {:?}", record.ExceptionAddress).unwrap();
writeln!(&mut file, "------------STACK------------").unwrap();
writeln!(&mut file, "{}", stack).unwrap();
writeln!(&mut file, "-----------------------------").unwrap();
error!(
"crash occured, error {}, address {:?}, crashlog {}",
code_to_str(record.ExceptionCode),
record.ExceptionAddress,
cr_filename
);

utils::message_box(
format!(
"Oops, it's a crash!\nError: {}\nAddress: {:?}\nCrashlog: {}\n",
code_to_str(record.ExceptionCode),
record.ExceptionAddress,
cr_filename
)
.as_str(),
"dfint hook error",
utils::MessageIconType::Error,
);

CrashResult::ExecuteHandler as LONG
}

fn stacktrace(target: Option<usize>) -> String {
let mut trace = Vec::<String>::new();
let mut i = 1;
backtrace::trace(|frame| {
let ip = frame.ip();
let symbol_address = frame.symbol_address();
let ma = frame.module_base_address().unwrap();
let offset = symbol_address as usize - ma as usize;

let mut name = String::from("");
backtrace::resolve_frame(frame, |symbol| {
name += format!("{}", symbol.name().unwrap()).as_str()
});
if name == "" {
name += "unknown";
}
let mut is_target = String::from("");
if target.unwrap() == ip as usize {
is_target += ">";
}
trace.push(format!("{}:{} {} + 0x{:X}", i, is_target, name, offset));
i += 1;
true
});
trace.join("\n")
}

fn code_to_str(code: u32) -> &'static str {
match code {
ErrorCode::EXCEPTION_ACCESS_VIOLATION => "EXCEPTION_ACCESS_VIOLATION",
ErrorCode::EXCEPTION_ARRAY_BOUNDS_EXCEEDED => "EXCEPTION_ARRAY_BOUNDS_EXCEEDED",
ErrorCode::EXCEPTION_BREAKPOINT => "EXCEPTION_BREAKPOINT",
ErrorCode::EXCEPTION_DATATYPE_MISALIGNMENT => "EXCEPTION_DATATYPE_MISALIGNMENT",
ErrorCode::EXCEPTION_FLT_DENORMAL_OPERAND => "EXCEPTION_FLT_DENORMAL_OPERAND",
ErrorCode::EXCEPTION_FLT_DIVIDE_BY_ZERO => "EXCEPTION_FLT_DIVIDE_BY_ZERO",
ErrorCode::EXCEPTION_FLT_INEXACT_RESULT => "EXCEPTION_FLT_INEXACT_RESULT",
ErrorCode::EXCEPTION_FLT_INVALID_OPERATION => "EXCEPTION_FLT_INVALID_OPERATION",
ErrorCode::EXCEPTION_FLT_OVERFLOW => "EXCEPTION_FLT_OVERFLOW",
ErrorCode::EXCEPTION_FLT_STACK_CHECK => "EXCEPTION_FLT_STACK_CHECK",
ErrorCode::EXCEPTION_FLT_UNDERFLOW => "EXCEPTION_FLT_UNDERFLOW",
ErrorCode::EXCEPTION_ILLEGAL_INSTRUCTION => "EXCEPTION_ILLEGAL_INSTRUCTION",
ErrorCode::EXCEPTION_IN_PAGE_ERROR => "EXCEPTION_IN_PAGE_ERROR",
ErrorCode::EXCEPTION_INT_DIVIDE_BY_ZERO => "EXCEPTION_INT_DIVIDE_BY_ZERO",
ErrorCode::EXCEPTION_INT_OVERFLOW => "EXCEPTION_INT_OVERFLOW",
ErrorCode::EXCEPTION_INVALID_DISPOSITION => "EXCEPTION_INVALID_DISPOSITION",
ErrorCode::EXCEPTION_NONCONTINUABLE_EXCEPTION => "EXCEPTION_NONCONTINUABLE_EXCEPTION",
ErrorCode::EXCEPTION_PRIV_INSTRUCTION => "EXCEPTION_PRIV_INSTRUCTION",
ErrorCode::EXCEPTION_SINGLE_STEP => "EXCEPTION_SINGLE_STEP",
ErrorCode::EXCEPTION_STACK_OVERFLOW => "EXCEPTION_STACK_OVERFLOW",
_ => "Unrecognized Exception",
}
}
Loading

0 comments on commit 78bde77

Please sign in to comment.