checks.cc checks.hh checks.ii \
sections.cc sections.hh sections.ii \
highlevel_check.cc highlevel_check.hh \
+ cu_coverage.cc cu_coverage.hh cu_coverage.ii \
check_debug_abbrev.cc check_debug_abbrev.hh check_debug_abbrev.ii \
check_debug_info.cc check_debug_info.hh check_debug_info.ii \
check_debug_line.cc \
check_debug_pub.cc \
- check_debug_loc_range.cc check_debug_loc_range.hh \
+ check_debug_loc_range.cc check_debug_loc_range.hh check_debug_loc_range.ii \
check_debug_aranges.cc check_debug_aranges.hh \
check_matching_ranges.cc \
check_range_out_of_scope.cc \
#include "check_debug_aranges.hh"
#include "check_debug_info.hh"
#include "check_debug_loc_range.hh"
+#include "cu_coverage.hh"
static reg<check_debug_aranges> reg_debug_aranges;
(checkdescriptor::create ("check_debug_aranges")
.groups ("@low")
.prereq<typeof (*_m_sec_aranges)> ()
+ .prereq<typeof (*_m_info)> ()
+ .prereq<typeof (*_m_cu_coverage)> ()
.description (
"Checks for low-level structure of .debug_aranges. In addition it\n"
"checks:\n"
check_debug_aranges::check_debug_aranges (checkstack &stack, dwarflint &lint)
: _m_sec_aranges (lint.check (stack, _m_sec_aranges))
+ , _m_info (lint.toplev_check (stack, _m_info))
+ , _m_cu_coverage (lint.toplev_check (stack, _m_cu_coverage))
{
- check_debug_info *info = lint.toplev_check<check_debug_info> (stack);
- coverage *cov = NULL;
- if (info != NULL)
- {
- // xxx If need_ranges is true, we have to load ranges first.
- // That's a flaw in design of checks, that data should have been
- // stored in check_ranges, and that should have been requested
- // explicitly. But for the time being...
- if (info->cu_cov.need_ranges)
- lint.toplev_check<check_debug_ranges> (stack);
- if (!info->cu_cov.need_ranges)
- cov = &info->cu_cov.cov;
- }
+ coverage *cov = _m_cu_coverage != NULL ? &_m_cu_coverage->cov : NULL;
if (!check_aranges_structural (&_m_sec_aranges->file,
&_m_sec_aranges->sect,
- info != NULL ? &info->cus.front () : NULL,
+ _m_info != NULL
+ ? &_m_info->cus.front () : NULL,
cov))
throw check_base::failed ();
}
#include "low.h"
#include "checks.hh"
#include "sections.ii"
+#include "check_debug_info.ii"
+#include "cu_coverage.ii"
class check_debug_aranges
: public check<check_debug_aranges>
{
section<sec_aranges> *_m_sec_aranges;
+ check_debug_info *_m_info;
+ cu_coverage *_m_cu_coverage;
public:
static checkdescriptor descriptor ();
struct ref_record *local_die_refs;
Elf_Data *strings;
struct coverage *strings_coverage;
- struct cu_coverage *cu_coverage;
+ struct coverage *pc_coverage;
+ bool *need_rangesp;
};
typedef void (*value_check_cb_t) (uint64_t addr,
wr_message (*ctx->where, cat (mc_ranges, mc_impact_2))
<< "rangeptr value " << pri::hex (value)
<< " not aligned to CU address size." << std::endl;
- ctx->cu_coverage->need_ranges = true;
+ *ctx->need_rangesp = true;
ref_record_add (&ctx->cu->range_refs, value, ctx->where);
}
struct ref_record *local_die_refs,
struct coverage *strings_coverage,
struct relocation_data *reloc,
- struct cu_coverage *cu_coverage)
+ struct coverage *pc_coverage,
+ bool *need_rangesp)
{
bool got_die = false;
uint64_t sibling_addr = 0;
ctx, &where, cu,
local_die_refs,
strings, strings_coverage,
- cu_coverage
+ pc_coverage,
+ need_rangesp
};
while (!read_ctx_eof (ctx))
cu->low_pc = value;
if (low_pc != (uint64_t)-1 && high_pc != (uint64_t)-1)
- coverage_add (&cu_coverage->cov, low_pc, high_pc - low_pc);
+ coverage_add (pc_coverage, low_pc, high_pc - low_pc);
}
}
where.ref = NULL;
int st = read_die_chain (ver, file, ctx, cu, abbrevs, strings,
local_die_refs,
strings_coverage, reloc,
- cu_coverage);
+ pc_coverage, need_rangesp);
if (st == -1)
return -1;
else if (st == 0)
if (read_die_chain (ver, _m_file, ctx, cu, &abbrevs, strings,
&local_die_refs, strings_coverage,
(reloc != NULL && reloc->size > 0) ? reloc : NULL,
- &cu_cov) < 0)
+ &_m_cov, &_m_need_ranges) < 0)
{
_m_abbr_skip.push_back (abbrevs.offset);
retval = false;
, _m_abbrevs (lint.check (stack, _m_abbrevs))
, _m_cu_headers (lint.check (stack, _m_cu_headers))
{
- memset (&cu_cov, 0, sizeof (cu_cov));
+ memset (&_m_cov, 0, sizeof (_m_cov));
check_info_structural ();
// re-link CUs so that they form a chain again. This is to
ref_record_free (&it->loc_refs);
ref_record_free (&it->decl_file_refs);
}
- coverage_free (&cu_cov.cov);
+ coverage_free (&_m_cov);
}
cu *
read_cu_headers (checkstack &stack, dwarflint &lint);
};
+/** The pass for in-depth structural analysis of .debug_info. */
class check_debug_info
: public check<check_debug_info>
{
// validation. Check for unused abbrevs should be skipped.
std::vector< ::Dwarf_Off> _m_abbr_skip;
+ // The check pass adds all low_pc/high_pc ranges loaded from DIE
+ // tree into this coverage structure.
+ coverage _m_cov;
+
+ // If, during the check, we find any rangeptr-class attributes, we
+ // set need_ranges to true. cu_ranges pass then uses this as a hint
+ // whether to request .debug_ranges or not.
+ bool _m_need_ranges;
+
bool check_cu_structural (struct read_ctx *ctx,
struct cu *const cu,
Elf_Data *strings,
public:
static checkdescriptor descriptor ();
- // The check pass adds all low_pc/high_pc ranges loaded from DIE
- // tree into this following cu_cov structure. If it finds any
- // rangeptr-class attributes, it sets cu_cov.need_ranges to true.
- cu_coverage cu_cov;
+ coverage const &cov () const { return _m_cov; }
+ bool need_ranges () const { return _m_need_ranges; }
+
+ // This is where the loaded CUs are stored.
std::vector<cu> cus;
check_debug_info (checkstack &stack, dwarflint &lint);
(checkdescriptor::create ("check_debug_ranges")
.groups ("@low")
.prereq<typeof (*_m_sec_ranges)> ()
- .prereq<typeof (*_m_cus)> ()
+ .prereq<typeof (*_m_info)> ()
.description (
"Checks for low-level structure of .debug_ranges. In addition it\n"
"checks:\n"
(checkdescriptor::create ("check_debug_loc")
.groups ("@low")
.prereq<typeof (*_m_sec_loc)> ()
- .prereq<typeof (*_m_cus)> ()
+ .prereq<typeof (*_m_info)> ()
.description (
"Checks for low-level structure of .debug_loc. In addition it\n"
"makes the same checks as .debug_ranges. For location expressions\n"
struct sec *sec,
struct coverage *coverage,
struct coverage_map *coverage_map,
- struct cu_coverage *cu_coverage,
+ struct coverage *pc_coverage,
uint64_t addr,
struct where const *wh,
enum message_category cat)
/* Skip coverage analysis if we have errors or have no base
(or just don't do coverage analysis at all). */
else if (base < (uint64_t)-2 && retval
- && (coverage_map != NULL || cu_coverage != NULL))
+ && (coverage_map != NULL || pc_coverage != NULL))
{
uint64_t address = begin_addr + base;
uint64_t length = end_addr - begin_addr;
if (coverage_map != NULL)
coverage_map_add (coverage_map, address, length, &where, cat);
- if (cu_coverage != NULL)
- coverage_add (&cu_coverage->cov, address, length);
+ if (pc_coverage != NULL)
+ coverage_add (pc_coverage, address, length);
}
if (contains_locations)
check_loc_or_range_structural (struct elf_file *file,
struct sec *sec,
struct cu *cu_chain,
- struct cu_coverage *cu_coverage)
+ struct coverage *pc_coverage)
{
assert (sec->id == sec_loc || sec->id == sec_ranges);
assert (cu_chain != NULL);
ranges get recorded, not only those belonging to CUs.
Perhaps that's undesirable. */
if (!check_loc_or_range_ref (file, &ctx, it->cu, sec,
- &coverage, coverage_map,
- sec->id == sec_ranges ? cu_coverage : NULL,
+ &coverage, coverage_map, pc_coverage,
off, &it->ref.who, cat))
retval = false;
last_off = off;
coverage_free (&coverage);
coverage_map_free_XA (coverage_map);
- if (retval && cu_coverage != NULL)
- /* Only drop the flag if we were successful, so that the coverage
- analysis isn't later done against incomplete data. */
- cu_coverage->need_ranges = false;
-
return retval;
}
}
check_debug_ranges::check_debug_ranges (checkstack &stack, dwarflint &lint)
: _m_sec_ranges (lint.check (stack, _m_sec_ranges))
- , _m_cus (lint.check (stack, _m_cus))
+ , _m_info (lint.check (stack, _m_info))
{
+ memset (&_m_cov, 0, sizeof (_m_cov));
if (!::check_loc_or_range_structural (&_m_sec_ranges->file,
&_m_sec_ranges->sect,
- &_m_cus->cus.front (),
- &_m_cus->cu_cov))
+ &_m_info->cus.front (),
+ &_m_cov))
throw check_base::failed ();
}
+check_debug_ranges::~check_debug_ranges ()
+{
+ coverage_free (&_m_cov);
+}
+
check_debug_loc::check_debug_loc (checkstack &stack, dwarflint &lint)
: _m_sec_loc (lint.check (stack, _m_sec_loc))
- , _m_cus (lint.check (stack, _m_cus))
+ , _m_info (lint.check (stack, _m_info))
{
if (!::check_loc_or_range_structural (&_m_sec_loc->file,
&_m_sec_loc->sect,
- &_m_cus->cus.front (),
+ &_m_info->cus.front (),
NULL))
throw check_base::failed ();
}
#include "sections.ii"
#include "check_debug_info.ii"
#include "messages.h"
+#include "coverage.hh"
class check_debug_ranges
: public check<check_debug_ranges>
{
section<sec_ranges> *_m_sec_ranges;
- check_debug_info *_m_cus;
+ check_debug_info *_m_info;
+ coverage _m_cov;
public:
static checkdescriptor const &descriptor ();
+
+ coverage const &cov () const { return _m_cov; }
check_debug_ranges (checkstack &stack, dwarflint &lint);
+ ~check_debug_ranges ();
};
class check_debug_loc
: public check<check_debug_loc>
{
section<sec_loc> *_m_sec_loc;
- check_debug_info *_m_cus;
+ check_debug_info *_m_info;
public:
static checkdescriptor const &descriptor ();
--- /dev/null
+class check_debug_ranges;
+class check_debug_loc;
+struct hole_info;
--- /dev/null
+/* 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
+ <http://www.openinventionnetwork.com>. */
+
+#include "cu_coverage.hh"
+#include "check_debug_info.hh"
+#include "check_debug_loc_range.hh"
+
+checkdescriptor const &
+cu_coverage::descriptor ()
+{
+ static checkdescriptor cd
+ (checkdescriptor::create ("cu_coverage")
+ .prereq<typeof (*_m_info)> ()
+ .prereq<typeof (*_m_ranges)> ());
+ return cd;
+}
+
+cu_coverage::cu_coverage (checkstack &stack, dwarflint &lint)
+ : _m_info (lint.check (stack, _m_info))
+ , _m_ranges (lint.check_if (_m_info->need_ranges (), stack, _m_ranges))
+{
+ memset (&cov, 0, sizeof (cov));
+ coverage_add_all (&cov, &_m_info->cov ());
+ if (_m_ranges)
+ coverage_add_all (&cov, &_m_ranges->cov ());
+}
+
+cu_coverage::~cu_coverage ()
+{
+ coverage_free (&cov);
+}
--- /dev/null
+/* 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
+ <http://www.openinventionnetwork.com>. */
+
+#ifndef DWARFLINT_CU_COVERAGE_HH
+#define DWARFLINT_CU_COVERAGE_HH
+
+#include "check_debug_info.ii"
+#include "check_debug_loc_range.ii"
+#include "coverage.hh"
+#include "checks.hh"
+
+/** The pass for finalizing cu_coverage. */
+class cu_coverage
+ : public check<cu_coverage>
+{
+ check_debug_info *_m_info;
+ check_debug_ranges *_m_ranges;
+
+public:
+ static checkdescriptor const &descriptor ();
+
+ coverage cov;
+
+ cu_coverage (checkstack &stack, dwarflint &lint);
+ ~cu_coverage ();
+};
+
+#endif//DWARFLINT_CU_COVERAGE_HH
--- /dev/null
+class cu_coverage;
template <class T>
T *toplev_check (checkstack &stack,
__attribute__ ((unused)) T *fake = NULL);
+
+ template <class T>
+ T *
+ check_if (bool whether, checkstack &stack,
+ __attribute__ ((unused)) T *fake = NULL)
+ {
+ if (whether)
+ return check<T> (stack);
+ else
+ return NULL;
+ }
};
#endif//DWARFLINT_HH
bool allow_overlap;
};
- struct cu_coverage
- {
- struct coverage cov;
- bool need_ranges; /* If all CU DIEs have high_pc/low_pc
- attribute pair, we don't need separate
- range pass. Otherwise we do. As soon as
- ranges are projected into cov, the flag
- is set to false again. */
- };
-
// xxx low-level check entry points, will go away
struct cu;
extern bool check_aranges_structural (struct elf_file *file,