Skip to content

Commit

Permalink
fix: Only consider "near" lines on il2cpp lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem committed Jul 6, 2022
1 parent e902660 commit d21135c
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 6 deletions.
10 changes: 5 additions & 5 deletions symbolic-il2cpp/src/line_mapping/from_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,26 @@ impl ObjectLineMapping {

/// An Il2cpp `source_info` record.
#[derive(Debug, PartialEq, Eq)]
struct SourceInfo<'data> {
pub(crate) struct SourceInfo<'data> {
/// The C++ source line the `source_info` was parsed from.
cpp_line: u32,
pub(crate) cpp_line: u32,
/// The corresponding C# source file.
cs_file: &'data str,
/// The corresponding C# source line.
cs_line: u32,
pub(crate) cs_line: u32,
}

/// An iterator over Il2cpp `source_info` markers.
///
/// The Iterator yields `SourceInfo`s.
struct SourceInfos<'data> {
pub(crate) struct SourceInfos<'data> {
lines: Enumerate<Lines<'data>>,
current: Option<(&'data str, u32)>,
}

impl<'data> SourceInfos<'data> {
/// Parses the `source` leniently, yielding an empty Iterator for non-utf8 data.
fn new(source: &'data [u8]) -> Self {
pub(crate) fn new(source: &'data [u8]) -> Self {
let lines = std::str::from_utf8(source)
.ok()
.unwrap_or_default()
Expand Down
61 changes: 60 additions & 1 deletion symbolic-il2cpp/src/line_mapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@ use std::collections::HashMap;

pub use from_object::ObjectLineMapping;

/// An internal line mapping.
#[derive(Debug)]
struct LineEntry {
/// The C++ line that is being mapped.
cpp_line: u32,
/// The C# line it corresponds to.
cs_line: u32,
/// The index into the `cs_files` [`IndexSet`] below for the corresponding C# file.
cs_file_idx: usize,
}

/// A parsed Il2Cpp/Unity Line mapping JSON.
#[derive(Debug, Default)]
pub struct LineMapping {
/// The set of C# files.
cs_files: IndexSet<String>,
/// A map of C++ filename to a list of Mappings.
cpp_file_map: HashMap<String, Vec<LineEntry>>,
}

impl LineMapping {
/// Parses a JSON buffer into a valid [`LineMapping`].
///
/// Returns [`None`] if the JSON was not a valid mapping.
pub fn parse(data: &[u8]) -> Option<Self> {
let json: serde_json::Value = serde_json::from_slice(data).ok()?;
let mut result = Self::default();
Expand Down Expand Up @@ -56,6 +66,9 @@ impl LineMapping {
Some(result)
}

/// Looks up the corresponding C# file/line for a given C++ file/line.
///
/// As these mappings are not exact, this will return an exact match, or a mapping "close-by".
pub fn lookup(&self, file: &str, line: u32) -> Option<(&str, u32)> {
let lines = self.cpp_file_map.get(file)?;

Expand All @@ -68,9 +81,55 @@ impl LineMapping {
let LineEntry {
cs_line,
cs_file_idx,
..
cpp_line,
} = lines.get(idx)?;

// We will return mappings at most 5 lines away from the source line they refer to.
if line.saturating_sub(*cpp_line) > 5 {
return None;
}

Some((self.cs_files.get_index(*cs_file_idx)?, *cs_line))
}
}

#[cfg(test)]
mod tests {
use super::from_object::SourceInfos;
use super::*;

#[test]
fn test_lookup() {
// well, we can either use a pre-made json, or create one ourselves:
let cpp_source = b"Lorem ipsum dolor sit amet
//<source_info:main.cs:17>
// some
// comments
some expression // 5
stretching
over
multiple lines
// blank lines
// and stuff
// 13
//<source_info:main.cs:29>
actual source code // 15
";

let line_mappings: HashMap<_, _> = SourceInfos::new(cpp_source)
.map(|si| (si.cpp_line, si.cs_line))
.collect();

let mapping = HashMap::from([("main.cpp", HashMap::from([("main.cs", line_mappings)]))]);
let mapping_json = serde_json::to_string(&mapping).unwrap();

let parsed_mapping = LineMapping::parse(mapping_json.as_bytes()).unwrap();

assert_eq!(parsed_mapping.lookup("main.cpp", 2), None);
assert_eq!(parsed_mapping.lookup("main.cpp", 5), Some(("main.cs", 17)));
assert_eq!(parsed_mapping.lookup("main.cpp", 12), None);
assert_eq!(parsed_mapping.lookup("main.cpp", 15), Some(("main.cs", 29)));
}
}

0 comments on commit d21135c

Please sign in to comment.