os-freebsd.c revision 298e575f2cbb4616004717812f28879b2633a6ac
12646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov/* libunwind - a platform-independent unwind library
26f7b335e89e1b7f9c539fc0ebb3f789e34d0b7e4Konstantin Belousov   Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
32646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
42646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovThis file is part of libunwind.
52646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
62646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovPermission is hereby granted, free of charge, to any person obtaining
72646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousova copy of this software and associated documentation files (the
82646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov"Software"), to deal in the Software without restriction, including
92646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovwithout limitation the rights to use, copy, modify, merge, publish,
102646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovdistribute, sublicense, and/or sell copies of the Software, and to
112646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovpermit persons to whom the Software is furnished to do so, subject to
122646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovthe following conditions:
132646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
142646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovThe above copyright notice and this permission notice shall be
152646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovincluded in all copies or substantial portions of the Software.
162646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
172646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin BelousovWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
242646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
252646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov#ifndef UNW_REMOTE_ONLY
262646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
27e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/param.h>
284de09a9c1569e17132973b801f77bcab8d927480Konstantin Belousov#include <sys/types.h>
29e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/mman.h>
30e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/sysctl.h>
314de09a9c1569e17132973b801f77bcab8d927480Konstantin Belousov#include <sys/user.h>
3263ae8ca8947c67aaa402abbe46a12d118366e1dfKonstantin Belousov#include <stdio.h>
332646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
342646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov#include "libunwind_i.h"
352646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
36e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovstatic void *
37e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovget_mem(size_t sz)
38e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov{
39e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  void *res;
40e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
41e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
42e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (res == MAP_FAILED)
43e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov    return (NULL);
44e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  return (res);
45e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov}
46e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
47e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovstatic void
48e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovfree_mem(void *ptr, size_t sz)
49e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov{
50e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  munmap(ptr, sz);
51e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov}
52e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
53bd2798805a68eac5491a4b096659a05e61e83580Konstantin BelousovPROTECTED int
542646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousovtdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
551787a2fd284a786b409af74047a12de02c644cd1Arun Sharma		    unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen)
562646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov{
57e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  int mib[4], error, ret;
58e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  size_t len, len1;
59e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  char *buf, *bp, *eb;
60e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  struct kinfo_vmentry *kv;
61e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
62e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  len = 0;
63e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[0] = CTL_KERN;
64e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[1] = KERN_PROC;
65e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[2] = KERN_PROC_VMMAP;
66e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[3] = pid;
67bd2798805a68eac5491a4b096659a05e61e83580Konstantin Belousov
68e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  error = sysctl(mib, 4, NULL, &len, NULL, 0);
69e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (error)
70e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov    return (-1);
71e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  len1 = len * 4 / 3;
72e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  buf = get_mem(len1);
73e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (buf == NULL)
74e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov    return (-1);
7561f4345a9e812713287e9f04949100416180b38fKonstantin Belousov  len = len1;
76e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  error = sysctl(mib, 4, buf, &len, NULL, 0);
77e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (error) {
78e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov    free_mem(buf, len1);
79bd2798805a68eac5491a4b096659a05e61e83580Konstantin Belousov    return (-1);
80e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  }
81e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  ret = -1;
82e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
83e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     kv = (struct kinfo_vmentry *)(uintptr_t)bp;
84e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     if (ip < kv->kve_start || ip >= kv->kve_end)
85e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov       continue;
86e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     if (kv->kve_type != KVME_TYPE_VNODE)
87e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov       break;
88e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     *segbase = kv->kve_start;
89e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     *mapoff = kv->kve_offset;
901787a2fd284a786b409af74047a12de02c644cd1Arun Sharma     if (path)
911787a2fd284a786b409af74047a12de02c644cd1Arun Sharma       {
92298e575f2cbb4616004717812f28879b2633a6acKonstantin Belousov         strncpy(path, kv->kve_path, pathlen);
931787a2fd284a786b409af74047a12de02c644cd1Arun Sharma       }
94e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     ret = elf_map_image(ei, kv->kve_path);
95e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov     break;
96e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  }
97e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  free_mem(buf, len1);
98e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  return (ret);
992646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov}
1002646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
1012646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov#endif /* UNW_REMOTE_ONLY */
102