This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: move dwarfstrings into libdw


On Tue, 2012-07-17 at 15:03 +0200, Mark Wielaard wrote:
> If this interface looks OK, the next step would be to add an extra test
> to exhaustively use them all (as self tests) to make sure the tables are
> complete (at least for the toolchain used to produce DWARF for our own
> code) generate all tables through known-dwarf.h macros (some might have
> big gaps in them, so we probably shouldn't generate arrays for all of
> them).

I hacked some more, added some test, found some issues/missing values
and came up with the attached. That is the patch relative to master (I
rebased mjw/dwarfstrings on top of master). The individual commits that
resulted in this are on the branch (commit messages also attached).

I would like to merge this to master now.
Comments, objections, suggestions for improvements?

Thanks,

Mark
diff --git a/ChangeLog b/ChangeLog
index 5842492..3be157c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2012-07-24  Mark Wielaard  <mjw@redhat.com>
 
+	* configure.ac: Add AX_CXX_COMPILE_STDCXX_0X check.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
 	* TODO: Add note on shdrs after elf_cntl (ELF_C_FDREAD).
 
 2012-06-22  Mark Wielaard  <mjw@redhat.com>
diff --git a/config/ChangeLog b/config/ChangeLog
index d039966..c8747f0 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* known-dwarf.awk: "Generated by" header had wrong file names,
+	mention config/known-dwarf.awk and libdw/dwarf.h contents.
+
 2012-06-22  Mark Wielaard  <mjw@redhat.com>
 
 	* config/elfutils.spec.in: Update for 0.154.
diff --git a/config/known-dwarf.awk b/config/known-dwarf.awk
index faef704..52ec5b6 100644
--- a/config/known-dwarf.awk
+++ b/config/known-dwarf.awk
@@ -41,7 +41,7 @@ $1 ~ /DW([_A-Z]+)_([^ ]+)/ {
 }
 
 END {
-  print "/* Generated by config/dwarf-known.awk from libdw.h contents.  */";
+  print "/* Generated by config/known-dwarf.awk from libdw/dwarf.h contents.  */";
   n = asorti(DW, sets);
   for (i = 1; i <= n; ++i) {
     set = sets[i];
diff --git a/configure.ac b/configure.ac
index 31ab21c..088dde3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,11 @@ AC_PROG_RANLIB
 AC_PROG_YACC
 AM_PROG_LEX
 
+# Check whether we can use g++ with -std=c++0x for the test.
+AC_PROG_CXX
+AX_CXX_COMPILE_STDCXX_0X
+AM_CONDITIONAL(HAVE_STDCXX_0X, test "x$ax_cv_cxx_compile_cxx0x_cxx" == "xyes")
+
 AC_CACHE_CHECK([for gcc with C99 support], ac_cv_c99, [dnl
 old_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS -std=gnu99"
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 5a07c46..302f5f6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,97 @@
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarfstrings.c (dwarf_tag_string): Use known-dwarf.h
+	ALL_KNOWN_DW_TAG macro to define switch case statement to return
+	strings.
+	(dwarf_attr_string): Use known-dwarf.h ALL_KNOWN_DW_AT macro to
+	define switch case statement to return strings.
+	(dwarf_form_string): Use known-dwarf.h ALL_KNOWN_DW_FORM macro to
+	define switch case statement to return strings.
+	(dwarf_inline_string): Use known-dwarf.h ALL_KNOWN_DW_INL macro
+	to define known array.
+	(dwarf_access_string): Use known-dwarf.h ALL_KNOWN_DW_ACCESS macro
+	to define known array.
+	(dwarf_visibility_string): Use known-dwarf.h ALL_KNOWN_DW_VIS
+	macro to define known array.
+	(dwarf_virtuality_string): Use known-dwarf.h ALL_KNOWN_DW_VIRTUALITY
+	macro to define known array.
+	(dwarf_identifier_case_string): Use known-dwarf.h ALL_KNOWN_DW_ID
+	macro to define known array.
+	(dwarf_calling_convention_string): Use known-dwarf.h ALL_KNOWN_DW_CC
+	macro to define known array.
+	(dwarf_ordering_string): Use known-dwarf.h ALL_KNOWN_DW_ORD
+	macro to define known array.
+	(dwarf_discr_list_string): Use known-dwarf.h ALL_KNOWN_DW_DSC
+	macro to define known array.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_ATE_UTF.
+	* dwarfstrings.c (dwarf_encoding_string): Use known-dwarf.h
+	ALL_KNOWN_DW_ATE macro to define known array.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw/Makefile.am (EXTRA_DIST): Add known-dwarf.h.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarfstrings.c (dwarf_lang_string): Return just the DW_LANG name.
+	(dwarf_lang_description): New function, returns the language
+	description that dwarf_lang_string used to return.
+	* libdw.h (dwarf_lang_string): Add new interface description.
+	(dwarf_lang_description): New function prototype with old description
+	of dwarf_lang_string.
+	* libdw.map (ELFUTILS_0.154): Add dwarf_lang_description.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarfstrings.c (dwarf_lang_string): Add DW_LANG_Go.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add correct spelling of DW_LANG_ObjC. Keep old
+	DW_LANG_Objc as alias.
+	* dwarf_aggregate_size.c (array_size): Use correct spelling of
+	DW_LANG_ObjC.
+	* dwarfstrings.c (dwarf_lang_string): Likewise.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_OP_GNU_parameter_ref.
+
+2012-07-17  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarfstrings.c.
+	* dwarfstrings.c: New file from dwarf branch.
+	* libdw.h: Declare dwarf_tag_string, dwarf_attr_string,
+	dwarf_lang_string, dwarf_inline_string, dwarf_encoding_string,
+	dwarf_access_string, dwarf_visibility_string,
+	dwarf_virtuality_string, dwarf_identifier_case_string,
+	dwarf_calling_convention_string, dwarf_ordering_string,
+	dwarf_discr_list_string, dwarf_locexpr_opcode_string,
+	dwarf_line_standard_opcode_string and
+	dwarf_line_extended_opcode_string.
+	* libdw.map (ELFUTILS_0.154): New symbol version directive for
+	new dwarfstrings.c functions.
+	* readelf.c (dwarf_tag_name): Renamed from dwarf_tag_string.
+	Uses new dwarf_tag_string or adds unknown_tag_%#x.
+	(dwarf_attr_name): Likewise.
+	(dwarf_form_name): Likewise.
+	(dwarf_lang_name): Likewise.
+	(dwarf_inline_name): Likewise.
+	(dwarf_encoding_name): Likewise.
+	(dwarf_access_name): Likewise.
+	(dwarf_visibility_name): Likewise.
+	(dwarf_virtuality_name): Likewise.
+	(dwarf_identifier_case_name): Likewise.
+	(dwarf_calling_convention_name): Likewise.
+	(dwarf_ordering_name): Likewise.
+	(dwarf_discr_list_name): Likewise.
+	(print_ops): Remove known[]. Use dwarf_locexpr_opcode_string.
+	(attr_callback): Call new dwarf_foobar_name instead of old
+	dwarf_foobar_string functions.
+
 2012-06-27  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf.h: Add DW_MACRO_GNU .debug_macro type encodings.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index e1fcef0..615602f 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 2002-2010 Red Hat, Inc.
+## Copyright (C) 2002-2012 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -87,7 +87,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
 		  dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \
 		  dwarf_cfi_addrframe.c \
 		  dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
-		  dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c
+		  dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c \
+		  dwarfstrings.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
@@ -133,6 +134,6 @@ libdw_a_LIBADD = $(addprefix ../libdwfl/,$(shell $(AR) t ../libdwfl/libdwfl.a))
 noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \
 		 dwarf_sig8_hash.h cfi.h encoded-value.h
 
-EXTRA_DIST = libdw.map
+EXTRA_DIST = libdw.map known-dwarf.h
 
 MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION)
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 78a553a..eb0408d 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -472,6 +472,7 @@ enum
     DW_OP_GNU_deref_type = 0xf6,
     DW_OP_GNU_convert = 0xf7,
     DW_OP_GNU_reinterpret = 0xf9,
+    DW_OP_GNU_parameter_ref = 0xfa,
 
     DW_OP_lo_user = 0xe0,	/* Implementation-defined range start.  */
     DW_OP_hi_user = 0xff	/* Implementation-defined range end.  */
@@ -497,6 +498,7 @@ enum
     DW_ATE_signed_fixed = 0xd,
     DW_ATE_unsigned_fixed = 0xe,
     DW_ATE_decimal_float = 0xf,
+    DW_ATE_UTF = 0x10,
 
     DW_ATE_lo_user = 0x80,
     DW_ATE_hi_user = 0xff
@@ -571,7 +573,8 @@ enum
     DW_LANG_Ada95 = 0x000d,	     /* ISO Ada:1995 */
     DW_LANG_Fortran95 = 0x000e,	     /* ISO Fortran 95 */
     DW_LANG_PL1 = 0x000f,	     /* ISO PL/1:1976 */
-    DW_LANG_Objc = 0x0010,	     /* Objective-C */
+    DW_LANG_ObjC = 0x0010,	     /* Objective-C */
+    DW_LANG_Objc = 0x0010,	     /* Objective-C - typo in constant name */
     DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */
     DW_LANG_UPC = 0x0012,	     /* Unified Parallel C */
     DW_LANG_D = 0x0013,		     /* D */
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
index 6fd1742..07c53a2 100644
--- a/libdw/dwarf_aggregate_size.c
+++ b/libdw/dwarf_aggregate_size.c
@@ -99,7 +99,7 @@ array_size (Dwarf_Die *die, Dwarf_Word *size,
 		    case DW_LANG_C89:
 		    case DW_LANG_C99:
 		    case DW_LANG_C_plus_plus:
-		    case DW_LANG_Objc:
+		    case DW_LANG_ObjC:
 		    case DW_LANG_ObjC_plus_plus:
 		    case DW_LANG_Java:
 		    case DW_LANG_D:
diff --git a/libdw/dwarfstrings.c b/libdw/dwarfstrings.c
new file mode 100644
index 0000000..9ed0630
--- /dev/null
+++ b/libdw/dwarfstrings.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 1999-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "known-dwarf.h"
+#include "dwarf.h"
+
+const char *
+dwarf_tag_string (unsigned int tag)
+{
+  switch (tag)
+    {
+#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+      ALL_KNOWN_DW_TAG
+#undef ONE_KNOWN_DW_TAG
+    default:
+      return NULL;
+    }
+}
+
+
+const char *
+dwarf_attr_string (unsigned int attrnum)
+{
+  switch (attrnum)
+    {
+#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+      ALL_KNOWN_DW_AT
+#undef ONE_KNOWN_DW_AT
+    default:
+      return NULL;
+    }
+}
+
+
+const char *
+dwarf_form_string (unsigned int form)
+{
+  switch (form)
+    {
+#define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
+      ALL_KNOWN_DW_FORM
+#undef ONE_KNOWN_DW_FORM
+    default:
+      return NULL;
+    }
+}
+
+
+const char *
+dwarf_lang_string (unsigned int lang)
+{
+  static const char *const known[] =
+    {
+      [DW_LANG_C89] = "C89",
+      [DW_LANG_C] = "C",
+      [DW_LANG_Ada83] = "Ada83",
+      [DW_LANG_C_plus_plus] = "C_plus_plus",
+      [DW_LANG_Cobol74] = "Cobol74",
+      [DW_LANG_Cobol85] = "Cobol85",
+      [DW_LANG_Fortran77] = "Fortran77",
+      [DW_LANG_Fortran90] = "Fortran90",
+      [DW_LANG_Pascal83] = "Pascal83",
+      [DW_LANG_Modula2] = "Modula2",
+      [DW_LANG_Java] = "Java",
+      [DW_LANG_C99] = "C99",
+      [DW_LANG_Ada95] = "Ada95",
+      [DW_LANG_Fortran95] = "Fortran95",
+      [DW_LANG_PL1] = "PL1",
+      [DW_LANG_ObjC] = "ObjC",
+      [DW_LANG_ObjC_plus_plus] = "ObjC_plus_plus",
+      [DW_LANG_UPC] = "UPC",
+      [DW_LANG_D] = "D",
+      [DW_LANG_Go] = "Go",
+    };
+
+  if (likely (lang < sizeof (known) / sizeof (known[0])))
+    return known[lang];
+  else if (lang == DW_LANG_Mips_Assembler)
+    return "Mips_Assembler";
+
+  return NULL;
+}
+
+const char *
+dwarf_lang_description (unsigned int lang)
+{
+  static const char *const known[] =
+    {
+      [DW_LANG_C89] = "ISO C89",
+      [DW_LANG_C] = "C",
+      [DW_LANG_Ada83] = "Ada83",
+      [DW_LANG_C_plus_plus] = "C++",
+      [DW_LANG_Cobol74] = "Cobol74",
+      [DW_LANG_Cobol85] = "Cobol85",
+      [DW_LANG_Fortran77] = "Fortran77",
+      [DW_LANG_Fortran90] = "Fortran90",
+      [DW_LANG_Pascal83] = "Pascal83",
+      [DW_LANG_Modula2] = "Modula2",
+      [DW_LANG_Java] = "Java",
+      [DW_LANG_C99] = "ISO C99",
+      [DW_LANG_Ada95] = "Ada95",
+      [DW_LANG_Fortran95] = "Fortran95",
+      [DW_LANG_PL1] = "PL1",
+      [DW_LANG_ObjC] = "Objective C",
+      [DW_LANG_ObjC_plus_plus] = "Objective C++",
+      [DW_LANG_UPC] = "UPC",
+      [DW_LANG_D] = "D",
+      [DW_LANG_Go] = "Go",
+    };
+
+  if (likely (lang < sizeof (known) / sizeof (known[0])))
+    return known[lang];
+  else if (lang == DW_LANG_Mips_Assembler)
+    /* This language tag is used for assembler in general.  */
+    return "Assembler";
+
+  return NULL;
+}
+
+
+const char *
+dwarf_inline_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_INL
+#undef ONE_KNOWN_DW_INL
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_encoding_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_ATE
+#undef ONE_KNOWN_DW_ATE
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_access_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_ACCESS
+#undef ONE_KNOWN_DW_ACCESS
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_visibility_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_VIS
+#undef ONE_KNOWN_DW_VIS
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_virtuality_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_VIRTUALITY
+#undef ONE_KNOWN_DW_VIRTUALITY
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_identifier_case_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_ID
+#undef ONE_KNOWN_DW_ID
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_calling_convention_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_CC
+#undef ONE_KNOWN_DW_CC
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_ordering_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_ORD
+#undef ONE_KNOWN_DW_ORD
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_discr_list_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_DSC
+#undef ONE_KNOWN_DW_DSC
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+const char *
+dwarf_locexpr_opcode_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+      /* Normally we can't affort building huge table of 64K entries,
+	 most of them zero, just because there are a couple defined
+	 values at the far end.  In case of opcodes, it's OK.  */
+#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP(NAME, CODE)
+#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_OP
+#undef ONE_KNOWN_DW_OP
+#undef ONE_KNOWN_DW_OP_DESC
+    };
+
+  const char *ret = NULL;
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    ret = known[code];
+
+  return ret;
+}
+
+const char *
+dwarf_line_standard_opcode_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_LNS(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_LNS
+#undef ONE_KNOWN_DW_LNS
+    };
+
+  const char *ret = NULL;
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    ret = known[code];
+
+  return ret;
+}
+
+const char *
+dwarf_line_extended_opcode_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define ONE_KNOWN_DW_LNE(NAME, CODE) [CODE] = #NAME,
+      ALL_KNOWN_DW_LNE
+#undef ONE_KNOWN_DW_LNE
+    };
+
+  const char *ret = NULL;
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    ret = known[code];
+
+  return ret;
+}
diff --git a/libdw/libdw.h b/libdw/libdw.h
index f5fc4e2..d59b831 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -1,5 +1,5 @@
 /* Interfaces for libdw.
-   Copyright (C) 2002-2010 Red Hat, Inc.
+   Copyright (C) 2002-2012 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -830,6 +830,88 @@ extern const char *dwarf_errmsg (int err);
 extern Dwarf_OOM dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler);
 
 
+/* Returns the tag name, without the DW_TAG_ prefix, if known.
+   Returns NULL if the given tag code is unknown.  */
+const char *dwarf_tag_string (unsigned int code);
+
+/* Returns the attribute name, without the DW_AT_ prefix, if known.
+   Returns NULL if the given attribute code is unknown.  */
+const char *dwarf_attr_string (unsigned int code);
+
+/* Returns the form name, without the DW_FORM_ prefix, if known.
+   Returns NULL if the given form code is unknown.  */
+const char *dwarf_form_string (unsigned int code);
+
+/* Returns the language name, without the DW_LANG_ prefix, if known.
+   Returns NULL if the given language code is unknown.  */
+const char *dwarf_lang_string (unsigned int code);
+
+/* Returns the language description used with the DW_AT_language
+   attribute, if known.  Returns NULL if the given DW_LANG code is
+   unknown.  */
+const char *dwarf_lang_description (unsigned int code);
+
+/* Returns the inline name, without the DW_INL_ prefix, as used with
+   the DW_AT_inline attribute, if known.  Returns NULL if the given
+   DW_LANG code is unknown.  */
+const char *dwarf_inline_string (unsigned int code);
+
+/* Returns the encoding name, without the DW_ATE_ prefix, as used with
+   the DW_AT_encoding attribute, if known.  Returns NULL if the given
+   DW_ATE code is unknown.  */
+const char *dwarf_encoding_string (unsigned int code);
+
+/* Returns the access name, without the DW_ACCESS_ prefix, as used with
+   the DW_AT_accessibility attribute, if known.  Returns NULL if the given
+   DW_ACCESS code is unknown.  */
+const char *dwarf_access_string (unsigned int code);
+
+/* Returns the access name, without the DW_VIS_ prefix, as used with
+   the DW_AT_visibility attribute, if known.  Returns NULL if the given
+   DW_VIS code is unknown.  */
+const char *dwarf_visibility_string (unsigned int code);
+
+/* Returns the virtuality name, with the DW_VIRTUALITY_ prefix, as used
+   with the DW_AT_virtuality attribute, if known.  Returns NULL if the
+   given DW_VIRTUALITY code is unknown.  */
+const char *dwarf_virtuality_string (unsigned int code);
+
+/* Returns the identifier case name, without the DW_ID_ prefix, as used
+   with the DW_AT_identifier_case attribute, if known.  Returns NULL if
+   the given DW_ID code is unknown.  */
+const char *dwarf_identifier_case_string (unsigned int code);
+
+/* Returns the calling convention name, without the DW_CC_ prefix, as
+   used with the DW_AT_calling_convention attribute, if known.  Returns
+   NULL if the given DW_CC code is unknown.  */
+const char *dwarf_calling_convention_string (unsigned int code);
+
+/* Returns the ordering name, without the DW_ORD_ prefix, as
+   used with the DW_AT_ordering attribute, if known.  Returns
+   NULL if the given DW_CC code is unknown.  */
+const char *dwarf_ordering_string (unsigned int code);
+
+/* Returns the discriminant list name, without the DW_ORD_ prefix, as
+   used in the DW_AT_ordering attribute block, if known.  Returns
+   NULL if the given DW_CC code is unknown.  */
+const char *dwarf_discr_list_string (unsigned int code);
+
+/* Returns the operation name, without the DW_OP_ prefix, as
+   used in a DWARF location expression block, if known.  Returns
+   NULL if the given DW_OP code is unknown.  */
+const char *dwarf_locexpr_opcode_string (unsigned int code);
+
+/* Returns the standard line information opcode name, without the
+   DW_LNS_ prefix, as used in the line number program instructions,
+   if known.  Returns NULL if the given DW_LNS opcode is unknown.  */
+const char *dwarf_line_standard_opcode_string (unsigned int code);
+
+/* Returns the extended line information opcode name, without the
+   DW_LNE_ prefix, as used in the line number program instructions,
+   if known.  Returns NULL if the given DW_LNE opcode is unknown.  */
+const char *dwarf_line_extended_opcode_string (unsigned int code);
+
+
 /* Inline optimizations.  */
 #ifdef __OPTIMIZE__
 /* Return attribute code of given attribute.  */
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 1f71d03..8944eb5 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -254,3 +254,24 @@ ELFUTILS_0.149 {
 
     dwfl_dwarf_line;
 } ELFUTILS_0.148;
