From: Petr Machata Date: Tue, 21 Sep 2010 20:13:26 +0000 (+0200) Subject: dwarflint: New module checked_read X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0a3199478f08c8e8adab16e3e24566cec272b5a;p=thirdparty%2Felfutils.git dwarflint: New module checked_read - a bunch of functions that I couldn't place just right are there --- diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am index ea22753da..673d94f92 100644 --- a/dwarflint/Makefile.am +++ b/dwarflint/Makefile.am @@ -46,6 +46,7 @@ dwarflint_SOURCES = \ expected-at.cc expected.hh \ coverage.cc coverage.h \ readctx.c readctx.h \ + checked_read.cc checked_read.h \ pri.cc pri.hh \ messages.cc messages.h \ section_id.cc section_id.h \ diff --git a/dwarflint/check_debug_abbrev.cc b/dwarflint/check_debug_abbrev.cc index ad4c28432..8cff94e23 100644 --- a/dwarflint/check_debug_abbrev.cc +++ b/dwarflint/check_debug_abbrev.cc @@ -1,5 +1,5 @@ /* Pedantic checking of DWARF files - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009, 2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -32,6 +32,7 @@ #include "pri.hh" #include "tables.hh" #include "sections.hh" +#include "checked_read.h" #include #include @@ -522,3 +523,15 @@ check_debug_abbrev::~check_debug_abbrev () free (it->second.abbr); } } + +int +check_sibling_form (dwarf_version_h ver, uint64_t form) +{ + if (!dwver_form_allowed (ver, DW_AT_sibling, form)) + return -2; + else if (form == DW_FORM_ref_addr) + return -1; + else + return 0; +} + diff --git a/dwarflint/check_debug_abbrev.hh b/dwarflint/check_debug_abbrev.hh index 11cd1dec8..e9bb451c2 100644 --- a/dwarflint/check_debug_abbrev.hh +++ b/dwarflint/check_debug_abbrev.hh @@ -1,5 +1,5 @@ /* Low-level checking of .debug_abbrev. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009, 2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -48,4 +48,6 @@ public: ~check_debug_abbrev (); }; +int check_sibling_form (dwarf_version_h ver, uint64_t form); + #endif//DWARFLINT_CHECK_DEBUG_ABBREV_HH diff --git a/dwarflint/check_debug_aranges.cc b/dwarflint/check_debug_aranges.cc index 3eacb462e..4283254a7 100644 --- a/dwarflint/check_debug_aranges.cc +++ b/dwarflint/check_debug_aranges.cc @@ -38,6 +38,7 @@ #include "check_debug_info.hh" #include "check_debug_loc_range.hh" #include "cu_coverage.hh" +#include "checked_read.h" checkdescriptor const * check_debug_aranges::descriptor () diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc index 353f4a290..e6e91aea7 100644 --- a/dwarflint/check_debug_info.cc +++ b/dwarflint/check_debug_info.cc @@ -36,6 +36,7 @@ #include "pri.hh" #include "option.hh" #include "sections.hh" +#include "checked_read.h" #include "check_debug_loc_range.hh" #include "check_debug_abbrev.hh" #include "check_debug_info.hh" diff --git a/dwarflint/check_debug_line.cc b/dwarflint/check_debug_line.cc index e57fdb8d5..a4ea25514 100644 --- a/dwarflint/check_debug_line.cc +++ b/dwarflint/check_debug_line.cc @@ -27,6 +27,7 @@ #include "check_debug_info.hh" #include "sections.hh" #include "pri.hh" +#include "checked_read.h" #include #include "../libdw/known-dwarf.h" diff --git a/dwarflint/check_debug_loc_range.cc b/dwarflint/check_debug_loc_range.cc index c348fd3c3..da82e00c4 100644 --- a/dwarflint/check_debug_loc_range.cc +++ b/dwarflint/check_debug_loc_range.cc @@ -41,6 +41,7 @@ #include "check_debug_loc_range.hh" #include "check_debug_info.hh" #include "sections.hh" +#include "checked_read.h" #include "../src/dwarf-opcodes.h" #include "pri.hh" diff --git a/dwarflint/check_debug_pub.cc b/dwarflint/check_debug_pub.cc index 1db93bf9a..2a7c0dd3f 100644 --- a/dwarflint/check_debug_pub.cc +++ b/dwarflint/check_debug_pub.cc @@ -27,15 +27,7 @@ #include "check_debug_info.hh" #include "sections.hh" #include "pri.hh" - -namespace -{ - template - struct where xwhere (A a, B b) - { - return WHERE (a, b); - } -} +#include "checked_read.h" template check_debug_pub::check_debug_pub (checkstack &stack, dwarflint &lint) diff --git a/dwarflint/checked_read.cc b/dwarflint/checked_read.cc new file mode 100644 index 000000000..fd5edebf0 --- /dev/null +++ b/dwarflint/checked_read.cc @@ -0,0 +1,131 @@ +/* Pedantic checking of DWARF files + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + 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 + . */ + +#define __STDC_FORMAT_MACROS +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include "checked_read.h" +#include "messages.h" + +bool +read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, + int *offset_sizep, struct where *where) +{ + if (size32 == DWARF3_LENGTH_64_BIT) + { + if (!read_ctx_read_8ubyte (ctx, sizep)) + { + wr_error (where, ": can't read 64bit CU length.\n"); + return false; + } + + *offset_sizep = 8; + } + else if (size32 >= DWARF3_LENGTH_MIN_ESCAPE_CODE) + { + wr_error (where, ": unrecognized CU length escape value: " + "%" PRIx32 ".\n", size32); + return false; + } + else + { + *sizep = size32; + *offset_sizep = 4; + } + + return true; +} + +bool +read_address_size (struct read_ctx *ctx, + bool addr_64, + int *address_sizep, + struct where const *where) +{ + uint8_t address_size; + if (!read_ctx_read_ubyte (ctx, &address_size)) + { + wr_error (where, ": can't read address size.\n"); + return false; + } + + if (address_size != 4 && address_size != 8) + { + /* Keep going. Deduce the address size from ELF header, and try + to parse it anyway. */ + wr_error (where, + ": invalid address size: %d (only 4 or 8 allowed).\n", + address_size); + address_size = addr_64 ? 8 : 4; + } + else if ((address_size == 8) != addr_64) + /* Keep going, we may still be able to parse it. */ + wr_error (where, + ": CU reports address size of %d in %d-bit ELF.\n", + address_size, addr_64 ? 64 : 32); + + *address_sizep = address_size; + return true; +} + +bool +checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret, + struct where *where, const char *what) +{ + const unsigned char *ptr = ctx->ptr; + int st = read_ctx_read_uleb128 (ctx, ret); + if (st < 0) + wr_error (where, ": can't read %s.\n", what); + else if (st > 0) + { + char buf[19]; // 16 hexa digits, "0x", terminating zero + sprintf (buf, "%#" PRIx64, *ret); + wr_format_leb128_message (where, what, buf, ptr, ctx->ptr); + } + return st >= 0; +} + +bool +checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret, + struct where *where, const char *what) +{ + const unsigned char *ptr = ctx->ptr; + int st = read_ctx_read_sleb128 (ctx, ret); + if (st < 0) + wr_error (where, ": can't read %s.\n", what); + else if (st > 0) + { + char buf[20]; // sign, "0x", 16 hexa digits, terminating zero + int64_t val = *ret; + sprintf (buf, "%s%#" PRIx64, val < 0 ? "-" : "", val < 0 ? -val : val); + wr_format_leb128_message (where, what, buf, ptr, ctx->ptr); + } + return st >= 0; +} diff --git a/dwarflint/checked_read.h b/dwarflint/checked_read.h new file mode 100644 index 000000000..caeba92d7 --- /dev/null +++ b/dwarflint/checked_read.h @@ -0,0 +1,54 @@ +/* Pedantic checking of DWARF files + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + 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 + . */ + +#ifndef DWARFLINT_CHECKED_READ_HH +#define DWARFLINT_CHECKED_READ_HH + +#include "readctx.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +bool read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, + int *offset_sizep, struct where *where); + +bool read_address_size (struct read_ctx *ctx, + bool addr_64, + int *address_sizep, + struct where const *where); + +bool checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret, + struct where *where, const char *what); + +bool checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret, + struct where *where, const char *what); + +#ifdef __cplusplus +} +#endif + +#endif//DWARFLINT_CHECKED_READ_HH diff --git a/dwarflint/low.c b/dwarflint/low.c index 6a4e649a2..da078859e 100644 --- a/dwarflint/low.c +++ b/dwarflint/low.c @@ -60,52 +60,6 @@ necessary_alignment (uint64_t start, uint64_t length, uint64_t align) return address_aligned (start + length, align) && length < align; } -bool -checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret, - struct where *where, const char *what) -{ - const unsigned char *ptr = ctx->ptr; - int st = read_ctx_read_uleb128 (ctx, ret); - if (st < 0) - wr_error (where, ": can't read %s.\n", what); - else if (st > 0) - { - char buf[19]; // 16 hexa digits, "0x", terminating zero - sprintf (buf, "%#" PRIx64, *ret); - wr_format_leb128_message (where, what, buf, ptr, ctx->ptr); - } - return st >= 0; -} - -bool -checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret, - struct where *where, const char *what) -{ - const unsigned char *ptr = ctx->ptr; - int st = read_ctx_read_sleb128 (ctx, ret); - if (st < 0) - wr_error (where, ": can't read %s.\n", what); - else if (st > 0) - { - char buf[20]; // sign, "0x", 16 hexa digits, terminating zero - int64_t val = *ret; - sprintf (buf, "%s%#" PRIx64, val < 0 ? "-" : "", val < 0 ? -val : val); - wr_format_leb128_message (where, what, buf, ptr, ctx->ptr); - } - return st >= 0; -} - -int -check_sibling_form (dwarf_version_h ver, uint64_t form) -{ - if (!dwver_form_allowed (ver, DW_AT_sibling, form)) - return -2; - else if (form == DW_FORM_ref_addr) - return -1; - else - return 0; -} - bool is_location_attrib (uint64_t name) { diff --git a/dwarflint/low.h b/dwarflint/low.h index b10ce402f..0527c5c2d 100644 --- a/dwarflint/low.h +++ b/dwarflint/low.h @@ -120,11 +120,6 @@ extern "C" extern int check_sibling_form (dwarf_version_h ver, uint64_t form); extern bool is_location_attrib (uint64_t name); - bool checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret, - struct where *where, const char *what); - bool checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret, - struct where *where, const char *what); - struct abbrev_attrib { struct where where; diff --git a/dwarflint/readctx.c b/dwarflint/readctx.c index a8ca038b3..afd041dc9 100644 --- a/dwarflint/readctx.c +++ b/dwarflint/readctx.c @@ -318,67 +318,6 @@ read_ctx_eof (struct read_ctx *ctx) return !read_ctx_need_data (ctx, 1); } -bool -read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, - int *offset_sizep, struct where *where) -{ - if (size32 == DWARF3_LENGTH_64_BIT) - { - if (!read_ctx_read_8ubyte (ctx, sizep)) - { - wr_error (where, ": can't read 64bit CU length.\n"); - return false; - } - - *offset_sizep = 8; - } - else if (size32 >= DWARF3_LENGTH_MIN_ESCAPE_CODE) - { - wr_error (where, ": unrecognized CU length escape value: " - "%" PRIx32 ".\n", size32); - return false; - } - else - { - *sizep = size32; - *offset_sizep = 4; - } - - return true; -} - -bool -read_address_size (struct read_ctx *ctx, - bool addr_64, - int *address_sizep, - struct where const *where) -{ - uint8_t address_size; - if (!read_ctx_read_ubyte (ctx, &address_size)) - { - wr_error (where, ": can't read address size.\n"); - return false; - } - - if (address_size != 4 && address_size != 8) - { - /* Keep going. Deduce the address size from ELF header, and try - to parse it anyway. */ - wr_error (where, - ": invalid address size: %d (only 4 or 8 allowed).\n", - address_size); - address_size = addr_64 ? 8 : 4; - } - else if ((address_size == 8) != addr_64) - /* Keep going, we may still be able to parse it. */ - wr_error (where, - ": CU reports address size of %d in %d-bit ELF.\n", - address_size, addr_64 ? 64 : 32); - - *address_sizep = address_size; - return true; -} - static void update_off (struct read_ctx *ctx, uint64_t *ret_off) diff --git a/dwarflint/readctx.h b/dwarflint/readctx.h index 99b1c7da5..29fc451c0 100644 --- a/dwarflint/readctx.h +++ b/dwarflint/readctx.h @@ -29,9 +29,6 @@ #include #include "../libelf/libelf.h" -// xxx We don't really like this one -#include "where.h" - #ifdef __cplusplus extern "C" { @@ -77,18 +74,6 @@ const char *read_ctx_read_str (struct read_ctx *ctx); bool read_ctx_skip (struct read_ctx *ctx, uint64_t len); bool read_ctx_eof (struct read_ctx *ctx); -/* The following procedures build on the ones above and do their own - error reporting in addition. */ - -bool read_size_extra (struct read_ctx *ctx, uint32_t size32, - uint64_t *sizep, int *offset_sizep, - struct where *where); - -bool read_address_size (struct read_ctx *ctx, - bool addr_64, - int *address_sizep, - struct where const *where); - /* See if what remains in the read context is just a zero padding. If yes, return true. If it isn't, revert the read pointer back as if nothing had happened and return false. Furthermore, in any case,