From 72e7850152a74b33b6bbfb1889599603fc52ebbb Mon Sep 17 00:00:00 2001
From: Corwin
Date: Wed, 17 Apr 2024 19:44:31 +0100
Subject: [PATCH 01/26] backtrace page with more detail
---
website/agb/src/app/crash/backtrace.tsx | 79 ++++++++++++++++++++-----
website/agb/src/app/crash/page.tsx | 16 +----
2 files changed, 68 insertions(+), 27 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 30570fca..28185f76 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -1,33 +1,84 @@
"use client";
-import { FC } from "react";
+import { ContentBlock } from "../contentBlock";
import { useClientValue } from "../useClientValue.hook";
import { styled } from "styled-components";
-const BacktraceWrapper = styled.section`
- display: flex;
- gap: 10px;
- justify-content: center;
-`;
-
-function getBacktrace() {
- return window.location.hash.slice(1);
+export function BacktracePage() {
+ return (
+
+ agbrs crash backtrace viewer
+
+ You likely got here from the link / QR code that was displayed when a
+ game you were playing crashed. This is the default crash page for games
+ made using the agb library.
+
+
+ The creator of the game is very likely interested in the code
+ below along with a description of what you were doing at the
+ time.{" "}
+ Send these to the creator of the game you are playing.
+
+
+
+
+ The owners of this website are not necessarily the creators of the
+ game you are playing.
+
+
+ For game developers
+ This page will eventually let you view backtraces in the browser.
+
+ For now you can copy the backtrace code here and use it with{" "}
+ agb-addr2line
.
+
+ If you don't want players to be sent to this page, you can:
+
+ Configure the backtrace page to point to your own site
+ Configure the backtrace page to not point to a site at all
+ Not use the backtrace feature
+
+
+ );
}
-export function BacktraceDisplay() {
+function BacktraceDisplay() {
const backtrace = useClientValue(getBacktrace) ?? "";
return (
- Backtrace:
-
- {backtrace}
+ {
navigator.clipboard.writeText(backtrace);
}}
>
Copy
-
+
);
}
+
+const BacktraceCodeBlock = styled.code`
+ font-size: 3rem;
+ background-color: #dddddd;
+ padding: 0px 40px;
+ overflow-x: scroll;
+`;
+
+const BacktraceWrapper = styled.section`
+ display: flex;
+ gap: 10px;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+`;
+
+const BacktraceCopyButton = styled.button`
+ padding: 10px;
+ overflow-x: scroll;
+`;
+
+function getBacktrace() {
+ return window.location.hash.slice(1);
+}
diff --git a/website/agb/src/app/crash/page.tsx b/website/agb/src/app/crash/page.tsx
index 3b97c492..05283ac3 100644
--- a/website/agb/src/app/crash/page.tsx
+++ b/website/agb/src/app/crash/page.tsx
@@ -1,21 +1,11 @@
import { Metadata } from "next";
-import { BacktraceDisplay } from "./backtrace";
+import { BacktracePage } from "./backtrace";
import { ContentBlock } from "../contentBlock";
export const metadata: Metadata = {
title: "agbrs crash backtrace",
};
-export default function Crash() {
- return (
-
- agbrs crash backtrace viewer
- This page will eventually let you view backtraces in the browser.
-
- For now you can copy the backtrace code here and use it with{" "}
- agb-addr2line
-
-
-
- );
+export default function Backtrace() {
+ return ;
}
From f269e6364a9fcf18d6f655616f0a97a86806f862 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 00:43:47 +0100
Subject: [PATCH 02/26] thiserror + expose some as lib
---
agb-debug/Cargo.toml | 2 +-
agb-debug/src/gwilym_encoding.rs | 30 +++++++----
agb-debug/src/lib.rs | 93 ++++++++++++++++++++++++++++++++
agb-debug/src/load_dwarf.rs | 38 ++++++++-----
agb-debug/src/main.rs | 32 +++--------
5 files changed, 148 insertions(+), 47 deletions(-)
create mode 100644 agb-debug/src/lib.rs
diff --git a/agb-debug/Cargo.toml b/agb-debug/Cargo.toml
index 4c3f41f9..12977469 100644
--- a/agb-debug/Cargo.toml
+++ b/agb-debug/Cargo.toml
@@ -8,7 +8,7 @@ description = "CLI utility to convert agb stack trace dumps into human readable
repository = "https://github.com/agbrs/agb"
[dependencies]
-anyhow = "1"
+thiserror = "1"
clap = { version = "4", features = ["derive"] }
addr2line = { version = "0.22", default-features = false, features = [
"rustc-demangle",
diff --git a/agb-debug/src/gwilym_encoding.rs b/agb-debug/src/gwilym_encoding.rs
index 1ce957f5..f192c28a 100644
--- a/agb-debug/src/gwilym_encoding.rs
+++ b/agb-debug/src/gwilym_encoding.rs
@@ -1,8 +1,20 @@
use std::{slice::ChunksExact, sync::OnceLock};
+use thiserror::Error;
+
const ALPHABET: &[u8] = b"0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
-pub fn gwilym_decode(input: &str) -> anyhow::Result> {
+#[derive(Debug, Error)]
+pub enum GwilymDecodeError {
+ #[error("Does not contain version")]
+ NoVersion,
+ #[error("Only version 1 is supported")]
+ WrongVersion,
+ #[error("Input must be a multiple of 3 but have {0}")]
+ LengthWrong(usize),
+}
+
+pub fn gwilym_decode(input: &str) -> Result, GwilymDecodeError> {
GwilymDecodeIter::new(input)
}
@@ -11,21 +23,21 @@ pub struct GwilymDecodeIter<'a> {
}
impl<'a> GwilymDecodeIter<'a> {
- fn new(input: &'a str) -> anyhow::Result {
+ fn new(input: &'a str) -> Result {
let input = input
.strip_prefix("https://agbrs.dev/crash#")
.unwrap_or(input);
let Some((input, version)) = input.rsplit_once('v') else {
- anyhow::bail!("Does not contain version");
+ return Err(GwilymDecodeError::NoVersion);
};
if version != "1" {
- anyhow::bail!("Only version 1 is supported");
+ return Err(GwilymDecodeError::WrongVersion);
}
if input.len() % 3 != 0 {
- anyhow::bail!("Input string must have length a multiple of 3");
+ return Err(GwilymDecodeError::LengthWrong(input.len()));
}
Ok(Self {
@@ -75,11 +87,11 @@ fn get_value_for_char(input: u8) -> u32 {
#[cfg(test)]
mod test {
- use super::{gwilym_decode, ALPHABET};
+ use super::*;
use std::fmt::Write;
#[test]
- fn should_correctly_decode_16s() -> anyhow::Result<()> {
+ fn should_correctly_decode_16s() -> Result<(), GwilymDecodeError> {
assert_eq!(
&gwilym_decode("2QI65Q69306Kv1")?.collect::>(),
&[0x0800_16d3, 0x0800_315b, 0x0800_3243, 0x0800_0195]
@@ -112,7 +124,7 @@ mod test {
}
#[test]
- fn should_correctly_decode_16s_and_32s() -> anyhow::Result<()> {
+ fn should_correctly_decode_16s_and_32s() -> Result<(), Box> {
let trace: &[u32] = &[
0x0300_2990,
0x0800_3289,
@@ -143,7 +155,7 @@ mod test {
}
#[test]
- fn should_strip_the_agbrsdev_prefix() -> anyhow::Result<()> {
+ fn should_strip_the_agbrsdev_prefix() -> Result<(), Box> {
assert_eq!(
&gwilym_decode("https://agbrs.dev/crash#2QI65Q69306Kv1")?.collect::>(),
&[0x0800_16d3, 0x0800_315b, 0x0800_3243, 0x0800_0195]
diff --git a/agb-debug/src/lib.rs b/agb-debug/src/lib.rs
new file mode 100644
index 00000000..e353a0ca
--- /dev/null
+++ b/agb-debug/src/lib.rs
@@ -0,0 +1,93 @@
+mod gwilym_encoding;
+mod load_dwarf;
+
+use addr2line::gimli::{self, EndianReader};
+pub use gwilym_encoding::{gwilym_decode, GwilymDecodeError};
+pub use load_dwarf::{load_dwarf, GimliDwarf, LoadDwarfError};
+use thiserror::Error;
+
+pub use addr2line;
+
+pub struct AddressInfo {
+ pub location: Location,
+ pub is_interesting: bool,
+ pub is_inline: bool,
+ pub function: String,
+}
+
+#[derive(Debug, Error)]
+pub enum AddressInfoError {
+ #[error(transparent)]
+ Gimli(#[from] gimli::Error),
+}
+
+pub struct Location {
+ pub filename: String,
+ pub line: u32,
+ pub col: u32,
+}
+
+pub type Addr2LineContext = addr2line::Context>;
+
+impl Default for Location {
+ fn default() -> Self {
+ Self {
+ filename: "??".to_string(),
+ line: 0,
+ col: 0,
+ }
+ }
+}
+
+pub fn address_info(
+ ctx: &Addr2LineContext,
+ address: u64,
+) -> Result, AddressInfoError> {
+ let mut frames = ctx.find_frames(address).skip_all_loads()?;
+
+ let mut is_first = true;
+
+ let mut infos = Vec::new();
+
+ while let Some(frame) = frames.next()? {
+ let function_name = if let Some(ref func) = frame.function {
+ func.demangle()?.into_owned()
+ } else {
+ "unknown function".to_string()
+ };
+
+ let location = frame
+ .location
+ .as_ref()
+ .map(|location| Location {
+ filename: location.file.unwrap_or("??").to_owned(),
+ line: location.line.unwrap_or(0),
+ col: location.column.unwrap_or(0),
+ })
+ .unwrap_or_default();
+
+ let is_interesting = is_interesting_function(&function_name, &location.filename);
+
+ infos.push(AddressInfo {
+ location,
+ is_interesting,
+ is_inline: is_first,
+ function: function_name,
+ });
+ is_first = false;
+ }
+
+ Ok(infos)
+}
+
+fn is_interesting_function(function_name: &str, path: &str) -> bool {
+ if function_name == "rust_begin_unwind" {
+ return false; // this is the unwind exception call
+ }
+
+ if path.ends_with("panicking.rs") {
+ return false; // probably part of rust's internal panic mechanisms
+ }
+
+ true
+}
diff --git a/agb-debug/src/load_dwarf.rs b/agb-debug/src/load_dwarf.rs
index 394e5e57..d4b13ab1 100644
--- a/agb-debug/src/load_dwarf.rs
+++ b/agb-debug/src/load_dwarf.rs
@@ -4,38 +4,52 @@ use addr2line::{
gimli,
object::{self, Object},
};
-use anyhow::bail;
+use thiserror::Error;
-pub fn load_dwarf(
- file_content: &[u8],
-) -> anyhow::Result>> {
+#[derive(Debug, Error)]
+pub enum LoadDwarfError {
+ #[error("Gba file is empty")]
+ GbaFileEmpty,
+ #[error("Failed to load debug information from ROM file, it might not have been included?")]
+ NoDebugInformation,
+ #[error("Failed to load debug information: {0}")]
+ DeserializationError(#[from] rmp_serde::decode::Error),
+ #[error(transparent)]
+ GimliError(#[from] gimli::Error),
+}
+
+pub type GimliDwarf = gimli::Dwarf>;
+
+pub fn load_dwarf(file_content: &[u8]) -> Result {
if let Ok(object) = object::File::parse(file_content) {
- return load_from_object(&object);
+ return Ok(load_from_object(&object)?);
}
// the file might have been padded, so ensure we skip any padding before continuing
let last_non_zero_byte = file_content
.iter()
.rposition(|&b| b != 0)
- .ok_or_else(|| anyhow::anyhow!("Gba file is empty"))?;
+ .ok_or_else(|| LoadDwarfError::GbaFileEmpty)?;
let file_content = &file_content[..last_non_zero_byte + 1];
let last_8_bytes = &file_content[file_content.len() - 8..];
- let len = u32::from_le_bytes(last_8_bytes[0..4].try_into()?) as usize;
+ let len = u32::from_le_bytes(
+ last_8_bytes[0..4]
+ .try_into()
+ .or(Err(LoadDwarfError::NoDebugInformation))?,
+ ) as usize;
let version = &last_8_bytes[4..];
if version != b"agb1" {
- bail!("Failed to load debug information from ROM file, it might not have been included?");
+ return Err(LoadDwarfError::NoDebugInformation);
}
let compressed_debug_data = &file_content[file_content.len() - len - 8..file_content.len() - 8];
let decompressing_reader =
lz4_flex::frame::FrameDecoder::new(Cursor::new(compressed_debug_data));
- let debug_info: HashMap> =
- rmp_serde::decode::from_read(decompressing_reader)
- .map_err(|e| anyhow::anyhow!("Failed to load debug information: {e}"))?;
+ let debug_info: HashMap> = rmp_serde::decode::from_read(decompressing_reader)?;
let dwarf = gimli::Dwarf::load(|id| {
let data = debug_info
@@ -54,7 +68,7 @@ pub fn load_dwarf(
fn load_from_object<'file>(
object: &object::File<'file, &'file [u8]>,
-) -> anyhow::Result>> {
+) -> Result {
let endian = if object.is_little_endian() {
gimli::RunTimeEndian::Little
} else {
diff --git a/agb-debug/src/main.rs b/agb-debug/src/main.rs
index efb5bd62..00611148 100644
--- a/agb-debug/src/main.rs
+++ b/agb-debug/src/main.rs
@@ -1,5 +1,6 @@
use std::{
borrow::Cow,
+ error::Error,
fs::{self, File},
io::Read,
path::PathBuf,
@@ -7,12 +8,9 @@ use std::{
};
use addr2line::gimli;
+use agb_debug::Location;
use clap::Parser;
use colored::Colorize;
-use load_dwarf::load_dwarf;
-
-mod gwilym_encoding;
-mod load_dwarf;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
@@ -24,23 +22,7 @@ struct Args {
dump: String,
}
-struct Location {
- filename: String,
- line: u32,
- col: u32,
-}
-
-impl Default for Location {
- fn default() -> Self {
- Self {
- filename: "??".to_string(),
- line: 0,
- col: 0,
- }
- }
-}
-
-fn main() -> anyhow::Result<()> {
+fn main() -> Result<(), Box> {
let cli = Args::parse();
let modification_time = fs::metadata(&cli.elf_path)?
@@ -48,11 +30,11 @@ fn main() -> anyhow::Result<()> {
.unwrap_or(SystemTime::UNIX_EPOCH);
let file = fs::read(&cli.elf_path)?;
- let dwarf = load_dwarf(&file)?;
+ let dwarf = agb_debug::load_dwarf(&file)?;
let ctx = addr2line::Context::from_dwarf(dwarf)?;
- for (i, address) in gwilym_encoding::gwilym_decode(&cli.dump)?.enumerate() {
+ for (i, address) in agb_debug::gwilym_decode(&cli.dump)?.enumerate() {
print_address(&ctx, i, address.into(), modification_time)?;
}
@@ -64,7 +46,7 @@ fn print_address(
index: usize,
address: u64,
elf_modification_time: SystemTime,
-) -> anyhow::Result<()> {
+) -> Result<(), Box> {
let mut frames = ctx.find_frames(address).skip_all_loads()?;
let mut is_first = true;
@@ -119,7 +101,7 @@ fn print_line_of_code(
frame: &addr2line::Frame<'_, impl gimli::Reader>,
location: Location,
elf_modification_time: SystemTime,
-) -> anyhow::Result<()> {
+) -> Result<(), Box> {
let Some(filename) = frame.location.as_ref().and_then(|location| location.file) else {
return Ok(());
};
From 1d9a7d51a3bfa53717b0e1146c7c1e2d2eda9288 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 00:44:13 +0100
Subject: [PATCH 03/26] expose as wasm
---
Cargo.toml | 1 +
agb-wasm/Cargo.toml | 29 +++++++++++++++++++++++++++
agb-wasm/src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+)
create mode 100644 agb-wasm/Cargo.toml
create mode 100644 agb-wasm/src/lib.rs
diff --git a/Cargo.toml b/Cargo.toml
index 9334e895..7c273d76 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,6 +26,7 @@ members = [
"emulator/mgba",
"emulator/mgba-sys",
"emulator/test-runner",
+ "agb-wasm",
]
exclude = [
diff --git a/agb-wasm/Cargo.toml b/agb-wasm/Cargo.toml
new file mode 100644
index 00000000..ee56b986
--- /dev/null
+++ b/agb-wasm/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "agb-wasm"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+
+[features]
+default = ["console_error_panic_hook"]
+
+[dependencies]
+wasm-bindgen = "0.2.84"
+agb-debug = { path="../agb-debug" }
+
+# The `console_error_panic_hook` crate provides better debugging of panics by
+# logging them with `console.error`. This is great for development, but requires
+# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
+# code size when deploying.
+console_error_panic_hook = { version = "0.1.7", optional = true }
+
+[dev-dependencies]
+wasm-bindgen-test = "0.3.34"
+
+[profile.release]
+# Tell `rustc` to optimize for small code size.
+opt-level = "s"
\ No newline at end of file
diff --git a/agb-wasm/src/lib.rs b/agb-wasm/src/lib.rs
new file mode 100644
index 00000000..c334fc95
--- /dev/null
+++ b/agb-wasm/src/lib.rs
@@ -0,0 +1,49 @@
+use agb_debug::{addr2line::Context, load_dwarf, Addr2LineContext};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub fn decode_backtrace(backtrace: &str) -> Result, JsError> {
+ Ok(agb_debug::gwilym_decode(backtrace)?.collect())
+}
+
+#[wasm_bindgen]
+pub struct DebugFile {
+ dwarf: Addr2LineContext,
+}
+
+#[wasm_bindgen(getter_with_clone)]
+pub struct AddressInfo {
+ pub filename: String,
+ pub function_name: String,
+ pub line_number: u32,
+ pub column: u32,
+ pub is_interesting: bool,
+ pub is_inline: bool,
+}
+
+#[wasm_bindgen]
+impl DebugFile {
+ #[wasm_bindgen(constructor)]
+ pub fn new(data: &[u8]) -> Result {
+ Ok(DebugFile {
+ dwarf: Context::from_dwarf(load_dwarf(data)?)?,
+ })
+ }
+
+ pub fn address_info(&self, address: u32) -> Result, JsError> {
+ let info = agb_debug::address_info(&self.dwarf, address.into())?;
+ let address_infos = info
+ .into_iter()
+ .map(|x| AddressInfo {
+ filename: x.location.filename,
+ line_number: x.location.line,
+ column: x.location.col,
+ is_interesting: x.is_interesting,
+ is_inline: x.is_inline,
+ function_name: x.function,
+ })
+ .collect();
+
+ Ok(address_infos)
+ }
+}
From 121ebe312cf81e45c42911f6fce1afd9c66c5666 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 00:50:13 +0100
Subject: [PATCH 04/26] add debug information to the crash page
---
justfile | 19 +++++-
website/agb/src/app/crash/backtrace.tsx | 86 +++++++++++++++++++++++++
website/agb/src/app/useAgbDebug.hook.ts | 35 ++++++++++
3 files changed, 138 insertions(+), 2 deletions(-)
create mode 100644 website/agb/src/app/useAgbDebug.hook.ts
diff --git a/justfile b/justfile
index a2b42bdf..eab6cfba 100644
--- a/justfile
+++ b/justfile
@@ -87,6 +87,15 @@ release +args: (_run-tool "release" args)
miri:
(cd agb-hashmap && cargo miri test)
+setup-cargo-wasm:
+ cargo install wasm-pack
+
+build-agb-wasm:
+ (cd agb-wasm && wasm-pack build --target web)
+ rm -rf website/agb/src/app/vendor/agb_wasm
+ mkdir website/agb/src/app/vendor
+ cp agb-wasm/pkg website/agb/src/app/vendor/agb_wasm -r
+
build-mgba-wasm:
rm -rf website/agb/src/app/mgba/vendor
mkdir website/agb/src/app/mgba/vendor
@@ -94,13 +103,19 @@ build-mgba-wasm:
build-combo-rom-site:
just _build-rom "examples/combo" "AGBGAMES"
-
-build-site-app: build-mgba-wasm build-combo-rom-site
mkdir -p website/agb/public
gzip -9 -c examples/target/examples/combo.gba > website/agb/public/combo.gba.gz
+
+
+setup-app-build: build-mgba-wasm build-combo-rom-site build-agb-wasm
(cd website/agb && npm install --no-save --prefer-offline --no-audit)
+
+build-site-app: setup-app-build
(cd website/agb && npm run build)
+serve-site-dev: setup-app-build
+ (cd website/agb && npm run dev)
+
build-site: build-site-app build-book
rm -rf website/build
cp website/agb/out website/build -r
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 28185f76..80430ec7 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -3,6 +3,9 @@
import { ContentBlock } from "../contentBlock";
import { useClientValue } from "../useClientValue.hook";
import { styled } from "styled-components";
+import { useEffect, useMemo, useState } from "react";
+import { useAgbDebug } from "../useAgbDebug.hook";
+import { AddressInfo } from "../vendor/agb_wasm/agb_wasm";
export function BacktracePage() {
return (
@@ -38,10 +41,93 @@ export function BacktracePage() {
Configure the backtrace page to not point to a site at all
Not use the backtrace feature
+
);
}
+function Backtrace() {
+ const backtrace = useClientValue(getBacktrace) ?? "";
+ const backtraceAddresses = useBacktraceData(backtrace);
+
+ const [files, setFile] = useState([]);
+ const backtraceLocations = useBacktraceLocations(
+ backtraceAddresses ?? [],
+ files ?? []
+ );
+
+ return (
+
+ Addresses in the backtrace
+ {
+ const files = evt.target.files;
+ const filesArr = (files && Array.from(files)) ?? [];
+ setFile(filesArr);
+ }}
+ />
+
+ {backtraceAddresses &&
+ backtraceAddresses.map((x, idx) => (
+
+ 0x{x.toString(16).padStart(8, "0")}
+
+
+ ))}
+
+
+ );
+}
+
+function BacktraceAddressInfo({ info }: { info: AddressInfo[] | undefined }) {
+ if (!info) return;
+
+ return (
+
+ {info.map((x, idx) => (
+
+ {x.is_inline && "(inlined into)"} {x.function_name}:{x.column}{" "}
+ {x.filename}:{x.line_number}
+
+ ))}
+
+ );
+}
+
+function useBacktraceLocations(addresses: number[], file: File[]) {
+ const debug = useAgbDebug();
+ const [debugInfo, setDebugInfo] = useState([]);
+
+ useEffect(() => {
+ const f = file[0];
+ if (!f) return;
+ if (!debug) return;
+ (async () => {
+ const buf = await f.arrayBuffer();
+ const view = new Uint8Array(buf);
+
+ const agbDebugFile = debug.debug_file(view);
+ const debugInfo = addresses.map((x) => agbDebugFile.address_info(x));
+ setDebugInfo(debugInfo);
+ })();
+ }, [addresses, debug, file]);
+
+ return debugInfo;
+}
+
+function useBacktraceData(trace?: string) {
+ const debug = useAgbDebug();
+
+ return useMemo(() => {
+ try {
+ if (!trace) return;
+ const addresses = debug?.decode_backtrace(trace);
+ return addresses && Array.from(addresses);
+ } catch {}
+ }, [debug, trace]);
+}
+
function BacktraceDisplay() {
const backtrace = useClientValue(getBacktrace) ?? "";
diff --git a/website/agb/src/app/useAgbDebug.hook.ts b/website/agb/src/app/useAgbDebug.hook.ts
new file mode 100644
index 00000000..6e6217e8
--- /dev/null
+++ b/website/agb/src/app/useAgbDebug.hook.ts
@@ -0,0 +1,35 @@
+import { useEffect, useState } from "react";
+import debugInit, {
+ decode_backtrace,
+ DebugFile,
+ InitOutput,
+} from "./vendor/agb_wasm/agb_wasm";
+
+let agbDebug: Promise | undefined;
+
+interface AgbDebug {
+ decode_backtrace: (backtrace: string) => Uint32Array;
+ debug_file: (file: Uint8Array) => DebugFile;
+}
+
+export function useAgbDebug() {
+ const [debug, setDebug] = useState();
+
+ useEffect(() => {
+ (async () => {
+ if (agbDebug === undefined) {
+ agbDebug = debugInit();
+ }
+
+ await agbDebug;
+ console.log("Loaded agb debug");
+
+ setDebug({
+ decode_backtrace,
+ debug_file: (file: Uint8Array) => new DebugFile(file),
+ });
+ })();
+ }, []);
+
+ return debug;
+}
From 1cdbf13814b83f64ad46df950ee970063952da9c Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 00:53:15 +0100
Subject: [PATCH 05/26] correct the text
---
website/agb/src/app/crash/backtrace.tsx | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 80430ec7..2d0d8d3e 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -30,17 +30,17 @@ export function BacktracePage() {
For game developers
- This page will eventually let you view backtraces in the browser.
-
- For now you can copy the backtrace code here and use it with{" "}
- agb-addr2line
.
-
If you don't want players to be sent to this page, you can:
Configure the backtrace page to point to your own site
Configure the backtrace page to not point to a site at all
Not use the backtrace feature
+
+ Here you can see the debug information contained in the crash log. Given
+ additional debug files it can present you with the corresponding
+ function names, file names, line numbers, and column numbers.
+
);
From 1a3b4319bc46f78361b9861b5da378590df771ee Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 00:53:20 +0100
Subject: [PATCH 06/26] correct justfile
---
justfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/justfile b/justfile
index eab6cfba..ef7f8e39 100644
--- a/justfile
+++ b/justfile
@@ -93,7 +93,7 @@ setup-cargo-wasm:
build-agb-wasm:
(cd agb-wasm && wasm-pack build --target web)
rm -rf website/agb/src/app/vendor/agb_wasm
- mkdir website/agb/src/app/vendor
+ mkdir -p website/agb/src/app/vendor
cp agb-wasm/pkg website/agb/src/app/vendor/agb_wasm -r
build-mgba-wasm:
From 55394640b098ba572c6b3e82369b082b80190b24 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 19:10:39 +0100
Subject: [PATCH 07/26] correct inline logic
---
agb-debug/src/lib.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/agb-debug/src/lib.rs b/agb-debug/src/lib.rs
index e353a0ca..5c2c69e2 100644
--- a/agb-debug/src/lib.rs
+++ b/agb-debug/src/lib.rs
@@ -1,7 +1,7 @@
mod gwilym_encoding;
mod load_dwarf;
-use addr2line::gimli::{self, EndianReader};
+use addr2line::gimli;
pub use gwilym_encoding::{gwilym_decode, GwilymDecodeError};
pub use load_dwarf::{load_dwarf, GimliDwarf, LoadDwarfError};
use thiserror::Error;
@@ -71,7 +71,7 @@ pub fn address_info(
infos.push(AddressInfo {
location,
is_interesting,
- is_inline: is_first,
+ is_inline: !is_first,
function: function_name,
});
is_first = false;
From 0d4005f163490280ae2009166bd5abad678d563e Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 19:10:53 +0100
Subject: [PATCH 08/26] make backtrace view fancy
---
website/agb/src/app/crash/backtrace.tsx | 121 +++++++++++++++++++-----
1 file changed, 96 insertions(+), 25 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 2d0d8d3e..2178673b 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -46,52 +46,121 @@ export function BacktracePage() {
);
}
+const BacktraceListWrapper = styled.div`
+ font-size: 1rem;
+ position: relative;
+ width: calc(100vw - 20px);
+ margin-left: calc(-1 * (100vw - 20px) / 2);
+ left: 50%;
+`;
+
+const BacktraceList = styled.ol`
+ overflow-x: scroll;
+ white-space: nowrap;
+`;
+
function Backtrace() {
const backtrace = useClientValue(getBacktrace) ?? "";
const backtraceAddresses = useBacktraceData(backtrace);
const [files, setFile] = useState([]);
+ const backtraceAddressesList =
+ typeof backtraceAddresses === "object" ? backtraceAddresses : [];
+ const backtraceError =
+ typeof backtraceAddresses === "string" ? backtraceAddresses : undefined;
+
const backtraceLocations = useBacktraceLocations(
- backtraceAddresses ?? [],
+ backtraceAddressesList,
files ?? []
);
return (
Addresses in the backtrace
- {
- const files = evt.target.files;
- const filesArr = (files && Array.from(files)) ?? [];
- setFile(filesArr);
- }}
- />
-
- {backtraceAddresses &&
- backtraceAddresses.map((x, idx) => (
+
+ Elf file or GBA file with debug information:
+ {
+ const files = evt.target.files;
+ const filesArr = (files && Array.from(files)) ?? [];
+ setFile(filesArr);
+ }}
+ />
+
+
+
+ {backtraceError}
+ {backtraceAddressesList.map((x, idx) => (
- 0x{x.toString(16).padStart(8, "0")}
-
+ {backtraceLocations[idx] ? (
+
+ ) : (
+ 0x{x.toString(16).padStart(8, "0")}
+ )}
))}
-
+
+
);
}
+function makeNicePath(path: string) {
+ const srcIndex = path.lastIndexOf("/src/");
+ if (srcIndex < 0) return path;
+
+ const crateNameStartIndex = path.slice(0, srcIndex).lastIndexOf("/");
+ const crateName =
+ crateNameStartIndex < 0
+ ? ""
+ : path.slice(crateNameStartIndex + 1, srcIndex);
+
+ return `<${crateName}>/${path.slice(srcIndex + 5)}`;
+}
+
+const GreenSpan = styled.span`
+ color: green;
+`;
+
+const BacktraceAddressLine = styled.ul`
+ list-style-type: none;
+ padding-left: 20px;
+`;
+
function BacktraceAddressInfo({ info }: { info: AddressInfo[] | undefined }) {
if (!info) return;
+ function FunctionName({
+ interesting,
+ functionName,
+ }: {
+ interesting: boolean;
+ functionName: string;
+ }) {
+ if (interesting) {
+ return {functionName} ;
+ }
+ return functionName;
+ }
+
return (
-
+
{info.map((x, idx) => (
- {x.is_inline && "(inlined into)"} {x.function_name}:{x.column}{" "}
- {x.filename}:{x.line_number}
+
+ {x.is_inline && "(inlined into)"}{" "}
+ {" "}
+
+ {makeNicePath(x.filename)}:{x.line_number}:{x.column}
+
+
))}
-
+
);
}
@@ -100,17 +169,17 @@ function useBacktraceLocations(addresses: number[], file: File[]) {
const [debugInfo, setDebugInfo] = useState([]);
useEffect(() => {
- const f = file[0];
- if (!f) return;
- if (!debug) return;
(async () => {
+ const f = file[0];
+ if (!f) return;
+ if (!debug) return;
const buf = await f.arrayBuffer();
const view = new Uint8Array(buf);
const agbDebugFile = debug.debug_file(view);
const debugInfo = addresses.map((x) => agbDebugFile.address_info(x));
- setDebugInfo(debugInfo);
- })();
+ return debugInfo;
+ })().then((x) => setDebugInfo(x ?? []));
}, [addresses, debug, file]);
return debugInfo;
@@ -124,7 +193,9 @@ function useBacktraceData(trace?: string) {
if (!trace) return;
const addresses = debug?.decode_backtrace(trace);
return addresses && Array.from(addresses);
- } catch {}
+ } catch (e: unknown) {
+ return `${e}`;
+ }
}, [debug, trace]);
}
From 9b773524d6fabdcb54e54c29b502ed965a68d505 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Thu, 18 Apr 2024 19:39:27 +0100
Subject: [PATCH 09/26] setup wasm
---
.github/workflows/build-site.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/build-site.yml b/.github/workflows/build-site.yml
index cdf7826f..7d2b0495 100644
--- a/.github/workflows/build-site.yml
+++ b/.github/workflows/build-site.yml
@@ -33,6 +33,8 @@ jobs:
uses: peaceiris/actions-mdbook@v2
with:
mdbook-version: "0.4.13"
+ - name: Setup wasm
+ run: just setup-cargo-wasm
- name: Build website
run: just build-site
- name: Upload artifact
From f5bbee01b7b788b77beb01c6ee00dc3e6fff8657 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 21:12:46 +0100
Subject: [PATCH 10/26] move agb-wasm to website directory
---
Cargo.toml | 2 +-
justfile | 8 ++++----
{agb-wasm => website/backtrace}/Cargo.toml | 4 ++--
{agb-wasm => website/backtrace}/src/lib.rs | 0
4 files changed, 7 insertions(+), 7 deletions(-)
rename {agb-wasm => website/backtrace}/Cargo.toml (92%)
rename {agb-wasm => website/backtrace}/src/lib.rs (100%)
diff --git a/Cargo.toml b/Cargo.toml
index 7c273d76..6d75a68f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,7 +26,7 @@ members = [
"emulator/mgba",
"emulator/mgba-sys",
"emulator/test-runner",
- "agb-wasm",
+ "website/backtrace",
]
exclude = [
diff --git a/justfile b/justfile
index ef7f8e39..cbe8bdc4 100644
--- a/justfile
+++ b/justfile
@@ -90,11 +90,11 @@ miri:
setup-cargo-wasm:
cargo install wasm-pack
-build-agb-wasm:
- (cd agb-wasm && wasm-pack build --target web)
+build-website-backtrace:
+ (cd website/backtrace && wasm-pack build --target web)
rm -rf website/agb/src/app/vendor/agb_wasm
mkdir -p website/agb/src/app/vendor
- cp agb-wasm/pkg website/agb/src/app/vendor/agb_wasm -r
+ cp website/backtrace/pkg website/agb/src/app/vendor/agb_wasm -r
build-mgba-wasm:
rm -rf website/agb/src/app/mgba/vendor
@@ -107,7 +107,7 @@ build-combo-rom-site:
gzip -9 -c examples/target/examples/combo.gba > website/agb/public/combo.gba.gz
-setup-app-build: build-mgba-wasm build-combo-rom-site build-agb-wasm
+setup-app-build: build-mgba-wasm build-combo-rom-site build-website-backtrace
(cd website/agb && npm install --no-save --prefer-offline --no-audit)
build-site-app: setup-app-build
diff --git a/agb-wasm/Cargo.toml b/website/backtrace/Cargo.toml
similarity index 92%
rename from agb-wasm/Cargo.toml
rename to website/backtrace/Cargo.toml
index ee56b986..222c93f5 100644
--- a/agb-wasm/Cargo.toml
+++ b/website/backtrace/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "agb-wasm"
+name = "backtrace"
version = "0.1.0"
edition = "2021"
@@ -13,7 +13,7 @@ default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.84"
-agb-debug = { path="../agb-debug" }
+agb-debug = { path="../../agb-debug" }
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
diff --git a/agb-wasm/src/lib.rs b/website/backtrace/src/lib.rs
similarity index 100%
rename from agb-wasm/src/lib.rs
rename to website/backtrace/src/lib.rs
From e82d7f7ce5806f0e111161d8d9e2870d92b270fd Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 21:12:50 +0100
Subject: [PATCH 11/26] remove log
---
website/agb/src/app/useAgbDebug.hook.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/website/agb/src/app/useAgbDebug.hook.ts b/website/agb/src/app/useAgbDebug.hook.ts
index 6e6217e8..3a8eba1a 100644
--- a/website/agb/src/app/useAgbDebug.hook.ts
+++ b/website/agb/src/app/useAgbDebug.hook.ts
@@ -22,7 +22,6 @@ export function useAgbDebug() {
}
await agbDebug;
- console.log("Loaded agb debug");
setDebug({
decode_backtrace,
From 8433b239672d2d9cc720c22587e2b28e65fafd2e Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 21:49:00 +0100
Subject: [PATCH 12/26] copy to backtrace
---
justfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/justfile b/justfile
index cbe8bdc4..97de6337 100644
--- a/justfile
+++ b/justfile
@@ -92,9 +92,9 @@ setup-cargo-wasm:
build-website-backtrace:
(cd website/backtrace && wasm-pack build --target web)
- rm -rf website/agb/src/app/vendor/agb_wasm
+ rm -rf website/agb/src/app/vendor/backtrace
mkdir -p website/agb/src/app/vendor
- cp website/backtrace/pkg website/agb/src/app/vendor/agb_wasm -r
+ cp website/backtrace/pkg website/agb/src/app/vendor/backtrace -r
build-mgba-wasm:
rm -rf website/agb/src/app/mgba/vendor
From 04d368edf0f2aedf62101a257d6e48e4f0791026 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 21:49:16 +0100
Subject: [PATCH 13/26] move out backtrace decoding
---
website/agb/src/app/crash/backtrace.tsx | 170 ++--------------------
website/agb/src/app/crash/debug.tsx | 184 ++++++++++++++++++++++++
website/agb/src/app/crash/page.tsx | 1 -
website/agb/src/app/useAgbDebug.hook.ts | 9 +-
4 files changed, 199 insertions(+), 165 deletions(-)
create mode 100644 website/agb/src/app/crash/debug.tsx
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 2178673b..4c393688 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -3,11 +3,11 @@
import { ContentBlock } from "../contentBlock";
import { useClientValue } from "../useClientValue.hook";
import { styled } from "styled-components";
-import { useEffect, useMemo, useState } from "react";
-import { useAgbDebug } from "../useAgbDebug.hook";
-import { AddressInfo } from "../vendor/agb_wasm/agb_wasm";
+import { Debug } from "./debug";
export function BacktracePage() {
+ const backtrace = useClientValue(getBacktrace);
+
return (
agbrs crash backtrace viewer
@@ -22,7 +22,9 @@ export function BacktracePage() {
time.{" "}
Send these to the creator of the game you are playing.
-
+ {(backtrace && ) || (
+ No backtrace data in Url
+ )}
The owners of this website are not necessarily the creators of the
@@ -41,167 +43,13 @@ export function BacktracePage() {
additional debug files it can present you with the corresponding
function names, file names, line numbers, and column numbers.
-
+ Backtrace
+ {backtrace && }
);
}
-const BacktraceListWrapper = styled.div`
- font-size: 1rem;
- position: relative;
- width: calc(100vw - 20px);
- margin-left: calc(-1 * (100vw - 20px) / 2);
- left: 50%;
-`;
-
-const BacktraceList = styled.ol`
- overflow-x: scroll;
- white-space: nowrap;
-`;
-
-function Backtrace() {
- const backtrace = useClientValue(getBacktrace) ?? "";
- const backtraceAddresses = useBacktraceData(backtrace);
-
- const [files, setFile] = useState([]);
- const backtraceAddressesList =
- typeof backtraceAddresses === "object" ? backtraceAddresses : [];
- const backtraceError =
- typeof backtraceAddresses === "string" ? backtraceAddresses : undefined;
-
- const backtraceLocations = useBacktraceLocations(
- backtraceAddressesList,
- files ?? []
- );
-
- return (
-
- Addresses in the backtrace
-
- Elf file or GBA file with debug information:
- {
- const files = evt.target.files;
- const filesArr = (files && Array.from(files)) ?? [];
- setFile(filesArr);
- }}
- />
-
-
-
- {backtraceError}
- {backtraceAddressesList.map((x, idx) => (
-
- {backtraceLocations[idx] ? (
-
- ) : (
- 0x{x.toString(16).padStart(8, "0")}
- )}
-
- ))}
-
-
-
- );
-}
-
-function makeNicePath(path: string) {
- const srcIndex = path.lastIndexOf("/src/");
- if (srcIndex < 0) return path;
-
- const crateNameStartIndex = path.slice(0, srcIndex).lastIndexOf("/");
- const crateName =
- crateNameStartIndex < 0
- ? ""
- : path.slice(crateNameStartIndex + 1, srcIndex);
-
- return `<${crateName}>/${path.slice(srcIndex + 5)}`;
-}
-
-const GreenSpan = styled.span`
- color: green;
-`;
-
-const BacktraceAddressLine = styled.ul`
- list-style-type: none;
- padding-left: 20px;
-`;
-
-function BacktraceAddressInfo({ info }: { info: AddressInfo[] | undefined }) {
- if (!info) return;
-
- function FunctionName({
- interesting,
- functionName,
- }: {
- interesting: boolean;
- functionName: string;
- }) {
- if (interesting) {
- return {functionName} ;
- }
- return functionName;
- }
-
- return (
-
- {info.map((x, idx) => (
-
-
- {x.is_inline && "(inlined into)"}{" "}
- {" "}
-
- {makeNicePath(x.filename)}:{x.line_number}:{x.column}
-
-
-
- ))}
-
- );
-}
-
-function useBacktraceLocations(addresses: number[], file: File[]) {
- const debug = useAgbDebug();
- const [debugInfo, setDebugInfo] = useState([]);
-
- useEffect(() => {
- (async () => {
- const f = file[0];
- if (!f) return;
- if (!debug) return;
- const buf = await f.arrayBuffer();
- const view = new Uint8Array(buf);
-
- const agbDebugFile = debug.debug_file(view);
- const debugInfo = addresses.map((x) => agbDebugFile.address_info(x));
- return debugInfo;
- })().then((x) => setDebugInfo(x ?? []));
- }, [addresses, debug, file]);
-
- return debugInfo;
-}
-
-function useBacktraceData(trace?: string) {
- const debug = useAgbDebug();
-
- return useMemo(() => {
- try {
- if (!trace) return;
- const addresses = debug?.decode_backtrace(trace);
- return addresses && Array.from(addresses);
- } catch (e: unknown) {
- return `${e}`;
- }
- }, [debug, trace]);
-}
-
-function BacktraceDisplay() {
- const backtrace = useClientValue(getBacktrace) ?? "";
-
+function BacktraceCopyDisplay({ backtrace }: { backtrace: string }) {
return (
{backtrace}
diff --git a/website/agb/src/app/crash/debug.tsx b/website/agb/src/app/crash/debug.tsx
new file mode 100644
index 00000000..a403f431
--- /dev/null
+++ b/website/agb/src/app/crash/debug.tsx
@@ -0,0 +1,184 @@
+import { styled } from "styled-components";
+import { AddressInfo, AgbDebug, useAgbDebug } from "../useAgbDebug.hook";
+import { useMemo, useState } from "react";
+
+const BacktraceListWrapper = styled.div`
+ font-size: 1rem;
+ position: relative;
+ width: calc(100vw - 20px);
+ margin-left: calc(-1 * (100vw - 20px) / 2);
+ left: 50%;
+`;
+
+const BacktraceList = styled.ol`
+ overflow-x: scroll;
+ white-space: nowrap;
+`;
+
+interface DebugProps {
+ encodedBacktrace: string;
+}
+
+export function Debug(props: DebugProps) {
+ const debug = useAgbDebug();
+ if (debug) {
+ return ;
+ } else {
+ return Loading debug viewer...
;
+ }
+}
+
+interface DebugBacktraceDecodeProps extends DebugProps {
+ debug: AgbDebug;
+}
+
+const NonWrapCode = styled.code`
+ white-space: nowrap;
+`;
+
+function DebugBacktraceDecode({
+ encodedBacktrace,
+ debug,
+}: DebugBacktraceDecodeProps) {
+ const backtraceAddresses = useBacktraceData(debug, encodedBacktrace);
+ const [backtraceLocations, setBacktraceLocations] = useState(
+ []
+ );
+
+ if (typeof backtraceAddresses === "string") {
+ return ;
+ }
+
+ return (
+ <>
+
+ If you add the elf file used to make the GBA file, or the GBA file
+ itself if it was made with agb-gbafix --debug
+ , you can see: function names, file names, line numbers, and column
+ numbers.
+
+
+ Elf file or GBA file with debug information:{" "}
+ {
+ const files = evt.target.files;
+ if (!files) return;
+ const file = files[0];
+ if (!file) return;
+ loadLocations(debug, backtraceAddresses, file).then((data) =>
+ setBacktraceLocations(data)
+ );
+ }}
+ />
+
+
+
+ {backtraceAddresses.map((x, idx) => (
+
+
+
+ ))}
+
+
+ >
+ );
+}
+
+function DebugError({ error }: { error: string }) {
+ return (
+ <>
+ Something went wrong decoding the backtrace
+ {error}
+ >
+ );
+}
+
+function makeNicePath(path: string) {
+ const srcIndex = path.lastIndexOf("/src/");
+ if (srcIndex < 0) return path;
+
+ const crateNameStartIndex = path.slice(0, srcIndex).lastIndexOf("/");
+ const crateName =
+ crateNameStartIndex < 0
+ ? ""
+ : path.slice(crateNameStartIndex + 1, srcIndex);
+
+ return `<${crateName}>/${path.slice(srcIndex + 5)}`;
+}
+
+const GreenSpan = styled.span`
+ color: green;
+`;
+
+const BacktraceAddressLine = styled.ul`
+ list-style-type: none;
+ padding-left: 20px;
+`;
+
+function BacktraceAddressInfo({
+ address,
+ info,
+}: {
+ address: number;
+ info: AddressInfo[] | undefined;
+}) {
+ if (!info) {
+ return 0x{address.toString(16).padStart(8, "0")}
;
+ }
+
+ function FunctionName({
+ interesting,
+ functionName,
+ }: {
+ interesting: boolean;
+ functionName: string;
+ }) {
+ if (interesting) {
+ return {functionName} ;
+ }
+ return functionName;
+ }
+
+ return (
+
+ {info.map((x, idx) => (
+
+
+ {x.is_inline && "(inlined into)"}{" "}
+ {" "}
+
+ {makeNicePath(x.filename)}:{x.line_number}:{x.column}
+
+
+
+ ))}
+
+ );
+}
+
+async function loadLocations(debug: AgbDebug, addresses: number[], file: File) {
+ const buf = await file.arrayBuffer();
+ const view = new Uint8Array(buf);
+
+ const agbDebugFile = debug.debug_file(view);
+ const debugInfo = addresses.map((x) => agbDebugFile.address_info(x));
+ return debugInfo;
+}
+
+function useBacktraceData(debug: AgbDebug, trace: string) {
+ return useMemo(() => {
+ try {
+ const addresses = debug?.decode_backtrace(trace);
+ return addresses && Array.from(addresses);
+ } catch (e: unknown) {
+ return `${e}`;
+ }
+ }, [debug, trace]);
+}
diff --git a/website/agb/src/app/crash/page.tsx b/website/agb/src/app/crash/page.tsx
index 05283ac3..e9d4c70d 100644
--- a/website/agb/src/app/crash/page.tsx
+++ b/website/agb/src/app/crash/page.tsx
@@ -1,6 +1,5 @@
import { Metadata } from "next";
import { BacktracePage } from "./backtrace";
-import { ContentBlock } from "../contentBlock";
export const metadata: Metadata = {
title: "agbrs crash backtrace",
diff --git a/website/agb/src/app/useAgbDebug.hook.ts b/website/agb/src/app/useAgbDebug.hook.ts
index 3a8eba1a..4ed74e4e 100644
--- a/website/agb/src/app/useAgbDebug.hook.ts
+++ b/website/agb/src/app/useAgbDebug.hook.ts
@@ -3,16 +3,19 @@ import debugInit, {
decode_backtrace,
DebugFile,
InitOutput,
-} from "./vendor/agb_wasm/agb_wasm";
+ AddressInfo,
+} from "./vendor/backtrace/backtrace";
let agbDebug: Promise | undefined;
-interface AgbDebug {
+export { AddressInfo };
+
+export interface AgbDebug {
decode_backtrace: (backtrace: string) => Uint32Array;
debug_file: (file: Uint8Array) => DebugFile;
}
-export function useAgbDebug() {
+export function useAgbDebug(): AgbDebug | undefined {
const [debug, setDebug] = useState();
useEffect(() => {
From 853c008ff71b38d30d4f35f85e13fd3a7c53aeef Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 21:49:34 +0100
Subject: [PATCH 14/26] cleanup duplicate text
---
website/agb/src/app/crash/backtrace.tsx | 5 -----
1 file changed, 5 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 4c393688..1d436348 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -38,11 +38,6 @@ export function BacktracePage() {
Configure the backtrace page to not point to a site at all
Not use the backtrace feature
-
- Here you can see the debug information contained in the crash log. Given
- additional debug files it can present you with the corresponding
- function names, file names, line numbers, and column numbers.
-
Backtrace
{backtrace && }
From 162bc17addeba2b620057aaa9ecf607f8eeb9fe1 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Fri, 19 Apr 2024 23:55:41 +0100
Subject: [PATCH 15/26] shift content around to make backtrace more apparent
---
website/agb/src/app/crash/backtrace.tsx | 4 ++--
website/agb/src/app/crash/debug.tsx | 24 ++++++++++++------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 1d436348..051c1606 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -31,6 +31,8 @@ export function BacktracePage() {
game you are playing.
+ Backtrace
+ {backtrace && }
For game developers
If you don't want players to be sent to this page, you can:
@@ -38,8 +40,6 @@ export function BacktracePage() {
Configure the backtrace page to not point to a site at all
Not use the backtrace feature
- Backtrace
- {backtrace && }
);
}
diff --git a/website/agb/src/app/crash/debug.tsx b/website/agb/src/app/crash/debug.tsx
index a403f431..27366b2d 100644
--- a/website/agb/src/app/crash/debug.tsx
+++ b/website/agb/src/app/crash/debug.tsx
@@ -51,6 +51,18 @@ function DebugBacktraceDecode({
return (
<>
+
+
+ {backtraceAddresses.map((x, idx) => (
+
+
+
+ ))}
+
+
If you add the elf file used to make the GBA file, or the GBA file
itself if it was made with agb-gbafix --debug
@@ -72,18 +84,6 @@ function DebugBacktraceDecode({
}}
/>
-
-
- {backtraceAddresses.map((x, idx) => (
-
-
-
- ))}
-
-
>
);
}
From 911ea848df31f6950b66399d32395e616786f7aa Mon Sep 17 00:00:00 2001
From: Gwilym Inzani
Date: Sat, 20 Apr 2024 12:31:20 +0100
Subject: [PATCH 16/26] Allow typing in the backtrace
---
website/agb/src/app/crash/backtrace.tsx | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 051c1606..3dbe3e91 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -1,12 +1,13 @@
"use client";
+import { useState } from 'react';
+
import { ContentBlock } from "../contentBlock";
-import { useClientValue } from "../useClientValue.hook";
import { styled } from "styled-components";
import { Debug } from "./debug";
export function BacktracePage() {
- const backtrace = useClientValue(getBacktrace);
+ const [backtrace, setBacktrace] = useState(getBacktrace);
return (
@@ -22,9 +23,7 @@ export function BacktracePage() {
time.{" "}
Send these to the creator of the game you are playing.
- {(backtrace && ) || (
- No backtrace data in Url
- )}
+
The owners of this website are not necessarily the creators of the
@@ -44,10 +43,10 @@ export function BacktracePage() {
);
}
-function BacktraceCopyDisplay({ backtrace }: { backtrace: string }) {
+function BacktraceCopyDisplay({ backtrace, setBacktrace }: { backtrace: string , setBacktrace: (newValue: string) => void}) {
return (
- {backtrace}
+ setBacktrace(e.target.value)} value={backtrace} />
{
navigator.clipboard.writeText(backtrace);
@@ -59,11 +58,10 @@ function BacktraceCopyDisplay({ backtrace }: { backtrace: string }) {
);
}
-const BacktraceCodeBlock = styled.code`
- font-size: 3rem;
+const BacktraceInputBox = styled.input`
+ font-size: larger;
background-color: #dddddd;
- padding: 0px 40px;
- overflow-x: scroll;
+ flex-grow: 999;
`;
const BacktraceWrapper = styled.section`
@@ -76,7 +74,6 @@ const BacktraceWrapper = styled.section`
const BacktraceCopyButton = styled.button`
padding: 10px;
- overflow-x: scroll;
`;
function getBacktrace() {
From dcdbf1069e30435a7d96ea6b143707cc82d4747e Mon Sep 17 00:00:00 2001
From: Gwilym Inzani
Date: Sat, 20 Apr 2024 12:33:24 +0100
Subject: [PATCH 17/26] The address isn't necessarily unique
---
website/agb/src/app/crash/debug.tsx | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/website/agb/src/app/crash/debug.tsx b/website/agb/src/app/crash/debug.tsx
index 27366b2d..4e33ce98 100644
--- a/website/agb/src/app/crash/debug.tsx
+++ b/website/agb/src/app/crash/debug.tsx
@@ -4,10 +4,6 @@ import { useMemo, useState } from "react";
const BacktraceListWrapper = styled.div`
font-size: 1rem;
- position: relative;
- width: calc(100vw - 20px);
- margin-left: calc(-1 * (100vw - 20px) / 2);
- left: 50%;
`;
const BacktraceList = styled.ol`
@@ -54,7 +50,7 @@ function DebugBacktraceDecode({
{backtraceAddresses.map((x, idx) => (
-
+
Date: Sat, 20 Apr 2024 12:38:44 +0100
Subject: [PATCH 18/26] Put the game developer summary in a details block
---
website/agb/src/app/crash/backtrace.tsx | 10 +++------
.../src/app/crash/gameDeveloperSummary.tsx | 21 +++++++++++++++++++
2 files changed, 24 insertions(+), 7 deletions(-)
create mode 100644 website/agb/src/app/crash/gameDeveloperSummary.tsx
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index 3dbe3e91..c572252e 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -3,6 +3,7 @@
import { useState } from 'react';
import { ContentBlock } from "../contentBlock";
+import { GameDeveloperSummary } from './gameDeveloperSummary';
import { styled } from "styled-components";
import { Debug } from "./debug";
@@ -32,13 +33,7 @@ export function BacktracePage() {
Backtrace
{backtrace && }
- For game developers
- If you don't want players to be sent to this page, you can:
-
- Configure the backtrace page to point to your own site
- Configure the backtrace page to not point to a site at all
- Not use the backtrace feature
-
+
);
}
@@ -76,6 +71,7 @@ const BacktraceCopyButton = styled.button`
padding: 10px;
`;
+
function getBacktrace() {
return window.location.hash.slice(1);
}
diff --git a/website/agb/src/app/crash/gameDeveloperSummary.tsx b/website/agb/src/app/crash/gameDeveloperSummary.tsx
new file mode 100644
index 00000000..aca73d86
--- /dev/null
+++ b/website/agb/src/app/crash/gameDeveloperSummary.tsx
@@ -0,0 +1,21 @@
+import { styled } from "styled-components";
+
+export const GameDeveloperSummary = () => {
+ return
+ For game developers
+ If you don't want players to be sent to this page, you can:
+
+ Configure the backtrace page to point to your own site
+ Configure the backtrace page to not point to a site at all
+ Not use the backtrace feature
+
+
+}
+
+const Details = styled.details`
+ margin-top: 10px;
+`;
+
+const Summary = styled.summary`
+ font-weight: bold;
+`;
\ No newline at end of file
From 141a77af80fe1662a5928b4833d02078350798b8 Mon Sep 17 00:00:00 2001
From: Gwilym Inzani
Date: Sat, 20 Apr 2024 12:40:07 +0100
Subject: [PATCH 19/26] Prettier
---
website/agb/src/app/crash/backtrace.tsx | 25 +++++++++++++------
.../src/app/crash/gameDeveloperSummary.tsx | 24 ++++++++++--------
2 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index c572252e..c67a906f 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -1,9 +1,9 @@
"use client";
-import { useState } from 'react';
+import { useState } from "react";
import { ContentBlock } from "../contentBlock";
-import { GameDeveloperSummary } from './gameDeveloperSummary';
+import { GameDeveloperSummary } from "./gameDeveloperSummary";
import { styled } from "styled-components";
import { Debug } from "./debug";
@@ -24,7 +24,7 @@ export function BacktracePage() {
time.{" "}
Send these to the creator of the game you are playing.
-
+
The owners of this website are not necessarily the creators of the
@@ -38,10 +38,21 @@ export function BacktracePage() {
);
}
-function BacktraceCopyDisplay({ backtrace, setBacktrace }: { backtrace: string , setBacktrace: (newValue: string) => void}) {
+function BacktraceCopyDisplay({
+ backtrace,
+ setBacktrace,
+}: {
+ backtrace: string;
+ setBacktrace: (newValue: string) => void;
+}) {
return (
- setBacktrace(e.target.value)} value={backtrace} />
+ setBacktrace(e.target.value)}
+ value={backtrace}
+ />
{
navigator.clipboard.writeText(backtrace);
@@ -55,7 +66,8 @@ function BacktraceCopyDisplay({ backtrace, setBacktrace }: { backtrace: string ,
const BacktraceInputBox = styled.input`
font-size: larger;
- background-color: #dddddd;
+ background-color: #eee;
+
flex-grow: 999;
`;
@@ -71,7 +83,6 @@ const BacktraceCopyButton = styled.button`
padding: 10px;
`;
-
function getBacktrace() {
return window.location.hash.slice(1);
}
diff --git a/website/agb/src/app/crash/gameDeveloperSummary.tsx b/website/agb/src/app/crash/gameDeveloperSummary.tsx
index aca73d86..d57c2746 100644
--- a/website/agb/src/app/crash/gameDeveloperSummary.tsx
+++ b/website/agb/src/app/crash/gameDeveloperSummary.tsx
@@ -1,16 +1,18 @@
import { styled } from "styled-components";
export const GameDeveloperSummary = () => {
- return
- For game developers
- If you don't want players to be sent to this page, you can:
-
- Configure the backtrace page to point to your own site
- Configure the backtrace page to not point to a site at all
- Not use the backtrace feature
-
-
-}
+ return (
+
+ For game developers
+ If you don't want players to be sent to this page, you can:
+
+ Configure the backtrace page to point to your own site
+ Configure the backtrace page to not point to a site at all
+ Not use the backtrace feature
+
+
+ );
+};
const Details = styled.details`
margin-top: 10px;
@@ -18,4 +20,4 @@ const Details = styled.details`
const Summary = styled.summary`
font-weight: bold;
-`;
\ No newline at end of file
+`;
From 4899ccd5aa43df9f2c421f74460cd60fc47872f6 Mon Sep 17 00:00:00 2001
From: Gwilym Inzani
Date: Sat, 20 Apr 2024 12:48:31 +0100
Subject: [PATCH 20/26] Avoid awkward wrapping
---
website/agb/src/app/crash/backtrace.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index c67a906f..af89b9ac 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -67,6 +67,9 @@ function BacktraceCopyDisplay({
const BacktraceInputBox = styled.input`
font-size: larger;
background-color: #eee;
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ min-width: 0;
flex-grow: 999;
`;
@@ -76,7 +79,6 @@ const BacktraceWrapper = styled.section`
gap: 10px;
justify-content: center;
align-items: center;
- flex-wrap: wrap;
`;
const BacktraceCopyButton = styled.button`
From 8352d20d73ac78ee734e78d1e8b8ac38cf4ba609 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 13:27:00 +0100
Subject: [PATCH 21/26] add errors for file decoding
---
website/agb/src/app/crash/debug.tsx | 41 ++++++++++++++++++++---------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/website/agb/src/app/crash/debug.tsx b/website/agb/src/app/crash/debug.tsx
index 4e33ce98..5e036640 100644
--- a/website/agb/src/app/crash/debug.tsx
+++ b/website/agb/src/app/crash/debug.tsx
@@ -1,6 +1,6 @@
import { styled } from "styled-components";
import { AddressInfo, AgbDebug, useAgbDebug } from "../useAgbDebug.hook";
-import { useMemo, useState } from "react";
+import { ReactNode, useMemo, useState } from "react";
const BacktraceListWrapper = styled.div`
font-size: 1rem;
@@ -41,8 +41,15 @@ function DebugBacktraceDecode({
[]
);
+ const [backtraceLocationsError, setBacktraceLocationsError] =
+ useState("");
+
if (typeof backtraceAddresses === "string") {
- return ;
+ return (
+
+ Something went wrong decoding the backtrace: {backtraceAddresses}
+
+ );
}
return (
@@ -74,23 +81,33 @@ function DebugBacktraceDecode({
if (!files) return;
const file = files[0];
if (!file) return;
- loadLocations(debug, backtraceAddresses, file).then((data) =>
- setBacktraceLocations(data)
- );
+ setBacktraceLocationsError("");
+ loadLocations(debug, backtraceAddresses, file)
+ .then((data) => setBacktraceLocations(data))
+ .catch((e) => setBacktraceLocationsError(`${e}`));
}}
/>
+ {backtraceLocationsError && (
+
+ Something went wrong looking up the addresses in the file provided:{" "}
+ {backtraceLocationsError}
+
+ )}
>
);
}
-function DebugError({ error }: { error: string }) {
- return (
- <>
- Something went wrong decoding the backtrace
- {error}
- >
- );
+const ErrorBlock = styled.div`
+ background-color: #f78f8f;
+ border: 2px solid #9c0a0a;
+ border-radius: 8px;
+ padding: 20px;
+ margin-top: 10px;
+`;
+
+function DebugError({ children }: { children: ReactNode }) {
+ return {children} ;
}
function makeNicePath(path: string) {
From 1adf31d140cbad1bff75ceb53fe674ada395c3ec Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 13:30:14 +0100
Subject: [PATCH 22/26] report when there's no information for an address
---
website/agb/src/app/crash/debug.tsx | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/website/agb/src/app/crash/debug.tsx b/website/agb/src/app/crash/debug.tsx
index 5e036640..3765f14f 100644
--- a/website/agb/src/app/crash/debug.tsx
+++ b/website/agb/src/app/crash/debug.tsx
@@ -139,8 +139,19 @@ function BacktraceAddressInfo({
address: number;
info: AddressInfo[] | undefined;
}) {
+ const formattedAddress = `0x${address.toString(16).padStart(8, "0")}`;
if (!info) {
- return 0x{address.toString(16).padStart(8, "0")}
;
+ return {formattedAddress}
;
+ }
+
+ if (info.length === 0) {
+ return (
+
+
+ (no info) {formattedAddress}
+
+
+ );
}
function FunctionName({
@@ -156,6 +167,8 @@ function BacktraceAddressInfo({
return functionName;
}
+ console.log(info);
+
return (
{info.map((x, idx) => (
From bc689cbbd200900d53332f1291cb3fd947e2f122 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 13:35:33 +0100
Subject: [PATCH 23/26] function style
---
website/agb/src/app/crash/gameDeveloperSummary.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/website/agb/src/app/crash/gameDeveloperSummary.tsx b/website/agb/src/app/crash/gameDeveloperSummary.tsx
index d57c2746..e67d9044 100644
--- a/website/agb/src/app/crash/gameDeveloperSummary.tsx
+++ b/website/agb/src/app/crash/gameDeveloperSummary.tsx
@@ -1,6 +1,6 @@
import { styled } from "styled-components";
-export const GameDeveloperSummary = () => {
+export function GameDeveloperSummary() {
return (
For game developers
@@ -12,7 +12,7 @@ export const GameDeveloperSummary = () => {
);
-};
+}
const Details = styled.details`
margin-top: 10px;
From 103085684a056be8a80d9ff4e1ee1c94976b83dd Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 13:43:42 +0100
Subject: [PATCH 24/26] get value that depends on being run in the client in an
effect
---
website/agb/src/app/crash/backtrace.tsx | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index af89b9ac..fca85a71 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { ContentBlock } from "../contentBlock";
import { GameDeveloperSummary } from "./gameDeveloperSummary";
@@ -8,7 +8,10 @@ import { styled } from "styled-components";
import { Debug } from "./debug";
export function BacktracePage() {
- const [backtrace, setBacktrace] = useState(getBacktrace);
+ const [backtrace, setBacktrace] = useState("");
+ useEffect(() => {
+ setBacktrace(getBacktrace());
+ }, []);
return (
From 6aee9ba1544601152279aa726ea78c24985f1669 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 15:38:55 +0100
Subject: [PATCH 25/26] placeholder
---
website/agb/src/app/crash/backtrace.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/website/agb/src/app/crash/backtrace.tsx b/website/agb/src/app/crash/backtrace.tsx
index fca85a71..589d1137 100644
--- a/website/agb/src/app/crash/backtrace.tsx
+++ b/website/agb/src/app/crash/backtrace.tsx
@@ -52,7 +52,7 @@ function BacktraceCopyDisplay({
setBacktrace(e.target.value)}
value={backtrace}
/>
From 04f1d5c2ffe1752bf63ec60b3281c1c7b0507ad5 Mon Sep 17 00:00:00 2001
From: Corwin
Date: Sat, 20 Apr 2024 21:49:05 +0100
Subject: [PATCH 26/26] use library functions to get address info
---
agb-debug/src/main.rs | 88 +++++++++++--------------------------------
1 file changed, 22 insertions(+), 66 deletions(-)
diff --git a/agb-debug/src/main.rs b/agb-debug/src/main.rs
index 00611148..9364a018 100644
--- a/agb-debug/src/main.rs
+++ b/agb-debug/src/main.rs
@@ -7,8 +7,7 @@ use std::{
time::SystemTime,
};
-use addr2line::gimli;
-use agb_debug::Location;
+use agb_debug::{address_info, AddressInfo, Location};
use clap::Parser;
use colored::Colorize;
@@ -35,77 +34,46 @@ fn main() -> Result<(), Box> {
let ctx = addr2line::Context::from_dwarf(dwarf)?;
for (i, address) in agb_debug::gwilym_decode(&cli.dump)?.enumerate() {
- print_address(&ctx, i, address.into(), modification_time)?;
+ let infos = address_info(&ctx, address.into())?;
+ for info in infos {
+ print_address_info(&info, i, modification_time)?;
+ }
}
Ok(())
}
-fn print_address(
- ctx: &addr2line::Context,
+fn print_address_info(
+ info: &AddressInfo,
index: usize,
- address: u64,
elf_modification_time: SystemTime,
) -> Result<(), Box> {
- let mut frames = ctx.find_frames(address).skip_all_loads()?;
+ let function_name_to_print = &info.function;
- let mut is_first = true;
+ if !info.is_inline {
+ print!("{index}:\t{function_name_to_print}");
+ } else {
+ print!("\t(inlined into) {function_name_to_print}");
+ }
- while let Some(frame) = frames.next()? {
- let function_name = if let Some(ref func) = frame.function {
- func.demangle()?.into_owned()
- } else {
- "unknown function".to_string()
- };
+ println!(
+ " {}:{}",
+ prettify_path(&info.location.filename).green(),
+ info.location.line.to_string().green()
+ );
- let location = frame
- .location
- .as_ref()
- .map(|location| Location {
- filename: location.file.unwrap_or("??").to_owned(),
- line: location.line.unwrap_or(0),
- col: location.column.unwrap_or(0),
- })
- .unwrap_or_default();
-
- let is_interesting = is_interesting_function(&function_name, &location.filename);
- let function_name_to_print = if is_interesting {
- function_name.bold()
- } else {
- function_name.normal()
- };
-
- if is_first {
- print!("{index}:\t{function_name_to_print}");
- } else {
- print!("\t(inlined into) {function_name_to_print}");
- }
-
- println!(
- " {}:{}",
- prettify_path(&location.filename).green(),
- location.line.to_string().green()
- );
-
- if location.line != 0 && is_interesting {
- print_line_of_code(&frame, location, elf_modification_time)?;
- }
-
- is_first = false;
+ if info.location.line != 0 && info.is_interesting {
+ print_line_of_code(&info.location, elf_modification_time)?;
}
Ok(())
}
fn print_line_of_code(
- frame: &addr2line::Frame<'_, impl gimli::Reader>,
- location: Location,
+ location: &Location,
elf_modification_time: SystemTime,
) -> Result<(), Box> {
- let Some(filename) = frame.location.as_ref().and_then(|location| location.file) else {
- return Ok(());
- };
-
+ let filename = &location.filename;
let Ok(mut file) = File::open(filename) else {
return Ok(());
};
@@ -153,15 +121,3 @@ fn prettify_path(path: &str) -> Cow<'_, str> {
Cow::Borrowed(path)
}
}
-
-fn is_interesting_function(function_name: &str, path: &str) -> bool {
- if function_name == "rust_begin_unwind" {
- return false; // this is the unwind exception call
- }
-
- if path.ends_with("panicking.rs") {
- return false; // probably part of rust's internal panic mechanisms
- }
-
- true
-}