blob: 384fc9a32dad7d60fbb1a27196bfe72e8b391f88 [file] [log] [blame]
Saleem Abdulrasool17552662015-04-24 19:39:17 +00001//===------------------------- AddressSpace.hpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Abstracts accessing local vs remote address spaces.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __ADDRESSSPACE_HPP__
14#define __ADDRESSSPACE_HPP__
15
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
Martin Storsjo4c1f84d2017-10-11 20:06:18 +000021#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
Saleem Abdulrasool17552662015-04-24 19:39:17 +000022#include <dlfcn.h>
23#endif
24
25#ifdef __APPLE__
26#include <mach-o/getsect.h>
27namespace libunwind {
28 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
29}
30#endif
31
32#include "libunwind.h"
33#include "config.h"
34#include "dwarf2.h"
Ed Schoutenda7d6252017-03-07 18:21:51 +000035#include "EHHeaderParser.hpp"
Saleem Abdulrasool17552662015-04-24 19:39:17 +000036#include "Registers.hpp"
37
John Baldwin67737ec2017-09-21 21:28:48 +000038#ifdef __APPLE__
39
40 struct dyld_unwind_sections
41 {
42 const struct mach_header* mh;
43 const void* dwarf_section;
44 uintptr_t dwarf_section_length;
45 const void* compact_unwind_section;
46 uintptr_t compact_unwind_section_length;
47 };
48 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
49 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
50 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
51 // In 10.7.0 or later, libSystem.dylib implements this function.
52 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
53 #else
54 // In 10.6.x and earlier, we need to implement this functionality. Note
55 // that this requires a newer version of libmacho (from cctools) than is
56 // present in libSystem on 10.6.x (for getsectiondata).
57 static inline bool _dyld_find_unwind_sections(void* addr,
58 dyld_unwind_sections* info) {
59 // Find mach-o image containing address.
60 Dl_info dlinfo;
61 if (!dladdr(addr, &dlinfo))
62 return false;
63#if __LP64__
64 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
65#else
66 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
67#endif
68
69 // Initialize the return struct
70 info->mh = (const struct mach_header *)mh;
71 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
72 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
73
74 if (!info->dwarf_section) {
75 info->dwarf_section_length = 0;
76 }
77
78 if (!info->compact_unwind_section) {
79 info->compact_unwind_section_length = 0;
80 }
81
82 return true;
83 }
84 #endif
85
whitequarkffd92e52017-12-25 17:05:07 +000086#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
87
88// When statically linked on bare-metal, the symbols for the EH table are looked
89// up without going through the dynamic loader.
90
91// The following linker script may be used to produce the necessary sections and symbols.
92// Unless the --eh-frame-hdr linker option is provided, the section is not generated
93// and does not take space in the output file.
94//
95// .eh_frame :
96// {
97// __eh_frame_start = .;
98// KEEP(*(.eh_frame))
99// __eh_frame_end = .;
100// }
101//
102// .eh_frame_hdr :
103// {
104// KEEP(*(.eh_frame_hdr))
105// }
106//
107// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
108// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
109
110extern char __eh_frame_start;
111extern char __eh_frame_end;
112
113#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
114extern char __eh_frame_hdr_start;
115extern char __eh_frame_hdr_end;
116#endif
117
John Baldwin67737ec2017-09-21 21:28:48 +0000118#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
119
120// When statically linked on bare-metal, the symbols for the EH table are looked
121// up without going through the dynamic loader.
122extern char __exidx_start;
123extern char __exidx_end;
124
125#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
126
127// ELF-based systems may use dl_iterate_phdr() to access sections
128// containing unwinding information. The ElfW() macro for pointer-size
129// independent ELF header traversal is not provided by <link.h> on some
130// systems (e.g., FreeBSD). On these systems the data structures are
131// just called Elf_XXX. Define ElfW() locally.
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000132#ifndef _WIN32
John Baldwin67737ec2017-09-21 21:28:48 +0000133#include <link.h>
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000134#else
135#include <windows.h>
136#include <psapi.h>
137#endif
John Baldwin67737ec2017-09-21 21:28:48 +0000138#if !defined(ElfW)
139#define ElfW(type) Elf_##type
140#endif
141
142#endif
143
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000144namespace libunwind {
145
146/// Used by findUnwindSections() to return info about needed sections.
147struct UnwindInfoSections {
Ranjeet Singh421231a2017-03-31 15:28:06 +0000148#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
149 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000150 // No dso_base for ARM EHABI.
151 uintptr_t dso_base;
152#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000153#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000154 uintptr_t dwarf_section;
155 uintptr_t dwarf_section_length;
156#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000157#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000158 uintptr_t dwarf_index_section;
159 uintptr_t dwarf_index_section_length;
160#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000161#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000162 uintptr_t compact_unwind_section;
163 uintptr_t compact_unwind_section_length;
164#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000165#if defined(_LIBUNWIND_ARM_EHABI)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000166 uintptr_t arm_section;
167 uintptr_t arm_section_length;
168#endif
169};
170
171
172/// LocalAddressSpace is used as a template parameter to UnwindCursor when
173/// unwinding a thread in the same process. The wrappers compile away,
174/// making local unwinds fast.
175class __attribute__((visibility("hidden"))) LocalAddressSpace {
176public:
Martin Storsjocac41382017-10-27 08:11:36 +0000177 typedef uintptr_t pint_t;
178 typedef intptr_t sint_t;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000179 uint8_t get8(pint_t addr) {
180 uint8_t val;
181 memcpy(&val, (void *)addr, sizeof(val));
182 return val;
183 }
184 uint16_t get16(pint_t addr) {
185 uint16_t val;
186 memcpy(&val, (void *)addr, sizeof(val));
187 return val;
188 }
189 uint32_t get32(pint_t addr) {
190 uint32_t val;
191 memcpy(&val, (void *)addr, sizeof(val));
192 return val;
193 }
194 uint64_t get64(pint_t addr) {
195 uint64_t val;
196 memcpy(&val, (void *)addr, sizeof(val));
197 return val;
198 }
199 double getDouble(pint_t addr) {
200 double val;
201 memcpy(&val, (void *)addr, sizeof(val));
202 return val;
203 }
204 v128 getVector(pint_t addr) {
205 v128 val;
206 memcpy(&val, (void *)addr, sizeof(val));
207 return val;
208 }
209 uintptr_t getP(pint_t addr);
210 static uint64_t getULEB128(pint_t &addr, pint_t end);
211 static int64_t getSLEB128(pint_t &addr, pint_t end);
212
213 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
214 pint_t datarelBase = 0);
215 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
216 unw_word_t *offset);
217 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
218 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
219
220 static LocalAddressSpace sThisAddressSpace;
221};
222
223inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
Martin Storsjocac41382017-10-27 08:11:36 +0000224#if __SIZEOF_POINTER__ == 8
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000225 return get64(addr);
226#else
227 return get32(addr);
228#endif
229}
230
231/// Read a ULEB128 into a 64-bit word.
232inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
233 const uint8_t *p = (uint8_t *)addr;
234 const uint8_t *pend = (uint8_t *)end;
235 uint64_t result = 0;
236 int bit = 0;
237 do {
238 uint64_t b;
239
240 if (p == pend)
241 _LIBUNWIND_ABORT("truncated uleb128 expression");
242
243 b = *p & 0x7f;
244
245 if (bit >= 64 || b << bit >> bit != b) {
246 _LIBUNWIND_ABORT("malformed uleb128 expression");
247 } else {
248 result |= b << bit;
249 bit += 7;
250 }
251 } while (*p++ >= 0x80);
252 addr = (pint_t) p;
253 return result;
254}
255
256/// Read a SLEB128 into a 64-bit word.
257inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
258 const uint8_t *p = (uint8_t *)addr;
259 const uint8_t *pend = (uint8_t *)end;
260 int64_t result = 0;
261 int bit = 0;
262 uint8_t byte;
263 do {
264 if (p == pend)
265 _LIBUNWIND_ABORT("truncated sleb128 expression");
266 byte = *p++;
267 result |= ((byte & 0x7f) << bit);
268 bit += 7;
269 } while (byte & 0x80);
270 // sign extend negative numbers
271 if ((byte & 0x40) != 0)
Marshall Clowa6d7c382017-06-21 16:02:53 +0000272 result |= (-1ULL) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000273 addr = (pint_t) p;
274 return result;
275}
276
277inline LocalAddressSpace::pint_t
278LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
279 pint_t datarelBase) {
280 pint_t startAddr = addr;
281 const uint8_t *p = (uint8_t *)addr;
282 pint_t result;
283
284 // first get value
285 switch (encoding & 0x0F) {
286 case DW_EH_PE_ptr:
287 result = getP(addr);
288 p += sizeof(pint_t);
289 addr = (pint_t) p;
290 break;
291 case DW_EH_PE_uleb128:
292 result = (pint_t)getULEB128(addr, end);
293 break;
294 case DW_EH_PE_udata2:
295 result = get16(addr);
296 p += 2;
297 addr = (pint_t) p;
298 break;
299 case DW_EH_PE_udata4:
300 result = get32(addr);
301 p += 4;
302 addr = (pint_t) p;
303 break;
304 case DW_EH_PE_udata8:
305 result = (pint_t)get64(addr);
306 p += 8;
307 addr = (pint_t) p;
308 break;
309 case DW_EH_PE_sleb128:
310 result = (pint_t)getSLEB128(addr, end);
311 break;
312 case DW_EH_PE_sdata2:
313 // Sign extend from signed 16-bit value.
314 result = (pint_t)(int16_t)get16(addr);
315 p += 2;
316 addr = (pint_t) p;
317 break;
318 case DW_EH_PE_sdata4:
319 // Sign extend from signed 32-bit value.
320 result = (pint_t)(int32_t)get32(addr);
321 p += 4;
322 addr = (pint_t) p;
323 break;
324 case DW_EH_PE_sdata8:
325 result = (pint_t)get64(addr);
326 p += 8;
327 addr = (pint_t) p;
328 break;
329 default:
330 _LIBUNWIND_ABORT("unknown pointer encoding");
331 }
332
333 // then add relative offset
334 switch (encoding & 0x70) {
335 case DW_EH_PE_absptr:
336 // do nothing
337 break;
338 case DW_EH_PE_pcrel:
339 result += startAddr;
340 break;
341 case DW_EH_PE_textrel:
342 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
343 break;
344 case DW_EH_PE_datarel:
345 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
346 // default value of 0, and we abort in the event that someone calls this
347 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
348 if (datarelBase == 0)
349 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
350 result += datarelBase;
351 break;
352 case DW_EH_PE_funcrel:
353 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
354 break;
355 case DW_EH_PE_aligned:
356 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
357 break;
358 default:
359 _LIBUNWIND_ABORT("unknown pointer encoding");
360 break;
361 }
362
363 if (encoding & DW_EH_PE_indirect)
364 result = getP(result);
365
366 return result;
367}
368
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000369inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
370 UnwindInfoSections &info) {
371#ifdef __APPLE__
372 dyld_unwind_sections dyldInfo;
373 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
374 info.dso_base = (uintptr_t)dyldInfo.mh;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000375 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000376 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
377 info.dwarf_section_length = dyldInfo.dwarf_section_length;
378 #endif
379 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
380 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
381 return true;
382 }
whitequarkffd92e52017-12-25 17:05:07 +0000383#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
384 // Bare metal is statically linked, so no need to ask the dynamic loader
385 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
386 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000387 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
388 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000389#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
390 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
391 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000392 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
393 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000394#endif
395 if (info.dwarf_section_length)
396 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000397#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000398 // Bare metal is statically linked, so no need to ask the dynamic loader
399 info.arm_section = (uintptr_t)(&__exidx_start);
400 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000401 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
402 (void *)info.arm_section, (void *)info.arm_section_length);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000403 if (info.arm_section && info.arm_section_length)
404 return true;
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000405#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
406 HMODULE mods[1024];
407 HANDLE process = GetCurrentProcess();
408 DWORD needed;
409
410 if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
411 return false;
412
413 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
414 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
415 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
416 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
417 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
418 bool found_obj = false;
419 bool found_hdr = false;
420
421 info.dso_base = (uintptr_t)mods[i];
422 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
423 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
424 uintptr_t end = begin + pish->Misc.VirtualSize;
425 if (!strncmp((const char *)pish->Name, ".text",
426 IMAGE_SIZEOF_SHORT_NAME)) {
427 if (targetAddr >= begin && targetAddr < end)
428 found_obj = true;
429 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
430 IMAGE_SIZEOF_SHORT_NAME)) {
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000431 info.dwarf_section = begin;
432 info.dwarf_section_length = pish->Misc.VirtualSize;
433 found_hdr = true;
434 }
435 if (found_obj && found_hdr)
436 return true;
437 }
438 }
439 return false;
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000440#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
441 (__ANDROID_API__ < 21)
442 int length = 0;
443 info.arm_section =
444 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
445 info.arm_section_length = (uintptr_t)length;
446 if (info.arm_section && info.arm_section_length)
447 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000448#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000449 struct dl_iterate_cb_data {
450 LocalAddressSpace *addressSpace;
451 UnwindInfoSections *sects;
452 uintptr_t targetAddr;
453 };
454
455 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
456 int found = dl_iterate_phdr(
457 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
458 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
Ed Schouten08032ee2017-02-23 09:13:22 +0000459 bool found_obj = false;
460 bool found_hdr = false;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000461
462 assert(cbdata);
463 assert(cbdata->sects);
464
465 if (cbdata->targetAddr < pinfo->dlpi_addr) {
466 return false;
467 }
468
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000469#if !defined(Elf_Half)
470 typedef ElfW(Half) Elf_Half;
471#endif
472#if !defined(Elf_Phdr)
473 typedef ElfW(Phdr) Elf_Phdr;
474#endif
Ivan Krasind34d77f2017-04-06 17:35:35 +0000475#if !defined(Elf_Addr) && defined(__ANDROID__)
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000476 typedef ElfW(Addr) Elf_Addr;
477#endif
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000478
Ranjeet Singh421231a2017-03-31 15:28:06 +0000479 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
480 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000481 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
482 #endif
483 size_t object_length;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000484#if defined(__ANDROID__)
485 Elf_Addr image_base =
Saleem Abdulrasoole4fe5f92017-04-05 21:29:38 +0000486 pinfo->dlpi_phnum
487 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
488 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
489 ->p_offset
490 : 0;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000491#endif
492
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000493 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
494 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000495 if (phdr->p_type == PT_LOAD) {
496 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000497#if defined(__ANDROID__)
498 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
499 begin = begin + image_base;
500#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000501 uintptr_t end = begin + phdr->p_memsz;
502 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
503 cbdata->sects->dso_base = begin;
504 object_length = phdr->p_memsz;
505 found_obj = true;
506 }
507 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
508 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
509 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000510#if defined(__ANDROID__)
511 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
512 eh_frame_hdr_start = eh_frame_hdr_start + image_base;
513#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000514 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
515 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
516 EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
517 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
518 hdrInfo);
519 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
520 found_hdr = true;
521 }
522 }
523
524 if (found_obj && found_hdr) {
525 cbdata->sects->dwarf_section_length = object_length;
526 return true;
527 } else {
528 return false;
529 }
Ranjeet Singh421231a2017-03-31 15:28:06 +0000530 #else // defined(_LIBUNWIND_ARM_EHABI)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000531 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
532 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
533 if (phdr->p_type == PT_LOAD) {
534 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
535 uintptr_t end = begin + phdr->p_memsz;
536 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
537 found_obj = true;
538 } else if (phdr->p_type == PT_ARM_EXIDX) {
539 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
540 cbdata->sects->arm_section = exidx_start;
Ed Schouten5d3f35b2017-03-07 15:21:57 +0000541 cbdata->sects->arm_section_length = phdr->p_memsz;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000542 found_hdr = true;
543 }
544 }
545 return found_obj && found_hdr;
546 #endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000547 },
548 &cb_data);
549 return static_cast<bool>(found);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000550#endif
551
552 return false;
553}
554
555
556inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
557#ifdef __APPLE__
558 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
559#else
560 // TO DO: if OS has way to dynamically register FDEs, check that.
561 (void)targetAddr;
562 (void)fde;
563 return false;
564#endif
565}
566
567inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
568 size_t bufLen,
569 unw_word_t *offset) {
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000570#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000571 Dl_info dyldInfo;
572 if (dladdr((void *)addr, &dyldInfo)) {
573 if (dyldInfo.dli_sname != NULL) {
574 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
575 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
576 return true;
577 }
578 }
579#endif
580 return false;
581}
582
583
584
585#ifdef UNW_REMOTE
586
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000587/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000588/// unwinding a thread in the another process. The other process can be a
589/// different endianness and a different pointer size which is handled by
590/// the P template parameter.
591template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000592class RemoteAddressSpace {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000593public:
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000594 RemoteAddressSpace(task_t task) : fTask(task) {}
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000595
596 typedef typename P::uint_t pint_t;
597
598 uint8_t get8(pint_t addr);
599 uint16_t get16(pint_t addr);
600 uint32_t get32(pint_t addr);
601 uint64_t get64(pint_t addr);
602 pint_t getP(pint_t addr);
603 uint64_t getULEB128(pint_t &addr, pint_t end);
604 int64_t getSLEB128(pint_t &addr, pint_t end);
605 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
606 pint_t datarelBase = 0);
607 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
608 unw_word_t *offset);
609 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
610 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
611private:
612 void *localCopy(pint_t addr);
613
614 task_t fTask;
615};
616
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000617template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000618 return *((uint8_t *)localCopy(addr));
619}
620
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000621template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000622 return P::E::get16(*(uint16_t *)localCopy(addr));
623}
624
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000625template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000626 return P::E::get32(*(uint32_t *)localCopy(addr));
627}
628
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000629template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000630 return P::E::get64(*(uint64_t *)localCopy(addr));
631}
632
633template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000634typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000635 return P::getP(*(uint64_t *)localCopy(addr));
636}
637
638template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000639uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000640 uintptr_t size = (end - addr);
641 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
642 LocalAddressSpace::pint_t sladdr = laddr;
643 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
644 addr += (laddr - sladdr);
645 return result;
646}
647
648template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000649int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000650 uintptr_t size = (end - addr);
651 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
652 LocalAddressSpace::pint_t sladdr = laddr;
653 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
654 addr += (laddr - sladdr);
655 return result;
656}
657
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000658template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000659 // FIX ME
660}
661
662template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000663bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
664 size_t bufLen,
665 unw_word_t *offset) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000666 // FIX ME
667}
668
669/// unw_addr_space is the base class that abstract unw_addr_space_t type in
670/// libunwind.h points to.
671struct unw_addr_space {
672 cpu_type_t cpuType;
673 task_t taskPort;
674};
675
676/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
677/// to when examining
678/// a 32-bit intel process.
679struct unw_addr_space_i386 : public unw_addr_space {
680 unw_addr_space_i386(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000681 RemoteAddressSpace<Pointer32<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000682};
683
684/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
685/// points to when examining
686/// a 64-bit intel process.
687struct unw_addr_space_x86_64 : public unw_addr_space {
688 unw_addr_space_x86_64(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000689 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000690};
691
692/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
693/// to when examining
694/// a 32-bit PowerPC process.
695struct unw_addr_space_ppc : public unw_addr_space {
696 unw_addr_space_ppc(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000697 RemoteAddressSpace<Pointer32<BigEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000698};
699
Martin Storsjo8338b0a2018-01-02 22:11:30 +0000700/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
701/// to when examining a 64-bit PowerPC process.
702struct unw_addr_space_ppc64 : public unw_addr_space {
703 unw_addr_space_ppc64(task_t task) : oas(task) {}
704 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
705};
706
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000707#endif // UNW_REMOTE
708
709} // namespace libunwind
710
711#endif // __ADDRESSSPACE_HPP__