1f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh/*
2f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * Copyright (C) 2016 The Android Open Source Project
3f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh *
4f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * Licensed under the Apache License, Version 2.0 (the "License");
5f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * you may not use this file except in compliance with the License.
6f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * You may obtain a copy of the License at
7f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh *
8f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh *      http://www.apache.org/licenses/LICENSE-2.0
9f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh *
10f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * Unless required by applicable law or agreed to in writing, software
11f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * distributed under the License is distributed on an "AS IS" BASIS,
12f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * See the License for the specific language governing permissions and
14f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh * limitations under the License.
15f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh */
16f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
17f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#ifndef SIMPLE_PERF_READ_APK_H_
18f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#define SIMPLE_PERF_READ_APK_H_
19f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
2041e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui#include <stdint.h>
2141e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui
22b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui#include <map>
23f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include <memory>
24f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include <string>
25b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui#include <tuple>
26f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
27b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui#include "read_elf.h"
28f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
29f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh// Container for info an on ELF file embedded into an APK file
30f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntoshclass EmbeddedElf {
31f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh public:
32f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  EmbeddedElf()
33f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      : entry_offset_(0)
34f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      , entry_size_(0)
35f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  {
36f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  }
37f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
38f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  EmbeddedElf(std::string filepath,
39f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh              std::string entry_name,
40f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh              size_t entry_offset,
41f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh              size_t entry_size)
42f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      : filepath_(filepath)
43f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      , entry_name_(entry_name)
44f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      , entry_offset_(entry_offset)
45f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      , entry_size_(entry_size)
46f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  {
47f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  }
48f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
49f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // Path to APK file
50f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  const std::string &filepath() const { return filepath_; }
51f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
52f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // Entry name within zip archive
53f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  const std::string &entry_name() const { return entry_name_; }
54f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
55f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // Offset of zip entry from start of containing APK file
5641e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui  uint64_t entry_offset() const { return entry_offset_; }
57f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
58f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // Size of zip entry (length of embedded ELF)
59f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  uint32_t entry_size() const { return entry_size_; }
60f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
61f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh private:
62f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  std::string filepath_; // containing APK path
63f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  std::string entry_name_; // name of entry in zip index of embedded elf file
6441e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui  uint64_t entry_offset_; // offset of ELF from start of containing APK file
65f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  uint32_t entry_size_;  // size of ELF file in zip
66f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh};
67f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
68f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh// APK inspector helper class
69f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntoshclass ApkInspector {
70f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh public:
71f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // Given an APK/ZIP/JAR file and an offset into that file, if the
72f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // corresponding region of the APK corresponds to an uncompressed
73f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  // ELF file, then return pertinent info on the ELF.
7441e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui  static EmbeddedElf* FindElfInApkByOffset(const std::string& apk_path, uint64_t file_offset);
75b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  static std::unique_ptr<EmbeddedElf> FindElfInApkByName(const std::string& apk_path,
76b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui                                                         const std::string& elf_filename);
77f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
78f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh private:
79b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  static std::unique_ptr<EmbeddedElf> FindElfInApkByOffsetWithoutCache(const std::string& apk_path,
8041e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui                                                                       uint64_t file_offset);
81b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
82b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  // First component of pair is APK file path, second is offset into APK.
8341e32ca272f474d35a84a6e7c7f0a28c3160abc3Yabin Cui  typedef std::pair<std::string, uint64_t> ApkOffset;
84b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
85b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  static std::map<ApkOffset, std::unique_ptr<EmbeddedElf>> embedded_elf_cache_;
86f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh};
87f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
88b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui// Export for test only.
89b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuibool IsValidApkPath(const std::string& apk_path);
90b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
91b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuistd::string GetUrlInApk(const std::string& apk_path, const std::string& elf_filename);
92b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuistd::tuple<bool, std::string, std::string> SplitUrlInApk(const std::string& path);
93b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
94dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus GetBuildIdFromApkFile(const std::string& apk_path, const std::string& elf_filename,
95dec43c18d06415a955b8f32355bca925be901905Yabin Cui                                BuildId* build_id);
96b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
97dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ParseSymbolsFromApkFile(const std::string& apk_path, const std::string& elf_filename,
98dec43c18d06415a955b8f32355bca925be901905Yabin Cui                                  const BuildId& expected_build_id,
99dec43c18d06415a955b8f32355bca925be901905Yabin Cui                                  const std::function<void(const ElfFileSymbol&)>& callback);
100b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
101b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
102f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#endif  // SIMPLE_PERF_READ_APK_H_
103