1 /*
2 * Copyright 2020 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 #include <functional>
18 #include <iostream>
19 #include <vector>
20
21 #include <unwindstack/JitDebug.h>
22 #include <unwindstack/Maps.h>
23 #include <unwindstack/Memory.h>
24 #include <unwindstack/Unwinder.h>
25
26 #include "UnwinderComponentCreator.h"
27 #include "fuzzer/FuzzedDataProvider.h"
28 #include "utils/MemoryFake.h"
29
30 namespace unwindstack {
31
32 static constexpr int kMaxUnwindStringLen = 50;
33 static constexpr int kMaxUnwindStrings = 50;
34
PerformUnwind(FuzzedDataProvider * data_provider,Unwinder * unwinder)35 void PerformUnwind(FuzzedDataProvider* data_provider, Unwinder* unwinder) {
36 // 0 = don't set any values
37 // 1 = set initial_map_names_to_skip
38 // 2 = set map_suffixes_to_ignore
39 // 3 = set both
40 uint8_t set_values = data_provider->ConsumeIntegral<uint8_t>() % 4;
41 if (set_values == 0) {
42 unwinder->Unwind();
43 } else if (set_values == 1) {
44 // Only setting initial_map_names_to_skip
45 std::vector<std::string> skip_names =
46 GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
47
48 unwinder->Unwind(&skip_names, nullptr);
49 } else if (set_values == 2) {
50 // Only setting map_suffixes_to_ignore
51 std::vector<std::string> ignore_suffixes =
52 GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
53
54 unwinder->Unwind(nullptr, &ignore_suffixes);
55 } else if (set_values == 3) {
56 // Setting both values
57 std::vector<std::string> skip_names =
58 GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
59 std::vector<std::string> ignore_suffixes =
60 GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings);
61
62 unwinder->Unwind(&skip_names, &ignore_suffixes);
63 }
64 }
65
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)66 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
67 FuzzedDataProvider data_provider(data, size);
68
69 // We need to construct an unwinder.
70 // Generate the Maps:
71 std::unique_ptr<Maps> maps = GetMaps(&data_provider);
72
73 // Generate the Regs:
74 uint8_t arch_val = data_provider.ConsumeIntegralInRange<uint8_t>(1, kArchCount);
75 ArchEnum arch = static_cast<ArchEnum>(arch_val);
76 std::unique_ptr<Regs> regs = GetRegisters(arch);
77
78 // Generate memory:
79 std::shared_ptr<Memory> memory = std::make_shared<MemoryFake>();
80 PutElfFilesInMemory(reinterpret_cast<MemoryFake*>(memory.get()), &data_provider);
81
82 size_t max_frames = data_provider.ConsumeIntegralInRange<size_t>(0, 5000);
83
84 std::unique_ptr<JitDebug> jit_debug_ptr = CreateJitDebug(arch, memory);
85
86 // Create instance
87 Unwinder unwinder(max_frames, maps.get(), regs.get(), memory);
88 unwinder.SetJitDebug(jit_debug_ptr.get());
89 unwinder.SetResolveNames(data_provider.ConsumeBool());
90 // Call unwind
91 PerformUnwind(&data_provider, &unwinder);
92
93 // Run some additional logic that changes after unwind
94 uint64_t pc = data_provider.ConsumeIntegral<uint64_t>();
95 unwinder.BuildFrameFromPcOnly(pc);
96 unwinder.ConsumeFrames();
97 return 0;
98 }
99 } // namespace unwindstack
100