* [PATCH 1/2] btrace: only search for lines in current symtab
2014-03-07 8:57 [PATCH 0/2] btrace: perf improvements Markus Metzger
@ 2014-03-07 8:57 ` Markus Metzger
2014-03-21 17:43 ` Jan Kratochvil
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
1 sibling, 1 reply; 13+ messages in thread
From: Markus Metzger @ 2014-03-07 8:57 UTC (permalink / raw)
To: jan.kratochvil; +Cc: gdb-patches
When computing the function trace, we lookup the line number from the PC
for each instruction in the trace. This is very expensive.
Instead, lookup the symtab once when we create the btrace function and
then only search in the linetable for that symtab.
Also use the stored symtab to print the filename.
2014-03-07 Markus Metzger <markus.t.metzger@intel.com>
* btrace.h (btrace_function)<symtab>: New.
* btrace.c (ftrace_skip_file): Remove.
(ftrace_print_filename): Use symtab.
(ftrace_new_function): Update parameters. Lookup symtab.
(ftrace_new_call, ftrace_new_tailcall, ftrace_new_return,
ftrace_new_switch): Update parameters.
(ftrace_update_function): Pass pc.
(ftrace_update_lines): Only search in BFUN->SYMTAB.
* record-btrace.c (btrace_call_history_src_line): Use symtab.
---
gdb/btrace.c | 116 +++++++++++++++++++++++++---------------------------
gdb/btrace.h | 3 ++
gdb/record-btrace.c | 8 ++--
3 files changed, 63 insertions(+), 64 deletions(-)
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 601eb41..b2e34b7 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -73,13 +73,12 @@ ftrace_print_function_name (const struct btrace_function *bfun)
static const char *
ftrace_print_filename (const struct btrace_function *bfun)
{
- struct symbol *sym;
+ struct symtab *symtab;
const char *filename;
- sym = bfun->sym;
-
- if (sym != NULL)
- filename = symtab_to_filename_for_display (sym->symtab);
+ symtab = bfun->symtab;
+ if (symtab != NULL)
+ filename = symtab_to_filename_for_display (symtab);
else
filename = "<unknown>";
@@ -168,26 +167,6 @@ ftrace_function_switched (const struct btrace_function *bfun,
return 0;
}
-/* Return non-zero if we should skip this file when generating the function
- call history, zero otherwise.
- We would want to do that if, say, a macro that is defined in another file
- is expanded in this function. */
-
-static int
-ftrace_skip_file (const struct btrace_function *bfun, const char *fullname)
-{
- struct symbol *sym;
- const char *bfile;
-
- sym = bfun->sym;
- if (sym == NULL)
- return 1;
-
- bfile = symtab_to_fullname (sym->symtab);
-
- return (filename_cmp (bfile, fullname) != 0);
-}
-
/* Allocate and initialize a new branch trace function segment.
PREV is the chronologically preceding function segment.
MFUN and FUN are the symbol information we have for this function. */
@@ -195,7 +174,8 @@ ftrace_skip_file (const struct btrace_function *bfun, const char *fullname)
static struct btrace_function *
ftrace_new_function (struct btrace_function *prev,
struct minimal_symbol *mfun,
- struct symbol *fun)
+ struct symbol *fun,
+ CORE_ADDR pc)
{
struct btrace_function *bfun;
@@ -205,6 +185,11 @@ ftrace_new_function (struct btrace_function *prev,
bfun->sym = fun;
bfun->flow.prev = prev;
+ if (fun != NULL)
+ bfun->symtab = SYMBOL_SYMTAB (fun);
+ else
+ bfun->symtab = find_pc_symtab (pc);
+
/* We start with the identities of min and max, respectively. */
bfun->lbegin = INT_MAX;
bfun->lend = INT_MIN;
@@ -270,11 +255,12 @@ ftrace_fixup_caller (struct btrace_function *bfun,
static struct btrace_function *
ftrace_new_call (struct btrace_function *caller,
struct minimal_symbol *mfun,
- struct symbol *fun)
+ struct symbol *fun,
+ CORE_ADDR pc)
{
struct btrace_function *bfun;
- bfun = ftrace_new_function (caller, mfun, fun);
+ bfun = ftrace_new_function (caller, mfun, fun, pc);
bfun->up = caller;
bfun->level = caller->level + 1;
@@ -290,11 +276,12 @@ ftrace_new_call (struct btrace_function *caller,
static struct btrace_function *
ftrace_new_tailcall (struct btrace_function *caller,
struct minimal_symbol *mfun,
- struct symbol *fun)
+ struct symbol *fun,
+ CORE_ADDR pc)
{
struct btrace_function *bfun;
- bfun = ftrace_new_function (caller, mfun, fun);
+ bfun = ftrace_new_function (caller, mfun, fun, pc);
bfun->up = caller;
bfun->level = caller->level + 1;
bfun->flags |= BFUN_UP_LINKS_TO_TAILCALL;
@@ -358,11 +345,12 @@ static struct btrace_function *
ftrace_new_return (struct gdbarch *gdbarch,
struct btrace_function *prev,
struct minimal_symbol *mfun,
- struct symbol *fun)
+ struct symbol *fun,
+ CORE_ADDR pc)
{
struct btrace_function *bfun, *caller;
- bfun = ftrace_new_function (prev, mfun, fun);
+ bfun = ftrace_new_function (prev, mfun, fun, pc);
/* It is important to start at PREV's caller. Otherwise, we might find
PREV itself, if PREV is a recursive function. */
@@ -433,13 +421,14 @@ ftrace_new_return (struct gdbarch *gdbarch,
static struct btrace_function *
ftrace_new_switch (struct btrace_function *prev,
struct minimal_symbol *mfun,
- struct symbol *fun)
+ struct symbol *fun,
+ CORE_ADDR pc)
{
struct btrace_function *bfun;
/* This is an unexplained function switch. The call stack will likely
be wrong at this point. */
- bfun = ftrace_new_function (prev, mfun, fun);
+ bfun = ftrace_new_function (prev, mfun, fun, pc);
/* We keep the function level. */
bfun->level = prev->level;
@@ -474,7 +463,7 @@ ftrace_update_function (struct gdbarch *gdbarch,
/* If we didn't have a function before, we create one. */
if (bfun == NULL)
- return ftrace_new_function (bfun, mfun, fun);
+ return ftrace_new_function (bfun, mfun, fun, pc);
/* Check the last instruction, if we have one.
We do this check first, since it allows us to fill in the call stack
@@ -491,7 +480,7 @@ ftrace_update_function (struct gdbarch *gdbarch,
/* Check for returns. */
if (gdbarch_insn_is_ret (gdbarch, lpc))
- return ftrace_new_return (gdbarch, bfun, mfun, fun);
+ return ftrace_new_return (gdbarch, bfun, mfun, fun, pc);
/* Check for calls. */
if (gdbarch_insn_is_call (gdbarch, lpc))
@@ -502,7 +491,7 @@ ftrace_update_function (struct gdbarch *gdbarch,
/* Ignore calls to the next instruction. They are used for PIC. */
if (lpc + size != pc)
- return ftrace_new_call (bfun, mfun, fun);
+ return ftrace_new_call (bfun, mfun, fun, pc);
}
}
@@ -529,10 +518,10 @@ ftrace_update_function (struct gdbarch *gdbarch,
/* Jumps indicate optimized tail calls. */
if (start == pc && gdbarch_insn_is_jump (gdbarch, lpc))
- return ftrace_new_tailcall (bfun, mfun, fun);
+ return ftrace_new_tailcall (bfun, mfun, fun, pc);
}
- return ftrace_new_switch (bfun, mfun, fun);
+ return ftrace_new_switch (bfun, mfun, fun, pc);
}
return bfun;
@@ -543,32 +532,39 @@ ftrace_update_function (struct gdbarch *gdbarch,
static void
ftrace_update_lines (struct btrace_function *bfun, CORE_ADDR pc)
{
- struct symtab_and_line sal;
- const char *fullname;
+ struct linetable *lines;
+ struct symtab *symtab;
+ int i;
- sal = find_pc_line (pc, 0);
- if (sal.symtab == NULL || sal.line == 0)
- {
- DEBUG_FTRACE ("no lines at %s", core_addr_to_string_nz (pc));
- return;
- }
+ symtab = bfun->symtab;
+ if (symtab == NULL)
+ return;
+
+ lines = LINETABLE (symtab);
+ if (lines == NULL)
+ return;
- /* Check if we switched files. This could happen if, say, a macro that
- is defined in another file is expanded here. */
- fullname = symtab_to_fullname (sal.symtab);
- if (ftrace_skip_file (bfun, fullname))
+ for (i = 0; i < lines->nitems; ++i)
{
- DEBUG_FTRACE ("ignoring file at %s, file=%s",
- core_addr_to_string_nz (pc), fullname);
- return;
- }
+ struct linetable_entry *entry;
- /* Update the line range. */
- bfun->lbegin = min (bfun->lbegin, sal.line);
- bfun->lend = max (bfun->lend, sal.line);
+ entry = &lines->item[i];
+ if (entry->pc == pc)
+ {
+ int line;
- if (record_debug > 1)
- ftrace_debug (bfun, "update lines");
+ line = entry->line;
+
+ /* Update the line range. */
+ bfun->lbegin = min (bfun->lbegin, line);
+ bfun->lend = max (bfun->lend, line);
+
+ if (record_debug > 1)
+ ftrace_debug (bfun, "update lines");
+
+ break;
+ }
+ }
}
/* Add the instruction at PC to BFUN's instructions. */
diff --git a/gdb/btrace.h b/gdb/btrace.h
index f83a80f..67ba577 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -76,6 +76,9 @@ struct btrace_function
struct minimal_symbol *msym;
struct symbol *sym;
+ /* The symbol table. May be NULL. */
+ struct symtab *symtab;
+
/* The previous and next segment belonging to the same function.
If a function calls another function, the former will have at least
two segments: one before the call and another after the return. */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index d4c0d42..1851823 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -507,15 +507,15 @@ static void
btrace_call_history_src_line (struct ui_out *uiout,
const struct btrace_function *bfun)
{
- struct symbol *sym;
+ struct symtab *symtab;
int begin, end;
- sym = bfun->sym;
- if (sym == NULL)
+ symtab = bfun->symtab;
+ if (symtab == NULL)
return;
ui_out_field_string (uiout, "file",
- symtab_to_filename_for_display (sym->symtab));
+ symtab_to_filename_for_display (symtab));
begin = bfun->lbegin;
end = bfun->lend;
--
1.8.3.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/2] btrace: avoid symbol lookup
2014-03-07 8:57 [PATCH 0/2] btrace: perf improvements Markus Metzger
2014-03-07 8:57 ` [PATCH 1/2] btrace: only search for lines in current symtab Markus Metzger
@ 2014-03-07 8:57 ` Markus Metzger
2014-03-07 15:55 ` Pedro Alves
` (2 more replies)
1 sibling, 3 replies; 13+ messages in thread
From: Markus Metzger @ 2014-03-07 8:57 UTC (permalink / raw)
To: jan.kratochvil; +Cc: gdb-patches
The debug symbol lookup is quite expensive, particularly if no symbol
is found for a given PC.
Avoid the lookup when computing the function trace if we already found
a minimal symbol.
The only different seems to be that some function names are now printed
without '()'.
2014-03-07 Markus Metzger <markus.t.metzger@intel.com>
* btrace.c (ftrace_update_function): Lookup symbol only if there
is no minimal symbol.
testsuite/
* gdb.btrace/exception.exp: Update.
* gdb.btrace/static_functions.exp: New.
---
gdb/btrace.c | 12 ++++--
gdb/testsuite/gdb.btrace/exception.exp | 4 +-
gdb/testsuite/gdb.btrace/static_functions.exp | 62 +++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 6 deletions(-)
create mode 100644 gdb/testsuite/gdb.btrace/static_functions.exp
diff --git a/gdb/btrace.c b/gdb/btrace.c
index b2e34b7..feb7bea 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -451,13 +451,17 @@ ftrace_update_function (struct gdbarch *gdbarch,
struct symbol *fun;
struct btrace_insn *last;
- /* Try to determine the function we're in. We use both types of symbols
- to avoid surprises when we sometimes get a full symbol and sometimes
- only a minimal symbol. */
- fun = find_pc_function (pc);
+ /* Try to determine the function we're in. */
bmfun = lookup_minimal_symbol_by_pc (pc);
mfun = bmfun.minsym;
+ /* We only lookup the symbol in the debug information if we have not found
+ a minimal symbol. This avoids the expensive lookup for globally visible
+ symbols. */
+ fun = NULL;
+ if (mfun == NULL)
+ fun = find_pc_function (pc);
+
if (fun == NULL && mfun == NULL)
DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc));
diff --git a/gdb/testsuite/gdb.btrace/exception.exp b/gdb/testsuite/gdb.btrace/exception.exp
index 0279a7f..71f54a2 100755
--- a/gdb/testsuite/gdb.btrace/exception.exp
+++ b/gdb/testsuite/gdb.btrace/exception.exp
@@ -47,7 +47,7 @@ gdb_continue_to_breakpoint "cont to bp.2" ".*$srcfile:$bp_2\r\n.*"
send_gdb "record function-call-history 1\n"
gdb_expect_list "flat" "\r\n$gdb_prompt $" [list \
[join [list \
- "1\tmain\\(\\)" \
+ "1\tmain" \
"2\ttest\\(\\)" \
"3\tfoo\\(\\)" \
"4\tbar\\(\\)" \
@@ -60,7 +60,7 @@ gdb_expect_list "flat" "\r\n$gdb_prompt $" [list \
send_gdb "record function-call-history /c 1\n"
gdb_expect_list "indented" "\r\n$gdb_prompt $" [list \
[join [list \
- "1\tmain\\(\\)" \
+ "1\tmain" \
"2\t test\\(\\)" \
"3\t foo\\(\\)" \
"4\t bar\\(\\)" \
diff --git a/gdb/testsuite/gdb.btrace/static_functions.exp b/gdb/testsuite/gdb.btrace/static_functions.exp
new file mode 100644
index 0000000..34ed485
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/static_functions.exp
@@ -0,0 +1,62 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# This program 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.
+#
+# This program 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/>.
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start inferior
+standard_testfile unknown_functions.c
+
+# discard local symbols
+set ldflags "additional_flags=-Wl,-x"
+if [prepare_for_testing $testfile.exp $testfile $srcfile {$ldflags debug}] {
+ return -1
+}
+if ![runto test] {
+ return -1
+}
+
+# we want to see the full trace for this test
+gdb_test_no_output "set record function-call-history-size 0"
+
+# trace from one call of test to the next
+gdb_test_no_output "record btrace"
+gdb_continue_to_breakpoint "cont to test" ".*test.*"
+
+# show the flat branch trace
+gdb_test "record function-call-history 1" [join [list \
+ "1\ttest" \
+ "2\tfoo" \
+ "3\tbar" \
+ "4\tfoo" \
+ "5\ttest" \
+ "6\tmain" \
+ "7\ttest" \
+ ] "\r\n"] "flat"
+
+# show the branch trace with calls indented
+gdb_test "record function-call-history /c 1" [join [list \
+ "1\t test" \
+ "2\t foo" \
+ "3\t bar" \
+ "4\t foo" \
+ "5\t test" \
+ "6\tmain" \
+ "7\t test" \
+ ] "\r\n"] "indented"
--
1.8.3.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/2] btrace: perf improvements
@ 2014-03-07 8:57 Markus Metzger
2014-03-07 8:57 ` [PATCH 1/2] btrace: only search for lines in current symtab Markus Metzger
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
0 siblings, 2 replies; 13+ messages in thread
From: Markus Metzger @ 2014-03-07 8:57 UTC (permalink / raw)
To: jan.kratochvil; +Cc: gdb-patches
The subsequent patches improve the performance of processing branch trace by
reducing the number of symbol table lookups.
For the currently hard-coded buffer size the impact should only be noticeable
for big programs. When tracing GDB itself, for example, there is no noticeable
delay.
Subsequent patches will allow the buffer size to be configurable. Bigger
buffers will require faster processing.
Markus Metzger (2):
btrace: only search for lines in current symtab
btrace: avoid symbol lookup
gdb/btrace.c | 128 +++++++++++++-------------
gdb/btrace.h | 3 +
gdb/record-btrace.c | 8 +-
gdb/testsuite/gdb.btrace/exception.exp | 4 +-
gdb/testsuite/gdb.btrace/static_functions.exp | 62 +++++++++++++
5 files changed, 135 insertions(+), 70 deletions(-)
create mode 100644 gdb/testsuite/gdb.btrace/static_functions.exp
--
1.8.3.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
@ 2014-03-07 15:55 ` Pedro Alves
2014-03-10 8:05 ` Metzger, Markus T
2014-03-07 15:56 ` Pedro Alves
2014-03-10 21:43 ` Jan Kratochvil
2 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2014-03-07 15:55 UTC (permalink / raw)
To: Markus Metzger; +Cc: jan.kratochvil, gdb-patches
On 03/07/2014 08:57 AM, Markus Metzger wrote:
> --- a/gdb/testsuite/gdb.btrace/exception.exp
> +++ b/gdb/testsuite/gdb.btrace/exception.exp
> @@ -47,7 +47,7 @@ gdb_continue_to_breakpoint "cont to bp.2" ".*$srcfile:$bp_2\r\n.*"
> send_gdb "record function-call-history 1\n"
> gdb_expect_list "flat" "\r\n$gdb_prompt $" [list \
> [join [list \
> - "1\tmain\\(\\)" \
> + "1\tmain" \
> "2\ttest\\(\\)" \
> "3\tfoo\\(\\)" \
> "4\tbar\\(\\)" \
I wonder whether people will think the different looks are a bug...
Also, doesn't that mean we'll show mangled C++ names? Won't that
be quite user unfriendly?
--
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
2014-03-07 15:55 ` Pedro Alves
@ 2014-03-07 15:56 ` Pedro Alves
2014-03-10 21:43 ` Jan Kratochvil
2 siblings, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2014-03-07 15:56 UTC (permalink / raw)
To: Markus Metzger; +Cc: jan.kratochvil, gdb-patches
On 03/07/2014 08:57 AM, Markus Metzger wrote:
> +# Copyright 2013 Free Software Foundation, Inc.
BTW, "2013-2014".
--
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-07 15:55 ` Pedro Alves
@ 2014-03-10 8:05 ` Metzger, Markus T
0 siblings, 0 replies; 13+ messages in thread
From: Metzger, Markus T @ 2014-03-10 8:05 UTC (permalink / raw)
To: Pedro Alves; +Cc: jan.kratochvil, gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Friday, March 07, 2014 4:56 PM
Thanks for your review.
> To: Metzger, Markus T
> Cc: jan.kratochvil@redhat.com; gdb-patches@sourceware.org
> Subject: Re: [PATCH 2/2] btrace: avoid symbol lookup
>
> On 03/07/2014 08:57 AM, Markus Metzger wrote:
> > --- a/gdb/testsuite/gdb.btrace/exception.exp
> > +++ b/gdb/testsuite/gdb.btrace/exception.exp
> > @@ -47,7 +47,7 @@ gdb_continue_to_breakpoint "cont to bp.2"
> ".*$srcfile:$bp_2\r\n.*"
> > send_gdb "record function-call-history 1\n"
> > gdb_expect_list "flat" "\r\n$gdb_prompt $" [list \
> > [join [list \
> > - "1\tmain\\(\\)" \
> > + "1\tmain" \
> > "2\ttest\\(\\)" \
> > "3\tfoo\\(\\)" \
> > "4\tbar\\(\\)" \
>
> I wonder whether people will think the different looks are a bug...
>
> Also, doesn't that mean we'll show mangled C++ names? Won't that
> be quite user unfriendly?
It would. Fortunately, GDB already prints the demangled name also for
minimal symbols - see MSYMBOL_PRINT_NAME which calls
symbol_natural_name. Minimal and full symbols seem to be treated the
same way.
This does not work for main, though, for which the minimal symbol has
language 'auto' and the full symbol has language 'cplus'.
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
2014-03-07 15:55 ` Pedro Alves
2014-03-07 15:56 ` Pedro Alves
@ 2014-03-10 21:43 ` Jan Kratochvil
2014-03-11 10:08 ` Metzger, Markus T
2 siblings, 1 reply; 13+ messages in thread
From: Jan Kratochvil @ 2014-03-10 21:43 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2493 bytes --]
On Fri, 07 Mar 2014 09:57:45 +0100, Markus Metzger wrote:
> --- a/gdb/btrace.c
> +++ b/gdb/btrace.c
> @@ -451,13 +451,17 @@ ftrace_update_function (struct gdbarch *gdbarch,
> struct symbol *fun;
> struct btrace_insn *last;
>
> - /* Try to determine the function we're in. We use both types of symbols
> - to avoid surprises when we sometimes get a full symbol and sometimes
> - only a minimal symbol. */
> - fun = find_pc_function (pc);
> + /* Try to determine the function we're in. */
> bmfun = lookup_minimal_symbol_by_pc (pc);
> mfun = bmfun.minsym;
>
> + /* We only lookup the symbol in the debug information if we have not found
> + a minimal symbol. This avoids the expensive lookup for globally visible
> + symbols. */
> + fun = NULL;
> + if (mfun == NULL)
> + fun = find_pc_function (pc);
> +
> if (fun == NULL && mfun == NULL)
> DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc));
>
[...]
Behavior after the change is not the same. DWARF functions symbols can span
over discontiguous ranges with DW_AT_ranges but their corresponding ELF
function symbols cannot, therefore those are just some approximation.
Testcase gdb.dwarf2/dw2-objfile-overlap.exp tests such a case, from:
https://sourceware.org/ml/gdb-patches/2011-11/msg00166.html
For address of symbol "inner":
* find_pc_function finds DWARF symbol "inner"
* lookup_minimal_symbol_by_pc finds ELF symbol "outer_inner"
In few Fedora 20 x86_64 -O2 -g built libraries I have not found any
DW_TAG_subprogram using DW_AT_ranges, only DW_TAG_inlined_subroutine use
DW_AT_ranges. But that is more a limitation of gcc, other compilers may
produce DW_TAG_subprogram using DW_AT_ranges with overlapping function parts.
Inlined functions are found by neither find_pc_function nor
lookup_minimal_symbol_by_pc (block_containing_function (block_for_pc ()) finds
inlined function). Not sure if it is not a bug of find_pc_function but that
is off-topic here.
I do not think it will be hit in real world cases. GDB would need some better
abstraction of the symbol kinds to be more systematic in what it outputs.
It would be good to know how much it helps your usecase as it is not a fully
clean/transparent change.
Thanks,
Jan
set confirm no
set trace-commands
file gdb.dwarf2/dw2-objfile-overlap-outer.x
add-symbol-file gdb.dwarf2/dw2-objfile-overlap-inner.x outer_inner
info sym inner
->
find_pc_function "inner".
lookup_minimal_symbol_by_pc "outer_inner".
[-- Attachment #2: 1 --]
[-- Type: text/plain, Size: 934 bytes --]
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 87b1448..f1517d2 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1107,6 +1107,27 @@ sym_info (char *arg, int from_tty)
error_no_arg (_("address"));
addr = parse_and_eval_address (arg);
+
+{
+struct symbol *sym=find_pc_function (addr);
+if (sym) {
+ printf_filtered ("find_pc_function \"");
+ fprintf_symbol_filtered (gdb_stdout, SYMBOL_PRINT_NAME (sym),
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\".\n");
+}
+}
+{
+struct bound_minimal_symbol bmfun=lookup_minimal_symbol_by_pc(addr);
+if (bmfun.minsym) {
+ printf_filtered ("lookup_minimal_symbol_by_pc \"");
+ fprintf_symbol_filtered (gdb_stdout, MSYMBOL_PRINT_NAME (bmfun.minsym),
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\".\n");
+}
+}
+
+
ALL_OBJSECTIONS (objfile, osect)
{
/* Only process each object file once, even if there's a separate
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-10 21:43 ` Jan Kratochvil
@ 2014-03-11 10:08 ` Metzger, Markus T
2014-03-21 17:22 ` Jan Kratochvil
0 siblings, 1 reply; 13+ messages in thread
From: Metzger, Markus T @ 2014-03-11 10:08 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, Pedro Alves (palves@redhat.com)
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Jan Kratochvil
> Sent: Monday, March 10, 2014 10:43 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 2/2] btrace: avoid symbol lookup
>
> On Fri, 07 Mar 2014 09:57:45 +0100, Markus Metzger wrote:
> > --- a/gdb/btrace.c
> > +++ b/gdb/btrace.c
> > @@ -451,13 +451,17 @@ ftrace_update_function (struct gdbarch
> *gdbarch,
> > struct symbol *fun;
> > struct btrace_insn *last;
> >
> > - /* Try to determine the function we're in. We use both types of symbols
> > - to avoid surprises when we sometimes get a full symbol and sometimes
> > - only a minimal symbol. */
> > - fun = find_pc_function (pc);
> > + /* Try to determine the function we're in. */
> > bmfun = lookup_minimal_symbol_by_pc (pc);
> > mfun = bmfun.minsym;
> >
> > + /* We only lookup the symbol in the debug information if we have not
> found
> > + a minimal symbol. This avoids the expensive lookup for globally visible
> > + symbols. */
> > + fun = NULL;
> > + if (mfun == NULL)
> > + fun = find_pc_function (pc);
> > +
> > if (fun == NULL && mfun == NULL)
> > DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc));
> >
> [...]
>
> Behavior after the change is not the same. DWARF functions symbols can
> span
> over discontiguous ranges with DW_AT_ranges but their corresponding ELF
> function symbols cannot, therefore those are just some approximation.
>
> Testcase gdb.dwarf2/dw2-objfile-overlap.exp tests such a case, from:
> https://sourceware.org/ml/gdb-patches/2011-11/msg00166.html
>
> For address of symbol "inner":
> * find_pc_function finds DWARF symbol "inner"
> * lookup_minimal_symbol_by_pc finds ELF symbol "outer_inner"
>
> In few Fedora 20 x86_64 -O2 -g built libraries I have not found any
> DW_TAG_subprogram using DW_AT_ranges, only
> DW_TAG_inlined_subroutine use
> DW_AT_ranges. But that is more a limitation of gcc, other compilers may
> produce DW_TAG_subprogram using DW_AT_ranges with overlapping
> function parts.
I have not seen DW_AT_ranges used for split functions. OpenMP is a good
candidate for this so I checked what gcc 4.8.2 and a recent icc are doing today.
Both generate separate functions for parallel regions and describe them as
artificial functions in DWARF. Whereas GCC generates a separate local function
in ELF, ICC puts the parallel region function after the function it was extracted
from and describes both as a single function in ELF.
For GCC we get a function with a funny name in both cases.
For ICC we get a function with a funny name in the DWARF case and the name
of the function from which the parallel region has been extracted in the ELF case.
So the result is different in some cases. I'm not sure whether it matters, though.
Inline functions are a different topic. I would like to support them one day.
As you point out below, the existing version does not support inline functions
either, so some work is necessary.
We might need some more work in symbol handling to allow a fast lookup
covering only inline functions. We could combine this with the minimal symbol
lookup to get both inline functions support and reasonable performance.
> Inlined functions are found by neither find_pc_function nor
> lookup_minimal_symbol_by_pc (block_containing_function (block_for_pc
> ()) finds
> inlined function). Not sure if it is not a bug of find_pc_function but that
> is off-topic here.
>
> I do not think it will be hit in real world cases. GDB would need some better
> abstraction of the symbol kinds to be more systematic in what it outputs.
>
> It would be good to know how much it helps your usecase as it is not a fully
> clean/transparent change.
As benchmark, I traced "gdb a.out -ex quit" with a breakpoint on quit_force
for debug versions of both gdb and a.out. The tracing GDB was compiled
without any additional options; the traced GDB was compiled with "-g -O0".
I used a relatively big buffer that contained ~1.5 million instructions.
I used "maintenance time 1" to measure the execution time of "info record".
The first patch improves performance by ~2x.
This patch improves performance by ~3x on top of the first patch.
I first tried to cache the returned symbol and check whether the next PC
belongs to the same function. My cache hit in ~50% of the cases but showed
no benefit. For the majority of the other ~50% no symbol was found. I can't
cache those.
What's missing is a "fast fail", i.e. quickly determine that we won't find any
symbol for this PC. I won't be able to do this in a reasonable amount of time,
though, so I thought this patch is a compromise between functionality and
performance.
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-11 10:08 ` Metzger, Markus T
@ 2014-03-21 17:22 ` Jan Kratochvil
2014-03-24 7:57 ` Metzger, Markus T
0 siblings, 1 reply; 13+ messages in thread
From: Jan Kratochvil @ 2014-03-21 17:22 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches, Pedro Alves (palves@redhat.com)
On Tue, 11 Mar 2014 11:08:43 +0100, Metzger, Markus T wrote:
> What's missing is a "fast fail", i.e. quickly determine that we won't find any
> symbol for this PC. I won't be able to do this in a reasonable amount of time,
> though, so I thought this patch is a compromise between functionality and
> performance.
I do not think providing incorrect behavior for performance reasons is a valid
tradeoff. The right way would be to fix the DWARF lookups to be fast enough.
But I no longer approve GDB patches so this is just my personal opinion.
Jan
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] btrace: only search for lines in current symtab
2014-03-07 8:57 ` [PATCH 1/2] btrace: only search for lines in current symtab Markus Metzger
@ 2014-03-21 17:43 ` Jan Kratochvil
0 siblings, 0 replies; 13+ messages in thread
From: Jan Kratochvil @ 2014-03-21 17:43 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On Fri, 07 Mar 2014 09:57:44 +0100, Markus Metzger wrote:
[...]
> @@ -543,32 +532,39 @@ ftrace_update_function (struct gdbarch *gdbarch,
> static void
> ftrace_update_lines (struct btrace_function *bfun, CORE_ADDR pc)
> {
> - struct symtab_and_line sal;
> - const char *fullname;
> + struct linetable *lines;
> + struct symtab *symtab;
> + int i;
>
> - sal = find_pc_line (pc, 0);
> - if (sal.symtab == NULL || sal.line == 0)
> - {
> - DEBUG_FTRACE ("no lines at %s", core_addr_to_string_nz (pc));
> - return;
> - }
> + symtab = bfun->symtab;
> + if (symtab == NULL)
> + return;
> +
> + lines = LINETABLE (symtab);
> + if (lines == NULL)
> + return;
>
> - /* Check if we switched files. This could happen if, say, a macro that
> - is defined in another file is expanded here. */
> - fullname = symtab_to_fullname (sal.symtab);
> - if (ftrace_skip_file (bfun, fullname))
> + for (i = 0; i < lines->nitems; ++i)
The line table has ordered PC values so one can find the right line in
logarithmic time.
> {
> - DEBUG_FTRACE ("ignoring file at %s, file=%s",
> - core_addr_to_string_nz (pc), fullname);
> - return;
> - }
> + struct linetable_entry *entry;
>
> - /* Update the line range. */
> - bfun->lbegin = min (bfun->lbegin, sal.line);
> - bfun->lend = max (bfun->lend, sal.line);
> + entry = &lines->item[i];
> + if (entry->pc == pc)
This is not right, PC can be between two ENTRY->PC values and it should match
the former line. This implementation would not find a matching line.
> + {
> + int line;
>
> - if (record_debug > 1)
> - ftrace_debug (bfun, "update lines");
> + line = entry->line;
> +
> + /* Update the line range. */
> + bfun->lbegin = min (bfun->lbegin, line);
> + bfun->lend = max (bfun->lend, line);
> +
> + if (record_debug > 1)
> + ftrace_debug (bfun, "update lines");
> +
> + break;
> + }
> + }
> }
>
> /* Add the instruction at PC to BFUN's instructions. */
I do not think this is the right approach, find_pc_sect_line() can be improved
to at least look up the lines in logarithmic time by bisecting the range.
It could also use some cache of recent lookups.
Also I am not sure this new implementation handles correctly include files and
their boundaries, which find_pc_sect_line() has to take care of.
This is my personal opinion unrelated to GDB project maintainers' opinion.
Regards,
Jan
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-21 17:22 ` Jan Kratochvil
@ 2014-03-24 7:57 ` Metzger, Markus T
2014-03-24 8:37 ` Jan Kratochvil
0 siblings, 1 reply; 13+ messages in thread
From: Metzger, Markus T @ 2014-03-24 7:57 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, Pedro Alves (palves@redhat.com)
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Friday, March 21, 2014 6:22 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org; Pedro Alves (palves@redhat.com)
> Subject: Re: [PATCH 2/2] btrace: avoid symbol lookup
>
> On Tue, 11 Mar 2014 11:08:43 +0100, Metzger, Markus T wrote:
> > What's missing is a "fast fail", i.e. quickly determine that we won't find any
> > symbol for this PC. I won't be able to do this in a reasonable amount of
> time,
> > though, so I thought this patch is a compromise between functionality and
> > performance.
>
> I do not think providing incorrect behavior for performance reasons is a valid
> tradeoff. The right way would be to fix the DWARF lookups to be fast
> enough.
I realized after I sent this that the word 'functionality' was not chosen well.
The only actual change in functionality I was able to observe was missing
parens for the main function, i.e. it had been printed "main()" and is now
printed "main". That's because its language is 'auto' and not 'c' or 'cpp'.
I believe that this could and should be fixed by fixing up the language of
the main mini-symbol to align with the language of other symbols in the
same object file.
I think the compromise is rather between a nice, general solution that
benefits everybody and a local solution that only benefits btrace and that
might make supporting inline functions more difficult in the future.
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-24 7:57 ` Metzger, Markus T
@ 2014-03-24 8:37 ` Jan Kratochvil
2014-03-24 9:21 ` Metzger, Markus T
0 siblings, 1 reply; 13+ messages in thread
From: Jan Kratochvil @ 2014-03-24 8:37 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches, Pedro Alves (palves@redhat.com)
On Mon, 24 Mar 2014 08:55:33 +0100, Metzger, Markus T wrote:
> > I do not think providing incorrect behavior for performance reasons is a valid
> > tradeoff. The right way would be to fix the DWARF lookups to be fast
> > enough.
[...]
> The only actual change in functionality I was able to observe was missing
> parens for the main function,
I agree in 99.9% of usecases it will work the same. This still does not prove
it is correct.
I believe I can create a reproducer with two overlapping functions:
0..1: a()
2..3: b()
4..6: a()
7..8: b()
properly describe by DW_AT_ranges which will work with former GDB but which
will no longer work with patched GDB.
This may definitely happen for some user .S code with hand-coded DWARF.
I do not say it necessarilly happens with any real world compiler output.
This may happen for gdb.dwarf2/dw2-objfile-overlap.exp which comes from a real
world case of Linux kernel modules mapping.
But maybe I miss something and I would fail to create the reproducer, if you
do not agree I can create a .S with hand coded DWARF I can try to create one.
Corner cases are the ones most difficult to debug and it is a pity when
debugger provides incorrect output in such corner cases.
As I said maybe this compromise is acceptable as it may not be hit in real
world usage cases but I do not want to make this decision.
> I think the compromise is rather between a nice, general solution that
> benefits everybody and a local solution that only benefits btrace
This is the second reason why I did not agree with the patch. GDB needs to be
faster and if this PC->functionname mapping can be accelerated such way then
it should be done globally.
Regards,
Jan
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/2] btrace: avoid symbol lookup
2014-03-24 8:37 ` Jan Kratochvil
@ 2014-03-24 9:21 ` Metzger, Markus T
0 siblings, 0 replies; 13+ messages in thread
From: Metzger, Markus T @ 2014-03-24 9:21 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, Pedro Alves (palves@redhat.com)
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Monday, March 24, 2014 9:37 AM
> On Mon, 24 Mar 2014 08:55:33 +0100, Metzger, Markus T wrote:
> > > I do not think providing incorrect behavior for performance reasons is a
> valid
> > > tradeoff. The right way would be to fix the DWARF lookups to be fast
> > > enough.
> [...]
> > The only actual change in functionality I was able to observe was missing
> > parens for the main function,
>
> I agree in 99.9% of usecases it will work the same. This still does not prove
> it is correct.
>
> I believe I can create a reproducer with two overlapping functions:
> 0..1: a()
> 2..3: b()
> 4..6: a()
> 7..8: b()
> properly describe by DW_AT_ranges which will work with former GDB but
> which
> will no longer work with patched GDB.
>
> This may definitely happen for some user .S code with hand-coded DWARF.
> I do not say it necessarilly happens with any real world compiler output.
>
> This may happen for gdb.dwarf2/dw2-objfile-overlap.exp which comes from
> a real
> world case of Linux kernel modules mapping.
>
> But maybe I miss something and I would fail to create the reproducer, if you
> do not agree I can create a .S with hand coded DWARF I can try to create one.
No need. I certainly agree that one can write such an assembly file and that
one can describe this in DWARF but not in ELF.
To describe this in ELF one would split a and b and thus end up with 4 functions -
that's what compilers seem to be doing today. And they also seem to emit
DWARF that describes it that way.
> Corner cases are the ones most difficult to debug and it is a pity when
> debugger provides incorrect output in such corner cases.
I agree.
> As I said maybe this compromise is acceptable as it may not be hit in real
> world usage cases but I do not want to make this decision.
If you just look hard enough, I guess you will find everything somewhere.
Those who use compilers, on the other hand, may not even be able to
tell the difference - except that it's faster which allows them to use
bigger buffers and thus record longer traces.
> > I think the compromise is rather between a nice, general solution that
> > benefits everybody and a local solution that only benefits btrace
>
> This is the second reason why I did not agree with the patch. GDB needs to
> be
> faster and if this PC->functionname mapping can be accelerated such way
> then
> it should be done globally.
The specific problem of btrace is that it needs to do a huge number of symbol
lookups within a single GDB command. I do not know any other GDB command
that gets anywhere near to that.
Regards,
Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2014-03-24 9:21 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-07 8:57 [PATCH 0/2] btrace: perf improvements Markus Metzger
2014-03-07 8:57 ` [PATCH 1/2] btrace: only search for lines in current symtab Markus Metzger
2014-03-21 17:43 ` Jan Kratochvil
2014-03-07 8:57 ` [PATCH 2/2] btrace: avoid symbol lookup Markus Metzger
2014-03-07 15:55 ` Pedro Alves
2014-03-10 8:05 ` Metzger, Markus T
2014-03-07 15:56 ` Pedro Alves
2014-03-10 21:43 ` Jan Kratochvil
2014-03-11 10:08 ` Metzger, Markus T
2014-03-21 17:22 ` Jan Kratochvil
2014-03-24 7:57 ` Metzger, Markus T
2014-03-24 8:37 ` Jan Kratochvil
2014-03-24 9:21 ` Metzger, Markus T
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox