32 #include "Teuchos_VerboseObject.hpp" 
   35 #ifdef HAVE_TEUCHOS_STACKTRACE 
   61 #ifdef HAVE_TEUCHOS_LINK 
   66 #ifdef HAVE_TEUCHOS_BFD 
   72 typedef long long unsigned bfd_vma;
 
   85 #ifdef HAVE_TEUCHOS_BFD 
   86   asymbol **symbol_table;     
 
   90   std::string function_name;
 
   97 bool is_whitespace_char(
const char c)
 
   99   return c == 
' ' || c == 
'\t';
 
  106 std::string remove_leading_whitespace(
const std::string &str)
 
  108   if (str.length() && is_whitespace_char(str[0])) {
 
  109     int first_nonwhitespace_index = 0;
 
  110     for (
int i = 0; i < static_cast<int>(str.length()); ++i) {
 
  111       if (!is_whitespace_char(str[i])) {
 
  112         first_nonwhitespace_index = i;
 
  116     return str.substr(first_nonwhitespace_index);
 
  123 std::string read_line_from_file(std::string filename, 
unsigned int line_number)
 
  125   std::ifstream in(filename.c_str());
 
  129   if (line_number == 0) {
 
  130     return "Line number must be positive";
 
  134   while (n < line_number) {
 
  136       return "Line not found";
 
  149 std::string demangle_function_name(std::string name)
 
  153   if (name.length() == 0) {
 
  158     d = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
 
  171 #ifdef HAVE_TEUCHOS_BFD 
  181 void process_section(bfd *abfd, asection *section, 
void *_data)
 
  183   line_data *data = (line_data*)_data;
 
  184   if (data->line_found) {
 
  188   if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) {
 
  192   bfd_vma section_vma = bfd_get_section_vma(abfd, section);
 
  193   if (data->addr < section_vma) {
 
  198   bfd_size_type section_size = bfd_section_size(abfd, section);
 
  199   if (data->addr >= section_vma + section_size) {
 
  205   bfd_vma offset = data->addr - section_vma - 1;
 
  209   const char *filename=NULL, *function_name=NULL;
 
  210   data->line_found = bfd_find_nearest_line(abfd, section, data->symbol_table,
 
  211     offset, &filename, &function_name, &data->line);
 
  213   if (filename == NULL)
 
  216     data->filename = filename;
 
  218   if (function_name == NULL)
 
  219     data->function_name = 
"";
 
  221     data->function_name = function_name;
 
  226 int load_symbol_table(bfd *abfd, line_data *data)
 
  228   if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
 
  232   void **symbol_table_ptr = 
reinterpret_cast<void **
>(&data->symbol_table);
 
  234   unsigned int symbol_size;
 
  235   n_symbols = bfd_read_minisymbols(abfd, 
false, symbol_table_ptr, &symbol_size);
 
  236   if (n_symbols == 0) {
 
  239     if (data->symbol_table != NULL)
 
  240       free(data->symbol_table);
 
  242     n_symbols = bfd_read_minisymbols(abfd, 
true, symbol_table_ptr, &symbol_size);
 
  254 #endif // HAVE_TEUCHOS_BFD 
  265 std::string addr2str(std::string file_name, bfd_vma addr)
 
  267 #ifdef HAVE_TEUCHOS_BFD 
  270   abfd = bfd_openr(file_name.c_str(), NULL);
 
  272     return "Cannot open the binary file '" + file_name + 
"'\n";
 
  273   if (bfd_check_format(abfd, bfd_archive))
 
  274     return "Cannot get addresses from the archive '" + file_name + 
"'\n";
 
  276   if (!bfd_check_format_matches(abfd, bfd_object, &matching))
 
  277     return "Unknown format of the binary file '" + file_name + 
"'\n";
 
  280   data.symbol_table = NULL;
 
  281   data.line_found = 
false;
 
  283   if (load_symbol_table(abfd, &data) == 1)
 
  284     return "Failed to load the symbol table from '" + file_name + 
"'\n";
 
  286   bfd_map_over_sections(abfd, process_section, &data);
 
  288   if (data.symbol_table != NULL) free(data.symbol_table);
 
  295   std::ostringstream s;
 
  298   if (!data.line_found) {
 
  300     s << 
"  File unknown, address: 0x" << (
long long unsigned int) addr;
 
  302     std::string name = demangle_function_name(data.function_name);
 
  303     if (data.filename.length() > 0) {
 
  305       s << 
"  File \"" << data.filename << 
"\", line " 
  306         << data.line << 
", in " << name;
 
  307       const std::string line_text = remove_leading_whitespace(
 
  308         read_line_from_file(data.filename, data.line));
 
  309       if (line_text != 
"") {
 
  310         s << 
"\n    " << line_text;
 
  315       s << 
"  File unknown, in " << name;
 
  325   std::string filename;
 
  326   bfd_vma addr_in_file;
 
  330 #ifdef HAVE_TEUCHOS_LINK 
  337 int shared_lib_callback(
struct dl_phdr_info *info,
 
  338   size_t size, 
void *_data)
 
  340   struct match_data *data = (
struct match_data *)_data;
 
  341   for (
int i=0; i < info->dlpi_phnum; i++) {
 
  342     if (info->dlpi_phdr[i].p_type == PT_LOAD) {
 
  343       ElfW(Addr) min_addr = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
 
  344       ElfW(Addr) max_addr = min_addr + info->dlpi_phdr[i].p_memsz;
 
  345       if ((data->addr >= min_addr) && (data->addr < max_addr)) {
 
  346         data->filename = info->dlpi_name;
 
  347         data->addr_in_file = data->addr - info->dlpi_addr;
 
  358 #endif // HAVE_TEUCHOS_LINK 
  364 class StacktraceAddresses {
 
  365   std::vector<bfd_vma> stacktrace_buffer;
 
  366   int impl_stacktrace_depth;
 
  368   StacktraceAddresses(
void *
const *_stacktrace_buffer, 
int _size, 
int _impl_stacktrace_depth)
 
  369     : impl_stacktrace_depth(_impl_stacktrace_depth)
 
  371       for (
int i=0; i < _size; i++)
 
  372         stacktrace_buffer.push_back((bfd_vma) _stacktrace_buffer[i]);
 
  374   bfd_vma get_address(
int i)
 const {
 
  375     return this->stacktrace_buffer[i];
 
  377   int get_size()
 const {
 
  378     return this->stacktrace_buffer.size();
 
  380   int get_impl_stacktrace_depth()
 const {
 
  381     return this->impl_stacktrace_depth;
 
  393 std::string stacktrace2str(
const StacktraceAddresses &stacktrace_addresses)
 
  395   int stack_depth = stacktrace_addresses.get_size() - 1;
 
  397   std::string full_stacktrace_str(
"Traceback (most recent call last):\n");
 
  399 #ifdef HAVE_TEUCHOS_BFD 
  403   const int stack_depth_start = stack_depth;
 
  404   const int stack_depth_end = stacktrace_addresses.get_impl_stacktrace_depth();
 
  405   for (
int i=stack_depth_start; i >= stack_depth_end; i--) {
 
  408     struct match_data match;
 
  409     match.addr = stacktrace_addresses.get_address(i);
 
  410 #ifdef HAVE_TEUCHOS_BFD 
  411     if (dl_iterate_phdr(shared_lib_callback, &match) == 0)
 
  412       return "dl_iterate_phdr() didn't find a match\n";
 
  415     match.addr_in_file = match.addr;
 
  418     if (match.filename.length() > 0) {
 
  422       full_stacktrace_str += addr2str(match.filename, match.addr_in_file);
 
  426       full_stacktrace_str += addr2str(
"/proc/self/exe", match.addr_in_file);
 
  430   return full_stacktrace_str;
 
  434 void loc_segfault_callback_print_stack(
int sig_num)
 
  438   *out << 
"\nSegfault caught. Printing stacktrace:\n\n";
 
  439   Teuchos::show_stacktrace();
 
  440   *out << 
"\nDone. Exiting the program.\n";
 
  442   signal(SIGABRT, SIG_DFL);
 
  447 void loc_abort_callback_print_stack(
int sig_num)
 
  451   *out << 
"\nAbort caught. Printing stacktrace:\n\n";
 
  452   Teuchos::show_stacktrace();
 
  457 RCP<StacktraceAddresses> get_stacktrace_addresses(
int impl_stacktrace_depth)
 
  459   const int STACKTRACE_ARRAY_SIZE = 100; 
 
  460   void *stacktrace_array[STACKTRACE_ARRAY_SIZE];
 
  461   const size_t stacktrace_size = backtrace(stacktrace_array,
 
  462     STACKTRACE_ARRAY_SIZE);
 
  463   return rcp(
new StacktraceAddresses(stacktrace_array, stacktrace_size,
 
  464       impl_stacktrace_depth+1));
 
  468 RCP<StacktraceAddresses> last_stacktrace;
 
  476 void Teuchos::store_stacktrace()
 
  478   const int impl_stacktrace_depth=1;
 
  479   last_stacktrace = get_stacktrace_addresses(impl_stacktrace_depth);
 
  483 std::string Teuchos::get_stored_stacktrace()
 
  485   if (last_stacktrace == null) {
 
  489     return stacktrace2str(*last_stacktrace);
 
  494 std::string Teuchos::get_stacktrace(
int impl_stacktrace_depth)
 
  496   RCP<StacktraceAddresses> addresses =
 
  497     get_stacktrace_addresses(impl_stacktrace_depth+1);
 
  498   return stacktrace2str(*addresses);
 
  502 void Teuchos::show_stacktrace()
 
  506   const int impl_stacktrace_depth=1;
 
  507   *out << Teuchos::get_stacktrace(impl_stacktrace_depth);
 
  511 void Teuchos::print_stack_on_segfault()
 
  513   signal(SIGSEGV, loc_segfault_callback_print_stack);
 
  514   signal(SIGABRT, loc_abort_callback_print_stack);
 
  518 #endif // HAVE_TEUCHOS_STACKTRACE 
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
 
Functions for returning stacktrace info (GCC only initially). 
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated. 
 
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object. 
 
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator. 
 
Smart reference counting pointer class for automatic garbage collection. 
 
Reference-counted pointer class and non-member templated function implementations.