41#include "Teuchos_VerboseObject.hpp" 
   44#ifdef HAVE_TEUCHOS_STACKTRACE 
   70#ifdef HAVE_TEUCHOS_LINK 
   75#ifdef HAVE_TEUCHOS_BFD 
   81typedef long long unsigned bfd_vma;
 
   94#ifdef HAVE_TEUCHOS_BFD 
   95  asymbol **symbol_table;     
 
   99  std::string function_name;
 
  106bool is_whitespace_char(
const char c)
 
  108  return c == 
' ' || c == 
'\t';
 
  115std::string remove_leading_whitespace(
const std::string &str)
 
  117  if (str.length() && is_whitespace_char(str[0])) {
 
  118    int first_nonwhitespace_index = 0;
 
  119    for (
int i = 0; i < static_cast<int>(str.length()); ++i) {
 
  120      if (!is_whitespace_char(str[i])) {
 
  121        first_nonwhitespace_index = i;
 
  125    return str.substr(first_nonwhitespace_index);
 
  132std::string read_line_from_file(std::string filename, 
unsigned int line_number)
 
  134  std::ifstream in(filename.c_str());
 
  138  if (line_number == 0) {
 
  139    return "Line number must be positive";
 
  143  while (n < line_number) {
 
  145      return "Line not found";
 
  158std::string demangle_function_name(std::string name)
 
  162  if (name.length() == 0) {
 
  167    d = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
 
  180#ifdef HAVE_TEUCHOS_BFD 
  190void process_section(bfd *abfd, asection *section, 
void *_data)
 
  192  line_data *data = (line_data*)_data;
 
  193  if (data->line_found) {
 
  197  if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) {
 
  201  bfd_vma section_vma = bfd_get_section_vma(abfd, section);
 
  202  if (data->addr < section_vma) {
 
  207  bfd_size_type section_size = bfd_section_size(abfd, section);
 
  208  if (data->addr >= section_vma + section_size) {
 
  214  bfd_vma offset = data->addr - section_vma - 1;
 
  218  const char *filename=NULL, *function_name=NULL;
 
  219  data->line_found = bfd_find_nearest_line(abfd, section, data->symbol_table,
 
  220    offset, &filename, &function_name, &data->line);
 
  222  if (filename == NULL)
 
  225    data->filename = filename;
 
  227  if (function_name == NULL)
 
  228    data->function_name = 
"";
 
  230    data->function_name = function_name;
 
  235int load_symbol_table(bfd *abfd, line_data *data)
 
  237  if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
 
  241  void **symbol_table_ptr = 
reinterpret_cast<void **
>(&data->symbol_table);
 
  243  unsigned int symbol_size;
 
  244  n_symbols = bfd_read_minisymbols(abfd, 
false, symbol_table_ptr, &symbol_size);
 
  245  if (n_symbols == 0) {
 
  248    if (data->symbol_table != NULL)
 
  249      free(data->symbol_table);
 
  251    n_symbols = bfd_read_minisymbols(abfd, 
true, symbol_table_ptr, &symbol_size);
 
  274std::string addr2str(std::string file_name, bfd_vma addr)
 
  276#ifdef HAVE_TEUCHOS_BFD 
  279  abfd = bfd_openr(file_name.c_str(), NULL);
 
  281    return "Cannot open the binary file '" + file_name + 
"'\n";
 
  282  if (bfd_check_format(abfd, bfd_archive))
 
  283    return "Cannot get addresses from the archive '" + file_name + 
"'\n";
 
  285  if (!bfd_check_format_matches(abfd, bfd_object, &matching))
 
  286    return "Unknown format of the binary file '" + file_name + 
"'\n";
 
  289  data.symbol_table = NULL;
 
  290  data.line_found = 
false;
 
  292  if (load_symbol_table(abfd, &data) == 1)
 
  293    return "Failed to load the symbol table from '" + file_name + 
"'\n";
 
  295  bfd_map_over_sections(abfd, process_section, &data);
 
  297  if (data.symbol_table != NULL) free(data.symbol_table);
 
  304  std::ostringstream s;
 
  307  if (!data.line_found) {
 
  309    s << 
"  File unknown, address: 0x" << (
long long unsigned int) addr;
 
  311    std::string name = demangle_function_name(data.function_name);
 
  312    if (data.filename.length() > 0) {
 
  314      s << 
"  File \"" << data.filename << 
"\", line " 
  315        << data.line << 
", in " << name;
 
  316      const std::string line_text = remove_leading_whitespace(
 
  317        read_line_from_file(data.filename, data.line));
 
  318      if (line_text != 
"") {
 
  319        s << 
"\n    " << line_text;
 
  324      s << 
"  File unknown, in " << name;
 
  334  std::string filename;
 
  335  bfd_vma addr_in_file;
 
  339#ifdef HAVE_TEUCHOS_LINK 
  346int shared_lib_callback(
struct dl_phdr_info *info,
 
  347  size_t size, 
void *_data)
 
  349  struct match_data *data = (
struct match_data *)_data;
 
  350  for (
int i=0; i < info->dlpi_phnum; i++) {
 
  351    if (info->dlpi_phdr[i].p_type == PT_LOAD) {
 
  352      ElfW(Addr) min_addr = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
 
  353      ElfW(Addr) max_addr = min_addr + info->dlpi_phdr[i].p_memsz;
 
  354      if ((data->addr >= min_addr) && (data->addr < max_addr)) {
 
  355        data->filename = info->dlpi_name;
 
  356        data->addr_in_file = data->addr - info->dlpi_addr;
 
  373class StacktraceAddresses {
 
  374  std::vector<bfd_vma> stacktrace_buffer;
 
  375  int impl_stacktrace_depth;
 
  377  StacktraceAddresses(
void *
const *_stacktrace_buffer, 
int _size, 
int _impl_stacktrace_depth)
 
  378    : impl_stacktrace_depth(_impl_stacktrace_depth)
 
  380      for (
int i=0; i < _size; i++)
 
  381        stacktrace_buffer.push_back((bfd_vma) _stacktrace_buffer[i]);
 
  383  bfd_vma get_address(
int i)
 const {
 
  384    return this->stacktrace_buffer[i];
 
  386  int get_size()
 const {
 
  387    return this->stacktrace_buffer.size();
 
  389  int get_impl_stacktrace_depth()
 const {
 
  390    return this->impl_stacktrace_depth;
 
  402std::string stacktrace2str(
const StacktraceAddresses &stacktrace_addresses)
 
  404  int stack_depth = stacktrace_addresses.get_size() - 1;
 
  406  std::string full_stacktrace_str(
"Traceback (most recent call last):\n");
 
  408#ifdef HAVE_TEUCHOS_BFD 
  412  const int stack_depth_start = stack_depth;
 
  413  const int stack_depth_end = stacktrace_addresses.get_impl_stacktrace_depth();
 
  414  for (
int i=stack_depth_start; i >= stack_depth_end; i--) {
 
  417    struct match_data match;
 
  418    match.addr = stacktrace_addresses.get_address(i);
 
  419#ifdef HAVE_TEUCHOS_BFD 
  420    if (dl_iterate_phdr(shared_lib_callback, &match) == 0)
 
  421      return "dl_iterate_phdr() didn't find a match\n";
 
  424    match.addr_in_file = match.addr;
 
  427    if (match.filename.length() > 0) {
 
  431      full_stacktrace_str += addr2str(match.filename, match.addr_in_file);
 
  435      full_stacktrace_str += addr2str(
"/proc/self/exe", match.addr_in_file);
 
  439  return full_stacktrace_str;
 
  443void loc_segfault_callback_print_stack(
int sig_num)
 
  447  *out << 
"\nSegfault caught. Printing stacktrace:\n\n";
 
  449  *out << 
"\nDone. Exiting the program.\n";
 
  451  signal(SIGABRT, SIG_DFL);
 
  456void loc_abort_callback_print_stack(
int sig_num)
 
  460  *out << 
"\nAbort caught. Printing stacktrace:\n\n";
 
  466RCP<StacktraceAddresses> get_stacktrace_addresses(
int impl_stacktrace_depth)
 
  468  const int STACKTRACE_ARRAY_SIZE = 100; 
 
  469  void *stacktrace_array[STACKTRACE_ARRAY_SIZE];
 
  470  const size_t stacktrace_size = backtrace(stacktrace_array,
 
  471    STACKTRACE_ARRAY_SIZE);
 
  472  return rcp(
new StacktraceAddresses(stacktrace_array, stacktrace_size,
 
  473      impl_stacktrace_depth+1));
 
  477RCP<StacktraceAddresses> last_stacktrace;
 
  487  const int impl_stacktrace_depth=1;
 
  488  last_stacktrace = get_stacktrace_addresses(impl_stacktrace_depth);
 
  494  if (last_stacktrace == null) {
 
  498    return stacktrace2str(*last_stacktrace);
 
  505  RCP<StacktraceAddresses> addresses =
 
  506    get_stacktrace_addresses(impl_stacktrace_depth+1);
 
  507  return stacktrace2str(*addresses);
 
  515  const int impl_stacktrace_depth=1;
 
  522  signal(SIGSEGV, loc_segfault_callback_print_stack);
 
  523  signal(SIGABRT, loc_abort_callback_print_stack);
 
Reference-counted pointer class and non-member templated function implementations.
 
Functions for returning stacktrace info (GCC only initially).
 
Smart reference counting pointer class for automatic garbage collection.
 
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.