blob: 32e66bbd2e85c917b5bfa054d86b9cb57e040fbb [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
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +000021#ifndef _LIBUNWIND_USE_DLADDR
22 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
23 #define _LIBUNWIND_USE_DLADDR 1
24 #else
25 #define _LIBUNWIND_USE_DLADDR 0
26 #endif
27#endif
28
29#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +000030#include <dlfcn.h>
31#endif
32
33#ifdef __APPLE__
34#include <mach-o/getsect.h>
35namespace libunwind {
36 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
37}
38#endif
39
40#include "libunwind.h"
41#include "config.h"
42#include "dwarf2.h"
Ed Schoutenda7d6252017-03-07 18:21:51 +000043#include "EHHeaderParser.hpp"
Saleem Abdulrasool17552662015-04-24 19:39:17 +000044#include "Registers.hpp"
45
John Baldwin67737ec2017-09-21 21:28:48 +000046#ifdef __APPLE__
47
48 struct dyld_unwind_sections
49 {
50 const struct mach_header* mh;
51 const void* dwarf_section;
52 uintptr_t dwarf_section_length;
53 const void* compact_unwind_section;
54 uintptr_t compact_unwind_section_length;
55 };
56 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
57 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
58 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
59 // In 10.7.0 or later, libSystem.dylib implements this function.
60 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
61 #else
62 // In 10.6.x and earlier, we need to implement this functionality. Note
63 // that this requires a newer version of libmacho (from cctools) than is
64 // present in libSystem on 10.6.x (for getsectiondata).
65 static inline bool _dyld_find_unwind_sections(void* addr,
66 dyld_unwind_sections* info) {
67 // Find mach-o image containing address.
68 Dl_info dlinfo;
69 if (!dladdr(addr, &dlinfo))
70 return false;
71#if __LP64__
72 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
73#else
74 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
75#endif
76
77 // Initialize the return struct
78 info->mh = (const struct mach_header *)mh;
79 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
80 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
81
82 if (!info->dwarf_section) {
83 info->dwarf_section_length = 0;
84 }
85
86 if (!info->compact_unwind_section) {
87 info->compact_unwind_section_length = 0;
88 }
89
90 return true;
91 }
92 #endif
93
whitequarkffd92e52017-12-25 17:05:07 +000094#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
95
96// When statically linked on bare-metal, the symbols for the EH table are looked
97// up without going through the dynamic loader.
98
99// The following linker script may be used to produce the necessary sections and symbols.
100// Unless the --eh-frame-hdr linker option is provided, the section is not generated
101// and does not take space in the output file.
102//
103// .eh_frame :
104// {
105// __eh_frame_start = .;
106// KEEP(*(.eh_frame))
107// __eh_frame_end = .;
108// }
109//
110// .eh_frame_hdr :
111// {
112// KEEP(*(.eh_frame_hdr))
113// }
114//
115// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
116// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
117
118extern char __eh_frame_start;
119extern char __eh_frame_end;
120
121#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
122extern char __eh_frame_hdr_start;
123extern char __eh_frame_hdr_end;
124#endif
125
John Baldwin67737ec2017-09-21 21:28:48 +0000126#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
127
128// When statically linked on bare-metal, the symbols for the EH table are looked
129// up without going through the dynamic loader.
130extern char __exidx_start;
131extern char __exidx_end;
132
133#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
134
135// ELF-based systems may use dl_iterate_phdr() to access sections
136// containing unwinding information. The ElfW() macro for pointer-size
137// independent ELF header traversal is not provided by <link.h> on some
138// systems (e.g., FreeBSD). On these systems the data structures are
139// just called Elf_XXX. Define ElfW() locally.
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000140#ifndef _WIN32
John Baldwin67737ec2017-09-21 21:28:48 +0000141#include <link.h>
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000142#else
143#include <windows.h>
144#include <psapi.h>
145#endif
John Baldwin67737ec2017-09-21 21:28:48 +0000146#if !defined(ElfW)
147#define ElfW(type) Elf_##type
148#endif
149
150#endif
151
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000152namespace libunwind {
153
154/// Used by findUnwindSections() to return info about needed sections.
155struct UnwindInfoSections {
Ranjeet Singh421231a2017-03-31 15:28:06 +0000156#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
157 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Charles Davisfa2e6202018-08-30 21:29:00 +0000158 // No dso_base for SEH or ARM EHABI.
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000159 uintptr_t dso_base;
160#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000161#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000162 uintptr_t dwarf_section;
163 uintptr_t dwarf_section_length;
164#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000165#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000166 uintptr_t dwarf_index_section;
167 uintptr_t dwarf_index_section_length;
168#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000169#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000170 uintptr_t compact_unwind_section;
171 uintptr_t compact_unwind_section_length;
172#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000173#if defined(_LIBUNWIND_ARM_EHABI)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000174 uintptr_t arm_section;
175 uintptr_t arm_section_length;
176#endif
177};
178
179
180/// LocalAddressSpace is used as a template parameter to UnwindCursor when
181/// unwinding a thread in the same process. The wrappers compile away,
182/// making local unwinds fast.
183class __attribute__((visibility("hidden"))) LocalAddressSpace {
184public:
Martin Storsjocac41382017-10-27 08:11:36 +0000185 typedef uintptr_t pint_t;
186 typedef intptr_t sint_t;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000187 uint8_t get8(pint_t addr) {
188 uint8_t val;
189 memcpy(&val, (void *)addr, sizeof(val));
190 return val;
191 }
192 uint16_t get16(pint_t addr) {
193 uint16_t val;
194 memcpy(&val, (void *)addr, sizeof(val));
195 return val;
196 }
197 uint32_t get32(pint_t addr) {
198 uint32_t val;
199 memcpy(&val, (void *)addr, sizeof(val));
200 return val;
201 }
202 uint64_t get64(pint_t addr) {
203 uint64_t val;
204 memcpy(&val, (void *)addr, sizeof(val));
205 return val;
206 }
207 double getDouble(pint_t addr) {
208 double val;
209 memcpy(&val, (void *)addr, sizeof(val));
210 return val;
211 }
212 v128 getVector(pint_t addr) {
213 v128 val;
214 memcpy(&val, (void *)addr, sizeof(val));
215 return val;
216 }
217 uintptr_t getP(pint_t addr);
John Baldwin1a6e6be2018-02-27 21:24:02 +0000218 uint64_t getRegister(pint_t addr);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000219 static uint64_t getULEB128(pint_t &addr, pint_t end);
220 static int64_t getSLEB128(pint_t &addr, pint_t end);
221
222 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
223 pint_t datarelBase = 0);
224 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
225 unw_word_t *offset);
226 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
227 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
228
229 static LocalAddressSpace sThisAddressSpace;
230};
231
232inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
Martin Storsjocac41382017-10-27 08:11:36 +0000233#if __SIZEOF_POINTER__ == 8
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000234 return get64(addr);
235#else
236 return get32(addr);
237#endif
238}
239
John Baldwin1a6e6be2018-02-27 21:24:02 +0000240inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
241#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
242 return get64(addr);
243#else
244 return get32(addr);
245#endif
246}
247
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000248/// Read a ULEB128 into a 64-bit word.
249inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
250 const uint8_t *p = (uint8_t *)addr;
251 const uint8_t *pend = (uint8_t *)end;
252 uint64_t result = 0;
253 int bit = 0;
254 do {
255 uint64_t b;
256
257 if (p == pend)
258 _LIBUNWIND_ABORT("truncated uleb128 expression");
259
260 b = *p & 0x7f;
261
262 if (bit >= 64 || b << bit >> bit != b) {
263 _LIBUNWIND_ABORT("malformed uleb128 expression");
264 } else {
265 result |= b << bit;
266 bit += 7;
267 }
268 } while (*p++ >= 0x80);
269 addr = (pint_t) p;
270 return result;
271}
272
273/// Read a SLEB128 into a 64-bit word.
274inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
275 const uint8_t *p = (uint8_t *)addr;
276 const uint8_t *pend = (uint8_t *)end;
277 int64_t result = 0;
278 int bit = 0;
279 uint8_t byte;
280 do {
281 if (p == pend)
282 _LIBUNWIND_ABORT("truncated sleb128 expression");
283 byte = *p++;
284 result |= ((byte & 0x7f) << bit);
285 bit += 7;
286 } while (byte & 0x80);
287 // sign extend negative numbers
288 if ((byte & 0x40) != 0)
Marshall Clowa6d7c382017-06-21 16:02:53 +0000289 result |= (-1ULL) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000290 addr = (pint_t) p;
291 return result;
292}
293
294inline LocalAddressSpace::pint_t
295LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
296 pint_t datarelBase) {
297 pint_t startAddr = addr;
298 const uint8_t *p = (uint8_t *)addr;
299 pint_t result;
300
301 // first get value
302 switch (encoding & 0x0F) {
303 case DW_EH_PE_ptr:
304 result = getP(addr);
305 p += sizeof(pint_t);
306 addr = (pint_t) p;
307 break;
308 case DW_EH_PE_uleb128:
309 result = (pint_t)getULEB128(addr, end);
310 break;
311 case DW_EH_PE_udata2:
312 result = get16(addr);
313 p += 2;
314 addr = (pint_t) p;
315 break;
316 case DW_EH_PE_udata4:
317 result = get32(addr);
318 p += 4;
319 addr = (pint_t) p;
320 break;
321 case DW_EH_PE_udata8:
322 result = (pint_t)get64(addr);
323 p += 8;
324 addr = (pint_t) p;
325 break;
326 case DW_EH_PE_sleb128:
327 result = (pint_t)getSLEB128(addr, end);
328 break;
329 case DW_EH_PE_sdata2:
330 // Sign extend from signed 16-bit value.
331 result = (pint_t)(int16_t)get16(addr);
332 p += 2;
333 addr = (pint_t) p;
334 break;
335 case DW_EH_PE_sdata4:
336 // Sign extend from signed 32-bit value.
337 result = (pint_t)(int32_t)get32(addr);
338 p += 4;
339 addr = (pint_t) p;
340 break;
341 case DW_EH_PE_sdata8:
342 result = (pint_t)get64(addr);
343 p += 8;
344 addr = (pint_t) p;
345 break;
346 default:
347 _LIBUNWIND_ABORT("unknown pointer encoding");
348 }
349
350 // then add relative offset
351 switch (encoding & 0x70) {
352 case DW_EH_PE_absptr:
353 // do nothing
354 break;
355 case DW_EH_PE_pcrel:
356 result += startAddr;
357 break;
358 case DW_EH_PE_textrel:
359 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
360 break;
361 case DW_EH_PE_datarel:
362 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
363 // default value of 0, and we abort in the event that someone calls this
364 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
365 if (datarelBase == 0)
366 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
367 result += datarelBase;
368 break;
369 case DW_EH_PE_funcrel:
370 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
371 break;
372 case DW_EH_PE_aligned:
373 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
374 break;
375 default:
376 _LIBUNWIND_ABORT("unknown pointer encoding");
377 break;
378 }
379
380 if (encoding & DW_EH_PE_indirect)
381 result = getP(result);
382
383 return result;
384}
385
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000386inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
387 UnwindInfoSections &info) {
388#ifdef __APPLE__
389 dyld_unwind_sections dyldInfo;
390 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
391 info.dso_base = (uintptr_t)dyldInfo.mh;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000392 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000393 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
394 info.dwarf_section_length = dyldInfo.dwarf_section_length;
395 #endif
396 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
397 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
398 return true;
399 }
whitequarkffd92e52017-12-25 17:05:07 +0000400#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
401 // Bare metal is statically linked, so no need to ask the dynamic loader
402 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
403 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000404 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
405 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000406#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
407 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
408 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000409 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
410 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000411#endif
412 if (info.dwarf_section_length)
413 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000414#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000415 // Bare metal is statically linked, so no need to ask the dynamic loader
416 info.arm_section = (uintptr_t)(&__exidx_start);
417 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000418 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
419 (void *)info.arm_section, (void *)info.arm_section_length);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000420 if (info.arm_section && info.arm_section_length)
421 return true;
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000422#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
423 HMODULE mods[1024];
424 HANDLE process = GetCurrentProcess();
425 DWORD needed;
426
427 if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
428 return false;
429
430 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
431 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
432 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
433 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
434 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
435 bool found_obj = false;
436 bool found_hdr = false;
437
438 info.dso_base = (uintptr_t)mods[i];
439 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
440 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
441 uintptr_t end = begin + pish->Misc.VirtualSize;
442 if (!strncmp((const char *)pish->Name, ".text",
443 IMAGE_SIZEOF_SHORT_NAME)) {
444 if (targetAddr >= begin && targetAddr < end)
445 found_obj = true;
446 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
447 IMAGE_SIZEOF_SHORT_NAME)) {
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000448 info.dwarf_section = begin;
449 info.dwarf_section_length = pish->Misc.VirtualSize;
450 found_hdr = true;
451 }
452 if (found_obj && found_hdr)
453 return true;
454 }
455 }
456 return false;
Charles Davisfa2e6202018-08-30 21:29:00 +0000457#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
458 // Don't even bother, since Windows has functions that do all this stuff
459 // for us.
460 return true;
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000461#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
462 (__ANDROID_API__ < 21)
463 int length = 0;
464 info.arm_section =
465 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
466 info.arm_section_length = (uintptr_t)length;
467 if (info.arm_section && info.arm_section_length)
468 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000469#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000470 struct dl_iterate_cb_data {
471 LocalAddressSpace *addressSpace;
472 UnwindInfoSections *sects;
473 uintptr_t targetAddr;
474 };
475
476 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
477 int found = dl_iterate_phdr(
478 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
479 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
Ed Schouten08032ee2017-02-23 09:13:22 +0000480 bool found_obj = false;
481 bool found_hdr = false;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000482
483 assert(cbdata);
484 assert(cbdata->sects);
485
486 if (cbdata->targetAddr < pinfo->dlpi_addr) {
487 return false;
488 }
489
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000490#if !defined(Elf_Half)
491 typedef ElfW(Half) Elf_Half;
492#endif
493#if !defined(Elf_Phdr)
494 typedef ElfW(Phdr) Elf_Phdr;
495#endif
Ivan Krasind34d77f2017-04-06 17:35:35 +0000496#if !defined(Elf_Addr) && defined(__ANDROID__)
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000497 typedef ElfW(Addr) Elf_Addr;
498#endif
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000499
Ranjeet Singh421231a2017-03-31 15:28:06 +0000500 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
501 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000502 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
503 #endif
504 size_t object_length;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000505#if defined(__ANDROID__)
506 Elf_Addr image_base =
Saleem Abdulrasoole4fe5f92017-04-05 21:29:38 +0000507 pinfo->dlpi_phnum
508 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
509 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
510 ->p_offset
511 : 0;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000512#endif
513
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000514 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
515 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000516 if (phdr->p_type == PT_LOAD) {
517 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000518#if defined(__ANDROID__)
519 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
520 begin = begin + image_base;
521#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000522 uintptr_t end = begin + phdr->p_memsz;
523 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
524 cbdata->sects->dso_base = begin;
525 object_length = phdr->p_memsz;
526 found_obj = true;
527 }
528 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
529 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
530 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000531#if defined(__ANDROID__)
532 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
533 eh_frame_hdr_start = eh_frame_hdr_start + image_base;
534#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000535 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
536 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
537 EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
538 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
539 hdrInfo);
540 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
541 found_hdr = true;
542 }
543 }
544
545 if (found_obj && found_hdr) {
546 cbdata->sects->dwarf_section_length = object_length;
547 return true;
548 } else {
549 return false;
550 }
Ranjeet Singh421231a2017-03-31 15:28:06 +0000551 #else // defined(_LIBUNWIND_ARM_EHABI)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000552 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
553 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
554 if (phdr->p_type == PT_LOAD) {
555 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
556 uintptr_t end = begin + phdr->p_memsz;
557 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
558 found_obj = true;
559 } else if (phdr->p_type == PT_ARM_EXIDX) {
560 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
561 cbdata->sects->arm_section = exidx_start;
Ed Schouten5d3f35b2017-03-07 15:21:57 +0000562 cbdata->sects->arm_section_length = phdr->p_memsz;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000563 found_hdr = true;
564 }
565 }
566 return found_obj && found_hdr;
567 #endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000568 },
569 &cb_data);
570 return static_cast<bool>(found);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000571#endif
572
573 return false;
574}
575
576
577inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
578#ifdef __APPLE__
579 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
580#else
581 // TO DO: if OS has way to dynamically register FDEs, check that.
582 (void)targetAddr;
583 (void)fde;
584 return false;
585#endif
586}
587
588inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
589 size_t bufLen,
590 unw_word_t *offset) {
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +0000591#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000592 Dl_info dyldInfo;
593 if (dladdr((void *)addr, &dyldInfo)) {
594 if (dyldInfo.dli_sname != NULL) {
595 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
596 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
597 return true;
598 }
599 }
600#endif
601 return false;
602}
603
604
605
606#ifdef UNW_REMOTE
607
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000608/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000609/// unwinding a thread in the another process. The other process can be a
610/// different endianness and a different pointer size which is handled by
611/// the P template parameter.
612template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000613class RemoteAddressSpace {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000614public:
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000615 RemoteAddressSpace(task_t task) : fTask(task) {}
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000616
617 typedef typename P::uint_t pint_t;
618
619 uint8_t get8(pint_t addr);
620 uint16_t get16(pint_t addr);
621 uint32_t get32(pint_t addr);
622 uint64_t get64(pint_t addr);
623 pint_t getP(pint_t addr);
John Baldwin1a6e6be2018-02-27 21:24:02 +0000624 uint64_t getRegister(pint_t addr);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000625 uint64_t getULEB128(pint_t &addr, pint_t end);
626 int64_t getSLEB128(pint_t &addr, pint_t end);
627 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
628 pint_t datarelBase = 0);
629 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
630 unw_word_t *offset);
631 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
632 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
633private:
634 void *localCopy(pint_t addr);
635
636 task_t fTask;
637};
638
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000639template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000640 return *((uint8_t *)localCopy(addr));
641}
642
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000643template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000644 return P::E::get16(*(uint16_t *)localCopy(addr));
645}
646
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000647template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000648 return P::E::get32(*(uint32_t *)localCopy(addr));
649}
650
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000651template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000652 return P::E::get64(*(uint64_t *)localCopy(addr));
653}
654
655template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000656typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000657 return P::getP(*(uint64_t *)localCopy(addr));
658}
659
660template <typename P>
John Baldwin1a6e6be2018-02-27 21:24:02 +0000661typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
662 return P::getRegister(*(uint64_t *)localCopy(addr));
663}
664
665template <typename P>
666uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000667 uintptr_t size = (end - addr);
668 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
669 LocalAddressSpace::pint_t sladdr = laddr;
670 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
671 addr += (laddr - sladdr);
672 return result;
673}
674
675template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000676int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000677 uintptr_t size = (end - addr);
678 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
679 LocalAddressSpace::pint_t sladdr = laddr;
680 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
681 addr += (laddr - sladdr);
682 return result;
683}
684
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000685template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000686 // FIX ME
687}
688
689template <typename P>
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000690bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
691 size_t bufLen,
692 unw_word_t *offset) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000693 // FIX ME
694}
695
696/// unw_addr_space is the base class that abstract unw_addr_space_t type in
697/// libunwind.h points to.
698struct unw_addr_space {
699 cpu_type_t cpuType;
700 task_t taskPort;
701};
702
703/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
704/// to when examining
705/// a 32-bit intel process.
706struct unw_addr_space_i386 : public unw_addr_space {
707 unw_addr_space_i386(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000708 RemoteAddressSpace<Pointer32<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000709};
710
711/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
712/// points to when examining
713/// a 64-bit intel process.
714struct unw_addr_space_x86_64 : public unw_addr_space {
715 unw_addr_space_x86_64(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000716 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000717};
718
719/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
720/// to when examining
721/// a 32-bit PowerPC process.
722struct unw_addr_space_ppc : public unw_addr_space {
723 unw_addr_space_ppc(task_t task) : oas(task) {}
Saleem Abdulrasool66efa8e2017-01-21 16:22:46 +0000724 RemoteAddressSpace<Pointer32<BigEndian>> oas;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000725};
726
Martin Storsjo8338b0a2018-01-02 22:11:30 +0000727/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
728/// to when examining a 64-bit PowerPC process.
729struct unw_addr_space_ppc64 : public unw_addr_space {
730 unw_addr_space_ppc64(task_t task) : oas(task) {}
731 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
732};
733
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000734#endif // UNW_REMOTE
735
736} // namespace libunwind
737
738#endif // __ADDRESSSPACE_HPP__