[PATCH 5/9] libdw: Add dwarf_default_lower_bound.

Mark Wielaard mark@klomp.org
Wed Jul 26 22:08:00 GMT 2017


Add dwarf_default_lower_bound to get the default lower bound for a language
when not given as attribute for an subrange type. Implementation extracted
from dwarf_aggregate_size.

Add a test to check all known language codes are handled.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 ChangeLog                         |  4 ++
 NEWS                              |  1 +
 libdw/ChangeLog                   | 11 +++++
 libdw/Makefile.am                 |  4 +-
 libdw/dwarf_aggregate_size.c      | 54 ++---------------------
 libdw/dwarf_default_lower_bound.c | 91 +++++++++++++++++++++++++++++++++++++++
 libdw/dwarf_error.c               |  1 +
 libdw/libdw.h                     |  6 +++
 libdw/libdw.map                   |  1 +
 libdw/libdwP.h                    |  4 +-
 tests/ChangeLog                   |  7 +++
 tests/Makefile.am                 |  5 ++-
 tests/dwarf_default_lower_bound.c | 83 +++++++++++++++++++++++++++++++++++
 13 files changed, 217 insertions(+), 55 deletions(-)
 create mode 100644 libdw/dwarf_default_lower_bound.c
 create mode 100644 tests/dwarf_default_lower_bound.c

diff --git a/ChangeLog b/ChangeLog
index d133061..25944f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention new dwarf_default_lower_bound function.
+
 2017-07-25  Mark Wielaard  <mark@klomp.org>
 
 	* NEWS: Mention new DWARF5 attributes, tags, character encodings
diff --git a/NEWS b/NEWS
index 2039cfe..5bf0a4d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Version 0.170
 
 libdw: Added new DWARF5 attribute, tag, character encodings constants and
        language codes to dwarf.h.
+       New function dwarf_default_lower_bound.
 
 strip: Add -R, --remove-section=SECTION and --keep-section=SECTION.
 
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 39a9c1d..ee7dc92 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,5 +1,16 @@
 2017-07-26  Mark Wielaard  <mark@klomp.org>
 
+	* dwarf_default_lower_bound.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_default_lower_bound.c.
+	* dwarf_aggregate_size.c (array_size): Use dwarf_default_lower_bound.
+	* dwarf_error.c (errmsgs): Add DWARF_E_UNKNOWN_LANGUAGE.
+	* libdw.h: Add dwarf_default_lower_bound.
+	* libdw.map (ELFUTILS_0.170): Add dwarf_default_lower_bound.
+	* libdwP.h: Add DWARF_E_UNKNOWN_LANGUAGE and
+	dwarf_default_lower_bound INTDECL.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
 	* dwarf.h: Add DW_LANG_OpenCL, DW_LANG_Modula3,
 	DW_LANG_C_plus_plus_03, DW_LANG_OCaml, DW_LANG_Rust, DW_LANG_Swift,
 	DW_LANG_Julia, DW_LANG_Dylan, DW_LANG_RenderScript, DW_LANG_BLISS.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index ad031b1..ff8c291 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, 2012, 2014 Red Hat, Inc.
+## Copyright (C) 2002-2010, 2012, 2014, 2016 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -89,7 +89,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
 		  dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c \
 		  dwarf_getlocation_die.c dwarf_getlocation_attr.c \
 		  dwarf_getalt.c dwarf_setalt.c dwarf_cu_getdwarf.c \
