Skip to content

Commit edd0de5

Browse files
committed
[Core] support dex041(Container format)
1 parent 0297423 commit edd0de5

File tree

6 files changed

+82
-41
lines changed

6 files changed

+82
-41
lines changed

Core/dexkit/dex_item.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,10 @@ namespace dexkit {
2828

2929
inline void PushEncodeNumber(dex::InstructionFormat op_format, uint8_t op, const uint16_t *ptr, std::vector<EncodeNumber> *using_numbers);
3030

31-
DexItem::DexItem(uint32_t id, uint8_t *data, size_t size, DexKit *dexkit) :
32-
_image(std::make_unique<MemMap>(data, size)),
33-
dexkit(dexkit),
34-
reader(_image->data(), _image->len()),
35-
dex_id(id) {
36-
InitBaseCache();
37-
}
38-
39-
DexItem::DexItem(uint32_t id, std::unique_ptr<MemMap> mmap, DexKit *dexkit) :
31+
DexItem::DexItem(uint32_t id, std::shared_ptr<MemMap> mmap, uint32_t header_off, DexKit *dexkit) :
4032
_image(std::move(mmap)),
4133
dexkit(dexkit),
42-
reader(_image->data(), _image->len()),
34+
reader(_image->data(), _image->len(), header_off),
4335
dex_id(id) {
4436
InitBaseCache();
4537
}

Core/dexkit/dexkit.cpp

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,36 +51,68 @@ Error DexKit::InitFullCache() {
5151
return Error::SUCCESS;
5252
}
5353

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+
5472
Error DexKit::AddDex(uint8_t *data, size_t size) {
5573
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+
}
5879
return Error::SUCCESS;
5980
}
6081

6182
Error DexKit::AddImage(std::unique_ptr<MemMap> dex_image) {
6283
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+
}
6589
return Error::SUCCESS;
6690
}
6791

6892
Error DexKit::AddImage(std::vector<std::unique_ptr<MemMap>> dex_images) {
6993
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());
73105
{
74106
ThreadPool pool(_thread_num);
75107
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);
79111
});
80112
index++;
81113
}
82114
}
83-
std::sort(dex_items.begin(), dex_items.end(), comp);
115+
dex_cnt += add_items.size();
84116
return Error::SUCCESS;
85117
}
86118

@@ -91,39 +123,55 @@ Error DexKit::AddZipPath(std::string_view apk_path, int unzip_thread_num) {
91123
}
92124
auto zip_file = ZipArchive::Open(map);
93125
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;
95127
for (int idx = 1;; ++idx) {
96128
auto entry_name = "classes" + (idx == 1 ? std::string() : std::to_string(idx)) + ".dex";
97129
auto entry = zip_file->Find(entry_name);
98130
if (!entry) {
99131
break;
100132
}
101-
dex_pairs.emplace_back(idx, entry);
133+
image_pairs.emplace_back(idx, entry);
102134
}
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);
106138
{
107139
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) {
109141
pool.enqueue([this, &dex_pair, old_size, &zip_file]() {
110142
auto dex_image = zip_file->GetUncompressData(*dex_pair.second);
111143
auto ptr = std::make_unique<MemMap>(std::move(dex_image));
112144
if (!ptr->ok()) {
113145
return;
114146
}
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);
117149
});
118150
}
119151
}
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();
121170
return Error::SUCCESS;
122171
}
123172

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) {
127175
std::string file_name(path);
128176
if (file_name.back() != '/') {
129177
file_name += '/';

Core/dexkit/include/dex_item.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ class DexKit;
4848
class DexItem {
4949
public:
5050

51-
explicit DexItem(uint32_t id, uint8_t *data, size_t size, DexKit *dexkit);
52-
explicit DexItem(uint32_t id, std::unique_ptr<MemMap> mmap, DexKit *dexkit);
51+
explicit DexItem(uint32_t id, std::shared_ptr<MemMap> mmap, uint32_t header_off, DexKit *dexkit);
5352
~DexItem() = default;
5453
DexItem(DexItem &&) = default;
5554
DexItem &operator=(DexItem &&) = default;
@@ -241,7 +240,7 @@ class DexItem {
241240

242241
private:
243242
DexKit *dexkit;
244-
std::unique_ptr<MemMap> _image;
243+
std::shared_ptr<MemMap> _image;
245244
dex::Reader reader;
246245

247246
uint32_t dex_cross_flag = 0;

Core/dexkit/include/dexkit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class DexKit {
5151
Error AddImage(std::unique_ptr<MemMap> dex_image);
5252
Error AddImage(std::vector<std::unique_ptr<MemMap>> dex_images);
5353
Error AddZipPath(std::string_view apk_path, int unzip_thread_num = 0);
54-
Error ExportDexFile(std::string_view path);
54+
[[nodiscard]] Error ExportDexFile(std::string_view path) const;
5555
[[nodiscard]] int GetDexNum() const;
5656

5757
std::unique_ptr<flatbuffers::FlatBufferBuilder> FindClass(const schema::FindClass *query);
@@ -89,6 +89,7 @@ class DexKit {
8989
std::shared_mutex _put_class_mutex;
9090
std::atomic<uint32_t> dex_cnt = 0;
9191
uint32_t _thread_num = std::thread::hardware_concurrency();
92+
std::vector<std::shared_ptr<MemMap>> images;
9293
std::vector<std::unique_ptr<DexItem>> dex_items;
9394
phmap::flat_hash_map<std::string_view, std::pair<uint16_t /*dex_id*/, uint32_t /*type_idx*/>> class_declare_dex_map;
9495

Core/third_party/slicer/export/slicer/reader.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace dex {
3636
//
3737
class Reader {
3838
public:
39-
Reader(const dex::u1* image, size_t size);
39+
Reader(const dex::u1* image, size_t size, dex::u4 header_off);
4040
~Reader() = default;
4141

4242
// No copy/move semantics
@@ -109,15 +109,15 @@ class Reader {
109109
template <class T>
110110
const T* ptr(int offset) const {
111111
SLICER_CHECK_GE(offset, 0 && offset + sizeof(T) <= size_);
112-
return reinterpret_cast<const T*>(image_ + offset);
112+
return reinterpret_cast<const T*>(image_ + header_off_ + offset);
113113
}
114114

115115
// Convert a data section file pointer (absolute offset) to an in-memory pointer
116116
// (offset should be inside the data section)
117117
template <class T>
118118
const T* dataPtr(int offset) const {
119119
SLICER_CHECK_GE(offset, header_->data_off && offset + sizeof(T) <= size_);
120-
return reinterpret_cast<const T*>(image_ + offset);
120+
return reinterpret_cast<const T*>(image_ + header_off_ + offset);
121121
}
122122

123123
// Map an indexed section to an ArrayView<T>
@@ -141,6 +141,7 @@ class Reader {
141141

142142
// .dex image header
143143
const dex::Header* header_;
144+
dex::u4 header_off_;
144145

145146
// .dex IR associated with the reader
146147
std::shared_ptr<ir::DexFile> dex_ir_;

Core/third_party/slicer/reader.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
namespace dex {
2929

30-
Reader::Reader(const dex::u1* image, size_t size) : image_(image), size_(size) {
30+
Reader::Reader(const dex::u1* image, size_t size, dex::u4 header_off = 0) : image_(image), size_(size), header_off_(header_off) {
3131
// init the header reference
3232
header_ = ptr<dex::Header>(0);
3333
ValidateHeader();

0 commit comments

Comments
 (0)