Compare commits

...

2 Commits

Author SHA1 Message Date
David Faust 822a139e7d dwarf: add wiki link for DWARF GNU_annotation extensions
include/

	* dwarf2.def (DW_TAG_GNU_annotation): Add link to wiki page
	documenting the extension.
	(DW_AT_GNU_annotation): Likewise.
2025-10-16 11:08:30 -07:00
Jonathan Wakely 08b2c542e4
libstdc++: Improve ostream output for std::stacktrace
With this change stacktrace entries always output the frame address, and
source file information no longer results in " at :0", e.g.

  16#  myfunc(int) at /tmp/bt.cc:48 [0x4008b7]
  17#  main at /tmp/bt.cc:61 [0x40091a]
  18#  __libc_start_call_main [0x7efc3d6d3574]
  19#  __libc_start_main@GLIBC_2.2.5 [0x7efc3d6d3627]
  20#  _start [0x400684]

This replaces the previous output:

  16# myfunc(int) at /tmp/bt.cc:48
  17# main at /tmp/bt.cc:61
  18# __libc_start_call_main at :0
  19# __libc_start_main@GLIBC_2.2.5 at :0
  20# _start at :0

A change that is not visible in the examples above is that for a
non-empty stacktrace_entry, we now print "<unknown>" for the function
name if description() returns an empty string.  For an empty (e.g.
default constructed) stacktrace_entry the entire string representation
is now "<unknown>" instead of an empty string.

Instead of printing "<unknown>" for the function name, we could set that
string in the stacktrace_entry::_Info object, so that description()
returns "<unknown>" and then operator<< wouldn't need to handle an empty
description() string. However, returning an empty string from that
function seems simpler for users to detect, rather than having to parse
"<unknown>".

We could also choose a different string for an empty stacktrace_entry,
maybe "<none>" or "<invalid>", but "<unknown>" seems good.

libstdc++-v3/ChangeLog:

	* include/std/stacktrace
	(operator<<(ostream&, const stacktrace_entry&)): Improve output
	when description() or source_file() returns an empty string,
	or the stacktrace_entry is invalid. Append frame address to
	output.
	(operator<<(ostream&, const basic_stacktrace<A>&)): Use the
	size_type of the correct specialization.

Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Reviewed-by: Nathan Myers <nmyers@redhat.com>
2025-10-16 14:59:42 +01:00
2 changed files with 28 additions and 4 deletions

View File

@ -175,6 +175,8 @@ DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108)
DW_TAG (DW_TAG_GNU_call_site, 0x4109)
DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a)
/* GNU annotation extension used by btf_decl_tag and btf_type_tag.
See https://gcc.gnu.org/wiki/GNUAnnotationsDwarf . */
DW_TAG (DW_TAG_GNU_annotation, 0x6001)
/* Extensions for UPC. See: http://dwarfstd.org/doc/DWARF4.pdf. */
@ -459,6 +461,8 @@ DW_AT (DW_AT_GNU_pubtypes, 0x2135)
DW_AT (DW_AT_GNU_discriminator, 0x2136)
DW_AT (DW_AT_GNU_locviews, 0x2137)
DW_AT (DW_AT_GNU_entry_view, 0x2138)
/* GNU annotation extension used by btf_decl_tag and btf_type_tag.
See https://gcc.gnu.org/wiki/GNUAnnotationsDwarf . */
DW_AT (DW_AT_GNU_annotation, 0x2139)
/* VMS extensions. */
DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201)

View File

@ -683,13 +683,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline ostream&
operator<<(ostream& __os, const stacktrace_entry& __f)
{
if (!__f) [[unlikely]]
return __os << "<unknown>";
string __desc, __file;
int __line;
if (__f._M_get_info(&__desc, &__file, &__line))
if (__f._M_get_info(&__desc, &__file, &__line)) [[likely]]
{
__os.width(4);
__os << __desc << " at " << __file << ':' << __line;
__os << ' ';
if (__desc.empty()) [[unlikely]]
__os << "<unknown>";
else
__os << __desc;
if (!__file.empty()) [[likely]]
__os << " at " << __file << ':' << __line;
}
struct _Flag_guard // Set and restore hex format
{
_Flag_guard(ios& __s) : _M_ios(__s) { }
~_Flag_guard() { _M_ios.setf(_M_f); }
ios& _M_ios;
ios::fmtflags _M_f = _M_ios.setf(ios::hex, ios::basefield);
};
_Flag_guard __g(__os);
__os << " [0x" << __f.native_handle() << ']';
return __os;
}
@ -697,7 +716,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline ostream&
operator<<(ostream& __os, const basic_stacktrace<_Allocator>& __st)
{
for (stacktrace::size_type __i = 0; __i < __st.size(); ++__i)
using size_type = typename basic_stacktrace<_Allocator>::size_type;
for (size_type __i = 0, __size = __st.size(); __i < __size; ++__i)
{
__os.width(4);
__os << __i << "# " << __st[__i] << '\n';