-		  dwarf_cu_die.c dwarf_peel_type.c
+		  dwarf_cu_die.c dwarf_peel_type.c dwarf_default_lower_bound.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
index 0472a9b..838468d 100644
--- a/libdw/dwarf_aggregate_size.c
+++ b/libdw/dwarf_aggregate_size.c
@@ -95,57 +95,11 @@ array_size (Dwarf_Die *die, Dwarf_Word *size,
 		}
 	      else
 		{
-		  /* Determine default lower bound from language,
-		     as per "4.12 Subrange Type Entries".  */
 		  Dwarf_Die cu = CUDIE (die->cu);
-		  switch (INTUSE(dwarf_srclang) (&cu))
-		    {
-		    case DW_LANG_C:
-		    case DW_LANG_C89:
-		    case DW_LANG_C99:
-		    case DW_LANG_C11:
-		    case DW_LANG_C_plus_plus:
-		    case DW_LANG_C_plus_plus_03:
-		    case DW_LANG_C_plus_plus_11:
-		    case DW_LANG_C_plus_plus_14:
-		    case DW_LANG_ObjC:
-		    case DW_LANG_ObjC_plus_plus:
-		    case DW_LANG_Java:
-		    case DW_LANG_D:
-		    case DW_LANG_Python:
-		    case DW_LANG_UPC:
-		    case DW_LANG_OpenCL:
-		    case DW_LANG_Go:
-		    case DW_LANG_Haskell:
-		    case DW_LANG_OCaml:
-		    case DW_LANG_Rust:
-		    case DW_LANG_Swift:
-		    case DW_LANG_Dylan:
-		    case DW_LANG_RenderScript:
-		    case DW_LANG_BLISS:
-		      lower = 0;
-		      break;
-
-		    case DW_LANG_Ada83:
-		    case DW_LANG_Ada95:
-		    case DW_LANG_Cobol74:
-		    case DW_LANG_Cobol85:
-		    case DW_LANG_Fortran77:
-		    case DW_LANG_Fortran90:
-		    case DW_LANG_Fortran95:
-		    case DW_LANG_Fortran03:
-		    case DW_LANG_Fortran08:
-		    case DW_LANG_Pascal83:
-		    case DW_LANG_Modula2:
-		    case DW_LANG_Modula3:
-		    case DW_LANG_PLI:
-		    case DW_LANG_Julia:
-		      lower = 1;
-		      break;
-
-		    default:
-		      return -1;
-		    }
+		  int lang = INTUSE(dwarf_srclang) (&cu);
+		  if (lang == -1
+		      || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
+		    return -1;
 		}
 	      if (unlikely (lower > upper))
 		return -1;
diff --git a/libdw/dwarf_default_lower_bound.c b/libdw/dwarf_default_lower_bound.c
new file mode 100644
index 0000000..a33a343
--- /dev/null
+++ b/libdw/dwarf_default_lower_bound.c
@@ -0,0 +1,91 @@
+/* Get the default subrange lower bound for a given language.
+   Copyright (C) 2016 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 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 <dwarf.h>
+#include "libdwP.h"
+
+/* Determine default lower bound from language, as per the DWARF5
+   "Subrange Type Entries" table.  */
+int
+dwarf_default_lower_bound (int lang, Dwarf_Sword *result)
+{
+  switch (lang)
+    {
+    case DW_LANG_C:
+    case DW_LANG_C89:
+    case DW_LANG_C99:
+    case DW_LANG_C11:
+    case DW_LANG_C_plus_plus:
+    case DW_LANG_C_plus_plus_03:
+    case DW_LANG_C_plus_plus_11:
+    case DW_LANG_C_plus_plus_14:
+    case DW_LANG_ObjC:
+    case DW_LANG_ObjC_plus_plus:
+    case DW_LANG_Java:
+    case DW_LANG_D:
+    case DW_LANG_Python:
+    case DW_LANG_UPC:
+    case DW_LANG_OpenCL:
+    case DW_LANG_Go:
+    case DW_LANG_Haskell:
+    case DW_LANG_OCaml:
+    case DW_LANG_Rust:
+    case DW_LANG_Swift:
+    case DW_LANG_Dylan:
+    case DW_LANG_RenderScript:
+    case DW_LANG_BLISS:
+      *result = 0;
+      return 0;
+
+    case DW_LANG_Ada83:
+    case DW_LANG_Ada95:
+    case DW_LANG_Cobol74:
+    case DW_LANG_Cobol85:
+    case DW_LANG_Fortran77:
+    case DW_LANG_Fortran90:
+    case DW_LANG_Fortran95:
+    case DW_LANG_Fortran03:
+    case DW_LANG_Fortran08:
+    case DW_LANG_Pascal83:
+    case DW_LANG_Modula2:
+    case DW_LANG_Modula3:
+    case DW_LANG_PLI:
+    case DW_LANG_Julia:
+      *result = 1;
+      return 0;
+
+    default:
+      __libdw_seterrno (DWARF_E_UNKNOWN_LANGUAGE);
+      return -1;
+    }
+}
+INTDEF (dwarf_default_lower_bound)
diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c
index 66fdc81..939ec04 100644
--- a/libdw/dwarf_error.c
+++ b/libdw/dwarf_error.c
@@ -95,6 +95,7 @@ static const char *errmsgs[] =
     [DWARF_E_NO_ALT_DEBUGLINK] = N_("no alternative debug link found"),
     [DWARF_E_INVALID_OPCODE] = N_("invalid opcode"),
     [DWARF_E_NOT_CUDIE] = N_("not a CU (unit) DIE"),
+    [DWARF_E_UNKNOWN_LANGUAGE] = N_("unknown language code")
   };
 #define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
 
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 4903b55..49c4ebb 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -733,6 +733,12 @@ extern int dwarf_getlocation_attr (Dwarf_Attribute *attr,
    For DW_TAG_array_type it can apply much more complex rules.  */
 extern int dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size);
 
