btrace, frame: fix crash in get_frame_type

In skip_artificial_frames we repeatedly call get_prev_frame_always until we get
a non-inline and non-tailcall frame assuming that there must be such a frame
eventually.

For record targets, however, we may have a frame chain that consists only of
artificial frames.  This leads to a crash in get_frame_type when dereferencing a
NULL frame pointer.

Change skip_artificial_frames and skip_tailcall_frames to return NULL in such a
case and modify each caller to cope with a NULL return.

In frame_unwind_caller_pc and frame_unwind_caller_arch, we simply assert that
the returned value is not NULL.  Their caller was supposed to check
frame_unwind_caller_id before calling those functions.

In other cases, we thrown an error.

In infcmd further move the skip_tailcall_frames call to the forward-stepping
case since we don't need a frame for reverse execution and we don't want to fail
because of that.  Reverse-finish does make sense for a tailcall frame.

gdb/
	* frame.h (skip_tailcall_frames): Update comment.
	* frame.c (skip_artificial_frames, skip_tailcall_frames): Return NULL
	if only	artificial frames are found.  Update comment.
	(frame_unwind_caller_id): Handle NULL return.
	(frame_unwind_caller_pc, frame_unwind_caller_arch): Assert that
	skip_artificial_frames does not return NULL.
	(frame_pop): Add an error if only tailcall frames are found.
	* infcmd.c (finish_command): Move skip_tailcall_frames call into forward-
	execution case.  Add an error if only tailcall frames are found.

testsuite/
	* gdb.btrace/tailcall-only.exp: New.
	* gdb.btrace/tailcall-only.c: New.
	* gdb.btrace/x86_64-tailcall-only.S: New.
	* gdb.btrace/i686-tailcall-only.S: New.
This commit is contained in:
Markus Metzger
2016-01-26 14:58:44 +01:00
parent a038fa3e14
commit 33b4777ca1
9 changed files with 1115 additions and 14 deletions

View File

@ -1,3 +1,16 @@
2016-02-12 Markus Metzger <markus.t.metzger@intel.com>
* frame.h (skip_tailcall_frames): Update comment.
* frame.c (skip_artificial_frames, skip_tailcall_frames): Return NULL
if only artificial frames are found. Update comment.
(frame_unwind_caller_id): Handle NULL return.
(frame_unwind_caller_pc, frame_unwind_caller_arch): Assert that
skip_artificial_frames does not return NULL.
(frame_pop): Add an error if only tailcall frames are found.
* infcmd.c (finish_command): Move skip_tailcall_frames call into
forward-execution case. Add an error if only tailcall frames are
found.
2016-02-12 Markus Metzger <markus.t.metzger@intel.com> 2016-02-12 Markus Metzger <markus.t.metzger@intel.com>
* stack.c (frame_info): Check frame_unwind_caller_id. * stack.c (frame_info): Check frame_unwind_caller_id.

View File

