summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2016-10-27 23:18:15 +0200
committerMark Wielaard <mjw@redhat.com>2016-10-28 13:25:23 +0200
commit454fd1fbbf845ccff0c5c37cd06c88b8101766c5 (patch)
treeb528010332fb566e73a87811c82fcad399a64ce8
parent7f33cfdeb8c879bb0591677159dda02428809028 (diff)
downloadelfutils-454fd1fbbf845ccff0c5c37cd06c88b8101766c5.tar.gz
libdw: Add dwarf_default_lower_bound.
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 <mjw@redhat.com>
-rw-r--r--libdw/ChangeLog11
-rw-r--r--libdw/Makefile.am4
-rw-r--r--libdw/dwarf_aggregate_size.c53
-rw-r--r--libdw/dwarf_default_lower_bound.c90
-rw-r--r--libdw/dwarf_error.c1
-rw-r--r--libdw/libdw.h6
-rw-r--r--libdw/libdw.map5
-rw-r--r--libdw/libdwP.h4
-rw-r--r--tests/ChangeLog9
-rw-r--r--tests/Makefile.am6
-rw-r--r--tests/dwarf_default_lower_bound.c83
11 files changed, 217 insertions, 55 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index e0141cc2..1e5a416b 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,14 @@
+2016-10-27 Mark Wielaard <mjw@redhat.com>
+
+ * 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.168): New section.
+ * libdwP.h: Add DWARF_E_UNKNOWN_LANGUAGE and
+ dwarf_default_lower_bound INTDECL.
+
2016-10-22 Mark Wielaard <mjw@redhat.com>
* dwarf.h: Add DW_LANG_OpenCL, DW_LANG_Modula3,
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 082d96c7..0f8d33fb 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 4645ff25..838468dd 100644
--- a/libdw/dwarf_aggregate_size.c
+++ b/libdw/dwarf_aggregate_size.c
@@ -95,56 +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:
- 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 00000000..98c82444
--- /dev/null
+++ b/libdw/dwarf_default_lower_bound.c
@@ -0,0 +1,90 @@
+/* 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:
+ *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 66fdc81a..939ec047 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 473e1a25..3a05595a 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -749,6 +749,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 83cb1d97..1559264e 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -338,3 +338,8 @@ ELFUTILS_0.167 {
dwelf_strent_str;
dwelf_strtab_free;
} ELFUTILS_0.165;
+
+ELFUTILS_0.168 {
+ global:
+ dwarf_default_lower_bound;
+} ELFUTILS_0.167; \ No newline at end of file
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 5d095a7e..6ad322c1 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 31904e76..bf5f7a4d 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,4 +1,11 @@
-2015-10-11 Akihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
+2016-10-27 Mark Wielaard <mjw@redhat.com>
+
+ * 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.
+
+2016-10-11 Akihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
* arextract.c: Remove sys/param.h include, add system.h include.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e331cb55..f186f1d0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -53,7 +53,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
buildid deleted deleted-lib.so aggregate_size vdsosyms \
getsrc_die strptr newdata elfstrtab dwfl-proc-attach \
elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \
- elfgetzdata elfputzdata zstrptr emptyfile vendorelf
+ elfgetzdata elfputzdata zstrptr emptyfile vendorelf \
+ dwarf_default_lower_bound
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -127,7 +128,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
+ emptyfile vendorelf dwarf_default_lower_bound
if !BIARCH
export ELFUTILS_DISABLE_BIARCH = 1
@@ -487,6 +488,7 @@ elfputzdata_LDADD = $(libelf)
zstrptr_LDADD = $(libelf)
emptyfile_LDADD = $(libelf)
vendorelf_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 00000000..d57424fc
--- /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;
+}