+/* Given a language code, as returned by dwarf_srclan, get the default
+   lower bound for a subrange type without a lower bound attribute.
+   Returns zero on success or -1 on failure when the given language
+   wasn't recognized.  */
+extern int dwarf_default_lower_bound (int lang, Dwarf_Sword *result)
+  __nonnull_attribute__ (2);
 
 /* Return scope DIEs containing PC address.
    Sets *SCOPES to a malloc'd array of Dwarf_Die structures,
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 44e096a..1430705 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -341,5 +341,6 @@ ELFUTILS_0.167 {
 
 ELFUTILS_0.170 {
   global:
+    dwarf_default_lower_bound;
     dwarf_line_file;
 } ELFUTILS_0.167;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 5d095a7..6ad322c 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -1,5 +1,5 @@
 /* Internal definitions for libdwarf.
-   Copyright (C) 2002-2011, 2013-2015 Red Hat, Inc.
+   Copyright (C) 2002-2011, 2013-2016 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -130,6 +130,7 @@ enum
   DWARF_E_NO_ALT_DEBUGLINK,
   DWARF_E_INVALID_OPCODE,
   DWARF_E_NOT_CUDIE,
+  DWARF_E_UNKNOWN_LANGUAGE,
 };
 
 
@@ -764,6 +765,7 @@ INTDECL (dwarf_attr_integrate)
 INTDECL (dwarf_begin)
 INTDECL (dwarf_begin_elf)
 INTDECL (dwarf_child)
+INTDECL (dwarf_default_lower_bound)
 INTDECL (dwarf_dieoffset)
 INTDECL (dwarf_diename)
 INTDECL (dwarf_end)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 519f25a..fa3f94e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_default_lower_bound.c: New test.
+	* Makefile.am (check_PROGRAMS): Add dwarf_default_lower_bound.
+	(TESTS): Likewise.
+	(dwarf_default_lower_bound_LDADD): New variable.
+
 2017-07-21  Mark Wielaard  <mark@klomp.org>
 
 	* get-lines.c (main): Add dwarf_line_file test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 407c051..3735084 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -55,7 +55,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
 		  getsrc_die strptr newdata elfstrtab dwfl-proc-attach \
 		  elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \
 		  elfgetzdata elfputzdata zstrptr emptyfile vendorelf \
-		  fillfile
+		  fillfile dwarf_default_lower_bound
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
 	    asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -135,7 +135,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-elfgetzdata.sh run-elfputzdata.sh run-zstrptr.sh \
 	run-compress-test.sh \
 	run-readelf-zdebug.sh run-readelf-zdebug-rel.sh \
-	emptyfile vendorelf fillfile
+	emptyfile vendorelf fillfile dwarf_default_lower_bound
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -505,6 +505,7 @@ zstrptr_LDADD = $(libelf)
 emptyfile_LDADD = $(libelf)
 vendorelf_LDADD = $(libelf)
 fillfile_LDADD = $(libelf)
+dwarf_default_lower_bound_LDADD = $(libdw)
 
 # We want to test the libelf header against the system elf.h header.
 # Don't include any -I CPPFLAGS.
diff --git a/tests/dwarf_default_lower_bound.c b/tests/dwarf_default_lower_bound.c
new file mode 100644
index 0000000..d57424f
--- /dev/null
+++ b/tests/dwarf_default_lower_bound.c
@@ -0,0 +1,83 @@
+/* Test all DW_LANG constants are handled by dwarf_default_lower_bound.
+
+   Copyright (C) 2016 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/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include "../libdw/known-dwarf.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+test_lang (const char *name, int lang)
+{
+  Dwarf_Sword low;
+  int res = dwarf_default_lower_bound (lang, &low);
+
+  /* Assembler is special, it doesn't really have arrays.  */
+  if (lang == DW_LANG_Mips_Assembler)
+    {
+      if (res == 0)
+	{
+	  printf ("%s shouldn't have a known lower bound\n", name);
+	  exit (-1);
+	}
+      printf ("%s: <unknown>\n", name);
+      return;
+    }
+
+  if (res != 0)
+    {
+      printf ("dwarf_default_lower_bound failed (%d) for %s\n", res, name);
+      exit (-1);
+    }
+
+  /* All currently known lower bounds are either zero or one, but
+     they don't have to.  Update test once one is a different value.  */
+  if (low != 0 && low != 1)
+    {
+      printf ("unexpected lower bound %" PRId64 " for %s\n", low, name);
+      exit (-1);
+    }
+
+  printf ("%s: %" PRId64 "\n", name, low);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+  Dwarf_Sword low;
+  /* Bad language code must fail.  */
+  if (dwarf_default_lower_bound (-1, &low) == 0)
+    {
+      printf ("Bad lang code -1 succeeded (%" PRId64 ")\n", low);
+      exit (-1);
+    }
+
+  /* Test all known language codes.  */
+#define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) test_lang (#NAME, CODE);
+  DWARF_ALL_KNOWN_DW_LANG
+#undef DWARF_ONE_KNOWN_DW_LANG
+
+  return 0;
+}
-- 
1.8.3.1



More information about the Elfutils-devel mailing list