blob: 20bc4b9022b696d794fd102cdcb91697b51493fd [file] [log] [blame]
Christopher Ferris150db122017-12-20 18:49:01 -08001/*
2 * Copyright (C) 2017 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 <stdint.h>
18#include <sys/mman.h>
19
20#include <memory>
21#include <vector>
22
23#include <unwindstack/Elf.h>
24#include <unwindstack/JitDebug.h>
25#include <unwindstack/Maps.h>
26#include <unwindstack/Memory.h>
27
28// This implements the JIT Compilation Interface.
29// See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html
30
31namespace unwindstack {
32
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000033struct JITCodeEntry32Pack {
34 uint32_t next;
35 uint32_t prev;
36 uint32_t symfile_addr;
37 uint64_t symfile_size;
Christopher Ferris150db122017-12-20 18:49:01 -080038} __attribute__((packed));
39
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000040struct JITCodeEntry32Pad {
41 uint32_t next;
42 uint32_t prev;
43 uint32_t symfile_addr;
44 uint32_t pad;
45 uint64_t symfile_size;
Christopher Ferris150db122017-12-20 18:49:01 -080046};
47
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000048struct JITCodeEntry64 {
49 uint64_t next;
50 uint64_t prev;
51 uint64_t symfile_addr;
52 uint64_t symfile_size;
Christopher Ferris150db122017-12-20 18:49:01 -080053};
54
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000055struct JITDescriptorHeader {
56 uint32_t version;
57 uint32_t action_flag;
58};
David Srbecky85b5fec2018-02-23 18:06:13 +000059
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000060struct JITDescriptor32 {
61 JITDescriptorHeader header;
62 uint32_t relevant_entry;
63 uint32_t first_entry;
64};
David Srbecky85b5fec2018-02-23 18:06:13 +000065
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000066struct JITDescriptor64 {
67 JITDescriptorHeader header;
68 uint64_t relevant_entry;
69 uint64_t first_entry;
70};
David Srbecky85b5fec2018-02-23 18:06:13 +000071
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000072JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}
David Srbecky85b5fec2018-02-23 18:06:13 +000073
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000074JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
75 : Global(memory, search_libs) {}
76
77JitDebug::~JitDebug() {
78 for (auto* elf : elf_list_) {
79 delete elf;
80 }
81}
82
83uint64_t JitDebug::ReadDescriptor32(uint64_t addr) {
84 JITDescriptor32 desc;
85 if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
86 return 0;
David Srbecky85b5fec2018-02-23 18:06:13 +000087 }
88
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000089 if (desc.header.version != 1 || desc.first_entry == 0) {
90 // Either unknown version, or no jit entries.
91 return 0;
92 }
David Srbecky85b5fec2018-02-23 18:06:13 +000093
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000094 return desc.first_entry;
95}
David Srbecky85b5fec2018-02-23 18:06:13 +000096
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000097uint64_t JitDebug::ReadDescriptor64(uint64_t addr) {
98 JITDescriptor64 desc;
99 if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
100 return 0;
101 }
David Srbecky85b5fec2018-02-23 18:06:13 +0000102
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000103 if (desc.header.version != 1 || desc.first_entry == 0) {
104 // Either unknown version, or no jit entries.
105 return 0;
106 }
Christopher Ferris150db122017-12-20 18:49:01 -0800107
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000108 return desc.first_entry;
109}
110
111uint64_t JitDebug::ReadEntry32Pack(uint64_t* start, uint64_t* size) {
112 JITCodeEntry32Pack code;
113 if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
114 return 0;
115 }
116
117 *start = code.symfile_addr;
118 *size = code.symfile_size;
119 return code.next;
120}
121
122uint64_t JitDebug::ReadEntry32Pad(uint64_t* start, uint64_t* size) {
123 JITCodeEntry32Pad code;
124 if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
125 return 0;
126 }
127
128 *start = code.symfile_addr;
129 *size = code.symfile_size;
130 return code.next;
131}
132
133uint64_t JitDebug::ReadEntry64(uint64_t* start, uint64_t* size) {
134 JITCodeEntry64 code;
135 if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
136 return 0;
137 }
138
139 *start = code.symfile_addr;
140 *size = code.symfile_size;
141 return code.next;
142}
143
144void JitDebug::ProcessArch() {
145 switch (arch()) {
Christopher Ferris150db122017-12-20 18:49:01 -0800146 case ARCH_X86:
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000147 read_descriptor_func_ = &JitDebug::ReadDescriptor32;
148 read_entry_func_ = &JitDebug::ReadEntry32Pack;
Christopher Ferris150db122017-12-20 18:49:01 -0800149 break;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000150
Christopher Ferris150db122017-12-20 18:49:01 -0800151 case ARCH_ARM:
152 case ARCH_MIPS:
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000153 read_descriptor_func_ = &JitDebug::ReadDescriptor32;
154 read_entry_func_ = &JitDebug::ReadEntry32Pad;
Christopher Ferris150db122017-12-20 18:49:01 -0800155 break;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000156
Christopher Ferris150db122017-12-20 18:49:01 -0800157 case ARCH_ARM64:
158 case ARCH_X86_64:
159 case ARCH_MIPS64:
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000160 read_descriptor_func_ = &JitDebug::ReadDescriptor64;
161 read_entry_func_ = &JitDebug::ReadEntry64;
Christopher Ferris150db122017-12-20 18:49:01 -0800162 break;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000163 case ARCH_UNKNOWN:
Christopher Ferris150db122017-12-20 18:49:01 -0800164 abort();
165 }
166}
167
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000168bool JitDebug::ReadVariableData(uint64_t ptr) {
169 entry_addr_ = (this->*read_descriptor_func_)(ptr);
170 return entry_addr_ != 0;
Christopher Ferris150db122017-12-20 18:49:01 -0800171}
172
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000173void JitDebug::Init(Maps* maps) {
174 if (initialized_) {
175 return;
David Srbecky85b5fec2018-02-23 18:06:13 +0000176 }
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000177 // Regardless of what happens below, consider the init finished.
178 initialized_ = true;
179
180 FindAndReadVariable(maps, "__jit_debug_descriptor");
David Srbecky85b5fec2018-02-23 18:06:13 +0000181}
182
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000183Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
184 // Use a single lock, this object should be used so infrequently that
185 // a fine grain lock is unnecessary.
Christopher Ferris150db122017-12-20 18:49:01 -0800186 std::lock_guard<std::mutex> guard(lock_);
187 if (!initialized_) {
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000188 Init(maps);
Christopher Ferris150db122017-12-20 18:49:01 -0800189 }
190
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000191 // Search the existing elf object first.
192 for (Elf* elf : elf_list_) {
193 if (elf->IsValidPc(pc)) {
194 return elf;
David Srbecky85b5fec2018-02-23 18:06:13 +0000195 }
196 }
197
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000198 while (entry_addr_ != 0) {
199 uint64_t start;
200 uint64_t size;
201 entry_addr_ = (this->*read_entry_func_)(&start, &size);
David Srbecky85b5fec2018-02-23 18:06:13 +0000202
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000203 Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0));
204 elf->Init();
205 if (!elf->valid()) {
206 // The data is not formatted in a way we understand, do not attempt
207 // to process any other entries.
208 entry_addr_ = 0;
209 delete elf;
210 return nullptr;
211 }
212 elf_list_.push_back(elf);
213
214 if (elf->IsValidPc(pc)) {
215 return elf;
216 }
David Srbecky85b5fec2018-02-23 18:06:13 +0000217 }
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000218 return nullptr;
David Srbecky85b5fec2018-02-23 18:06:13 +0000219}
220
Christopher Ferris150db122017-12-20 18:49:01 -0800221} // namespace unwindstack