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
25e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/param.h>
264de09a9c1569e17132973b801f77bcab8d927480Konstantin Belousov#include <sys/types.h>
27e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/mman.h>
28e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov#include <sys/sysctl.h>
294de09a9c1569e17132973b801f77bcab8d927480Konstantin Belousov#include <sys/user.h>
3063ae8ca8947c67aaa402abbe46a12d118366e1dfKonstantin Belousov#include <stdio.h>
315f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov#include <errno.h>
322646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
332646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov#include "libunwind_i.h"
342646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov
35e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovstatic void *
36e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovget_mem(size_t sz)
37e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov{
38e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  void *res;
39e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
40e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
41e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (res == MAP_FAILED)
42e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov    return (NULL);
43e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  return (res);
44e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov}
45e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
46e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovstatic void
47e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousovfree_mem(void *ptr, size_t sz)
48e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov{
49e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  munmap(ptr, sz);
50e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov}
51e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
525f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousovstatic int
535f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousovget_pid_by_tid(int tid)
545f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov{
555f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  int mib[3], error;
565f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  size_t len, len1;
575f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  char *buf;
585f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  struct kinfo_proc *kv;
595f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  int i, pid;
605f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov
615f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  len = 0;
625f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  mib[0] = CTL_KERN;
635f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  mib[1] = KERN_PROC;
645f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  mib[2] = KERN_PROC_ALL;
655f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov
665f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  error = sysctl(mib, 3, NULL, &len, NULL, 0);
675f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  if (error == -1)
685f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    return (-1);
695f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  len1 = len * 4 / 3;
705f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  buf = get_mem(len1);
715f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  if (buf == NULL)
725f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    return (-1);
735f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  len = len1;
745f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  error = sysctl(mib, 3, buf, &len, NULL, 0);
755f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  if (error == -1) {
765f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    free_mem(buf, len1);
775f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    return (-1);
785f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  }
795f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  pid = -1;
805f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  for (i = 0, kv = (struct kinfo_proc *)buf; i < len / sizeof(*kv);
815f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov   i++, kv++) {
825f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    if (kv->ki_tid == tid) {
835f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov      pid = kv->ki_pid;
845f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov      break;
855f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov    }
865f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  }
875f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  free_mem(buf, len1);
885f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  return (pid);
895f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov}
905f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov
91f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris/* ANDROID support update. */
92f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrisstruct map_info *
93f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferrismap_create_list(pid_t pid)
942646e0fde8a5721ec7356dce38e5341b3080ca62Konstantin Belousov{
95e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  int mib[4], error, ret;
96e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  size_t len, len1;
97e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  char *buf, *bp, *eb;
98e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  struct kinfo_vmentry *kv;
99f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  struct map_info *map_list = NULL;
100e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov
101e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  len = 0;
102e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[0] = CTL_KERN;
103e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[1] = KERN_PROC;
104e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[2] = KERN_PROC_VMMAP;
105e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  mib[3] = pid;
106bd2798805a68eac5491a4b096659a05e61e83580Konstantin Belousov
107e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  error = sysctl(mib, 4, NULL, &len, NULL, 0);
1085f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  if (error == -1) {
109f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    if (errno == ESRCH)
110f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      {
111f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        mib[3] = get_pid_by_tid(pid);
112f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        if (mib[3] != -1)
113f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          error = sysctl(mib, 4, NULL, &len, NULL, 0);
114f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        if (error == -1)
115f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris          return (-UNW_EUNSPEC);
116f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      }
117f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    else
1185f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov      return (-UNW_EUNSPEC);
1195f440b4af2b5dcae2f15652999b9aca7db55d02cKonstantin Belousov  }
120e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  len1 = len * 4 / 3;
121e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  buf = get_mem(len1);
122e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  if (buf == NULL)
1230fac4c8109e23b5363fea3366e35ba17d9f7ea79Konstantin Belousov    return (-UNW_EUNSPEC);
12461f4345a9e812713287e9f04949100416180b38fKonstantin Belousov  len = len1;
125e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  error = sysctl(mib, 4, buf, &len, NULL, 0);
126f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  if (error == -1)
127f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
128f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      free_mem(buf, len1);
129f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      return (-UNW_EUNSPEC);
130f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
1310fac4c8109e23b5363fea3366e35ba17d9f7ea79Konstantin Belousov  ret = -UNW_EUNSPEC;
132f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize)
133f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    {
134f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      kv = (struct kinfo_vmentry *)(uintptr_t)bp;
135f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (kv->kve_type != KVME_TYPE_VNODE)
136f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        continue;
137f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris
138f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map = map_alloc_info ();
139f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      if (cur_map == NULL)
140f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris        break;
141f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->next = map_list;
142f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->start = kv->kve_start;
143f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->end = kv->kv_end;
144f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->offset = kv->kve_offset;
145f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->path = strdup(kv->kve_path);
146f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      mutex_init (&cur_map->ei_lock);
147f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->ei.size = 0;
148f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->ei.image = NULL;
149f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris      cur_map->ei_shared = 0;
150f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris    }
151e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44Konstantin Belousov  free_mem(buf, len1);
1527d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris
153f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris  return map_list;
1547d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris}
155f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris/* End of ANDROID update. */
156