1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-02-18 11:01:41 +01:00

Ditch using the libutil, it is not async-signal safe.

This commit is contained in:
Konstantin Belousov 2010-04-11 14:36:24 +03:00
parent 69001646fa
commit e33fa9f73c

View file

@ -24,41 +24,74 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#ifndef UNW_REMOTE_ONLY #ifndef UNW_REMOTE_ONLY
#include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <sys/user.h> #include <sys/user.h>
#include <libutil.h> #include <libutil.h>
#include <stdio.h> #include <stdio.h>
#include "libunwind_i.h" #include "libunwind_i.h"
static void *
get_mem(size_t sz)
{
void *res;
res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (res == MAP_FAILED)
return (NULL);
return (res);
}
static void
free_mem(void *ptr, size_t sz)
{
munmap(ptr, sz);
}
PROTECTED int PROTECTED int
tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
unsigned long *segbase, unsigned long *mapoff) unsigned long *segbase, unsigned long *mapoff)
{ {
struct kinfo_vmentry *freep, *kve; int mib[4], error, ret;
int cnt, rc, i; size_t len, len1;
char *buf, *bp, *eb;
struct kinfo_vmentry *kv;
freep = kinfo_getvmmap(pid, &cnt); len = 0;
if (freep == NULL) mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_VMMAP;
mib[3] = pid;
error = sysctl(mib, 4, NULL, &len, NULL, 0);
if (error)
return (-1); return (-1);
for (i = 0; i < cnt; i++) len1 = len * 4 / 3;
{ buf = get_mem(len1);
kve = &freep[i]; if (buf == NULL)
if (ip < kve->kve_start || ip >= kve->kve_end) return (-1);
continue; error = sysctl(mib, 4, buf, &len, NULL, 0);
if (kve->kve_type != KVME_TYPE_VNODE) if (error) {
{ free_mem(buf, len1);
free(freep); return (-1);
return (-1); }
} ret = -1;
*segbase = kve->kve_start; for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
*mapoff = kve->kve_offset; kv = (struct kinfo_vmentry *)(uintptr_t)bp;
rc = elf_map_image(ei, kve->kve_path); if (ip < kv->kve_start || ip >= kv->kve_end)
free(freep); continue;
return (rc); if (kv->kve_type != KVME_TYPE_VNODE)
} break;
free(freep); *segbase = kv->kve_start;
return (-1); *mapoff = kv->kve_offset;
ret = elf_map_image(ei, kv->kve_path);
break;
}
free_mem(buf, len1);
return (ret);
} }
#endif /* UNW_REMOTE_ONLY */ #endif /* UNW_REMOTE_ONLY */