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:
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
|
#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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue