From 277a2b96fdafd1cb5eb489198c7a58c43ad16a4b Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 28 Feb 2014 12:25:37 -0500 Subject: [PATCH] PR6941: skip prologue-skipping for GCC optimized code If the code was compiled using -g -O2, then prologue searching is not necessary since location data is valid there. We determine this by looking for DW_AT_location attributes with data of form DW_FORM_sec_offset (see GDB's PR12573 and also RHBZ612253#c6). --- dwflpp.cxx | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ dwflpp.h | 1 + tapsets.cxx | 9 ++++---- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index c6a94cc65..388cf73d9 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -4122,4 +4122,66 @@ dwflpp::is_gcc_producer(Dwarf_Die *cudie, string& producer, string& version) return true; } +static bool +die_has_loclist(Dwarf_Die *begin_die) +{ + Dwarf_Die die; + Dwarf_Attribute loc; + + if (dwarf_child(begin_die, &die) != 0) + return false; + + do + { + switch (dwarf_tag(&die)) + { + case DW_TAG_formal_parameter: + case DW_TAG_variable: + if (dwarf_attr_integrate(&die, DW_AT_location, &loc) + && dwarf_whatform(&loc) == DW_FORM_sec_offset) + return true; + break; + default: + if (dwarf_haschildren (&die)) + if (die_has_loclist(&die)) + return true; + break; + } + } + while (dwarf_siblingof (&die, &die) == 0); + + return false; +} + +bool +dwflpp::has_valid_locs () +{ + assert(cu); + + // The current CU has valid location info (implying we do not need to skip the + // prologue) if + // - it was compiled with -O2 -g (in which case, GCC outputs proper location + // info for the prologue), and + // - it was compiled by GCC >= 4.5 (previous versions could have had invalid + // debug info in the prologue, see GDB's PR13777) + + string prod, vers; + if (is_gcc_producer(cu, prod, vers) + && strverscmp(vers.c_str(), "4.5") < 0) + return false; + + // We determine if the current CU has been optimized with -O2 -g by looking + // for any data objects whose DW_AT_location is a location list. This is also + // how GDB determines whether to skip the prologue or not. See GDB's PR12573 + // and also RHBZ612253#c6. + if (!die_has_loclist(cu)) + return false; + + if (sess.verbose > 2) + clog << _F("CU '%s' in module '%s' has valid locs", + cu_name().c_str(), module_name.c_str()) << endl; + + return true; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/dwflpp.h b/dwflpp.h index 81a5f0d28..ad3632117 100644 --- a/dwflpp.h +++ b/dwflpp.h @@ -447,6 +447,7 @@ struct dwflpp const target_symbol *e); bool has_gnu_debugdata(); + bool has_valid_locs(); private: DwflPtr dwfl_ptr; diff --git a/tapsets.cxx b/tapsets.cxx index 2c9af236a..7eaaf4864 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1885,10 +1885,11 @@ query_cu (Dwarf_Die * cudie, dwarf_query * q) if (rc != DWARF_CB_OK) q->query_done = true; - if ((q->sess.prologue_searching || q->has_process) // PR 6871 - && !q->has_statement_str) // PR 2608 - if (! q->filtered_functions.empty()) - q->dw.resolve_prologue_endings (q->filtered_functions); + if (!q->filtered_functions.empty() && + !q->has_statement_str && // PR 2608 + (q->sess.prologue_searching || + (q->has_process && !q->dw.has_valid_locs()))) // PR 6871 && PR 6941 + q->dw.resolve_prologue_endings (q->filtered_functions); // NB: we could skip the resolve_prologue_endings() call here for has_return case (PR13200), // but don't have to. We can resolve the prologue, just not actually use it in query_addr(). -- 2.43.5