1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright 2020 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include "UnwinderComponentCreator.h"
18*eb293b8fSAndroid Build Coastguard Worker
19*eb293b8fSAndroid Build Coastguard Worker #include <map>
20*eb293b8fSAndroid Build Coastguard Worker #include <memory>
21*eb293b8fSAndroid Build Coastguard Worker #include <string>
22*eb293b8fSAndroid Build Coastguard Worker #include <vector>
23*eb293b8fSAndroid Build Coastguard Worker
GetRegisters(ArchEnum arch)24*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Regs> GetRegisters(ArchEnum arch) {
25*eb293b8fSAndroid Build Coastguard Worker switch (arch) {
26*eb293b8fSAndroid Build Coastguard Worker case unwindstack::ARCH_ARM: {
27*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::RegsArm> regs = std::make_unique<unwindstack::RegsArm>();
28*eb293b8fSAndroid Build Coastguard Worker return regs;
29*eb293b8fSAndroid Build Coastguard Worker }
30*eb293b8fSAndroid Build Coastguard Worker case unwindstack::ARCH_ARM64: {
31*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::RegsArm64> regs = std::make_unique<unwindstack::RegsArm64>();
32*eb293b8fSAndroid Build Coastguard Worker return regs;
33*eb293b8fSAndroid Build Coastguard Worker }
34*eb293b8fSAndroid Build Coastguard Worker case unwindstack::ARCH_RISCV64: {
35*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::RegsRiscv64> regs = std::make_unique<unwindstack::RegsRiscv64>();
36*eb293b8fSAndroid Build Coastguard Worker return regs;
37*eb293b8fSAndroid Build Coastguard Worker }
38*eb293b8fSAndroid Build Coastguard Worker case unwindstack::ARCH_X86_64: {
39*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
40*eb293b8fSAndroid Build Coastguard Worker return regs;
41*eb293b8fSAndroid Build Coastguard Worker }
42*eb293b8fSAndroid Build Coastguard Worker case unwindstack::ARCH_UNKNOWN:
43*eb293b8fSAndroid Build Coastguard Worker default: {
44*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<unwindstack::RegsX86_64> regs = std::make_unique<unwindstack::RegsX86_64>();
45*eb293b8fSAndroid Build Coastguard Worker return regs;
46*eb293b8fSAndroid Build Coastguard Worker }
47*eb293b8fSAndroid Build Coastguard Worker }
48*eb293b8fSAndroid Build Coastguard Worker }
49*eb293b8fSAndroid Build Coastguard Worker
GetArch(FuzzedDataProvider * data_provider)50*eb293b8fSAndroid Build Coastguard Worker ArchEnum GetArch(FuzzedDataProvider* data_provider) {
51*eb293b8fSAndroid Build Coastguard Worker uint8_t arch = data_provider->ConsumeIntegralInRange<uint8_t>(1, kArchCount);
52*eb293b8fSAndroid Build Coastguard Worker return static_cast<ArchEnum>(arch);
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker
ElfAddMapInfo(Maps * maps,uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,const char * name,Elf * elf=nullptr)55*eb293b8fSAndroid Build Coastguard Worker void ElfAddMapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
56*eb293b8fSAndroid Build Coastguard Worker const char* name, Elf* elf = nullptr) {
57*eb293b8fSAndroid Build Coastguard Worker std::string str_name(name);
58*eb293b8fSAndroid Build Coastguard Worker maps->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
59*eb293b8fSAndroid Build Coastguard Worker if (elf != nullptr) {
60*eb293b8fSAndroid Build Coastguard Worker const auto& map_info = *--maps->end();
61*eb293b8fSAndroid Build Coastguard Worker map_info->set_elf(elf);
62*eb293b8fSAndroid Build Coastguard Worker }
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker
ElfPushFakeFunctionData(FuzzedDataProvider * data_provider,ElfInterfaceFake * elf)65*eb293b8fSAndroid Build Coastguard Worker void ElfPushFakeFunctionData(FuzzedDataProvider* data_provider, ElfInterfaceFake* elf) {
66*eb293b8fSAndroid Build Coastguard Worker uint8_t func_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxFuncCount);
67*eb293b8fSAndroid Build Coastguard Worker for (uint8_t i = 0; i < func_count; i++) {
68*eb293b8fSAndroid Build Coastguard Worker std::string func_name = data_provider->ConsumeRandomLengthString(kMaxFuncNameLen);
69*eb293b8fSAndroid Build Coastguard Worker bool global = data_provider->ConsumeBool();
70*eb293b8fSAndroid Build Coastguard Worker if (global) {
71*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetGlobalVariable(func_name, data_provider->ConsumeIntegral<uint64_t>());
72*eb293b8fSAndroid Build Coastguard Worker } else {
73*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceFake::FakePushFunctionData(FunctionData(func_name, i));
74*eb293b8fSAndroid Build Coastguard Worker }
75*eb293b8fSAndroid Build Coastguard Worker }
76*eb293b8fSAndroid Build Coastguard Worker }
ElfPushFakeStepData(FuzzedDataProvider * data_provider)77*eb293b8fSAndroid Build Coastguard Worker void ElfPushFakeStepData(FuzzedDataProvider* data_provider) {
78*eb293b8fSAndroid Build Coastguard Worker uint8_t step_count = data_provider->ConsumeIntegralInRange<uint>(0, kMaxStepCount);
79*eb293b8fSAndroid Build Coastguard Worker for (uint8_t i = 0; i < step_count; i++) {
80*eb293b8fSAndroid Build Coastguard Worker uint64_t pc = data_provider->ConsumeIntegral<uint64_t>();
81*eb293b8fSAndroid Build Coastguard Worker uint64_t sp = data_provider->ConsumeIntegral<uint64_t>();
82*eb293b8fSAndroid Build Coastguard Worker bool finished = i + 1 == step_count;
83*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceFake::FakePushStepData(StepData(pc, sp, finished));
84*eb293b8fSAndroid Build Coastguard Worker }
85*eb293b8fSAndroid Build Coastguard Worker }
86*eb293b8fSAndroid Build Coastguard Worker
PopulateElfFake(FuzzedDataProvider * data_provider)87*eb293b8fSAndroid Build Coastguard Worker ElfFake* PopulateElfFake(FuzzedDataProvider* data_provider) {
88*eb293b8fSAndroid Build Coastguard Worker // This will be passed to a smart pointer in ElfAddMapInfo.
89*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> memory(new MemoryFake);
90*eb293b8fSAndroid Build Coastguard Worker ElfFake* elf = new ElfFake(memory);
91*eb293b8fSAndroid Build Coastguard Worker
92*eb293b8fSAndroid Build Coastguard Worker // This will be handled by a smart pointer within Elf.
93*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> empty;
94*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceFake* interface_fake = new ElfInterfaceFake(empty);
95*eb293b8fSAndroid Build Coastguard Worker std::string build_id = data_provider->ConsumeRandomLengthString(kMaxBuildIdLen);
96*eb293b8fSAndroid Build Coastguard Worker interface_fake->FakeSetBuildID(build_id);
97*eb293b8fSAndroid Build Coastguard Worker std::string so_name = data_provider->ConsumeRandomLengthString(kMaxSoNameLen);
98*eb293b8fSAndroid Build Coastguard Worker interface_fake->FakeSetSoname(so_name.c_str());
99*eb293b8fSAndroid Build Coastguard Worker
100*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetArch(GetArch(data_provider));
101*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetLoadBias(data_provider->ConsumeIntegral<uint64_t>());
102*eb293b8fSAndroid Build Coastguard Worker
103*eb293b8fSAndroid Build Coastguard Worker ElfPushFakeFunctionData(data_provider, interface_fake);
104*eb293b8fSAndroid Build Coastguard Worker ElfPushFakeStepData(data_provider);
105*eb293b8fSAndroid Build Coastguard Worker
106*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetInterface(interface_fake);
107*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceFake::FakeClear();
108*eb293b8fSAndroid Build Coastguard Worker return elf;
109*eb293b8fSAndroid Build Coastguard Worker }
110*eb293b8fSAndroid Build Coastguard Worker
111*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kPageSize = 4096;
112*eb293b8fSAndroid Build Coastguard Worker
AlignToPage(uint64_t address,uint64_t * aligned_address)113*eb293b8fSAndroid Build Coastguard Worker static inline bool AlignToPage(uint64_t address, uint64_t* aligned_address) {
114*eb293b8fSAndroid Build Coastguard Worker if (__builtin_add_overflow(address, kPageSize - 1, aligned_address)) {
115*eb293b8fSAndroid Build Coastguard Worker return false;
116*eb293b8fSAndroid Build Coastguard Worker }
117*eb293b8fSAndroid Build Coastguard Worker *aligned_address &= ~(kPageSize - 1);
118*eb293b8fSAndroid Build Coastguard Worker return true;
119*eb293b8fSAndroid Build Coastguard Worker }
120*eb293b8fSAndroid Build Coastguard Worker
GetMaps(FuzzedDataProvider * data_provider)121*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Maps> GetMaps(FuzzedDataProvider* data_provider) {
122*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<Maps> maps = std::make_unique<Maps>();
123*eb293b8fSAndroid Build Coastguard Worker std::map<uint64_t, uint64_t> map_ends;
124*eb293b8fSAndroid Build Coastguard Worker uint8_t entry_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxMapEntryCount);
125*eb293b8fSAndroid Build Coastguard Worker for (uint8_t i = 0; i < entry_count; i++) {
126*eb293b8fSAndroid Build Coastguard Worker uint64_t start;
127*eb293b8fSAndroid Build Coastguard Worker if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &start)) {
128*eb293b8fSAndroid Build Coastguard Worker // Overflowed.
129*eb293b8fSAndroid Build Coastguard Worker continue;
130*eb293b8fSAndroid Build Coastguard Worker }
131*eb293b8fSAndroid Build Coastguard Worker uint64_t end;
132*eb293b8fSAndroid Build Coastguard Worker if (!AlignToPage(data_provider->ConsumeIntegralInRange<uint64_t>(start, UINT64_MAX), &end)) {
133*eb293b8fSAndroid Build Coastguard Worker // Overflowed.
134*eb293b8fSAndroid Build Coastguard Worker continue;
135*eb293b8fSAndroid Build Coastguard Worker }
136*eb293b8fSAndroid Build Coastguard Worker if (start == end) {
137*eb293b8fSAndroid Build Coastguard Worker // It's impossible to see start == end in the real world, so
138*eb293b8fSAndroid Build Coastguard Worker // make sure the map contains at least one page of data.
139*eb293b8fSAndroid Build Coastguard Worker if (__builtin_add_overflow(end, 0x1000, &end)) {
140*eb293b8fSAndroid Build Coastguard Worker continue;
141*eb293b8fSAndroid Build Coastguard Worker }
142*eb293b8fSAndroid Build Coastguard Worker }
143*eb293b8fSAndroid Build Coastguard Worker // Make sure not to add overlapping maps, that is not something that can
144*eb293b8fSAndroid Build Coastguard Worker // happen in the real world.
145*eb293b8fSAndroid Build Coastguard Worker auto entry = map_ends.upper_bound(start);
146*eb293b8fSAndroid Build Coastguard Worker if (entry != map_ends.end() && end > entry->second) {
147*eb293b8fSAndroid Build Coastguard Worker continue;
148*eb293b8fSAndroid Build Coastguard Worker }
149*eb293b8fSAndroid Build Coastguard Worker map_ends[end] = start;
150*eb293b8fSAndroid Build Coastguard Worker
151*eb293b8fSAndroid Build Coastguard Worker uint64_t offset;
152*eb293b8fSAndroid Build Coastguard Worker if (!AlignToPage(data_provider->ConsumeIntegral<uint64_t>(), &offset)) {
153*eb293b8fSAndroid Build Coastguard Worker // Overflowed.
154*eb293b8fSAndroid Build Coastguard Worker continue;
155*eb293b8fSAndroid Build Coastguard Worker }
156*eb293b8fSAndroid Build Coastguard Worker std::string map_info_name = data_provider->ConsumeRandomLengthString(kMaxMapInfoNameLen);
157*eb293b8fSAndroid Build Coastguard Worker uint8_t flags = PROT_READ | PROT_WRITE;
158*eb293b8fSAndroid Build Coastguard Worker
159*eb293b8fSAndroid Build Coastguard Worker bool exec = data_provider->ConsumeBool();
160*eb293b8fSAndroid Build Coastguard Worker if (exec) {
161*eb293b8fSAndroid Build Coastguard Worker flags |= PROT_EXEC;
162*eb293b8fSAndroid Build Coastguard Worker }
163*eb293b8fSAndroid Build Coastguard Worker
164*eb293b8fSAndroid Build Coastguard Worker bool shouldAddElf = data_provider->ConsumeBool();
165*eb293b8fSAndroid Build Coastguard Worker if (shouldAddElf) {
166*eb293b8fSAndroid Build Coastguard Worker ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str(),
167*eb293b8fSAndroid Build Coastguard Worker PopulateElfFake(data_provider));
168*eb293b8fSAndroid Build Coastguard Worker } else {
169*eb293b8fSAndroid Build Coastguard Worker ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str());
170*eb293b8fSAndroid Build Coastguard Worker }
171*eb293b8fSAndroid Build Coastguard Worker }
172*eb293b8fSAndroid Build Coastguard Worker maps->Sort();
173*eb293b8fSAndroid Build Coastguard Worker return maps;
174*eb293b8fSAndroid Build Coastguard Worker }
175*eb293b8fSAndroid Build Coastguard Worker
176*eb293b8fSAndroid Build Coastguard Worker // This code (until PutElfFilesInMemory) is pretty much directly copied from JitDebugTest.cpp
177*eb293b8fSAndroid Build Coastguard Worker // There's a few minor modifications, most notably, all methods accept a MemoryFake pointer, and
178*eb293b8fSAndroid Build Coastguard Worker // PutElfInMemory inserts JIT data when called.
WriteDescriptor32(MemoryFake * memory,uint64_t addr,uint32_t entry)179*eb293b8fSAndroid Build Coastguard Worker void WriteDescriptor32(MemoryFake* memory, uint64_t addr, uint32_t entry) {
180*eb293b8fSAndroid Build Coastguard Worker // Format of the 32 bit JITDescriptor structure:
181*eb293b8fSAndroid Build Coastguard Worker // uint32_t version
182*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr, 1);
183*eb293b8fSAndroid Build Coastguard Worker // uint32_t action_flag
184*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 4, 0);
185*eb293b8fSAndroid Build Coastguard Worker // uint32_t relevant_entry
186*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 8, 0);
187*eb293b8fSAndroid Build Coastguard Worker // uint32_t first_entry
188*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 12, entry);
189*eb293b8fSAndroid Build Coastguard Worker }
190*eb293b8fSAndroid Build Coastguard Worker
WriteDescriptor64(MemoryFake * memory,uint64_t addr,uint64_t entry)191*eb293b8fSAndroid Build Coastguard Worker void WriteDescriptor64(MemoryFake* memory, uint64_t addr, uint64_t entry) {
192*eb293b8fSAndroid Build Coastguard Worker // Format of the 64 bit JITDescriptor structure:
193*eb293b8fSAndroid Build Coastguard Worker // uint32_t version
194*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr, 1);
195*eb293b8fSAndroid Build Coastguard Worker // uint32_t action_flag
196*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 4, 0);
197*eb293b8fSAndroid Build Coastguard Worker // uint64_t relevant_entry
198*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 8, 0);
199*eb293b8fSAndroid Build Coastguard Worker // uint64_t first_entry
200*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 16, entry);
201*eb293b8fSAndroid Build Coastguard Worker }
202*eb293b8fSAndroid Build Coastguard Worker
WriteEntry32Pack(MemoryFake * memory,uint64_t addr,uint32_t prev,uint32_t next,uint32_t elf_addr,uint64_t elf_size)203*eb293b8fSAndroid Build Coastguard Worker void WriteEntry32Pack(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
204*eb293b8fSAndroid Build Coastguard Worker uint32_t elf_addr, uint64_t elf_size) {
205*eb293b8fSAndroid Build Coastguard Worker // Format of the 32 bit JITCodeEntry structure:
206*eb293b8fSAndroid Build Coastguard Worker // uint32_t next
207*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr, next);
208*eb293b8fSAndroid Build Coastguard Worker // uint32_t prev
209*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 4, prev);
210*eb293b8fSAndroid Build Coastguard Worker // uint32_t symfile_addr
211*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 8, elf_addr);
212*eb293b8fSAndroid Build Coastguard Worker // uint64_t symfile_size
213*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 12, elf_size);
214*eb293b8fSAndroid Build Coastguard Worker }
215*eb293b8fSAndroid Build Coastguard Worker
WriteEntry32Pad(MemoryFake * memory,uint64_t addr,uint32_t prev,uint32_t next,uint32_t elf_addr,uint64_t elf_size)216*eb293b8fSAndroid Build Coastguard Worker void WriteEntry32Pad(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next,
217*eb293b8fSAndroid Build Coastguard Worker uint32_t elf_addr, uint64_t elf_size) {
218*eb293b8fSAndroid Build Coastguard Worker // Format of the 32 bit JITCodeEntry structure:
219*eb293b8fSAndroid Build Coastguard Worker // uint32_t next
220*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr, next);
221*eb293b8fSAndroid Build Coastguard Worker // uint32_t prev
222*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 4, prev);
223*eb293b8fSAndroid Build Coastguard Worker // uint32_t symfile_addr
224*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 8, elf_addr);
225*eb293b8fSAndroid Build Coastguard Worker // uint32_t pad
226*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(addr + 12, 0);
227*eb293b8fSAndroid Build Coastguard Worker // uint64_t symfile_size
228*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 16, elf_size);
229*eb293b8fSAndroid Build Coastguard Worker }
230*eb293b8fSAndroid Build Coastguard Worker
WriteEntry64(MemoryFake * memory,uint64_t addr,uint64_t prev,uint64_t next,uint64_t elf_addr,uint64_t elf_size)231*eb293b8fSAndroid Build Coastguard Worker void WriteEntry64(MemoryFake* memory, uint64_t addr, uint64_t prev, uint64_t next,
232*eb293b8fSAndroid Build Coastguard Worker uint64_t elf_addr, uint64_t elf_size) {
233*eb293b8fSAndroid Build Coastguard Worker // Format of the 64 bit JITCodeEntry structure:
234*eb293b8fSAndroid Build Coastguard Worker // uint64_t next
235*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr, next);
236*eb293b8fSAndroid Build Coastguard Worker // uint64_t prev
237*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 8, prev);
238*eb293b8fSAndroid Build Coastguard Worker // uint64_t symfile_addr
239*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 16, elf_addr);
240*eb293b8fSAndroid Build Coastguard Worker // uint64_t symfile_size
241*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(addr + 24, elf_size);
242*eb293b8fSAndroid Build Coastguard Worker }
243*eb293b8fSAndroid Build Coastguard Worker
244*eb293b8fSAndroid Build Coastguard Worker template <typename EhdrType, typename ShdrType>
PutElfInMemory(MemoryFake * memory,uint64_t offset,uint8_t class_type,uint8_t machine_type,uint32_t pc,uint32_t size)245*eb293b8fSAndroid Build Coastguard Worker void PutElfInMemory(MemoryFake* memory, uint64_t offset, uint8_t class_type, uint8_t machine_type,
246*eb293b8fSAndroid Build Coastguard Worker uint32_t pc, uint32_t size) {
247*eb293b8fSAndroid Build Coastguard Worker EhdrType ehdr;
248*eb293b8fSAndroid Build Coastguard Worker memset(&ehdr, 0, sizeof(ehdr));
249*eb293b8fSAndroid Build Coastguard Worker uint64_t sh_offset = sizeof(ehdr);
250*eb293b8fSAndroid Build Coastguard Worker memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
251*eb293b8fSAndroid Build Coastguard Worker ehdr.e_ident[EI_CLASS] = class_type;
252*eb293b8fSAndroid Build Coastguard Worker ehdr.e_machine = machine_type;
253*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shstrndx = 1;
254*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = sh_offset;
255*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(ShdrType);
256*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 3;
257*eb293b8fSAndroid Build Coastguard Worker memory->SetMemory(offset, &ehdr, sizeof(ehdr));
258*eb293b8fSAndroid Build Coastguard Worker
259*eb293b8fSAndroid Build Coastguard Worker ShdrType shdr;
260*eb293b8fSAndroid Build Coastguard Worker memset(&shdr, 0, sizeof(shdr));
261*eb293b8fSAndroid Build Coastguard Worker shdr.sh_type = SHT_NULL;
262*eb293b8fSAndroid Build Coastguard Worker memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
263*eb293b8fSAndroid Build Coastguard Worker
264*eb293b8fSAndroid Build Coastguard Worker sh_offset += sizeof(shdr);
265*eb293b8fSAndroid Build Coastguard Worker memset(&shdr, 0, sizeof(shdr));
266*eb293b8fSAndroid Build Coastguard Worker shdr.sh_type = SHT_STRTAB;
267*eb293b8fSAndroid Build Coastguard Worker shdr.sh_name = 1;
268*eb293b8fSAndroid Build Coastguard Worker shdr.sh_offset = 0x500;
269*eb293b8fSAndroid Build Coastguard Worker shdr.sh_size = 0x100;
270*eb293b8fSAndroid Build Coastguard Worker memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
271*eb293b8fSAndroid Build Coastguard Worker memory->SetMemory(offset + 0x500, ".debug_frame");
272*eb293b8fSAndroid Build Coastguard Worker
273*eb293b8fSAndroid Build Coastguard Worker sh_offset += sizeof(shdr);
274*eb293b8fSAndroid Build Coastguard Worker memset(&shdr, 0, sizeof(shdr));
275*eb293b8fSAndroid Build Coastguard Worker shdr.sh_type = SHT_PROGBITS;
276*eb293b8fSAndroid Build Coastguard Worker shdr.sh_name = 0;
277*eb293b8fSAndroid Build Coastguard Worker shdr.sh_addr = 0x600;
278*eb293b8fSAndroid Build Coastguard Worker shdr.sh_offset = 0x600;
279*eb293b8fSAndroid Build Coastguard Worker shdr.sh_size = 0x200;
280*eb293b8fSAndroid Build Coastguard Worker memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
281*eb293b8fSAndroid Build Coastguard Worker
282*eb293b8fSAndroid Build Coastguard Worker // Now add a single cie/fde.
283*eb293b8fSAndroid Build Coastguard Worker uint64_t dwarf_offset = offset + 0x600;
284*eb293b8fSAndroid Build Coastguard Worker if (class_type == ELFCLASS32) {
285*eb293b8fSAndroid Build Coastguard Worker // CIE 32 information.
286*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset, 0xfc);
287*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x4, 0xffffffff);
288*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x8, 1);
289*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x9, '\0');
290*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0xa, 0x4);
291*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0xb, 0x4);
292*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0xc, 0x1);
293*eb293b8fSAndroid Build Coastguard Worker
294*eb293b8fSAndroid Build Coastguard Worker // FDE 32 information.
295*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x100, 0xfc);
296*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x104, 0);
297*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x108, pc);
298*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x10c, size);
299*eb293b8fSAndroid Build Coastguard Worker } else {
300*eb293b8fSAndroid Build Coastguard Worker // CIE 64 information.
301*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset, 0xffffffff);
302*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 4, 0xf4);
303*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL);
304*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x14, 1);
305*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x15, '\0');
306*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x16, 0x4);
307*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x17, 0x4);
308*eb293b8fSAndroid Build Coastguard Worker memory->SetData8(dwarf_offset + 0x18, 0x1);
309*eb293b8fSAndroid Build Coastguard Worker
310*eb293b8fSAndroid Build Coastguard Worker // FDE 64 information.
311*eb293b8fSAndroid Build Coastguard Worker memory->SetData32(dwarf_offset + 0x100, 0xffffffff);
312*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 0x104, 0xf4);
313*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 0x10c, 0);
314*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 0x114, pc);
315*eb293b8fSAndroid Build Coastguard Worker memory->SetData64(dwarf_offset + 0x11c, size);
316*eb293b8fSAndroid Build Coastguard Worker }
317*eb293b8fSAndroid Build Coastguard Worker }
318*eb293b8fSAndroid Build Coastguard Worker
PutElfFilesInMemory(MemoryFake * memory,FuzzedDataProvider * data_provider)319*eb293b8fSAndroid Build Coastguard Worker void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider) {
320*eb293b8fSAndroid Build Coastguard Worker uint8_t elf_file_count = data_provider->ConsumeIntegralInRange<uint8_t>(0, kMaxJitElfFiles);
321*eb293b8fSAndroid Build Coastguard Worker int entry_offset = 0;
322*eb293b8fSAndroid Build Coastguard Worker int prev_jit_addr = 0;
323*eb293b8fSAndroid Build Coastguard Worker for (uint8_t i = 0; i < elf_file_count; i++) {
324*eb293b8fSAndroid Build Coastguard Worker uint64_t offset = data_provider->ConsumeIntegral<uint64_t>();
325*eb293b8fSAndroid Build Coastguard Worker // Technically the max valid value is ELFCLASSNUM - 1 (2), but
326*eb293b8fSAndroid Build Coastguard Worker // we want to test values outside of that range.
327*eb293b8fSAndroid Build Coastguard Worker uint8_t class_type = data_provider->ConsumeIntegral<uint8_t>();
328*eb293b8fSAndroid Build Coastguard Worker // Same here, EM_NUM is 253, max valid machine type is 252
329*eb293b8fSAndroid Build Coastguard Worker uint8_t machine_type = data_provider->ConsumeIntegral<uint8_t>();
330*eb293b8fSAndroid Build Coastguard Worker uint32_t pc = data_provider->ConsumeIntegral<uint32_t>();
331*eb293b8fSAndroid Build Coastguard Worker uint32_t size = data_provider->ConsumeIntegral<uint32_t>();
332*eb293b8fSAndroid Build Coastguard Worker bool sixty_four_bit = data_provider->ConsumeBool();
333*eb293b8fSAndroid Build Coastguard Worker bool write_jit = data_provider->ConsumeBool();
334*eb293b8fSAndroid Build Coastguard Worker if (sixty_four_bit) {
335*eb293b8fSAndroid Build Coastguard Worker PutElfInMemory<Elf64_Ehdr, Elf64_Shdr>(memory, offset, class_type, machine_type, pc, size);
336*eb293b8fSAndroid Build Coastguard Worker } else {
337*eb293b8fSAndroid Build Coastguard Worker PutElfInMemory<Elf32_Ehdr, Elf32_Shdr>(memory, offset, class_type, machine_type, pc, size);
338*eb293b8fSAndroid Build Coastguard Worker }
339*eb293b8fSAndroid Build Coastguard Worker if (write_jit) {
340*eb293b8fSAndroid Build Coastguard Worker bool use_pad = data_provider->ConsumeBool();
341*eb293b8fSAndroid Build Coastguard Worker // It is possible this will overwrite part of the ELF.
342*eb293b8fSAndroid Build Coastguard Worker // This provides an interesting test of how malformed ELF
343*eb293b8fSAndroid Build Coastguard Worker // data is handled.
344*eb293b8fSAndroid Build Coastguard Worker uint64_t cur_descriptor_addr = 0x11800 + entry_offset;
345*eb293b8fSAndroid Build Coastguard Worker uint64_t cur_jit_addr = 0x200000 + entry_offset;
346*eb293b8fSAndroid Build Coastguard Worker uint64_t next_jit_addr = cur_jit_addr + size;
347*eb293b8fSAndroid Build Coastguard Worker if (sixty_four_bit) {
348*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(memory, 0x11800, cur_jit_addr);
349*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
350*eb293b8fSAndroid Build Coastguard Worker } else {
351*eb293b8fSAndroid Build Coastguard Worker // Loop back. Again, this may corrupt data,
352*eb293b8fSAndroid Build Coastguard Worker // but that will allow for testing edge cases with
353*eb293b8fSAndroid Build Coastguard Worker // malformed JIT data.
354*eb293b8fSAndroid Build Coastguard Worker if (cur_jit_addr > UINT32_MAX) {
355*eb293b8fSAndroid Build Coastguard Worker entry_offset = 0;
356*eb293b8fSAndroid Build Coastguard Worker cur_jit_addr = 0x200000;
357*eb293b8fSAndroid Build Coastguard Worker cur_descriptor_addr = 0x11800;
358*eb293b8fSAndroid Build Coastguard Worker next_jit_addr = cur_jit_addr + size;
359*eb293b8fSAndroid Build Coastguard Worker }
360*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(memory, cur_descriptor_addr, cur_jit_addr);
361*eb293b8fSAndroid Build Coastguard Worker if (use_pad) {
362*eb293b8fSAndroid Build Coastguard Worker WriteEntry32Pad(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
363*eb293b8fSAndroid Build Coastguard Worker } else {
364*eb293b8fSAndroid Build Coastguard Worker WriteEntry32Pack(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size);
365*eb293b8fSAndroid Build Coastguard Worker }
366*eb293b8fSAndroid Build Coastguard Worker }
367*eb293b8fSAndroid Build Coastguard Worker entry_offset += size;
368*eb293b8fSAndroid Build Coastguard Worker prev_jit_addr = cur_jit_addr;
369*eb293b8fSAndroid Build Coastguard Worker }
370*eb293b8fSAndroid Build Coastguard Worker }
371*eb293b8fSAndroid Build Coastguard Worker }
372*eb293b8fSAndroid Build Coastguard Worker
GetStringList(FuzzedDataProvider * data_provider,uint max_str_len,uint max_strings)373*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> GetStringList(FuzzedDataProvider* data_provider, uint max_str_len,
374*eb293b8fSAndroid Build Coastguard Worker uint max_strings) {
375*eb293b8fSAndroid Build Coastguard Worker uint str_count = data_provider->ConsumeIntegralInRange<uint>(0, max_strings);
376*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> strings;
377*eb293b8fSAndroid Build Coastguard Worker for (uint i = 0; i < str_count; i++) {
378*eb293b8fSAndroid Build Coastguard Worker strings.push_back(data_provider->ConsumeRandomLengthString(max_str_len));
379*eb293b8fSAndroid Build Coastguard Worker }
380*eb293b8fSAndroid Build Coastguard Worker return strings;
381*eb293b8fSAndroid Build Coastguard Worker }
382*eb293b8fSAndroid Build Coastguard Worker
GetDexFiles(FuzzedDataProvider * data_provider,std::shared_ptr<Memory> memory,uint max_library_length,uint max_libraries,ArchEnum arch)383*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<DexFiles> GetDexFiles(FuzzedDataProvider* data_provider,
384*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> memory, uint max_library_length,
385*eb293b8fSAndroid Build Coastguard Worker uint max_libraries, ArchEnum arch) {
386*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> search_libs =
387*eb293b8fSAndroid Build Coastguard Worker GetStringList(data_provider, max_library_length, max_libraries);
388*eb293b8fSAndroid Build Coastguard Worker if (search_libs.size() <= 0) {
389*eb293b8fSAndroid Build Coastguard Worker return CreateDexFiles(arch, memory);
390*eb293b8fSAndroid Build Coastguard Worker }
391*eb293b8fSAndroid Build Coastguard Worker
392*eb293b8fSAndroid Build Coastguard Worker return CreateDexFiles(arch, memory, search_libs);
393*eb293b8fSAndroid Build Coastguard Worker }
394