1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SIMPLE_PERF_READ_APK_H_
18 #define SIMPLE_PERF_READ_APK_H_
19 
20 #include <stdint.h>
21 
22 #include <memory>
23 #include <string>
24 #include <tuple>
25 #include <unordered_map>
26 
27 #include "read_elf.h"
28 
29 // Container for info an on ELF file embedded into an APK file
30 class EmbeddedElf {
31  public:
EmbeddedElf()32   EmbeddedElf()
33       : entry_offset_(0)
34       , entry_size_(0)
35   {
36   }
37 
EmbeddedElf(const std::string & filepath,const std::string & entry_name,uint64_t entry_offset,size_t entry_size)38   EmbeddedElf(const std::string& filepath,
39               const std::string& entry_name,
40               uint64_t entry_offset,
41               size_t entry_size)
42       : filepath_(filepath)
43       , entry_name_(entry_name)
44       , entry_offset_(entry_offset)
45       , entry_size_(entry_size)
46   {
47   }
48 
49   // Path to APK file
filepath()50   const std::string &filepath() const { return filepath_; }
51 
52   // Entry name within zip archive
entry_name()53   const std::string &entry_name() const { return entry_name_; }
54 
55   // Offset of zip entry from start of containing APK file
entry_offset()56   uint64_t entry_offset() const { return entry_offset_; }
57 
58   // Size of zip entry (length of embedded ELF)
entry_size()59   uint32_t entry_size() const { return entry_size_; }
60 
61  private:
62   std::string filepath_; // containing APK path
63   std::string entry_name_; // name of entry in zip index of embedded elf file
64   uint64_t entry_offset_; // offset of ELF from start of containing APK file
65   uint32_t entry_size_;  // size of ELF file in zip
66 };
67 
68 // APK inspector helper class
69 class ApkInspector {
70  public:
71   static EmbeddedElf* FindElfInApkByOffset(const std::string& apk_path, uint64_t file_offset);
72   static EmbeddedElf* FindElfInApkByName(const std::string& apk_path,
73                                          const std::string& entry_name);
74 
75  private:
76   static std::unique_ptr<EmbeddedElf> FindElfInApkByOffsetWithoutCache(const std::string& apk_path,
77                                                                        uint64_t file_offset);
78   static std::unique_ptr<EmbeddedElf> FindElfInApkByNameWithoutCache(
79       const std::string& apk_path, const std::string& entry_name);
80 
81   struct ApkNode {
82     // Map from entry_offset to EmbeddedElf.
83     std::unordered_map<uint64_t, std::unique_ptr<EmbeddedElf>> offset_map;
84     // Map from entry_name to EmbeddedElf.
85     std::unordered_map<std::string, EmbeddedElf*> name_map;
86   };
87   static std::unordered_map<std::string, ApkNode> embedded_elf_cache_;
88 };
89 
90 std::string GetUrlInApk(const std::string& apk_path, const std::string& elf_filename);
91 std::tuple<bool, std::string, std::string> SplitUrlInApk(const std::string& path);
92 
93 // Parse path like "[anon:dalvik-classes.dex extracted in memory from /..base.apk] (deleted)",
94 // or "/dev/ashmem/dalvik-classes.dex extracted in memory from /..base.apk (deleted)" on Android P.
95 bool ParseExtractedInMemoryPath(const std::string& path, std::string* zip_path,
96                                 std::string* entry_name);
97 
98 #endif  // SIMPLE_PERF_READ_APK_H_
99