@ -420,7 +420,8 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
/* Given FRAME, return the enclosing frame as found in real frames read-in from /* Given FRAME, return the enclosing frame as found in real frames read-in from
inferior memory. Skip any previous frames which were made up by GDB. inferior memory. Skip any previous frames which were made up by GDB.
Return the original frame if no immediate previous frames exist. */ Return FRAME if FRAME is a non-artificial frame.
Return NULL if FRAME is the start of an artificial-only chain. */
static struct frame_info * static struct frame_info *
skip_artificial_frames (struct frame_info *frame) skip_artificial_frames (struct frame_info *frame)
@ -428,12 +429,17 @@ skip_artificial_frames (struct frame_info *frame)
/* Note we use get_prev_frame_always, and not get_prev_frame. The /* Note we use get_prev_frame_always, and not get_prev_frame. The
latter will truncate the frame chain, leading to this function latter will truncate the frame chain, leading to this function
unintentionally returning a null_frame_id (e.g., when the user unintentionally returning a null_frame_id (e.g., when the user
sets a backtrace limit). This is safe, because as these frames sets a backtrace limit).
are made up by GDB, there must be a real frame in the chain
below. */ Note that for record targets we may get a frame chain that consists
of artificial frames only. */
while (get_frame_type (frame) == INLINE_FRAME while (get_frame_type (frame) == INLINE_FRAME
|| get_frame_type (frame) == TAILCALL_FRAME) || get_frame_type (frame) == TAILCALL_FRAME)
frame = get_prev_frame_always (frame); {
frame = get_prev_frame_always (frame);
if (frame == NULL)
break;
}
return frame; return frame;
} }
@ -444,7 +450,13 @@ struct frame_info *
skip_tailcall_frames (struct frame_info *frame) skip_tailcall_frames (struct frame_info *frame)
{ {
while (get_frame_type (frame) == TAILCALL_FRAME) while (get_frame_type (frame) == TAILCALL_FRAME)
frame = get_prev_frame (frame); {
/* Note that for record targets we may get a frame chain that consists of
tailcall frames only. */
frame = get_prev_frame (frame);
if (frame == NULL)
break;
}
return frame; return frame;
} }
@ -507,6 +519,9 @@ frame_unwind_caller_id (struct frame_info *next_frame)
requests the frame ID of "main()"s caller. */ requests the frame ID of "main()"s caller. */
next_frame = skip_artificial_frames (next_frame); next_frame = skip_artificial_frames (next_frame);
if (next_frame == NULL)
return null_frame_id;
this_frame = get_prev_frame_always (next_frame); this_frame = get_prev_frame_always (next_frame);
if (this_frame) if (this_frame)
return get_frame_id (skip_artificial_frames (this_frame)); return get_frame_id (skip_artificial_frames (this_frame));
@ -880,7 +895,14 @@ frame_unwind_pc (struct frame_info *this_frame)
CORE_ADDR CORE_ADDR
frame_unwind_caller_pc (struct frame_info *this_frame) frame_unwind_caller_pc (struct frame_info *this_frame)
{ {
return frame_unwind_pc (skip_artificial_frames (this_frame)); this_frame = skip_artificial_frames (this_frame);
/* We must have a non-artificial frame. The caller is supposed to check
the result of frame_unwind_caller_id (), which returns NULL_FRAME_ID
in this case. */
gdb_assert (this_frame != NULL);
return frame_unwind_pc (this_frame);
} }
int int
@ -985,6 +1007,9 @@ frame_pop (struct frame_info *this_frame)
entering THISFRAME. */ entering THISFRAME. */
prev_frame = skip_tailcall_frames (prev_frame); prev_frame = skip_tailcall_frames (prev_frame);
if (prev_frame == NULL)
error (_("Cannot find the caller frame."));
/* Make a copy of all the register values unwound from this frame. /* Make a copy of all the register values unwound from this frame.
Save them in a scratch buffer so that there isn't a race between Save them in a scratch buffer so that there isn't a race between
trying to extract the old values from the current regcache while trying to extract the old values from the current regcache while
@ -2571,7 +2596,14 @@ frame_unwind_arch (struct frame_info *next_frame)
struct gdbarch * struct gdbarch *
frame_unwind_caller_arch (struct frame_info *next_frame) frame_unwind_caller_arch (struct frame_info *next_frame)
{ {
return frame_unwind_arch (skip_artificial_frames (next_frame)); next_frame = skip_artificial_frames (next_frame);
/* We must have a non-artificial frame. The caller is supposed to check
the result of frame_unwind_caller_id (), which returns NULL_FRAME_ID
in this case. */
gdb_assert (next_frame != NULL);
return frame_unwind_arch (next_frame);
} }
/* Gets the language of FRAME. */ /* Gets the language of FRAME. */

View File

@ -821,7 +821,8 @@ extern int frame_unwinder_is (struct frame_info *fi,
extern enum language get_frame_language (struct frame_info *frame); extern enum language get_frame_language (struct frame_info *frame);
/* Return the first non-tailcall frame above FRAME or FRAME if it is not a /* Return the first non-tailcall frame above FRAME or FRAME if it is not a
tailcall frame. */ tailcall frame. Return NULL if FRAME is the start of a tailcall-only
chain. */
extern struct frame_info *skip_tailcall_frames (struct frame_info *frame); extern struct frame_info *skip_tailcall_frames (struct frame_info *frame);

View File

@ -2000,10 +2000,6 @@ finish_command (char *arg, int from_tty)
return; return;
} }
/* Ignore TAILCALL_FRAME type frames, they were executed already before
entering THISFRAME. */
frame = skip_tailcall_frames (frame);
/* Find the function we will return from. */ /* Find the function we will return from. */
sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
@ -2030,7 +2026,16 @@ finish_command (char *arg, int from_tty)
if (execution_direction == EXEC_REVERSE) if (execution_direction == EXEC_REVERSE)
finish_backward (sm); finish_backward (sm);
else else
finish_forward (sm, frame); {
/* Ignore TAILCALL_FRAME type frames, they were executed already before
entering THISFRAME. */
frame = skip_tailcall_frames (frame);
if (frame == NULL)
error (_("Cannot find the caller frame."));
finish_forward (sm, frame);
}
} }

