Merge "Fix how the script gets data from apks."
diff --git a/scripts/stack_core.py b/scripts/stack_core.py
index a62afd9..d29acbf 100755
--- a/scripts/stack_core.py
+++ b/scripts/stack_core.py
@@ -43,7 +43,10 @@
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 @@
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 @@
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 @@
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):