Skip to content

Commit

Permalink
Add the ability to demangle java resource files
Browse files Browse the repository at this point in the history
  • Loading branch information
Saldivarcher authored and khuey committed Jun 23, 2020
1 parent bc47954 commit 1e51bce
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 3 deletions.
3 changes: 1 addition & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ use std::fmt::Write;
let mut s: HashSet<_> = (0..86).collect();
s.extend(87..89);
s.extend(91..93);
s.extend(94..105);
s.extend(106..113);
s.extend(94..113);
s.extend(115..118);
s.extend(119..120);
s.extend(121..124);
Expand Down
124 changes: 123 additions & 1 deletion src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7265,6 +7265,7 @@ where
/// ::= TF <type> # typinfo function
/// ::= TH <name> # TLS initialization function
/// ::= TW <name> # TLS wrapper function
/// ::= Gr <resource name> # Java Resource
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SpecialName {
Expand Down Expand Up @@ -7304,6 +7305,9 @@ pub enum SpecialName {

/// A TLS wrapper function.
TlsWrapper(Name),

/// A Java Resource.
JavaResource(Vec<ResourceName>),
}

impl Parse for SpecialName {
Expand Down Expand Up @@ -7393,6 +7397,26 @@ impl Parse for SpecialName {
};
Ok((SpecialName::GuardTemporary(name, idx), tail))
}
b"Gr" => {
let (resource_name_len, tail) = parse_number(10, false, tail)?;
if resource_name_len == 0 {
return Err(error::Error::UnexpectedText);
}

let (head, tail) = match tail.try_split_at(resource_name_len as _) {
Some((head, tail)) => (head, tail),
None => return Err(error::Error::UnexpectedEnd),
};

let head = consume(b"_", head)?;

let (resource_names, empty) = zero_or_more::<ResourceName>(ctx, subs, head)?;
if !empty.is_empty() {
return Err(error::Error::UnexpectedText);
}

Ok((SpecialName::JavaResource(resource_names), tail))
}
_ => Err(error::Error::UnexpectedText),
}
}
Expand Down Expand Up @@ -7480,10 +7504,100 @@ where
write!(ctx, "TLS wrapper function for ")?;
name.demangle(ctx, scope)
}
SpecialName::JavaResource(ref names) => {
write!(ctx, "java resource ")?;
for name in names {
name.demangle(ctx, scope)?;
}
Ok(())
}
}
}
}

/// The `<resource name>` pseudo-terminal.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResourceName {
start: usize,
end: usize,
}

impl Parse for ResourceName {
fn parse<'a, 'b>(
ctx: &'a ParseContext,
_subs: &'a mut SubstitutionTable,
input: IndexStr<'b>,
) -> Result<(ResourceName, IndexStr<'b>)> {
try_begin_parse!("ResourceName", ctx, input);

if input.is_empty() {
return Err(error::Error::UnexpectedEnd);
}

let mut end = input
.as_ref()
.iter()
.map(|&c| c as char)
.take_while(|&c| c != '$' || c.is_digit(36))
.count();

if end == 0 {
return Err(error::Error::UnexpectedText);
}

if input.range_from(end..).peek() == Some(b'$') {
match input.range_from(end..).peek_second() {
Some(b'S') | Some(b'_') | Some(b'$') => end += 2,
_ => return Err(error::Error::UnexpectedText)
}
}

let tail = input.range_from(end..);

let resource_name = ResourceName {
start: input.index(),
end: tail.index(),
};

Ok((resource_name, tail))
}
}

impl<'subs, W> Demangle<'subs, W> for ResourceName
where
W: 'subs + DemangleWrite,
{
#[inline]
fn demangle<'prev, 'ctx>(
&'subs self,
ctx: &'ctx mut DemangleContext<'subs, W>,
scope: Option<ArgScopeStack<'prev, 'subs>>,
) -> fmt::Result {
let ctx = try_begin_demangle!(self, ctx, scope);

let mut i = self.start;
while i < self.end {
let ch = ctx.input[i];
if ch == b'$' {
// Skip past the '$'
i += 1;
match ctx.input[i] {
b'S' => write!(ctx, "{}", '/')?,
b'_' => write!(ctx, "{}", '.')?,
b'$' => write!(ctx, "{}", '$')?,
_ => {
// Fall through
},
}
} else {
write!(ctx, "{}", ch as char)?;
}
i += 1;
}

Ok(())
}
}
/// Expect and consume the given byte str, and return the advanced `IndexStr` if
/// we saw the expectation. Otherwise return an error of kind
/// `error::Error::UnexpectedText` if the input doesn't match, or
Expand Down Expand Up @@ -7598,7 +7712,7 @@ mod tests {
FunctionParam, FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig,
LocalName, MangledName, MemberName, Name, NestedName, NonSubstitution, Number,
NvOffset, OperatorName, Parse, ParseContext, PointerToMemberType, Prefix,
PrefixHandle, RefQualifier, SeqId, SimpleId, SimpleOperatorName, SourceName,
PrefixHandle, RefQualifier, ResourceName, SeqId, SimpleId, SimpleOperatorName, SourceName,
SpecialName, StandardBuiltinType, Substitution, TaggedName, TemplateArg,
TemplateArgs, TemplateParam, TemplateTemplateParam, TemplateTemplateParamHandle,
Type, TypeHandle, UnnamedTypeName, UnqualifiedName, UnresolvedName,
Expand Down Expand Up @@ -10398,6 +10512,13 @@ mod tests {
1),
b"..."
}
b"Gr4_abc..." => {
SpecialName::JavaResource(vec![ResourceName {
start: 4,
end: 7,
}]),
b"..."
}
b"TCc7_i..." => {
SpecialName::ConstructionVtable(
TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
Expand Down Expand Up @@ -10440,6 +10561,7 @@ mod tests {
b"GR3abc0" => Error::UnexpectedEnd,
// This number is not allowed to be negative.
b"TCcn7_i..." => Error::UnexpectedText,
b"Gr3abc0" => Error::UnexpectedText,
}
});
}
Expand Down

0 comments on commit 1e51bce

Please sign in to comment.