View File

@ -1,3 +1,10 @@
2016-02-12 Markus Metzger <markus.t.metzger@intel.com>
* gdb.btrace/tailcall-only.exp: New.
* gdb.btrace/tailcall-only.c: New.
* gdb.btrace/x86_64-tailcall-only.S: New.
* gdb.btrace/i686-tailcall-only.S: New.
2016-02-11 Pedro Alves <palves@redhat.com> 2016-02-11 Pedro Alves <palves@redhat.com>
* README (Parallel testing): Add missing double quotes. * README (Parallel testing): Add missing double quotes.

View File

@ -0,0 +1,447 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2016 Free Software Foundation, Inc.
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/>.
This file has been generated using:
gcc -m32 -march=i686 -S -O2 -dA -g tailcall-only.c -o i686-tailcall-only.S
*/
.file "tailcall-only.c"
.text
.Ltext0:
.p2align 4,,15
.type bar_1, @function
bar_1:
.LFB0:
.file 1 "tailcall-only.c"
# tailcall-only.c:22
.loc 1 22 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:24
.loc 1 24 0
movl $42, %eax
# SUCC: EXIT [100.0%]
ret
.cfi_endproc
.LFE0:
.size bar_1, .-bar_1
.p2align 4,,15
.type bar, @function
bar:
.LFB1:
# tailcall-only.c:28
.loc 1 28 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:29
.loc 1 29 0
jmp bar_1
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL0:
.cfi_endproc
.LFE1:
.size bar, .-bar
.p2align 4,,15
.type foo_1, @function
foo_1:
.LFB2:
# tailcall-only.c:34
.loc 1 34 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:35
.loc 1 35 0
jmp bar
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL1:
.cfi_endproc
.LFE2:
.size foo_1, .-foo_1
.p2align 4,,15
.type foo, @function
foo:
.LFB3:
# tailcall-only.c:40
.loc 1 40 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:41
.loc 1 41 0
jmp foo_1
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL2:
.cfi_endproc
.LFE3:
.size foo, .-foo
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB4:
# tailcall-only.c:46
.loc 1 46 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:49
.loc 1 49 0
call foo
.LVL3:
# tailcall-only.c:50
.loc 1 50 0
addl $1, %eax
.LVL4:
# SUCC: EXIT [100.0%]
# tailcall-only.c:53
.loc 1 53 0
ret
.cfi_endproc
.LFE4:
.size main, .-main
.text
.Letext0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.long 0xd5 # Length of Compilation Unit Info
.value 0x4 # DWARF version number
.long .Ldebug_abbrev0 # Offset Into Abbrev. Section
.byte 0x4 # Pointer Size (in bytes)
.uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
.long .LASF1 # DW_AT_producer: "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -m32 -march=i686 -g -O2"
.byte 0x1 # DW_AT_language
.long .LASF2 # DW_AT_name: "tailcall-only.c"
.long .LASF3 # DW_AT_comp_dir: ""
.long .Ldebug_ranges0+0 # DW_AT_ranges
.long 0 # DW_AT_low_pc
.long .Ldebug_line0 # DW_AT_stmt_list
.uleb128 0x2 # (DIE (0x25) DW_TAG_subprogram)
.long .LASF4 # DW_AT_name: "bar_1"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x15 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x3a # DW_AT_type
.long .LFB0 # DW_AT_low_pc
.long .LFE0-.LFB0 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.uleb128 0x3 # (DIE (0x3a) DW_TAG_base_type)
.byte 0x4 # DW_AT_byte_size
.byte 0x5 # DW_AT_encoding
.ascii "int\0" # DW_AT_name
.uleb128 0x4 # (DIE (0x41) DW_TAG_subprogram)
.ascii "bar\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x1b # DW_AT_decl_line
# DW_AT_prototyped
.long 0x3a # DW_AT_type
.long .LFB1 # DW_AT_low_pc
.long .LFE1-.LFB1 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0x64 # DW_AT_sibling
.uleb128 0x5 # (DIE (0x5a) DW_TAG_GNU_call_site)
.long .LVL0 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x25 # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0x41
.uleb128 0x6 # (DIE (0x64) DW_TAG_subprogram)
.long .LASF0 # DW_AT_name: "foo_1"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x21 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x3a # DW_AT_type
.long .LFB2 # DW_AT_low_pc
.long .LFE2-.LFB2 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0x87 # DW_AT_sibling
.uleb128 0x5 # (DIE (0x7d) DW_TAG_GNU_call_site)
.long .LVL1 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x41 # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0x64
.uleb128 0x4 # (DIE (0x87) DW_TAG_subprogram)
.ascii "foo\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x27 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x3a # DW_AT_type
.long .LFB3 # DW_AT_low_pc
.long .LFE3-.LFB3 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0xaa # DW_AT_sibling
.uleb128 0x5 # (DIE (0xa0) DW_TAG_GNU_call_site)
.long .LVL2 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x64 # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0x87
.uleb128 0x7 # (DIE (0xaa) DW_TAG_subprogram)
# DW_AT_external
.long .LASF5 # DW_AT_name: "main"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x2d # DW_AT_decl_line
# DW_AT_prototyped
.long 0x3a # DW_AT_type
.long .LFB4 # DW_AT_low_pc
.long .LFE4-.LFB4 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.uleb128 0x8 # (DIE (0xbf) DW_TAG_variable)
.long .LASF6 # DW_AT_name: "answer"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x2f # DW_AT_decl_line
.long 0x3a # DW_AT_type
.long .LLST0 # DW_AT_location
.uleb128 0x9 # (DIE (0xce) DW_TAG_GNU_call_site)
.long .LVL3 # DW_AT_low_pc
.long 0x87 # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0xaa
.byte 0 # end of children of DIE 0xb
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.uleb128 0x1 # (abbrev code)
.uleb128 0x11 # (TAG: DW_TAG_compile_unit)
.byte 0x1 # DW_children_yes
.uleb128 0x25 # (DW_AT_producer)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x13 # (DW_AT_language)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x1b # (DW_AT_comp_dir)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x55 # (DW_AT_ranges)
.uleb128 0x17 # (DW_FORM_sec_offset)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x10 # (DW_AT_stmt_list)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x2 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x6 # (DW_FORM_data4)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.byte 0
.byte 0
.uleb128 0x3 # (abbrev code)
.uleb128 0x24 # (TAG: DW_TAG_base_type)
.byte 0 # DW_children_no
.uleb128 0xb # (DW_AT_byte_size)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3e # (DW_AT_encoding)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.byte 0
.byte 0
.uleb128 0x4 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x6 # (DW_FORM_data4)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x5 # (abbrev code)
.uleb128 0x4109 # (TAG: DW_TAG_GNU_call_site)
.byte 0 # DW_children_no
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x2115 # (DW_AT_GNU_tail_call)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x6 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x6 # (DW_FORM_data4)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x7 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3f # (DW_AT_external)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x6 # (DW_FORM_data4)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.byte 0
.byte 0
.uleb128 0x8 # (abbrev code)
.uleb128 0x34 # (TAG: DW_TAG_variable)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x2 # (DW_AT_location)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x9 # (abbrev code)
.uleb128 0x4109 # (TAG: DW_TAG_GNU_call_site)
.byte 0 # DW_children_no
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.byte 0
.section .debug_loc,"",@progbits
.Ldebug_loc0:
.LLST0:
.long .LVL3 # Location list begin address (*.LLST0)
.long .LVL4 # Location list end address (*.LLST0)
.value 0x3 # Location expression size
.byte 0x70 # DW_OP_breg0
.sleb128 1
.byte 0x9f # DW_OP_stack_value
.long .LVL4 # Location list begin address (*.LLST0)
.long .LFE4 # Location list end address (*.LLST0)
.value 0x1 # Location expression size
.byte 0x50 # DW_OP_reg0
.long 0 # Location list terminator begin (*.LLST0)
.long 0 # Location list terminator end (*.LLST0)
.section .debug_aranges,"",@progbits
.long 0x24 # Length of Address Ranges Info
.value 0x2 # DWARF Version
.long .Ldebug_info0 # Offset of Compilation Unit Info
.byte 0x4 # Size of Address
.byte 0 # Size of Segment Descriptor
.value 0 # Pad to 8 byte boundary
.value 0
.long .Ltext0 # Address
.long .Letext0-.Ltext0 # Length
.long .LFB4 # Address
.long .LFE4-.LFB4 # Length
.long 0
.long 0
.section .debug_ranges,"",@progbits
.Ldebug_ranges0:
.long .Ltext0 # Offset 0
.long .Letext0
.long .LFB4 # Offset 0x8
.long .LFE4
.long 0
.long 0
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.LASF4:
.string "bar_1"
.LASF2:
.string "tailcall-only.c"
.LASF1:
.string "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -m32 -march=i686 -g -O2"
.LASF6:
.string "answer"
.LASF5:
.string "main"
.LASF3:
.string ""
.LASF0:
.string "foo_1"
.ident "GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-9)"
.section .note.GNU-stack,"",@progbits

