@@ -51,36 +51,68 @@ Error DexKit::InitFullCache() {
51
51
return Error::SUCCESS;
52
52
}
53
53
54
+ static inline std::vector<uint32_t > ParseLogicalDexOffsets (const std::shared_ptr<MemMap> &image) {
55
+ std::vector<uint32_t > offs;
56
+ const uint8_t *base = image->data ();
57
+ const size_t n = image->len ();
58
+
59
+ size_t off = 0 ;
60
+ while (true ) {
61
+ if (off + sizeof (dex::Header) > n) break ;
62
+ const auto header = reinterpret_cast <const dex::Header *>(base + off);
63
+ uint32_t sz = header->file_size ;
64
+ if (sz < sizeof (dex::Header) || off + sz > n) break ;
65
+ offs.push_back (static_cast <uint32_t >(off));
66
+ off += sz;
67
+ if (off >= n) break ;
68
+ }
69
+ return offs;
70
+ }
71
+
54
72
Error DexKit::AddDex (uint8_t *data, size_t size) {
55
73
std::lock_guard lock (_mutex);
56
- dex_items.emplace_back (std::make_unique<DexItem>(dex_cnt++, data, size, this ));
57
- std::sort (dex_items.begin (), dex_items.end (), comp);
74
+ images.emplace_back (std::make_shared<MemMap>(data, size));
75
+ auto image = images.back ();
76
+ for (auto off : ParseLogicalDexOffsets (image)) {
77
+ dex_items.emplace_back (std::make_unique<DexItem>(dex_cnt++, image, off, this ));
78
+ }
58
79
return Error::SUCCESS;
59
80
}
60
81
61
82
Error DexKit::AddImage (std::unique_ptr<MemMap> dex_image) {
62
83
std::lock_guard lock (_mutex);
63
- dex_items.emplace_back (std::make_unique<DexItem>(dex_cnt++, std::move (dex_image), this ));
64
- std::sort (dex_items.begin (), dex_items.end (), comp);
84
+ images.emplace_back (std::move (dex_image));
85
+ auto image = images.back ();
86
+ for (auto off : ParseLogicalDexOffsets (image)) {
87
+ dex_items.emplace_back (std::make_unique<DexItem>(dex_cnt++, image, off, this ));
88
+ }
65
89
return Error::SUCCESS;
66
90
}
67
91
68
92
Error DexKit::AddImage (std::vector<std::unique_ptr<MemMap>> dex_images) {
69
93
std::lock_guard lock (_mutex);
70
- auto old_size = dex_items.size ();
71
- auto new_size = old_size + dex_images.size ();
72
- dex_items.resize (new_size);
94
+ const auto old_size = images.size ();
95
+ const auto new_size = old_size + dex_images.size ();
96
+ images.resize (new_size);
97
+ std::vector<std::pair<std::shared_ptr<MemMap>, uint32_t >> add_items;
98
+ for (auto i = old_size; i < new_size; i++) {
99
+ images[i] = std::move (dex_images[i]);
100
+ for (auto off : ParseLogicalDexOffsets (images[i])) {
101
+ add_items.emplace_back (images[i], off);
102
+ }
103
+ }
104
+ dex_items.resize (dex_items.size () + add_items.size ());
73
105
{
74
106
ThreadPool pool (_thread_num);
75
107
auto index = old_size;
76
- for (auto &dex_image: dex_images ) {
77
- pool.enqueue ([this , &dex_image , index]() {
78
- dex_items[index] = std::make_unique<DexItem>(index, std::move (dex_image) , this );
108
+ for (auto &[image, offset]: add_items ) {
109
+ pool.enqueue ([this , &image , index, offset ]() {
110
+ dex_items[index] = std::make_unique<DexItem>(index, std::move (image), offset , this );
79
111
});
80
112
index++;
81
113
}
82
114
}
83
- std::sort (dex_items. begin (), dex_items. end (), comp );
115
+ dex_cnt += add_items. size ( );
84
116
return Error::SUCCESS;
85
117
}
86
118
@@ -91,39 +123,55 @@ Error DexKit::AddZipPath(std::string_view apk_path, int unzip_thread_num) {
91
123
}
92
124
auto zip_file = ZipArchive::Open (map);
93
125
if (!zip_file) return Error::OPEN_ZIP_FILE_FAILED;
94
- std::vector<std::pair<int , const Entry *>> dex_pairs ;
126
+ std::vector<std::pair<int , const Entry *>> image_pairs ;
95
127
for (int idx = 1 ;; ++idx) {
96
128
auto entry_name = " classes" + (idx == 1 ? std::string () : std::to_string (idx)) + " .dex" ;
97
129
auto entry = zip_file->Find (entry_name);
98
130
if (!entry) {
99
131
break ;
100
132
}
101
- dex_pairs .emplace_back (idx, entry);
133
+ image_pairs .emplace_back (idx, entry);
102
134
}
103
- int old_size = ( int ) dex_items .size ();
104
- int new_size = ( int ) ( old_size + dex_pairs .size () );
105
- dex_items .resize (new_size);
135
+ const auto old_size = images .size ();
136
+ const auto new_size = old_size + image_pairs .size ();
137
+ images .resize (new_size);
106
138
{
107
139
ThreadPool pool (unzip_thread_num == 0 ? _thread_num : unzip_thread_num);
108
- for (auto &dex_pair: dex_pairs ) {
140
+ for (auto &dex_pair: image_pairs ) {
109
141
pool.enqueue ([this , &dex_pair, old_size, &zip_file]() {
110
142
auto dex_image = zip_file->GetUncompressData (*dex_pair.second );
111
143
auto ptr = std::make_unique<MemMap>(std::move (dex_image));
112
144
if (!ptr->ok ()) {
113
145
return ;
114
146
}
115
- int idx = old_size + dex_pair.first - 1 ;
116
- dex_items [idx] = std::make_unique<DexItem>(idx, std:: move (ptr), this );
147
+ auto idx = old_size + dex_pair.first - 1 ;
148
+ images [idx] = std::move (ptr);
117
149
});
118
150
}
119
151
}
120
- dex_cnt += (uint32_t ) dex_pairs.size ();
152
+ std::vector<std::pair<std::shared_ptr<MemMap>, uint32_t >> add_items;
153
+ for (auto i = old_size; i < new_size; i++) {
154
+ for (auto off : ParseLogicalDexOffsets (images[i])) {
155
+ add_items.emplace_back (images[i], off);
156
+ }
157
+ }
158
+ dex_items.resize (dex_items.size () + add_items.size ());
159
+ {
160
+ ThreadPool pool (_thread_num);
161
+ auto index = old_size;
162
+ for (auto &[image, offset]: add_items) {
163
+ pool.enqueue ([this , &image, index, offset]() {
164
+ dex_items[index] = std::make_unique<DexItem>(index, std::move (image), offset, this );
165
+ });
166
+ index++;
167
+ }
168
+ }
169
+ dex_cnt += add_items.size ();
121
170
return Error::SUCCESS;
122
171
}
123
172
124
- Error DexKit::ExportDexFile (std::string_view path) {
125
- for (auto &dex_item: dex_items) {
126
- auto image = dex_item->GetImage ();
173
+ Error DexKit::ExportDexFile (std::string_view path) const {
174
+ for (const auto &image: images) {
127
175
std::string file_name (path);
128
176
if (file_name.back () != ' /' ) {
129
177
file_name += ' /' ;
0 commit comments