xref: /aosp_15_r20/system/extras/pinner/meminspect.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker #include "meminspect.h"
2*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
3*288bf522SAndroid Build Coastguard Worker #include "ziparchive/zip_archive.h"
4*288bf522SAndroid Build Coastguard Worker 
5*288bf522SAndroid Build Coastguard Worker using namespace std;
6*288bf522SAndroid Build Coastguard Worker using namespace android::base;
7*288bf522SAndroid Build Coastguard Worker using namespace ::android::base;
8*288bf522SAndroid Build Coastguard Worker 
9*288bf522SAndroid Build Coastguard Worker const static VmaRange VMA_RANGE_EMPTY = VmaRange(0, 0);
10*288bf522SAndroid Build Coastguard Worker 
end_offset() const11*288bf522SAndroid Build Coastguard Worker uint32_t VmaRange::end_offset() const {
12*288bf522SAndroid Build Coastguard Worker     return offset + length;
13*288bf522SAndroid Build Coastguard Worker }
14*288bf522SAndroid Build Coastguard Worker 
compute_total_size()15*288bf522SAndroid Build Coastguard Worker uint64_t VmaRangeGroup::compute_total_size() {
16*288bf522SAndroid Build Coastguard Worker     uint64_t total_size = 0;
17*288bf522SAndroid Build Coastguard Worker     for (auto&& range : ranges) {
18*288bf522SAndroid Build Coastguard Worker         total_size += range.length;
19*288bf522SAndroid Build Coastguard Worker     }
20*288bf522SAndroid Build Coastguard Worker     return total_size;
21*288bf522SAndroid Build Coastguard Worker }
22*288bf522SAndroid Build Coastguard Worker 
apply_offset(uint64_t offset)23*288bf522SAndroid Build Coastguard Worker void VmaRangeGroup::apply_offset(uint64_t offset) {
24*288bf522SAndroid Build Coastguard Worker     for (auto&& range : ranges) {
25*288bf522SAndroid Build Coastguard Worker         range.offset += offset;
26*288bf522SAndroid Build Coastguard Worker     }
27*288bf522SAndroid Build Coastguard Worker }
28*288bf522SAndroid Build Coastguard Worker 
compute_coverage(const VmaRange & range,VmaRangeGroup & out_memres) const29*288bf522SAndroid Build Coastguard Worker void VmaRangeGroup::compute_coverage(const VmaRange& range, VmaRangeGroup& out_memres) const {
30*288bf522SAndroid Build Coastguard Worker     for (auto&& resident_range : ranges) {
31*288bf522SAndroid Build Coastguard Worker         VmaRange intersect_res = resident_range.intersect(range);
32*288bf522SAndroid Build Coastguard Worker         if (!intersect_res.is_empty()) {
33*288bf522SAndroid Build Coastguard Worker             out_memres.ranges.push_back(intersect_res);
34*288bf522SAndroid Build Coastguard Worker         }
35*288bf522SAndroid Build Coastguard Worker     }
36*288bf522SAndroid Build Coastguard Worker }
37*288bf522SAndroid Build Coastguard Worker 
is_empty() const38*288bf522SAndroid Build Coastguard Worker bool VmaRange::is_empty() const {
39*288bf522SAndroid Build Coastguard Worker     return length == 0;
40*288bf522SAndroid Build Coastguard Worker }
41*288bf522SAndroid Build Coastguard Worker 
intersect(const VmaRange & target) const42*288bf522SAndroid Build Coastguard Worker VmaRange VmaRange::intersect(const VmaRange& target) const {
43*288bf522SAndroid Build Coastguard Worker     // First check if the slice is outside our range
44*288bf522SAndroid Build Coastguard Worker     if (target.end_offset() <= this->offset) {
45*288bf522SAndroid Build Coastguard Worker         return VMA_RANGE_EMPTY;
46*288bf522SAndroid Build Coastguard Worker     }
47*288bf522SAndroid Build Coastguard Worker     if (target.offset >= this->end_offset()) {
48*288bf522SAndroid Build Coastguard Worker         return VMA_RANGE_EMPTY;
49*288bf522SAndroid Build Coastguard Worker     }
50*288bf522SAndroid Build Coastguard Worker     VmaRange result;
51*288bf522SAndroid Build Coastguard Worker     // the slice should now be inside the range so compute the intersection.
52*288bf522SAndroid Build Coastguard Worker     result.offset = std::max(target.offset, this->offset);
53*288bf522SAndroid Build Coastguard Worker     uint32_t res_end = std::min(target.end_offset(), end_offset());
54*288bf522SAndroid Build Coastguard Worker     result.length = res_end - result.offset;
55*288bf522SAndroid Build Coastguard Worker 
56*288bf522SAndroid Build Coastguard Worker     return result;
57*288bf522SAndroid Build Coastguard Worker }
58*288bf522SAndroid Build Coastguard Worker 
union_merge(const VmaRange & target) const59*288bf522SAndroid Build Coastguard Worker VmaRange VmaRange::union_merge(const VmaRange& target) const {
60*288bf522SAndroid Build Coastguard Worker     VmaRange result = intersect(target);
61*288bf522SAndroid Build Coastguard Worker     if (result.is_empty()) {
62*288bf522SAndroid Build Coastguard Worker         // Disjointed ranges, no merge.
63*288bf522SAndroid Build Coastguard Worker         return VMA_RANGE_EMPTY;
64*288bf522SAndroid Build Coastguard Worker     }
65*288bf522SAndroid Build Coastguard Worker 
66*288bf522SAndroid Build Coastguard Worker     // Since there is an intersection, merge ranges between lowest
67*288bf522SAndroid Build Coastguard Worker     // and highest value.
68*288bf522SAndroid Build Coastguard Worker     result.offset = std::min(offset, target.offset);
69*288bf522SAndroid Build Coastguard Worker     uint32_t res_end = std::max(target.end_offset(), end_offset());
70*288bf522SAndroid Build Coastguard Worker     result.length = res_end - result.offset;
71*288bf522SAndroid Build Coastguard Worker     return result;
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker 
align_ranges(std::vector<VmaRange> & vmas_to_align,unsigned int alignment)74*288bf522SAndroid Build Coastguard Worker void align_ranges(std::vector<VmaRange>& vmas_to_align, unsigned int alignment) {
75*288bf522SAndroid Build Coastguard Worker     for (auto&& vma_to_align : vmas_to_align) {
76*288bf522SAndroid Build Coastguard Worker         uint32_t unaligned_offset = vma_to_align.offset % alignment;
77*288bf522SAndroid Build Coastguard Worker         vma_to_align.offset -= unaligned_offset;
78*288bf522SAndroid Build Coastguard Worker         vma_to_align.length += unaligned_offset;
79*288bf522SAndroid Build Coastguard Worker     }
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker 
compare_range(VmaRange & a,VmaRange & b)82*288bf522SAndroid Build Coastguard Worker bool compare_range(VmaRange& a, VmaRange& b) {
83*288bf522SAndroid Build Coastguard Worker     return a.offset < b.offset;
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker 
merge_ranges(const std::vector<VmaRange> & ranges)86*288bf522SAndroid Build Coastguard Worker std::vector<VmaRange> merge_ranges(const std::vector<VmaRange>& ranges) {
87*288bf522SAndroid Build Coastguard Worker     if (ranges.size() <= 1) {
88*288bf522SAndroid Build Coastguard Worker         // Not enough ranges to perform a merge.
89*288bf522SAndroid Build Coastguard Worker         return ranges;
90*288bf522SAndroid Build Coastguard Worker     }
91*288bf522SAndroid Build Coastguard Worker 
92*288bf522SAndroid Build Coastguard Worker     std::vector<VmaRange> to_merge_ranges = ranges;
93*288bf522SAndroid Build Coastguard Worker     std::vector<VmaRange> merged_ranges;
94*288bf522SAndroid Build Coastguard Worker     // Sort the ranges to make a slightly more efficient merging.
95*288bf522SAndroid Build Coastguard Worker     std::sort(to_merge_ranges.begin(), to_merge_ranges.end(), compare_range);
96*288bf522SAndroid Build Coastguard Worker 
97*288bf522SAndroid Build Coastguard Worker     // The first element will always start as-is, then start merging with subsequent elements.
98*288bf522SAndroid Build Coastguard Worker     merged_ranges.push_back(to_merge_ranges[0]);
99*288bf522SAndroid Build Coastguard Worker     for (int iMerged = 0, iTarget = 1; iTarget < to_merge_ranges.size(); ++iTarget) {
100*288bf522SAndroid Build Coastguard Worker         VmaRange merged = merged_ranges[iMerged].union_merge(to_merge_ranges[iTarget]);
101*288bf522SAndroid Build Coastguard Worker         if (!merged.is_empty()) {
102*288bf522SAndroid Build Coastguard Worker             // Merge was successful, swallow range.
103*288bf522SAndroid Build Coastguard Worker             merged_ranges[iMerged] = merged;
104*288bf522SAndroid Build Coastguard Worker         } else {
105*288bf522SAndroid Build Coastguard Worker             // Merge failed, add disjointed range.
106*288bf522SAndroid Build Coastguard Worker             merged_ranges.push_back(to_merge_ranges[iTarget]);
107*288bf522SAndroid Build Coastguard Worker             ++iMerged;
108*288bf522SAndroid Build Coastguard Worker         }
109*288bf522SAndroid Build Coastguard Worker     }
110*288bf522SAndroid Build Coastguard Worker 
111*288bf522SAndroid Build Coastguard Worker     return merged_ranges;
112*288bf522SAndroid Build Coastguard Worker }
113*288bf522SAndroid Build Coastguard Worker 
get_file_size(const std::string & file)114*288bf522SAndroid Build Coastguard Worker int64_t get_file_size(const std::string& file) {
115*288bf522SAndroid Build Coastguard Worker     unique_fd file_ufd(open(file.c_str(), O_RDONLY));
116*288bf522SAndroid Build Coastguard Worker     int fd = file_ufd.get();
117*288bf522SAndroid Build Coastguard Worker     if (fd == -1) {
118*288bf522SAndroid Build Coastguard Worker         return -1;
119*288bf522SAndroid Build Coastguard Worker     }
120*288bf522SAndroid Build Coastguard Worker 
121*288bf522SAndroid Build Coastguard Worker     struct stat fstat_res;
122*288bf522SAndroid Build Coastguard Worker     int res = fstat(fd, &fstat_res);
123*288bf522SAndroid Build Coastguard Worker     if (res == -1) {
124*288bf522SAndroid Build Coastguard Worker         return -1;
125*288bf522SAndroid Build Coastguard Worker     }
126*288bf522SAndroid Build Coastguard Worker 
127*288bf522SAndroid Build Coastguard Worker     return fstat_res.st_size;
128*288bf522SAndroid Build Coastguard Worker }
129*288bf522SAndroid Build Coastguard Worker 
probe_resident_memory(string probed_file,VmaRangeGroup & resident_ranges,int pages_per_mincore)130*288bf522SAndroid Build Coastguard Worker int probe_resident_memory(string probed_file,
131*288bf522SAndroid Build Coastguard Worker                           /*out*/ VmaRangeGroup& resident_ranges, int pages_per_mincore) {
132*288bf522SAndroid Build Coastguard Worker     unique_fd probed_file_ufd(open(probed_file.c_str(), O_RDONLY));
133*288bf522SAndroid Build Coastguard Worker     int probe_fd = probed_file_ufd.get();
134*288bf522SAndroid Build Coastguard Worker     if (probe_fd == -1) {
135*288bf522SAndroid Build Coastguard Worker         return MEMINSPECT_FAIL_OPEN;
136*288bf522SAndroid Build Coastguard Worker     }
137*288bf522SAndroid Build Coastguard Worker 
138*288bf522SAndroid Build Coastguard Worker     int64_t total_bytes = get_file_size(probed_file);
139*288bf522SAndroid Build Coastguard Worker     if (total_bytes < 0) {
140*288bf522SAndroid Build Coastguard Worker         return MEMINSPECT_FAIL_FSTAT;
141*288bf522SAndroid Build Coastguard Worker     }
142*288bf522SAndroid Build Coastguard Worker 
143*288bf522SAndroid Build Coastguard Worker     char* base_address =
144*288bf522SAndroid Build Coastguard Worker             (char*)mmap(0, (uint64_t)total_bytes, PROT_READ, MAP_SHARED, probe_fd, /*offset*/ 0);
145*288bf522SAndroid Build Coastguard Worker 
146*288bf522SAndroid Build Coastguard Worker     // this determines how many pages to inspect per mincore syscall
147*288bf522SAndroid Build Coastguard Worker     unsigned char* window = new unsigned char[pages_per_mincore];
148*288bf522SAndroid Build Coastguard Worker 
149*288bf522SAndroid Build Coastguard Worker     unsigned int page_size = sysconf(_SC_PAGESIZE);
150*288bf522SAndroid Build Coastguard Worker     unsigned long bytes_inspected = 0;
151*288bf522SAndroid Build Coastguard Worker 
152*288bf522SAndroid Build Coastguard Worker     // total bytes in inspection window
153*288bf522SAndroid Build Coastguard Worker     unsigned long window_bytes = page_size * pages_per_mincore;
154*288bf522SAndroid Build Coastguard Worker 
155*288bf522SAndroid Build Coastguard Worker     char* window_base;
156*288bf522SAndroid Build Coastguard Worker     bool started_vma_range = false;
157*288bf522SAndroid Build Coastguard Worker     uint32_t resident_vma_start_offset = 0;
158*288bf522SAndroid Build Coastguard Worker     for (window_base = base_address; bytes_inspected < total_bytes;
159*288bf522SAndroid Build Coastguard Worker          window_base += window_bytes, bytes_inspected += window_bytes) {
160*288bf522SAndroid Build Coastguard Worker         int res = mincore(window_base, window_bytes, window);
161*288bf522SAndroid Build Coastguard Worker         if (res != 0) {
162*288bf522SAndroid Build Coastguard Worker             if (errno == ENOMEM) {
163*288bf522SAndroid Build Coastguard Worker                 // Did not find page, maybe it's a hole.
164*288bf522SAndroid Build Coastguard Worker                 continue;
165*288bf522SAndroid Build Coastguard Worker             }
166*288bf522SAndroid Build Coastguard Worker             return MEMINSPECT_FAIL_MINCORE;
167*288bf522SAndroid Build Coastguard Worker         }
168*288bf522SAndroid Build Coastguard Worker         // Inspect the provided mincore window result sequentially
169*288bf522SAndroid Build Coastguard Worker         // and as soon as a change in residency happens a range is
170*288bf522SAndroid Build Coastguard Worker         // created or finished.
171*288bf522SAndroid Build Coastguard Worker         for (int iWin = 0; iWin < pages_per_mincore; ++iWin) {
172*288bf522SAndroid Build Coastguard Worker             if ((window[iWin] & (unsigned char)1) != 0) {
173*288bf522SAndroid Build Coastguard Worker                 // Page is resident
174*288bf522SAndroid Build Coastguard Worker                 if (!started_vma_range) {
175*288bf522SAndroid Build Coastguard Worker                     // End of range
176*288bf522SAndroid Build Coastguard Worker                     started_vma_range = true;
177*288bf522SAndroid Build Coastguard Worker                     uint32_t window_offset = iWin * page_size;
178*288bf522SAndroid Build Coastguard Worker                     resident_vma_start_offset = window_base + window_offset - base_address;
179*288bf522SAndroid Build Coastguard Worker                 }
180*288bf522SAndroid Build Coastguard Worker             } else {
181*288bf522SAndroid Build Coastguard Worker                 // Page is not resident
182*288bf522SAndroid Build Coastguard Worker                 if (started_vma_range) {
183*288bf522SAndroid Build Coastguard Worker                     // Start of range
184*288bf522SAndroid Build Coastguard Worker                     started_vma_range = false;
185*288bf522SAndroid Build Coastguard Worker                     uint32_t window_offset = iWin * page_size;
186*288bf522SAndroid Build Coastguard Worker                     uint32_t resident_vma_end_offset = window_base + window_offset - base_address;
187*288bf522SAndroid Build Coastguard Worker                     uint32_t resident_len = resident_vma_end_offset - resident_vma_start_offset;
188*288bf522SAndroid Build Coastguard Worker                     VmaRange vma_range(resident_vma_start_offset, resident_len);
189*288bf522SAndroid Build Coastguard Worker                     resident_ranges.ranges.push_back(vma_range);
190*288bf522SAndroid Build Coastguard Worker                 }
191*288bf522SAndroid Build Coastguard Worker             }
192*288bf522SAndroid Build Coastguard Worker         }
193*288bf522SAndroid Build Coastguard Worker     }
194*288bf522SAndroid Build Coastguard Worker     // This was the last window, so close any opened vma range
195*288bf522SAndroid Build Coastguard Worker     if (started_vma_range) {
196*288bf522SAndroid Build Coastguard Worker         started_vma_range = false;
197*288bf522SAndroid Build Coastguard Worker         uint32_t in_memory_vma_end = window_base - base_address;
198*288bf522SAndroid Build Coastguard Worker         uint32_t resident_len = in_memory_vma_end - resident_vma_start_offset;
199*288bf522SAndroid Build Coastguard Worker         VmaRange vma_range(resident_vma_start_offset, resident_len);
200*288bf522SAndroid Build Coastguard Worker         resident_ranges.ranges.push_back(vma_range);
201*288bf522SAndroid Build Coastguard Worker     }
202*288bf522SAndroid Build Coastguard Worker 
203*288bf522SAndroid Build Coastguard Worker     return 0;
204*288bf522SAndroid Build Coastguard Worker }
205*288bf522SAndroid Build Coastguard Worker 
~ZipMemInspector()206*288bf522SAndroid Build Coastguard Worker ZipMemInspector::~ZipMemInspector() {
207*288bf522SAndroid Build Coastguard Worker     CloseArchive(handle_);
208*288bf522SAndroid Build Coastguard Worker     delete probe_resident_;
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker 
compute_coverage(const VmaRangeGroup & probe) const211*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage ZipEntryCoverage::compute_coverage(const VmaRangeGroup& probe) const {
212*288bf522SAndroid Build Coastguard Worker     ZipEntryCoverage file_coverage;
213*288bf522SAndroid Build Coastguard Worker     file_coverage.info = info;
214*288bf522SAndroid Build Coastguard Worker 
215*288bf522SAndroid Build Coastguard Worker     // Compute coverage for each range in file against probe which represents a set of ranges.
216*288bf522SAndroid Build Coastguard Worker     for (auto&& range : coverage.ranges) {
217*288bf522SAndroid Build Coastguard Worker         probe.compute_coverage(range, file_coverage.coverage);
218*288bf522SAndroid Build Coastguard Worker     }
219*288bf522SAndroid Build Coastguard Worker 
220*288bf522SAndroid Build Coastguard Worker     return file_coverage;
221*288bf522SAndroid Build Coastguard Worker }
222*288bf522SAndroid Build Coastguard Worker 
compute_coverage(const std::vector<ZipEntryCoverage> & files,VmaRangeGroup * probe)223*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage> ZipMemInspector::compute_coverage(
224*288bf522SAndroid Build Coastguard Worker         const std::vector<ZipEntryCoverage>& files, VmaRangeGroup* probe) {
225*288bf522SAndroid Build Coastguard Worker     if (probe == nullptr) {
226*288bf522SAndroid Build Coastguard Worker         // No probe to calculate coverage against, so coverage is zero.
227*288bf522SAndroid Build Coastguard Worker         return std::vector<ZipEntryCoverage>();
228*288bf522SAndroid Build Coastguard Worker     }
229*288bf522SAndroid Build Coastguard Worker 
230*288bf522SAndroid Build Coastguard Worker     std::vector<ZipEntryCoverage> file_coverages;
231*288bf522SAndroid Build Coastguard Worker     // Find the file coverage against provided probe.
232*288bf522SAndroid Build Coastguard Worker     for (auto&& file : files) {
233*288bf522SAndroid Build Coastguard Worker         // For each file, compute coverage against the probe which represents a list of ranges.
234*288bf522SAndroid Build Coastguard Worker         ZipEntryCoverage file_coverage = file.compute_coverage(*probe);
235*288bf522SAndroid Build Coastguard Worker         file_coverages.push_back(file_coverage);
236*288bf522SAndroid Build Coastguard Worker     }
237*288bf522SAndroid Build Coastguard Worker 
238*288bf522SAndroid Build Coastguard Worker     return file_coverages;
239*288bf522SAndroid Build Coastguard Worker }
240*288bf522SAndroid Build Coastguard Worker 
add_file_info(ZipEntryInfo & file)241*288bf522SAndroid Build Coastguard Worker void ZipMemInspector::add_file_info(ZipEntryInfo& file) {
242*288bf522SAndroid Build Coastguard Worker     entry_infos_.push_back(file);
243*288bf522SAndroid Build Coastguard Worker }
244*288bf522SAndroid Build Coastguard Worker 
compute_per_file_coverage()245*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::compute_per_file_coverage() {
246*288bf522SAndroid Build Coastguard Worker     if (entry_infos_.empty()) {
247*288bf522SAndroid Build Coastguard Worker         // We haven't read the file information yet, so do it now.
248*288bf522SAndroid Build Coastguard Worker         if (read_files_and_offsets()) {
249*288bf522SAndroid Build Coastguard Worker             cerr << "Could not read zip entries to compute coverages." << endl;
250*288bf522SAndroid Build Coastguard Worker             return 1;
251*288bf522SAndroid Build Coastguard Worker         }
252*288bf522SAndroid Build Coastguard Worker     }
253*288bf522SAndroid Build Coastguard Worker 
254*288bf522SAndroid Build Coastguard Worker     // All existing files should consider their whole memory as present by default.
255*288bf522SAndroid Build Coastguard Worker     std::vector<ZipEntryCoverage> entry_coverages;
256*288bf522SAndroid Build Coastguard Worker     for (auto&& entry_info : entry_infos_) {
257*288bf522SAndroid Build Coastguard Worker         ZipEntryCoverage entry_coverage;
258*288bf522SAndroid Build Coastguard Worker         entry_coverage.info = entry_info;
259*288bf522SAndroid Build Coastguard Worker         VmaRange file_vma_range(entry_info.offset_in_zip, entry_info.file_size_bytes);
260*288bf522SAndroid Build Coastguard Worker         entry_coverage.coverage.ranges.push_back(file_vma_range);
261*288bf522SAndroid Build Coastguard Worker         entry_coverage.coverage.compute_total_size();
262*288bf522SAndroid Build Coastguard Worker         entry_coverages.push_back(entry_coverage);
263*288bf522SAndroid Build Coastguard Worker     }
264*288bf522SAndroid Build Coastguard Worker 
265*288bf522SAndroid Build Coastguard Worker     if (probe_resident_ != nullptr) {
266*288bf522SAndroid Build Coastguard Worker         // We decided to compute coverage based on a probe
267*288bf522SAndroid Build Coastguard Worker         entry_coverages_ = compute_coverage(entry_coverages, probe_resident_);
268*288bf522SAndroid Build Coastguard Worker     } else {
269*288bf522SAndroid Build Coastguard Worker         // No probe means whole file coverage
270*288bf522SAndroid Build Coastguard Worker         entry_coverages_ = entry_coverages;
271*288bf522SAndroid Build Coastguard Worker     }
272*288bf522SAndroid Build Coastguard Worker 
273*288bf522SAndroid Build Coastguard Worker     return 0;
274*288bf522SAndroid Build Coastguard Worker }
275*288bf522SAndroid Build Coastguard Worker 
get_probe()276*288bf522SAndroid Build Coastguard Worker VmaRangeGroup* ZipMemInspector::get_probe() {
277*288bf522SAndroid Build Coastguard Worker     return probe_resident_;
278*288bf522SAndroid Build Coastguard Worker }
279*288bf522SAndroid Build Coastguard Worker 
set_existing_probe(VmaRangeGroup * probe)280*288bf522SAndroid Build Coastguard Worker void ZipMemInspector::set_existing_probe(VmaRangeGroup* probe) {
281*288bf522SAndroid Build Coastguard Worker     this->probe_resident_ = probe;
282*288bf522SAndroid Build Coastguard Worker }
283*288bf522SAndroid Build Coastguard Worker 
get_file_coverages()284*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage>& ZipMemInspector::get_file_coverages() {
285*288bf522SAndroid Build Coastguard Worker     return entry_coverages_;
286*288bf522SAndroid Build Coastguard Worker }
287*288bf522SAndroid Build Coastguard Worker 
probe_resident()288*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::probe_resident() {
289*288bf522SAndroid Build Coastguard Worker     probe_resident_ = new VmaRangeGroup();
290*288bf522SAndroid Build Coastguard Worker     int res = probe_resident_memory(filename_, *probe_resident_);
291*288bf522SAndroid Build Coastguard Worker     if (res != 0) {
292*288bf522SAndroid Build Coastguard Worker         // Failed to probe
293*288bf522SAndroid Build Coastguard Worker         return res;
294*288bf522SAndroid Build Coastguard Worker     }
295*288bf522SAndroid Build Coastguard Worker 
296*288bf522SAndroid Build Coastguard Worker     return 0;
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker 
get_file_infos()299*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryInfo>& ZipMemInspector::get_file_infos() {
300*288bf522SAndroid Build Coastguard Worker     return entry_infos_;
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker 
read_files_and_offsets()303*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::read_files_and_offsets() {
304*288bf522SAndroid Build Coastguard Worker     if (OpenArchive(filename_.c_str(), &handle_) < 0) {
305*288bf522SAndroid Build Coastguard Worker         return 1;
306*288bf522SAndroid Build Coastguard Worker     }
307*288bf522SAndroid Build Coastguard Worker     void* cookie;
308*288bf522SAndroid Build Coastguard Worker     int res = StartIteration(handle_, &cookie);
309*288bf522SAndroid Build Coastguard Worker     if (res != 0) {
310*288bf522SAndroid Build Coastguard Worker         return 1;
311*288bf522SAndroid Build Coastguard Worker     }
312*288bf522SAndroid Build Coastguard Worker 
313*288bf522SAndroid Build Coastguard Worker     ZipEntry64 entry;
314*288bf522SAndroid Build Coastguard Worker     string name;
315*288bf522SAndroid Build Coastguard Worker     while (Next(cookie, &entry, &name) == 0) {
316*288bf522SAndroid Build Coastguard Worker         ZipEntryInfo file;
317*288bf522SAndroid Build Coastguard Worker         file.name = name;
318*288bf522SAndroid Build Coastguard Worker         file.offset_in_zip = entry.offset;
319*288bf522SAndroid Build Coastguard Worker         file.file_size_bytes = entry.compressed_length;
320*288bf522SAndroid Build Coastguard Worker         file.uncompressed_size = entry.uncompressed_length;
321*288bf522SAndroid Build Coastguard Worker         entry_infos_.push_back(file);
322*288bf522SAndroid Build Coastguard Worker     }
323*288bf522SAndroid Build Coastguard Worker     return 0;
324*288bf522SAndroid Build Coastguard Worker }
325