+
+ELFUTILS_0.154 {
+  global:
+    dwarf_tag_string;
+    dwarf_attr_string;
+    dwarf_form_string;
+    dwarf_lang_string;
+    dwarf_lang_description;
+    dwarf_inline_string;
+    dwarf_encoding_string;
+    dwarf_access_string;
+    dwarf_visibility_string;
+    dwarf_virtuality_string;
+    dwarf_identifier_case_string;
+    dwarf_calling_convention_string;
+    dwarf_ordering_string;
+    dwarf_discr_list_string;
+    dwarf_locexpr_opcode_string;
+    dwarf_line_standard_opcode_string;
+    dwarf_line_extended_opcode_string;
+} ELFUTILS_0.149;
diff --git a/m4/ChangeLog b/m4/ChangeLog
index d4f2bc1..af717c4 100644
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,7 @@
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* ax_cxx_compile_stdcxx_0x.m4: Add from autoconf-archive.
+
 2010-04-14  Roland McGrath  <roland@redhat.com>
 
 	* gettext.m4: Upgrade to gettext-0.17.
diff --git a/m4/ax_cxx_compile_stdcxx_0x.m4 b/m4/ax_cxx_compile_stdcxx_0x.m4
new file mode 100644
index 0000000..a4e556f
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_0x.m4
@@ -0,0 +1,107 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_0X
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++0x
+#   standard.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [
+  AC_CACHE_CHECK(if g++ supports C++0x features without additional flags,
+  ax_cv_cxx_compile_cxx0x_native,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no)
+  AC_LANG_RESTORE
+  ])
+
+  AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x,
+  ax_cv_cxx_compile_cxx0x_cxx,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  ac_save_CXXFLAGS="$CXXFLAGS"
+  CXXFLAGS="$CXXFLAGS -std=c++0x"
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no)
+  CXXFLAGS="$ac_save_CXXFLAGS"
+  AC_LANG_RESTORE
+  ])
+
+  AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x,
+  ax_cv_cxx_compile_cxx0x_gxx,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  ac_save_CXXFLAGS="$CXXFLAGS"
+  CXXFLAGS="$CXXFLAGS -std=gnu++0x"
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no)
+  CXXFLAGS="$ac_save_CXXFLAGS"
+  AC_LANG_RESTORE
+  ])
+
+  if test "$ax_cv_cxx_compile_cxx0x_native" = yes ||
+     test "$ax_cv_cxx_compile_cxx0x_cxx" = yes ||
+     test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then
+    AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ])
+  fi
+])
diff --git a/src/ChangeLog b/src/ChangeLog
index 2b657f8..a9d68f3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_lang_name): Use dwarf_lang_description.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_parameter_ref.
+
 2012-07-11  Mark Wielaard  <mjw@redhat.com>
 
 	* readelf.c (options): Add macro to help of debug-dump.
