xref: /aosp_15_r20/system/extras/pinner/pin_utils.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker #include "pin_utils.h"
2*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
3*288bf522SAndroid Build Coastguard Worker #include <algorithm>
4*288bf522SAndroid Build Coastguard Worker #include <fstream>
5*288bf522SAndroid Build Coastguard Worker #include <map>
6*288bf522SAndroid Build Coastguard Worker #include <string_view>
7*288bf522SAndroid Build Coastguard Worker #include <utility>
8*288bf522SAndroid Build Coastguard Worker #include <vector>
9*288bf522SAndroid Build Coastguard Worker 
10*288bf522SAndroid Build Coastguard Worker using namespace std;
11*288bf522SAndroid Build Coastguard Worker using namespace android::base;
12*288bf522SAndroid Build Coastguard Worker 
write_pinlist_file(const std::string & output_file,const std::vector<ZipEntryCoverage> & files_to_write,int64_t write_quota)13*288bf522SAndroid Build Coastguard Worker int write_pinlist_file(const std::string& output_file,
14*288bf522SAndroid Build Coastguard Worker                        const std::vector<ZipEntryCoverage>& files_to_write, int64_t write_quota) {
15*288bf522SAndroid Build Coastguard Worker     std::vector<VmaRange> ranges;
16*288bf522SAndroid Build Coastguard Worker     for (auto&& file : files_to_write) {
17*288bf522SAndroid Build Coastguard Worker         ranges.insert(ranges.end(), file.coverage.ranges.begin(), file.coverage.ranges.end());
18*288bf522SAndroid Build Coastguard Worker     }
19*288bf522SAndroid Build Coastguard Worker     return write_pinlist_file(output_file, ranges, write_quota);
20*288bf522SAndroid Build Coastguard Worker }
21*288bf522SAndroid Build Coastguard Worker 
write_pinlist_file(const std::string & output_file,const std::vector<VmaRange> & vmas_to_write,int64_t write_quota)22*288bf522SAndroid Build Coastguard Worker int write_pinlist_file(const std::string& output_file, const std::vector<VmaRange>& vmas_to_write,
23*288bf522SAndroid Build Coastguard Worker                        int64_t write_quota) {
24*288bf522SAndroid Build Coastguard Worker     ofstream pinlist_file(output_file);
25*288bf522SAndroid Build Coastguard Worker     if (pinlist_file.fail()) {
26*288bf522SAndroid Build Coastguard Worker         return 1;
27*288bf522SAndroid Build Coastguard Worker     }
28*288bf522SAndroid Build Coastguard Worker     int64_t total_written = 0;
29*288bf522SAndroid Build Coastguard Worker     unsigned int page_size = sysconf(_SC_PAGESIZE);
30*288bf522SAndroid Build Coastguard Worker     const bool has_quota = write_quota > 0;
31*288bf522SAndroid Build Coastguard Worker     bool reached_quota = false;
32*288bf522SAndroid Build Coastguard Worker 
33*288bf522SAndroid Build Coastguard Worker     // The PinnerService does not require aligned offsets, however, aligning
34*288bf522SAndroid Build Coastguard Worker     // allows our summary results to be accurate and avoids over-accounting
35*288bf522SAndroid Build Coastguard Worker     // of pinning in PinnerService.
36*288bf522SAndroid Build Coastguard Worker     std::vector<VmaRange> processed_vmas_to_write = vmas_to_write;
37*288bf522SAndroid Build Coastguard Worker     align_ranges(processed_vmas_to_write, page_size);
38*288bf522SAndroid Build Coastguard Worker 
39*288bf522SAndroid Build Coastguard Worker     // When we page-align the ranges, we may cause overlaps between ranges
40*288bf522SAndroid Build Coastguard Worker     // as we elongate the begin offset to match the page the previous
41*288bf522SAndroid Build Coastguard Worker     // range may end up overlapping the current one.
42*288bf522SAndroid Build Coastguard Worker     processed_vmas_to_write = merge_ranges(processed_vmas_to_write);
43*288bf522SAndroid Build Coastguard Worker 
44*288bf522SAndroid Build Coastguard Worker     for (auto&& processed_vma_to_write : processed_vmas_to_write) {
45*288bf522SAndroid Build Coastguard Worker         uint32_t vma_start_offset = processed_vma_to_write.offset;
46*288bf522SAndroid Build Coastguard Worker         uint32_t vma_length = processed_vma_to_write.length;
47*288bf522SAndroid Build Coastguard Worker         if (has_quota && (total_written + vma_length > write_quota)) {
48*288bf522SAndroid Build Coastguard Worker             // We would go beyond quota, set the maximum allowed write and exit.
49*288bf522SAndroid Build Coastguard Worker             vma_length = write_quota - total_written;
50*288bf522SAndroid Build Coastguard Worker             reached_quota = true;
51*288bf522SAndroid Build Coastguard Worker         }
52*288bf522SAndroid Build Coastguard Worker         // Transform to BigEndian as PinnerService requires that endianness for reading.
53*288bf522SAndroid Build Coastguard Worker         uint32_t vma_start_offset_be = htobe32(vma_start_offset);
54*288bf522SAndroid Build Coastguard Worker         uint32_t vma_length_be = htobe32(vma_length);
55*288bf522SAndroid Build Coastguard Worker         cout << "Pinlist Writing start=" << vma_start_offset << " bytes=" << vma_length << endl;
56*288bf522SAndroid Build Coastguard Worker         pinlist_file.write(reinterpret_cast<char*>(&vma_start_offset_be),
57*288bf522SAndroid Build Coastguard Worker                            sizeof(vma_start_offset_be));
58*288bf522SAndroid Build Coastguard Worker         if (pinlist_file.fail()) {
59*288bf522SAndroid Build Coastguard Worker             return 1;
60*288bf522SAndroid Build Coastguard Worker         }
61*288bf522SAndroid Build Coastguard Worker         pinlist_file.write(reinterpret_cast<char*>(&vma_length_be), sizeof(vma_length_be));
62*288bf522SAndroid Build Coastguard Worker         total_written += vma_length;
63*288bf522SAndroid Build Coastguard Worker         if (pinlist_file.fail()) {
64*288bf522SAndroid Build Coastguard Worker             return 1;
65*288bf522SAndroid Build Coastguard Worker         }
66*288bf522SAndroid Build Coastguard Worker 
67*288bf522SAndroid Build Coastguard Worker         if (reached_quota) {
68*288bf522SAndroid Build Coastguard Worker             break;
69*288bf522SAndroid Build Coastguard Worker         }
70*288bf522SAndroid Build Coastguard Worker     }
71*288bf522SAndroid Build Coastguard Worker     return 0;
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker 
read_pinlist_file(const std::string & pinner_file,std::vector<VmaRange> & pinranges)74*288bf522SAndroid Build Coastguard Worker int read_pinlist_file(const std::string& pinner_file, /*out*/ std::vector<VmaRange>& pinranges) {
75*288bf522SAndroid Build Coastguard Worker     ifstream pinlist_file(pinner_file);
76*288bf522SAndroid Build Coastguard Worker     if (pinlist_file.fail()) {
77*288bf522SAndroid Build Coastguard Worker         return 1;
78*288bf522SAndroid Build Coastguard Worker     }
79*288bf522SAndroid Build Coastguard Worker 
80*288bf522SAndroid Build Coastguard Worker     uint32_t vma_start;
81*288bf522SAndroid Build Coastguard Worker     uint32_t vma_length;
82*288bf522SAndroid Build Coastguard Worker     while (!pinlist_file.eof()) {
83*288bf522SAndroid Build Coastguard Worker         pinlist_file.read(reinterpret_cast<char*>(&vma_start), sizeof(vma_start));
84*288bf522SAndroid Build Coastguard Worker         pinlist_file.read(reinterpret_cast<char*>(&vma_length), sizeof(vma_length));
85*288bf522SAndroid Build Coastguard Worker         if (pinlist_file.fail()) {
86*288bf522SAndroid Build Coastguard Worker             return 1;
87*288bf522SAndroid Build Coastguard Worker         }
88*288bf522SAndroid Build Coastguard Worker         vma_start = betoh32(vma_start);
89*288bf522SAndroid Build Coastguard Worker         vma_length = betoh32(vma_length);
90*288bf522SAndroid Build Coastguard Worker         pinranges.push_back(VmaRange(vma_start, vma_length));
91*288bf522SAndroid Build Coastguard Worker     }
92*288bf522SAndroid Build Coastguard Worker 
93*288bf522SAndroid Build Coastguard Worker     return 0;
94*288bf522SAndroid Build Coastguard Worker }
95*288bf522SAndroid Build Coastguard Worker 
to_zipfilemem(const ZipEntryInfo & info)96*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage PinConfigFile::to_zipfilemem(const ZipEntryInfo& info) {
97*288bf522SAndroid Build Coastguard Worker     ZipEntryCoverage file;
98*288bf522SAndroid Build Coastguard Worker     file.info = info;
99*288bf522SAndroid Build Coastguard Worker 
100*288bf522SAndroid Build Coastguard Worker     if (ranges.empty()) {
101*288bf522SAndroid Build Coastguard Worker         cout << "No ranges found for file " << info.name << " creating entire file range" << endl;
102*288bf522SAndroid Build Coastguard Worker         // Any file coming from pinconfig without explicit
103*288bf522SAndroid Build Coastguard Worker         // ranges will be assumed to be wanted in its entirety
104*288bf522SAndroid Build Coastguard Worker         ranges.push_back(VmaRange(0, info.file_size_bytes));
105*288bf522SAndroid Build Coastguard Worker     }
106*288bf522SAndroid Build Coastguard Worker 
107*288bf522SAndroid Build Coastguard Worker     file.coverage.ranges = ranges;
108*288bf522SAndroid Build Coastguard Worker 
109*288bf522SAndroid Build Coastguard Worker     // Offsets specified in pinconfig file are relative to the file
110*288bf522SAndroid Build Coastguard Worker     // so transform to zip global offsets which are used for coverage
111*288bf522SAndroid Build Coastguard Worker     // computations.
112*288bf522SAndroid Build Coastguard Worker     file.coverage.apply_offset(info.offset_in_zip);
113*288bf522SAndroid Build Coastguard Worker 
114*288bf522SAndroid Build Coastguard Worker     file.coverage.compute_total_size();
115*288bf522SAndroid Build Coastguard Worker     return file;
116*288bf522SAndroid Build Coastguard Worker }
117*288bf522SAndroid Build Coastguard Worker 
parse(std::string config_file,bool verbose)118*288bf522SAndroid Build Coastguard Worker int PinConfig::parse(std::string config_file, bool verbose) {
119*288bf522SAndroid Build Coastguard Worker     ifstream file(config_file);
120*288bf522SAndroid Build Coastguard Worker     string file_in_zip;
121*288bf522SAndroid Build Coastguard Worker     if (verbose) {
122*288bf522SAndroid Build Coastguard Worker         cout << "Parsing file: " << config_file << endl;
123*288bf522SAndroid Build Coastguard Worker     }
124*288bf522SAndroid Build Coastguard Worker     string token;
125*288bf522SAndroid Build Coastguard Worker     file >> token;
126*288bf522SAndroid Build Coastguard Worker     while (!file.eof()) {
127*288bf522SAndroid Build Coastguard Worker         if (token == "file") {
128*288bf522SAndroid Build Coastguard Worker             file >> file_in_zip;
129*288bf522SAndroid Build Coastguard Worker             PinConfigFile pin_config_file;
130*288bf522SAndroid Build Coastguard Worker             pin_config_file.filename = file_in_zip;
131*288bf522SAndroid Build Coastguard Worker             file >> token;
132*288bf522SAndroid Build Coastguard Worker             while (token != "file" && !file.eof()) {
133*288bf522SAndroid Build Coastguard Worker                 VmaRange range;
134*288bf522SAndroid Build Coastguard Worker                 // Inner parsing loop for per file config.
135*288bf522SAndroid Build Coastguard Worker                 if (token == "offset") {
136*288bf522SAndroid Build Coastguard Worker                     file >> token;
137*288bf522SAndroid Build Coastguard Worker                     android::base::ParseUint(token, &range.offset);
138*288bf522SAndroid Build Coastguard Worker                     file >> token;
139*288bf522SAndroid Build Coastguard Worker                     if (token != "len") {
140*288bf522SAndroid Build Coastguard Worker                         cerr << "Malformed file, expected 'len' after offset" << endl;
141*288bf522SAndroid Build Coastguard Worker                         return 1;
142*288bf522SAndroid Build Coastguard Worker                     }
143*288bf522SAndroid Build Coastguard Worker                     file >> token;
144*288bf522SAndroid Build Coastguard Worker                     android::base::ParseUint(token, &range.length);
145*288bf522SAndroid Build Coastguard Worker                     pin_config_file.ranges.push_back(range);
146*288bf522SAndroid Build Coastguard Worker                 }
147*288bf522SAndroid Build Coastguard Worker                 file >> token;
148*288bf522SAndroid Build Coastguard Worker             }
149*288bf522SAndroid Build Coastguard Worker             files_.push_back(pin_config_file);
150*288bf522SAndroid Build Coastguard Worker         } else {
151*288bf522SAndroid Build Coastguard Worker             cerr << "Unexpected token: " << token << ". Exit read" << endl;
152*288bf522SAndroid Build Coastguard Worker             return 1;
153*288bf522SAndroid Build Coastguard Worker         }
154*288bf522SAndroid Build Coastguard Worker     }
155*288bf522SAndroid Build Coastguard Worker 
156*288bf522SAndroid Build Coastguard Worker     if (files_.empty()) {
157*288bf522SAndroid Build Coastguard Worker         cerr << "Failed parsing pinconfig file, no entries found." << endl;
158*288bf522SAndroid Build Coastguard Worker         return 1;
159*288bf522SAndroid Build Coastguard Worker     }
160*288bf522SAndroid Build Coastguard Worker 
161*288bf522SAndroid Build Coastguard Worker     if (verbose) {
162*288bf522SAndroid Build Coastguard Worker         cout << "Finished parsing Pinconfig file" << endl;
163*288bf522SAndroid Build Coastguard Worker         for (auto&& pin_file : files_) {
164*288bf522SAndroid Build Coastguard Worker             cout << "file=" << pin_file.filename << endl;
165*288bf522SAndroid Build Coastguard Worker             for (auto&& range : pin_file.ranges) {
166*288bf522SAndroid Build Coastguard Worker                 cout << "offset=" << range.offset << " bytes=" << range.length << endl;
167*288bf522SAndroid Build Coastguard Worker             }
168*288bf522SAndroid Build Coastguard Worker         }
169*288bf522SAndroid Build Coastguard Worker     }
170*288bf522SAndroid Build Coastguard Worker 
171*288bf522SAndroid Build Coastguard Worker     return 0;
172*288bf522SAndroid Build Coastguard Worker }
173*288bf522SAndroid Build Coastguard Worker 
set_custom_zip_inspector(ZipMemInspector * inspector)174*288bf522SAndroid Build Coastguard Worker void PinTool::set_custom_zip_inspector(ZipMemInspector* inspector) {
175*288bf522SAndroid Build Coastguard Worker     delete zip_inspector_;
176*288bf522SAndroid Build Coastguard Worker     zip_inspector_ = inspector;
177*288bf522SAndroid Build Coastguard Worker }
178*288bf522SAndroid Build Coastguard Worker 
set_verbose_output(bool verbose)179*288bf522SAndroid Build Coastguard Worker void PinTool::set_verbose_output(bool verbose) {
180*288bf522SAndroid Build Coastguard Worker     verbose_ = verbose;
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker 
read_probe_from_pinlist(std::string custom_probe_file)183*288bf522SAndroid Build Coastguard Worker void PinTool::read_probe_from_pinlist(std::string custom_probe_file) {
184*288bf522SAndroid Build Coastguard Worker     custom_probe_file_ = custom_probe_file;
185*288bf522SAndroid Build Coastguard Worker     VmaRangeGroup* custom_probe = new VmaRangeGroup();
186*288bf522SAndroid Build Coastguard Worker     read_pinlist_file(custom_probe_file_, custom_probe->ranges);
187*288bf522SAndroid Build Coastguard Worker     custom_probe->compute_total_size();
188*288bf522SAndroid Build Coastguard Worker     if (custom_probe->ranges.empty()) {
189*288bf522SAndroid Build Coastguard Worker         cerr << "Did not find any memory range in " << custom_probe_file_ << endl;
190*288bf522SAndroid Build Coastguard Worker         delete custom_probe;
191*288bf522SAndroid Build Coastguard Worker         return;
192*288bf522SAndroid Build Coastguard Worker     }
193*288bf522SAndroid Build Coastguard Worker     zip_inspector_->set_existing_probe(custom_probe);
194*288bf522SAndroid Build Coastguard Worker }
195*288bf522SAndroid Build Coastguard Worker 
probe_resident()196*288bf522SAndroid Build Coastguard Worker int PinTool::probe_resident() {
197*288bf522SAndroid Build Coastguard Worker     return zip_inspector_->probe_resident();
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker 
compute_zip_entry_coverages()200*288bf522SAndroid Build Coastguard Worker void PinTool::compute_zip_entry_coverages() {
201*288bf522SAndroid Build Coastguard Worker     zip_inspector_->compute_per_file_coverage();
202*288bf522SAndroid Build Coastguard Worker     if (verbose_) {
203*288bf522SAndroid Build Coastguard Worker         std::vector<ZipEntryInfo> files = zip_inspector_->get_file_infos();
204*288bf522SAndroid Build Coastguard Worker         for (auto&& file : files) {
205*288bf522SAndroid Build Coastguard Worker             cout << "file found. name=" << file.name << " offset=" << file.offset_in_zip
206*288bf522SAndroid Build Coastguard Worker                  << " uncompressed=" << file.uncompressed_size
207*288bf522SAndroid Build Coastguard Worker                  << " compressed=" << file.file_size_bytes << endl
208*288bf522SAndroid Build Coastguard Worker                  << endl;
209*288bf522SAndroid Build Coastguard Worker         }
210*288bf522SAndroid Build Coastguard Worker     }
211*288bf522SAndroid Build Coastguard Worker }
212*288bf522SAndroid Build Coastguard Worker 
dump_coverages(PinTool::DumpType dump_type)213*288bf522SAndroid Build Coastguard Worker void PinTool::dump_coverages(PinTool::DumpType dump_type) {
214*288bf522SAndroid Build Coastguard Worker     std::vector<ZipEntryCoverage>* file_coverages;
215*288bf522SAndroid Build Coastguard Worker     if (dump_type == PinTool::DumpType::FILTERED) {
216*288bf522SAndroid Build Coastguard Worker         file_coverages = &filtered_files_;
217*288bf522SAndroid Build Coastguard Worker     } else if (dump_type == PinTool::DumpType::FILE_COVERAGE) {
218*288bf522SAndroid Build Coastguard Worker         file_coverages = &(zip_inspector_->get_file_coverages());
219*288bf522SAndroid Build Coastguard Worker     } else {  // PinTool::DumpType::PROBE
220*288bf522SAndroid Build Coastguard Worker         VmaRangeGroup* probe = zip_inspector_->get_probe();
221*288bf522SAndroid Build Coastguard Worker         file_coverages = new vector<ZipEntryCoverage>();
222*288bf522SAndroid Build Coastguard Worker         ZipEntryCoverage file;
223*288bf522SAndroid Build Coastguard Worker         file.coverage = *probe;
224*288bf522SAndroid Build Coastguard Worker         file.info.name = input_file_;
225*288bf522SAndroid Build Coastguard Worker         file.info.offset_in_zip = 0;
226*288bf522SAndroid Build Coastguard Worker         uint64_t file_size_bytes = get_file_size(input_file_);
227*288bf522SAndroid Build Coastguard Worker         if (file_size_bytes == -1) {
228*288bf522SAndroid Build Coastguard Worker             cerr << "Failed to dump, cannot fstat file: " << input_file_ << endl;
229*288bf522SAndroid Build Coastguard Worker             delete file_coverages;
230*288bf522SAndroid Build Coastguard Worker             return;
231*288bf522SAndroid Build Coastguard Worker         }
232*288bf522SAndroid Build Coastguard Worker         file.info.file_size_bytes = file_size_bytes;
233*288bf522SAndroid Build Coastguard Worker         file_coverages->push_back(file);
234*288bf522SAndroid Build Coastguard Worker     }
235*288bf522SAndroid Build Coastguard Worker 
236*288bf522SAndroid Build Coastguard Worker     for (auto&& file : *file_coverages) {
237*288bf522SAndroid Build Coastguard Worker         uint64_t total_size = file.coverage.compute_total_size();
238*288bf522SAndroid Build Coastguard Worker         cout << file.info.name << " size(B)=" << file.info.file_size_bytes
239*288bf522SAndroid Build Coastguard Worker              << " resident(B)=" << total_size
240*288bf522SAndroid Build Coastguard Worker              << " resident(%)=" << (double)(total_size) / file.info.file_size_bytes * 100.0 << endl;
241*288bf522SAndroid Build Coastguard Worker         if (verbose_) {
242*288bf522SAndroid Build Coastguard Worker             cout << "file_base_zip_offset=" << file.info.offset_in_zip << endl;
243*288bf522SAndroid Build Coastguard Worker         }
244*288bf522SAndroid Build Coastguard Worker         cout << "file resident ranges" << endl;
245*288bf522SAndroid Build Coastguard Worker         if (dump_type != DumpType::PROBE) {
246*288bf522SAndroid Build Coastguard Worker             for (auto&& range : file.coverage.ranges) {
247*288bf522SAndroid Build Coastguard Worker                 // The offset in the range represents the absolute absolute offset relative to the
248*288bf522SAndroid Build Coastguard Worker                 // zip so substract the file base offset to get the relative offset within the file
249*288bf522SAndroid Build Coastguard Worker                 // which may be what is worth for a user to specify in pinconfig.txt files.
250*288bf522SAndroid Build Coastguard Worker                 uint64_t offset_in_file = range.offset - file.info.offset_in_zip;
251*288bf522SAndroid Build Coastguard Worker 
252*288bf522SAndroid Build Coastguard Worker                 cout << "zip_offset=" << range.offset << " file_offset=" << offset_in_file
253*288bf522SAndroid Build Coastguard Worker                      << " total_bytes=" << range.length << endl;
254*288bf522SAndroid Build Coastguard Worker             }
255*288bf522SAndroid Build Coastguard Worker         } else {
256*288bf522SAndroid Build Coastguard Worker             for (auto&& range : file.coverage.ranges) {
257*288bf522SAndroid Build Coastguard Worker                 cout << "file_offset=" << range.offset << " total_bytes=" << range.length << endl;
258*288bf522SAndroid Build Coastguard Worker             }
259*288bf522SAndroid Build Coastguard Worker         }
260*288bf522SAndroid Build Coastguard Worker         cout << endl;
261*288bf522SAndroid Build Coastguard Worker     }
262*288bf522SAndroid Build Coastguard Worker     cout << endl;
263*288bf522SAndroid Build Coastguard Worker     if (dump_type == DumpType::PROBE) {
264*288bf522SAndroid Build Coastguard Worker         // For other dump types we do not create memory, we reuse from class.
265*288bf522SAndroid Build Coastguard Worker         delete file_coverages;
266*288bf522SAndroid Build Coastguard Worker     }
267*288bf522SAndroid Build Coastguard Worker }
268*288bf522SAndroid Build Coastguard Worker 
filter_zip_entry_coverages(const std::string & pinconfig_filename)269*288bf522SAndroid Build Coastguard Worker void PinTool::filter_zip_entry_coverages(const std::string& pinconfig_filename) {
270*288bf522SAndroid Build Coastguard Worker     if (pinconfig_filename.length() == 0) {
271*288bf522SAndroid Build Coastguard Worker         // Nothing to do.
272*288bf522SAndroid Build Coastguard Worker         return;
273*288bf522SAndroid Build Coastguard Worker     }
274*288bf522SAndroid Build Coastguard Worker 
275*288bf522SAndroid Build Coastguard Worker     PinConfig* pinconfig = new PinConfig();
276*288bf522SAndroid Build Coastguard Worker     if (pinconfig->parse(pinconfig_filename, verbose_) > 0) {
277*288bf522SAndroid Build Coastguard Worker         cerr << "Failed parsing pinconfig file " << pinconfig_filename << ". Skip filtering";
278*288bf522SAndroid Build Coastguard Worker         delete pinconfig;
279*288bf522SAndroid Build Coastguard Worker         return;
280*288bf522SAndroid Build Coastguard Worker     }
281*288bf522SAndroid Build Coastguard Worker 
282*288bf522SAndroid Build Coastguard Worker     filter_zip_entry_coverages(pinconfig);
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker 
filter_zip_entry_coverages(PinConfig * pinconfig)285*288bf522SAndroid Build Coastguard Worker void PinTool::filter_zip_entry_coverages(PinConfig* pinconfig) {
286*288bf522SAndroid Build Coastguard Worker     pinconfig_ = pinconfig;
287*288bf522SAndroid Build Coastguard Worker 
288*288bf522SAndroid Build Coastguard Worker     // Filter based on the per file configuration.
289*288bf522SAndroid Build Coastguard Worker     vector<ZipEntryCoverage> file_coverages = zip_inspector_->get_file_coverages();
290*288bf522SAndroid Build Coastguard Worker     vector<ZipEntryCoverage>& filtered_files = filtered_files_;
291*288bf522SAndroid Build Coastguard Worker 
292*288bf522SAndroid Build Coastguard Worker     for (auto&& file_coverage : file_coverages) {
293*288bf522SAndroid Build Coastguard Worker         for (auto&& pinconfig_file : pinconfig_->files_) {
294*288bf522SAndroid Build Coastguard Worker             // Match each zip entry against every pattern in filter file.
295*288bf522SAndroid Build Coastguard Worker             std::string_view file_coverage_view(file_coverage.info.name.c_str());
296*288bf522SAndroid Build Coastguard Worker             std::string_view pinconfig_view(pinconfig_file.filename.c_str());
297*288bf522SAndroid Build Coastguard Worker             if (file_coverage_view.find(pinconfig_view) != std::string_view::npos) {
298*288bf522SAndroid Build Coastguard Worker                 // Now that we found a match, create a file with offsets that are global to zip file
299*288bf522SAndroid Build Coastguard Worker                 ZipEntryCoverage file_in_config = pinconfig_file.to_zipfilemem(file_coverage.info);
300*288bf522SAndroid Build Coastguard Worker                 if (verbose_) {
301*288bf522SAndroid Build Coastguard Worker                     cout << "Found a match: file=" << file_coverage.info.name
302*288bf522SAndroid Build Coastguard Worker                          << " matching filter=" << pinconfig_file.filename << endl;
303*288bf522SAndroid Build Coastguard Worker                     for (auto&& range : file_in_config.coverage.ranges) {
304*288bf522SAndroid Build Coastguard Worker                         cout << "zip_offset=" << range.offset << " bytes=" << range.length << endl;
305*288bf522SAndroid Build Coastguard Worker                     }
306*288bf522SAndroid Build Coastguard Worker                 }
307*288bf522SAndroid Build Coastguard Worker                 ZipEntryCoverage filtered_file =
308*288bf522SAndroid Build Coastguard Worker                         file_coverage.compute_coverage(file_in_config.coverage);
309*288bf522SAndroid Build Coastguard Worker                 filtered_files.push_back(filtered_file);
310*288bf522SAndroid Build Coastguard Worker                 break;
311*288bf522SAndroid Build Coastguard Worker             }
312*288bf522SAndroid Build Coastguard Worker         }
313*288bf522SAndroid Build Coastguard Worker     }
314*288bf522SAndroid Build Coastguard Worker }
315*288bf522SAndroid Build Coastguard Worker 
get_filtered_zip_entries()316*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage> PinTool::get_filtered_zip_entries() {
317*288bf522SAndroid Build Coastguard Worker     return filtered_files_;
318*288bf522SAndroid Build Coastguard Worker }
319*288bf522SAndroid Build Coastguard Worker 
write_coverages_as_pinlist(std::string output_pinlist,int64_t write_quota)320*288bf522SAndroid Build Coastguard Worker void PinTool::write_coverages_as_pinlist(std::string output_pinlist, int64_t write_quota) {
321*288bf522SAndroid Build Coastguard Worker     std::vector<ZipEntryCoverage>* pinlist_coverages = nullptr;
322*288bf522SAndroid Build Coastguard Worker     if (!filtered_files_.empty()) {
323*288bf522SAndroid Build Coastguard Worker         // Highest preference is writing filtered files if they exist
324*288bf522SAndroid Build Coastguard Worker         if (verbose_) {
325*288bf522SAndroid Build Coastguard Worker             cout << "Writing pinconfig filtered file coverages" << endl;
326*288bf522SAndroid Build Coastguard Worker         }
327*288bf522SAndroid Build Coastguard Worker         pinlist_coverages = &filtered_files_;
328*288bf522SAndroid Build Coastguard Worker     } else if (!zip_inspector_->get_file_coverages().empty()) {
329*288bf522SAndroid Build Coastguard Worker         // Fallback to looking for file coverage computation
330*288bf522SAndroid Build Coastguard Worker         pinlist_coverages = &zip_inspector_->get_file_coverages();
331*288bf522SAndroid Build Coastguard Worker         if (verbose_) {
332*288bf522SAndroid Build Coastguard Worker             cout << "Writing regular file coverages." << endl;
333*288bf522SAndroid Build Coastguard Worker         }
334*288bf522SAndroid Build Coastguard Worker     }
335*288bf522SAndroid Build Coastguard Worker     if (pinlist_coverages == nullptr) {
336*288bf522SAndroid Build Coastguard Worker         cerr << "Failed to find coverage to write to: " << output_pinlist << endl;
337*288bf522SAndroid Build Coastguard Worker         return;
338*288bf522SAndroid Build Coastguard Worker     }
339*288bf522SAndroid Build Coastguard Worker     int res = write_pinlist_file(output_pinlist, *pinlist_coverages, write_quota);
340*288bf522SAndroid Build Coastguard Worker     if (res > 0) {
341*288bf522SAndroid Build Coastguard Worker         cerr << "Failed to write pin file at: " << output_pinlist << endl;
342*288bf522SAndroid Build Coastguard Worker     } else {
343*288bf522SAndroid Build Coastguard Worker         if (verbose_) {
344*288bf522SAndroid Build Coastguard Worker             cout << "Finished writing pin file at: " << output_pinlist << endl;
345*288bf522SAndroid Build Coastguard Worker         }
346*288bf522SAndroid Build Coastguard Worker     }
347*288bf522SAndroid Build Coastguard Worker }