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
52 changes: 26 additions & 26 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ pub(crate) struct RewriteRule<'s> {
pub(crate) struct Member<'s> {
/// The method the member refers to.
pub(crate) method: MethodKey<'s>,
/// The obfuscated/minified start line.
pub(crate) startline: usize,
/// The obfuscated/minified end line.
pub(crate) endline: usize,
/// The original start line.
pub(crate) original_startline: usize,
/// The obfuscated/minified start line, `None` when no minified range prefix was present.
pub(crate) startline: Option<usize>,
/// The obfuscated/minified end line, `None` when no minified range prefix was present.
pub(crate) endline: Option<usize>,
/// The original start line, `None` when no line mapping was present.
pub(crate) original_startline: Option<usize>,
/// The original end line.
pub(crate) original_endline: Option<usize>,
/// Optional outline callsite positions map attached to this member.
Expand Down Expand Up @@ -291,29 +291,29 @@ impl<'s> ParsedProguardMapping<'s> {
} else {
None
};
// in case the mapping has no line records, we use `0` here.
let (mut startline, mut endline) =
line_mapping.as_ref().map_or((0, 0), |line_mapping| {
(line_mapping.startline, line_mapping.endline)
});
let (mut original_startline, mut original_endline) =
line_mapping.map_or((0, None), |line_mapping| {
match line_mapping.original_startline {
Some(original_startline) => {
(original_startline, line_mapping.original_endline)
}
None => (line_mapping.startline, Some(line_mapping.endline)),
}
});
let (mut startline, mut endline) = match line_mapping.as_ref() {
Some(lm) => (lm.startline, lm.endline),
None => (None, None),
};
let (mut original_startline, mut original_endline) = match line_mapping {
None => (None, None),
Some(lm) => match lm.original_startline {
Some(os) => (Some(os), lm.original_endline),
None => (startline, endline),
},
};