diff --git a/src/readelf.c b/src/readelf.c
index ab76a1f..01cf149 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3182,707 +3182,184 @@ format_dwarf_addr (Dwfl_Module *dwflmod,
 }
 
 static const char *
-dwarf_tag_string (unsigned int tag)
+dwarf_tag_name (unsigned int tag)
 {
-  static const char *const known_tags[]  =
-    {
-      [DW_TAG_array_type] = "array_type",
-      [DW_TAG_class_type] = "class_type",
-      [DW_TAG_entry_point] = "entry_point",
-      [DW_TAG_enumeration_type] = "enumeration_type",
-      [DW_TAG_formal_parameter] = "formal_parameter",
-      [DW_TAG_imported_declaration] = "imported_declaration",
-      [DW_TAG_label] = "label",
-      [DW_TAG_lexical_block] = "lexical_block",
-      [DW_TAG_member] = "member",
-      [DW_TAG_pointer_type] = "pointer_type",
-      [DW_TAG_reference_type] = "reference_type",
-      [DW_TAG_compile_unit] = "compile_unit",
-      [DW_TAG_string_type] = "string_type",
-      [DW_TAG_structure_type] = "structure_type",
-      [DW_TAG_subroutine_type] = "subroutine_type",
-      [DW_TAG_typedef] = "typedef",
-      [DW_TAG_union_type] = "union_type",
-      [DW_TAG_unspecified_parameters] = "unspecified_parameters",
-      [DW_TAG_variant] = "variant",
-      [DW_TAG_common_block] = "common_block",
-      [DW_TAG_common_inclusion] = "common_inclusion",
-      [DW_TAG_inheritance] = "inheritance",
-      [DW_TAG_inlined_subroutine] = "inlined_subroutine",
-      [DW_TAG_module] = "module",
-      [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
-      [DW_TAG_set_type] = "set_type",
-      [DW_TAG_subrange_type] = "subrange_type",
-      [DW_TAG_with_stmt] = "with_stmt",
-      [DW_TAG_access_declaration] = "access_declaration",
-      [DW_TAG_base_type] = "base_type",
-      [DW_TAG_catch_block] = "catch_block",
-      [DW_TAG_const_type] = "const_type",
-      [DW_TAG_constant] = "constant",
-      [DW_TAG_enumerator] = "enumerator",
-      [DW_TAG_file_type] = "file_type",
-      [DW_TAG_friend] = "friend",
-      [DW_TAG_namelist] = "namelist",
-      [DW_TAG_namelist_item] = "namelist_item",
-      [DW_TAG_packed_type] = "packed_type",
-      [DW_TAG_subprogram] = "subprogram",
-      [DW_TAG_template_type_parameter] = "template_type_parameter",
-      [DW_TAG_template_value_parameter] = "template_value_parameter",
-      [DW_TAG_thrown_type] = "thrown_type",
-      [DW_TAG_try_block] = "try_block",
-      [DW_TAG_variant_part] = "variant_part",
-      [DW_TAG_variable] = "variable",
-      [DW_TAG_volatile_type] = "volatile_type",
-      [DW_TAG_dwarf_procedure] = "dwarf_procedure",
-      [DW_TAG_restrict_type] = "restrict_type",
-      [DW_TAG_interface_type] = "interface_type",
-      [DW_TAG_namespace] = "namespace",
-      [DW_TAG_imported_module] = "imported_module",
-      [DW_TAG_unspecified_type] = "unspecified_type",
-      [DW_TAG_partial_unit] = "partial_unit",
-      [DW_TAG_imported_unit] = "imported_unit",
-      [DW_TAG_mutable_type] = "mutable_type",
-      [DW_TAG_condition] = "condition",
-      [DW_TAG_shared_type] = "shared_type",
-      [DW_TAG_type_unit] = "type_unit",
-      [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
-      [DW_TAG_template_alias] = "template_alias",
-    };
-  const unsigned int nknown_tags = (sizeof (known_tags)
-				    / sizeof (known_tags[0]));
-  static char buf[40];
-  const char *result = NULL;
-
-  if (likely (tag < nknown_tags))
-    result = known_tags[tag];
-
+  const char *result = dwarf_tag_string (tag);
   if (unlikely (result == NULL))
-    /* There are a few known extensions.  */
-    switch (tag)
-      {
-      case DW_TAG_MIPS_loop:
-	result = "MIPS_loop";
-	break;
-
-      case DW_TAG_format_label:
-	result = "format_label";
-	break;
-
-      case DW_TAG_function_template:
-	result = "function_template";
-	break;
-
-      case DW_TAG_class_template:
-	result = "class_template";
-	break;
-
-      case DW_TAG_GNU_BINCL:
-	result = "GNU_BINCL";
-	break;
-
-      case DW_TAG_GNU_EINCL:
-	result = "GNU_EINCL";
-	break;
-
-      case DW_TAG_GNU_template_template_param:
-	result = "GNU_template_template_param";
-	break;
-
-      case DW_TAG_GNU_template_parameter_pack:
-	result = "GNU_template_parameter_pack";
-	break;
-
-      case DW_TAG_GNU_formal_parameter_pack:
-	result = "GNU_formal_parameter_pack";
-	break;
-
-      case DW_TAG_GNU_call_site:
-	result = "GNU_call_site";
-	break;
-
-      case DW_TAG_GNU_call_site_parameter:
-	result = "GNU_call_site_parameter";
-	break;
-
-      default:
-	if (tag < DW_TAG_lo_user)
-	  snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
-	else
-	  snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
-	result = buf;
-	break;
-      }
-
+    {
+      static char buf[24];
+      snprintf (buf, sizeof buf, "unknown_tag_%#x" , tag);
+      result = buf;
+    }
   return result;
 }
 
 
 static const char *
-dwarf_attr_string (unsigned int attrnum)
+dwarf_attr_name (unsigned int attr)
 {
-  static const char *const known_attrs[] =
-    {
-      [DW_AT_sibling] = "sibling",
-      [DW_AT_location] = "location",
-      [DW_AT_name] = "name",
-      [DW_AT_ordering] = "ordering",
-      [DW_AT_subscr_data] = "subscr_data",
-      [DW_AT_byte_size] = "byte_size",
-      [DW_AT_bit_offset] = "bit_offset",
-      [DW_AT_bit_size] = "bit_size",
-      [DW_AT_element_list] = "element_list",
-      [DW_AT_stmt_list] = "stmt_list",
-      [DW_AT_low_pc] = "low_pc",
-      [DW_AT_high_pc] = "high_pc",
-      [DW_AT_language] = "language",
-      [DW_AT_member] = "member",
-      [DW_AT_discr] = "discr",
-      [DW_AT_discr_value] = "discr_value",
-      [DW_AT_visibility] = "visibility",
-      [DW_AT_import] = "import",
-      [DW_AT_string_length] = "string_length",
-      [DW_AT_common_reference] = "common_reference",
-      [DW_AT_comp_dir] = "comp_dir",
-      [DW_AT_const_value] = "const_value",
-      [DW_AT_containing_type] = "containing_type",
-      [DW_AT_default_value] = "default_value",
-      [DW_AT_inline] = "inline",
-      [DW_AT_is_optional] = "is_optional",
-      [DW_AT_lower_bound] = "lower_bound",
-      [DW_AT_producer] = "producer",
-      [DW_AT_prototyped] = "prototyped",
-      [DW_AT_return_addr] = "return_addr",
-      [DW_AT_start_scope] = "start_scope",
-      [DW_AT_bit_stride] = "bit_stride",
-      [DW_AT_upper_bound] = "upper_bound",
-      [DW_AT_abstract_origin] = "abstract_origin",
-      [DW_AT_accessibility] = "accessibility",
-      [DW_AT_address_class] = "address_class",
-      [DW_AT_artificial] = "artificial",
-      [DW_AT_base_types] = "base_types",
-      [DW_AT_calling_convention] = "calling_convention",
-      [DW_AT_count] = "count",
-      [DW_AT_data_member_location] = "data_member_location",
-      [DW_AT_decl_column] = "decl_column",
-      [DW_AT_decl_file] = "decl_file",
-      [DW_AT_decl_line] = "decl_line",
-      [DW_AT_declaration] = "declaration",
-      [DW_AT_discr_list] = "discr_list",
-      [DW_AT_encoding] = "encoding",
-      [DW_AT_external] = "external",
-      [DW_AT_frame_base] = "frame_base",
-      [DW_AT_friend] = "friend",
-      [DW_AT_identifier_case] = "identifier_case",
-      [DW_AT_macro_info] = "macro_info",
-      [DW_AT_namelist_item] = "namelist_item",
-      [DW_AT_priority] = "priority",
-      [DW_AT_segment] = "segment",
-      [DW_AT_specification] = "specification",
-      [DW_AT_static_link] = "static_link",
-      [DW_AT_type] = "type",
-      [DW_AT_use_location] = "use_location",
-      [DW_AT_variable_parameter] = "variable_parameter",
-      [DW_AT_virtuality] = "virtuality",
-      [DW_AT_vtable_elem_location] = "vtable_elem_location",
-      [DW_AT_allocated] = "allocated",
-      [DW_AT_associated] = "associated",
-      [DW_AT_data_location] = "data_location",
-      [DW_AT_byte_stride] = "byte_stride",
-      [DW_AT_entry_pc] = "entry_pc",
-      [DW_AT_use_UTF8] = "use_UTF8",
-      [DW_AT_extension] = "extension",
-      [DW_AT_ranges] = "ranges",
-      [DW_AT_trampoline] = "trampoline",
-      [DW_AT_call_column] = "call_column",
-      [DW_AT_call_file] = "call_file",
-      [DW_AT_call_line] = "call_line",
-      [DW_AT_description] = "description",
-      [DW_AT_binary_scale] = "binary_scale",
-      [DW_AT_decimal_scale] = "decimal_scale",
-      [DW_AT_small] = "small",
-      [DW_AT_decimal_sign] = "decimal_sign",
-      [DW_AT_digit_count] = "digit_count",
-      [DW_AT_picture_string] = "picture_string",
-      [DW_AT_mutable] = "mutable",
-      [DW_AT_threads_scaled] = "threads_scaled",
-      [DW_AT_explicit] = "explicit",
-      [DW_AT_object_pointer] = "object_pointer",
-      [DW_AT_endianity] = "endianity",
-      [DW_AT_elemental] = "elemental",
-      [DW_AT_pure] = "pure",
-      [DW_AT_recursive] = "recursive",
-      [DW_AT_signature] = "signature",
-      [DW_AT_main_subprogram] = "main_subprogram",
-      [DW_AT_data_bit_offset] = "data_bit_offset",
-      [DW_AT_const_expr] = "const_expr",
-      [DW_AT_enum_class] = "enum_class",
-      [DW_AT_linkage_name] = "linkage_name",
-    };
-  const unsigned int nknown_attrs = (sizeof (known_attrs)
-				     / sizeof (known_attrs[0]));
-  static char buf[40];
-  const char *result = NULL;
-
-  if (likely (attrnum < nknown_attrs))
-    result = known_attrs[attrnum];
-
+  const char *result = dwarf_attr_string (attr);
   if (unlikely (result == NULL))
-    /* There are a few known extensions.  */
-    switch (attrnum)
-      {
-      case DW_AT_MIPS_fde:
-	result = "MIPS_fde";
-	break;
-
-      case DW_AT_MIPS_loop_begin:
-	result = "MIPS_loop_begin";
-	break;
-
-      case DW_AT_MIPS_tail_loop_begin:
-	result = "MIPS_tail_loop_begin";
-	break;
-
-      case DW_AT_MIPS_epilog_begin:
-	result = "MIPS_epilog_begin";
-	break;
-
-      case DW_AT_MIPS_loop_unroll_factor:
-	result = "MIPS_loop_unroll_factor";
-	break;
-
-      case DW_AT_MIPS_software_pipeline_depth:
-	result = "MIPS_software_pipeline_depth";
-	break;
-
-      case DW_AT_MIPS_linkage_name:
-	result = "MIPS_linkage_name";
-	break;
-
-      case DW_AT_MIPS_stride:
-	result = "MIPS_stride";
-	break;
-
-      case DW_AT_MIPS_abstract_name:
-	result = "MIPS_abstract_name";
-	break;
-
-      case DW_AT_MIPS_clone_origin:
-	result = "MIPS_clone_origin";
-	break;
-
-      case DW_AT_MIPS_has_inlines:
-	result = "MIPS_has_inlines";
-	break;
-
-      case DW_AT_MIPS_stride_byte:
-	result = "MIPS_stride_byte";
-	break;
-
-      case DW_AT_MIPS_stride_elem:
-	result = "MIPS_stride_elem";
-	break;
-
-      case DW_AT_MIPS_ptr_dopetype:
-	result = "MIPS_ptr_dopetype";
-	break;
-
-      case DW_AT_MIPS_allocatable_dopetype:
-	result = "MIPS_allocatable_dopetype";
-	break;
-
-      case DW_AT_MIPS_assumed_shape_dopetype:
-	result = "MIPS_assumed_shape_dopetype";
-	break;
-
-      case DW_AT_MIPS_assumed_size:
-	result = "MIPS_assumed_size";
-	break;
-
-      case DW_AT_sf_names:
-	result = "sf_names";
-	break;
-
-      case DW_AT_src_info:
-	result = "src_info";
-	break;
-
-      case DW_AT_mac_info:
-	result = "mac_info";
-	break;
-
-      case DW_AT_src_coords:
-	result = "src_coords";
-	break;
-
-      case DW_AT_body_begin:
-	result = "body_begin";
-	break;
-
-      case DW_AT_body_end:
-	result = "body_end";
-	break;
-
-      case DW_AT_GNU_vector:
-	result = "GNU_vector";
-	break;
-
-      case DW_AT_GNU_guarded_by:
-	result = "GNU_guarded_by";
-	break;
-
-      case DW_AT_GNU_pt_guarded_by:
-	result = "GNU_pt_guarded_by";
-	break;
-
-      case DW_AT_GNU_guarded:
-	result = "GNU_guarded";
-	break;
-
-      case DW_AT_GNU_pt_guarded:
-	result = "GNU_pt_guarded";
-	break;
-
-      case DW_AT_GNU_locks_excluded:
-	result = "GNU_locks_excluded";
-	break;
-
-      case DW_AT_GNU_exclusive_locks_required:
-	result = "GNU_exclusive_locks_required";
-	break;
-
-      case DW_AT_GNU_shared_locks_required:
-	result = "GNU_shared_locks_required";
-	break;
-
-      case DW_AT_GNU_odr_signature:
-	result = "GNU_odr_signature";
-	break;
-
-      case DW_AT_GNU_template_name:
-	result = "GNU_template_name";
-	break;
-
-      case DW_AT_GNU_call_site_value:
-	result = "GNU_call_site_value";
-	break;
-
-      case DW_AT_GNU_call_site_data_value:
-	result = "GNU_call_site_data_value";
-	break;
-
-      case DW_AT_GNU_call_site_target:
-	result = "GNU_call_site_target";
-	break;
-
-      case DW_AT_GNU_call_site_target_clobbered:
-	result = "GNU_call_site_target_clobbered";
-	break;
-
-      case DW_AT_GNU_tail_call:
-	result = "GNU_tail_call";
-	break;
-
-      case DW_AT_GNU_all_tail_call_sites:
-	result = "GNU_all_tail_call_sites";
-	break;
-
-      case DW_AT_GNU_all_call_sites:
-	result = "GNU_all_call_sites";
-	break;
-
-      case DW_AT_GNU_all_source_call_sites:
-	result = "GNU_all_source_call_sites";
-	break;
-
-      case DW_AT_GNU_macros:
-	result = "GNU_macros";
-	break;
-
-      default:
-	if (attrnum < DW_AT_lo_user)
-	  snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
-		    attrnum);
-	else
-	  snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
-		    attrnum);
-	result = buf;
-	break;
-      }
-
+    {
+      static char buf[25];
+      snprintf (buf, sizeof buf, "unknown_attr_%#x", attr);
+      result = buf;
+    }
   return result;
 }
 
 
 static const char *
