mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-26 09:07:38 +01:00
Ditch using the libutil, it is not async-signal safe.
This commit is contained in:
parent
69001646fa
commit
e33fa9f73c
1 changed files with 55 additions and 22 deletions
|
@ -24,41 +24,74 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <libutil.h>
|
||||
#include <stdio.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
|
||||
tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff)
|
||||
{
|
||||
struct kinfo_vmentry *freep, *kve;
|
||||
int cnt, rc, i;
|
||||
int mib[4], error, ret;
|
||||
size_t len, len1;
|
||||
char *buf, *bp, *eb;
|
||||
struct kinfo_vmentry *kv;
|
||||
|
||||
freep = kinfo_getvmmap(pid, &cnt);
|
||||
if (freep == NULL)
|
||||
len = 0;
|
||||
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);
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
kve = &freep[i];
|
||||
if (ip < kve->kve_start || ip >= kve->kve_end)
|
||||
continue;
|
||||
if (kve->kve_type != KVME_TYPE_VNODE)
|
||||
{
|
||||
free(freep);
|
||||
return (-1);
|
||||
}
|
||||
*segbase = kve->kve_start;
|
||||
*mapoff = kve->kve_offset;
|
||||
rc = elf_map_image(ei, kve->kve_path);
|
||||
free(freep);
|
||||
return (rc);
|
||||
}
|
||||
free(freep);
|
||||
return (-1);
|
||||
len1 = len * 4 / 3;
|
||||
buf = get_mem(len1);
|
||||
if (buf == NULL)
|
||||
return (-1);
|
||||
error = sysctl(mib, 4, buf, &len, NULL, 0);
|
||||
if (error) {
|
||||
free_mem(buf, len1);
|
||||
return (-1);
|
||||
}
|
||||
ret = -1;
|
||||
for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
|
||||
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
|
||||
if (ip < kv->kve_start || ip >= kv->kve_end)
|
||||
continue;
|
||||
if (kv->kve_type != KVME_TYPE_VNODE)
|
||||
break;
|
||||
*segbase = kv->kve_start;
|
||||
*mapoff = kv->kve_offset;
|
||||
ret = elf_map_image(ei, kv->kve_path);
|
||||
break;
|
||||
}
|
||||
free_mem(buf, len1);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
||||
|
|
Loading…
Reference in a new issue