mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-26 00:57:39 +01:00
dwarf: Configurable cache size
Add interface for configurable dwarf cache size * Use item size and round up to nearest power of 2. * Initial cache still exists in BSS. Without this, it means we would fail backtrace when out of memory. The test-mem test fails without this
This commit is contained in:
parent
29483327be
commit
a51cf49031
19 changed files with 314 additions and 32 deletions
|
@ -17,6 +17,7 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \
|
||||||
unw_destroy_addr_space.man \
|
unw_destroy_addr_space.man \
|
||||||
unw_regname.man unw_resume.man \
|
unw_regname.man unw_resume.man \
|
||||||
unw_set_caching_policy.man \
|
unw_set_caching_policy.man \
|
||||||
|
unw_set_cache_size.man \
|
||||||
unw_set_fpreg.man \
|
unw_set_fpreg.man \
|
||||||
unw_set_reg.man \
|
unw_set_reg.man \
|
||||||
unw_step.man \
|
unw_step.man \
|
||||||
|
@ -41,6 +42,7 @@ EXTRA_DIST = NOTES libunwind.trans \
|
||||||
unw_is_signal_frame.tex \
|
unw_is_signal_frame.tex \
|
||||||
unw_create_addr_space.tex unw_destroy_addr_space.tex \
|
unw_create_addr_space.tex unw_destroy_addr_space.tex \
|
||||||
unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \
|
unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \
|
||||||
|
unw_set_cache_size.tex \
|
||||||
unw_set_fpreg.tex \
|
unw_set_fpreg.tex \
|
||||||
unw_set_reg.tex \
|
unw_set_reg.tex \
|
||||||
unw_step.tex \
|
unw_step.tex \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'\" t
|
'\" t
|
||||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:43 MDT 2007
|
.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017
|
||||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||||
.de Vb
|
.de Vb
|
||||||
.ft CW
|
.ft CW
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
.fi
|
.fi
|
||||||
..
|
..
|
||||||
.TH "LIBUNWIND" "3" "16 August 2007" "Programming Library " "Programming Library "
|
.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library "
|
||||||
.SH NAME
|
.SH NAME
|
||||||
libunwind
|
libunwind
|
||||||
\-\- a (mostly) platform\-independent unwind API
|
\-\- a (mostly) platform\-independent unwind API
|
||||||
|
@ -82,6 +82,11 @@ int
|
||||||
unw_set_caching_policy(unw_addr_space_t,
|
unw_set_caching_policy(unw_addr_space_t,
|
||||||
unw_caching_policy_t);
|
unw_caching_policy_t);
|
||||||
.br
|
.br
|
||||||
|
int
|
||||||
|
unw_set_cache_size(unw_addr_space_t,
|
||||||
|
size_t,
|
||||||
|
int);
|
||||||
|
.br
|
||||||
.PP
|
.PP
|
||||||
const char *unw_regname(unw_regnum_t);
|
const char *unw_regname(unw_regnum_t);
|
||||||
.br
|
.br
|
||||||
|
@ -428,7 +433,9 @@ UNW_CACHE_NONE,
|
||||||
it is possible to turn off caching
|
it is possible to turn off caching
|
||||||
completely, therefore eliminating the risk of stale data alltogether
|
completely, therefore eliminating the risk of stale data alltogether
|
||||||
(at the cost of slower execution). By default, caching is enabled for
|
(at the cost of slower execution). By default, caching is enabled for
|
||||||
local unwinding only.
|
local unwinding only. The cache size can be dynamically changed with
|
||||||
|
unw_set_cache_size(),
|
||||||
|
which also fluches the current cache.
|
||||||
.PP
|
.PP
|
||||||
.SH FILES
|
.SH FILES
|
||||||
|
|
||||||
|
@ -482,6 +489,7 @@ unw_is_signal_frame(3),
|
||||||
unw_regname(3),
|
unw_regname(3),
|
||||||
unw_resume(3),
|
unw_resume(3),
|
||||||
unw_set_caching_policy(3),
|
unw_set_caching_policy(3),
|
||||||
|
unw_set_cache_size(3),
|
||||||
unw_set_fpreg(3),
|
unw_set_fpreg(3),
|
||||||
unw_set_reg(3),
|
unw_set_reg(3),
|
||||||
unw_step(3),
|
unw_step(3),
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
|
\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
|
||||||
\noindent
|
\noindent
|
||||||
\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\
|
\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\
|
||||||
|
\noindent
|
||||||
|
\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t}, \Type{size\_t}, \Type{int});\\
|
||||||
|
|
||||||
\noindent
|
\noindent
|
||||||
\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\
|
\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\
|
||||||
|
@ -293,7 +295,8 @@ object. In particular, by selecting the policy
|
||||||
\Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
|
\Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
|
||||||
completely, therefore eliminating the risk of stale data alltogether
|
completely, therefore eliminating the risk of stale data alltogether
|
||||||
(at the cost of slower execution). By default, caching is enabled for
|
(at the cost of slower execution). By default, caching is enabled for
|
||||||
local unwinding only.
|
local unwinding only. The cache size can be dynamically changed with
|
||||||
|
\Func{unw\_set\_cache\_size}(), which also fluches the current cache.
|
||||||
|
|
||||||
|
|
||||||
\section{Files}
|
\section{Files}
|
||||||
|
@ -337,6 +340,7 @@ local unwinding only.
|
||||||
\SeeAlso{unw\_regname(3)},
|
\SeeAlso{unw\_regname(3)},
|
||||||
\SeeAlso{unw\_resume(3)},
|
\SeeAlso{unw\_resume(3)},
|
||||||
\SeeAlso{unw\_set\_caching\_policy(3)},
|
\SeeAlso{unw\_set\_caching\_policy(3)},
|
||||||
|
\SeeAlso{unw\_set\_cache\_size(3)},
|
||||||
\SeeAlso{unw\_set\_fpreg(3)},
|
\SeeAlso{unw\_set\_fpreg(3)},
|
||||||
\SeeAlso{unw\_set\_reg(3)},
|
\SeeAlso{unw\_set\_reg(3)},
|
||||||
\SeeAlso{unw\_step(3)},
|
\SeeAlso{unw\_step(3)},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'\" t
|
'\" t
|
||||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
|
.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
|
||||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||||
.de Vb
|
.de Vb
|
||||||
.ft CW
|
.ft CW
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
.fi
|
.fi
|
||||||
..
|
..
|
||||||
.TH "UNW\\_FLUSH\\_CACHE" "3" "16 August 2007" "Programming Library " "Programming Library "
|
.TH "UNW\\_FLUSH\\_CACHE" "3" "02 December 2016" "Programming Library " "Programming Library "
|
||||||
.SH NAME
|
.SH NAME
|
||||||
unw_flush_cache
|
unw_flush_cache
|
||||||
\-\- flush cached info
|
\-\- flush cached info
|
||||||
|
@ -80,6 +80,7 @@ use from a signal handler.
|
||||||
.PP
|
.PP
|
||||||
libunwind(3),
|
libunwind(3),
|
||||||
unw_set_caching_policy(3)
|
unw_set_caching_policy(3)
|
||||||
|
unw_set_cache_size(3)
|
||||||
.PP
|
.PP
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ use from a signal handler.
|
||||||
|
|
||||||
\SeeAlso{libunwind(3)},
|
\SeeAlso{libunwind(3)},
|
||||||
\SeeAlso{unw\_set\_caching\_policy(3)}
|
\SeeAlso{unw\_set\_caching\_policy(3)}
|
||||||
|
\SeeAlso{unw\_set\_cache\_size(3)}
|
||||||
|
|
||||||
\section{Author}
|
\section{Author}
|
||||||
|
|
||||||
|
|
88
doc/unw_set_cache_size.man
Normal file
88
doc/unw_set_cache_size.man
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
'\" t
|
||||||
|
.\" Manual page created with latex2man on Fri Jan 13 08:33:21 PST 2017
|
||||||
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||||
|
.de Vb
|
||||||
|
.ft CW
|
||||||
|
.nf
|
||||||
|
..
|
||||||
|
.de Ve
|
||||||
|
.ft R
|
||||||
|
|
||||||
|
.fi
|
||||||
|
..
|
||||||
|
.TH "UNW\\_SET\\_CACHE\\_SIZE" "3" "13 January 2017" "Programming Library " "Programming Library "
|
||||||
|
.SH NAME
|
||||||
|
unw_set_cache_size
|
||||||
|
\-\- set unwind cache size
|
||||||
|
.PP
|
||||||
|
.SH SYNOPSIS
|
||||||
|
|
||||||
|
.PP
|
||||||
|
#include <libunwind.h>
|
||||||
|
.br
|
||||||
|
.PP
|
||||||
|
int
|
||||||
|
unw_set_cache_size(unw_addr_space_t
|
||||||
|
as,
|
||||||
|
size_t
|
||||||
|
size,
|
||||||
|
int
|
||||||
|
flag);
|
||||||
|
.br
|
||||||
|
.PP
|
||||||
|
.SH DESCRIPTION
|
||||||
|
|
||||||
|
.PP
|
||||||
|
The unw_set_cache_size()
|
||||||
|
routine sets the cache size of
|
||||||
|
address space as
|
||||||
|
to hold at least as many items as given by
|
||||||
|
argument size\&.
|
||||||
|
It may hold more items as determined by the
|
||||||
|
implementation. To disable caching, call
|
||||||
|
unw_set_caching_policy)
|
||||||
|
with a policy of
|
||||||
|
UNW_CACHE_NONE\&.
|
||||||
|
Flag is currently unused and must be 0.
|
||||||
|
.PP
|
||||||
|
.SH RETURN VALUE
|
||||||
|
|
||||||
|
.PP
|
||||||
|
On successful completion, unw_set_cache_size()
|
||||||
|
returns 0.
|
||||||
|
Otherwise the negative value of one of the error\-codes below is
|
||||||
|
returned.
|
||||||
|
.PP
|
||||||
|
.SH THREAD AND SIGNAL SAFETY
|
||||||
|
|
||||||
|
.PP
|
||||||
|
unw_set_cache_size()
|
||||||
|
is thread\-safe but \fInot\fP
|
||||||
|
safe
|
||||||
|
to use from a signal handler.
|
||||||
|
.PP
|
||||||
|
.SH ERRORS
|
||||||
|
|
||||||
|
.PP
|
||||||
|
.TP
|
||||||
|
UNW_ENOMEM
|
||||||
|
The desired cache size could not be
|
||||||
|
established because the application is out of memory.
|
||||||
|
.PP
|
||||||
|
.SH SEE ALSO
|
||||||
|
|
||||||
|
.PP
|
||||||
|
libunwind(3),
|
||||||
|
unw_create_addr_space(3),
|
||||||
|
unw_set_caching_policy(3),
|
||||||
|
unw_flush_cache(3)
|
||||||
|
.PP
|
||||||
|
.SH AUTHOR
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Dave Watson
|
||||||
|
.br
|
||||||
|
Email: \fBdade.watson@gmail.com\fP
|
||||||
|
.br
|
||||||
|
WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
|
||||||
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
59
doc/unw_set_cache_size.tex
Normal file
59
doc/unw_set_cache_size.tex
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
\documentclass{article}
|
||||||
|
\usepackage[fancyhdr,pdf]{latex2man}
|
||||||
|
|
||||||
|
\input{common.tex}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\begin{Name}{3}{unw\_set\_cache\_size}{Dave Watson}{Programming Library}{unw\_set\_cache\_size}unw\_set\_cache\_size -- set unwind cache size
|
||||||
|
\end{Name}
|
||||||
|
|
||||||
|
\section{Synopsis}
|
||||||
|
|
||||||
|
\File{\#include $<$libunwind.h$>$}\\
|
||||||
|
|
||||||
|
\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{size\_t} \Var{size}, \Type{int} \Var{flag});\\
|
||||||
|
|
||||||
|
\section{Description}
|
||||||
|
|
||||||
|
The \Func{unw\_set\_cache\_size}() routine sets the cache size of
|
||||||
|
address space \Var{as} to hold at least as many items as given by
|
||||||
|
argument \Var{size}. It may hold more items as determined by the
|
||||||
|
implementation. To disable caching, call
|
||||||
|
\Func{unw\_set\_caching\_policy}) with a policy of
|
||||||
|
\Const{UNW\_CACHE\_NONE}. Flag is currently unused and must be 0.
|
||||||
|
|
||||||
|
\section{Return Value}
|
||||||
|
|
||||||
|
On successful completion, \Func{unw\_set\_cache\_size}() returns 0.
|
||||||
|
Otherwise the negative value of one of the error-codes below is
|
||||||
|
returned.
|
||||||
|
|
||||||
|
\section{Thread and Signal Safety}
|
||||||
|
|
||||||
|
\Func{unw\_set\_cache\_size}() is thread-safe but \emph{not} safe
|
||||||
|
to use from a signal handler.
|
||||||
|
|
||||||
|
\section{Errors}
|
||||||
|
|
||||||
|
\begin{Description}
|
||||||
|
\item[\Const{UNW\_ENOMEM}] The desired cache size could not be
|
||||||
|
established because the application is out of memory.
|
||||||
|
\end{Description}
|
||||||
|
|
||||||
|
\section{See Also}
|
||||||
|
|
||||||
|
\SeeAlso{libunwind(3)},
|
||||||
|
\SeeAlso{unw\_create\_addr\_space(3)},
|
||||||
|
\SeeAlso{unw\_set\_caching\_policy(3)},
|
||||||
|
\SeeAlso{unw\_flush\_cache(3)}
|
||||||
|
|
||||||
|
\section{Author}
|
||||||
|
|
||||||
|
\noindent
|
||||||
|
Dave Watson\\
|
||||||
|
Email: \Email{dade.watson@gmail.com}\\
|
||||||
|
WWW: \URL{http://www.nongnu.org/libunwind/}.
|
||||||
|
\LatexManEnd
|
||||||
|
|
||||||
|
\end{document}
|
|
@ -1,5 +1,5 @@
|
||||||
'\" t
|
'\" t
|
||||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
|
.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
|
||||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||||
.de Vb
|
.de Vb
|
||||||
.ft CW
|
.ft CW
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
.fi
|
.fi
|
||||||
..
|
..
|
||||||
.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "16 August 2007" "Programming Library " "Programming Library "
|
.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "02 December 2016" "Programming Library " "Programming Library "
|
||||||
.SH NAME
|
.SH NAME
|
||||||
unw_set_caching_policy
|
unw_set_caching_policy
|
||||||
\-\- set unwind caching policy
|
\-\- set unwind caching policy
|
||||||
|
@ -105,6 +105,7 @@ established because the application is out of memory.
|
||||||
.PP
|
.PP
|
||||||
libunwind(3),
|
libunwind(3),
|
||||||
unw_create_addr_space(3),
|
unw_create_addr_space(3),
|
||||||
|
unw_set_cache_size(3),
|
||||||
unw_flush_cache(3)
|
unw_flush_cache(3)
|
||||||
.PP
|
.PP
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
|
|
|
@ -67,6 +67,7 @@ to use from a signal handler.
|
||||||
|
|
||||||
\SeeAlso{libunwind(3)},
|
\SeeAlso{libunwind(3)},
|
||||||
\SeeAlso{unw\_create\_addr\_space(3)},
|
\SeeAlso{unw\_create\_addr\_space(3)},
|
||||||
|
\SeeAlso{unw\_set\_cache\_size(3)},
|
||||||
\SeeAlso{unw\_flush\_cache(3)}
|
\SeeAlso{unw\_flush\_cache(3)}
|
||||||
|
|
||||||
\section{Author}
|
\section{Author}
|
||||||
|
|
|
@ -325,11 +325,11 @@ typedef struct dwarf_cursor
|
||||||
}
|
}
|
||||||
dwarf_cursor_t;
|
dwarf_cursor_t;
|
||||||
|
|
||||||
#define DWARF_LOG_UNW_CACHE_SIZE 7
|
#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
|
||||||
#define DWARF_UNW_CACHE_SIZE (1 << DWARF_LOG_UNW_CACHE_SIZE)
|
#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
|
||||||
|
|
||||||
#define DWARF_LOG_UNW_HASH_SIZE (DWARF_LOG_UNW_CACHE_SIZE + 1)
|
#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
|
||||||
#define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE)
|
#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
|
||||||
|
|
||||||
typedef unsigned char unw_hash_index_t;
|
typedef unsigned char unw_hash_index_t;
|
||||||
|
|
||||||
|
@ -339,13 +339,20 @@ struct dwarf_rs_cache
|
||||||
unsigned short lru_head; /* index of lead-recently used rs */
|
unsigned short lru_head; /* index of lead-recently used rs */
|
||||||
unsigned short lru_tail; /* index of most-recently used rs */
|
unsigned short lru_tail; /* index of most-recently used rs */
|
||||||
|
|
||||||
|
unsigned short log_size;
|
||||||
|
unsigned short prev_log_size;
|
||||||
|
|
||||||
/* hash table that maps instruction pointer to rs index: */
|
/* hash table that maps instruction pointer to rs index: */
|
||||||
unsigned short hash[DWARF_UNW_HASH_SIZE];
|
unsigned short *hash;
|
||||||
|
|
||||||
uint32_t generation; /* generation number */
|
uint32_t generation; /* generation number */
|
||||||
|
|
||||||
/* rs cache: */
|
/* rs cache: */
|
||||||
dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
|
dwarf_reg_state_t *buckets;
|
||||||
|
|
||||||
|
/* default memory, loaded in BSS segment */
|
||||||
|
unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
|
||||||
|
dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A list of descriptors for loaded .debug_frame sections. */
|
/* A list of descriptors for loaded .debug_frame sections. */
|
||||||
|
@ -395,6 +402,7 @@ struct dwarf_callback_data
|
||||||
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
||||||
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
||||||
#define dwarf_step UNW_OBJ (dwarf_step)
|
#define dwarf_step UNW_OBJ (dwarf_step)
|
||||||
|
#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
|
||||||
|
|
||||||
extern int dwarf_init (void);
|
extern int dwarf_init (void);
|
||||||
#ifndef UNW_REMOTE_ONLY
|
#ifndef UNW_REMOTE_ONLY
|
||||||
|
@ -443,5 +451,6 @@ extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
||||||
const unw_proc_info_t *pi,
|
const unw_proc_info_t *pi,
|
||||||
unw_word_t *valp, void *arg);
|
unw_word_t *valp, void *arg);
|
||||||
extern int dwarf_step (struct dwarf_cursor *c);
|
extern int dwarf_step (struct dwarf_cursor *c);
|
||||||
|
extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
|
||||||
|
|
||||||
#endif /* dwarf_h */
|
#endif /* dwarf_h */
|
||||||
|
|
|
@ -225,6 +225,7 @@ unw_save_loc_t;
|
||||||
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
|
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
|
||||||
#define unw_get_proc_name UNW_OBJ(get_proc_name)
|
#define unw_get_proc_name UNW_OBJ(get_proc_name)
|
||||||
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
|
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
|
||||||
|
#define unw_set_cache_size UNW_OBJ(set_cache_size)
|
||||||
#define unw_regname UNW_ARCH_OBJ(regname)
|
#define unw_regname UNW_ARCH_OBJ(regname)
|
||||||
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
|
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
|
||||||
#define unw_strerror UNW_ARCH_OBJ(strerror)
|
#define unw_strerror UNW_ARCH_OBJ(strerror)
|
||||||
|
@ -234,6 +235,7 @@ extern void unw_destroy_addr_space (unw_addr_space_t);
|
||||||
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
|
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
|
||||||
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
|
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 int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
|
||||||
|
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
|
||||||
extern const char *unw_regname (unw_regnum_t);
|
extern const char *unw_regname (unw_regnum_t);
|
||||||
|
|
||||||
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
|
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
|
||||||
|
|
|
@ -109,7 +109,8 @@ libunwind_la_SOURCES_generic = \
|
||||||
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
|
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
|
||||||
mi/Gget_reg.c mi/Gset_reg.c \
|
mi/Gget_reg.c mi/Gset_reg.c \
|
||||||
mi/Gget_fpreg.c mi/Gset_fpreg.c \
|
mi/Gget_fpreg.c mi/Gset_fpreg.c \
|
||||||
mi/Gset_caching_policy.c
|
mi/Gset_caching_policy.c \
|
||||||
|
mi/Gset_cache_size.c
|
||||||
|
|
||||||
if SUPPORT_CXX_EXCEPTIONS
|
if SUPPORT_CXX_EXCEPTIONS
|
||||||
libunwind_la_SOURCES_local_unwind = \
|
libunwind_la_SOURCES_local_unwind = \
|
||||||
|
@ -137,7 +138,8 @@ libunwind_la_SOURCES_local_nounwind = \
|
||||||
mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
|
mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
|
||||||
mi/Lget_reg.c mi/Lset_reg.c \
|
mi/Lget_reg.c mi/Lset_reg.c \
|
||||||
mi/Lget_fpreg.c mi/Lset_fpreg.c \
|
mi/Lget_fpreg.c mi/Lset_fpreg.c \
|
||||||
mi/Lset_caching_policy.c
|
mi/Lset_caching_policy.c \
|
||||||
|
mi/Lset_cache_size.c
|
||||||
|
|
||||||
libunwind_la_SOURCES_local = \
|
libunwind_la_SOURCES_local = \
|
||||||
$(libunwind_la_SOURCES_local_nounwind) \
|
$(libunwind_la_SOURCES_local_nounwind) \
|
||||||
|
|
|
@ -23,13 +23,17 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "dwarf_i.h"
|
#include "dwarf_i.h"
|
||||||
#include "libunwind_i.h"
|
#include "libunwind_i.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
|
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
|
||||||
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
|
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
|
||||||
|
|
||||||
|
#define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size)
|
||||||
|
#define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1))
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
unw_word_t *valp, void *arg)
|
unw_word_t *valp, void *arg)
|
||||||
|
@ -508,15 +512,37 @@ parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
HIDDEN int
|
||||||
flush_rs_cache (struct dwarf_rs_cache *cache)
|
dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cache->lru_head = DWARF_UNW_CACHE_SIZE - 1;
|
if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
|
||||||
|
|| !cache->hash) {
|
||||||
|
cache->hash = cache->default_hash;
|
||||||
|
cache->buckets = cache->default_buckets;
|
||||||
|
cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
|
||||||
|
} else {
|
||||||
|
if (cache->hash && cache->hash != cache->default_hash)
|
||||||
|
munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size));
|
||||||
|
if (cache->buckets && cache->buckets != cache->default_buckets)
|
||||||
|
munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size));
|
||||||
|
GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
|
||||||
|
* sizeof (cache->hash[0]));
|
||||||
|
GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
|
||||||
|
* sizeof (cache->buckets[0]));
|
||||||
|
if (!cache->hash || !cache->buckets)
|
||||||
|
{
|
||||||
|
Debug (1, "Unable to allocate cache memory");
|
||||||
|
return -UNW_ENOMEM;
|
||||||
|
}
|
||||||
|
cache->prev_log_size = cache->log_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->lru_head = DWARF_UNW_CACHE_SIZE(cache->log_size) - 1;
|
||||||
cache->lru_tail = 0;
|
cache->lru_tail = 0;
|
||||||
|
|
||||||
for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
|
for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
cache->buckets[i].lru_chain = (i - 1);
|
cache->buckets[i].lru_chain = (i - 1);
|
||||||
|
@ -524,8 +550,10 @@ flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||||
cache->buckets[i].ip = 0;
|
cache->buckets[i].ip = 0;
|
||||||
cache->buckets[i].valid = 0;
|
cache->buckets[i].valid = 0;
|
||||||
}
|
}
|
||||||
for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i)
|
for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
|
||||||
cache->hash[i] = -1;
|
cache->hash[i] = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct dwarf_rs_cache *
|
static inline struct dwarf_rs_cache *
|
||||||
|
@ -543,9 +571,11 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
|
||||||
lock_acquire (&cache->lock, *saved_maskp);
|
lock_acquire (&cache->lock, *saved_maskp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
||||||
|
|| !cache->hash)
|
||||||
{
|
{
|
||||||
flush_rs_cache (cache);
|
if (dwarf_flush_rs_cache (cache) < 0)
|
||||||
|
return NULL;
|
||||||
cache->generation = as->cache_generation;
|
cache->generation = as->cache_generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,12 +594,12 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unw_hash_index_t CONST_ATTR
|
static inline unw_hash_index_t CONST_ATTR
|
||||||
hash (unw_word_t ip)
|
hash (unw_word_t ip, unsigned short log_size)
|
||||||
{
|
{
|
||||||
/* based on (sqrt(5)/2-1)*2^64 */
|
/* based on (sqrt(5)/2-1)*2^64 */
|
||||||
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
|
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
|
||||||
|
|
||||||
return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
|
return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline long
|
static inline long
|
||||||
|
@ -592,8 +622,8 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
|
||||||
if (cache_match (rs, ip))
|
if (cache_match (rs, ip))
|
||||||
return rs;
|
return rs;
|
||||||
|
|
||||||
index = cache->hash[hash (ip)];
|
index = cache->hash[hash (ip, cache->log_size)];
|
||||||
if (index >= DWARF_UNW_CACHE_SIZE)
|
if (index >= DWARF_UNW_CACHE_SIZE(cache->log_size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rs = cache->buckets + index;
|
rs = cache->buckets + index;
|
||||||
|
@ -606,7 +636,7 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
|
||||||
(rs - cache->buckets);
|
(rs - cache->buckets);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
if (rs->coll_chain >= DWARF_UNW_HASH_SIZE)
|
if (rs->coll_chain >= DWARF_UNW_HASH_SIZE(cache->log_size))
|
||||||
return NULL;
|
return NULL;
|
||||||
rs = cache->buckets + rs->coll_chain;
|
rs = cache->buckets + rs->coll_chain;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +660,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
||||||
/* remove the old rs from the hash table (if it's there): */
|
/* remove the old rs from the hash table (if it's there): */
|
||||||
if (rs->ip)
|
if (rs->ip)
|
||||||
{
|
{
|
||||||
index = hash (rs->ip);
|
index = hash (rs->ip, cache->log_size);
|
||||||
tmp = cache->buckets + cache->hash[index];
|
tmp = cache->buckets + cache->hash[index];
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -645,7 +675,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
prev = tmp;
|
prev = tmp;
|
||||||
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
|
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE(cache->log_size))
|
||||||
/* old rs wasn't in the hash-table */
|
/* old rs wasn't in the hash-table */
|
||||||
break;
|
break;
|
||||||
tmp = cache->buckets + tmp->coll_chain;
|
tmp = cache->buckets + tmp->coll_chain;
|
||||||
|
@ -653,7 +683,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enter new rs in the hash table */
|
/* enter new rs in the hash table */
|
||||||
index = hash (c->ip);
|
index = hash (c->ip, cache->log_size);
|
||||||
rs->coll_chain = cache->hash[index];
|
rs->coll_chain = cache->hash[index];
|
||||||
cache->hash[index] = rs - cache->buckets;
|
cache->hash[index] = rs - cache->buckets;
|
||||||
|
|
||||||
|
|
64
src/mi/Gset_cache_size.c
Normal file
64
src/mi/Gset_cache_size.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* libunwind - a platform-independent unwind library
|
||||||
|
Copyright (C) 2014
|
||||||
|
Contributed by Milian Wolff <address@hidden>
|
||||||
|
and Dave Watson <dade.watson@gmail.com>
|
||||||
|
|
||||||
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
|
||||||
|
#include "libunwind_i.h"
|
||||||
|
|
||||||
|
PROTECTED int
|
||||||
|
unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
|
||||||
|
{
|
||||||
|
size_t power = 1;
|
||||||
|
unsigned short log_size = 0;
|
||||||
|
|
||||||
|
if (!tdep_init_done)
|
||||||
|
tdep_init ();
|
||||||
|
|
||||||
|
if (flag != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Round up to next power of two, slowly but portably */
|
||||||
|
while(power < size)
|
||||||
|
{
|
||||||
|
power *= 2;
|
||||||
|
log_size++;
|
||||||
|
/* Largest size currently supported by rs_cache */
|
||||||
|
if (log_size >= 15)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_size == as->global_cache.log_size)
|
||||||
|
return 0; /* no change */
|
||||||
|
|
||||||
|
as->global_cache.log_size = log_size;
|
||||||
|
|
||||||
|
/* Ensure caches are empty (and initialized). */
|
||||||
|
unw_flush_cache (as, 0, 0);
|
||||||
|
#ifdef __ia64__
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
/* Synchronously purge cache, to ensure memory is allocated */
|
||||||
|
return dwarf_flush_rs_cache(&as->global_cache);
|
||||||
|
#endif
|
||||||
|
}
|
5
src/mi/Lset_cache_size.c
Normal file
5
src/mi/Lset_cache_size.c
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||||
|
#include "Gset_cache_size.c"
|
||||||
|
#endif
|
|
@ -103,6 +103,7 @@ check_local_unw_abi () {
|
||||||
match _UL${plat}_local_addr_space
|
match _UL${plat}_local_addr_space
|
||||||
match _UL${plat}_resume
|
match _UL${plat}_resume
|
||||||
match _UL${plat}_set_caching_policy
|
match _UL${plat}_set_caching_policy
|
||||||
|
match _UL${plat}_set_cache_size
|
||||||
match _UL${plat}_set_reg
|
match _UL${plat}_set_reg
|
||||||
match _UL${plat}_set_fpreg
|
match _UL${plat}_set_fpreg
|
||||||
match _UL${plat}_step
|
match _UL${plat}_step
|
||||||
|
@ -199,6 +200,7 @@ check_generic_unw_abi () {
|
||||||
match _U${plat}_regname
|
match _U${plat}_regname
|
||||||
match _U${plat}_resume
|
match _U${plat}_resume
|
||||||
match _U${plat}_set_caching_policy
|
match _U${plat}_set_caching_policy
|
||||||
|
match _U${plat}_set_cache_size
|
||||||
match _U${plat}_set_fpreg
|
match _U${plat}_set_fpreg
|
||||||
match _U${plat}_set_reg
|
match _U${plat}_set_reg
|
||||||
match _U${plat}_step
|
match _U${plat}_step
|
||||||
|
|
|
@ -46,6 +46,7 @@ f257 (void)
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
printf ("[%d] ip=%p\n", i, buffer[i]);
|
printf ("[%d] ip=%p\n", i, buffer[i]);
|
||||||
|
|
||||||
|
unw_set_cache_size (unw_local_addr_space, 1023, 0);
|
||||||
unw_flush_cache (unw_local_addr_space, 0, 0);
|
unw_flush_cache (unw_local_addr_space, 0, 0);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
|
|
@ -43,6 +43,7 @@ static void *funcs[] =
|
||||||
(void *) &unw_get_accessors,
|
(void *) &unw_get_accessors,
|
||||||
(void *) &unw_flush_cache,
|
(void *) &unw_flush_cache,
|
||||||
(void *) &unw_set_caching_policy,
|
(void *) &unw_set_caching_policy,
|
||||||
|
(void *) &unw_set_cache_size,
|
||||||
(void *) &unw_regname,
|
(void *) &unw_regname,
|
||||||
(void *) &unw_get_proc_info,
|
(void *) &unw_get_proc_info,
|
||||||
(void *) &unw_get_save_loc,
|
(void *) &unw_get_save_loc,
|
||||||
|
|
|
@ -61,6 +61,7 @@ static void *funcs[] =
|
||||||
(void *) &unw_get_accessors,
|
(void *) &unw_get_accessors,
|
||||||
(void *) &unw_flush_cache,
|
(void *) &unw_flush_cache,
|
||||||
(void *) &unw_set_caching_policy,
|
(void *) &unw_set_caching_policy,
|
||||||
|
(void *) &unw_set_cache_size,
|
||||||
(void *) &unw_regname,
|
(void *) &unw_regname,
|
||||||
(void *) &unw_get_proc_info,
|
(void *) &unw_get_proc_info,
|
||||||
(void *) &unw_get_save_loc,
|
(void *) &unw_get_save_loc,
|
||||||
|
|
Loading…
Reference in a new issue