-dwarf_form_string (unsigned int form)
+dwarf_form_name (unsigned int form)
 {
-  static const char *const known_forms[] =
-    {
-      [DW_FORM_addr] = "addr",
-      [DW_FORM_block2] = "block2",
-      [DW_FORM_block4] = "block4",
-      [DW_FORM_data2] = "data2",
-      [DW_FORM_data4] = "data4",
-      [DW_FORM_data8] = "data8",
-      [DW_FORM_string] = "string",
-      [DW_FORM_block] = "block",
-      [DW_FORM_block1] = "block1",
-      [DW_FORM_data1] = "data1",
-      [DW_FORM_flag] = "flag",
-      [DW_FORM_sdata] = "sdata",
-      [DW_FORM_strp] = "strp",
-      [DW_FORM_udata] = "udata",
-      [DW_FORM_ref_addr] = "ref_addr",
-      [DW_FORM_ref1] = "ref1",
-      [DW_FORM_ref2] = "ref2",
-      [DW_FORM_ref4] = "ref4",
-      [DW_FORM_ref8] = "ref8",
-      [DW_FORM_ref_udata] = "ref_udata",
-      [DW_FORM_indirect] = "indirect",
-      [DW_FORM_sec_offset] = "sec_offset",
-      [DW_FORM_exprloc] = "exprloc",
-      [DW_FORM_flag_present] = "flag_present",
-      [DW_FORM_ref_sig8] = "ref_sig8",
-    };
-  const unsigned int nknown_forms = (sizeof (known_forms)
-				     / sizeof (known_forms[0]));
-  static char buf[40];
-  const char *result = NULL;
-
-  if (likely (form < nknown_forms))
-    result = known_forms[form];
-
+  const char *result = dwarf_form_string (form);
   if (unlikely (result == NULL))
     {
-      snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64),
-		(uint64_t) form);
+      static char buf[25];
+      snprintf (buf, sizeof buf, "unknown_form_%#x", form);
       result = buf;
     }
-
   return result;
 }
 
 
 static const char *
-dwarf_lang_string (unsigned int lang)
+dwarf_lang_name (unsigned int lang)
 {
-  static const char *const known[] =
-    {
-      [DW_LANG_C89] = "ISO C89",
-      [DW_LANG_C] = "C",
-      [DW_LANG_Ada83] = "Ada83",
-      [DW_LANG_C_plus_plus] = "C++",
-      [DW_LANG_Cobol74] = "Cobol74",
-      [DW_LANG_Cobol85] = "Cobol85",
-      [DW_LANG_Fortran77] = "Fortran77",
-      [DW_LANG_Fortran90] = "Fortran90",
-      [DW_LANG_Pascal83] = "Pascal83",
-      [DW_LANG_Modula2] = "Modula2",
-      [DW_LANG_Java] = "Java",
-      [DW_LANG_C99] = "ISO C99",
-      [DW_LANG_Ada95] = "Ada95",
-      [DW_LANG_Fortran95] = "Fortran95",
-      [DW_LANG_PL1] = "PL1",
-      [DW_LANG_Objc] = "Objective C",
-      [DW_LANG_ObjC_plus_plus] = "Objective C++",
-      [DW_LANG_UPC] = "UPC",
-      [DW_LANG_D] = "D",
-    };
-
-  if (likely (lang < sizeof (known) / sizeof (known[0])))
-    return known[lang];
-  else if (lang == DW_LANG_Mips_Assembler)
-    /* This language tag is used for assembler in general.  */
-    return "Assembler";
-
-  if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
+  const char *result = dwarf_lang_description (lang);
+  if (unlikely (result == NULL))
     {
-      static char buf[30];
-      snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
-      return buf;
+      static char buf[29];
+      snprintf (buf, sizeof buf, "Unknown Language %#x", lang);
+      result = buf;
     }
-
-  return "???";
+  return result;
 }
 
 
 static const char *
