Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

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

72 changes: 19 additions & 53 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,56 +400,32 @@ impl<'data> ProguardCache<'data> {
})
}

/// Determines if a frame refers to an outline method, either via the
/// method-level flag or via any matching mapping entry for the frame line.
fn is_outline_frame(
&self,
class: &str,
method: &str,
line: usize,
parameters: Option<&str>,
) -> bool {
/// Determines if a frame refers to an outline method via the method-level flag.
/// Outline metadata is consistent across all mapping entries for a method, so
/// we only need to inspect the method metadata instead of individual lines.
pub fn is_outline_frame(&self, class: &str, method: &str) -> bool {
let Some(class) = self.get_class(class) else {
return false;
};

let candidates: &[raw::Member] = if let Some(params) = parameters {
let Some(members) = self.get_class_members_by_params(class) else {
return false;
};
let Some(range) = Self::find_range_by_binary_search(members, |m| {
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
return Ordering::Greater;
};
let p = self.read_string(m.params_offset).unwrap_or_default();
(obfuscated_name, p).cmp(&(method, params))
}) else {
return false;
};
range
} else {
let Some(members) = self.get_class_members(class) else {
return false;
};
let Some(range) = Self::find_range_by_binary_search(members, |m| {
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
return Ordering::Greater;
};
obfuscated_name.cmp(method)
}) else {
return false;
let Some(members) = self.get_class_members(class) else {
return false;
};

let Some(candidates) = Self::find_range_by_binary_search(members, |m| {
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
return Ordering::Greater;
};
range
obfuscated_name.cmp(method)
}) else {
return false;
};

candidates.iter().any(|m| {
m.is_outline()
&& (m.endline == 0 || (line >= m.startline as usize && line <= m.endline as usize))
})
candidates.first().is_some_and(|member| member.is_outline())
}

/// Applies any carried outline position to the frame line and returns the adjusted frame.
fn prepare_frame_for_mapping<'a>(
pub fn prepare_frame_for_mapping<'a>(
&self,
frame: &StackFrame<'a>,
carried_outline_pos: &mut Option<usize>,
Expand Down Expand Up @@ -483,12 +459,7 @@ impl<'data> ProguardCache<'data> {
None => match stacktrace::parse_frame(line) {
None => writeln!(&mut stacktrace, "{line}")?,
Some(frame) => {
if self.is_outline_frame(
frame.class,
frame.method,
frame.line,
frame.parameters,
) {
if self.is_outline_frame(frame.class, frame.method) {
carried_outline_pos = Some(frame.line);
} else {
let effective_frame =
Expand Down Expand Up @@ -520,12 +491,7 @@ impl<'data> ProguardCache<'data> {
}
},
Some(frame) => {
if self.is_outline_frame(
frame.class,
frame.method,
frame.line,
frame.parameters,
) {
if self.is_outline_frame(frame.class, frame.method) {
carried_outline_pos = Some(frame.line);
continue;
}
Expand All @@ -549,7 +515,7 @@ impl<'data> ProguardCache<'data> {
let mut carried_outline_pos: Option<usize> = None;
let mut frames: Vec<StackFrame<'a>> = Vec::with_capacity(trace.frames.len());
for f in trace.frames.iter() {
if self.is_outline_frame(f.class, f.method, f.line, f.parameters) {
if self.is_outline_frame(f.class, f.method) {
carried_outline_pos = Some(f.line);
continue;
}
Expand Down
45 changes: 9 additions & 36 deletions src/mapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,32 +359,15 @@ impl<'s> ProguardMapper<'s> {
})
}

/// Determines if a frame refers to an outline method, either via the
/// method-level flag or via any matching mapping entry for the frame line.
fn is_outline_frame(
&self,
class: &str,
method: &str,
line: usize,
parameters: Option<&str>,
) -> bool {
/// Determines if a frame refers to an outline method via the method-level flag.
/// Outline metadata is consistent across all mappings for a method, so checking
/// a single mapping entry is sufficient.
fn is_outline_frame(&self, class: &str, method: &str) -> bool {
self.classes
.get(class)
.and_then(|c| c.members.get(method))
.map(|ms| {
let mappings: &[_] = if let Some(params) = parameters {
match ms.mappings_by_params.get(params) {
Some(v) => &v[..],
None => &[],
}
} else {
&ms.all_mappings[..]
};
mappings.iter().any(|m| {
m.is_outline && (m.endline == 0 || (line >= m.startline && line <= m.endline))
})
})
.unwrap_or(false)
.and_then(|ms| ms.all_mappings.first())
.is_some_and(|m| m.is_outline)
}

/// Applies any carried outline position to the frame line and returns the adjusted frame.
Expand Down Expand Up @@ -520,12 +503,7 @@ impl<'s> ProguardMapper<'s> {
None => match stacktrace::parse_frame(line) {
None => writeln!(&mut stacktrace, "{line}")?,
Some(frame) => {
if self.is_outline_frame(
frame.class,
frame.method,
frame.line,
frame.parameters,
) {
if self.is_outline_frame(frame.class, frame.method) {
carried_outline_pos = Some(frame.line);
} else {
let effective_frame =
Expand Down Expand Up @@ -557,12 +535,7 @@ impl<'s> ProguardMapper<'s> {
}
},
Some(frame) => {
if self.is_outline_frame(
frame.class,
frame.method,
frame.line,
frame.parameters,
) {
if self.is_outline_frame(frame.class, frame.method) {
carried_outline_pos = Some(frame.line);
continue;
}
Expand All @@ -587,7 +560,7 @@ impl<'s> ProguardMapper<'s> {
let mut carried_outline_pos: Option<usize> = None;
let mut frames_out = Vec::with_capacity(trace.frames.len());
for f in trace.frames.iter() {
if self.is_outline_frame(f.class, f.method, f.line, f.parameters) {
if self.is_outline_frame(f.class, f.method) {
carried_outline_pos = Some(f.line);
continue;
}
Expand Down
Loading