Skip to content

Commit

Permalink
Merge pull request #10 from petrhosek/libunwind-cherry-pick
Browse files Browse the repository at this point in the history
Libunwind cherry pick
  • Loading branch information
alexcrichton authored Mar 13, 2019
2 parents 38ad31b + b6e414a commit ce9347d
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 250 deletions.
26 changes: 0 additions & 26 deletions libunwind/include/libunwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,32 +125,6 @@ extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUN

extern unw_addr_space_t unw_local_addr_space;

#ifdef UNW_REMOTE
/*
* Mac OS X "remote" API for unwinding other processes on same machine
*
*/
extern unw_addr_space_t unw_create_addr_space_for_task(task_t);
extern void unw_destroy_addr_space(unw_addr_space_t);
extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *);
#endif /* UNW_REMOTE */

/*
* traditional libunwind "remote" API
* NOT IMPLEMENTED on Mac OS X
*
* extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t,
* thread_t*);
* extern unw_accessors_t unw_get_accessors(unw_addr_space_t);
* extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int);
* extern void unw_flush_cache(unw_addr_space_t, unw_word_t,
* unw_word_t);
* extern int unw_set_caching_policy(unw_addr_space_t,
* unw_caching_policy_t);
* extern void _U_dyn_register(unw_dyn_info_t*);
* extern void _U_dyn_cancel(unw_dyn_info_t*);
*/

#ifdef __cplusplus
}
#endif
Expand Down
132 changes: 0 additions & 132 deletions libunwind/src/AddressSpace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,138 +601,6 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
return false;
}



#ifdef UNW_REMOTE

/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
/// unwinding a thread in the another process. The other process can be a
/// different endianness and a different pointer size which is handled by
/// the P template parameter.
template <typename P>
class RemoteAddressSpace {
public:
RemoteAddressSpace(task_t task) : fTask(task) {}

typedef typename P::uint_t pint_t;

uint8_t get8(pint_t addr);
uint16_t get16(pint_t addr);
uint32_t get32(pint_t addr);
uint64_t get64(pint_t addr);
pint_t getP(pint_t addr);
uint64_t getRegister(pint_t addr);
uint64_t getULEB128(pint_t &addr, pint_t end);
int64_t getSLEB128(pint_t &addr, pint_t end);
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
pint_t datarelBase = 0);
bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
unw_word_t *offset);
bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
bool findOtherFDE(pint_t targetAddr, pint_t &fde);
private:
void *localCopy(pint_t addr);

task_t fTask;
};

template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
return *((uint8_t *)localCopy(addr));
}

template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
return P::E::get16(*(uint16_t *)localCopy(addr));
}

template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
return P::E::get32(*(uint32_t *)localCopy(addr));
}

template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
return P::E::get64(*(uint64_t *)localCopy(addr));
}

template <typename P>
typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
return P::getP(*(uint64_t *)localCopy(addr));
}

template <typename P>
typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
return P::getRegister(*(uint64_t *)localCopy(addr));
}

template <typename P>
uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
uintptr_t size = (end - addr);
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
LocalAddressSpace::pint_t sladdr = laddr;
uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
addr += (laddr - sladdr);
return result;
}

template <typename P>
int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
uintptr_t size = (end - addr);
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
LocalAddressSpace::pint_t sladdr = laddr;
uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
addr += (laddr - sladdr);
return result;
}

template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
// FIX ME
}

template <typename P>
bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
size_t bufLen,
unw_word_t *offset) {
// FIX ME
}

/// unw_addr_space is the base class that abstract unw_addr_space_t type in
/// libunwind.h points to.
struct unw_addr_space {
cpu_type_t cpuType;
task_t taskPort;
};

/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
/// to when examining
/// a 32-bit intel process.
struct unw_addr_space_i386 : public unw_addr_space {
unw_addr_space_i386(task_t task) : oas(task) {}
RemoteAddressSpace<Pointer32<LittleEndian>> oas;
};

/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
/// points to when examining
/// a 64-bit intel process.
struct unw_addr_space_x86_64 : public unw_addr_space {
unw_addr_space_x86_64(task_t task) : oas(task) {}
RemoteAddressSpace<Pointer64<LittleEndian>> oas;
};