View File

@ -0,0 +1,53 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2016 Free Software Foundation, Inc.
Contributed by Intel Corp. <markus.t.metzger@intel.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
static __attribute__ ((noinline)) int
bar_1 (void)
{
return 42;
}
static __attribute__ ((noinline)) int
bar (void)
{
return bar_1 ();
}
static __attribute__ ((noinline)) int
foo_1 (void)
{
return bar ();
}
static __attribute__ ((noinline)) int
foo (void)
{
return foo_1 ();
}
int
main (void)
{
int answer;
answer = foo ();
answer += 1;
return answer;
}

View File

@ -0,0 +1,97 @@
# This testcase is part of GDB, the GNU debugger.
#
# Copyright 2016 Free Software Foundation, Inc.
#
# 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/>.
#
#
# This is a variant of tailcall.exp where the entire trace contains only tail
# calls. This used to cause a crash in get_frame_type.
#
# check for btrace support
if { [skip_btrace_tests] } { return -1 }
# This test requires the compiler to generate a tail call. To guarantee that
# we always get one, we use an assembly source file.
#
# We use different assembly sources based on the target architecture.
#
# Luckily, they are similar enough that a single test script can handle
# both.
set opts {}
if [info exists COMPILE] {
# make check RUNTESTFLAGS="gdb.btrace/tailcall-only.exp COMPILE=1"
standard_testfile tailcall-only.c
lappend opts debug optimize=-O2
} elseif {[istarget "x86_64-*-*"]} {
standard_testfile x86_64-tailcall-only.S
} elseif {[istarget "i?86-*-*"]} {
standard_testfile i686-tailcall-only.S
} else {
verbose "Skipping ${testfile}."
return
}
if [prepare_for_testing tailcall-only.exp $testfile $srcfile $opts] {
return -1
}
if ![runto_main] {
return -1
}
# we want to see the full trace for this test
gdb_test_no_output "set record function-call-history-size 0"
# trace foo
gdb_test "step" ".*" "prepare for recording"
gdb_test_no_output "record btrace"
gdb_test "stepi 4" ".*" "record branch trace"
# for debugging
gdb_test "info record" ".*"
# show the branch trace with calls indented
gdb_test "record function-call-history /c 1" [multi_line \
"1\tfoo" \
"2\t foo_1" \
"3\t bar" \
"4\t bar_1"
] "function-call-history"
# We can step
gdb_test "record goto begin" ".*foo.*"
gdb_test "stepi" ".*foo_1.*" "step into foo_1"
gdb_test "step" ".*bar.*" "step into bar"
gdb_test "stepi" ".*bar_1.*" "step into bar_1"
# We can neither finish nor return.
gdb_test "finish" "Cannot find the caller frame.*"
gdb_test_multiple "return" "return" {
-re "Make .* return now.*y or n. $" {
send_gdb "y\n"
exp_continue
}
-re "Cannot find the caller frame.*$gdb_prompt $" {
pass "return"
}
}
# But we can reverse-finish
gdb_test "reverse-finish" ".*bar.*"
gdb_test "reverse-step" ".*foo_1.*"
# Info frame isn't useful but doesn't crash as it used to.
gdb_test "up" ".*foo.*"
gdb_test "info frame" ".*"

