* [patch 04/12] entryval#3: Virtual tail call frames
@ 2011-09-29 19:50 Jan Kratochvil
2011-10-09 19:27 ` [commit] " Jan Kratochvil
2011-10-10 13:40 ` doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames) Ulrich Weigand
0 siblings, 2 replies; 23+ messages in thread
From: Jan Kratochvil @ 2011-09-29 19:50 UTC (permalink / raw)
To: gdb-patches
Hi,
[patch 04/12+doc] entryval#2: Virtual tail call frames
http://sourceware.org/ml/gdb-patches/2011-09/msg00226.html
doc updates by Eli, new examples in the doc, more output on `set debug
entry-values', move the debugging output to earlier patch part.
Thanks,
Jan
gdb/
2011-09-13 Jan Kratochvil <jan.kratochvil@redhat.com>
Recognize virtual tail call frames.
* Makefile.in (SFILES): Add dwarf2-frame-tailcall.c.
(HFILES_NO_SRCDIR): Add dwarf2-frame-tailcall.h.
(COMMON_OBS): Add dwarf2-frame-tailcall.o.
* dwarf2-frame-tailcall.c: New file.
* dwarf2-frame-tailcall.h: New file.
* dwarf2-frame.c: Include dwarf2-frame-tailcall.h.
(execute_cfa_program): New function comment. Return INSN_PTR. Reset
REGS.PREV only after CIE execution.
(struct dwarf2_frame_cache): New field tailcall_cache.
(dwarf2_frame_cache): New variables entry_pc, entry_cfa_sp_offset,
entry_cfa_sp_offset_p and instr. Execute FDE instructions in two
parts, try to find entry_cfa_sp_offset. Call
dwarf2_tailcall_sniffer_first.
(dwarf2_frame_prev_register): Call dwarf2_tailcall_prev_register_first
when appropriate.
(dwarf2_frame_dealloc_cache): New function.
(dwarf2_frame_sniffer): Preinitialize cache by dwarf2_frame_cache.
(dwarf2_frame_unwind): Install dwarf2_frame_dealloc_cache.
(dwarf2_signal_frame_unwind): Do not install dwarf2_frame_dealloc_cache.
(dwarf2_append_unwinders): Add dwarf2_tailcall_frame_unwind.
(dwarf2_frame_cfa): Support also dwarf2_tailcall_frame_unwind.
* dwarf2loc.c (func_addr_to_tail_call_list)
(tailcall_dump, call_sitep, VEC (call_sitep), chain_candidate)
(call_site_find_chain_1, call_site_find_chain): New.
* dwarf2loc.h (struct call_site_chain): New.
(call_site_find_chain): New declaration.
* frame.c (get_frame_address_in_block): Support also TAILCALL_FRAME.
* frame.h (enum frame_type): New entry TAILCALL_FRAME.
* python/py-frame.c (gdbpy_initialize_frames): Add TAILCALL_FRAME.
* stack.c (frame_info): Support also TAILCALL_FRAME.
gdb/doc/
2011-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
Eli Zaretskii <eliz@gnu.org>
Recognize virtual tail call frames.
* gdb.texinfo (Optimized Code): Add reference to Tail Call Frames.
(Tail Call Frames): New node.
(Frames In Python): Add gdb.TAILCALL_FRAME.
gdb/testsuite/
2011-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
Recognize virtual tail call frames.
* gdb.arch/amd64-entry-value.cc (c, a, b, amb_z, amb_y, amb_x, amb)
(amb_b, amb_a): New.
(main): Call a and b.
* gdb.arch/amd64-entry-value.exp (tailcall: breakhere, tailcall: bt)
(tailcall: p i, tailcall: p j, set $sp0=$sp, up, p $sp0 == $sp, frame 3)
(p $sp0 + sizeof (void *) == $sp, ambiguous: breakhere, ambiguous: bt):
New tests.
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -695,6 +695,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
cp-name-parser.y \
dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
+ dwarf2-frame-tailcall.c \
elfread.c environ.c eval.c event-loop.c event-top.c \
exceptions.c expprint.c \
f-exp.y f-lang.c f-typeprint.c f-valprint.c filesystem.c \
@@ -771,7 +772,7 @@ cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h cli/cli-utils.h \
cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
gnulib/string.in.h gnulib/str-two-way.h \
gnulib/stdint.in.h remote.h gdb.h sparc-nat.h \
-gdbthread.h dwarf2-frame.h nbsd-nat.h dcache.h \
+gdbthread.h dwarf2-frame.h dwarf2-frame-tailcall.h nbsd-nat.h dcache.h \
amd64-nat.h s390-tdep.h arm-linux-tdep.h exceptions.h macroscope.h \
gdbarch.h bsd-uthread.h gdb_stat.h memory-map.h memrange.h \
mdebugread.h m88k-tdep.h stabsread.h hppa-linux-offsets.h linux-fork.h \
@@ -879,7 +880,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \
dbxread.o coffread.o coff-pe-read.o \
dwarf2read.o mipsread.o stabsread.o corefile.o \
- dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
+ dwarf2expr.o dwarf2loc.o dwarf2-frame.o dwarf2-frame-tailcall.o \
ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
ada-tasks.o \
ui-out.o cli-out.o \
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9486,6 +9486,7 @@ please report it to us as a bug (including a test case!).
@menu
* Inline Functions:: How @value{GDBN} presents inlining
+* Tail Call Frames:: @value{GDBN} analysis of jumps to functions
@end menu
@node Inline Functions
@@ -9553,6 +9554,126 @@ and print a variable where your program stored the return value.
@end itemize
+@node Tail Call Frames
+@section Tail Call Frames
+@cindex tail call frames, debugging
+
+Function @code{B} can call function @code{C} in its very last statement. In
+unoptimized compilation the call of @code{C} is immediately followed by return
+instruction at the end of @code{B} code. Optimizing compiler may replace the
+call and return in function @code{B} into one jump to function @code{C}
+instead. Such use of a jump instruction is called @dfn{tail call}.
+
+During execution of function @code{C}, there will be no indication in the
+function call stack frames that it was tail-called from @code{B}. If function
+@code{A} regularly calls function @code{B} which tail-calls function @code{C},
+then @value{GDBN} will see @code{A} as the caller of @code{C}. However, in
+some cases @value{GDBN} can determine that @code{C} was tail-called from
+@code{B}, and it will then create fictitious call frame for that, with the
+return address set up as if @code{B} called @code{C} normally.
+
+This functionality is currently supported only by DWARF 2 debugging format and
+the compiler has to produce @samp{DW_TAG_GNU_call_site} tags. With
+@value{NGCC}, you need to specify @option{-O -g} during compilation, to get
+this information.
+
+@kbd{info frame} command (@pxref{Frame Info}) will indicate the tail call frame
+kind by text @code{tail call frame} such as in this sample @value{GDBN} output:
+
+@smallexample
+(gdb) x/i $pc - 2
+ 0x40066b <b(int, double)+11>: jmp 0x400640 <c(int, double)>
+(gdb) info frame
+Stack level 1, frame at 0x7fffffffda30:
+ rip = 0x40066d in b (amd64-entry-value.cc:59); saved rip 0x4004c5
+ tail call frame, caller of frame at 0x7fffffffda30
+ source language c++.
+ Arglist at unknown address.
+ Locals at unknown address, Previous frame's sp is 0x7fffffffda30
+@end smallexample
+
+The detection of all the possible code path executions can find them ambiguous.
+There is no execution history stored (possible @ref{Reverse Execution} is never
+used for this purpose) and the last known caller could have reached the known
+callee by multiple different jump sequences. In such case @value{GDBN} still
+tries to show at least all the unambiguous top tail callers and all the
+unambiguous bottom tail calees, if any.
+
+@table @code
+@item set debug entry-values
+@kindex set debug entry-values
+When set to on, enables printing of analysis messages for both frame argument
+values at function entry and tail calls. It will show all the possible valid
+tail calls code paths it has considered. It will also print the intersection
+of them with the final unambiguous (possibly partial or even empty) code path
+result.
+
+@item show debug entry-values
+@kindex show debug entry-values
+Show the current state of analysis messages printing for both frame argument
+values at function entry and tail calls.
+@end table
+
+The analysis messages for tail calls can for example show why the virtual tail
+call frame for function @code{c} has not been recognized (due to the indirect
+reference by variable @code{x}):
+
+@smallexample
+static void __attribute__((noinline, noclone)) c (void);
+void (*x) (void) = c;
+static void __attribute__((noinline, noclone)) a (void) @{ x++; @}
+static void __attribute__((noinline, noclone)) c (void) @{ a (); @}
+int main (void) @{ x (); return 0; @}
+
+Breakpoint 1, DW_OP_GNU_entry_value resolving cannot find
+DW_TAG_GNU_call_site 0x40039a in main
+a () at t.c:3
+3 static void __attribute__((noinline, noclone)) a (void) @{ x++; @}
+(gdb) bt
+#0 a () at t.c:3
+#1 0x000000000040039a in main () at t.c:5
+@end smallexample
+
+Another possibility is an ambiguous virtual tail call frames resolution:
+
+@smallexample
+int i;
+static void __attribute__((noinline, noclone)) f (void) @{ i++; @}
+static void __attribute__((noinline, noclone)) e (void) @{ f (); @}
+static void __attribute__((noinline, noclone)) d (void) @{ f (); @}
+static void __attribute__((noinline, noclone)) c (void) @{ d (); @}
+static void __attribute__((noinline, noclone)) b (void)
+@{ if (i) c (); else e (); @}
+static void __attribute__((noinline, noclone)) a (void) @{ b (); @}
+int main (void) @{ a (); return 0; @}
+
+tailcall: initial: 0x4004d2(a) 0x4004ce(b) 0x4004b2(c) 0x4004a2(d)
+tailcall: compare: 0x4004d2(a) 0x4004cc(b) 0x400492(e)
+tailcall: reduced: 0x4004d2(a) |
+(gdb) bt
+#0 f () at t.c:2
+#1 0x00000000004004d2 in a () at t.c:8
+#2 0x0000000000400395 in main () at t.c:9
+@end smallexample
+
+Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
+possible execution paths
+@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
+@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
+one from the inferior state.
+
+@code{initial:} state shows some random possible calling sequence @value{GDBN}
+has found. It then finds another possible calling sequcen - that one is
+prefixed by @code{compare:}. The non-ambiguous intersection of these two is
+printed as the @code{reduced:} calling sequence. That one could have many
+futher @code{compare:} and @code{reduced:} statements as long as there remain
+any non-ambiguous sequence entries.
+
+For the frame of function @code{b} in both cases there are different possible
+@code{$pc} values (@code{0x4004cc} or @code{0x4004ce}), therefore this frame is
+also ambigous. The only non-ambiguous frame is the one for function @code{a},
+therefore this one is displayed to the user while the ambiguous frames are
+omitted.
@node Macros
@chapter C Preprocessor Macros
@@ -23080,6 +23201,9 @@ inferior function call.
A frame representing an inlined function. The function was inlined
into a @code{gdb.NORMAL_FRAME} that is older than this one.
+@item gdb.TAILCALL_FRAME
+A frame representing a tail call. @xref{Tail Call Frames}.
+
@item gdb.SIGTRAMP_FRAME
A signal trampoline frame. This is the frame created by the OS when
it calls into a signal handler.
--- /dev/null
+++ b/gdb/dwarf2-frame-tailcall.c
@@ -0,0 +1,479 @@
+/* Virtual tail call frames unwinder for GDB.
+
+ Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#include "defs.h"
+#include "gdb_assert.h"
+#include "frame.h"
+#include "dwarf2-frame-tailcall.h"
+#include "dwarf2loc.h"
+#include "frame-unwind.h"
+#include "block.h"
+#include "hashtab.h"
+#include "exceptions.h"
+#include "gdbtypes.h"
+#include "regcache.h"
+#include "value.h"
+
+/* Contains struct tailcall_cache indexed by next_bottom_frame. */
+static htab_t cache_htab;
+
+/* Associate structure of the unwinder to call_site_chain. Lifetime of this
+ structure is maintained by REFC decremented by dealloc_cache, all of them
+ get deleted during reinit_frame_cache. */
+struct tailcall_cache
+{
+ /* It must be the first one of this struct. It is the furthest callee. */
+ struct frame_info *next_bottom_frame;
+
+ /* Reference count. The whole chain of virtual tail call frames shares one
+ tailcall_cache. */
+ int refc;
+
+ /* Associated found virtual taill call frames chain, it is never NULL. */
+ struct call_site_chain *chain;
+
+ /* Cached pretended_chain_levels result. */
+ int chain_levels;
+
+ /* Unwound PC from the top (caller) frame, as it is not contained
+ in CHAIN. */
+ CORE_ADDR prev_pc;
+
+ /* Compensate SP in caller frames appropriately. prev_sp and
+ entry_cfa_sp_offset are valid only if PREV_SP_P. PREV_SP is SP at the top
+ (caller) frame. ENTRY_CFA_SP_OFFSET is shift of SP in tail call frames
+ against next_bottom_frame SP. */
+ unsigned prev_sp_p : 1;
+ CORE_ADDR prev_sp;
+ LONGEST entry_cfa_sp_offset;
+};
+
+/* hash_f for htab_create_alloc of cache_htab. */
+
+static hashval_t
+cache_hash (const void *arg)
+{
+ const struct tailcall_cache *cache = arg;
+
+ return htab_hash_pointer (cache->next_bottom_frame);
+}
+
+/* eq_f for htab_create_alloc of cache_htab. */
+
+static int
+cache_eq (const void *arg1, const void *arg2)
+{
+ const struct tailcall_cache *cache1 = arg1;
+ const struct tailcall_cache *cache2 = arg2;
+
+ return cache1->next_bottom_frame == cache2->next_bottom_frame;
+}
+
+/* Create new tailcall_cache for NEXT_BOTTOM_FRAME, NEXT_BOTTOM_FRAME must not
+ yet have been indexed by cache_htab. Caller holds one reference of the new
+ tailcall_cache. */
+
+static struct tailcall_cache *
+cache_new_ref1 (struct frame_info *next_bottom_frame)
+{
+ struct tailcall_cache *cache;
+ void **slot;
+
+ cache = xzalloc (sizeof (*cache));
+
+ cache->next_bottom_frame = next_bottom_frame;
+ cache->refc = 1;
+
+ slot = htab_find_slot (cache_htab, cache, INSERT);
+ gdb_assert (*slot == NULL);
+ *slot = cache;
+
+ return cache;
+}
+
+/* Create new reference to CACHE. */
+
+static void
+cache_ref (struct tailcall_cache *cache)
+{
+ gdb_assert (cache->refc > 0);
+
+ cache->refc++;
+}
+
+/* Drop reference to CACHE, possibly fully freeing it and unregistering it from
+ cache_htab. */
+
+static void
+cache_unref (struct tailcall_cache *cache)
+{
+ gdb_assert (cache->refc > 0);
+
+ if (!--cache->refc)
+ {
+ gdb_assert (htab_find_slot (cache_htab, cache, NO_INSERT) != NULL);
+ htab_remove_elt (cache_htab, cache);
+
+ xfree (cache->chain);
+ xfree (cache);
+ }
+}
+
+/* Return 1 if FI is a non-bottom (not the callee) tail call frame. Otherwise
+ return 0. */
+
+static int
+frame_is_tailcall (struct frame_info *fi)
+{
+ return frame_unwinder_is (fi, &dwarf2_tailcall_frame_unwind);
+}
+
+/* Try to find tailcall_cache in cache_htab if FI is a part of its virtual tail
+ call chain. Otherwise return NULL. No new reference is created. */
+
+static struct tailcall_cache *
+cache_find (struct frame_info *fi)
+{
+ struct tailcall_cache *cache;
+ void **slot;
+
+ while (frame_is_tailcall (fi))
+ {
+ fi = get_next_frame (fi);
+ gdb_assert (fi != NULL);
+ }
+
+ slot = htab_find_slot (cache_htab, &fi, NO_INSERT);
+ if (slot == NULL)
+ return NULL;
+
+ cache = *slot;
+ gdb_assert (cache != NULL);
+ return cache;
+}
+
+/* Number of virtual frames between THIS_FRAME and CACHE->NEXT_BOTTOM_FRAME.
+ If THIS_FRAME is CACHE-> NEXT_BOTTOM_FRAME return -1. */
+
+static int
+existing_next_levels (struct frame_info *this_frame,
+ struct tailcall_cache *cache)
+{
+ int retval = (frame_relative_level (this_frame)
+ - frame_relative_level (cache->next_bottom_frame) - 1);
+
+ gdb_assert (retval >= -1);
+
+ return retval;
+}
+
+/* The number of virtual tail call frames in CHAIN. With no virtual tail call
+ frames the function would return 0 (but CHAIN does not exist in such
+ case). */
+
+static int
+pretended_chain_levels (struct call_site_chain *chain)
+{
+ int chain_levels;
+
+ gdb_assert (chain != NULL);
+
+ if (chain->callers == chain->length && chain->callees == chain->length)
+ return chain->length;
+
+ chain_levels = chain->callers + chain->callees;
+ gdb_assert (chain_levels < chain->length);
+
+ return chain_levels;
+}
+
+/* Implementation of frame_this_id_ftype. THIS_CACHE must be already
+ initialized with tailcall_cache, THIS_FRAME must be a part of THIS_CACHE.
+
+ Specific virtual tail call frames are tracked by INLINE_DEPTH. */
+
+static void
+tailcall_frame_this_id (struct frame_info *this_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct tailcall_cache *cache = *this_cache;
+ struct frame_info *next_frame;
+
+ /* Tail call does not make sense for a sentinel frame. */
+ next_frame = get_next_frame (this_frame);
+ gdb_assert (next_frame != NULL);
+
+ *this_id = get_frame_id (next_frame);
+ (*this_id).code_addr = get_frame_pc (this_frame);
+ (*this_id).code_addr_p = 1;
+ (*this_id).inline_depth = (cache->chain_levels
+ - existing_next_levels (this_frame, cache));
+ gdb_assert ((*this_id).inline_depth > 0);
+}
+
+/* Find PC to be unwound from THIS_FRAME. THIS_FRAME must be a part of
+ CACHE. */
+
+static CORE_ADDR
+pretend_pc (struct frame_info *this_frame, struct tailcall_cache *cache)
+{
+ int next_levels = existing_next_levels (this_frame, cache);
+ struct call_site_chain *chain = cache->chain;
+ int caller_no;
+
+ gdb_assert (chain != NULL);
+
+ next_levels++;
+ gdb_assert (next_levels >= 0);
+
+ if (next_levels < chain->callees)
+ return chain->call_site[chain->length - next_levels - 1]->pc;
+ next_levels -= chain->callees;
+
+ /* Otherwise CHAIN->CALLEES are already covered by CHAIN->CALLERS. */
+ if (chain->callees != chain->length)
+ {
+ if (next_levels < chain->callers)
+ return chain->call_site[chain->callers - next_levels - 1]->pc;
+ next_levels -= chain->callers;
+ }
+
+ gdb_assert (next_levels == 0);
+ return cache->prev_pc;
+}
+
+/* Implementation of frame_prev_register_ftype. If no specific register
+ override is supplied NULL is returned (this is incompatible with
+ frame_prev_register_ftype semantics). next_bottom_frame and tail call
+ frames unwind the NULL case differently. */
+
+struct value *
+dwarf2_tailcall_prev_register_first (struct frame_info *this_frame,
+ void **tailcall_cachep, int regnum)
+{
+ struct gdbarch *this_gdbarch = get_frame_arch (this_frame);
+ struct tailcall_cache *cache = *tailcall_cachep;
+ CORE_ADDR addr;
+
+ if (regnum == gdbarch_pc_regnum (this_gdbarch))
+ addr = pretend_pc (this_frame, cache);
+ else if (cache->prev_sp_p && regnum == gdbarch_sp_regnum (this_gdbarch))
+ {
+ int next_levels = existing_next_levels (this_frame, cache);
+
+ if (next_levels == cache->chain_levels - 1)
+ addr = cache->prev_sp;
+ else
+ addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset;
+ }
+ else
+ return NULL;
+
+ return frame_unwind_got_address (this_frame, regnum, addr);
+}
+
+/* Implementation of frame_prev_register_ftype for tail call frames. Register
+ set of virtual tail call frames is assumed to be the one of the top (caller)
+ frame - assume unchanged register value for NULL from
+ dwarf2_tailcall_prev_register_first. */
+
+static struct value *
+tailcall_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
+{
+ struct tailcall_cache *cache = *this_cache;
+ struct value *val;
+
+ gdb_assert (this_frame != cache->next_bottom_frame);
+
+ val = dwarf2_tailcall_prev_register_first (this_frame, this_cache, regnum);
+ if (val)
+ return val;
+
+ return frame_unwind_got_register (this_frame, regnum, regnum);
+}
+
+/* Implementation of frame_sniffer_ftype. It will never find a new chain, use
+ dwarf2_tailcall_sniffer_first for the bottom (callee) frame. It will find
+ all the predecessing virtual tail call frames, it will return false when
+ there exist no more tail call frames in this chain. */
+
+static int
+tailcall_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **this_cache)
+{
+ struct frame_info *next_frame;
+ int next_levels;
+ struct tailcall_cache *cache;
+
+ /* Inner tail call element does not make sense for a sentinel frame. */
+ next_frame = get_next_frame (this_frame);
+ if (next_frame == NULL)
+ return 0;
+
+ cache = cache_find (next_frame);
+ if (cache == NULL)
+ return 0;
+
+ cache_ref (cache);
+
+ next_levels = existing_next_levels (this_frame, cache);
+
+ /* NEXT_LEVELS is -1 only in dwarf2_tailcall_sniffer_first. */
+ gdb_assert (next_levels >= 0);
+ gdb_assert (next_levels <= cache->chain_levels);
+
+ if (next_levels == cache->chain_levels)
+ {
+ cache_unref (cache);
+ return 0;
+ }
+
+ *this_cache = cache;
+ return 1;
+}
+
+/* The initial "sniffer" whether THIS_FRAME is a bottom (callee) frame of a new
+ chain to create. Keep TAILCALL_CACHEP NULL if it did not find any chain,
+ initialize it otherwise. No tail call chain is created if there are no
+ unambiguous virtual tail call frames to report.
+
+ ENTRY_CFA_SP_OFFSETP is NULL if no special SP handling is possible,
+ otherwise *ENTRY_CFA_SP_OFFSETP is the number of bytes to subtract from tail
+ call frames frame base to get the SP value there - to simulate return
+ address pushed on the stack. */
+
+void
+dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
+ void **tailcall_cachep,
+ const LONGEST *entry_cfa_sp_offsetp)
+{
+ CORE_ADDR prev_pc = 0, prev_sp = 0; /* GCC warning. */
+ int prev_sp_p = 0;
+ CORE_ADDR this_pc, pc;
+ struct gdbarch *prev_gdbarch;
+ struct call_site_chain *chain = NULL;
+ struct frame_info *fi;
+ struct tailcall_cache *cache;
+ volatile struct gdb_exception except;
+
+ gdb_assert (*tailcall_cachep == NULL);
+
+ this_pc = get_frame_pc (this_frame);
+
+ /* Catch any unwinding errors. */
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ int pc_regnum, sp_regnum;
+
+ prev_gdbarch = frame_unwind_arch (this_frame);
+ pc_regnum = gdbarch_pc_regnum (prev_gdbarch);
+ if (pc_regnum == -1)
+ break;
+
+ /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */
+ prev_pc = frame_unwind_register_unsigned (this_frame, pc_regnum);
+
+ /* call_site_find_chain can throw an exception. */
+ chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc);
+
+ if (entry_cfa_sp_offsetp == NULL)
+ break;
+ sp_regnum = gdbarch_sp_regnum (prev_gdbarch);
+ if (sp_regnum == -1)
+ break;
+ prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum);
+ prev_sp_p = 1;
+ }
+ if (except.reason < 0)
+ {
+ if (entry_values_debug)
+ exception_print (gdb_stdout, except);
+ return;
+ }
+
+ /* Ambiguous unwind or unambiguous unwind verified as matching. */
+ if (chain == NULL || chain->length == 0)
+ {
+ xfree (chain);
+ return;
+ }
+
+ cache = cache_new_ref1 (this_frame);
+ *tailcall_cachep = cache;
+ cache->chain = chain;
+ cache->prev_pc = prev_pc;
+ cache->chain_levels = pretended_chain_levels (chain);
+ cache->prev_sp_p = prev_sp_p;
+ if (cache->prev_sp_p)
+ {
+ cache->prev_sp = prev_sp;
+ cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp;
+ }
+ gdb_assert (cache->chain_levels > 0);
+}
+
+/* Implementation of frame_dealloc_cache_ftype. It can be called even for the
+ bottom chain frame from dwarf2_frame_dealloc_cache which is not a real
+ TAILCALL_FRAME. */
+
+static void
+tailcall_frame_dealloc_cache (struct frame_info *self, void *this_cache)
+{
+ struct tailcall_cache *cache = this_cache;
+
+ cache_unref (cache);
+}
+
+/* Implementation of frame_prev_arch_ftype. We assume all the virtual tail
+ call frames have gdbarch of the bottom (callee) frame. */
+
+static struct gdbarch *
+tailcall_frame_prev_arch (struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ struct tailcall_cache *cache = *this_prologue_cache;
+
+ return get_frame_arch (cache->next_bottom_frame);
+}
+
+/* Virtual tail call frame unwinder if dwarf2_tailcall_sniffer_first finds
+ a chain to create. */
+
+const struct frame_unwind dwarf2_tailcall_frame_unwind =
+{
+ TAILCALL_FRAME,
+ default_frame_unwind_stop_reason,
+ tailcall_frame_this_id,
+ tailcall_frame_prev_register,
+ NULL,
+ tailcall_frame_sniffer,
+ tailcall_frame_dealloc_cache,
+ tailcall_frame_prev_arch
+};
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_tailcall_frame;
+
+void
+_initialize_tailcall_frame (void)
+{
+ cache_htab = htab_create_alloc (50, cache_hash, cache_eq, NULL, xcalloc,
+ xfree);
+}
--- /dev/null
+++ b/gdb/dwarf2-frame-tailcall.h
@@ -0,0 +1,39 @@
+/* Definitions for virtual tail call frames unwinder for GDB.
+
+ Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef DWARF2_FRAME_TAILCALL_H
+#define DWARF2_FRAME_TAILCALL_H 1
+
+struct frame_info;
+struct frame_unwind;
+
+/* The tail call frame unwinder. */
+
+extern void
+ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
+ void **tailcall_cachep,
+ const LONGEST *entry_cfa_sp_offsetp);
+
+extern struct value *
+ dwarf2_tailcall_prev_register_first (struct frame_info *this_frame,
+ void **tailcall_cachep, int regnum);
+
+extern const struct frame_unwind dwarf2_tailcall_frame_unwind;
+
+#endif /* !DWARF2_FRAME_TAILCALL_H */
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -41,6 +41,7 @@
#include "ax.h"
#include "dwarf2loc.h"
#include "exceptions.h"
+#include "dwarf2-frame-tailcall.h"
struct comp_unit;
@@ -398,7 +399,11 @@ Not implemented: computing unwound register using explicit value operator"));
}
\f
-static void
+/* Execute FDE program from INSN_PTR possibly up to INSN_END or up to inferior
+ PC. Modify FS state accordingly. Return current INSN_PTR where the
+ execution has stopped, one can resume it on the next call. */
+
+static const gdb_byte *
execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
const gdb_byte *insn_end, struct gdbarch *gdbarch,
CORE_ADDR pc, struct dwarf2_frame_state *fs)
@@ -681,9 +686,14 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
}
}
- /* Don't allow remember/restore between CIE and FDE programs. */
- dwarf2_frame_state_free_regs (fs->regs.prev);
- fs->regs.prev = NULL;
+ if (fs->initial.reg == NULL)
+ {
+ /* Don't allow remember/restore between CIE and FDE programs. */
+ dwarf2_frame_state_free_regs (fs->regs.prev);
+ fs->regs.prev = NULL;
+ }
+
+ return insn_ptr;
}
\f
@@ -975,6 +985,13 @@ struct dwarf2_frame_cache
/* The .text offset. */
CORE_ADDR text_offset;
+
+ /* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME
+ sequence. If NULL then it is a normal case with no TAILCALL_FRAME
+ involved. Non-bottom frames of a virtual tail call frames chain use
+ dwarf2_tailcall_frame_unwind unwinder so this field does not apply for
+ them. */
+ void *tailcall_cache;
};
static struct dwarf2_frame_cache *
@@ -988,6 +1005,10 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
struct dwarf2_frame_state *fs;
struct dwarf2_fde *fde;
volatile struct gdb_exception ex;
+ CORE_ADDR entry_pc;
+ LONGEST entry_cfa_sp_offset;
+ int entry_cfa_sp_offset_p = 0;
+ const gdb_byte *instr;
if (*this_cache)
return *this_cache;
@@ -1039,8 +1060,25 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
fs->initial = fs->regs;
fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs);
+ if (get_frame_func_if_available (this_frame, &entry_pc))
+ {
+ /* Decode the insns in the FDE up to the entry PC. */
+ instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
+ entry_pc, fs);
+
+ if (fs->regs.cfa_how == CFA_REG_OFFSET
+ && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg)
+ == gdbarch_sp_regnum (gdbarch)))
+ {
+ entry_cfa_sp_offset = fs->regs.cfa_offset;
+ entry_cfa_sp_offset_p = 1;
+ }
+ }
+ else
+ instr = fde->instructions;
+
/* Then decode the insns in the FDE up to our target PC. */
- execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
+ execute_cfa_program (fde, instr, fde->end, gdbarch,
get_frame_pc (this_frame), fs);
TRY_CATCH (ex, RETURN_MASK_ERROR)
@@ -1181,6 +1219,12 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"),
do_cleanups (old_chain);
+ /* Try to find a virtual tail call frames chain with bottom (callee) frame
+ starting at THIS_FRAME. */
+ dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
+ (entry_cfa_sp_offset_p
+ ? &entry_cfa_sp_offset : NULL));
+
return cache;
}
@@ -1226,6 +1270,22 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
CORE_ADDR addr;
int realnum;
+ /* Non-bottom frames of a virtual tail call frames chain use
+ dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
+ them. If dwarf2_tailcall_prev_register_first does not have specific value
+ unwind the register, tail call frames are assumed to have the register set
+ of the top caller. */
+ if (cache->tailcall_cache)
+ {
+ struct value *val;
+
+ val = dwarf2_tailcall_prev_register_first (this_frame,
+ &cache->tailcall_cache,
+ regnum);
+ if (val)
+ return val;
+ }
+
switch (cache->reg[regnum].how)
{
case DWARF2_FRAME_REG_UNDEFINED:
@@ -1295,6 +1355,18 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
}
}
+/* Proxy for tailcall_frame_dealloc_cache for bottom frame of a virtual tail
+ call frames chain. */
+
+static void
+dwarf2_frame_dealloc_cache (struct frame_info *self, void *this_cache)
+{
+ struct dwarf2_frame_cache *cache = dwarf2_frame_cache (self, &this_cache);
+
+ if (cache->tailcall_cache)
+ dwarf2_tailcall_frame_unwind.dealloc_cache (self, cache->tailcall_cache);
+}
+
static int
dwarf2_frame_sniffer (const struct frame_unwind *self,
struct frame_info *this_frame, void **this_cache)
@@ -1321,7 +1393,14 @@ dwarf2_frame_sniffer (const struct frame_unwind *self,
this_frame))
return self->type == SIGTRAMP_FRAME;
- return self->type != SIGTRAMP_FRAME;
+ if (self->type != NORMAL_FRAME)
+ return 0;
+
+ /* Preinitializa the cache so that TAILCALL_FRAME can find the record by
+ dwarf2_tailcall_sniffer_first. */
+ dwarf2_frame_cache (this_frame, this_cache);
+
+ return 1;
}
static const struct frame_unwind dwarf2_frame_unwind =
@@ -1331,7 +1410,8 @@ static const struct frame_unwind dwarf2_frame_unwind =
dwarf2_frame_this_id,
dwarf2_frame_prev_register,
NULL,
- dwarf2_frame_sniffer
+ dwarf2_frame_sniffer,
+ dwarf2_frame_dealloc_cache
};
static const struct frame_unwind dwarf2_signal_frame_unwind =
@@ -1341,7 +1421,10 @@ static const struct frame_unwind dwarf2_signal_frame_unwind =
dwarf2_frame_this_id,
dwarf2_frame_prev_register,
NULL,
- dwarf2_frame_sniffer
+ dwarf2_frame_sniffer,
+
+ /* TAILCALL_CACHE can never be in such frame to need dealloc_cache. */
+ NULL
};
/* Append the DWARF-2 frame unwinders to GDBARCH's list. */
@@ -1349,6 +1432,10 @@ static const struct frame_unwind dwarf2_signal_frame_unwind =
void
dwarf2_append_unwinders (struct gdbarch *gdbarch)
{
+ /* TAILCALL_FRAME must be first to find the record by
+ dwarf2_tailcall_sniffer_first. */
+ frame_unwind_append_unwinder (gdbarch, &dwarf2_tailcall_frame_unwind);
+
frame_unwind_append_unwinder (gdbarch, &dwarf2_frame_unwind);
frame_unwind_append_unwinder (gdbarch, &dwarf2_signal_frame_unwind);
}
@@ -1400,7 +1487,8 @@ dwarf2_frame_cfa (struct frame_info *this_frame)
/* This restriction could be lifted if other unwinders are known to
compute the frame base in a way compatible with the DWARF
unwinder. */
- if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind))
+ if (!frame_unwinder_is (this_frame, &dwarf2_frame_unwind)
+ && !frame_unwinder_is (this_frame, &dwarf2_tailcall_frame_unwind))
error (_("can't compute CFA for this frame"));
return get_frame_base (this_frame);
}
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -399,6 +399,321 @@ call_site_to_target_addr (struct gdbarch *call_site_gdbarch,
}
}
+/* Convert function entry point exact address ADDR to the function which is
+ compliant with TAIL_CALL_LIST_COMPLETE condition. Throw
+ NO_ENTRY_VALUE_ERROR otherwise. */
+
+static struct symbol *
+func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ struct symbol *sym = find_pc_function (addr);
+ struct type *type;
+
+ if (sym == NULL || BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) != addr)
+ throw_error (NO_ENTRY_VALUE_ERROR,
+ _("DW_TAG_GNU_call_site resolving failed to find function "
+ "name for address %s"),
+ paddress (gdbarch, addr));
+
+ type = SYMBOL_TYPE (sym);
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_FUNC);
+ gdb_assert (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FUNC);
+
+ return sym;
+}
+
+/* Print user readable form of CALL_SITE->PC to gdb_stdlog. Used only for
+ ENTRY_VALUES_DEBUG. */
+
+static void
+tailcall_dump (struct gdbarch *gdbarch, const struct call_site *call_site)
+{
+ CORE_ADDR addr = call_site->pc;
+ struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (addr - 1);
+
+ fprintf_unfiltered (gdb_stdlog, " %s(%s)", paddress (gdbarch, addr),
+ msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym));
+
+}
+
+/* vec.h needs single word type name, typedef it. */
+typedef struct call_site *call_sitep;
+
+/* Define VEC (call_sitep) functions. */
+DEF_VEC_P (call_sitep);
+
+/* Intersect RESULTP with CHAIN to keep RESULTP unambiguous, keep in RESULTP
+ only top callers and bottom callees which are present in both. GDBARCH is
+ used only for ENTRY_VALUES_DEBUG. RESULTP is NULL after return if there are
+ no remaining possibilities to provide unambiguous non-trivial result.
+ RESULTP should point to NULL on the first (initialization) call. Caller is
+ responsible for xfree of any RESULTP data. */
+
+static void
+chain_candidate (struct gdbarch *gdbarch, struct call_site_chain **resultp,
+ VEC (call_sitep) *chain)
+{
+ struct call_site_chain *result = *resultp;
+ long length = VEC_length (call_sitep, chain);
+ int callers, callees, idx;
+
+ if (result == NULL)
+ {
+ /* Create the initial chain containing all the passed PCs. */
+
+ result = xmalloc (sizeof (*result) + sizeof (*result->call_site)
+ * (length - 1));
+ result->length = length;
+ result->callers = result->callees = length;
+ memcpy (result->call_site, VEC_address (call_sitep, chain),
+ sizeof (*result->call_site) * length);
+ *resultp = result;
+
+ if (entry_values_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "tailcall: initial:");
+ for (idx = 0; idx < length; idx++)
+ tailcall_dump (gdbarch, result->call_site[idx]);
+ fputc_unfiltered ('\n', gdb_stdlog);
+ }
+
+ return;
+ }
+
+ if (entry_values_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "tailcall: compare:");
+ for (idx = 0; idx < length; idx++)
+ tailcall_dump (gdbarch, VEC_index (call_sitep, chain, idx));
+ fputc_unfiltered ('\n', gdb_stdlog);
+ }
+
+ /* Intersect callers. */
+
+ callers = min (result->callers, length);
+ for (idx = 0; idx < callers; idx++)
+ if (result->call_site[idx] != VEC_index (call_sitep, chain, idx))
+ {
+ result->callers = idx;
+ break;
+ }
+
+ /* Intersect callees. */
+
+ callees = min (result->callees, length);
+ for (idx = 0; idx < callees; idx++)
+ if (result->call_site[result->length - 1 - idx]
+ != VEC_index (call_sitep, chain, length - 1 - idx))
+ {
+ result->callees = idx;
+ break;
+ }
+
+ if (entry_values_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "tailcall: reduced:");
+ for (idx = 0; idx < result->callers; idx++)
+ tailcall_dump (gdbarch, result->call_site[idx]);
+ fputs_unfiltered (" |", gdb_stdlog);
+ for (idx = 0; idx < result->callees; idx++)
+ tailcall_dump (gdbarch, result->call_site[result->length
+ - result->callees + idx]);
+ fputc_unfiltered ('\n', gdb_stdlog);
+ }
+
+ if (result->callers == 0 && result->callees == 0)
+ {
+ /* There are no common callers or callees. It could be also a direct
+ call (which has length 0) with ambiguous possibility of an indirect
+ call - CALLERS == CALLEES == 0 is valid during the first allocation
+ but any subsequence processing of such entry means ambiguity. */
+ xfree (result);
+ *resultp = NULL;
+ return;
+ }
+
+ /* See call_site_find_chain_1 why there is no way to reach the bottom callee
+ PC again. In such case there must be two different code paths to reach
+ it, therefore some of the former determined intermediate PCs must differ
+ and the unambiguous chain gets shortened. */
+ gdb_assert (result->callers + result->callees < result->length);
+}
+
+/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the
+ assumed frames between them use GDBARCH. Use depth first search so we can
+ keep single CHAIN of call_site's back to CALLER_PC. Function recursion
+ would have needless GDB stack overhead. Caller is responsible for xfree of
+ the returned result. Any unreliability results in thrown
+ NO_ENTRY_VALUE_ERROR. */
+
+static struct call_site_chain *
+call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
+ CORE_ADDR callee_pc)
+{
+ struct func_type *func_specific;
+ struct obstack addr_obstack;
+ struct cleanup *back_to_retval, *back_to_workdata;
+ struct call_site_chain *retval = NULL;
+ struct call_site *call_site;
+
+ /* Mark CALL_SITEs so we do not visit the same ones twice. */
+ htab_t addr_hash;
+
+ /* CHAIN contains only the intermediate CALL_SITEs. Neither CALLER_PC's
+ call_site nor any possible call_site at CALLEE_PC's function is there.
+ Any CALL_SITE in CHAIN will be iterated to its siblings - via
+ TAIL_CALL_NEXT. This is inappropriate for CALLER_PC's call_site. */
+ VEC (call_sitep) *chain = NULL;
+
+ /* We are not interested in the specific PC inside the callee function. */
+ callee_pc = get_pc_function_start (callee_pc);
+ if (callee_pc == 0)
+ throw_error (NO_ENTRY_VALUE_ERROR, _("Unable to find function for PC %s"),
+ paddress (gdbarch, callee_pc));
+
+ back_to_retval = make_cleanup (free_current_contents, &retval);
+
+ obstack_init (&addr_obstack);
+ back_to_workdata = make_cleanup_obstack_free (&addr_obstack);
+ addr_hash = htab_create_alloc_ex (64, core_addr_hash, core_addr_eq, NULL,
+ &addr_obstack, hashtab_obstack_allocate,
+ NULL);
+ make_cleanup_htab_delete (addr_hash);
+
+ make_cleanup (VEC_cleanup (call_sitep), &chain);
+
+ /* Do not push CALL_SITE to CHAIN. Push there only the first tail call site
+ at the target's function. All the possible tail call sites in the
+ target's function will get iterated as already pushed into CHAIN via their
+ TAIL_CALL_NEXT. */
+ call_site = call_site_for_pc (gdbarch, caller_pc);
+
+ while (call_site)
+ {
+ CORE_ADDR target_func_addr;
+ struct call_site *target_call_site;
+
+ /* CALLER_FRAME with registers is not available for tail-call jumped
+ frames. */
+ target_func_addr = call_site_to_target_addr (gdbarch, call_site, NULL);
+
+ if (target_func_addr == callee_pc)
+ {
+ chain_candidate (gdbarch, &retval, chain);
+ if (retval == NULL)
+ break;
+
+ /* There is no way to reach CALLEE_PC again as we would prevent
+ entering it twice as being already marked in ADDR_HASH. */
+ target_call_site = NULL;
+ }
+ else
+ {
+ struct symbol *target_func;
+
+ target_func = func_addr_to_tail_call_list (gdbarch, target_func_addr);
+ target_call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (target_func));
+ }
+
+ do
+ {
+ /* Attempt to visit TARGET_CALL_SITE. */
+
+ if (target_call_site)
+ {
+ void **slot;
+
+ slot = htab_find_slot (addr_hash, &target_call_site->pc, INSERT);
+ if (*slot == NULL)
+ {
+ /* Successfully entered TARGET_CALL_SITE. */
+
+ *slot = &target_call_site->pc;
+ VEC_safe_push (call_sitep, chain, target_call_site);
+ break;
+ }
+ }
+
+ /* Backtrack (without revisiting the originating call_site). Try the
+ callers's sibling; if there isn't any try the callers's callers's
+ sibling etc. */
+
+ target_call_site = NULL;
+ while (!VEC_empty (call_sitep, chain))
+ {
+ call_site = VEC_pop (call_sitep, chain);
+
+ gdb_assert (htab_find_slot (addr_hash, &call_site->pc,
+ NO_INSERT) != NULL);
+ htab_remove_elt (addr_hash, &call_site->pc);
+
+ target_call_site = call_site->tail_call_next;
+ if (target_call_site)
+ break;
+ }
+ }
+ while (target_call_site);
+
+ if (VEC_empty (call_sitep, chain))
+ call_site = NULL;
+ else
+ call_site = VEC_last (call_sitep, chain);
+ }
+
+ if (retval == NULL)
+ {
+ struct minimal_symbol *msym_caller, *msym_callee;
+
+ msym_caller = lookup_minimal_symbol_by_pc (caller_pc);
+ msym_callee = lookup_minimal_symbol_by_pc (callee_pc);
+ throw_error (NO_ENTRY_VALUE_ERROR,
+ _("There are no unambiguously determinable intermediate "
+ "callers or callees between caller function \"%s\" at %s "
+ "and callee function \"%s\" at %s"),
+ (msym_caller == NULL
+ ? "???" : SYMBOL_PRINT_NAME (msym_caller)),
+ paddress (gdbarch, caller_pc),
+ (msym_callee == NULL
+ ? "???" : SYMBOL_PRINT_NAME (msym_callee)),
+ paddress (gdbarch, callee_pc));
+ }
+
+ do_cleanups (back_to_workdata);
+ discard_cleanups (back_to_retval);
+ return retval;
+}
+
+/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the
+ assumed frames between them use GDBARCH. If valid call_site_chain cannot be
+ constructed return NULL. Caller is responsible for xfree of the returned
+ result. */
+
+struct call_site_chain *
+call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
+ CORE_ADDR callee_pc)
+{
+ volatile struct gdb_exception e;
+ struct call_site_chain *retval = NULL;
+
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ retval = call_site_find_chain_1 (gdbarch, caller_pc, callee_pc);
+ }
+ if (e.reason < 0)
+ {
+ if (e.error == NO_ENTRY_VALUE_ERROR)
+ {
+ if (entry_values_debug)
+ exception_print (gdb_stdout, e);
+
+ return NULL;
+ }
+ else
+ throw_exception (e);
+ }
+ return retval;
+}
+
/* Fetch call_site_parameter from caller matching the parameters. FRAME is for
callee. See DWARF_REG and FB_OFFSET description at struct
dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -135,4 +135,23 @@ extern void dwarf2_compile_expr_to_ax (struct agent_expr *expr,
const gdb_byte *op_end,
struct dwarf2_per_cu_data *per_cu);
+/* Determined tail calls for constructing virtual tail call frames. */
+
+struct call_site_chain
+ {
+ /* Initially CALLERS == CALLEES == LENGTH. For partially ambiguous result
+ CALLERS + CALLEES < LENGTH. */
+ int callers, callees, length;
+
+ /* Variably sized array with LENGTH elements. Later [0..CALLERS-1] contain
+ top (GDB "prev") sites and [LENGTH-CALLEES..LENGTH-1] contain bottom
+ (GDB "next") sites. One is interested primarily in the PC field. */
+ struct call_site *call_site[1];
+ };
+
+struct call_site_stuff;
+extern struct call_site_chain *call_site_find_chain (struct gdbarch *gdbarch,
+ CORE_ADDR caller_pc,
+ CORE_ADDR callee_pc);
+
#endif /* dwarf2loc.h */
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2035,8 +2035,10 @@ get_frame_address_in_block (struct frame_info *this_frame)
while (get_frame_type (next_frame) == INLINE_FRAME)
next_frame = next_frame->next;
- if (get_frame_type (next_frame) == NORMAL_FRAME
+ if ((get_frame_type (next_frame) == NORMAL_FRAME
+ || get_frame_type (next_frame) == TAILCALL_FRAME)
&& (get_frame_type (this_frame) == NORMAL_FRAME
+ || get_frame_type (this_frame) == TAILCALL_FRAME
|| get_frame_type (this_frame) == INLINE_FRAME))
return pc - 1;
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -206,6 +206,8 @@ enum frame_type
/* A frame representing an inlined function, associated with an
upcoming (prev, outer, older) NORMAL_FRAME. */
INLINE_FRAME,
+ /* A virtual frame of a tail call - see dwarf2_tailcall_frame_unwind. */
+ TAILCALL_FRAME,
/* In a signal handler, various OSs handle this in various ways.
The main thing is that the frame may be far from normal. */
SIGTRAMP_FRAME,
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -595,6 +595,7 @@ gdbpy_initialize_frames (void)
PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME);
+ PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME);
PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1086,6 +1086,8 @@ frame_info (char *addr_exp, int from_tty)
printf_filtered (_(" Outermost frame: %s\n"),
frame_stop_reason_string (reason));
}
+ else if (get_frame_type (fi) == TAILCALL_FRAME)
+ puts_filtered (" tail call frame");
else if (get_frame_type (fi) == INLINE_FRAME)
printf_filtered (" inlined into frame %d",
frame_relative_level (get_prev_frame (fi)));
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.cc
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.cc
@@ -34,9 +34,71 @@ asm ("breakhere:");
e (v, v);
}
+static void __attribute__((noinline, noclone))
+c (int i, double j)
+{
+ d (i * 10, j * 10);
+}
+
+static void __attribute__((noinline, noclone))
+a (int i, double j)
+{
+ c (i + 1, j + 1);
+}
+
+static void __attribute__((noinline, noclone))
+b (int i, double j)
+{
+ c (i + 2, j + 2);
+}
+
+static void __attribute__((noinline, noclone))
+amb_z (int i)
+{
+ d (i + 7, i + 7.5);
+}
+
+static void __attribute__((noinline, noclone))
+amb_y (int i)
+{
+ amb_z (i + 6);
+}
+
+static void __attribute__((noinline, noclone))
+amb_x (int i)
+{
+ amb_y (i + 5);
+}
+
+static void __attribute__((noinline, noclone))
+amb (int i)
+{
+ if (i < 0)
+ amb_x (i + 3);
+ else
+ amb_x (i + 4);
+}
+
+static void __attribute__((noinline, noclone))
+amb_b (int i)
+{
+ amb (i + 2);
+}
+
+static void __attribute__((noinline, noclone))
+amb_a (int i)
+{
+ amb_b (i + 1);
+}
+
int
main ()
{
d (30, 30.5);
+ if (v)
+ a (1, 1.25);
+ else
+ b (5, 5.25);
+ amb_a (100);
return 0;
}
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.exp
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.exp
@@ -45,3 +45,31 @@ gdb_test "bt" "^bt\r\n#0 +d *\\(i=31, j=31\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]
"entry: bt"
gdb_test "p i" " = 31" "entry: p i"
gdb_test "p j" { = 31\.5} "entry: p j"
+
+
+# Test virtual tail call frames.
+
+gdb_continue_to_breakpoint "tailcall: breakhere"
+
+gdb_test "bt" "^bt\r\n#0 +d *\\(i=71, j=73\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in c \\(i=7, j=7\\.25\\) \[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in b \\(i=5, j=5\\.25\\) \[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in main \[^\r\n\]*" \
+ "tailcall: bt"
+gdb_test "p i" " = 71" "tailcall: p i"
+gdb_test "p j" " = 73\\.5" "tailcall: p j"
+
+# Test $sp simulation for tail call frames.
+#gdb_test {p/x $sp} " = 0x.*"
+#gdb_test {p/x $pc} " = 0x.*"
+gdb_test_no_output {set $sp0=$sp}
+gdb_test "up" "\r\n#1 .*"
+#gdb_test {p/x $sp} " = 0x.*"
+gdb_test {p $sp0 == $sp} " = true"
+gdb_test "frame 3" "\r\n#3 .*"
+gdb_test {p $sp0 + sizeof (void *) == $sp} " = true"
+
+
+# Test partial-ambiguous virtual tail call frames chain.
+
+gdb_continue_to_breakpoint "ambiguous: breakhere"
+
+gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>, j=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in amb_z \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in amb_y \\(i=<optimized out>\\)\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in amb_x \\(i=<optimized out>\\)\[^\r\n\]*\r\n#4 +0x\[0-9a-f\]+ in amb_b \\(i=101\\)\[^\r\n\]*\r\n#5 +0x\[0-9a-f\]+ in amb_a \\(i=100\\)\[^\r\n\]*\r\n#6 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
+ "ambiguous: bt"
^ permalink raw reply [flat|nested] 23+ messages in thread* [commit] [patch 04/12] entryval#3: Virtual tail call frames
2011-09-29 19:50 [patch 04/12] entryval#3: Virtual tail call frames Jan Kratochvil
@ 2011-10-09 19:27 ` Jan Kratochvil
2011-10-09 20:23 ` Jan Kratochvil
2011-10-10 13:40 ` doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames) Ulrich Weigand
1 sibling, 1 reply; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-09 19:27 UTC (permalink / raw)
To: gdb-patches
On Thu, 29 Sep 2011 21:49:25 +0200, Jan Kratochvil wrote:
> gdb/
> 2011-09-13 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> Recognize virtual tail call frames.
> * Makefile.in (SFILES): Add dwarf2-frame-tailcall.c.
> (HFILES_NO_SRCDIR): Add dwarf2-frame-tailcall.h.
> (COMMON_OBS): Add dwarf2-frame-tailcall.o.
> * dwarf2-frame-tailcall.c: New file.
> * dwarf2-frame-tailcall.h: New file.
> * dwarf2-frame.c: Include dwarf2-frame-tailcall.h.
> (execute_cfa_program): New function comment. Return INSN_PTR. Reset
> REGS.PREV only after CIE execution.
> (struct dwarf2_frame_cache): New field tailcall_cache.
> (dwarf2_frame_cache): New variables entry_pc, entry_cfa_sp_offset,
> entry_cfa_sp_offset_p and instr. Execute FDE instructions in two
> parts, try to find entry_cfa_sp_offset. Call
> dwarf2_tailcall_sniffer_first.
> (dwarf2_frame_prev_register): Call dwarf2_tailcall_prev_register_first
> when appropriate.
> (dwarf2_frame_dealloc_cache): New function.
> (dwarf2_frame_sniffer): Preinitialize cache by dwarf2_frame_cache.
> (dwarf2_frame_unwind): Install dwarf2_frame_dealloc_cache.
> (dwarf2_signal_frame_unwind): Do not install dwarf2_frame_dealloc_cache.
> (dwarf2_append_unwinders): Add dwarf2_tailcall_frame_unwind.
> (dwarf2_frame_cfa): Support also dwarf2_tailcall_frame_unwind.
> * dwarf2loc.c (func_addr_to_tail_call_list)
> (tailcall_dump, call_sitep, VEC (call_sitep), chain_candidate)
> (call_site_find_chain_1, call_site_find_chain): New.
> * dwarf2loc.h (struct call_site_chain): New.
> (call_site_find_chain): New declaration.
> * frame.c (get_frame_address_in_block): Support also TAILCALL_FRAME.
> * frame.h (enum frame_type): New entry TAILCALL_FRAME.
> * python/py-frame.c (gdbpy_initialize_frames): Add TAILCALL_FRAME.
> * stack.c (frame_info): Support also TAILCALL_FRAME.
>
> gdb/doc/
> 2011-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
> Eli Zaretskii <eliz@gnu.org>
>
> Recognize virtual tail call frames.
> * gdb.texinfo (Optimized Code): Add reference to Tail Call Frames.
> (Tail Call Frames): New node.
> (Frames In Python): Add gdb.TAILCALL_FRAME.
>
> gdb/testsuite/
> 2011-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> Recognize virtual tail call frames.
> * gdb.arch/amd64-entry-value.cc (c, a, b, amb_z, amb_y, amb_x, amb)
> (amb_b, amb_a): New.
> (main): Call a and b.
> * gdb.arch/amd64-entry-value.exp (tailcall: breakhere, tailcall: bt)
> (tailcall: p i, tailcall: p j, set $sp0=$sp, up, p $sp0 == $sp, frame 3)
> (p $sp0 + sizeof (void *) == $sp, ambiguous: breakhere, ambiguous: bt):
> New tests.
Checked in:
http://sourceware.org/ml/gdb-cvs/2011-10/msg00059.html
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread
* doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)
2011-09-29 19:50 [patch 04/12] entryval#3: Virtual tail call frames Jan Kratochvil
2011-10-09 19:27 ` [commit] " Jan Kratochvil
@ 2011-10-10 13:40 ` Ulrich Weigand
2011-10-10 13:54 ` Eli Zaretskii
1 sibling, 1 reply; 23+ messages in thread
From: Ulrich Weigand @ 2011-10-10 13:40 UTC (permalink / raw)
To: Jan Kratochvil, eliz; +Cc: gdb-patches
Jan Kratochvil wrote:
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> +Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
> +possible execution paths
> +@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
> +@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
> +one from the inferior state.
This causes make install to fail for me with:
makeinfo --split-size=5000000 --split-size=5000000 -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../../readline/doc -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../mi -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc \
-o gdb.info /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced }.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Unknown command `arrow'.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced {.
/home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9795: Misplaced }.
makeinfo: Removing output file `gdb.info' due to errors; use --force to preserve.
make[5]: *** [gdb.info] Error 1
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)
2011-10-10 13:40 ` doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames) Ulrich Weigand
@ 2011-10-10 13:54 ` Eli Zaretskii
2011-10-10 13:58 ` Ulrich Weigand
0 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2011-10-10 13:54 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: jan.kratochvil, gdb-patches
> Date: Mon, 10 Oct 2011 15:40:13 +0200 (CEST)
> From: "Ulrich Weigand" <uweigand@de.ibm.com>
> Cc: gdb-patches@sourceware.org
>
> Jan Kratochvil wrote:
>
> > --- a/gdb/doc/gdb.texinfo
> > +++ b/gdb/doc/gdb.texinfo
>
> > +Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
> > +possible execution paths
> > +@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
> > +@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
> > +one from the inferior state.
>
> This causes make install to fail for me with:
>
> makeinfo --split-size=5000000 --split-size=5000000 -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../../readline/doc -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../mi -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc \
> -o gdb.info /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo
> /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
@arrow is from a relatively new version of Texinfo. What version do
you have on that machine?
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)
2011-10-10 13:54 ` Eli Zaretskii
@ 2011-10-10 13:58 ` Ulrich Weigand
2011-10-10 14:58 ` [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)] Jan Kratochvil
0 siblings, 1 reply; 23+ messages in thread
From: Ulrich Weigand @ 2011-10-10 13:58 UTC (permalink / raw)
To: eliz; +Cc: jan.kratochvil, gdb-patches
Eli Zaretskii wrote:
> > Date: Mon, 10 Oct 2011 15:40:13 +0200 (CEST)
> > From: "Ulrich Weigand" <uweigand@de.ibm.com>
> > Cc: gdb-patches@sourceware.org
> >
> > Jan Kratochvil wrote:
> >
> > > --- a/gdb/doc/gdb.texinfo
> > > +++ b/gdb/doc/gdb.texinfo
> >
> > > +Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
> > > +possible execution paths
> > > +@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
> > > +@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
> > > +one from the inferior state.
> >
> > This causes make install to fail for me with:
> >
> > makeinfo --split-size=5000000 --split-size=5000000 -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../../readline/doc -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/../mi -I /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc \
> > -o gdb.info /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo
> > /home/kwerner/dailybuild/spu-tc-2011-10-10/gdb-head/src/gdb/doc/gdb.texinfo:9794: Unknown command `arrow'.
>
> @arrow is from a relatively new version of Texinfo. What version do
> you have on that machine?
This is a RHEL 5 machine, which has:
[uweigand@pctc1 ~]$ makeinfo --version
makeinfo (GNU texinfo) 4.8
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 23+ messages in thread* [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 13:58 ` Ulrich Weigand
@ 2011-10-10 14:58 ` Jan Kratochvil
2011-10-10 15:16 ` Pedro Alves
0 siblings, 1 reply; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-10 14:58 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: eliz, gdb-patches
On Mon, 10 Oct 2011 15:57:48 +0200, Ulrich Weigand wrote:
> Eli Zaretskii wrote:
> > @arrow is from a relatively new version of Texinfo. What version do
> > you have on that machine?
>
> This is a RHEL 5 machine, which has:
>
> [uweigand@pctc1 ~]$ makeinfo --version
> makeinfo (GNU texinfo) 4.8
I will check in the patch below if no comments appear.
Thanks,
Jan
gdb/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* configure: Regenerate.
* configure.ac (HAVE_MAKEINFO_CLICK): New test for AC_SUBST.
gdb/doc/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* Makefile.in (MAKEINFO): Add @HAVE_MAKEINFO_CLICK@.
* gdb.texinfo (Tail Call Frames): Convert @arrow{} to @click, make the
sentence conditional on HAVE_MAKEINFO_CLICK.
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2179,6 +2179,20 @@ dnl At the moment, we just assume it's UTF-8.
AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "UTF-8",
[Define to be a string naming the default host character set.])
+AC_CACHE_CHECK([whether makeinfo supports @click], gdb_cv_have_makeinfo_click,
+ [echo '@clicksequence{a @click{} b}' >conftest.texinfo
+ if makeinfo conftest.texinfo >/dev/null 2>/dev/null; then
+ gdb_cv_have_makeinfo_click=yes
+ else
+ gdb_cv_have_makeinfo_click=no
+ fi])
+if test x"$gdb_cv_have_makeinfo_click" = xyes; then
+ HAVE_MAKEINFO_CLICK="-DHAVE_MAKEINFO_CLICK"
+else
+ HAVE_MAKEINFO_CLICK=""
+fi
+AC_SUBST(HAVE_MAKEINFO_CLICK)
+
AC_OUTPUT(Makefile .gdbinit:gdbinit.in doc/Makefile gnulib/Makefile data-directory/Makefile,
[
case x$CONFIG_HEADERS in
--- a/gdb/doc/Makefile.in
+++ b/gdb/doc/Makefile.in
@@ -45,7 +45,7 @@ gdbdir = $(srcdir)/..
TEXIDIR=${gdbdir}/../texinfo
# where to find makeinfo, preferably one designed for texinfo-2
-MAKEINFO=makeinfo
+MAKEINFO=makeinfo @HAVE_MAKEINFO_CLICK@
MAKEHTML = $(MAKEINFO) --html
MAKEHTMLFLAGS =
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9789,11 +9789,13 @@ tailcall: reduced: 0x4004d2(a) |
#2 0x0000000000400395 in main () at t.c:9
@end smallexample
-Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
-possible execution paths
-@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
-@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
+Frames #0 and #2 are real, #1 is a virtual tail call frame.
+@ifset HAVE_MAKEINFO_CLICK
+The code can have possible execution paths
+@clicksequence{main@click{}a@click{}b@click{}c@click{}d@click{}f} or
+@clicksequence{main@click{}a@click{}b@click{}e@click{}f}, @value{GDBN} cannot find which
one from the inferior state.
+@end ifset
@code{initial:} state shows some random possible calling sequence @value{GDBN}
has found. It then finds another possible calling sequcen - that one is
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 14:58 ` [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)] Jan Kratochvil
@ 2011-10-10 15:16 ` Pedro Alves
2011-10-10 15:31 ` Jan Kratochvil
2011-10-10 16:09 ` Eli Zaretskii
0 siblings, 2 replies; 23+ messages in thread
From: Pedro Alves @ 2011-10-10 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil, Ulrich Weigand, eliz
On Monday 10 October 2011 15:57:49, Jan Kratochvil wrote:
> +@ifset HAVE_MAKEINFO_CLICK
> +The code can have possible execution paths
> +@clicksequence{main@click{}a@click{}b@click{}c@click{}d@click{}f} or
> +@clicksequence{main@click{}a@click{}b@click{}e@click{}f}, @value{GDBN} cannot find which
> one from the inferior state.
> +@end ifset
Leaving a piece of the manual out like that is not okay.
If this feature is too new for the currently required makeinfo
version (which is it, btw?), we have two real choices:
1. bump the minimum required makeinfo version so we can use it
2. don't use the new feature
We could also have an @else that spells that bit out without
using @click/@arrow, but I don't think the benefits of a
clicksequence (or @arrow) justify the extra maintenance
burden. IMO.
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 15:16 ` Pedro Alves
@ 2011-10-10 15:31 ` Jan Kratochvil
2011-10-10 15:51 ` Pedro Alves
2011-10-10 16:10 ` Eli Zaretskii
2011-10-10 16:09 ` Eli Zaretskii
1 sibling, 2 replies; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-10 15:31 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, Ulrich Weigand, eliz
On Mon, 10 Oct 2011 17:15:38 +0200, Pedro Alves wrote:
> Leaving a piece of the manual out like that is not okay.
I was thinking about it but I do not find this part as too significant there,
it is just another illustration.
> If this feature is too new for the currently required makeinfo
> version (which is it, btw?), we have two real choices:
>
> 1. bump the minimum required makeinfo version so we can use it
Unfortunately sourceware tree does not build without makeinfo at all. This is
a pretty painful dependency on various hosts I build GDB on, I tried once to
make the dependency optional but I do not find it so easy as I thought it is.
> 2. don't use the new feature
>
> We could also have an @else that spells that bit out without
> using @click/@arrow, but I don't think the benefits of a
> clicksequence (or @arrow) justify the extra maintenance
> burden. IMO.
IMO it makes better quality of the output for user. If the feature has been
implemented and it is useful in such case it should be used. There is no
excuse not doing so.
I can provide alternative less nifty graphical representation keeping the text
even with older texinfos.
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 15:31 ` Jan Kratochvil
@ 2011-10-10 15:51 ` Pedro Alves
2011-10-10 18:47 ` Jan Kratochvil
2011-10-10 16:10 ` Eli Zaretskii
1 sibling, 1 reply; 23+ messages in thread
From: Pedro Alves @ 2011-10-10 15:51 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, Ulrich Weigand, eliz
On Monday 10 October 2011 16:30:49, Jan Kratochvil wrote:
> On Mon, 10 Oct 2011 17:15:38 +0200, Pedro Alves wrote:
> > Leaving a piece of the manual out like that is not okay.
>
> I was thinking about it but I do not find this part as too significant there,
> it is just another illustration.
A bad precedent. Let's not do it please. People e.g.,
building gdb's on old systems in order to make sure the binaries
are binary compatible with a wide range of OS versions will get
silently bitten with parts of the manual missing. If it's not
significant, drop it. If it is, make it available everywhere.
> > If this feature is too new for the currently required makeinfo
> > version (which is it, btw?), we have two real choices:
> >
> > 1. bump the minimum required makeinfo version so we can use it
>
> Unfortunately sourceware tree does not build without makeinfo at all. This is
> a pretty painful dependency on various hosts I build GDB on, I tried once to
> make the dependency optional but I do not find it so easy as I thought it is.
Since it's not, we could say that such old versions are unsupported,
and error out loudly instead. (that is, bump the minimum required
makeinfo version, if makeinfo is in use).
> > 2. don't use the new feature
> >
> > We could also have an @else that spells that bit out without
> > using @click/@arrow, but I don't think the benefits of a
> > clicksequence (or @arrow) justify the extra maintenance
> > burden. IMO.
>
> IMO it makes better quality of the output for user. If the feature has been
> implemented and it is useful in such case it should be used. There is no
> excuse not doing so.
The "doesn't justify the extra maintenance burden" is always a valid
excuse. But if you and Eli think it justifies it, go for it.
> I can provide alternative less nifty graphical representation keeping the text
> even with older texinfos.
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 15:51 ` Pedro Alves
@ 2011-10-10 18:47 ` Jan Kratochvil
2011-10-10 19:11 ` Eli Zaretskii
2011-10-10 21:56 ` Pedro Alves
0 siblings, 2 replies; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-10 18:47 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, Ulrich Weigand, eliz
On Mon, 10 Oct 2011 17:51:00 +0200, Pedro Alves wrote:
> The "doesn't justify the extra maintenance burden" is always a valid
> excuse. But if you and Eli think it justifies it, go for it.
Attached. In info document it looks the same, in PDF it looks very similar.
Thanks,
Jan
gdb/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* configure: Regenerate.
* configure.ac (HAVE_MAKEINFO_CLICK): New test for AC_SUBST.
gdb/doc/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* Makefile.in (MAKEINFO): Add @HAVE_MAKEINFO_CLICK@.
* gdb.texinfo (Tail Call Frames): Convert @arrow{} to @click, when possible.
Make the conversion conditional on HAVE_MAKEINFO_CLICK, using variables
CALLSEQ1A, CALLSEQ1B, CALLSEQ2A and CALLSEQ2B.
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2179,6 +2179,20 @@ dnl At the moment, we just assume it's UTF-8.
AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "UTF-8",
[Define to be a string naming the default host character set.])
+AC_CACHE_CHECK([whether makeinfo supports @click], gdb_cv_have_makeinfo_click,
+ [echo '@clicksequence{a @click{} b}' >conftest.texinfo
+ if makeinfo conftest.texinfo >&5 2>&5; then
+ gdb_cv_have_makeinfo_click=yes
+ else
+ gdb_cv_have_makeinfo_click=no
+ fi])
+if test x"$gdb_cv_have_makeinfo_click" = xyes; then
+ HAVE_MAKEINFO_CLICK="-DHAVE_MAKEINFO_CLICK"
+else
+ HAVE_MAKEINFO_CLICK=""
+fi
+AC_SUBST(HAVE_MAKEINFO_CLICK)
+
AC_OUTPUT(Makefile .gdbinit:gdbinit.in doc/Makefile gnulib/Makefile data-directory/Makefile,
[
case x$CONFIG_HEADERS in
--- a/gdb/doc/Makefile.in
+++ b/gdb/doc/Makefile.in
@@ -45,7 +45,7 @@ gdbdir = $(srcdir)/..
TEXIDIR=${gdbdir}/../texinfo
# where to find makeinfo, preferably one designed for texinfo-2
-MAKEINFO=makeinfo
+MAKEINFO=makeinfo @HAVE_MAKEINFO_CLICK@
MAKEHTML = $(MAKEINFO) --html
MAKEHTMLFLAGS =
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9789,11 +9789,24 @@ tailcall: reduced: 0x4004d2(a) |
#2 0x0000000000400395 in main () at t.c:9
@end smallexample
-Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
-possible execution paths
-@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
-@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
-one from the inferior state.
+@set CALLSEQ1A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}c@value{ARROW}d@value{ARROW}f}
+@set CALLSEQ2A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}e@value{ARROW}f}
+
+@c Convert CALLSEQ#A to CALLSEQ#B depending on HAVE_MAKEINFO_CLICK.
+@ifset HAVE_MAKEINFO_CLICK
+@set ARROW @click{}
+@set CALLSEQ1B @clicksequence{@value{CALLSEQ1A}}
+@set CALLSEQ2B @clicksequence{@value{CALLSEQ2A}}
+@end ifset
+@ifclear HAVE_MAKEINFO_CLICK
+@set ARROW ->
+@set CALLSEQ1B @value{CALLSEQ1A}
+@set CALLSEQ2B @value{CALLSEQ2A}
+@end ifclear
+
+Frames #0 and #2 are real, #1 is a virtual tail call frame.
+The code can have possible execution paths @value{CALLSEQ1B} or
+@value{CALLSEQ2B}, @value{GDBN} cannot find which one from the inferior state.
@code{initial:} state shows some random possible calling sequence @value{GDBN}
has found. It then finds another possible calling sequcen - that one is
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 18:47 ` Jan Kratochvil
@ 2011-10-10 19:11 ` Eli Zaretskii
2011-10-10 21:56 ` Pedro Alves
1 sibling, 0 replies; 23+ messages in thread
From: Eli Zaretskii @ 2011-10-10 19:11 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: pedro, gdb-patches, uweigand
> Date: Mon, 10 Oct 2011 20:47:26 +0200
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Cc: gdb-patches@sourceware.org, Ulrich Weigand <uweigand@de.ibm.com>,
> eliz@gnu.org
>
> On Mon, 10 Oct 2011 17:51:00 +0200, Pedro Alves wrote:
> > The "doesn't justify the extra maintenance burden" is always a valid
> > excuse. But if you and Eli think it justifies it, go for it.
>
> Attached. In info document it looks the same, in PDF it looks very similar.
Fine with me, thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 18:47 ` Jan Kratochvil
2011-10-10 19:11 ` Eli Zaretskii
@ 2011-10-10 21:56 ` Pedro Alves
2011-10-10 22:19 ` Andreas Schwab
2011-10-11 23:34 ` Jan Kratochvil
1 sibling, 2 replies; 23+ messages in thread
From: Pedro Alves @ 2011-10-10 21:56 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, Ulrich Weigand, eliz
On Monday 10 October 2011 19:47:26, Jan Kratochvil wrote:
> + if makeinfo conftest.texinfo >&5 2>&5; then
Shouldn't this be $(MAKEINFO) instead (like in Makefile.in)?
Though I'm not sure how to do that here. Maybe
AC_CHECK_PROGS(MAKEINFO, makeinfo) ?
> +if test x"$gdb_cv_have_makeinfo_click" = xyes; then
> + HAVE_MAKEINFO_CLICK="-DHAVE_MAKEINFO_CLICK"
> +else
> + HAVE_MAKEINFO_CLICK=""
> +fi
> +AC_SUBST(HAVE_MAKEINFO_CLICK)
AC_DEFINE is usualy better for predicate defines, such
as HAVE_FOOS. But in this is case, I think it's the variable's
name that is confusing. It should be somethink like MAKEINFO_EXTRA_FLAGS.
(MAKEINFOFLAGS is the moral equivalent of CFLAGS, so we should
leave it reserved for the user.)
if test x"$gdb_cv_have_makeinfo_click" = xyes; then
MAKEINFO_EXTRA_FLAGS="-DHAVE_MAKEINFO_CLICK"
else
MAKEINFO_EXTRA_FLAGS=""
fi
MAKEINFO=makeinfo @MAKEINFO_EXTRA_FLAGS@
Thanks!
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 21:56 ` Pedro Alves
@ 2011-10-10 22:19 ` Andreas Schwab
2011-10-11 23:34 ` Jan Kratochvil
1 sibling, 0 replies; 23+ messages in thread
From: Andreas Schwab @ 2011-10-10 22:19 UTC (permalink / raw)
To: Pedro Alves; +Cc: Jan Kratochvil, gdb-patches, Ulrich Weigand, eliz
Pedro Alves <pedro@codesourcery.com> writes:
> if test x"$gdb_cv_have_makeinfo_click" = xyes; then
> MAKEINFO_EXTRA_FLAGS="-DHAVE_MAKEINFO_CLICK"
> else
> MAKEINFO_EXTRA_FLAGS=""
> fi
> MAKEINFO=makeinfo @MAKEINFO_EXTRA_FLAGS@
You should not modify MAKEINFO. If you say
"make info MAKEINFO=/usr/local/bin/makeinfo" you lose the flags.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 21:56 ` Pedro Alves
2011-10-10 22:19 ` Andreas Schwab
@ 2011-10-11 23:34 ` Jan Kratochvil
2011-10-12 15:26 ` Pedro Alves
2011-10-25 14:35 ` Joel Brobecker
1 sibling, 2 replies; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-11 23:34 UTC (permalink / raw)
To: Pedro Alves, Andreas Schwab; +Cc: gdb-patches, Ulrich Weigand, eliz
On Mon, 10 Oct 2011 23:56:34 +0200, Pedro Alves wrote:
> On Monday 10 October 2011 19:47:26, Jan Kratochvil wrote:
> > + if makeinfo conftest.texinfo >&5 2>&5; then
>
> Shouldn't this be $(MAKEINFO) instead (like in Makefile.in)?
> Though I'm not sure how to do that here. Maybe
> AC_CHECK_PROGS(MAKEINFO, makeinfo) ?
Yes, it should, although it is more complicated.
There is IMO a bug in toplevel configure it does not pass down MAKEINFOFLAGS
and includes "--split-size=5000000" directly into MAKEINFO. Without the
special handling of --split-size=5000000 it would be used during first
compilation but no longer used after automatic re-run of configure in gdb/
(although only if one deletes gdb/config.cache).
Therefore I added --split-size=5000000 there explicitly, which means it is
duplicated during the dirst compilation but it does not matter.
--split-size=5000000 was not used in gdb/doc/ before at all but I think it was
a bug, even gcc uses --no-split.
> It should be somethink like MAKEINFO_EXTRA_FLAGS.
> (MAKEINFOFLAGS is the moral equivalent of CFLAGS, so we should
> leave it reserved for the user.)
Done.
On Tue, 11 Oct 2011 00:18:54 +0200, Andreas Schwab wrote:
> You should not modify MAKEINFO. If you say
> "make info MAKEINFO=/usr/local/bin/makeinfo" you lose the flags.
True, toplevel configure is already violating that but fixed it in gdb/ .
Thanks,
Jan
gdb/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* Makefile.in (MAKEINFO): Set to @MAKEINFO@.
(MAKEINFOFLAGS, MAKEINFO_EXTRA_FLAGS, MAKEINFO_CMD): New.
(MAKEHTMLFLAGS): Use MAKEINFO_CMD.
(FLAGS_TO_PASS): Add MAKEINFOFLAGS and MAKEINFO_EXTRA_FLAGS.
* configure: Regenerate.
* configure.ac (MAKEINFO): Find it, from libiberty/configure.ac.
(MAKEINFOFLAGS): Pre-set it to --split-size=5000000.
(MAKEINFO_EXTRA_FLAGS): New test for -DHAVE_MAKEINFO_CLICK.
gdb/doc/
2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix compatibility with texinfo versions older than 4.12.
* Makefile.in (MAKEINFO): Set to @MAKEINFO@.
(MAKEINFOFLAGS, MAKEINFO_EXTRA_FLAGS, MAKEINFO_CMD): New.
(MAKEHTMLFLAGS): Use MAKEINFO_CMD.
(gdb.info, gdbint.info, stabs.info, annotate.info): Use MAKEINFO_CMD.
* gdb.texinfo (Tail Call Frames): Convert @arrow{} to @click, when possible.
Make the conversion conditional on HAVE_MAKEINFO_CLICK, using variables
CALLSEQ1A, CALLSEQ1B, CALLSEQ2A and CALLSEQ2B.
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -109,9 +109,12 @@ FLEX = flex
YLWRAP = $(srcdir)/../ylwrap
# where to find makeinfo, preferably one designed for texinfo-2
-MAKEINFO=makeinfo
+MAKEINFO = @MAKEINFO@
+MAKEINFOFLAGS = @MAKEINFOFLAGS@
+MAKEINFO_EXTRA_FLAGS = @MAKEINFO_EXTRA_FLAGS@
+MAKEINFO_CMD = $(MAKEINFO) $(MAKEINFOFLAGS) $(MAKEINFO_EXTRA_FLAGS)
-MAKEHTML = $(MAKEINFO) --html
+MAKEHTML = $(MAKEINFO_CMD) --html
MAKEHTMLFLAGS =
# Set this up with gcc if you have gnu ld and the loader will print out
@@ -614,6 +617,8 @@ FLAGS_TO_PASS = \
"LDFLAGS=$(LDFLAGS)" \
"RANLIB=$(RANLIB)" \
"MAKEINFO=$(MAKEINFO)" \
+ "MAKEINFOFLAGS=$(MAKEINFOFLAGS)" \
+ "MAKEINFO_EXTRA_FLAGS=$(MAKEINFO_EXTRA_FLAGS)" \
"MAKEHTML=$(MAKEHTML)" \
"MAKEHTMLFLAGS=$(MAKEHTMLFLAGS)" \
"INSTALL=$(INSTALL)" \
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -87,6 +87,38 @@ PACKAGE=gdb
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package. ])
AC_SUBST(PACKAGE)
+# Do we have a single-tree copy of texinfo? Even if we do, we can't
+# rely on it - libiberty is built before texinfo.
+AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo, )
+if test "x$MAKEINFO" = "x"; then
+ AC_ERROR([makeinfo is required for compilation])
+else
+ case "$MAKEINFO" in
+ */missing\ makeinfo*)
+ AC_ERROR([makeinfo is required for compilation])
+ ;;
+ esac
+fi
+AC_SUBST(MAKEINFO)
+
+# --split-size=5000000 may be already in $MAKEINFO from parent configure.
+# Re-running configure in gdb/ would lose it so ensure it stays present.
+MAKEINFOFLAGS=${MAKEINFOFLAGS---split-size=5000000}
+AC_SUBST(MAKEINFOFLAGS)
+
+MAKEINFO_EXTRA_FLAGS=""
+AC_CACHE_CHECK([whether $MAKEINFO supports @click], gdb_cv_have_makeinfo_click,
+ [echo '@clicksequence{a @click{} b}' >conftest.texinfo
+ if eval "$MAKEINFO conftest.texinfo >&5 2>&5"; then
+ gdb_cv_have_makeinfo_click=yes
+ else
+ gdb_cv_have_makeinfo_click=no
+ fi])
+if test x"$gdb_cv_have_makeinfo_click" = xyes; then
+ MAKEINFO_EXTRA_FLAGS="$MAKEINFO_EXTRA_FLAGS -DHAVE_MAKEINFO_CLICK"
+fi
+AC_SUBST(MAKEINFO_EXTRA_FLAGS)
+
# GDB does not use automake, but gnulib does. This line lets us
# generate its Makefile.in.
AM_INIT_AUTOMAKE(gdb, UNUSED-VERSION, [no-define])
--- a/gdb/doc/Makefile.in
+++ b/gdb/doc/Makefile.in
@@ -45,9 +45,12 @@ gdbdir = $(srcdir)/..
TEXIDIR=${gdbdir}/../texinfo
# where to find makeinfo, preferably one designed for texinfo-2
-MAKEINFO=makeinfo
+MAKEINFO = @MAKEINFO@
+MAKEINFOFLAGS = @MAKEINFOFLAGS@
+MAKEINFO_EXTRA_FLAGS = @MAKEINFO_EXTRA_FLAGS@
+MAKEINFO_CMD = $(MAKEINFO) $(MAKEINFOFLAGS) $(MAKEINFO_EXTRA_FLAGS)
-MAKEHTML = $(MAKEINFO) --html
+MAKEHTML = $(MAKEINFO_CMD) --html
MAKEHTMLFLAGS =
# where to find texi2roff, ditto
@@ -365,7 +368,7 @@ gdb.pdf: ${GDB_DOC_FILES}
# GDB MANUAL: info file
gdb.info: ${GDB_DOC_FILES}
- $(MAKEINFO) $(READLINE_TEXI_INCFLAG) -I ${GDBMI_DIR} -I $(srcdir) \
+ $(MAKEINFO_CMD) $(READLINE_TEXI_INCFLAG) -I ${GDBMI_DIR} -I $(srcdir) \
-o gdb.info $(srcdir)/gdb.texinfo
# GDB MANUAL: roff translations
@@ -464,7 +467,7 @@ gdbint.pdf: $(GDBINT_DOC_FILES)
# GDB INTERNALS MANUAL: info file
gdbint.info: $(GDBINT_DOC_FILES)
- $(MAKEINFO) -I $(srcdir) -o gdbint.info $(srcdir)/gdbint.texinfo
+ $(MAKEINFO_CMD) -I $(srcdir) -o gdbint.info $(srcdir)/gdbint.texinfo
# GDB INTERNALS MANUAL: HTML file
@@ -472,7 +475,7 @@ gdbint/index.html: $(GDBINT_DOC_FILES)
$(MAKEHTML) $(MAKEHTMLFLAGS) -I $(srcdir) $(srcdir)/gdbint.texinfo
stabs.info: $(STABS_DOC_FILES)
- $(MAKEINFO) -I $(srcdir) -o stabs.info $(srcdir)/stabs.texinfo
+ $(MAKEINFO_CMD) -I $(srcdir) -o stabs.info $(srcdir)/stabs.texinfo
# STABS DOCUMENTATION: HTML file
@@ -516,7 +519,7 @@ annotate.pdf: $(ANNOTATE_DOC_FILES)
$(TEXI2DVI) --pdf -I $(srcdir) $(srcdir)/annotate.texinfo
annotate.info: $(ANNOTATE_DOC_FILES)
- $(MAKEINFO) -I $(srcdir) -o annotate.info $(srcdir)/annotate.texinfo
+ $(MAKEINFO_CMD) -I $(srcdir) -o annotate.info $(srcdir)/annotate.texinfo
annotate/index.html: $(ANNOTATE_DOC_FILES)
$(MAKEHTML) $(MAKEHTMLFLAGS) -I $(srcdir) $(srcdir)/annotate.texinfo
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9789,11 +9789,24 @@ tailcall: reduced: 0x4004d2(a) |
#2 0x0000000000400395 in main () at t.c:9
@end smallexample
-Frames #0 and #2 are real, #1 is a virtual tail call frame. The code can have
-possible execution paths
-@code{main@arrow{}a@arrow{}b@arrow{}c@arrow{}d@arrow{}f} or
-@code{main@arrow{}a@arrow{}b@arrow{}e@arrow{}f}, @value{GDBN} cannot find which
-one from the inferior state.
+@set CALLSEQ1A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}c@value{ARROW}d@value{ARROW}f}
+@set CALLSEQ2A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}e@value{ARROW}f}
+
+@c Convert CALLSEQ#A to CALLSEQ#B depending on HAVE_MAKEINFO_CLICK.
+@ifset HAVE_MAKEINFO_CLICK
+@set ARROW @click{}
+@set CALLSEQ1B @clicksequence{@value{CALLSEQ1A}}
+@set CALLSEQ2B @clicksequence{@value{CALLSEQ2A}}
+@end ifset
+@ifclear HAVE_MAKEINFO_CLICK
+@set ARROW ->
+@set CALLSEQ1B @value{CALLSEQ1A}
+@set CALLSEQ2B @value{CALLSEQ2A}
+@end ifclear
+
+Frames #0 and #2 are real, #1 is a virtual tail call frame.
+The code can have possible execution paths @value{CALLSEQ1B} or
+@value{CALLSEQ2B}, @value{GDBN} cannot find which one from the inferior state.
@code{initial:} state shows some random possible calling sequence @value{GDBN}
has found. It then finds another possible calling sequcen - that one is
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-11 23:34 ` Jan Kratochvil
@ 2011-10-12 15:26 ` Pedro Alves
2011-10-12 15:56 ` Jan Kratochvil
2011-10-25 14:35 ` Joel Brobecker
1 sibling, 1 reply; 23+ messages in thread
From: Pedro Alves @ 2011-10-12 15:26 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Andreas Schwab, gdb-patches, Ulrich Weigand, eliz
On Wednesday 12 October 2011 00:34:17, Jan Kratochvil wrote:
> On Mon, 10 Oct 2011 23:56:34 +0200, Pedro Alves wrote:
> > On Monday 10 October 2011 19:47:26, Jan Kratochvil wrote:
> > > + if makeinfo conftest.texinfo >&5 2>&5; then
> >
> > Shouldn't this be $(MAKEINFO) instead (like in Makefile.in)?
> > Though I'm not sure how to do that here. Maybe
> > AC_CHECK_PROGS(MAKEINFO, makeinfo) ?
>
> Yes, it should, although it is more complicated.
>
> There is IMO a bug in toplevel configure it does not pass down MAKEINFOFLAGS
> and includes "--split-size=5000000" directly into MAKEINFO. Without the
> special handling of --split-size=5000000 it would be used during first
> compilation but no longer used after automatic re-run of configure in gdb/
> (although only if one deletes gdb/config.cache).
I see. We should get that fixed someday.
> Therefore I added --split-size=5000000 there explicitly, which means it is
> duplicated during the dirst compilation but it does not matter.
>
> --split-size=5000000 was not used in gdb/doc/ before at all but I think it was
> a bug, even gcc uses --no-split.
No opinion on that.
> On Tue, 11 Oct 2011 00:18:54 +0200, Andreas Schwab wrote:
> > You should not modify MAKEINFO. If you say
> > "make info MAKEINFO=/usr/local/bin/makeinfo" you lose the flags.
>
> True, toplevel configure is already violating that but fixed it in gdb/ .
Thanks. Looks good to me.
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-11 23:34 ` Jan Kratochvil
2011-10-12 15:26 ` Pedro Alves
@ 2011-10-25 14:35 ` Joel Brobecker
2011-10-25 14:47 ` Jan Kratochvil
1 sibling, 1 reply; 23+ messages in thread
From: Joel Brobecker @ 2011-10-25 14:35 UTC (permalink / raw)
To: Jan Kratochvil
Cc: Pedro Alves, Andreas Schwab, gdb-patches, Ulrich Weigand, eliz
Hi Jan,
> gdb/
> 2011-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> Fix compatibility with texinfo versions older than 4.12.
> * Makefile.in (MAKEINFO): Set to @MAKEINFO@.
> (MAKEINFOFLAGS, MAKEINFO_EXTRA_FLAGS, MAKEINFO_CMD): New.
> (MAKEHTMLFLAGS): Use MAKEINFO_CMD.
> (FLAGS_TO_PASS): Add MAKEINFOFLAGS and MAKEINFO_EXTRA_FLAGS.
> * configure: Regenerate.
> * configure.ac (MAKEINFO): Find it, from libiberty/configure.ac.
> (MAKEINFOFLAGS): Pre-set it to --split-size=5000000.
> (MAKEINFO_EXTRA_FLAGS): New test for -DHAVE_MAKEINFO_CLICK.
There is one bit that I don't understand:
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -87,6 +87,38 @@ PACKAGE=gdb
> AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package. ])
> AC_SUBST(PACKAGE)
>
> +# Do we have a single-tree copy of texinfo? Even if we do, we can't
> +# rely on it - libiberty is built before texinfo.
> +AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo, )
> +if test "x$MAKEINFO" = "x"; then
> + AC_ERROR([makeinfo is required for compilation])
Why do we error out if makeinfo is not available? I think we should do
the same as other projects such as binutils where we display a warning
("makeinfo is missing, documentation will not be built"), and then
continue. We used to be able to build without requiring makeinfo, and
installing makeinfo on all machines on our network would be a real pain.
For us, we know how to work around the problem (configure with
MAKEINFO=true), but less experience users might not.
Let me know what you think, and I'll see if I can whip up a patch.
--
Joel
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-25 14:35 ` Joel Brobecker
@ 2011-10-25 14:47 ` Jan Kratochvil
2011-10-25 16:09 ` Joel Brobecker
0 siblings, 1 reply; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-25 14:47 UTC (permalink / raw)
To: Joel Brobecker
Cc: Pedro Alves, Andreas Schwab, gdb-patches, Ulrich Weigand, eliz
On Tue, 25 Oct 2011 16:26:47 +0200, Joel Brobecker wrote:
> Why do we error out if makeinfo is not available?
As the GDB build errored out by some error later anyway which was moreover not
understandable to the users.
> I think we should do
> the same as other projects such as binutils where we display a warning
> ("makeinfo is missing, documentation will not be built"), and then
> continue. We used to be able to build without requiring makeinfo, and
> installing makeinfo on all machines on our network would be a real pain.
> For us, we know how to work around the problem (configure with
> MAKEINFO=true), but less experience users might not.
As I said in one of the mails I would welcome to be able to build gdb without
makeinfo. It is always a pain having to install all the texinfo to some slow
exotic arch just to be able to build native gdb there.
I see I could make some mistake but even before the patch of mine above GDB
just was not able to build without makeinfo. I once tried to fix it - so that
GDB can be built without makeinfo (just not building any doc) but I had some
problems making such patch and as the patch had no business justifications
I just gave up on it.
It would be sure a great patch after the years of pain if you have / could
provide such one.
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-25 14:47 ` Jan Kratochvil
@ 2011-10-25 16:09 ` Joel Brobecker
0 siblings, 0 replies; 23+ messages in thread
From: Joel Brobecker @ 2011-10-25 16:09 UTC (permalink / raw)
To: Jan Kratochvil
Cc: Pedro Alves, Andreas Schwab, gdb-patches, Ulrich Weigand, eliz
> > Why do we error out if makeinfo is not available?
>
> As the GDB build errored out by some error later anyway which was moreover not
> understandable to the users.
I see, it's `make install' from bfd/ that is failing. One of these
days, I will have to take care of that. We used to do much better
in GDB, and now it feels like we've regressed. But, as you correctly
point out, from the user's perspective, things are equivalent.
--
Joel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 15:31 ` Jan Kratochvil
2011-10-10 15:51 ` Pedro Alves
@ 2011-10-10 16:10 ` Eli Zaretskii
2011-10-10 16:15 ` Jan Kratochvil
1 sibling, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2011-10-10 16:10 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: pedro, gdb-patches, uweigand
> Date: Mon, 10 Oct 2011 17:30:49 +0200
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Cc: gdb-patches@sourceware.org, Ulrich Weigand <uweigand@de.ibm.com>,
> eliz@gnu.org
>
> I can provide alternative less nifty graphical representation keeping the text
> even with older texinfos.
That'd be fine, but there's no good way in Texinfo to test for the
version of makeinfo. So what exactly would be the condition for using
the alternative?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 16:10 ` Eli Zaretskii
@ 2011-10-10 16:15 ` Jan Kratochvil
0 siblings, 0 replies; 23+ messages in thread
From: Jan Kratochvil @ 2011-10-10 16:15 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: pedro, gdb-patches, uweigand
On Mon, 10 Oct 2011 18:10:04 +0200, Eli Zaretskii wrote:
> That'd be fine, but there's no good way in Texinfo to test for the
> version of makeinfo. So what exactly would be the condition for using
> the alternative?
There is already the feature test in my last patch by autoconf. Going to post
the alternative (ASCII art?) variant in a moment.
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)]
2011-10-10 15:16 ` Pedro Alves
2011-10-10 15:31 ` Jan Kratochvil
@ 2011-10-10 16:09 ` Eli Zaretskii
1 sibling, 0 replies; 23+ messages in thread
From: Eli Zaretskii @ 2011-10-10 16:09 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, jan.kratochvil, uweigand
> From: Pedro Alves <pedro@codesourcery.com>
> Date: Mon, 10 Oct 2011 16:15:38 +0100
> Cc: Jan Kratochvil <jan.kratochvil@redhat.com>,
> Ulrich Weigand <uweigand@de.ibm.com>,
> eliz@gnu.org
>
> On Monday 10 October 2011 15:57:49, Jan Kratochvil wrote:
> > +@ifset HAVE_MAKEINFO_CLICK
> > +The code can have possible execution paths
> > +@clicksequence{main@click{}a@click{}b@click{}c@click{}d@click{}f} or
> > +@clicksequence{main@click{}a@click{}b@click{}e@click{}f}, @value{GDBN} cannot find which
> > one from the inferior state.
> > +@end ifset
>
> Leaving a piece of the manual out like that is not okay.
I agree.
> If this feature is too new for the currently required makeinfo
> version (which is it, btw?), we have two real choices:
>
> 1. bump the minimum required makeinfo version so we can use it
> 2. don't use the new feature
I don't want to do (1), because 4.8 is not too old relatively to 4.12,
and many people still use it. OTOH, there's nothing wrong with using
ASCII art in this case.
Jan, how strong are your feelings about using @arrow or @click?
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2011-10-25 14:47 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-29 19:50 [patch 04/12] entryval#3: Virtual tail call frames Jan Kratochvil
2011-10-09 19:27 ` [commit] " Jan Kratochvil
2011-10-09 20:23 ` Jan Kratochvil
2011-10-10 13:40 ` doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames) Ulrich Weigand
2011-10-10 13:54 ` Eli Zaretskii
2011-10-10 13:58 ` Ulrich Weigand
2011-10-10 14:58 ` [patch] New test+use texinfo @click - @HAVE_MAKEINFO_CLICK@ [Re: doc build failure (Re: [patch 04/12] entryval#3: Virtual tail call frames)] Jan Kratochvil
2011-10-10 15:16 ` Pedro Alves
2011-10-10 15:31 ` Jan Kratochvil
2011-10-10 15:51 ` Pedro Alves
2011-10-10 18:47 ` Jan Kratochvil
2011-10-10 19:11 ` Eli Zaretskii
2011-10-10 21:56 ` Pedro Alves
2011-10-10 22:19 ` Andreas Schwab
2011-10-11 23:34 ` Jan Kratochvil
2011-10-12 15:26 ` Pedro Alves
2011-10-12 15:56 ` Jan Kratochvil
2011-10-25 14:35 ` Joel Brobecker
2011-10-25 14:47 ` Jan Kratochvil
2011-10-25 16:09 ` Joel Brobecker
2011-10-10 16:10 ` Eli Zaretskii
2011-10-10 16:15 ` Jan Kratochvil
2011-10-10 16:09 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox