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 <map>
23 #include <memory>
24 #include <string>
25 #include <tuple>
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(std::string filepath,std::string entry_name,size_t entry_offset,size_t entry_size)38   EmbeddedElf(std::string filepath,
39               std::string entry_name,
40               size_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   // Given an APK/ZIP/JAR file and an offset into that file, if the
72   // corresponding region of the APK corresponds to an uncompressed
73   // ELF file, then return pertinent info on the ELF.
74   static EmbeddedElf* FindElfInApkByOffset(const std::string& apk_path, uint64_t file_offset);
75   static std::unique_ptr<EmbeddedElf> FindElfInApkByName(const std::string& apk_path,
76                                                          const std::string& elf_filename);
77 
78  private:
79   static std::unique_ptr<EmbeddedElf> FindElfInApkByOffsetWithoutCache(const std::string& apk_path,
80                                                                        uint64_t file_offset);
81 
82   // First component of pair is APK file path, second is offset into APK.
83   typedef std::pair<std::string, uint64_t> ApkOffset;
84 
85   static std::map<ApkOffset, std::unique_ptr<EmbeddedElf>> embedded_elf_cache_;
86 };
87 
88 // Export for test only.
89 bool IsValidApkPath(const std::string& apk_path);
90 
91 std::string GetUrlInApk(const std::string& apk_path, const std::string& elf_filename);
92 std::tuple<bool, std::string, std::string> SplitUrlInApk(const std::string& path);
93 
94 ElfStatus GetBuildIdFromApkFile(const std::string& apk_path, const std::string& elf_filename,
95                                 BuildId* build_id);
96 
97 ElfStatus ParseSymbolsFromApkFile(const std::string& apk_path, const std::string& elf_filename,
98                                   const BuildId& expected_build_id,
99                                   const std::function<void(const ElfFileSymbol&)>& callback);
100 
101 
102 #endif  // SIMPLE_PERF_READ_APK_H_
103