-dwarf_inline_string (unsigned int code)
+dwarf_inline_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_inline_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_INL_not_inlined] = "not_inlined",
-      [DW_INL_inlined] = "inlined",
-      [DW_INL_declared_not_inlined] = "declared_not_inlined",
-      [DW_INL_declared_inlined] = "declared_inlined"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[27];
+      snprintf (buf, sizeof buf, "unknown_inline_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_encoding_string (unsigned int code)
+dwarf_encoding_name (unsigned int code)
 {
-  static const char *const known[] =
-    {
-      [DW_ATE_void] = "void",
-      [DW_ATE_address] = "address",
-      [DW_ATE_boolean] = "boolean",
-      [DW_ATE_complex_float] = "complex_float",
-      [DW_ATE_float] = "float",
-      [DW_ATE_signed] = "signed",
-      [DW_ATE_signed_char] = "signed_char",
-      [DW_ATE_unsigned] = "unsigned",
-      [DW_ATE_unsigned_char] = "unsigned_char",
-      [DW_ATE_imaginary_float] = "imaginary_float",
-      [DW_ATE_packed_decimal] = "packed_decimal",
-      [DW_ATE_numeric_string] = "numeric_string",
-      [DW_ATE_edited] = "edited",
-      [DW_ATE_signed_fixed] = "signed_fixed",
-      [DW_ATE_unsigned_fixed] = "unsigned_fixed",
-      [DW_ATE_decimal_float] = "decimal_float",
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
+  const char *result = dwarf_encoding_string (code);
+  if (unlikely (result == NULL))
     {
-      static char buf[30];
-      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
-      return buf;
+      static char buf[29];
+      snprintf (buf, sizeof buf, "unknown_encoding_%#x", code);
+      result = buf;
     }
-
-  return "???";
+  return result;
 }
 
 
 static const char *
-dwarf_access_string (unsigned int code)
+dwarf_access_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_access_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_ACCESS_public] = "public",
-      [DW_ACCESS_protected] = "protected",
-      [DW_ACCESS_private] = "private"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[27];
+      snprintf (buf, sizeof buf, "unknown_access_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_visibility_string (unsigned int code)
+dwarf_visibility_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_visibility_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_VIS_local] = "local",
-      [DW_VIS_exported] = "exported",
-      [DW_VIS_qualified] = "qualified"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[31];
+      snprintf (buf, sizeof buf, "unknown_visibility_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_virtuality_string (unsigned int code)
+dwarf_virtuality_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_virtuality_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_VIRTUALITY_none] = "none",
-      [DW_VIRTUALITY_virtual] = "virtual",
-      [DW_VIRTUALITY_pure_virtual] = "pure_virtual"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[31];
+      snprintf (buf, sizeof buf, "unknown_virtuality_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_identifier_case_string (unsigned int code)
+dwarf_identifier_case_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_identifier_case_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_ID_case_sensitive] = "sensitive",
-      [DW_ID_up_case] = "up_case",
-      [DW_ID_down_case] = "down_case",
-      [DW_ID_case_insensitive] = "insensitive"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[31];
+      snprintf (buf, sizeof buf, "unknown_virtuality_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_calling_convention_string (unsigned int code)
+dwarf_calling_convention_name (unsigned int code)
 {
-  static const char *const known[] =
-    {
-      [DW_CC_normal] = "normal",
-      [DW_CC_program] = "program",
-      [DW_CC_nocall] = "nocall",
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  if (code >= DW_CC_lo_user && code <= DW_CC_hi_user)
+  const char *result = dwarf_calling_convention_string (code);
+  if (unlikely (result == NULL))
     {
-      static char buf[30];
-      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user);
-      return buf;
+      static char buf[39];
+      snprintf (buf, sizeof buf, "unknown_calling_convention_%#x", code);
+      result = buf;
     }
-
-  return "???";
+  return result;
 }
 
 
 static const char *
-dwarf_ordering_string (unsigned int code)
+dwarf_ordering_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_ordering_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_ORD_row_major] = "row_major",
-      [DW_ORD_col_major] = "col_major"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[28];
+      snprintf (buf, sizeof buf, "unknown_ordering_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
 static const char *
-dwarf_discr_list_string (unsigned int code)
+dwarf_discr_list_name (unsigned int code)
 {
-  static const char *const known[] =
+  const char *result = dwarf_discr_list_string (code);
+  if (unlikely (result == NULL))
     {
-      [DW_DSC_label] = "label",
-      [DW_DSC_range] = "range"
-    };
-
-  if (likely (code < sizeof (known) / sizeof (known[0])))
-    return known[code];
-
-  return "???";
+      static char buf[30];
+      snprintf (buf, sizeof buf, "unknown_discr_list_%#x", code);
+      result = buf;
+    }
+  return result;
 }
 
 
@@ -3909,174 +3386,6 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 {
   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
 
-  static const char *const known[] =
-    {
-      [DW_OP_addr] = "addr",
-      [DW_OP_deref] = "deref",
-      [DW_OP_const1u] = "const1u",
-      [DW_OP_const1s] = "const1s",
-      [DW_OP_const2u] = "const2u",
-      [DW_OP_const2s] = "const2s",
-      [DW_OP_const4u] = "const4u",
-      [DW_OP_const4s] = "const4s",
-      [DW_OP_const8u] = "const8u",
-      [DW_OP_const8s] = "const8s",
-      [DW_OP_constu] = "constu",
-      [DW_OP_consts] = "consts",
-      [DW_OP_dup] = "dup",
-      [DW_OP_drop] = "drop",
-      [DW_OP_over] = "over",
-      [DW_OP_pick] = "pick",
-      [DW_OP_swap] = "swap",
-      [DW_OP_rot] = "rot",
-      [DW_OP_xderef] = "xderef",
-      [DW_OP_abs] = "abs",
-      [DW_OP_and] = "and",
-      [DW_OP_div] = "div",
-      [DW_OP_minus] = "minus",
-      [DW_OP_mod] = "mod",
-      [DW_OP_mul] = "mul",
-      [DW_OP_neg] = "neg",
-      [DW_OP_not] = "not",
-      [DW_OP_or] = "or",
-      [DW_OP_plus] = "plus",
-      [DW_OP_plus_uconst] = "plus_uconst",
-      [DW_OP_shl] = "shl",
-      [DW_OP_shr] = "shr",
-      [DW_OP_shra] = "shra",
-      [DW_OP_xor] = "xor",
-      [DW_OP_bra] = "bra",
-      [DW_OP_eq] = "eq",
-      [DW_OP_ge] = "ge",
-      [DW_OP_gt] = "gt",
-      [DW_OP_le] = "le",
-      [DW_OP_lt] = "lt",
-      [DW_OP_ne] = "ne",
-      [DW_OP_skip] = "skip",
-      [DW_OP_lit0] = "lit0",
-      [DW_OP_lit1] = "lit1",
-      [DW_OP_lit2] = "lit2",
-      [DW_OP_lit3] = "lit3",
-      [DW_OP_lit4] = "lit4",
-      [DW_OP_lit5] = "lit5",
-      [DW_OP_lit6] = "lit6",
-      [DW_OP_lit7] = "lit7",
-      [DW_OP_lit8] = "lit8",
-      [DW_OP_lit9] = "lit9",
-      [DW_OP_lit10] = "lit10",
-      [DW_OP_lit11] = "lit11",
-      [DW_OP_lit12] = "lit12",
-      [DW_OP_lit13] = "lit13",
-      [DW_OP_lit14] = "lit14",
-      [DW_OP_lit15] = "lit15",
-      [DW_OP_lit16] = "lit16",
-      [DW_OP_lit17] = "lit17",
-      [DW_OP_lit18] = "lit18",
-      [DW_OP_lit19] = "lit19",
-      [DW_OP_lit20] = "lit20",
-      [DW_OP_lit21] = "lit21",
-      [DW_OP_lit22] = "lit22",
-      [DW_OP_lit23] = "lit23",
-      [DW_OP_lit24] = "lit24",
-      [DW_OP_lit25] = "lit25",
-      [DW_OP_lit26] = "lit26",
-      [DW_OP_lit27] = "lit27",
-      [DW_OP_lit28] = "lit28",
-      [DW_OP_lit29] = "lit29",
-      [DW_OP_lit30] = "lit30",
-      [DW_OP_lit31] = "lit31",
-      [DW_OP_reg0] = "reg0",
-      [DW_OP_reg1] = "reg1",
-      [DW_OP_reg2] = "reg2",
-      [DW_OP_reg3] = "reg3",
-      [DW_OP_reg4] = "reg4",
-      [DW_OP_reg5] = "reg5",
-      [DW_OP_reg6] = "reg6",
-      [DW_OP_reg7] = "reg7",
-      [DW_OP_reg8] = "reg8",
-      [DW_OP_reg9] = "reg9",
-      [DW_OP_reg10] = "reg10",
-      [DW_OP_reg11] = "reg11",
-      [DW_OP_reg12] = "reg12",
-      [DW_OP_reg13] = "reg13",
-      [DW_OP_reg14] = "reg14",
-      [DW_OP_reg15] = "reg15",
-      [DW_OP_reg16] = "reg16",
-      [DW_OP_reg17] = "reg17",
-      [DW_OP_reg18] = "reg18",
-      [DW_OP_reg19] = "reg19",
-      [DW_OP_reg20] = "reg20",
-      [DW_OP_reg21] = "reg21",
-      [DW_OP_reg22] = "reg22",
-      [DW_OP_reg23] = "reg23",
-      [DW_OP_reg24] = "reg24",
-      [DW_OP_reg25] = "reg25",
-      [DW_OP_reg26] = "reg26",
-      [DW_OP_reg27] = "reg27",
-      [DW_OP_reg28] = "reg28",
-      [DW_OP_reg29] = "reg29",
-      [DW_OP_reg30] = "reg30",
-      [DW_OP_reg31] = "reg31",
-      [DW_OP_breg0] = "breg0",
-      [DW_OP_breg1] = "breg1",
-      [DW_OP_breg2] = "breg2",
-      [DW_OP_breg3] = "breg3",
-      [DW_OP_breg4] = "breg4",
-      [DW_OP_breg5] = "breg5",
-      [DW_OP_breg6] = "breg6",
-      [DW_OP_breg7] = "breg7",
-      [DW_OP_breg8] = "breg8",
-      [DW_OP_breg9] = "breg9",
-      [DW_OP_breg10] = "breg10",
-      [DW_OP_breg11] = "breg11",
-      [DW_OP_breg12] = "breg12",
-      [DW_OP_breg13] = "breg13",
-      [DW_OP_breg14] = "breg14",
-      [DW_OP_breg15] = "breg15",
-      [DW_OP_breg16] = "breg16",
-      [DW_OP_breg17] = "breg17",
-      [DW_OP_breg18] = "breg18",
-      [DW_OP_breg19] = "breg19",
-      [DW_OP_breg20] = "breg20",
-      [DW_OP_breg21] = "breg21",
-      [DW_OP_breg22] = "breg22",
-      [DW_OP_breg23] = "breg23",
-      [DW_OP_breg24] = "breg24",
-      [DW_OP_breg25] = "breg25",
-      [DW_OP_breg26] = "breg26",
-      [DW_OP_breg27] = "breg27",
-      [DW_OP_breg28] = "breg28",
-      [DW_OP_breg29] = "breg29",
-      [DW_OP_breg30] = "breg30",
-      [DW_OP_breg31] = "breg31",
-      [DW_OP_regx] = "regx",
-      [DW_OP_fbreg] = "fbreg",
-      [DW_OP_bregx] = "bregx",
-      [DW_OP_piece] = "piece",
-      [DW_OP_deref_size] = "deref_size",
-      [DW_OP_xderef_size] = "xderef_size",
-      [DW_OP_nop] = "nop",
-      [DW_OP_push_object_address] = "push_object_address",
-      [DW_OP_call2] = "call2",
-      [DW_OP_call4] = "call4",
-      [DW_OP_call_ref] = "call_ref",
-      [DW_OP_form_tls_address] = "form_tls_address",
-      [DW_OP_call_frame_cfa] = "call_frame_cfa",
-      [DW_OP_bit_piece] = "bit_piece",
-      [DW_OP_implicit_value] = "implicit_value",
-      [DW_OP_stack_value] = "stack_value",
-      [DW_OP_GNU_push_tls_address] = "GNU_push_tls_address",
-      [DW_OP_GNU_uninit] = "GNU_uninit",
-      [DW_OP_GNU_encoded_addr] = "GNU_encoded_addr",
-      [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
-      [DW_OP_GNU_entry_value] = "GNU_entry_value",
-      [DW_OP_GNU_const_type] = "GNU_const_type",
-      [DW_OP_GNU_regval_type] = "GNU_regval_type",
-      [DW_OP_GNU_deref_type] = "GNU_deref_type",
-      [DW_OP_GNU_convert] = "GNU_convert",
-      [DW_OP_GNU_reinterpret] = "GNU_reinterpret",
-    };
-
   if (len == 0)
     {
       printf ("%*s(empty)\n", indent, "");
@@ -4091,6 +3400,14 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
     {
       uint_fast8_t op = *data++;
 
+      const char *op_name = dwarf_locexpr_opcode_string (op);
+      if (unlikely (op_name == NULL))
+	{
+	  static char buf[26];
+	  snprintf (buf, sizeof buf, "unknown_opcode_%#x", op);
+	  op_name = buf;
+	}
+
       switch (op)
 	{
 	case DW_OP_addr:;
@@ -4109,7 +3426,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	  char *a = format_dwarf_addr (dwflmod, 0, addr);
 	  printf ("%*s[%4" PRIuMAX "] %s %s\n",
-		  indent, "", (uintmax_t) offset, known[op], a);
+		  indent, "", (uintmax_t) offset, op_name, a);
 	  free (a);
 
 	  offset += 1 + addrsize;
@@ -4130,7 +3447,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], (uintmax_t) addr);
+		  op_name, (uintmax_t) addr);
 	  offset += 1 + ref_size;
 	  break;
 
@@ -4142,7 +3459,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], *((uint8_t *) data));
+		  op_name, *((uint8_t *) data));
 	  ++data;
 	  --len;
 	  offset += 2;