/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
/// to when examining
/// a 32-bit PowerPC process.
struct unw_addr_space_ppc : public unw_addr_space {
unw_addr_space_ppc(task_t task) : oas(task) {}
RemoteAddressSpace<Pointer32<BigEndian>> oas;
};

/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
/// to when examining a 64-bit PowerPC process.
struct unw_addr_space_ppc64 : public unw_addr_space {
unw_addr_space_ppc64(task_t task) : oas(task) {}
RemoteAddressSpace<Pointer64<LittleEndian>> oas;
};

#endif // UNW_REMOTE

} // namespace libunwind

#endif // __ADDRESSSPACE_HPP__
15 changes: 9 additions & 6 deletions libunwind/src/Unwind-seh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,20 +442,23 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
static int
_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
#ifdef _LIBUNWIND_TARGET_X86_64
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_x86_64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_ARM)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
#elif defined(_LIBUNWIND_TARGET_AARCH64)
new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))
UnwindCursor<LocalAddressSpace, Registers_arm64>(
context, LocalAddressSpace::sThisAddressSpace);
auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
co->setInfoBasedOnIPRegister();
return UNW_ESUCCESS;
Expand Down
8 changes: 8 additions & 0 deletions libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ class UnwindCursor : public AbstractUnwindCursor {
DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }

// libunwind does not and should not depend on C++ library which means that we
// need our own defition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }

private:

pint_t getLastPC() const { return _dispContext.ControlPc; }
Expand Down Expand Up @@ -892,6 +896,10 @@ class UnwindCursor : public AbstractUnwindCursor{
virtual void saveVFPAsX();
#endif

// libunwind does not and should not depend on C++ library which means that we
// need our own defition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }

private:

#if defined(_LIBUNWIND_ARM_EHABI)
Expand Down
89 changes: 3 additions & 86 deletions libunwind/src/libunwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
#ifndef NDEBUG
#include <cstdlib> // getenv
#endif
#include <new>
#include <algorithm>

#include "libunwind_ext.h"
#include "config.h"
Expand Down Expand Up @@ -73,97 +71,16 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# error Architecture not supported
#endif
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
context, LocalAddressSpace::sThisAddressSpace);
new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
context, LocalAddressSpace::sThisAddressSpace);
#undef REGISTER_KIND
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->setInfoBasedOnIPRegister();

return UNW_ESUCCESS;
}

#ifdef UNW_REMOTE
/// Create a cursor into a thread in another process.
_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
unw_addr_space_t as,
void *arg) {
// special case: unw_init_remote(xx, unw_local_addr_space, xx)
if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
return unw_init_local(cursor, NULL); //FIXME

// use "placement new" to allocate UnwindCursor in the cursor buffer
switch (as->cpuType) {
case CPU_TYPE_I386:
new ((void *)cursor)
UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
break;
case CPU_TYPE_X86_64:
new ((void *)cursor)
UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
break;
case CPU_TYPE_POWERPC:
new ((void *)cursor)
UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
break;
default:
return UNW_EUNSPEC;
}
return UNW_ESUCCESS;
}


static bool is64bit(task_t task) {
return false; // FIXME
}

/// Create an address_space object for use in examining another task.
_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
#if __i386__
if (is64bit(task)) {
unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
as->taskPort = task;
as->cpuType = CPU_TYPE_X86_64;
//as->oas
} else {
unw_addr_space_i386 *as = new unw_addr_space_i386(task);
as->taskPort = task;
as->cpuType = CPU_TYPE_I386;
//as->oas
}
#else
// FIXME
#endif
}


/// Delete an address_space object.
_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
switch (asp->cpuType) {
#if __i386__ || __x86_64__
case CPU_TYPE_I386: {
unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
delete as;
}
break;
case CPU_TYPE_X86_64: {
unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
delete as;
}
break;
#endif
case CPU_TYPE_POWERPC: {
unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
delete as;
}
break;
}
}
#endif // UNW_REMOTE


/// Get value of specified register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_word_t *value) {
Expand Down

0 comments on commit ce9347d

Please sign in to comment.