blob: eccc2153c69772143454f66c10ae09353aa4c0e5 [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
Ryan Prichardc155d182020-08-19 01:54:17 -070020#include "libunwind.h"
21#include "config.h"
22#include "dwarf2.h"
23#include "EHHeaderParser.hpp"
24#include "Registers.hpp"
25
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +000026#ifndef _LIBUNWIND_USE_DLADDR
27 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
28 #define _LIBUNWIND_USE_DLADDR 1
29 #else
30 #define _LIBUNWIND_USE_DLADDR 0
31 #endif
32#endif
33
34#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +000035#include <dlfcn.h>
Michał Górnyf939ab72019-11-30 15:13:56 +010036#if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB)
Petr Hosek7b727032019-05-30 01:34:41 +000037#pragma comment(lib, "dl")
38#endif
Saleem Abdulrasool17552662015-04-24 19:39:17 +000039#endif
40
Ryan Prichard2a4f1362019-10-18 19:59:22 +000041#if defined(_LIBUNWIND_ARM_EHABI)
42struct EHABIIndexEntry {
43 uint32_t functionOffset;
44 uint32_t data;
45};
46#endif
47
John Baldwin67737ec2017-09-21 21:28:48 +000048#ifdef __APPLE__
49
50 struct dyld_unwind_sections
51 {
52 const struct mach_header* mh;
53 const void* dwarf_section;
54 uintptr_t dwarf_section_length;
55 const void* compact_unwind_section;
56 uintptr_t compact_unwind_section_length;
57 };
John Baldwin67737ec2017-09-21 21:28:48 +000058
Steven Wu8d1344f2020-08-17 14:08:50 -070059 // In 10.7.0 or later, libSystem.dylib implements this function.
60 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
John Baldwin67737ec2017-09-21 21:28:48 +000061
whitequarkffd92e52017-12-25 17:05:07 +000062#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
63
64// When statically linked on bare-metal, the symbols for the EH table are looked
65// up without going through the dynamic loader.
66
67// The following linker script may be used to produce the necessary sections and symbols.
68// Unless the --eh-frame-hdr linker option is provided, the section is not generated
69// and does not take space in the output file.
70//
71// .eh_frame :
72// {
73// __eh_frame_start = .;
74// KEEP(*(.eh_frame))
75// __eh_frame_end = .;
76// }
77//
78// .eh_frame_hdr :
79// {
80// KEEP(*(.eh_frame_hdr))
81// }
82//
83// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
84// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
85
86extern char __eh_frame_start;
87extern char __eh_frame_end;
88
89#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
90extern char __eh_frame_hdr_start;
91extern char __eh_frame_hdr_end;
92#endif
93
John Baldwin67737ec2017-09-21 21:28:48 +000094#elif defined(_LIBUNWIND_ARM_EHABI) && 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.
98extern char __exidx_start;
99extern char __exidx_end;
100
Ryan Prichard7629c302020-08-27 23:46:49 -0700101#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
John Baldwin67737ec2017-09-21 21:28:48 +0000102
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000103#include <windows.h>
104#include <psapi.h>
Ryan Prichard7629c302020-08-27 23:46:49 -0700105
106#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \
107 defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
108
109#include <link.h>
John Baldwin67737ec2017-09-21 21:28:48 +0000110
111#endif
112
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000113namespace libunwind {
114
115/// Used by findUnwindSections() to return info about needed sections.
116struct UnwindInfoSections {
Ranjeet Singh421231a2017-03-31 15:28:06 +0000117#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
118 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Charles Davisfa2e6202018-08-30 21:29:00 +0000119 // No dso_base for SEH or ARM EHABI.
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000120 uintptr_t dso_base;
121#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000122#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000123 uintptr_t dwarf_section;
124 uintptr_t dwarf_section_length;
125#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000126#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000127 uintptr_t dwarf_index_section;
128 uintptr_t dwarf_index_section_length;
129#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000130#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000131 uintptr_t compact_unwind_section;
132 uintptr_t compact_unwind_section_length;
133#endif
Ranjeet Singh421231a2017-03-31 15:28:06 +0000134#if defined(_LIBUNWIND_ARM_EHABI)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000135 uintptr_t arm_section;
136 uintptr_t arm_section_length;
137#endif
138};
139
140
141/// LocalAddressSpace is used as a template parameter to UnwindCursor when
142/// unwinding a thread in the same process. The wrappers compile away,
143/// making local unwinds fast.
Charles Davis04f0c2e2018-08-31 13:41:05 +0000144class _LIBUNWIND_HIDDEN LocalAddressSpace {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000145public:
Martin Storsjocac41382017-10-27 08:11:36 +0000146 typedef uintptr_t pint_t;
147 typedef intptr_t sint_t;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000148 uint8_t get8(pint_t addr) {
149 uint8_t val;
150 memcpy(&val, (void *)addr, sizeof(val));
151 return val;
152 }
153 uint16_t get16(pint_t addr) {
154 uint16_t val;
155 memcpy(&val, (void *)addr, sizeof(val));
156 return val;
157 }
158 uint32_t get32(pint_t addr) {
159 uint32_t val;
160 memcpy(&val, (void *)addr, sizeof(val));
161 return val;
162 }
163 uint64_t get64(pint_t addr) {
164 uint64_t val;
165 memcpy(&val, (void *)addr, sizeof(val));
166 return val;
167 }
168 double getDouble(pint_t addr) {
169 double val;
170 memcpy(&val, (void *)addr, sizeof(val));
171 return val;
172 }
173 v128 getVector(pint_t addr) {
174 v128 val;
175 memcpy(&val, (void *)addr, sizeof(val));
176 return val;
177 }
178 uintptr_t getP(pint_t addr);
John Baldwin1a6e6be2018-02-27 21:24:02 +0000179 uint64_t getRegister(pint_t addr);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000180 static uint64_t getULEB128(pint_t &addr, pint_t end);
181 static int64_t getSLEB128(pint_t &addr, pint_t end);
182
183 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
184 pint_t datarelBase = 0);
185 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
186 unw_word_t *offset);
187 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
188 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
189
190 static LocalAddressSpace sThisAddressSpace;
191};
192
193inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
Martin Storsjocac41382017-10-27 08:11:36 +0000194#if __SIZEOF_POINTER__ == 8
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000195 return get64(addr);
196#else
197 return get32(addr);
198#endif
199}
200
John Baldwin1a6e6be2018-02-27 21:24:02 +0000201inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
202#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
203 return get64(addr);
204#else
205 return get32(addr);
206#endif
207}
208
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000209/// Read a ULEB128 into a 64-bit word.
210inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
211 const uint8_t *p = (uint8_t *)addr;
212 const uint8_t *pend = (uint8_t *)end;
213 uint64_t result = 0;
214 int bit = 0;
215 do {
216 uint64_t b;
217
218 if (p == pend)
219 _LIBUNWIND_ABORT("truncated uleb128 expression");
220
221 b = *p & 0x7f;
222
223 if (bit >= 64 || b << bit >> bit != b) {
224 _LIBUNWIND_ABORT("malformed uleb128 expression");
225 } else {
226 result |= b << bit;
227 bit += 7;
228 }
229 } while (*p++ >= 0x80);
230 addr = (pint_t) p;
231 return result;
232}
233
234/// Read a SLEB128 into a 64-bit word.
235inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
236 const uint8_t *p = (uint8_t *)addr;
237 const uint8_t *pend = (uint8_t *)end;
238 int64_t result = 0;
239 int bit = 0;
240 uint8_t byte;
241 do {
242 if (p == pend)
243 _LIBUNWIND_ABORT("truncated sleb128 expression");
244 byte = *p++;
Ryan Prichardc2174592020-07-13 22:06:47 -0700245 result |= (uint64_t)(byte & 0x7f) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000246 bit += 7;
247 } while (byte & 0x80);
248 // sign extend negative numbers
Ryan Prichardc2174592020-07-13 22:06:47 -0700249 if ((byte & 0x40) != 0 && bit < 64)
Marshall Clowa6d7c382017-06-21 16:02:53 +0000250 result |= (-1ULL) << bit;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000251 addr = (pint_t) p;
252 return result;
253}
254
255inline LocalAddressSpace::pint_t
256LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
257 pint_t datarelBase) {
258 pint_t startAddr = addr;
259 const uint8_t *p = (uint8_t *)addr;
260 pint_t result;
261
262 // first get value
263 switch (encoding & 0x0F) {
264 case DW_EH_PE_ptr:
265 result = getP(addr);
266 p += sizeof(pint_t);
267 addr = (pint_t) p;
268 break;
269 case DW_EH_PE_uleb128:
270 result = (pint_t)getULEB128(addr, end);
271 break;
272 case DW_EH_PE_udata2:
273 result = get16(addr);
274 p += 2;
275 addr = (pint_t) p;
276 break;
277 case DW_EH_PE_udata4:
278 result = get32(addr);
279 p += 4;
280 addr = (pint_t) p;
281 break;
282 case DW_EH_PE_udata8:
283 result = (pint_t)get64(addr);
284 p += 8;
285 addr = (pint_t) p;
286 break;
287 case DW_EH_PE_sleb128:
288 result = (pint_t)getSLEB128(addr, end);
289 break;
290 case DW_EH_PE_sdata2:
291 // Sign extend from signed 16-bit value.
292 result = (pint_t)(int16_t)get16(addr);
293 p += 2;
294 addr = (pint_t) p;
295 break;
296 case DW_EH_PE_sdata4:
297 // Sign extend from signed 32-bit value.
298 result = (pint_t)(int32_t)get32(addr);
299 p += 4;
300 addr = (pint_t) p;
301 break;
302 case DW_EH_PE_sdata8:
303 result = (pint_t)get64(addr);
304 p += 8;
305 addr = (pint_t) p;
306 break;
307 default:
308 _LIBUNWIND_ABORT("unknown pointer encoding");
309 }
310
311 // then add relative offset
312 switch (encoding & 0x70) {
313 case DW_EH_PE_absptr:
314 // do nothing
315 break;
316 case DW_EH_PE_pcrel:
317 result += startAddr;
318 break;
319 case DW_EH_PE_textrel:
320 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
321 break;
322 case DW_EH_PE_datarel:
323 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
324 // default value of 0, and we abort in the event that someone calls this
325 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
326 if (datarelBase == 0)
327 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
328 result += datarelBase;
329 break;
330 case DW_EH_PE_funcrel:
331 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
332 break;
333 case DW_EH_PE_aligned:
334 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
335 break;
336 default:
337 _LIBUNWIND_ABORT("unknown pointer encoding");
338 break;
339 }
340
341 if (encoding & DW_EH_PE_indirect)
342 result = getP(result);
343
344 return result;
345}
346
Ryan Prichard7629c302020-08-27 23:46:49 -0700347#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
Sterling Augustine6d474102020-03-04 12:41:54 -0800348
Ryan Prichard7629c302020-08-27 23:46:49 -0700349// The ElfW() macro for pointer-size independent ELF header traversal is not
350// provided by <link.h> on some systems (e.g., FreeBSD). On these systems the
351// data structures are just called Elf_XXX. Define ElfW() locally.
352#if !defined(ElfW)
353 #define ElfW(type) Elf_##type
354#endif
Sterling Augustine6d474102020-03-04 12:41:54 -0800355#if !defined(Elf_Half)
356 typedef ElfW(Half) Elf_Half;
357#endif
358#if !defined(Elf_Phdr)
359 typedef ElfW(Phdr) Elf_Phdr;
360#endif
361#if !defined(Elf_Addr)
362 typedef ElfW(Addr) Elf_Addr;
363#endif
364
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800365static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) {
Sterling Augustine6d474102020-03-04 12:41:54 -0800366 Elf_Addr image_base = pinfo->dlpi_addr;
Sterling Augustine6d474102020-03-04 12:41:54 -0800367#if defined(__ANDROID__) && __ANDROID_API__ < 18
368 if (image_base == 0) {
369 // Normally, an image base of 0 indicates a non-PIE executable. On
370 // versions of Android prior to API 18, the dynamic linker reported a
371 // dlpi_addr of 0 for PIE executables. Compute the true image base
372 // using the PT_PHDR segment.
373 // See https://github.com/android/ndk/issues/505.
374 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
375 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
376 if (phdr->p_type == PT_PHDR) {
377 image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
378 phdr->p_vaddr;
379 break;
380 }
381 }
382 }
383#endif
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800384 return image_base;
385}
Sterling Augustine6d474102020-03-04 12:41:54 -0800386
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800387struct _LIBUNWIND_HIDDEN dl_iterate_cb_data {
388 LocalAddressSpace *addressSpace;
389 UnwindInfoSections *sects;
390 uintptr_t targetAddr;
391};
392
393#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Sterling Augustine6d474102020-03-04 12:41:54 -0800394 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800395 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
Sterling Augustine6d474102020-03-04 12:41:54 -0800396 #endif
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800397
Sterling Augustineb778c912020-08-18 12:05:07 -0700398#if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
Sterling Augustine2e9018a2020-03-10 12:03:24 -0700399#include "FrameHeaderCache.hpp"
400
Ryan Prichardc155d182020-08-19 01:54:17 -0700401// Typically there is one cache per process, but when libunwind is built as a
402// hermetic static library, then each shared object may have its own cache.
403static FrameHeaderCache TheFrameHeaderCache;
Sterling Augustineb778c912020-08-18 12:05:07 -0700404#endif
Sterling Augustine2e9018a2020-03-10 12:03:24 -0700405
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800406static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base,
407 dl_iterate_cb_data *cbdata) {
408 if (phdr->p_type == PT_LOAD) {
409 uintptr_t begin = image_base + phdr->p_vaddr;
410 uintptr_t end = begin + phdr->p_memsz;
411 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
412 cbdata->sects->dso_base = begin;
413 cbdata->sects->dwarf_section_length = phdr->p_memsz;
414 return true;
415 }
416 }
417 return false;
418}
419
Ryan Prichard6de71032020-08-22 17:12:52 -0700420static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
421 size_t pinfo_size, void *data) {
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800422 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
423 if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr)
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800424 return 0;
Sterling Augustineb778c912020-08-18 12:05:07 -0700425#if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
Ryan Prichardc155d182020-08-19 01:54:17 -0700426 if (TheFrameHeaderCache.find(pinfo, pinfo_size, data))
Sterling Augustine2e9018a2020-03-10 12:03:24 -0700427 return 1;
Mikael Holmen7c371492020-08-25 12:26:48 +0200428#else
429 // Avoid warning about unused variable.
430 (void)pinfo_size;
Sterling Augustineb778c912020-08-18 12:05:07 -0700431#endif
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800432
433 Elf_Addr image_base = calculateImageBase(pinfo);
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800434 bool found_obj = false;
435 bool found_hdr = false;
Sterling Augustine6d474102020-03-04 12:41:54 -0800436
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800437 // Third phdr is usually the executable phdr.
438 if (pinfo->dlpi_phnum > 2)
439 found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata);
440
441 // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know
442 // that there is one or more phdrs.
443 for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) {
444 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1];
445 if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) {
Sterling Augustine6d474102020-03-04 12:41:54 -0800446 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
447 uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr;
448 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
449 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
450 found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
451 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
452 hdrInfo);
453 if (found_hdr)
454 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800455 } else if (!found_obj) {
456 found_obj = checkAddrInSegment(phdr, image_base, cbdata);
Sterling Augustine6d474102020-03-04 12:41:54 -0800457 }
Sterling Augustine2e9018a2020-03-10 12:03:24 -0700458 if (found_obj && found_hdr) {
Sterling Augustineb778c912020-08-18 12:05:07 -0700459#if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
Ryan Prichardc155d182020-08-19 01:54:17 -0700460 TheFrameHeaderCache.add(cbdata->sects);
Sterling Augustineb778c912020-08-18 12:05:07 -0700461#endif
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800462 return 1;
Sterling Augustine2e9018a2020-03-10 12:03:24 -0700463 }
Sterling Augustine6d474102020-03-04 12:41:54 -0800464 }
Sterling Augustine5101ebe2020-03-06 15:59:16 -0800465 cbdata->sects->dwarf_section_length = 0;
466 return 0;
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800467}
468
Ryan Prichard7629c302020-08-27 23:46:49 -0700469#elif defined(_LIBUNWIND_ARM_EHABI)
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800470
Ryan Prichard6de71032020-08-22 17:12:52 -0700471static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t,
472 void *data) {
Sterling Augustine8eb93ce2020-03-05 11:50:51 -0800473 auto *cbdata = static_cast<dl_iterate_cb_data *>(data);
474 bool found_obj = false;
475 bool found_hdr = false;
476
477 assert(cbdata);
478 assert(cbdata->sects);
479
480 if (cbdata->targetAddr < pinfo->dlpi_addr)
481 return 0;
482
483 Elf_Addr image_base = calculateImageBase(pinfo);
484
Sterling Augustine6d474102020-03-04 12:41:54 -0800485 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
486 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
487 if (phdr->p_type == PT_LOAD) {
488 uintptr_t begin = image_base + phdr->p_vaddr;
489 uintptr_t end = begin + phdr->p_memsz;
490 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
491 found_obj = true;
492 } else if (phdr->p_type == PT_ARM_EXIDX) {
493 uintptr_t exidx_start = image_base + phdr->p_vaddr;
494 cbdata->sects->arm_section = exidx_start;
495 cbdata->sects->arm_section_length = phdr->p_memsz;
496 found_hdr = true;
497 }
498 }
499 return found_obj && found_hdr;
Sterling Augustine6d474102020-03-04 12:41:54 -0800500}
Ryan Prichard7629c302020-08-27 23:46:49 -0700501
502#endif
503#endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
Sterling Augustine6d474102020-03-04 12:41:54 -0800504
505
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000506inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
507 UnwindInfoSections &info) {
508#ifdef __APPLE__
509 dyld_unwind_sections dyldInfo;
510 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
511 info.dso_base = (uintptr_t)dyldInfo.mh;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000512 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000513 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
514 info.dwarf_section_length = dyldInfo.dwarf_section_length;
515 #endif
516 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
517 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
518 return true;
519 }
whitequarkffd92e52017-12-25 17:05:07 +0000520#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
Ryan Prichard2cfcb8c2020-09-09 15:43:35 -0700521 info.dso_base = 0;
whitequarkffd92e52017-12-25 17:05:07 +0000522 // Bare metal is statically linked, so no need to ask the dynamic loader
523 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
524 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000525 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
526 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000527#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
528 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
529 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000530 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
531 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
whitequarkffd92e52017-12-25 17:05:07 +0000532#endif
533 if (info.dwarf_section_length)
534 return true;
Ranjeet Singh421231a2017-03-31 15:28:06 +0000535#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000536 // Bare metal is statically linked, so no need to ask the dynamic loader
537 info.arm_section = (uintptr_t)(&__exidx_start);
538 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
Chandler Carruth3d957272017-12-27 05:46:53 +0000539 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
540 (void *)info.arm_section, (void *)info.arm_section_length);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000541 if (info.arm_section && info.arm_section_length)
542 return true;
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000543#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
544 HMODULE mods[1024];
545 HANDLE process = GetCurrentProcess();
546 DWORD needed;
547
Martin Storsjöa914ec12019-10-28 10:11:05 +0200548 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) {
549 DWORD err = GetLastError();
550 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "
551 "returned error %d", (int)err);
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000552 return false;
Martin Storsjöa914ec12019-10-28 10:11:05 +0200553 }
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000554
555 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
556 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
557 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
558 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
559 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
560 bool found_obj = false;
561 bool found_hdr = false;
562
563 info.dso_base = (uintptr_t)mods[i];
564 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
565 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
566 uintptr_t end = begin + pish->Misc.VirtualSize;
567 if (!strncmp((const char *)pish->Name, ".text",
568 IMAGE_SIZEOF_SHORT_NAME)) {
569 if (targetAddr >= begin && targetAddr < end)
570 found_obj = true;
571 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
572 IMAGE_SIZEOF_SHORT_NAME)) {
Martin Storsjo4c1f84d2017-10-11 20:06:18 +0000573 info.dwarf_section = begin;
574 info.dwarf_section_length = pish->Misc.VirtualSize;
575 found_hdr = true;
576 }
577 if (found_obj && found_hdr)
578 return true;
579 }
580 }
581 return false;
Charles Davisfa2e6202018-08-30 21:29:00 +0000582#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
583 // Don't even bother, since Windows has functions that do all this stuff
584 // for us.
Martin Storsjo059a1632019-01-22 22:12:23 +0000585 (void)targetAddr;
586 (void)info;
Charles Davisfa2e6202018-08-30 21:29:00 +0000587 return true;
Ryan Prichard7629c302020-08-27 23:46:49 -0700588#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000589 int length = 0;
590 info.arm_section =
591 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
Ryan Prichard2a4f1362019-10-18 19:59:22 +0000592 info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry);
Dan Albert1bf6ebe2017-11-01 21:26:06 +0000593 if (info.arm_section && info.arm_section_length)
594 return true;
Ryan Prichard7629c302020-08-27 23:46:49 -0700595#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000596 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
Sterling Augustine6d474102020-03-04 12:41:54 -0800597 int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000598 return static_cast<bool>(found);
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000599#endif
600
601 return false;
602}
603
604
605inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000606 // TO DO: if OS has way to dynamically register FDEs, check that.
607 (void)targetAddr;
608 (void)fde;
609 return false;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000610}
611
612inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
613 size_t bufLen,
614 unw_word_t *offset) {
Jordan Rupprecht8ac87db2018-06-29 20:41:50 +0000615#if _LIBUNWIND_USE_DLADDR
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000616 Dl_info dyldInfo;
617 if (dladdr((void *)addr, &dyldInfo)) {
618 if (dyldInfo.dli_sname != NULL) {
619 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
620 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
621 return true;
622 }
623 }
Martin Storsjo059a1632019-01-22 22:12:23 +0000624#else
625 (void)addr;
626 (void)buf;
627 (void)bufLen;
628 (void)offset;
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000629#endif
630 return false;
631}
632
Saleem Abdulrasool17552662015-04-24 19:39:17 +0000633} // namespace libunwind
634
635#endif // __ADDRESSSPACE_HPP__