X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fframe.c;h=5c4217c6d05a1c8ff8d9c3f1e35518bc6e0a8705;hb=ed34ef5ed3b11141a622e3edfb0c47e790f1fea7;hp=df1d2189d9853d26eea568c901ca7e98b0a111e2;hpb=50fd528a13ff8a6131ead1b2635fa8a8cf828d80;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/frame.c b/gdb/frame.c index df1d218..5c4217c 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1,6 +1,6 @@ /* Cache and manage frames for GDB, the GNU debugger. - Copyright (C) 1986-2013 Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -23,8 +23,6 @@ #include "value.h" #include "inferior.h" /* for inferior_ptid */ #include "regcache.h" -#include "gdb_assert.h" -#include #include "user-regs.h" #include "gdb_obstack.h" #include "dummy-frame.h" @@ -38,7 +36,6 @@ #include "gdbcmd.h" #include "observer.h" #include "objfiles.h" -#include "exceptions.h" #include "gdbthread.h" #include "block.h" #include "inline-frame.h" @@ -46,8 +43,25 @@ #include "hashtab.h" #include "valprint.h" -static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame); +static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason); + +/* Status of some values cached in the frame_info object. */ + +enum cached_copy_status +{ + /* Value is unknown. */ + CC_UNKNOWN, + + /* We have a value. */ + CC_VALUE, + + /* Value was not saved. */ + CC_NOT_SAVED, + + /* Value is unavailable. */ + CC_UNAVAILABLE +}; /* We keep a cache of stack frames, each of which is a "struct frame_info". The innermost one gets allocated (in @@ -95,7 +109,7 @@ struct frame_info /* Cached copy of the previous frame's resume address. */ struct { - int p; + enum cached_copy_status status; CORE_ADDR value; } prev_pc; @@ -128,6 +142,10 @@ struct frame_info /* The reason why we could not set PREV, or UNWIND_NO_REASON if we could. Only valid when PREV_P is set. */ enum unwind_stop_reason stop_reason; + + /* A frame specific string describing the STOP_REASON in more detail. + Only valid when PREV_P is set, but even then may still be NULL. */ + const char *stop_string; }; /* A frame stash used to speed up frame lookups. Create a hash table @@ -148,10 +166,11 @@ frame_addr_hash (const void *ap) const struct frame_id f_id = frame->this_id.value; hashval_t hash = 0; - gdb_assert (f_id.stack_addr_p || f_id.code_addr_p + gdb_assert (f_id.stack_status != FID_STACK_INVALID + || f_id.code_addr_p || f_id.special_addr_p); - if (f_id.stack_addr_p) + if (f_id.stack_status == FID_STACK_VALID) hash = iterative_hash (&f_id.stack_addr, sizeof (f_id.stack_addr), hash); if (f_id.code_addr_p) @@ -299,13 +318,23 @@ void fprint_frame_id (struct ui_file *file, struct frame_id id) { fprintf_unfiltered (file, "{"); - fprint_field (file, "stack", id.stack_addr_p, id.stack_addr); + + if (id.stack_status == FID_STACK_INVALID) + fprintf_unfiltered (file, "!stack"); + else if (id.stack_status == FID_STACK_UNAVAILABLE) + fprintf_unfiltered (file, "stack="); + else + fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr)); fprintf_unfiltered (file, ","); + fprint_field (file, "code", id.code_addr_p, id.code_addr); fprintf_unfiltered (file, ","); + fprint_field (file, "special", id.special_addr_p, id.special_addr); + if (id.artificial_depth) fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth); + fprintf_unfiltered (file, "}"); } @@ -365,10 +394,15 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) fprintf_unfiltered (file, ""); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "pc="); - if (fi->next != NULL && fi->next->prev_pc.p) - fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value)); - else + if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN) fprintf_unfiltered (file, ""); + else if (fi->next->prev_pc.status == CC_VALUE) + fprintf_unfiltered (file, "%s", + hex_string (fi->next->prev_pc.value)); + else if (fi->next->prev_pc.status == CC_NOT_SAVED) + val_print_not_saved (file); + else if (fi->next->prev_pc.status == CC_UNAVAILABLE) + val_print_unavailable (file); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "id="); if (fi->this_id.p) @@ -391,9 +425,15 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) static struct frame_info * skip_artificial_frames (struct frame_info *frame) { + /* Note we use get_prev_frame_always, and not get_prev_frame. The + latter will truncate the frame chain, leading to this function + unintentionally returning a null_frame_id (e.g., when the user + sets a backtrace limit). This is safe, because as these frames + are made up by GDB, there must be a real frame in the chain + below. */ while (get_frame_type (frame) == INLINE_FRAME || get_frame_type (frame) == TAILCALL_FRAME) - frame = get_prev_frame (frame); + frame = get_prev_frame_always (frame); return frame; } @@ -450,13 +490,13 @@ frame_unwind_caller_id (struct frame_info *next_frame) { struct frame_info *this_frame; - /* Use get_prev_frame_1, and not get_prev_frame. The latter will truncate - the frame chain, leading to this function unintentionally - returning a null_frame_id (e.g., when a caller requests the frame - ID of "main()"s caller. */ + /* Use get_prev_frame_always, and not get_prev_frame. The latter + will truncate the frame chain, leading to this function + unintentionally returning a null_frame_id (e.g., when a caller + requests the frame ID of "main()"s caller. */ next_frame = skip_artificial_frames (next_frame); - this_frame = get_prev_frame_1 (next_frame); + this_frame = get_prev_frame_always (next_frame); if (this_frame) return get_frame_id (skip_artificial_frames (this_frame)); else @@ -464,7 +504,7 @@ frame_unwind_caller_id (struct frame_info *next_frame) } const struct frame_id null_frame_id; /* All zeros. */ -const struct frame_id outer_frame_id = { 0, 0, 0, 0, 0, 1, 0 }; +const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_INVALID, 0, 1, 0 }; struct frame_id frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr, @@ -473,7 +513,36 @@ frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr, struct frame_id id = null_frame_id; id.stack_addr = stack_addr; - id.stack_addr_p = 1; + id.stack_status = FID_STACK_VALID; + id.code_addr = code_addr; + id.code_addr_p = 1; + id.special_addr = special_addr; + id.special_addr_p = 1; + return id; +} + +/* See frame.h. */ + +struct frame_id +frame_id_build_unavailable_stack (CORE_ADDR code_addr) +{ + struct frame_id id = null_frame_id; + + id.stack_status = FID_STACK_UNAVAILABLE; + id.code_addr = code_addr; + id.code_addr_p = 1; + return id; +} + +/* See frame.h. */ + +struct frame_id +frame_id_build_unavailable_stack_special (CORE_ADDR code_addr, + CORE_ADDR special_addr) +{ + struct frame_id id = null_frame_id; + + id.stack_status = FID_STACK_UNAVAILABLE; id.code_addr = code_addr; id.code_addr_p = 1; id.special_addr = special_addr; @@ -487,7 +556,7 @@ frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr) struct frame_id id = null_frame_id; id.stack_addr = stack_addr; - id.stack_addr_p = 1; + id.stack_status = FID_STACK_VALID; id.code_addr = code_addr; id.code_addr_p = 1; return id; @@ -499,7 +568,7 @@ frame_id_build_wild (CORE_ADDR stack_addr) struct frame_id id = null_frame_id; id.stack_addr = stack_addr; - id.stack_addr_p = 1; + id.stack_status = FID_STACK_VALID; return id; } @@ -509,7 +578,7 @@ frame_id_p (struct frame_id l) int p; /* The frame is valid iff it has a valid stack address. */ - p = l.stack_addr_p; + p = l.stack_status != FID_STACK_INVALID; /* outer_frame_id is also valid. */ if (!p && memcmp (&l, &outer_frame_id, sizeof (l)) == 0) p = 1; @@ -536,19 +605,20 @@ frame_id_eq (struct frame_id l, struct frame_id r) { int eq; - if (!l.stack_addr_p && l.special_addr_p - && !r.stack_addr_p && r.special_addr_p) + if (l.stack_status == FID_STACK_INVALID && l.special_addr_p + && r.stack_status == FID_STACK_INVALID && r.special_addr_p) /* The outermost frame marker is equal to itself. This is the dodgy thing about outer_frame_id, since between execution steps we might step into another function - from which we can't unwind either. More thought required to get rid of outer_frame_id. */ eq = 1; - else if (!l.stack_addr_p || !r.stack_addr_p) + else if (l.stack_status == FID_STACK_INVALID + || l.stack_status == FID_STACK_INVALID) /* Like a NaN, if either ID is invalid, the result is false. Note that a frame ID is invalid iff it is the null frame ID. */ eq = 0; - else if (l.stack_addr != r.stack_addr) + else if (l.stack_status != r.stack_status || l.stack_addr != r.stack_addr) /* If .stack addresses are different, the frames are different. */ eq = 0; else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr) @@ -615,8 +685,9 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r) { int inner; - if (!l.stack_addr_p || !r.stack_addr_p) - /* Like NaN, any operation involving an invalid ID always fails. */ + if (l.stack_status != FID_STACK_VALID || r.stack_status != FID_STACK_VALID) + /* Like NaN, any operation involving an invalid ID always fails. + Likewise if either ID has an unavailable stack address. */ inner = 0; else if (l.artificial_depth > r.artificial_depth && l.stack_addr == r.stack_addr @@ -625,7 +696,7 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r) && l.special_addr == r.special_addr) { /* Same function, different inlined functions. */ - struct block *lb, *rb; + const struct block *lb, *rb; gdb_assert (l.code_addr_p && r.code_addr_p); @@ -706,10 +777,10 @@ frame_find_by_id (struct frame_id id) return NULL; } -static int -frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) +static CORE_ADDR +frame_unwind_pc (struct frame_info *this_frame) { - if (!this_frame->prev_pc.p) + if (this_frame->prev_pc.status == CC_UNKNOWN) { if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame))) { @@ -739,24 +810,35 @@ frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); } - if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) - { - this_frame->prev_pc.p = -1; - - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d)" - " -> }\n", - this_frame->level); - } - else if (ex.reason < 0) + if (ex.reason < 0) { - throw_exception (ex); + if (ex.error == NOT_AVAILABLE_ERROR) + { + this_frame->prev_pc.status = CC_UNAVAILABLE; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> }\n", + this_frame->level); + } + else if (ex.error == OPTIMIZED_OUT_ERROR) + { + this_frame->prev_pc.status = CC_NOT_SAVED; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> }\n", + this_frame->level); + } + else + throw_exception (ex); } else { this_frame->prev_pc.value = pc; - this_frame->prev_pc.p = 1; + this_frame->prev_pc.status = CC_VALUE; if (frame_debug) fprintf_unfiltered (gdb_stdlog, "{ frame_unwind_pc (this_frame=%d) " @@ -768,27 +850,17 @@ frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) else internal_error (__FILE__, __LINE__, _("No unwind_pc method")); } - if (this_frame->prev_pc.p < 0) - { - *pc = -1; - return 0; - } - else - { - *pc = this_frame->prev_pc.value; - return 1; - } -} -static CORE_ADDR -frame_unwind_pc (struct frame_info *this_frame) -{ - CORE_ADDR pc; - - if (!frame_unwind_pc_if_available (this_frame, &pc)) + if (this_frame->prev_pc.status == CC_VALUE) + return this_frame->prev_pc.value; + else if (this_frame->prev_pc.status == CC_UNAVAILABLE) throw_error (NOT_AVAILABLE_ERROR, _("PC not available")); + else if (this_frame->prev_pc.status == CC_NOT_SAVED) + throw_error (OPTIMIZED_OUT_ERROR, _("PC not saved")); else - return pc; + internal_error (__FILE__, __LINE__, + "unexpected prev_pc status: %d", + (int) this_frame->prev_pc.status); } CORE_ADDR @@ -798,13 +870,6 @@ frame_unwind_caller_pc (struct frame_info *this_frame) } int -frame_unwind_caller_pc_if_available (struct frame_info *this_frame, - CORE_ADDR *pc) -{ - return frame_unwind_pc_if_available (skip_artificial_frames (this_frame), pc); -} - -int get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { struct frame_info *next_frame = this_frame->next; @@ -892,12 +957,12 @@ frame_pop (struct frame_info *this_frame) { /* Popping a dummy frame involves restoring more than just registers. dummy_frame_pop does all the work. */ - dummy_frame_pop (get_frame_id (this_frame)); + dummy_frame_pop (get_frame_id (this_frame), inferior_ptid); return; } /* Ensure that we have a frame to pop to. */ - prev_frame = get_prev_frame_1 (this_frame); + prev_frame = get_prev_frame_always (this_frame); if (!prev_frame) error (_("Cannot pop the initial frame.")); @@ -1006,7 +1071,8 @@ frame_unwind_register (struct frame_info *frame, int regnum, gdb_byte *buf) &lval, &addr, &realnum, buf); if (optimized) - error (_("Register %d was not saved"), regnum); + throw_error (OPTIMIZED_OUT_ERROR, + _("Register %d was not saved"), regnum); if (unavailable) throw_error (NOT_AVAILABLE_ERROR, _("Register %d is not available"), regnum); @@ -1570,7 +1636,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) very likely to read this, and the corresponding unwinder is entitled to rely that the PC doesn't magically change. */ fi->next->prev_pc.value = pc; - fi->next->prev_pc.p = 1; + fi->next->prev_pc.status = CC_VALUE; /* We currently assume that frame chain's can't cross spaces. */ fi->pspace = fi->next->pspace; @@ -1673,6 +1739,22 @@ frame_register_unwind_location (struct frame_info *this_frame, int regnum, } } +/* Called during frame unwinding to remove a previous frame pointer from a + frame passed in ARG. */ + +static void +remove_prev_frame (void *arg) +{ + struct frame_info *this_frame, *prev_frame; + + this_frame = (struct frame_info *) arg; + prev_frame = this_frame->prev; + gdb_assert (prev_frame != NULL); + + prev_frame->next = NULL; + this_frame->prev = NULL; +} + /* Get the previous raw frame, and check that it is not identical to same other frame frame already in the chain. If it is, there is most likely a stack cycle, so we discard it, and mark THIS_FRAME as @@ -1685,40 +1767,45 @@ static struct frame_info * get_prev_frame_if_no_cycle (struct frame_info *this_frame) { struct frame_info *prev_frame; + struct cleanup *prev_frame_cleanup; prev_frame = get_prev_frame_raw (this_frame); if (prev_frame == NULL) return NULL; - compute_frame_id (prev_frame); - if (frame_stash_add (prev_frame)) - return prev_frame; + /* The cleanup will remove the previous frame that get_prev_frame_raw + linked onto THIS_FRAME. */ + prev_frame_cleanup = make_cleanup (remove_prev_frame, this_frame); - /* Another frame with the same id was already in the stash. We just - detected a cycle. */ - if (frame_debug) + compute_frame_id (prev_frame); + if (!frame_stash_add (prev_frame)) { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, " // this frame has same ID }\n"); + /* Another frame with the same id was already in the stash. We just + detected a cycle. */ + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // this frame has same ID }\n"); + } + this_frame->stop_reason = UNWIND_SAME_ID; + /* Unlink. */ + prev_frame->next = NULL; + this_frame->prev = NULL; + prev_frame = NULL; } - this_frame->stop_reason = UNWIND_SAME_ID; - /* Unlink. */ - prev_frame->next = NULL; - this_frame->prev = NULL; - return NULL; -} -/* Return a "struct frame_info" corresponding to the frame that called - THIS_FRAME. Returns NULL if there is no such frame. + discard_cleanups (prev_frame_cleanup); + return prev_frame; +} - Unlike get_prev_frame, this function always tries to unwind the - frame. */ +/* Helper function for get_prev_frame_always, this is called inside a + TRY_CATCH block. Return the frame that called THIS_FRAME or NULL if + there is no such frame. This may throw an exception. */ static struct frame_info * -get_prev_frame_1 (struct frame_info *this_frame) +get_prev_frame_always_1 (struct frame_info *this_frame) { - struct frame_id this_id; struct gdbarch *gdbarch; gdb_assert (this_frame != NULL); @@ -1726,7 +1813,7 @@ get_prev_frame_1 (struct frame_info *this_frame) if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_1 (this_frame="); + fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_always (this_frame="); if (this_frame != NULL) fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level); else @@ -1771,7 +1858,18 @@ get_prev_frame_1 (struct frame_info *this_frame) &this_frame->prologue_cache); if (this_frame->stop_reason != UNWIND_NO_REASON) - return NULL; + { + if (frame_debug) + { + enum unwind_stop_reason reason = this_frame->stop_reason; + + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // %s }\n", + frame_stop_reason_symbol_string (reason)); + } + return NULL; + } /* Check that this frame's ID isn't inner to (younger, below, next) the next frame. This happens when a frame unwind goes backwards. @@ -1779,7 +1877,8 @@ get_prev_frame_1 (struct frame_info *this_frame) See the comment at frame_id_inner for details. */ if (get_frame_type (this_frame) == NORMAL_FRAME && this_frame->next->unwind->type == NORMAL_FRAME - && frame_id_inner (get_frame_arch (this_frame->next), this_id, + && frame_id_inner (get_frame_arch (this_frame->next), + get_frame_id (this_frame), get_frame_id (this_frame->next))) { CORE_ADDR this_pc_in_block; @@ -1790,7 +1889,7 @@ get_prev_frame_1 (struct frame_info *this_frame) this_pc_in_block = get_frame_address_in_block (this_frame); morestack_msym = lookup_minimal_symbol_by_pc (this_pc_in_block).minsym; if (morestack_msym) - morestack_name = SYMBOL_LINKAGE_NAME (morestack_msym); + morestack_name = MSYMBOL_LINKAGE_NAME (morestack_msym); if (!morestack_name || strcmp (morestack_name, "__morestack") != 0) { if (frame_debug) @@ -1855,6 +1954,50 @@ get_prev_frame_1 (struct frame_info *this_frame) return get_prev_frame_if_no_cycle (this_frame); } +/* Return a "struct frame_info" corresponding to the frame that called + THIS_FRAME. Returns NULL if there is no such frame. + + Unlike get_prev_frame, this function always tries to unwind the + frame. */ + +struct frame_info * +get_prev_frame_always (struct frame_info *this_frame) +{ + volatile struct gdb_exception ex; + struct frame_info *prev_frame = NULL; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + prev_frame = get_prev_frame_always_1 (this_frame); + } + if (ex.reason < 0) + { + if (ex.error == MEMORY_ERROR) + { + this_frame->stop_reason = UNWIND_MEMORY_ERROR; + if (ex.message != NULL) + { + char *stop_string; + size_t size; + + /* The error needs to live as long as the frame does. + Allocate using stack local STOP_STRING then assign the + pointer to the frame, this allows the STOP_STRING on the + frame to be of type 'const char *'. */ + size = strlen (ex.message) + 1; + stop_string = frame_obstack_zalloc (size); + memcpy (stop_string, ex.message, size); + this_frame->stop_string = stop_string; + } + prev_frame = NULL; + } + else + throw_exception (ex); + } + + return prev_frame; +} + /* Construct a new "struct frame_info" and link it previous to this_frame. */ @@ -1936,18 +2079,18 @@ frame_debug_got_null_frame (struct frame_info *this_frame, static int inside_main_func (struct frame_info *this_frame) { - struct minimal_symbol *msymbol; + struct bound_minimal_symbol msymbol; CORE_ADDR maddr; if (symfile_objfile == 0) return 0; msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile); - if (msymbol == NULL) + if (msymbol.minsym == NULL) return 0; /* Make certain that the code, and not descriptor, address is returned. */ maddr = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame), - SYMBOL_VALUE_ADDRESS (msymbol), + BMSYMBOL_VALUE_ADDRESS (msymbol), ¤t_target); return maddr == get_frame_func (this_frame); } @@ -2066,7 +2209,7 @@ get_prev_frame (struct frame_info *this_frame) return NULL; } - return get_prev_frame_1 (this_frame); + return get_prev_frame_always (this_frame); } CORE_ADDR @@ -2451,20 +2594,17 @@ get_frame_sp (struct frame_info *this_frame) enum unwind_stop_reason get_frame_unwind_stop_reason (struct frame_info *frame) { - /* If we haven't tried to unwind past this point yet, then assume - that unwinding would succeed. */ - if (frame->prev_p == 0) - return UNWIND_NO_REASON; + /* Fill-in STOP_REASON. */ + get_prev_frame_always (frame); + gdb_assert (frame->prev_p); - /* Otherwise, we set a reason when we succeeded (or failed) to - unwind. */ return frame->stop_reason; } /* Return a string explaining REASON. */ const char * -frame_stop_reason_string (enum unwind_stop_reason reason) +unwind_stop_reason_to_string (enum unwind_stop_reason reason) { switch (reason) { @@ -2479,6 +2619,39 @@ frame_stop_reason_string (enum unwind_stop_reason reason) } } +const char * +frame_stop_reason_string (struct frame_info *fi) +{ + gdb_assert (fi->prev_p); + gdb_assert (fi->prev == NULL); + + /* Return the specific string if we have one. */ + if (fi->stop_string != NULL) + return fi->stop_string; + + /* Return the generic string if we have nothing better. */ + return unwind_stop_reason_to_string (fi->stop_reason); +} + +/* Return the enum symbol name of REASON as a string, to use in debug + output. */ + +static const char * +frame_stop_reason_symbol_string (enum unwind_stop_reason reason) +{ + switch (reason) + { +#define SET(name, description) \ + case name: return #name; +#include "unwind_stop_reasons.def" +#undef SET + + default: + internal_error (__FILE__, __LINE__, + "Invalid frame stop reason"); + } +} + /* Clean up after a failed (wrong unwinder) attempt to unwind past FRAME. */ @@ -2531,7 +2704,8 @@ static struct cmd_list_element *show_backtrace_cmdlist; static void set_backtrace_cmd (char *args, int from_tty) { - help_list (set_backtrace_cmdlist, "set backtrace ", -1, gdb_stdout); + help_list (set_backtrace_cmdlist, "set backtrace ", all_commands, + gdb_stdout); } static void