diff options
author | Christopher Ferris <cferris@google.com> | 2016-03-16 12:17:59 -0700 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2016-05-31 13:21:55 -0700 |
commit | d50f287b81011f6a6cb9091a0a9c75f6bbc19966 (patch) | |
tree | 70eb4179ca7fcc84c95864d1df0c19405af948d9 | |
parent | 6d99fa2661637d43f9e42a95fcab135c98727fc9 (diff) | |
download | development-d50f287b81011f6a6cb9091a0a9c75f6bbc19966.tar.gz |
Fix how the script gets data from apks.
The previous code used unzip to get the offsets of the files in
the zip file. This was an estimate, and it turns out to be wrong
in many cases. Replace that with zipinfo -v which gives the exact
offset of the files in the zip.
Also update the tmp files so that they are in a dictionary of their
own by apk, instead of embedded in the offset list.
Bug: 29050779
(cherry picked from commit abe22f46161224559078da804c00d2859221f325)
Change-Id: I4e33704c5b26cd238ff7e316bca9de729480c59c
-rwxr-xr-x | scripts/stack_core.py | 75 |
1 files changed, 49 insertions, 26 deletions
diff --git a/scripts/stack_core.py b/scripts/stack_core.py index a62afd923..d29acbfa5 100755 --- a/scripts/stack_core.py +++ b/scripts/stack_core.py @@ -43,7 +43,10 @@ class TraceConverter: sanitizer_trace_line = re.compile("$a") value_line = re.compile("$a") code_line = re.compile("$a") - unzip_line = re.compile("\s*(\d+)\s+\S+\s+\S+\s+(\S+)") + zipinfo_central_directory_line = re.compile("Central\s+directory\s+entry") + zipinfo_central_info_match = re.compile( + "^\s*(\S+)$\s*offset of local header from start of archive:\s*(\d+)" + ".*^\s*compressed size:\s+(\d+)", re.M | re.S) trace_lines = [] value_lines = [] last_frame = -1 @@ -163,10 +166,9 @@ class TraceConverter: print "-----------------------------------------------------\n" def DeleteApkTmpFiles(self): - for _, offset_list in self.apk_info.values(): - for _, _, tmp_file in offset_list: - if tmp_file: - os.unlink(tmp_file) + for _, _, tmp_files in self.apk_info.values(): + for tmp_file in tmp_files.values(): + os.unlink(tmp_file) def ConvertTrace(self, lines): lines = map(self.CleanLine, lines) @@ -216,20 +218,31 @@ class TraceConverter: os.unlink(tmp_file) return None + def ProcessCentralInfo(self, offset_list, central_info): + match = self.zipinfo_central_info_match.search(central_info) + if not match: + raise Exception("Cannot find all info from zipinfo\n" + central_info) + name = match.group(1) + start = int(match.group(2)) + end = start + int(match.group(3)) + + offset_list.append([name, start, end]) + return name, start, end + def GetLibFromApk(self, apk, offset): # Convert the string to hex. offset = int(offset, 16) # Check if we already have information about this offset. if apk in self.apk_info: - apk_full_path, offset_list = self.apk_info[apk] - for current_offset, file_name, tmp_file in offset_list: - if offset <= current_offset: - if tmp_file: - return file_name, tmp_file - # This modifies the value in offset_list. + apk_full_path, offset_list, tmp_files = self.apk_info[apk] + for file_name, start, end in offset_list: + if offset >= start and offset < end: + if file_name in tmp_files: + return file_name, tmp_files[file_name] tmp_file = self.ExtractLibFromApk(apk_full_path, file_name) if tmp_file: + tmp_files[file_name] = tmp_file return file_name, tmp_file break return None, None @@ -249,28 +262,38 @@ class TraceConverter: print "Cannot find apk " + apk; return None, None - cmd = subprocess.Popen(["unzip", "-lqq", apk_full_path], stdout=subprocess.PIPE) - current_offset = 0 - file_entry = None + cmd = subprocess.Popen(["zipinfo", "-v", apk_full_path], stdout=subprocess.PIPE) + # Find the first central info marker. + for line in cmd.stdout: + if self.zipinfo_central_directory_line.search(line): + break + + central_info = "" + file_name = None offset_list = [] for line in cmd.stdout: - match = self.unzip_line.match(line) + match = self.zipinfo_central_directory_line.search(line) if match: - # Round the size up to a page boundary. - current_offset += (int(match.group(1), 10) + 0x1000) & ~0xfff - offset_entry = [current_offset - 1, match.group(2), None] - offset_list.append(offset_entry) - if offset < current_offset and not file_entry: - file_entry = offset_entry + cur_name, start, end = self.ProcessCentralInfo(offset_list, central_info) + if not file_name and offset >= start and offset < end: + file_name = cur_name + central_info = "" + else: + central_info += line + if central_info: + cur_name, start, end = self.ProcessCentralInfo(offset_list, central_info) + if not file_name and offset >= start and offset < end: + file_name = cur_name # Save the information from the zip. - self.apk_info[apk] = [apk_full_path, offset_list] - if not file_entry: + tmp_files = dict() + self.apk_info[apk] = [apk_full_path, offset_list, tmp_files] + if not file_name: return None, None - tmp_shared_lib = self.ExtractLibFromApk(apk_full_path, file_entry[1]) + tmp_shared_lib = self.ExtractLibFromApk(apk_full_path, file_name) if tmp_shared_lib: - file_entry[2] = tmp_shared_lib - return file_entry[1], file_entry[2] + tmp_files[file_name] = tmp_shared_lib + return file_name, tmp_shared_lib return None, None def ProcessLine(self, line): |