@@ -4153,7 +3470,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], read_2ubyte_unaligned (dbg, data));
+		  op_name, read_2ubyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -4164,7 +3481,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], read_4ubyte_unaligned (dbg, data));
+		  op_name, read_4ubyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -4175,7 +3492,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], (uint64_t) read_8ubyte_unaligned (dbg, data));
+		  op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
 	  CONSUME (8);
 	  data += 8;
 	  offset += 9;
@@ -4186,7 +3503,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], *((int8_t *) data));
+		  op_name, *((int8_t *) data));
 	  ++data;
 	  --len;
 	  offset += 2;
@@ -4197,7 +3514,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], read_2sbyte_unaligned (dbg, data));
+		  op_name, read_2sbyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -4208,7 +3525,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], read_4sbyte_unaligned (dbg, data));
+		  op_name, read_4sbyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -4219,7 +3536,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  // XXX value might be modified by relocation
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], read_8sbyte_unaligned (dbg, data));
+		  op_name, read_8sbyte_unaligned (dbg, data));
 	  CONSUME (8);
 	  data += 8;
 	  offset += 9;
@@ -4234,7 +3551,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
-		  indent, "", (uintmax_t) offset, known[op], uleb);
+		  indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4246,7 +3563,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  get_uleb128 (uleb2, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
-		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
+		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4259,7 +3576,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_sleb128 (sleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
-		  indent, "", (uintmax_t) offset, known[op], sleb);
+		  indent, "", (uintmax_t) offset, op_name, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4270,7 +3587,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  get_sleb128 (sleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
-		  indent, "", (uintmax_t) offset, known[op], uleb, sleb);
+		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4278,7 +3595,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_call2:
 	  NEED (2);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
-		  indent, "", (uintmax_t) offset, known[op],
+		  indent, "", (uintmax_t) offset, op_name,
 		  read_2ubyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  offset += 3;
@@ -4287,7 +3604,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_call4:
 	  NEED (4);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
-		  indent, "", (uintmax_t) offset, known[op],
+		  indent, "", (uintmax_t) offset, op_name,
 		  read_4ubyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  offset += 5;
@@ -4297,7 +3614,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_bra:
 	  NEED (2);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
-		  indent, "", (uintmax_t) offset, known[op],
+		  indent, "", (uintmax_t) offset, op_name,
 		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
 	  CONSUME (2);
 	  data += 2;
@@ -4309,7 +3626,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s: ",
-		  indent, "", (uintmax_t) offset, known[op]);
+		  indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
 	  print_block (uleb, data);
 	  data += uleb;
@@ -4334,7 +3651,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	  printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
 		  indent, "", (intmax_t) offset,
-		  known[op], (uintmax_t) addr, sleb);
+		  op_name, (uintmax_t) addr, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4345,7 +3662,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s:\n",
-		  indent, "", (uintmax_t) offset, known[op]);
+		  indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
 	  print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
 		     addrsize, offset_size, uleb, data);
@@ -4362,7 +3679,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  uint8_t usize = *(uint8_t *) data++;
 	  NEED (usize);
 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
-		  indent, "", (uintmax_t) offset, known[op], uleb);
+		  indent, "", (uintmax_t) offset, op_name, uleb);
 	  print_block (usize, data);
 	  data += usize;
 	  CONSUME (data - start);
@@ -4375,7 +3692,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  get_uleb128 (uleb2, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n",
-		  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
+		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4387,7 +3704,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
 		  indent, "", (uintmax_t) offset,
-		  known[op], usize, uleb);
+		  op_name, usize, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -4398,19 +3715,27 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_uleb128 (uleb, data); /* XXX check overrun */
 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset, known[op], uleb);
+		  indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
 
+	case DW_OP_GNU_parameter_ref:
+	  /* 4 byte CU relative reference to the abstract optimized away
+	     DW_TAG_formal_parameter.  */
+	  NEED (4);
+	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset, op_name,
+		  (uintmax_t) read_4ubyte_unaligned (dbg, data));
+	  CONSUME (4);
+	  data += 4;
+	  offset += 5;
+	  break;
+
 	default:
 	  /* No Operand.  */
-	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
 	    printf ("%*s[%4" PRIuMAX "] %s\n",
-		    indent, "", (uintmax_t) offset, known[op]);
-	  else
-	    printf ("%*s[%4" PRIuMAX "] %#x\n",
-		    indent, "", (uintmax_t) offset, op);
+		    indent, "", (uintmax_t) offset, op_name);
 	  ++offset;
 	  break;
 	}
@@ -4420,7 +3745,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
     invalid:
       printf (gettext ("%*s[%4" PRIuMAX "] %s  <TRUNCATED>\n"),
-	      indent, "", (uintmax_t) offset, known[op]);
+	      indent, "", (uintmax_t) offset, op_name);
       break;
     }
 }
@@ -4613,7 +3938,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			   ", children: %s, tag: %s\n"),
 		  code, (int64_t) offset,
 		  has_children ? gettext ("yes") : gettext ("no"),
-		  dwarf_tag_string (tag));
+		  dwarf_tag_name (tag));
 
 	  size_t cnt = 0;
 	  unsigned int name;
@@ -4623,7 +3948,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 				      &name, &form, &enoffset) == 0)
 	    {
 	      printf ("          attr: %s, form: %s, offset: %#" PRIx64 "\n",
-		      dwarf_attr_string (name), dwarf_form_string (form),
+		      dwarf_attr_name (name), dwarf_form_name (form),
 		      (uint64_t) enoffset);
 
 	      ++cnt;
@@ -5572,8 +4897,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	    }
 	  char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
 	  printf ("           %*s%-20s (%s) %s\n",
-		  (int) (level * 2), "", dwarf_attr_string (attr),
-		  dwarf_form_string (form), a);
+		  (int) (level * 2), "", dwarf_attr_name (attr),
+		  dwarf_form_name (form), a);
 	  free (a);
 	}
       break;
@@ -5587,8 +4912,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       if (unlikely (str == NULL))
 	goto attrval_out;
       printf ("           %*s%-20s (%s) \"%s\"\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form), str);
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), str);
       break;
 
     case DW_FORM_ref_addr:
@@ -5604,16 +4929,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	goto attrval_out;
 
       printf ("           %*s%-20s (%s) [%6" PRIxMAX "]\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref));
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref));
       break;
 
     case DW_FORM_ref_sig8:
       if (cbargs->silent)
 	break;
       printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form),
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form),
 	      (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
       break;
 
@@ -5639,8 +4964,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	    {
 	      if (!cbargs->silent)
 		printf ("           %*s%-20s (%s) %" PRIxMAX "\n",
-			(int) (level * 2), "", dwarf_attr_string (attr),
-			dwarf_form_string (form), (uintmax_t) num);
+			(int) (level * 2), "", dwarf_attr_name (attr),
+			dwarf_form_name (form), (uintmax_t) num);
 	      return DWARF_CB_OK;
 	    }
 	  /* else fallthrough */
@@ -5662,8 +4987,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 			  cbargs->addrsize, cbargs->offset_size, num);
 	  if (!cbargs->silent)
 	    printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
-		    (int) (level * 2), "", dwarf_attr_string (attr),
-		    dwarf_form_string (form), (uintmax_t) num);
+		    (int) (level * 2), "", dwarf_attr_name (attr),
+		    dwarf_form_name (form), (uintmax_t) num);
 	  return DWARF_CB_OK;
 
 	case DW_AT_ranges:
@@ -5671,39 +4996,39 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 			  cbargs->addrsize, cbargs->offset_size, num);
 	  if (!cbargs->silent)
 	    printf ("           %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
-		    (int) (level * 2), "", dwarf_attr_string (attr),
-		    dwarf_form_string (form), (uintmax_t) num);
+		    (int) (level * 2), "", dwarf_attr_name (attr),
+		    dwarf_form_name (form), (uintmax_t) num);
 	  return DWARF_CB_OK;
 
 	case DW_AT_language:
-	  valuestr = dwarf_lang_string (num);
+	  valuestr = dwarf_lang_name (num);
 	  break;
 	case DW_AT_encoding:
-	  valuestr = dwarf_encoding_string (num);
+	  valuestr = dwarf_encoding_name (num);
 	  break;
 	case DW_AT_accessibility:
-	  valuestr = dwarf_access_string (num);
+	  valuestr = dwarf_access_name (num);
 	  break;
 	case DW_AT_visibility:
-	  valuestr = dwarf_visibility_string (num);
+	  valuestr = dwarf_visibility_name (num);
 	  break;
 	case DW_AT_virtuality:
-	  valuestr = dwarf_virtuality_string (num);
+	  valuestr = dwarf_virtuality_name (num);
 	  break;
 	case DW_AT_identifier_case:
-	  valuestr = dwarf_identifier_case_string (num);
+	  valuestr = dwarf_identifier_case_name (num);
 	  break;
 	case DW_AT_calling_convention:
-	  valuestr = dwarf_calling_convention_string (num);
+	  valuestr = dwarf_calling_convention_name (num);
 	  break;
 	case DW_AT_inline:
-	  valuestr = dwarf_inline_string (num);
+	  valuestr = dwarf_inline_name (num);
 	  break;
 	case DW_AT_ordering:
-	  valuestr = dwarf_ordering_string (num);
+	  valuestr = dwarf_ordering_name (num);
 	  break;
 	case DW_AT_discr_list:
-	  valuestr = dwarf_discr_list_string (num);
+	  valuestr = dwarf_discr_list_name (num);
 	  break;
 	default:
 	  /* Nothing.  */
@@ -5715,12 +5040,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 
       if (valuestr == NULL)
 	printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
-		(int) (level * 2), "", dwarf_attr_string (attr),
-		dwarf_form_string (form), (uintmax_t) num);
+		(int) (level * 2), "", dwarf_attr_name (attr),
+		dwarf_form_name (form), (uintmax_t) num);
       else
 	printf ("           %*s%-20s (%s) %s (%" PRIuMAX ")\n",
-		(int) (level * 2), "", dwarf_attr_string (attr),
-		dwarf_form_string (form), valuestr, (uintmax_t) num);
+		(int) (level * 2), "", dwarf_attr_name (attr),
+		dwarf_form_name (form), valuestr, (uintmax_t) num);
       break;
 
     case DW_FORM_flag:
@@ -5731,16 +5056,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	goto attrval_out;
 
       printf ("           %*s%-20s (%s) %s\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR));
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
       break;
 
     case DW_FORM_flag_present:
       if (cbargs->silent)
 	break;
       printf ("           %*s%-20s (%s) %s\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form), nl_langinfo (YESSTR));
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), nl_langinfo (YESSTR));
       break;
 
     case DW_FORM_exprloc:
@@ -5755,8 +5080,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	goto attrval_out;
 
       printf ("           %*s%-20s (%s) ",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
-	      dwarf_form_string (form));
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form));
 
       switch (attr)
 	{
@@ -5804,7 +5129,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       if (cbargs->silent)
 	break;
       printf ("           %*s%-20s (form: %#x) ???\n",
-	      (int) (level * 2), "", dwarf_attr_string (attr),
+	      (int) (level * 2), "", dwarf_attr_name (attr),
 	      (int) form);
       break;
     }
@@ -5919,7 +5244,7 @@ print_debug_units (Dwfl_Module *dwflmod,
       if (!silent)
 	printf (" [%6" PRIx64 "]  %*s%s\n",
 		(uint64_t) offset, (int) (level * 2), "",
-		dwarf_tag_string (tag));
+		dwarf_tag_name (tag));
 
       /* Print the attribute values.  */
       args.level = level;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 6133048..0bb0a00 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,28 @@
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* cpp-various.cxx: New testfile.
+	* Makefile.am (cpp_various_SOURCES): New.
+	(HAVE_STDCXX_0X): Add cpp-various and -std=c++0x if exists.
+	(EXTRA_DIST): Add cpp-various.cxx
+	* run-readelf-unknown.sh: runtest ./cpp-various if exists.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-unknown.sh: egrep also for "Unknown Language".
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-unknown.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-unknown.sh.
+	(EXTRA_DIST): Likewise.
+
+2012-07-17  Mark Wielaard  <mjw@redhat.com>
+
+	* allregs.c (dwarf_encoding_string): Removed.
+	* show-die-info.c (tagnames): Removed.
+	(attrs): Removed.
+	(handle): Call dwarf_tag_string and dwarf_attr_string instead.
+
 2012-07-19  Mark Wielaard  <mjw@redhat.com>
 
 	* Makefile.am (check_PROGRAMS): Add test-elf_cntl_gelf_getshdr.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a8b0f16..038d374 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -71,7 +71,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
 	run-find-prologues.sh run-allregs.sh \
 	run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
-	run-readelf-test4.sh run-readelf-twofiles.sh \
+	run-readelf-test4.sh run-readelf-twofiles.sh run-readelf-unknown.sh \
 	run-readelf-macro.sh \
 	run-native-test.sh run-bug1-test.sh \
 	dwfl-bug-addr-overflow run-addrname-test.sh \
@@ -94,6 +94,11 @@ check_PROGRAMS += $(asm_TESTS)
 TESTS += $(asm_TESTS)
 endif
 
+if HAVE_STDCXX_0X
+check_PROGRAMS += cpp-various
+AM_CXXFLAGS = -std=c++0x
+cpp_various_SOURCES = cpp-various.cxx
+endif
 
 EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     run-show-die-info.sh run-get-files.sh run-get-lines.sh \
@@ -129,6 +134,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     coverage.sh test-subr.sh test-wrapper.sh \
 	     run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
 	     run-readelf-test4.sh run-readelf-twofiles.sh \
+	     run-readelf-unknown.sh cpp-various.cxx \
 	     run-bug1-test.sh testfile28.bz2 testfile28.rdwr.bz2 \
 	     testfile29.bz2 testfile29.rdwr.bz2 \
 	     testfile30.bz2 testfile31.bz2 testfile32.bz2 testfile33.bz2 \
diff --git a/tests/allregs.c b/tests/allregs.c
index b30d899..279ddb5 100644
--- a/tests/allregs.c
+++ b/tests/allregs.c
@@ -29,42 +29,6 @@
 #include <dwarf.h>
 
 
