From ecb3813b1d64a01570bfda1e462a52cc25526fd3 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Sat, 31 Jan 2009 22:39:14 +0100 Subject: [PATCH] Split dwarflint into C and C++ part * high-level checks can be written in C++ using shiny new libdw interfaces --- src/Makefile.am | 3 + src/dwarflint-hl.cc | 45 +++++++++++++ src/dwarflint.c | 155 +++++++----------------------------------- src/dwarflint.h | 159 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+), 132 deletions(-) create mode 100644 src/dwarflint-hl.cc create mode 100644 src/dwarflint.h diff --git a/src/Makefile.am b/src/Makefile.am index ffb58cb87..7e2e9aad8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,6 +88,9 @@ libdwplusplus_SOURCES = ../libdw/c++/values.cc ../libdw/c++/known.cc \ dwarfcmp_SOURCES = dwarfcmp.cc dwarfcmp_SOURCES += $(libdwplusplus_SOURCES) +dwarflint_SOURCES = dwarflint.c dwarflint-hl.cc +dwarflint_SOURCES += $(libdwplusplus_SOURCES) # XXX drop when we have the DSO + noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \ ldscript.h xelf.h unaligned.h diff --git a/src/dwarflint-hl.cc b/src/dwarflint-hl.cc new file mode 100644 index 000000000..1b7a1ab49 --- /dev/null +++ b/src/dwarflint-hl.cc @@ -0,0 +1,45 @@ +/* Pedantic checking of DWARF files. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Petr Machata , 2009. + + Red Hat elfutils 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; version 2 of the License. + + Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include "dwarflint.h" +#include "c++/dwarf" +#include "../libdw/libdwP.h" + + +bool +check_aranges_hl (Dwarf *dwarf) +{ + return dwarf != NULL; +} diff --git a/src/dwarflint.c b/src/dwarflint.c index 20b38131b..2f8e7f06f 100644 --- a/src/dwarflint.c +++ b/src/dwarflint.c @@ -48,6 +48,7 @@ #include "../libdw/dwarf.h" #include "../libdw/libdwP.h" #include "dwarfstrings.h" +#include "dwarflint.h" /* Bug report address. */ const char *argp_program_bug_address = PACKAGE_BUGREPORT; @@ -95,85 +96,6 @@ static void process_file (int fd, Dwarf *dwarf, const char *fname, size_t size, bool only_one); -/* Functions and data structures describing location in Dwarf. */ - -enum section_id -{ - sec_invalid = 0, - sec_info, - sec_abbrev, - sec_aranges, - sec_pubnames, - sec_pubtypes, - sec_str, - sec_loc, - sec_locexpr, /* Not a section, but a portion of file that contains a - location expression. */ - sec_ranges, -}; - -struct where -{ - enum section_id section; - uint64_t addr1; // E.g. a CU offset. - uint64_t addr2; // E.g. a DIE address. - uint64_t addr3; // E.g. an attribute. - struct where *ref; // Related reference, e.g. an abbrev related to given DIE. - struct where *next; // Hierarchically superior location. -}; - -#define WHERE(SECTION, NEXT) \ - ((struct where) \ - {(SECTION), (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, NULL, NEXT}) - -static const char *where_fmt (struct where *wh, char *ptr); -static void where_fmt_chain (struct where *wh, const char *severity); -static void where_reset_1 (struct where *wh, uint64_t addr); -static void where_reset_2 (struct where *wh, uint64_t addr); -static void where_reset_3 (struct where *wh, uint64_t addr); - - -/* Functions and data structures for emitting various types of - messages. */ - -enum message_category -{ - mc_none = 0, - - /* Severity: */ - mc_impact_1 = 0x1, // no impact on the consumer - mc_impact_2 = 0x2, // still no impact, but suspicious or worth mentioning - mc_impact_3 = 0x4, // some impact - mc_impact_4 = 0x8, // high impact - mc_impact_all= 0xf, // all severity levels - mc_impact_2p = 0xe, // 2+ - mc_impact_3p = 0xc, // 3+ - - /* Accuracy: */ - mc_acc_bloat = 0x10, // unnecessary constructs (e.g. unreferenced strings) - mc_acc_suboptimal= 0x20, // suboptimal construct (e.g. lack of siblings) - mc_acc_all = 0x30, // all accuracy options - - /* Various: */ - mc_error = 0x40, // turn the message into an error - - /* Area: */ - mc_leb128 = 0x100, // ULEB/SLEB storage - mc_abbrevs = 0x200, // abbreviations and abbreviation tables - mc_die_rel = 0x400, // DIE relationship - mc_die_other = 0x800, // other messages related to DIEs - mc_info = 0x1000, // messages related to .debug_info, but not particular DIEs - mc_strings = 0x2000, // string table - mc_aranges = 0x4000, // address ranges table - mc_elf = 0x8000, // ELF structure, e.g. missing optional sections - mc_pubtables = 0x10000, // table of public names/types - mc_pubtypes = 0x20000, // .debug_pubtypes presence - mc_loc = 0x40000, // messages related to .debug_loc - mc_ranges = 0x80000, // messages related to .debug_ranges - mc_other = 0x100000, // messages unrelated to any of the above - mc_all = 0xffffff00, // all areas -}; - struct message_criteria { enum message_category accept; /* cat & accept must be != 0 */ @@ -220,7 +142,7 @@ wr_vwarning (struct where *wh, const char *format, va_list ap) ++error_count; } -static void __attribute__ ((format (printf, 2, 3))) +void wr_error (struct where *wh, const char *format, ...) { va_list ap; @@ -229,7 +151,7 @@ wr_error (struct where *wh, const char *format, ...) va_end (ap); } -static void __attribute__ ((format (printf, 2, 3))) +void wr_warning (struct where *wh, const char *format, ...) { va_list ap; @@ -238,7 +160,7 @@ wr_warning (struct where *wh, const char *format, ...) va_end (ap); } -static void __attribute__ ((format (printf, 3, 4))) +void wr_message (enum message_category category, struct where *wh, const char *format, ...) { @@ -254,7 +176,7 @@ wr_message (enum message_category category, struct where *wh, va_end (ap); } -static void +void wr_format_padding_message (enum message_category category, struct where *wh, uint64_t start, uint64_t end, char *kind) @@ -263,7 +185,7 @@ wr_format_padding_message (enum message_category category, ": 0x%" PRIx64 "..0x%" PRIx64 ": %s.\n", start, end, kind); } -static void +void wr_format_leb128_message (int st, struct where *wh, const char *what) { enum message_category category = mc_leb128 | mc_acc_bloat | mc_impact_3; @@ -276,7 +198,7 @@ wr_format_leb128_message (int st, struct where *wh, const char *what) wr_message (category, wh, ": unnecessarily long encoding of %s.\n", what); } -static void +void wr_message_padding_0 (enum message_category category, struct where *wh, uint64_t start, uint64_t end) @@ -286,7 +208,7 @@ wr_message_padding_0 (enum message_category category, "unnecessary padding with zero bytes"); } -static void +void wr_message_padding_n0 (enum message_category category, struct where *wh, uint64_t start, uint64_t end) @@ -568,39 +490,6 @@ static void ref_record_add (struct ref_record *rr, uint64_t addr, struct where * static void ref_record_free (struct ref_record *rr); -/* Functions and data structures for handling of address range - coverage. We use that to find holes of unused bytes in DWARF string - table. */ - -typedef uint_fast32_t coverage_emt_type; -static const size_t coverage_emt_size = sizeof (coverage_emt_type); -static const size_t coverage_emt_bits = 8 * sizeof (coverage_emt_type); - -struct coverage -{ - size_t alloc; - uint64_t size; - coverage_emt_type *buf; -}; - -struct hole_info -{ - enum section_id section; - enum message_category category; - unsigned align; - void *d_buf; -}; - -static void coverage_init (struct coverage *ar, uint64_t size); -static void coverage_add (struct coverage *ar, uint64_t begin, uint64_t end); -static bool coverage_is_covered (struct coverage *ar, uint64_t address); -static void coverage_find_holes (struct coverage *ar, - void (*cb)(uint64_t begin, uint64_t end, void *data), - void *data); -static void found_hole (uint64_t begin, uint64_t end, void *data); -static void coverage_free (struct coverage *ar); - - /* Functions and data structures for CU handling. */ struct cu @@ -649,7 +538,8 @@ static bool check_pub_structural (struct read_ctx *ctx, enum section_id sec); -static const char *where_fmt (struct where *wh, char *ptr) +const char * +where_fmt (struct where *wh, char *ptr) { if (wh == NULL) return ""; @@ -755,7 +645,7 @@ static const char *where_fmt (struct where *wh, char *ptr) return ptr; } -static void +void where_fmt_chain (struct where *wh, const char *severity) { if (wh != NULL) @@ -764,21 +654,21 @@ where_fmt_chain (struct where *wh, const char *severity) severity, where_fmt (it, NULL)); } -static void +void where_reset_1 (struct where *wh, uint64_t addr) { wh->addr1 = addr; wh->addr2 = wh->addr3 = (uint64_t)-1; } -static void +void where_reset_2 (struct where *wh, uint64_t addr) { wh->addr2 = addr; wh->addr3 = (uint64_t)-1; } -static void +void where_reset_3 (struct where *wh, uint64_t addr) { wh->addr3 = addr; @@ -865,7 +755,8 @@ process_file (int fd __attribute__((unused)), if (aranges_data != NULL) { read_ctx_init (&ctx, dwarf, aranges_data); - check_aranges_structural (&ctx, cu_chain); + if (check_aranges_structural (&ctx, cu_chain)) + check_aranges_hl (dwarf); } if (pubnames_data != NULL) @@ -1578,7 +1469,7 @@ ref_record_free (struct ref_record *rr) } -static void +void coverage_init (struct coverage *ar, uint64_t size) { size_t ctemts = size / coverage_emt_bits + 1; @@ -1587,7 +1478,7 @@ coverage_init (struct coverage *ar, uint64_t size) ar->size = size; } -static void +void coverage_add (struct coverage *ar, uint64_t begin, uint64_t end) { assert (ar); @@ -1613,7 +1504,7 @@ coverage_add (struct coverage *ar, uint64_t begin, uint64_t end) } } -static bool +bool coverage_is_covered (struct coverage *ar, uint64_t address) { assert (ar); @@ -1625,7 +1516,7 @@ coverage_is_covered (struct coverage *ar, uint64_t address) return !!(ar->buf[bi] & bm); } -static bool +bool coverage_pristine (struct coverage *ar, uint64_t begin, uint64_t length) { for (uint64_t i = 0; i < length; ++i) @@ -1634,7 +1525,7 @@ coverage_pristine (struct coverage *ar, uint64_t begin, uint64_t length) return true; } -static void +void coverage_find_holes (struct coverage *ar, void (*cb)(uint64_t begin, uint64_t end, void *user), void *user) @@ -1685,7 +1576,7 @@ coverage_find_holes (struct coverage *ar, hole_end (ar->size); } -static void +void found_hole (uint64_t begin, uint64_t end, void *data) { struct hole_info *info = (struct hole_info *)data; @@ -1714,7 +1605,7 @@ found_hole (uint64_t begin, uint64_t end, void *data) begin, end); } -static void +void coverage_free (struct coverage *ar) { free (ar->buf); diff --git a/src/dwarflint.h b/src/dwarflint.h new file mode 100644 index 000000000..ee1ced918 --- /dev/null +++ b/src/dwarflint.h @@ -0,0 +1,159 @@ +#ifndef DWARFLINT_HL_H +#define DWARFLINT_HL_H + +#include "../libdw/libdw.h" + +#ifdef __cplusplus +extern "C" +{ +#else +# include +#endif + + /* Entry points for high-level checks. */ + extern bool check_aranges_hl (Dwarf *dwarf); + + + /* Functions and data structures describing location in Dwarf. */ + + enum section_id + { + sec_invalid = 0, + sec_info, + sec_abbrev, + sec_aranges, + sec_pubnames, + sec_pubtypes, + sec_str, + sec_loc, + sec_locexpr, /* Not a section, but a portion of file that contains a + location expression. */ + sec_ranges, + }; + + struct where + { + enum section_id section; + uint64_t addr1; // E.g. a CU offset. + uint64_t addr2; // E.g. a DIE address. + uint64_t addr3; // E.g. an attribute. + struct where *ref; // Related reference, e.g. an abbrev related to given DIE. + struct where *next; // Hierarchically superior location. + }; + +# define WHERE(SECTION, NEXT) \ + ((struct where) \ + {(SECTION), (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, NULL, NEXT}) + + extern const char *where_fmt (struct where *wh, char *ptr); + extern void where_fmt_chain (struct where *wh, const char *severity); + extern void where_reset_1 (struct where *wh, uint64_t addr); + extern void where_reset_2 (struct where *wh, uint64_t addr); + extern void where_reset_3 (struct where *wh, uint64_t addr); + + + /* Functions and data structures for emitting various types of + messages. */ + + enum message_category + { + mc_none = 0, + + /* Severity: */ + mc_impact_1 = 0x1, // no impact on the consumer + mc_impact_2 = 0x2, // still no impact, but suspicious or worth mentioning + mc_impact_3 = 0x4, // some impact + mc_impact_4 = 0x8, // high impact + mc_impact_all= 0xf, // all severity levels + mc_impact_2p = 0xe, // 2+ + mc_impact_3p = 0xc, // 3+ + + /* Accuracy: */ + mc_acc_bloat = 0x10, // unnecessary constructs (e.g. unreferenced strings) + mc_acc_suboptimal= 0x20, // suboptimal construct (e.g. lack of siblings) + mc_acc_all = 0x30, // all accuracy options + + /* Various: */ + mc_error = 0x40, // turn the message into an error + + /* Area: */ + mc_leb128 = 0x100, // ULEB/SLEB storage + mc_abbrevs = 0x200, // abbreviations and abbreviation tables + mc_die_rel = 0x400, // DIE relationship + mc_die_other = 0x800, // other messages related to DIEs + mc_info = 0x1000, // messages related to .debug_info, but not particular DIEs + mc_strings = 0x2000, // string table + mc_aranges = 0x4000, // address ranges table + mc_elf = 0x8000, // ELF structure, e.g. missing optional sections + mc_pubtables = 0x10000, // table of public names/types + mc_pubtypes = 0x20000, // .debug_pubtypes presence + mc_loc = 0x40000, // messages related to .debug_loc + mc_ranges = 0x80000, // messages related to .debug_ranges + mc_other = 0x100000, // messages unrelated to any of the above + mc_all = 0xffffff00, // all areas + }; + + extern void wr_error (struct where *wh, const char *format, ...) + __attribute__ ((format (printf, 2, 3))); + + extern void wr_warning (struct where *wh, const char *format, ...) + __attribute__ ((format (printf, 2, 3))); + + extern void wr_message (enum message_category category, struct where *wh, + const char *format, ...) + __attribute__ ((format (printf, 3, 4))); + + extern void wr_format_padding_message (enum message_category category, + struct where *wh, + uint64_t start, uint64_t end, + char *kind); + + extern void wr_format_leb128_message (int st, struct where *wh, + const char *what); + + extern void wr_message_padding_0 (enum message_category category, + struct where *wh, + uint64_t start, uint64_t end); + + extern void wr_message_padding_n0 (enum message_category category, + struct where *wh, + uint64_t start, uint64_t end); + + + /* Functions and data structures for handling of address range + coverage. We use that to find holes of unused bytes in DWARF + string table. */ + + typedef uint_fast32_t coverage_emt_type; + static const size_t coverage_emt_size = sizeof (coverage_emt_type); + static const size_t coverage_emt_bits = 8 * sizeof (coverage_emt_type); + + struct coverage + { + size_t alloc; + uint64_t size; + coverage_emt_type *buf; + }; + + struct hole_info + { + enum section_id section; + enum message_category category; + unsigned align; + void *d_buf; + }; + + void coverage_init (struct coverage *ar, uint64_t size); + void coverage_add (struct coverage *ar, uint64_t begin, uint64_t end); + bool coverage_is_covered (struct coverage *ar, uint64_t address); + void coverage_find_holes (struct coverage *ar, + void (*cb)(uint64_t begin, uint64_t end, void *data), + void *data); + void found_hole (uint64_t begin, uint64_t end, void *data); + void coverage_free (struct coverage *ar); + +#ifdef __cplusplus +} +#endif + +#endif/*DWARFLINT_HL_H*/ -- 2.47.2