blob: 908c898d74035fc34a3dfd5876744b02591c2560 [file] [log] [blame]
Saleem Abdulrasool17552662015-04-24 19:39:17 +00001//===------------------------- AddressSpace.hpp ---------------------------===//
2//
Chandler Carruth61860a52019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Saleem Abdulrasool17552662015-04-24 19:39:17 +00006//
7//
8// Abstracts accessing local vs remote address spaces.
9//
10//===----------------------------------------------------------------------===//
11
12#ifndef __ADDRESSSPACE_HPP__
13#define __ADDRESSSPACE_HPP__
14
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +000020#ifndef _LIBUNWIND_USE_DLADDR
21 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
22 #define _LIBUNWIND_USE_DLADDR 1
23 #else
24 #define _LIBUNWIND_USE_DLADDR 0
25 #endif
26#endif
27
28#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +000029#include <dlfcn.h>
Yi Kongc6995212019-07-22 20:41:03 +000030#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
Petr Hosek7b727032019-05-30 01:34:41 +000031#pragma comment(lib, "dl")
32#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +000033#endif
34
Ryan Prichard2a4f1362019-10-18 19:59:22 +000035#if defined(_LIBUNWIND_ARM_EHABI)
36struct EHABIIndexEntry {
37 uint32_t functionOffset;
38 uint32_t data;
39};
40#endif
41
Saleem Abdulrasool17552662015-04-24 19:39:17 +000042#ifdef __APPLE__
43#include <mach-o/getsect.h>
44namespace libunwind {
45 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
46}
47#endif
48
49#include "libunwind.h"
50#include "config.h"
51#include "dwarf2.h"
Ed Schoutenda7d6252017-03-07 18:21:51 +000052#include "EHHeaderParser.hpp"
Saleem Abdulrasool17552662015-04-24 19:39:17 +000053#include "Registers.hpp"
54
John Baldwin67737ec2017-09-21 21:28:48 +000055#ifdef __APPLE__
56
57 struct dyld_unwind_sections
58 {
59 const struct mach_header* mh;
60 const void* dwarf_section;
61 uintptr_t dwarf_section_length;
62 const void* compact_unwind_section;
63 uintptr_t compact_unwind_section_length;
64 };
65 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
66 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
67 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
68 // In 10.7.0 or later, libSystem.dylib implements this function.
69 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
70 #else
71 // In 10.6.x and earlier, we need to implement this functionality. Note
72 // that this requires a newer version of libmacho (from cctools) than is
73 // present in libSystem on 10.6.x (for getsectiondata).
74 static inline bool _dyld_find_unwind_sections(void* addr,
75 dyld_unwind_sections* info) {
76 // Find mach-o image containing address.
77 Dl_info dlinfo;
78 if (!dladdr(addr, &dlinfo))
79 return false;
80#if __LP64__
81 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
82#else
83 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
84#endif
85
86 // Initialize the return struct
87 info->mh = (const struct mach_header *)mh;
88 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
89 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
90
91 if (!info->dwarf_section) {
92 info->dwarf_section_length = 0;
93 }
94
95 if (!info->compact_unwind_section) {
96 info->compact_unwind_section_length = 0;
97 }
98
99 return true;
100 }
101 #endif
102
whitequarkffd92e52017-12-25 17:05:07 +0000103#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
104
105// When statically linked on bare-metal, the symbols for the EH table are looked
106// up without going through the dynamic loader.
107
108// The following linker script may be used to produce the necessary sections and symbols.
109// Unless the --eh-frame-hdr linker option is provided, the section is not generated
110// and does not take space in the output file.
111//
112// .eh_frame :
113// {
114// __eh_frame_start = .;
115// KEEP(*(.eh_frame))
116// __eh_frame_end = .;
117// }
118//
119// .eh_frame_hdr :
120// {
121// KEEP(*(.eh_frame_hdr))
122// }
123//
124// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
125// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
126
127extern char __eh_frame_start;
128extern char __eh_frame_end;
129
130#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
131extern char __eh_frame_hdr_start;
132extern char __eh_frame_hdr_end;
133#endif
134
John Baldwin67737ec2017-09-21 21:28:48 +0000135#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
136
137// When statically linked on bare-metal, the symbols for the EH table are looked
138// up without going through the dynamic loader.
139extern char __exidx_start;
140extern char __exidx_end;
141
142#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
143
144// ELF-based systems may use dl_iterate_phdr() to access sections
145// containing unwinding information. The ElfW() macro for pointer-size
146// independent ELF header traversal is not provided by <link.h> on some
147// systems (e.g., FreeBSD). On these systems the data structures are
148// just called Elf_XXX. Define ElfW() locally.
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000149#ifndef _WIN32
John Baldwin67737ec2017-09-21 21:28:48 +0000150#include <link.h>
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000151#else
152#include <windows.h>
153#include <psapi.h>
154#endif
John Baldwin67737ec2017-09-21 21:28:48 +0000155#if !defined(ElfW)
156#define ElfW(type) Elf_##type
157#endif
158
159#endif
160
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000161namespace libunwind {
162
163/// Used by findUnwindSections() to return info about needed sections.
164struct UnwindInfoSections {
Ranjeet Singh421231a2017-03-31 15:28:06 +0000165#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
166 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Charles Davisfa2e6202018-08-30 21:29:00 +0000167 // No dso_base for SEH or ARM EHABI.
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000168 uintptr_t dso_base;
169#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000170#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000171 uintptr_t dwarf_section;
172 uintptr_t dwarf_section_length;
173#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000174#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000175 uintptr_t dwarf_index_section;
176 uintptr_t dwarf_index_section_length;
177#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000178#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000179 uintptr_t compact_unwind_section;
180 uintptr_t compact_unwind_section_length;
181#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000182#if defined(_LIBUNWIND_ARM_EHABI)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000183 uintptr_t arm_section;
184 uintptr_t arm_section_length;
185#endif
186};
187
188
189/// LocalAddressSpace is used as a template parameter to UnwindCursor when
190/// unwinding a thread in the same process. The wrappers compile away,
191/// making local unwinds fast.
Charles Davis04f0c2e2018-08-31 13:41:05 +0000192class _LIBUNWIND_HIDDEN LocalAddressSpace {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000193public:
Martin Storsjocac41382017-10-27 08:11:36 +0000194 typedef uintptr_t pint_t;
195 typedef intptr_t sint_t;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000196 uint8_t get8(pint_t addr) {
197 uint8_t val;
198 memcpy(&val, (void *)addr, sizeof(val));
199 return val;
200 }
201 uint16_t get16(pint_t addr) {
202 uint16_t val;
203 memcpy(&val, (void *)addr, sizeof(val));
204 return val;
205 }
206 uint32_t get32(pint_t addr) {
207 uint32_t val;
208 memcpy(&val, (void *)addr, sizeof(val));
209 return val;
210 }
211 uint64_t get64(pint_t addr) {
212 uint64_t val;
213 memcpy(&val, (void *)addr, sizeof(val));
214 return val;
215 }
216 double getDouble(pint_t addr) {
217 double val;
218 memcpy(&val, (void *)addr, sizeof(val));
219 return val;
220 }
221 v128 getVector(pint_t addr) {
222 v128 val;
223 memcpy(&val, (void *)addr, sizeof(val));
224 return val;
225 }
226 uintptr_t getP(pint_t addr);
John Baldwin1a6e6be2018-02-27 21:24:02 +0000227 uint64_t getRegister(pint_t addr);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000228 static uint64_t getULEB128(pint_t &addr, pint_t end);
229 static int64_t getSLEB128(pint_t &addr, pint_t end);
230
231 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
232 pint_t datarelBase = 0);
233 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
234 unw_word_t *offset);
235 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
236 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
237
238 static LocalAddressSpace sThisAddressSpace;
239};
240
241inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
Martin Storsjocac41382017-10-27 08:11:36 +0000242#if __SIZEOF_POINTER__ == 8
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000243 return get64(addr);
244#else
245 return get32(addr);
246#endif
247}
248
John Baldwin1a6e6be2018-02-27 21:24:02 +0000249inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
250#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
251 return get64(addr);
252#else
253 return get32(addr);
254#endif
255}
256
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000257/// Read a ULEB128 into a 64-bit word.
258inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
259 const uint8_t *p = (uint8_t *)addr;
260 const uint8_t *pend = (uint8_t *)end;
261 uint64_t result = 0;
262 int bit = 0;
263 do {
264 uint64_t b;
265
266 if (p == pend)
267 _LIBUNWIND_ABORT("truncated uleb128 expression");
268
269 b = *p & 0x7f;
270
271 if (bit >= 64 || b << bit >> bit != b) {
272 _LIBUNWIND_ABORT("malformed uleb128 expression");
273 } else {
274 result |= b << bit;
275 bit += 7;
276 }
277 } while (*p++ >= 0x80);
278 addr = (pint_t) p;
279 return result;
280}
281
282/// Read a SLEB128 into a 64-bit word.
283inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
284 const uint8_t *p = (uint8_t *)addr;
285 const uint8_t *pend = (uint8_t *)end;
286 int64_t result = 0;
287 int bit = 0;
288 uint8_t byte;
289 do {
290 if (p == pend)
291 _LIBUNWIND_ABORT("truncated sleb128 expression");
292 byte = *p++;
293 result |= ((byte & 0x7f) << bit);
294 bit += 7;
295 } while (byte & 0x80);
296 // sign extend negative numbers
297 if ((byte & 0x40) != 0)
Marshall Clowa6d7c382017-06-21 16:02:53 +0000298 result |= (-1ULL) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000299 addr = (pint_t) p;
300 return result;
301}
302
303inline LocalAddressSpace::pint_t
304LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
305 pint_t datarelBase) {
306 pint_t startAddr = addr;
307 const uint8_t *p = (uint8_t *)addr;
308 pint_t result;
309
310 // first get value
311 switch (encoding & 0x0F) {
312 case DW_EH_PE_ptr:
313 result = getP(addr);
314 p += sizeof(pint_t);
315 addr = (pint_t) p;
316 break;
317 case DW_EH_PE_uleb128:
318 result = (pint_t)getULEB128(addr, end);
319 break;
320 case DW_EH_PE_udata2:
321 result = get16(addr);
322 p += 2;
323 addr = (pint_t) p;
324 break;
325 case DW_EH_PE_udata4:
326 result = get32(addr);
327 p += 4;
328 addr = (pint_t) p;
329 break;
330 case DW_EH_PE_udata8:
331 result = (pint_t)get64(addr);
332 p += 8;
333 addr = (pint_t) p;
334 break;
335 case DW_EH_PE_sleb128:
336 result = (pint_t)getSLEB128(addr, end);
337 break;
338 case DW_EH_PE_sdata2:
339 // Sign extend from signed 16-bit value.
340 result = (pint_t)(int16_t)get16(addr);
341 p += 2;
342 addr = (pint_t) p;
343 break;
344 case DW_EH_PE_sdata4:
345 // Sign extend from signed 32-bit value.
346 result = (pint_t)(int32_t)get32(addr);
347 p += 4;
348 addr = (pint_t) p;
349 break;
350 case DW_EH_PE_sdata8:
351 result = (pint_t)get64(addr);
352 p += 8;
353 addr = (pint_t) p;
354 break;
355 default:
356 _LIBUNWIND_ABORT("unknown pointer encoding");
357 }
358
359 // then add relative offset
360 switch (encoding & 0x70) {
361 case DW_EH_PE_absptr:
362 // do nothing
363 break;
364 case DW_EH_PE_pcrel:
365 result += startAddr;
366 break;
367 case DW_EH_PE_textrel:
368 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
369 break;
370 case DW_EH_PE_datarel:
371 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
372 // default value of 0, and we abort in the event that someone calls this
373 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
374 if (datarelBase == 0)
375 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
376 result += datarelBase;
377 break;
378 case DW_EH_PE_funcrel:
379 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
380 break;
381 case DW_EH_PE_aligned:
382 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
383 break;
384 default:
385 _LIBUNWIND_ABORT("unknown pointer encoding");
386 break;
387 }
388
389 if (encoding & DW_EH_PE_indirect)
390 result = getP(result);
391
392 return result;
393}
394
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000395inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
396 UnwindInfoSections &info) {
397#ifdef __APPLE__
398 dyld_unwind_sections dyldInfo;
399 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
400 info.dso_base = (uintptr_t)dyldInfo.mh;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000401 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000402 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
403 info.dwarf_section_length = dyldInfo.dwarf_section_length;
404 #endif
405 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
406 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
407 return true;
408 }
whitequarkffd92e52017-12-25 17:05:07 +0000409#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
410 // Bare metal is statically linked, so no need to ask the dynamic loader
411 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
412 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000413 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
414 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000415#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
416 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
417 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000418 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
419 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000420#endif
421 if (info.dwarf_section_length)
422 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000423#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000424 // Bare metal is statically linked, so no need to ask the dynamic loader
425 info.arm_section = (uintptr_t)(&__exidx_start);
426 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000427 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
428 (void *)info.arm_section, (void *)info.arm_section_length);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000429 if (info.arm_section && info.arm_section_length)
430 return true;
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000431#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
432 HMODULE mods[1024];
433 HANDLE process = GetCurrentProcess();
434 DWORD needed;
435
436 if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
437 return false;
438
439 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
440 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
441 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
442 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
443 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
444 bool found_obj = false;
445 bool found_hdr = false;
446
447 info.dso_base = (uintptr_t)mods[i];
448 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
449 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
450 uintptr_t end = begin + pish->Misc.VirtualSize;
451 if (!strncmp((const char *)pish->Name, ".text",
452 IMAGE_SIZEOF_SHORT_NAME)) {
453 if (targetAddr >= begin && targetAddr < end)
454 found_obj = true;
455 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
456 IMAGE_SIZEOF_SHORT_NAME)) {
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000457 info.dwarf_section = begin;
458 info.dwarf_section_length = pish->Misc.VirtualSize;
459 found_hdr = true;
460 }
461 if (found_obj && found_hdr)
462 return true;
463 }
464 }
465 return false;
Charles Davisfa2e6202018-08-30 21:29:00 +0000466#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
467 // Don't even bother, since Windows has functions that do all this stuff
468 // for us.
Martin Storsjo059a1632019-01-22 22:12:23 +0000469 (void)targetAddr;
470 (void)info;
Charles Davisfa2e6202018-08-30 21:29:00 +0000471 return true;
Ryan Prichard2a4f1362019-10-18 19:59:22 +0000472#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__)
473 // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
474 // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000475 int length = 0;
476 info.arm_section =
477 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
Ryan Prichard2a4f1362019-10-18 19:59:22 +0000478 info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000479 if (info.arm_section && info.arm_section_length)
480 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000481#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000482 struct dl_iterate_cb_data {
483 LocalAddressSpace *addressSpace;
484 UnwindInfoSections *sects;
485 uintptr_t targetAddr;
486 };
487
488 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
489 int found = dl_iterate_phdr(
490 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
491 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
Ed Schouten08032ee2017-02-23 09:13:22 +0000492 bool found_obj = false;
493 bool found_hdr = false;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000494
495 assert(cbdata);
496 assert(cbdata->sects);
497
498 if (cbdata->targetAddr < pinfo->dlpi_addr) {
499 return false;
500 }
501
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000502#if !defined(Elf_Half)
503 typedef ElfW(Half) Elf_Half;
504#endif
505#if !defined(Elf_Phdr)
506 typedef ElfW(Phdr) Elf_Phdr;
507#endif
Ryan Prichardb6bfd8b2019-10-16 02:38:47 +0000508#if !defined(Elf_Addr)
509 typedef ElfW(Addr) Elf_Addr;
510#endif
511
512 Elf_Addr image_base = pinfo->dlpi_addr;
513
514#if defined(__ANDROID__) && __ANDROID_API__ < 18
515 if (image_base == 0) {
516 // Normally, an image base of 0 indicates a non-PIE executable. On
517 // versions of Android prior to API 18, the dynamic linker reported a
518 // dlpi_addr of 0 for PIE executables. Compute the true image base
519 // using the PT_PHDR segment.
520 // See https://github.com/android/ndk/issues/505.
521 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
522 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
523 if (phdr->p_type == PT_PHDR) {
524 image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
525 phdr->p_vaddr;
526 break;
527 }
528 }
529 }
530#endif
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000531
Ranjeet Singh421231a2017-03-31 15:28:06 +0000532 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
533 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000534 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
535 #endif
536 size_t object_length;
Saleem Abdulrasool241fe722017-04-05 18:33:23 +0000537
Viktor Kutuzova28f5b32015-05-06 10:32:28 +0000538 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
539 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000540 if (phdr->p_type == PT_LOAD) {
Ryan Prichardb6bfd8b2019-10-16 02:38:47 +0000541 uintptr_t begin = image_base + phdr->p_vaddr;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000542 uintptr_t end = begin + phdr->p_memsz;
543 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
544 cbdata->sects->dso_base = begin;
545 object_length = phdr->p_memsz;
546 found_obj = true;
547 }
548 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
549 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
Ryan Prichardb6bfd8b2019-10-16 02:38:47 +0000550 uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000551 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
552 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
Petr Hosek06be3282019-01-24 03:04:42 +0000553 found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000554 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
555 hdrInfo);
Petr Hosek06be3282019-01-24 03:04:42 +0000556 if (found_hdr)
557 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000558 }
559 }
560
561 if (found_obj && found_hdr) {
562 cbdata->sects->dwarf_section_length = object_length;
563 return true;
564 } else {
565 return false;
566 }
Ranjeet Singh421231a2017-03-31 15:28:06 +0000567 #else // defined(_LIBUNWIND_ARM_EHABI)
Ed Schouten6a4939b2017-03-05 19:11:24 +0000568 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
569 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
570 if (phdr->p_type == PT_LOAD) {
Ryan Prichardb6bfd8b2019-10-16 02:38:47 +0000571 uintptr_t begin = image_base + phdr->p_vaddr;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000572 uintptr_t end = begin + phdr->p_memsz;
573 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
574 found_obj = true;
575 } else if (phdr->p_type == PT_ARM_EXIDX) {
Ryan Prichardb6bfd8b2019-10-16 02:38:47 +0000576 uintptr_t exidx_start = image_base + phdr->p_vaddr;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000577 cbdata->sects->arm_section = exidx_start;
Ed Schouten5d3f35b2017-03-07 15:21:57 +0000578 cbdata->sects->arm_section_length = phdr->p_memsz;
Ed Schouten6a4939b2017-03-05 19:11:24 +0000579 found_hdr = true;
580 }
581 }
582 return found_obj && found_hdr;
583 #endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000584 },
585 &cb_data);
586 return static_cast<bool>(found);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000587#endif
588
589 return false;
590}
591
592
593inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
594#ifdef __APPLE__
595 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
596#else
597 // TO DO: if OS has way to dynamically register FDEs, check that.
598 (void)targetAddr;
599 (void)fde;
600 return false;
601#endif
602}
603
604inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
605 size_t bufLen,
606 unw_word_t *offset) {
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +0000607#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000608 Dl_info dyldInfo;
609 if (dladdr((void *)addr, &dyldInfo)) {
610 if (dyldInfo.dli_sname != NULL) {
611 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
612 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
613 return true;
614 }
615 }
Martin Storsjo059a1632019-01-22 22:12:23 +0000616#else
617 (void)addr;
618 (void)buf;
619 (void)bufLen;
620 (void)offset;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000621#endif
622 return false;
623}
624
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000625} // namespace libunwind
626
627#endif // __ADDRESSSPACE_HPP__