-static const char *
-dwarf_encoding_string (unsigned int code)
-{
-  static const char *known[] =
-    {
-      [DW_ATE_void] = "void",
-      [DW_ATE_address] = "address",
-      [DW_ATE_boolean] = "boolean",
-      [DW_ATE_complex_float] = "complex_float",
-      [DW_ATE_float] = "float",
-      [DW_ATE_signed] = "signed",
-      [DW_ATE_signed_char] = "signed_char",
-      [DW_ATE_unsigned] = "unsigned",
-      [DW_ATE_unsigned_char] = "unsigned_char",
-      [DW_ATE_imaginary_float] = "imaginary_float",
-      [DW_ATE_packed_decimal] = "packed_decimal",
-      [DW_ATE_numeric_string] = "numeric_string",
-      [DW_ATE_edited] = "edited",
-      [DW_ATE_signed_fixed] = "signed_fixed",
-      [DW_ATE_unsigned_fixed] = "unsigned_fixed",
-      [DW_ATE_decimal_float] = "decimal_float",
-    };
-
-  if (code < sizeof (known) / sizeof (known[0]))
-    return known[code];
-
-  if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user)
-    {
-      static char buf[30];
-      snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user);
-      return buf;
-    }
-
-  return "???";
-}
-
 static int
 first_module (Dwfl_Module *mod,
 	      void **userdatap __attribute__ ((unused)),
diff --git a/tests/cpp-various.cxx b/tests/cpp-various.cxx
new file mode 100644
index 0000000..39db5a1
--- /dev/null
+++ b/tests/cpp-various.cxx
@@ -0,0 +1,136 @@
+/* Test program for testing C++0X features are recognized.
+   Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <iostream>
+
+using namespace std;
+
+#define PI 3.14159
+#define NEWLINE '\n'
+
+int arr[5] = { 1, 26, 7, 740, 1271 };
+char days[365][24][60][60];
+int *b;
+
+struct p { int w; float p;};
+p a;
+
+typedef char CHAR;
+typedef int INT;
+typedef float FLOAT;
+
+union u
+{
+  CHAR c;
+  INT i;
+  FLOAT f;
+  union
+  {
+    int i2;
+    char c2;
+  };
+  union sub
+  {
+    float f;
+    double d;
+  };
+  union chars
+  {
+    char c;
+    unsigned char uc;
+    signed char sc;
+    wchar_t wc;
+    char16_t c16;
+    char32_t c32;
+  };
+};
+
+enum en { foo, bar, baz };
+enum en2 { en_a = 1, en_b, en_c, en_d, en_e, en_f = 16};
+
+class Rect
+{
+  int x, y;
+public:
+  void set (int, int);
+  int get () { return (x * y); };
+};
+
+void Rect::set (int a, int b)
+{
+  x = a;
+  y = b;
+}
+
+double print_circle (double r)
+{
+  double ret;
+  ret = 2 * PI *r;
+  cout << "circle r:" << r << " circle: " << ret << NEWLINE;
+  return ret;
+}
+
+void printp (p foo)
+{
+  cout << foo.w << ", " << foo.p << endl;
+}
+
+int substract (int a, int b=1)
+{
+  int ret;
+  ret = a - b;
+  return (ret);
+}
+
+template <class T, int N>
+class seq {
+  T mem [N];
+public:
+  void set (int x, T value);
+  T get (int x);
+};
+
+template <class T, int N>
+void seq<T,N>::set (int x, T val)
+{
+  mem[x] = val;
+}
+
+template <class T, int N>
+T seq<T,N>::get (int x)
+{
+  return mem[x];
+}
+
+seq <int, 13> ints;
+seq <Rect, 42> rects;
+
+int main ()
+{
+  b = new int [5];
+  cout << "Hello World!";
+  double c = print_circle (5.0);
+  int l = substract (c);
+  a.w = l;
+  a.p = 42.50;
+  printp (a);
+  delete[] b;
+  Rect rect;
+  rect.set (3, 4);
+  cout << "rect: " << rect.get () << endl;
+  return 0;
+}
diff --git a/tests/run-readelf-unknown.sh b/tests/run-readelf-unknown.sh
new file mode 100755
index 0000000..ea8aaf7
--- /dev/null
+++ b/tests/run-readelf-unknown.sh
@@ -0,0 +1,64 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles readelf.unknown.out
+status=0
+
+runtest() {
+  testrun ../src/readelf -N -w $1 \
+	| egrep -o "(unknown_[a-z]+_0x[0-9a-f]+)|(Unknown Language 0x[0-9a-f]+)" \
+	| sort -u > readelf.unknown.out ||
+  { echo "*** failure readelf -N -w $1"; status=1; }
+  if test -s readelf.unknown.out; then
+	echo "*** failure unknowns in $1"; cat readelf.unknown.out
+	status=1;
+  fi
+}
+
+runtest ../src/addr2line
+runtest ../src/elfcmp
+runtest ../src/elflint
+runtest ../src/findtextrel
+runtest ../src/ld
+runtest ../src/nm
+runtest ../src/objdump
+runtest ../src/readelf
+runtest ../src/size
+runtest ../src/strip
+runtest ../libelf/libelf.so
+runtest ../libdw/libdw.so
+runtest ../libasm/libasm.so
+runtest ../backends/libebl_alpha.so
+runtest ../backends/libebl_arm.so
+runtest ../backends/libebl_i386.so
+runtest ../backends/libebl_ia64.so
+runtest ../backends/libebl_ppc.so
+runtest ../backends/libebl_ppc64.so
+runtest ../backends/libebl_sh.so
+runtest ../backends/libebl_sparc.so
+runtest ../backends/libebl_x86_64.so
+
+# Might not exist if we don't have a c++ compiler around
+if test -f ./cpp-various; then
+  runtest ./cpp-various
+fi
+
+test_cleanup
+
+exit $status
diff --git a/tests/show-die-info.c b/tests/show-die-info.c
index cdd0d54..9e21b9f 100644
--- a/tests/show-die-info.c
+++ b/tests/show-die-info.c
@@ -27,192 +27,6 @@
 #include <unistd.h>
 
 
-static const char *tagnames[] =
-{
-  [DW_TAG_array_type] = "DW_TAG_array_type",
-  [DW_TAG_class_type] = "DW_TAG_class_type",
-  [DW_TAG_entry_point] = "DW_TAG_entry_point",
-  [DW_TAG_enumeration_type] = "DW_TAG_enumeration_type",
-  [DW_TAG_formal_parameter] = "DW_TAG_formal_parameter",
-  [DW_TAG_imported_declaration] = "DW_TAG_imported_declaration",
-  [DW_TAG_label] = "DW_TAG_label",
-  [DW_TAG_lexical_block] = "DW_TAG_lexical_block",
-  [DW_TAG_member] = "DW_TAG_member",
-  [DW_TAG_pointer_type] = "DW_TAG_pointer_type",
-  [DW_TAG_reference_type] = "DW_TAG_reference_type",
-  [DW_TAG_compile_unit] = "DW_TAG_compile_unit",
-  [DW_TAG_string_type] = "DW_TAG_string_type",
-  [DW_TAG_structure_type] = "DW_TAG_structure_type",
-  [DW_TAG_subroutine_type] = "DW_TAG_subroutine_type",
-  [DW_TAG_typedef] = "DW_TAG_typedef",
-  [DW_TAG_union_type] = "DW_TAG_union_type",
-  [DW_TAG_unspecified_parameters] = "DW_TAG_unspecified_parameters",
-  [DW_TAG_variant] = "DW_TAG_variant",
-  [DW_TAG_common_block] = "DW_TAG_common_block",
-  [DW_TAG_common_inclusion] = "DW_TAG_common_inclusion",
-  [DW_TAG_inheritance] = "DW_TAG_inheritance",
-  [DW_TAG_inlined_subroutine] = "DW_TAG_inlined_subroutine",
-  [DW_TAG_module] = "DW_TAG_module",
-  [DW_TAG_ptr_to_member_type] = "DW_TAG_ptr_to_member_type",
-  [DW_TAG_set_type] = "DW_TAG_set_type",
-  [DW_TAG_subrange_type] = "DW_TAG_subrange_type",
-  [DW_TAG_with_stmt] = "DW_TAG_with_stmt",
-  [DW_TAG_access_declaration] = "DW_TAG_access_declaration",
-  [DW_TAG_base_type] = "DW_TAG_base_type",
-  [DW_TAG_catch_block] = "DW_TAG_catch_block",
-  [DW_TAG_const_type] = "DW_TAG_const_type",
-  [DW_TAG_constant] = "DW_TAG_constant",
-  [DW_TAG_enumerator] = "DW_TAG_enumerator",
-  [DW_TAG_file_type] = "DW_TAG_file_type",
-  [DW_TAG_friend] = "DW_TAG_friend",
-  [DW_TAG_namelist] = "DW_TAG_namelist",
-  [DW_TAG_namelist_item] = "DW_TAG_namelist_item",
-  [DW_TAG_packed_type] = "DW_TAG_packed_type",
-  [DW_TAG_subprogram] = "DW_TAG_subprogram",
-  [DW_TAG_template_type_parameter] = "DW_TAG_template_type_parameter",
-  [DW_TAG_template_value_parameter] = "DW_TAG_template_value_parameter",
-  [DW_TAG_thrown_type] = "DW_TAG_thrown_type",
-  [DW_TAG_try_block] = "DW_TAG_try_block",
-  [DW_TAG_variant_part] = "DW_TAG_variant_part",
-  [DW_TAG_variable] = "DW_TAG_variable",
-  [DW_TAG_volatile_type] = "DW_TAG_volatile_type",
-  [DW_TAG_dwarf_procedure] = "DW_TAG_dwarf_procedure",
-  [DW_TAG_restrict_type] = "DW_TAG_restrict_type",
-  [DW_TAG_interface_type] = "DW_TAG_interface_type",
-  [DW_TAG_namespace] = "DW_TAG_namespace",
-  [DW_TAG_imported_module] = "DW_TAG_imported_module",
-  [DW_TAG_unspecified_type] = "DW_TAG_unspecified_type",
-  [DW_TAG_partial_unit] = "DW_TAG_partial_unit",
-  [DW_TAG_imported_unit] = "DW_TAG_imported_unit",
-  [DW_TAG_mutable_type] = "DW_TAG_mutable_type",
-  [DW_TAG_condition] = "DW_TAG_condition",
-  [DW_TAG_shared_type] = "DW_TAG_shared_type",
-};
-#define ntagnames (sizeof (tagnames) / sizeof (tagnames[0]))
-
-
-const struct
-{
-  int code;
-  const char *name;
-} attrs[] =
-{
-  { DW_AT_sibling, "sibling" },
-  { DW_AT_location, "location" },
-  { DW_AT_name, "name" },
-  { DW_AT_ordering, "ordering" },
-  { DW_AT_subscr_data, "subscr_data" },
-  { DW_AT_byte_size, "byte_size" },
-  { DW_AT_bit_offset, "bit_offset" },
-  { DW_AT_bit_size, "bit_size" },
-  { DW_AT_element_list, "element_list" },
-  { DW_AT_stmt_list, "stmt_list" },
-  { DW_AT_low_pc, "low_pc" },
-  { DW_AT_high_pc, "high_pc" },
-  { DW_AT_language, "language" },
-  { DW_AT_member, "member" },
-  { DW_AT_discr, "discr" },
-  { DW_AT_discr_value, "discr_value" },
-  { DW_AT_visibility, "visibility" },
-  { DW_AT_import, "import" },
-  { DW_AT_string_length, "string_length" },
-  { DW_AT_common_reference, "common_reference" },
-  { DW_AT_comp_dir, "comp_dir" },
-  { DW_AT_const_value, "const_value" },
-  { DW_AT_containing_type, "containing_type" },
-  { DW_AT_default_value, "default_value" },
-  { DW_AT_inline, "inline" },
-  { DW_AT_is_optional, "is_optional" },
-  { DW_AT_lower_bound, "lower_bound" },
-  { DW_AT_producer, "producer" },
-  { DW_AT_prototyped, "prototyped" },
-  { DW_AT_return_addr, "return_addr" },
-  { DW_AT_start_scope, "start_scope" },
-  { DW_AT_bit_stride, "bit_stride" },
-  { DW_AT_upper_bound, "upper_bound" },
-  { DW_AT_abstract_origin, "abstract_origin" },
-  { DW_AT_accessibility, "accessibility" },
-  { DW_AT_address_class, "address_class" },
-  { DW_AT_artificial, "artificial" },
-  { DW_AT_base_types, "base_types" },
-  { DW_AT_calling_convention, "calling_convention" },
-  { DW_AT_count, "count" },
-  { DW_AT_data_member_location, "data_member_location" },
-  { DW_AT_decl_column, "decl_column" },
-  { DW_AT_decl_file, "decl_file" },
-  { DW_AT_decl_line, "decl_line" },
-  { DW_AT_declaration, "declaration" },
-  { DW_AT_discr_list, "discr_list" },
-  { DW_AT_encoding, "encoding" },
-  { DW_AT_external, "external" },
-  { DW_AT_frame_base, "frame_base" },
-  { DW_AT_friend, "friend" },
-  { DW_AT_identifier_case, "identifier_case" },
-  { DW_AT_macro_info, "macro_info" },
-  { DW_AT_namelist_item, "namelist_item" },
-  { DW_AT_priority, "priority" },
-  { DW_AT_segment, "segment" },
-  { DW_AT_specification, "specification" },
-  { DW_AT_static_link, "static_link" },
-  { DW_AT_type, "type" },
-  { DW_AT_use_location, "use_location" },
-  { DW_AT_variable_parameter, "variable_parameter" },
-  { DW_AT_virtuality, "virtuality" },
-  { DW_AT_vtable_elem_location, "vtable_elem_location" },
-  { DW_AT_allocated, "allocated" },
-  { DW_AT_associated, "associated" },
-  { DW_AT_data_location, "data_location" },
-  { DW_AT_byte_stride, "byte_stride" },
-  { DW_AT_entry_pc, "entry_pc" },
-  { DW_AT_use_UTF8, "use_UTF8" },
-  { DW_AT_extension, "extension" },
-  { DW_AT_ranges, "ranges" },
-  { DW_AT_trampoline, "trampoline" },
-  { DW_AT_call_column, "call_column" },
-  { DW_AT_call_file, "call_file" },
-  { DW_AT_call_line, "call_line" },
-  { DW_AT_description, "description" },
-  { DW_AT_binary_scale, "binary_scale" },
-  { DW_AT_decimal_scale, "decimal_scale" },
-  { DW_AT_small, "small" },
-  { DW_AT_decimal_sign, "decimal_sign" },
-  { DW_AT_digit_count, "digit_count" },
-  { DW_AT_picture_string, "picture_string" },
-  { DW_AT_mutable, "mutable" },
-  { DW_AT_threads_scaled, "threads_scaled" },
-  { DW_AT_explicit, "explicit" },
-  { DW_AT_object_pointer, "object_pointer" },
-  { DW_AT_endianity, "endianity" },
-  { DW_AT_elemental, "elemental" },
-  { DW_AT_pure, "pure" },
-  { DW_AT_recursive, "recursive" },
-  { DW_AT_MIPS_fde, "MIPS_fde" },
-  { DW_AT_MIPS_loop_begin, "MIPS_loop_begin" },
-  { DW_AT_MIPS_tail_loop_begin, "MIPS_tail_loop_begin" },
-  { DW_AT_MIPS_epilog_begin, "MIPS_epilog_begin" },
-  { DW_AT_MIPS_loop_unroll_factor, "MIPS_loop_unroll_factor" },
-  { DW_AT_MIPS_software_pipeline_depth, "MIPS_software_pipeline_depth" },
-  { DW_AT_MIPS_linkage_name, "MIPS_linkage_name" },
-  { DW_AT_MIPS_stride, "MIPS_stride" },
-  { DW_AT_MIPS_abstract_name, "MIPS_abstract_name" },
-  { DW_AT_MIPS_clone_origin, "MIPS_clone_origin" },
-  { DW_AT_MIPS_has_inlines, "MIPS_has_inlines" },
-  { DW_AT_MIPS_stride_byte, "MIPS_stride_byte" },
-  { DW_AT_MIPS_stride_elem, "MIPS_stride_elem" },
-  { DW_AT_MIPS_ptr_dopetype, "MIPS_ptr_dopetype" },
-  { DW_AT_MIPS_allocatable_dopetype, "MIPS_allocatable_dopetype" },
-  { DW_AT_MIPS_assumed_shape_dopetype, "MIPS_assumed_shape_dopetype" },
-  { DW_AT_MIPS_assumed_size, "MIPS_assumed_size" },
-  { DW_AT_sf_names, "sf_names" },
-  { DW_AT_src_info, "src_info" },
-  { DW_AT_mac_info, "mac_info" },
-  { DW_AT_src_coords, "src_coords" },
-  { DW_AT_body_begin, "body_begin" },
-  { DW_AT_body_end, "body_end" },
-};
-#define nattrs (sizeof (attrs) / sizeof (attrs[0]))
-
-
 void
 handle (Dwarf *dbg, Dwarf_Die *die, int n)
 {
@@ -230,9 +44,8 @@ handle (Dwarf *dbg, Dwarf_Die *die, int n)
   tag = dwarf_tag (die);
   if (tag != DW_TAG_invalid)
     {
-      if (tag < ntagnames)
-	str = tagnames[tag];
-      else
+      str = dwarf_tag_string (tag);
+      if (str == NULL)
 	{
 	  snprintf (buf, sizeof buf, "%#x", tag);
 	  str = buf;
@@ -248,15 +61,15 @@ handle (Dwarf *dbg, Dwarf_Die *die, int n)
   off = dwarf_dieoffset (die);
   cuoff = dwarf_cuoffset (die);
 
-  printf ("%*s%s\n", n * 5, "", str);
+  printf ("%*sDW_TAG_%s\n", n * 5, "", str);
   printf ("%*s Name      : %s\n", n * 5, "", name);
   printf ("%*s Offset    : %lld\n", n * 5, "", (long long int) off);
   printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff);
 
   printf ("%*s Attrs     :", n * 5, "");
-  for (cnt = 0; cnt < nattrs; ++cnt)
-    if (dwarf_hasattr (die, attrs[cnt].code))
-      printf (" %s", attrs[cnt].name);
+  for (cnt = 0; cnt < 0xffff; ++cnt)
+    if (dwarf_hasattr (die, cnt))
+      printf (" %s", dwarf_attr_string (cnt));
   puts ("");
 
   if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0)

Attachment: commits.ksh
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]