| # Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Utilities to restore DEX symbols name from obfuscated names.""" |
| |
| import functools |
| import logging |
| import re |
| |
| _PROGUARD_CLASS_MAPPING_RE = re.compile(r'(?P<original_name>[^ ]+)' |
| r' -> ' |
| r'(?P<obfuscated_name>[^:]+):') |
| |
| |
| def _CreateClassDeobfuscationMap(mapping_line_iter): |
| """Parses .mapping file lines into map to deobfuscate class names.""" |
| mapping = {} |
| for line in mapping_line_iter: |
| # We are on a class name so add it to the class mapping. |
| if not line.startswith(' '): |
| match = _PROGUARD_CLASS_MAPPING_RE.search(line) |
| if match: |
| mapping[match.group('obfuscated_name')] = match.group('original_name') |
| return mapping |
| |
| |
| class CachedDexDeobfuscators: |
| """Computes and caches obfuscators for DEX symbols.""" |
| |
| @functools.lru_cache(None) |
| def GetForMappingFile(self, proguard_mapping_file_path): |
| """Gets a map to deobfuscate class names using .mapping file data. |
| |
| Args: |
| proguard_mapping_file_path: Path to ProGuard .mapping file. |
| |
| Returns: |
| A dict to map obfuscated class names to original names, or empty dict if |
| input was given as None. |
| """ |
| if proguard_mapping_file_path is None: |
| return {} |
| logging.debug('Parsing mapping file %s', proguard_mapping_file_path) |
| with open(proguard_mapping_file_path, 'r') as fh: |
| return _CreateClassDeobfuscationMap(fh) |