// Normalize inverted ranges independently.
if startline > endline {
std::mem::swap(&mut startline, &mut endline);
if let (Some(s), Some(e)) = (startline, endline) {
if s > e {
startline = Some(e);
endline = Some(s);
}
}
if let Some(oe) = original_endline {
if original_startline > oe {
original_endline = Some(original_startline);
original_startline = oe;
if let (Some(os), Some(oe)) = (original_startline, original_endline) {
if os > oe {
original_startline = Some(oe);
original_endline = Some(os);
}
}

Expand Down
53 changes: 24 additions & 29 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,9 @@ impl<'data> ProguardCache<'data> {
for member in mapping_entries {
// Check if this member would produce a frame (line matching)
let pf_line = prepared_frame.line.unwrap_or(0);
if member.endline == 0
|| (pf_line >= member.startline as usize && pf_line <= member.endline as usize)
{
let startline = member.startline().unwrap_or(0) as usize;
let endline = member.endline().unwrap_or(0) as usize;
if endline == 0 || (pf_line >= startline && pf_line <= endline) {
had_mappings = true;
rewrite_rules.extend(self.decode_rewrite_rules(member));
}
Expand All @@ -405,7 +405,7 @@ impl<'data> ProguardCache<'data> {
}
}

let has_line_info = mapping_entries.iter().any(|m| m.endline > 0);
let has_line_info = mapping_entries.iter().any(|m| m.endline().unwrap_or(0) > 0);

Some((
mapping_entries,
Expand Down Expand Up @@ -631,9 +631,9 @@ impl<'data> ProguardCache<'data> {
candidates
.iter()
.filter(|m| {
m.endline == 0
|| (callsite_line >= m.startline as usize
&& callsite_line <= m.endline as usize)
m.endline().unwrap_or(0) == 0
|| (callsite_line >= m.startline().unwrap_or(0) as usize
&& callsite_line <= m.endline().unwrap_or(0) as usize)
})
.find_map(|m| {
self.member_outline_pairs(m)
Expand Down Expand Up @@ -917,7 +917,7 @@ impl<'r, 'data> RemappedFrameIter<'r, 'data> {
NoLineSelection::IterateBase => {
let mut mapped = None;
for member in members.by_ref() {
if member.endline == 0 {
if member.endline().unwrap_or(0) == 0 {
mapped = map_member_without_lines(
cache,
&frame,
Expand Down Expand Up @@ -985,28 +985,29 @@ fn iterate_with_lines<'a>(
) -> Option<StackFrame<'a>> {
let frame_line = frame.line.unwrap_or(0);
for member in members {
let member_endline = member.endline().unwrap_or(0) as usize;
let member_startline = member.startline().unwrap_or(0) as usize;
// If this method has line mappings, skip base (no-line) entries when we have a concrete line.
if has_line_info && frame_line > 0 && member.endline == 0 {
if has_line_info && frame_line > 0 && member_endline == 0 {
continue;
}
// If the mapping entry has no line range, preserve the input line number (if any).
if member.endline == 0 {
if member_endline == 0 {
return map_member_without_lines(cache, frame, member, outer_source_file);
}
// skip any members which do not match our frames line
if member.endline > 0
&& (frame_line < member.startline as usize || frame_line > member.endline as usize)
{
if member_endline > 0 && (frame_line < member_startline || frame_line > member_endline) {
continue;
}
let original_startline = member.original_startline().unwrap_or(0) as usize;
// parents of inlined frames don't have an `endline`, and
// the top inlined frame need to be correctly offset.
let line = if member.original_endline == u32::MAX
|| member.original_endline == member.original_startline
|| member.original_endline as usize == original_startline
{
member.original_startline as usize
original_startline
} else {
member.original_startline as usize + frame_line - member.startline as usize
original_startline + frame_line - member_startline
};

let class = cache
Expand Down Expand Up @@ -1058,7 +1059,7 @@ enum NoLineSelection<'a> {

fn select_no_line_members<'a>(members: &'a [raw::Member]) -> Option<NoLineSelection<'a>> {
// Prefer base entries (endline == 0) if present.
let mut base_members = members.iter().filter(|m| m.endline == 0);
let mut base_members = members.iter().filter(|m| m.endline().unwrap_or(0) == 0);
if let Some(first_base) = base_members.next() {
let all_same = base_members.all(|m| {
m.original_class_offset == first_base.original_class_offset
Expand Down Expand Up @@ -1097,10 +1098,7 @@ fn map_member_without_lines<'a>(
let method = cache.read_string(member.original_name_offset).ok()?;
let file = synthesize_source_file(class, outer_source_file).map(Cow::Owned);

let original_startline = match member.original_startline {
0 | u32::MAX => None,
value => Some(value as usize),
};
let original_startline = member.original_startline().map(|v| v as usize);

Some(StackFrame {
class,
Expand All @@ -1109,8 +1107,8 @@ fn map_member_without_lines<'a>(
line: Some(resolve_no_line_output_line(
frame.line.unwrap_or(0),
original_startline,
member.startline as usize,
member.endline as usize,
member.startline().map(|v| v as usize),
member.endline().map(|v| v as usize),
)),
parameters: frame.parameters,
method_synthesized: member.is_synthesized(),
Expand All @@ -1134,10 +1132,7 @@ fn iterate_without_lines<'a>(
// Synthesize from class name (input filename is not reliable)
let file = synthesize_source_file(class, outer_source_file).map(Cow::Owned);

let original_startline = match member.original_startline {
0 | u32::MAX => None,
value => Some(value as usize),
};
let original_startline = member.original_startline().map(|v| v as usize);

Some(StackFrame {
class,
Expand All @@ -1146,8 +1141,8 @@ fn iterate_without_lines<'a>(
line: Some(resolve_no_line_output_line(
frame.line.unwrap_or(0),
original_startline,
member.startline as usize,
member.endline as usize,
member.startline().map(|v| v as usize),
member.endline().map(|v| v as usize),
)),
parameters: frame.parameters,
method_synthesized: member.is_synthesized(),
Expand Down
44 changes: 36 additions & 8 deletions src/cache/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,26 @@ impl Default for Class {
}
}

/// Sentinel value representing absent/`None` for u32 fields in the binary format.
const NONE_VALUE: u32 = u32::MAX;

/// An entry corresponding to a method line in a proguard cache file.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[repr(C)]
pub(crate) struct Member {
/// The obfuscated method name (offset into the string section).
pub(crate) obfuscated_name_offset: u32,
/// The start of the range covered by this entry (1-based).
/// The start of the range covered by this entry (1-based), `u32::MAX` if absent.
pub(crate) startline: u32,
/// The end of the range covered by this entry (inclusive).
/// The end of the range covered by this entry (inclusive), `u32::MAX` if absent.
pub(crate) endline: u32,
/// The original class name (offset into the string section).
pub(crate) original_class_offset: u32,
/// The original file name (offset into the string section).
pub(crate) original_file_offset: u32,
/// The original method name (offset into the string section).
pub(crate) original_name_offset: u32,
/// The original start line (1-based).
/// The original start line (0-based), `u32::MAX` if absent.
pub(crate) original_startline: u32,
/// The original end line (inclusive).
pub(crate) original_endline: u32,
Expand All @@ -136,6 +139,7 @@ pub(crate) struct Member {
///
/// `0` means `false`, all other values mean `true`.
pub(crate) is_outline: u8,

/// Reserved space.
pub(crate) _reserved: [u8; 2],
}
Expand All @@ -149,6 +153,30 @@ impl Member {
pub(crate) fn is_outline(&self) -> bool {
self.is_outline != 0
}
/// Returns the startline as `Option<u32>`, where `NONE_VALUE` maps to `None`.
pub(crate) fn startline(&self) -> Option<u32> {
if self.startline == NONE_VALUE {
None
} else {
Some(self.startline)
}
}
/// Returns the endline as `Option<u32>`, where `NONE_VALUE` maps to `None`.
pub(crate) fn endline(&self) -> Option<u32> {
if self.endline == NONE_VALUE {
None
} else {
Some(self.endline)
}
}
/// Returns the original_startline as `Option<u32>`, where `NONE_VALUE` maps to `None`.
pub(crate) fn original_startline(&self) -> Option<u32> {
if self.original_startline == NONE_VALUE {
None
} else {
Some(self.original_startline)
}
}
}

unsafe impl Pod for Header {}
Expand Down Expand Up @@ -616,22 +644,22 @@ impl<'data> ProguardCache<'data> {
.collect();

let member: Member = Member {
startline: member.startline as u32,
endline: member.endline as u32,
startline: member.startline.map_or(NONE_VALUE, |v| v as u32),
endline: member.endline.map_or(NONE_VALUE, |v| v as u32),
original_class_offset,
original_file_offset,
original_name_offset,
original_startline: member.original_startline as u32,
original_endline: member.original_endline.map_or(u32::MAX, |l| l as u32),
original_startline: member.original_startline.map_or(NONE_VALUE, |v| v as u32),
original_endline: member.original_endline.map_or(NONE_VALUE, |l| l as u32),
obfuscated_name_offset,
params_offset,
is_synthesized,
is_outline,
_reserved: [0; 2],
outline_pairs_offset: 0,
outline_pairs_len: 0,
rewrite_rules_offset: 0,
rewrite_rules_len: 0,
_reserved: [0; 2],
};

MemberInProgress {
Expand Down
Loading
Loading