View File

@ -0,0 +1,446 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2016 Free Software Foundation, Inc.
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/>.
This file has been generated using:
gcc -S -O2 -dA -g tailcall-only.c -o x86_64-tailcall-only.S */
.file "tailcall-only.c"
.text
.Ltext0:
.p2align 4,,15
.type bar_1, @function
bar_1:
.LFB0:
.file 1 "tailcall-only.c"
# tailcall-only.c:22
.loc 1 22 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:24
.loc 1 24 0
movl $42, %eax
# SUCC: EXIT [100.0%]
ret
.cfi_endproc
.LFE0:
.size bar_1, .-bar_1
.p2align 4,,15
.type bar, @function
bar:
.LFB1:
# tailcall-only.c:28
.loc 1 28 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:29
.loc 1 29 0
jmp bar_1
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL0:
.cfi_endproc
.LFE1:
.size bar, .-bar
.p2align 4,,15
.type foo_1, @function
foo_1:
.LFB2:
# tailcall-only.c:34
.loc 1 34 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:35
.loc 1 35 0
jmp bar
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL1:
.cfi_endproc
.LFE2:
.size foo_1, .-foo_1
.p2align 4,,15
.type foo, @function
foo:
.LFB3:
# tailcall-only.c:40
.loc 1 40 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:41
.loc 1 41 0
jmp foo_1
# SUCC: EXIT [100.0%] (ABNORMAL,SIBCALL)
.LVL2:
.cfi_endproc
.LFE3:
.size foo, .-foo
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB4:
# tailcall-only.c:46
.loc 1 46 0
.cfi_startproc
# BLOCK 2 freq:10000 seq:0
# PRED: ENTRY [100.0%] (FALLTHRU)
# tailcall-only.c:49
.loc 1 49 0
call foo
.LVL3:
# tailcall-only.c:50
.loc 1 50 0
addl $1, %eax
.LVL4:
# SUCC: EXIT [100.0%]
# tailcall-only.c:53
.loc 1 53 0
ret
.cfi_endproc
.LFE4:
.size main, .-main
.text
.Letext0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.long 0x111 # Length of Compilation Unit Info
.value 0x4 # DWARF version number
.long .Ldebug_abbrev0 # Offset Into Abbrev. Section
.byte 0x8 # Pointer Size (in bytes)
.uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
.long .LASF1 # DW_AT_producer: "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -mtune=generic -march=x86-64 -g -O2"
.byte 0x1 # DW_AT_language
.long .LASF2 # DW_AT_name: "tailcall-only.c"
.long .LASF3 # DW_AT_comp_dir: ""
.long .Ldebug_ranges0+0 # DW_AT_ranges
.quad 0 # DW_AT_low_pc
.long .Ldebug_line0 # DW_AT_stmt_list
.uleb128 0x2 # (DIE (0x29) DW_TAG_subprogram)
.long .LASF4 # DW_AT_name: "bar_1"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x15 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x46 # DW_AT_type
.quad .LFB0 # DW_AT_low_pc
.quad .LFE0-.LFB0 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.uleb128 0x3 # (DIE (0x46) DW_TAG_base_type)
.byte 0x4 # DW_AT_byte_size
.byte 0x5 # DW_AT_encoding
.ascii "int\0" # DW_AT_name
.uleb128 0x4 # (DIE (0x4d) DW_TAG_subprogram)
.ascii "bar\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x1b # DW_AT_decl_line
# DW_AT_prototyped
.long 0x46 # DW_AT_type
.quad .LFB1 # DW_AT_low_pc
.quad .LFE1-.LFB1 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0x7c # DW_AT_sibling
.uleb128 0x5 # (DIE (0x6e) DW_TAG_GNU_call_site)
.quad .LVL0 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x29 # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0x4d
.uleb128 0x6 # (DIE (0x7c) DW_TAG_subprogram)
.long .LASF0 # DW_AT_name: "foo_1"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x21 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x46 # DW_AT_type
.quad .LFB2 # DW_AT_low_pc
.quad .LFE2-.LFB2 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0xab # DW_AT_sibling
.uleb128 0x5 # (DIE (0x9d) DW_TAG_GNU_call_site)
.quad .LVL1 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x4d # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0x7c
.uleb128 0x4 # (DIE (0xab) DW_TAG_subprogram)
.ascii "foo\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x27 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x46 # DW_AT_type
.quad .LFB3 # DW_AT_low_pc
.quad .LFE3-.LFB3 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0xda # DW_AT_sibling
.uleb128 0x5 # (DIE (0xcc) DW_TAG_GNU_call_site)
.quad .LVL2 # DW_AT_low_pc
# DW_AT_GNU_tail_call
.long 0x7c # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0xab
.uleb128 0x7 # (DIE (0xda) DW_TAG_subprogram)
# DW_AT_external
.long .LASF5 # DW_AT_name: "main"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x2d # DW_AT_decl_line
# DW_AT_prototyped
.long 0x46 # DW_AT_type
.quad .LFB4 # DW_AT_low_pc
.quad .LFE4-.LFB4 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.uleb128 0x8 # (DIE (0xf7) DW_TAG_variable)
.long .LASF6 # DW_AT_name: "answer"
.byte 0x1 # DW_AT_decl_file (tailcall-only.c)
.byte 0x2f # DW_AT_decl_line
.long 0x46 # DW_AT_type
.long .LLST0 # DW_AT_location
.uleb128 0x9 # (DIE (0x106) DW_TAG_GNU_call_site)
.quad .LVL3 # DW_AT_low_pc
.long 0xab # DW_AT_abstract_origin
.byte 0 # end of children of DIE 0xda
.byte 0 # end of children of DIE 0xb
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.uleb128 0x1 # (abbrev code)
.uleb128 0x11 # (TAG: DW_TAG_compile_unit)
.byte 0x1 # DW_children_yes
.uleb128 0x25 # (DW_AT_producer)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x13 # (DW_AT_language)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x1b # (DW_AT_comp_dir)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x55 # (DW_AT_ranges)
.uleb128 0x17 # (DW_FORM_sec_offset)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x10 # (DW_AT_stmt_list)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x2 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x7 # (DW_FORM_data8)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.byte 0
.byte 0
.uleb128 0x3 # (abbrev code)
.uleb128 0x24 # (TAG: DW_TAG_base_type)
.byte 0 # DW_children_no
.uleb128 0xb # (DW_AT_byte_size)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3e # (DW_AT_encoding)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.byte 0
.byte 0
.uleb128 0x4 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x7 # (DW_FORM_data8)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x5 # (abbrev code)
.uleb128 0x4109 # (TAG: DW_TAG_GNU_call_site)
.byte 0 # DW_children_no
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x2115 # (DW_AT_GNU_tail_call)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x6 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x7 # (DW_FORM_data8)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x7 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3f # (DW_AT_external)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x7 # (DW_FORM_data8)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.byte 0
.byte 0
.uleb128 0x8 # (abbrev code)
.uleb128 0x34 # (TAG: DW_TAG_variable)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x2 # (DW_AT_location)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x9 # (abbrev code)
.uleb128 0x4109 # (TAG: DW_TAG_GNU_call_site)
.byte 0 # DW_children_no
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.byte 0
.section .debug_loc,"",@progbits
.Ldebug_loc0:
.LLST0:
.quad .LVL3 # Location list begin address (*.LLST0)
.quad .LVL4 # Location list end address (*.LLST0)
.value 0x3 # Location expression size
.byte 0x70 # DW_OP_breg0
.sleb128 1
.byte 0x9f # DW_OP_stack_value
.quad .LVL4 # Location list begin address (*.LLST0)
.quad .LFE4 # Location list end address (*.LLST0)
.value 0x1 # Location expression size
.byte 0x50 # DW_OP_reg0
.quad 0 # Location list terminator begin (*.LLST0)
.quad 0 # Location list terminator end (*.LLST0)
.section .debug_aranges,"",@progbits
.long 0x3c # Length of Address Ranges Info
.value 0x2 # DWARF Version
.long .Ldebug_info0 # Offset of Compilation Unit Info
.byte 0x8 # Size of Address
.byte 0 # Size of Segment Descriptor
.value 0 # Pad to 16 byte boundary
.value 0
.quad .Ltext0 # Address
.quad .Letext0-.Ltext0 # Length
.quad .LFB4 # Address
.quad .LFE4-.LFB4 # Length
.quad 0
.quad 0
.section .debug_ranges,"",@progbits
.Ldebug_ranges0:
.quad .Ltext0 # Offset 0
.quad .Letext0
.quad .LFB4 # Offset 0x10
.quad .LFE4
.quad 0
.quad 0
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.LASF4:
.string "bar_1"
.LASF2:
.string "tailcall-only.c"
.LASF1:
.string "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -mtune=generic -march=x86-64 -g -O2"
.LASF6:
.string "answer"
.LASF5:
.string "main"
.LASF3:
.string ""
.LASF0:
.string "foo_1"
.ident "GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-9)"
.section .note.GNU-stack,"",@progbits