blob: d283929cdce7923ad78483378af672c8d6e9eacb [file] [log] [blame]
Martin Stjernholmc15e7e42020-12-02 22:50:53 +00001/*
2 * Copyright (C) 2019 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 ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
18#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
19
20// C++ wrapper for the dex file external API.
21
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000022#include <memory>
23#include <string>
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000024
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000025#include "art_api/dex_file_external.h"
26
27namespace art_api {
28namespace dex {
29
Martin Stjernholm4fb51112021-04-30 11:53:52 +010030#define FOR_EACH_ADEX_FILE_SYMBOL(MACRO) \
31 MACRO(ADexFile_Error_toString) \
32 MACRO(ADexFile_Method_getClassDescriptor) \
33 MACRO(ADexFile_Method_getCodeOffset) \
34 MACRO(ADexFile_Method_getName) \
35 MACRO(ADexFile_Method_getQualifiedName) \
36 MACRO(ADexFile_create) \
37 MACRO(ADexFile_destroy) \
38 MACRO(ADexFile_findMethodAtOffset) \
39 MACRO(ADexFile_forEachMethod) \
40
41#define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) extern decltype(DLFUNC)* g_##DLFUNC;
42FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL)
43#undef DEFINE_ADEX_FILE_SYMBOL
44
45// Returns true if libdexfile.so is already loaded. Otherwise tries to
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000046// load it and returns true if successful. Otherwise returns false and sets
Martin Stjernholm4fb51112021-04-30 11:53:52 +010047// *error_msg. Thread safe.
48bool TryLoadLibdexfile(std::string* error_msg);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000049
Martin Stjernholm4fb51112021-04-30 11:53:52 +010050// TryLoadLibdexfile and fatally abort process if unsuccessful.
51void LoadLibdexfile();
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000052
Martin Stjernholm4fb51112021-04-30 11:53:52 +010053// API for reading ordinary dex files and CompactDex files.
54// It is minimal 1:1 C++ wrapper around the C ABI.
55// See documentation in dex_file_external.h
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000056class DexFile {
57 public:
Martin Stjernholm4fb51112021-04-30 11:53:52 +010058 struct Method {
59 size_t GetCodeOffset(size_t* out_size = nullptr) const {
60 return g_ADexFile_Method_getCodeOffset(self, out_size);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000061 }
Martin Stjernholm4fb51112021-04-30 11:53:52 +010062
63 const char* GetName(size_t* out_size = nullptr) const {
64 return g_ADexFile_Method_getName(self, out_size);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +000065 }
Martin Stjernholm4fb51112021-04-30 11:53:52 +010066
67 const char* GetQualifiedName(bool with_params = false, size_t* out_size = nullptr) const {
68 return g_ADexFile_Method_getQualifiedName(self, with_params, out_size);
69 }
70
71 const char* GetClassDescriptor(size_t* out_size = nullptr) const {
72 return g_ADexFile_Method_getClassDescriptor(self, out_size);
73 }
74
75 const ADexFile_Method* const self;
76 };
77
78 struct Error {
79 const char* ToString() const {
80 return g_ADexFile_Error_toString(self);
81 }
82
83 bool Ok() const {
84 return self == ADEXFILE_ERROR_OK;
85 }
86
87 ADexFile_Error Code() {
88 return self;
89 }
90
91 ADexFile_Error const self;
92 };
93
94 static Error Create(const void* address,
95 size_t size,
96 size_t* new_size,
97 const char* location,
98 /*out*/ std::unique_ptr<DexFile>* out_dex_file) {
99 LoadLibdexfile();
100 ADexFile* adex = nullptr;
101 ADexFile_Error error = g_ADexFile_create(address, size, new_size, location, &adex);
102 if (adex != nullptr) {
103 *out_dex_file = std::unique_ptr<DexFile>(new DexFile{adex});
104 }
105 return Error{error};
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000106 }
107
Martin Stjernholm4fb51112021-04-30 11:53:52 +0100108 virtual ~DexFile() {
109 g_ADexFile_destroy(self_);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000110 }
111
Martin Stjernholm4fb51112021-04-30 11:53:52 +0100112 template<typename T /* lambda which takes (const DexFile::Method&) as argument */>
113 inline size_t FindMethodAtOffset(uint32_t dex_offset, T callback) {
114 auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); };
115 return g_ADexFile_findMethodAtOffset(self_, dex_offset, cb, &callback);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000116 }
117
Martin Stjernholm4fb51112021-04-30 11:53:52 +0100118 template<typename T /* lambda which takes (const DexFile::Method&) as argument */>
119 inline size_t ForEachMethod(T callback) {
120 auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); };
121 return g_ADexFile_forEachMethod(self_, cb, &callback);
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000122 }
123
Martin Stjernholm4fb51112021-04-30 11:53:52 +0100124 protected:
125 explicit DexFile(ADexFile* self) : self_(self) {}
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000126
Martin Stjernholm4fb51112021-04-30 11:53:52 +0100127 ADexFile* const self_;
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000128
Fairphone ODM25c12f52023-12-15 17:24:06 +0800129 // Have to expand DISALLOW_COPY_AND_ASSIGN here, since we cannot depend on
130 // libbase headers without re-exporting them, and that may make them override
131 // the non-ABI compatible headers that the libdexfile_support user may have.
132 DexFile(const DexFile&) = delete;
133 void operator=(const DexFile&) = delete;
Martin Stjernholmc15e7e42020-12-02 22:50:53 +0000134};
135
136} // namespace dex
137} // namespace art_api
138
139#endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_