1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583 |
- /* Print and select stack frames for GDB, the GNU debugger.
- Copyright (C) 1986-2022 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 "value.h"
- #include "symtab.h"
- #include "gdbtypes.h"
- #include "expression.h"
- #include "language.h"
- #include "frame.h"
- #include "gdbcmd.h"
- #include "gdbcore.h"
- #include "target.h"
- #include "source.h"
- #include "breakpoint.h"
- #include "demangle.h"
- #include "inferior.h"
- #include "annotate.h"
- #include "ui-out.h"
- #include "block.h"
- #include "stack.h"
- #include "dictionary.h"
- #include "reggroups.h"
- #include "regcache.h"
- #include "solib.h"
- #include "valprint.h"
- #include "gdbthread.h"
- #include "cp-support.h"
- #include "disasm.h"
- #include "inline-frame.h"
- #include "linespec.h"
- #include "cli/cli-utils.h"
- #include "objfiles.h"
- #include "annotate.h"
- #include "symfile.h"
- #include "extension.h"
- #include "observable.h"
- #include "gdbsupport/def-vector.h"
- #include "cli/cli-option.h"
- #include "cli/cli-style.h"
- #include "gdbsupport/buildargv.h"
- /* The possible choices of "set print frame-arguments", and the value
- of this setting. */
- const char print_frame_arguments_all[] = "all";
- const char print_frame_arguments_scalars[] = "scalars";
- const char print_frame_arguments_none[] = "none";
- const char print_frame_arguments_presence[] = "presence";
- static const char *const print_frame_arguments_choices[] =
- {
- print_frame_arguments_all,
- print_frame_arguments_scalars,
- print_frame_arguments_none,
- print_frame_arguments_presence,
- NULL
- };
- /* The possible choices of "set print frame-info", and the value
- of this setting. */
- const char print_frame_info_auto[] = "auto";
- const char print_frame_info_source_line[] = "source-line";
- const char print_frame_info_location[] = "location";
- const char print_frame_info_source_and_location[] = "source-and-location";
- const char print_frame_info_location_and_address[] = "location-and-address";
- const char print_frame_info_short_location[] = "short-location";
- static const char *const print_frame_info_choices[] =
- {
- print_frame_info_auto,
- print_frame_info_source_line,
- print_frame_info_location,
- print_frame_info_source_and_location,
- print_frame_info_location_and_address,
- print_frame_info_short_location,
- NULL
- };
- /* print_frame_info_print_what[i] maps a choice to the corresponding
- print_what enum. */
- static const gdb::optional<enum print_what> print_frame_info_print_what[] =
- {{}, /* Empty value for "auto". */
- SRC_LINE, LOCATION, SRC_AND_LOC, LOC_AND_ADDRESS, SHORT_LOCATION};
- /* The possible choices of "set print entry-values", and the value
- of this setting. */
- const char print_entry_values_no[] = "no";
- const char print_entry_values_only[] = "only";
- const char print_entry_values_preferred[] = "preferred";
- const char print_entry_values_if_needed[] = "if-needed";
- const char print_entry_values_both[] = "both";
- const char print_entry_values_compact[] = "compact";
- const char print_entry_values_default[] = "default";
- static const char *const print_entry_values_choices[] =
- {
- print_entry_values_no,
- print_entry_values_only,
- print_entry_values_preferred,
- print_entry_values_if_needed,
- print_entry_values_both,
- print_entry_values_compact,
- print_entry_values_default,
- NULL
- };
- /* See frame.h. */
- frame_print_options user_frame_print_options;
- /* Option definitions for some frame-related "set print ..."
- settings. */
- using boolean_option_def
- = gdb::option::boolean_option_def<frame_print_options>;
- using enum_option_def
- = gdb::option::enum_option_def<frame_print_options>;
- static const gdb::option::option_def frame_print_option_defs[] = {
- enum_option_def {
- "entry-values",
- print_entry_values_choices,
- [] (frame_print_options *opt) { return &opt->print_entry_values; },
- NULL, /* show_cmd_cb */
- N_("Set printing of function arguments at function entry."),
- N_("Show printing of function arguments at function entry."),
- N_("GDB can sometimes determine the values of function arguments at entry,\n\
- in addition to their current values. This option tells GDB whether\n\
- to print the current value, the value at entry (marked as val@entry),\n\
- or both. Note that one or both of these values may be <optimized out>."),
- },
- enum_option_def {
- "frame-arguments",
- print_frame_arguments_choices,
- [] (frame_print_options *opt) { return &opt->print_frame_arguments; },
- NULL, /* show_cmd_cb */
- N_("Set printing of non-scalar frame arguments."),
- N_("Show printing of non-scalar frame arguments."),
- NULL /* help_doc */
- },
- boolean_option_def {
- "raw-frame-arguments",
- [] (frame_print_options *opt) { return &opt->print_raw_frame_arguments; },
- NULL, /* show_cmd_cb */
- N_("Set whether to print frame arguments in raw form."),
- N_("Show whether to print frame arguments in raw form."),
- N_("If set, frame arguments are printed in raw form, bypassing any\n\
- pretty-printers for that value.")
- },
- enum_option_def {
- "frame-info",
- print_frame_info_choices,
- [] (frame_print_options *opt) { return &opt->print_frame_info; },
- NULL, /* show_cmd_cb */
- N_("Set printing of frame information."),
- N_("Show printing of frame information."),
- NULL /* help_doc */
- }
- };
- /* Options for the "backtrace" command. */
- struct backtrace_cmd_options
- {
- bool full = false;
- bool no_filters = false;
- bool hide = false;
- };
- using bt_flag_option_def
- = gdb::option::flag_option_def<backtrace_cmd_options>;
- static const gdb::option::option_def backtrace_command_option_defs[] = {
- bt_flag_option_def {
- "full",
- [] (backtrace_cmd_options *opt) { return &opt->full; },
- N_("Print values of local variables.")
- },
- bt_flag_option_def {
- "no-filters",
- [] (backtrace_cmd_options *opt) { return &opt->no_filters; },
- N_("Prohibit frame filters from executing on a backtrace."),
- },
- bt_flag_option_def {
- "hide",
- [] (backtrace_cmd_options *opt) { return &opt->hide; },
- N_("Causes Python frame filter elided frames to not be printed."),
- },
- };
- /* Prototypes for local functions. */
- static void print_frame_local_vars (struct frame_info *frame,
- bool quiet,
- const char *regexp, const char *t_regexp,
- int num_tabs, struct ui_file *stream);
- static void print_frame (const frame_print_options &opts,
- frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal);
- static struct frame_info *find_frame_for_function (const char *);
- static struct frame_info *find_frame_for_address (CORE_ADDR);
- /* Zero means do things normally; we are interacting directly with the
- user. One means print the full filename and linenumber when a
- frame is printed, and do so in a format emacs18/emacs19.22 can
- parse. Two means print similar annotations, but in many more
- cases and in a slightly different syntax. */
- int annotation_level = 0;
- /* Class used to manage tracking the last symtab we displayed. */
- class last_displayed_symtab_info_type
- {
- public:
- /* True if the cached information is valid. */
- bool is_valid () const
- { return m_valid; }
- /* Return the cached program_space. If the cache is invalid nullptr is
- returned. */
- struct program_space *pspace () const
- { return m_pspace; }
- /* Return the cached CORE_ADDR address. If the cache is invalid 0 is
- returned. */
- CORE_ADDR address () const
- { return m_address; }
- /* Return the cached symtab. If the cache is invalid nullptr is
- returned. */
- struct symtab *symtab () const
- { return m_symtab; }
- /* Return the cached line number. If the cache is invalid 0 is
- returned. */
- int line () const
- { return m_line; }
- /* Invalidate the cache, reset all the members to their default value. */
- void invalidate ()
- {
- m_valid = false;
- m_pspace = nullptr;
- m_address = 0;
- m_symtab = nullptr;
- m_line = 0;
- }
- /* Store a new set of values in the cache. */
- void set (struct program_space *pspace, CORE_ADDR address,
- struct symtab *symtab, int line)
- {
- gdb_assert (pspace != nullptr);
- m_valid = true;
- m_pspace = pspace;
- m_address = address;
- m_symtab = symtab;
- m_line = line;
- }
- private:
- /* True when the cache is valid. */
- bool m_valid = false;
- /* The last program space displayed. */
- struct program_space *m_pspace = nullptr;
- /* The last address displayed. */
- CORE_ADDR m_address = 0;
- /* The last symtab displayed. */
- struct symtab *m_symtab = nullptr;
- /* The last line number displayed. */
- int m_line = 0;
- };
- /* An actual instance of the cache, holds information about the last symtab
- displayed. */
- static last_displayed_symtab_info_type last_displayed_symtab_info;
- /* See stack.h. */
- bool
- frame_show_address (struct frame_info *frame,
- struct symtab_and_line sal)
- {
- /* If there is a line number, but no PC, then there is no location
- information associated with this sal. The only way that should
- happen is for the call sites of inlined functions (SAL comes from
- find_frame_sal). Otherwise, we would have some PC range if the
- SAL came from a line table. */
- if (sal.line != 0 && sal.pc == 0 && sal.end == 0)
- {
- if (get_next_frame (frame) == NULL)
- gdb_assert (inline_skipped_frames (inferior_thread ()) > 0);
- else
- gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME);
- return false;
- }
- return get_frame_pc (frame) != sal.pc || !sal.is_stmt;
- }
- /* See frame.h. */
- void
- print_stack_frame_to_uiout (struct ui_out *uiout, struct frame_info *frame,
- int print_level, enum print_what print_what,
- int set_current_sal)
- {
- scoped_restore save_uiout = make_scoped_restore (¤t_uiout, uiout);
- print_stack_frame (frame, print_level, print_what, set_current_sal);
- }
- /* Show or print a stack frame FRAME briefly. The output is formatted
- according to PRINT_LEVEL and PRINT_WHAT printing the frame's
- relative level, function name, argument list, and file name and
- line number. If the frame's PC is not at the beginning of the
- source line, the actual PC is printed at the beginning. */
- void
- print_stack_frame (struct frame_info *frame, int print_level,
- enum print_what print_what,
- int set_current_sal)
- {
- /* For mi, always print location and address. */
- if (current_uiout->is_mi_like_p ())
- print_what = LOC_AND_ADDRESS;
- try
- {
- print_frame_info (user_frame_print_options,
- frame, print_level, print_what, 1 /* print_args */,
- set_current_sal);
- if (set_current_sal)
- set_current_sal_from_frame (frame);
- }
- catch (const gdb_exception_error &e)
- {
- }
- }
- /* Print nameless arguments of frame FRAME on STREAM, where START is
- the offset of the first nameless argument, and NUM is the number of
- nameless arguments to print. FIRST is nonzero if this is the first
- argument (not just the first nameless argument). */
- static void
- print_frame_nameless_args (struct frame_info *frame, long start, int num,
- int first, struct ui_file *stream)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int i;
- CORE_ADDR argsaddr;
- long arg_value;
- for (i = 0; i < num; i++)
- {
- QUIT;
- argsaddr = get_frame_args_address (frame);
- if (!argsaddr)
- return;
- arg_value = read_memory_integer (argsaddr + start,
- sizeof (int), byte_order);
- if (!first)
- gdb_printf (stream, ", ");
- gdb_printf (stream, "%ld", arg_value);
- first = 0;
- start += sizeof (int);
- }
- }
- /* Print single argument of inferior function. ARG must be already
- read in.
- Errors are printed as if they would be the parameter value. Use zeroed ARG
- iff it should not be printed according to user settings. */
- static void
- print_frame_arg (const frame_print_options &fp_opts,
- const struct frame_arg *arg)
- {
- struct ui_out *uiout = current_uiout;
- string_file stb;
- gdb_assert (!arg->val || !arg->error);
- gdb_assert (arg->entry_kind == print_entry_values_no
- || arg->entry_kind == print_entry_values_only
- || (!uiout->is_mi_like_p ()
- && arg->entry_kind == print_entry_values_compact));
- annotate_arg_emitter arg_emitter;
- ui_out_emit_tuple tuple_emitter (uiout, NULL);
- gdb_puts (arg->sym->print_name (), &stb);
- if (arg->entry_kind == print_entry_values_compact)
- {
- /* It is OK to provide invalid MI-like stream as with
- PRINT_ENTRY_VALUE_COMPACT we never use MI. */
- stb.puts ("=");
- gdb_puts (arg->sym->print_name (), &stb);
- }
- if (arg->entry_kind == print_entry_values_only
- || arg->entry_kind == print_entry_values_compact)
- stb.puts ("@entry");
- uiout->field_stream ("name", stb, variable_name_style.style ());
- annotate_arg_name_end ();
- uiout->text ("=");
- ui_file_style style;
- if (!arg->val && !arg->error)
- uiout->text ("...");
- else
- {
- if (arg->error)
- {
- stb.printf (_("<error reading variable: %s>"), arg->error.get ());
- style = metadata_style.style ();
- }
- else
- {
- try
- {
- const struct language_defn *language;
- struct value_print_options vp_opts;
- /* Avoid value_print because it will deref ref parameters. We
- just want to print their addresses. Print ??? for args whose
- address we do not know. We pass 2 as "recurse" to val_print
- because our standard indentation here is 4 spaces, and
- val_print indents 2 for each recurse. */
- annotate_arg_value (value_type (arg->val));
- /* Use the appropriate language to display our symbol, unless the
- user forced the language to a specific language. */
- if (language_mode == language_mode_auto)
- language = language_def (arg->sym->language ());
- else
- language = current_language;
- get_no_prettyformat_print_options (&vp_opts);
- vp_opts.deref_ref = 1;
- vp_opts.raw = fp_opts.print_raw_frame_arguments;
- /* True in "summary" mode, false otherwise. */
- vp_opts.summary
- = fp_opts.print_frame_arguments == print_frame_arguments_scalars;
- common_val_print_checked (arg->val, &stb, 2, &vp_opts, language);
- }
- catch (const gdb_exception_error &except)
- {
- stb.printf (_("<error reading variable: %s>"),
- except.what ());
- style = metadata_style.style ();
- }
- }
- }
- uiout->field_stream ("value", stb, style);
- }
- /* Read in inferior function local SYM at FRAME into ARGP. Caller is
- responsible for xfree of ARGP->ERROR. This function never throws an
- exception. */
- void
- read_frame_local (struct symbol *sym, struct frame_info *frame,
- struct frame_arg *argp)
- {
- argp->sym = sym;
- argp->val = NULL;
- argp->error = NULL;
- try
- {
- argp->val = read_var_value (sym, NULL, frame);
- }
- catch (const gdb_exception_error &except)
- {
- argp->error.reset (xstrdup (except.what ()));
- }
- }
- /* Read in inferior function parameter SYM at FRAME into ARGP. This
- function never throws an exception. */
- void
- read_frame_arg (const frame_print_options &fp_opts,
- symbol *sym, frame_info *frame,
- struct frame_arg *argp, struct frame_arg *entryargp)
- {
- struct value *val = NULL, *entryval = NULL;
- char *val_error = NULL, *entryval_error = NULL;
- int val_equal = 0;
- if (fp_opts.print_entry_values != print_entry_values_only
- && fp_opts.print_entry_values != print_entry_values_preferred)
- {
- try
- {
- val = read_var_value (sym, NULL, frame);
- }
- catch (const gdb_exception_error &except)
- {
- val_error = (char *) alloca (except.message->size () + 1);
- strcpy (val_error, except.what ());
- }
- }
- if (SYMBOL_COMPUTED_OPS (sym) != NULL
- && SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry != NULL
- && fp_opts.print_entry_values != print_entry_values_no
- && (fp_opts.print_entry_values != print_entry_values_if_needed
- || !val || value_optimized_out (val)))
- {
- try
- {
- const struct symbol_computed_ops *ops;
- ops = SYMBOL_COMPUTED_OPS (sym);
- entryval = ops->read_variable_at_entry (sym, frame);
- }
- catch (const gdb_exception_error &except)
- {
- if (except.error != NO_ENTRY_VALUE_ERROR)
- {
- entryval_error = (char *) alloca (except.message->size () + 1);
- strcpy (entryval_error, except.what ());
- }
- }
- if (entryval != NULL && value_optimized_out (entryval))
- entryval = NULL;
- if (fp_opts.print_entry_values == print_entry_values_compact
- || fp_opts.print_entry_values == print_entry_values_default)
- {
- /* For MI do not try to use print_entry_values_compact for ARGP. */
- if (val && entryval && !current_uiout->is_mi_like_p ())
- {
- struct type *type = value_type (val);
- if (value_lazy (val))
- value_fetch_lazy (val);
- if (value_lazy (entryval))
- value_fetch_lazy (entryval);
- if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
- {
- /* Initialize it just to avoid a GCC false warning. */
- struct value *val_deref = NULL, *entryval_deref;
- /* DW_AT_call_value does match with the current
- value. If it is a reference still try to verify if
- dereferenced DW_AT_call_data_value does not differ. */
- try
- {
- struct type *type_deref;
- val_deref = coerce_ref (val);
- if (value_lazy (val_deref))
- value_fetch_lazy (val_deref);
- type_deref = value_type (val_deref);
- entryval_deref = coerce_ref (entryval);
- if (value_lazy (entryval_deref))
- value_fetch_lazy (entryval_deref);
- /* If the reference addresses match but dereferenced
- content does not match print them. */
- if (val != val_deref
- && value_contents_eq (val_deref, 0,
- entryval_deref, 0,
- TYPE_LENGTH (type_deref)))
- val_equal = 1;
- }
- catch (const gdb_exception_error &except)
- {
- /* If the dereferenced content could not be
- fetched do not display anything. */
- if (except.error == NO_ENTRY_VALUE_ERROR)
- val_equal = 1;
- else if (except.message != NULL)
- {
- entryval_error
- = (char *) alloca (except.message->size () + 1);
- strcpy (entryval_error, except.what ());
- }
- }
- /* Value was not a reference; and its content matches. */
- if (val == val_deref)
- val_equal = 1;
- if (val_equal)
- entryval = NULL;
- }
- }
- /* Try to remove possibly duplicate error message for ENTRYARGP even
- in MI mode. */
- if (val_error && entryval_error
- && strcmp (val_error, entryval_error) == 0)
- {
- entryval_error = NULL;
- /* Do not se VAL_EQUAL as the same error message may be shown for
- the entry value even if no entry values are present in the
- inferior. */
- }
- }
- }
- if (entryval == NULL)
- {
- if (fp_opts.print_entry_values == print_entry_values_preferred)
- {
- gdb_assert (val == NULL);
- try
- {
- val = read_var_value (sym, NULL, frame);
- }
- catch (const gdb_exception_error &except)
- {
- val_error = (char *) alloca (except.message->size () + 1);
- strcpy (val_error, except.what ());
- }
- }
- if (fp_opts.print_entry_values == print_entry_values_only
- || fp_opts.print_entry_values == print_entry_values_both
- || (fp_opts.print_entry_values == print_entry_values_preferred
- && (!val || value_optimized_out (val))))
- {
- entryval = allocate_optimized_out_value (sym->type ());
- entryval_error = NULL;
- }
- }
- if ((fp_opts.print_entry_values == print_entry_values_compact
- || fp_opts.print_entry_values == print_entry_values_if_needed
- || fp_opts.print_entry_values == print_entry_values_preferred)
- && (!val || value_optimized_out (val)) && entryval != NULL)
- {
- val = NULL;
- val_error = NULL;
- }
- argp->sym = sym;
- argp->val = val;
- argp->error.reset (val_error ? xstrdup (val_error) : NULL);
- if (!val && !val_error)
- argp->entry_kind = print_entry_values_only;
- else if ((fp_opts.print_entry_values == print_entry_values_compact
- || fp_opts.print_entry_values == print_entry_values_default)
- && val_equal)
- {
- argp->entry_kind = print_entry_values_compact;
- gdb_assert (!current_uiout->is_mi_like_p ());
- }
- else
- argp->entry_kind = print_entry_values_no;
- entryargp->sym = sym;
- entryargp->val = entryval;
- entryargp->error.reset (entryval_error ? xstrdup (entryval_error) : NULL);
- if (!entryval && !entryval_error)
- entryargp->entry_kind = print_entry_values_no;
- else
- entryargp->entry_kind = print_entry_values_only;
- }
- /* Print the arguments of frame FRAME on STREAM, given the function
- FUNC running in that frame (as a symbol), where NUM is the number
- of arguments according to the stack frame (or -1 if the number of
- arguments is unknown). */
- /* Note that currently the "number of arguments according to the
- stack frame" is only known on VAX where i refers to the "number of
- ints of arguments according to the stack frame". */
- static void
- print_frame_args (const frame_print_options &fp_opts,
- struct symbol *func, struct frame_info *frame,
- int num, struct ui_file *stream)
- {
- struct ui_out *uiout = current_uiout;
- int first = 1;
- /* Offset of next stack argument beyond the one we have seen that is
- at the highest offset, or -1 if we haven't come to a stack
- argument yet. */
- long highest_offset = -1;
- /* Number of ints of arguments that we have printed so far. */
- int args_printed = 0;
- /* True if we should print arg names. If false, we only indicate
- the presence of arguments by printing ellipsis. */
- bool print_names
- = fp_opts.print_frame_arguments != print_frame_arguments_presence;
- /* True if we should print arguments, false otherwise. */
- bool print_args
- = (print_names
- && fp_opts.print_frame_arguments != print_frame_arguments_none);
- /* Temporarily change the selected frame to the given FRAME.
- This allows routines that rely on the selected frame instead
- of being given a frame as parameter to use the correct frame. */
- scoped_restore_selected_frame restore_selected_frame;
- select_frame (frame);
- if (func)
- {
- const struct block *b = SYMBOL_BLOCK_VALUE (func);
- struct block_iterator iter;
- struct symbol *sym;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- struct frame_arg arg, entryarg;
- QUIT;
- /* Keep track of the highest stack argument offset seen, and
- skip over any kinds of symbols we don't care about. */
- if (!sym->is_argument ())
- continue;
- if (!print_names)
- {
- uiout->text ("...");
- first = 0;
- break;
- }
- switch (sym->aclass ())
- {
- case LOC_ARG:
- case LOC_REF_ARG:
- {
- long current_offset = SYMBOL_VALUE (sym);
- int arg_size = TYPE_LENGTH (sym->type ());
- /* Compute address of next argument by adding the size of
- this argument and rounding to an int boundary. */
- current_offset =
- ((current_offset + arg_size + sizeof (int) - 1)
- & ~(sizeof (int) - 1));
- /* If this is the highest offset seen yet, set
- highest_offset. */
- if (highest_offset == -1
- || (current_offset > highest_offset))
- highest_offset = current_offset;
- /* Add the number of ints we're about to print to
- args_printed. */
- args_printed += (arg_size + sizeof (int) - 1) / sizeof (int);
- }
- /* We care about types of symbols, but don't need to
- keep track of stack offsets in them. */
- case LOC_REGISTER:
- case LOC_REGPARM_ADDR:
- case LOC_COMPUTED:
- case LOC_OPTIMIZED_OUT:
- default:
- break;
- }
- /* We have to look up the symbol because arguments can have
- two entries (one a parameter, one a local) and the one we
- want is the local, which lookup_symbol will find for us.
- This includes gcc1 (not gcc2) on SPARC when passing a
- small structure and gcc2 when the argument type is float
- and it is passed as a double and converted to float by
- the prologue (in the latter case the type of the LOC_ARG
- symbol is double and the type of the LOC_LOCAL symbol is
- float). */
- /* But if the parameter name is null, don't try it. Null
- parameter names occur on the RS/6000, for traceback
- tables. FIXME, should we even print them? */
- if (*sym->linkage_name ())
- {
- struct symbol *nsym;
- nsym = lookup_symbol_search_name (sym->search_name (),
- b, VAR_DOMAIN).symbol;
- gdb_assert (nsym != NULL);
- if (nsym->aclass () == LOC_REGISTER
- && !nsym->is_argument ())
- {
- /* There is a LOC_ARG/LOC_REGISTER pair. This means
- that it was passed on the stack and loaded into a
- register, or passed in a register and stored in a
- stack slot. GDB 3.x used the LOC_ARG; GDB
- 4.0-4.11 used the LOC_REGISTER.
- Reasons for using the LOC_ARG:
- (1) Because find_saved_registers may be slow for
- remote debugging.
- (2) Because registers are often re-used and stack
- slots rarely (never?) are. Therefore using
- the stack slot is much less likely to print
- garbage.
- Reasons why we might want to use the LOC_REGISTER:
- (1) So that the backtrace prints the same value
- as "print foo". I see no compelling reason
- why this needs to be the case; having the
- backtrace print the value which was passed
- in, and "print foo" print the value as
- modified within the called function, makes
- perfect sense to me.
- Additional note: It might be nice if "info args"
- displayed both values.
- One more note: There is a case with SPARC
- structure passing where we need to use the
- LOC_REGISTER, but this is dealt with by creating
- a single LOC_REGPARM in symbol reading. */
- /* Leave sym (the LOC_ARG) alone. */
- ;
- }
- else
- sym = nsym;
- }
- /* Print the current arg. */
- if (!first)
- uiout->text (", ");
- uiout->wrap_hint (4);
- if (!print_args)
- {
- arg.sym = sym;
- arg.entry_kind = print_entry_values_no;
- entryarg.sym = sym;
- entryarg.entry_kind = print_entry_values_no;
- }
- else
- read_frame_arg (fp_opts, sym, frame, &arg, &entryarg);
- if (arg.entry_kind != print_entry_values_only)
- print_frame_arg (fp_opts, &arg);
- if (entryarg.entry_kind != print_entry_values_no)
- {
- if (arg.entry_kind != print_entry_values_only)
- {
- uiout->text (", ");
- uiout->wrap_hint (4);
- }
- print_frame_arg (fp_opts, &entryarg);
- }
- first = 0;
- }
- }
- /* Don't print nameless args in situations where we don't know
- enough about the stack to find them. */
- if (num != -1)
- {
- long start;
- if (highest_offset == -1)
- start = gdbarch_frame_args_skip (get_frame_arch (frame));
- else
- start = highest_offset;
- if (!print_names && !first && num > 0)
- uiout->text ("...");
- else
- print_frame_nameless_args (frame, start, num - args_printed,
- first, stream);
- }
- }
- /* Set the current source and line to the location given by frame
- FRAME, if possible. When CENTER is true, adjust so the relevant
- line is in the center of the next 'list'. */
- void
- set_current_sal_from_frame (struct frame_info *frame)
- {
- symtab_and_line sal = find_frame_sal (frame);
- if (sal.symtab != NULL)
- set_current_source_symtab_and_line (sal);
- }
- /* If ON, GDB will display disassembly of the next source line when
- execution of the program being debugged stops.
- If AUTO (which is the default), or there's no line info to determine
- the source line of the next instruction, display disassembly of next
- instruction instead. */
- static enum auto_boolean disassemble_next_line;
- static void
- show_disassemble_next_line (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
- {
- gdb_printf (file,
- _("Debugger's willingness to use "
- "disassemble-next-line is %s.\n"),
- value);
- }
- /* Use TRY_CATCH to catch the exception from the gdb_disassembly
- because it will be broken by filter sometime. */
- static void
- do_gdb_disassembly (struct gdbarch *gdbarch,
- int how_many, CORE_ADDR low, CORE_ADDR high)
- {
- try
- {
- gdb_disassembly (gdbarch, current_uiout,
- DISASSEMBLY_RAW_INSN, how_many,
- low, high);
- }
- catch (const gdb_exception_error &exception)
- {
- /* If an exception was thrown while doing the disassembly, print
- the error message, to give the user a clue of what happened. */
- exception_print (gdb_stderr, exception);
- }
- }
- /* Converts the PRINT_FRAME_INFO choice to an optional enum print_what.
- Value not present indicates to the caller to use default values
- specific to the command being executed. */
- static gdb::optional<enum print_what>
- print_frame_info_to_print_what (const char *print_frame_info)
- {
- for (int i = 0; print_frame_info_choices[i] != NULL; i++)
- if (print_frame_info == print_frame_info_choices[i])
- return print_frame_info_print_what[i];
- internal_error (__FILE__, __LINE__,
- "Unexpected print frame-info value `%s'.",
- print_frame_info);
- }
- /* Print the PC from FRAME, plus any flags, to UIOUT. */
- static void
- print_pc (struct ui_out *uiout, struct gdbarch *gdbarch, frame_info *frame,
- CORE_ADDR pc)
- {
- uiout->field_core_addr ("addr", gdbarch, pc);
- std::string flags = gdbarch_get_pc_address_flags (gdbarch, frame, pc);
- if (!flags.empty ())
- {
- uiout->text (" [");
- uiout->field_string ("addr_flags", flags);
- uiout->text ("]");
- }
- }
- /* See stack.h. */
- void
- get_user_print_what_frame_info (gdb::optional<enum print_what> *what)
- {
- *what
- = print_frame_info_to_print_what
- (user_frame_print_options.print_frame_info);
- }
- /* Print information about frame FRAME. The output is format according
- to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS. For the meaning of
- PRINT_WHAT, see enum print_what comments in frame.h.
- Note that PRINT_WHAT is overridden if FP_OPTS.print_frame_info
- != print_frame_info_auto.
- Used in "where" output, and to emit breakpoint or step
- messages. */
- void
- print_frame_info (const frame_print_options &fp_opts,
- frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- int set_current_sal)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- int source_print;
- int location_print;
- struct ui_out *uiout = current_uiout;
- if (!current_uiout->is_mi_like_p ()
- && fp_opts.print_frame_info != print_frame_info_auto)
- {
- /* Use the specific frame information desired by the user. */
- print_what = *print_frame_info_to_print_what (fp_opts.print_frame_info);
- }
- if (get_frame_type (frame) == DUMMY_FRAME
- || get_frame_type (frame) == SIGTRAMP_FRAME
- || get_frame_type (frame) == ARCH_FRAME)
- {
- ui_out_emit_tuple tuple_emitter (uiout, "frame");
- annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- gdbarch, get_frame_pc (frame));
- /* Do this regardless of SOURCE because we don't have any source
- to list for this frame. */
- if (print_level)
- {
- uiout->text ("#");
- uiout->field_fmt_signed (2, ui_left, "level",
- frame_relative_level (frame));
- }
- if (uiout->is_mi_like_p ())
- {
- annotate_frame_address ();
- print_pc (uiout, gdbarch, frame, get_frame_pc (frame));
- annotate_frame_address_end ();
- }
- if (get_frame_type (frame) == DUMMY_FRAME)
- {
- annotate_function_call ();
- uiout->field_string ("func", "<function called from gdb>",
- metadata_style.style ());
- }
- else if (get_frame_type (frame) == SIGTRAMP_FRAME)
- {
- annotate_signal_handler_caller ();
- uiout->field_string ("func", "<signal handler called>",
- metadata_style.style ());
- }
- else if (get_frame_type (frame) == ARCH_FRAME)
- {
- uiout->field_string ("func", "<cross-architecture call>",
- metadata_style.style ());
- }
- uiout->text ("\n");
- annotate_frame_end ();
- /* If disassemble-next-line is set to auto or on output the next
- instruction. */
- if (disassemble_next_line == AUTO_BOOLEAN_AUTO
- || disassemble_next_line == AUTO_BOOLEAN_TRUE)
- do_gdb_disassembly (get_frame_arch (frame), 1,
- get_frame_pc (frame), get_frame_pc (frame) + 1);
- return;
- }
- /* If FRAME is not the innermost frame, that normally means that
- FRAME->pc points to *after* the call instruction, and we want to
- get the line containing the call, never the next line. But if
- the next frame is a SIGTRAMP_FRAME or a DUMMY_FRAME, then the
- next frame was not entered as the result of a call, and we want
- to get the line containing FRAME->pc. */
- symtab_and_line sal = find_frame_sal (frame);
- location_print = (print_what == LOCATION
- || print_what == SRC_AND_LOC
- || print_what == LOC_AND_ADDRESS
- || print_what == SHORT_LOCATION);
- if (location_print || !sal.symtab)
- print_frame (fp_opts, frame, print_level, print_what, print_args, sal);
- source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
- /* If disassemble-next-line is set to auto or on and doesn't have
- the line debug messages for $pc, output the next instruction. */
- if ((disassemble_next_line == AUTO_BOOLEAN_AUTO
- || disassemble_next_line == AUTO_BOOLEAN_TRUE)
- && source_print && !sal.symtab)
- do_gdb_disassembly (get_frame_arch (frame), 1,
- get_frame_pc (frame), get_frame_pc (frame) + 1);
- if (source_print && sal.symtab)
- {
- int mid_statement = ((print_what == SRC_LINE)
- && frame_show_address (frame, sal));
- if (annotation_level > 0
- && annotate_source_line (sal.symtab, sal.line, mid_statement,
- get_frame_pc (frame)))
- {
- /* The call to ANNOTATE_SOURCE_LINE already printed the
- annotation for this source line, so we avoid the two cases
- below and do not print the actual source line. The
- documentation for annotations makes it clear that the source
- line annotation is printed __instead__ of printing the source
- line, not as well as.
- However, if we fail to print the source line, which usually
- means either the source file is missing, or the requested
- line is out of range of the file, then we don't print the
- source annotation, and will pass through the "normal" print
- source line code below, the expectation is that this code
- will print an appropriate error. */
- }
- else if (deprecated_print_frame_info_listing_hook)
- deprecated_print_frame_info_listing_hook (sal.symtab, sal.line,
- sal.line + 1, 0);
- else
- {
- struct value_print_options opts;
- get_user_print_options (&opts);
- /* We used to do this earlier, but that is clearly
- wrong. This function is used by many different
- parts of gdb, including normal_stop in infrun.c,
- which uses this to print out the current PC
- when we stepi/nexti into the middle of a source
- line. Only the command line really wants this
- behavior. Other UIs probably would like the
- ability to decide for themselves if it is desired. */
- if (opts.addressprint && mid_statement)
- {
- print_pc (uiout, gdbarch, frame, get_frame_pc (frame));
- uiout->text ("\t");
- }
- print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
- }
- /* If disassemble-next-line is set to on and there is line debug
- messages, output assembly codes for next line. */
- if (disassemble_next_line == AUTO_BOOLEAN_TRUE)
- do_gdb_disassembly (get_frame_arch (frame), -1, sal.pc, sal.end);
- }
- if (set_current_sal)
- {
- CORE_ADDR pc;
- if (get_frame_pc_if_available (frame, &pc))
- last_displayed_symtab_info.set (sal.pspace, pc, sal.symtab, sal.line);
- else
- last_displayed_symtab_info.invalidate ();
- }
- annotate_frame_end ();
- gdb_flush (gdb_stdout);
- }
- /* See stack.h. */
- void
- clear_last_displayed_sal (void)
- {
- last_displayed_symtab_info.invalidate ();
- }
- /* See stack.h. */
- bool
- last_displayed_sal_is_valid (void)
- {
- return last_displayed_symtab_info.is_valid ();
- }
- /* See stack.h. */
- struct program_space *
- get_last_displayed_pspace (void)
- {
- return last_displayed_symtab_info.pspace ();
- }
- /* See stack.h. */
- CORE_ADDR
- get_last_displayed_addr (void)
- {
- return last_displayed_symtab_info.address ();
- }
- /* See stack.h. */
- struct symtab*
- get_last_displayed_symtab (void)
- {
- return last_displayed_symtab_info.symtab ();
- }
- /* See stack.h. */
- int
- get_last_displayed_line (void)
- {
- return last_displayed_symtab_info.line ();
- }
- /* See stack.h. */
- symtab_and_line
- get_last_displayed_sal ()
- {
- symtab_and_line sal;
- if (last_displayed_symtab_info.is_valid ())
- {
- sal.pspace = last_displayed_symtab_info.pspace ();
- sal.pc = last_displayed_symtab_info.address ();
- sal.symtab = last_displayed_symtab_info.symtab ();
- sal.line = last_displayed_symtab_info.line ();
- }
- return sal;
- }
- /* Attempt to obtain the name, FUNLANG and optionally FUNCP of the function
- corresponding to FRAME. */
- gdb::unique_xmalloc_ptr<char>
- find_frame_funname (struct frame_info *frame, enum language *funlang,
- struct symbol **funcp)
- {
- struct symbol *func;
- gdb::unique_xmalloc_ptr<char> funname;
- *funlang = language_unknown;
- if (funcp)
- *funcp = NULL;
- func = get_frame_function (frame);
- if (func)
- {
- const char *print_name = func->print_name ();
- *funlang = func->language ();
- if (funcp)
- *funcp = func;
- if (*funlang == language_cplus)
- {
- /* It seems appropriate to use print_name() here,
- to display the demangled name that we already have
- stored in the symbol table, but we stored a version
- with DMGL_PARAMS turned on, and here we don't want to
- display parameters. So remove the parameters. */
- funname = cp_remove_params (print_name);
- }
- /* If we didn't hit the C++ case above, set *funname
- here. */
- if (funname == NULL)
- funname.reset (xstrdup (print_name));
- }
- else
- {
- struct bound_minimal_symbol msymbol;
- CORE_ADDR pc;
- if (!get_frame_address_in_block_if_available (frame, &pc))
- return funname;
- msymbol = lookup_minimal_symbol_by_pc (pc);
- if (msymbol.minsym != NULL)
- {
- funname.reset (xstrdup (msymbol.minsym->print_name ()));
- *funlang = msymbol.minsym->language ();
- }
- }
- return funname;
- }
- static void
- print_frame (const frame_print_options &fp_opts,
- frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct ui_out *uiout = current_uiout;
- enum language funlang = language_unknown;
- struct value_print_options opts;
- struct symbol *func;
- CORE_ADDR pc = 0;
- int pc_p;
- pc_p = get_frame_pc_if_available (frame, &pc);
- gdb::unique_xmalloc_ptr<char> funname
- = find_frame_funname (frame, &funlang, &func);
- annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- gdbarch, pc);
- {
- ui_out_emit_tuple tuple_emitter (uiout, "frame");
- if (print_level)
- {
- uiout->text ("#");
- uiout->field_fmt_signed (2, ui_left, "level",
- frame_relative_level (frame));
- }
- get_user_print_options (&opts);
- if (opts.addressprint)
- if (!sal.symtab
- || frame_show_address (frame, sal)
- || print_what == LOC_AND_ADDRESS)
- {
- annotate_frame_address ();
- if (pc_p)
- print_pc (uiout, gdbarch, frame, pc);
- else
- uiout->field_string ("addr", "<unavailable>",
- metadata_style.style ());
- annotate_frame_address_end ();
- uiout->text (" in ");
- }
- annotate_frame_function_name ();
- string_file stb;
- gdb_puts (funname ? funname.get () : "??", &stb);
- uiout->field_stream ("func", stb, function_name_style.style ());
- uiout->wrap_hint (3);
- annotate_frame_args ();
- uiout->text (" (");
- if (print_args)
- {
- int numargs;
- if (gdbarch_frame_num_args_p (gdbarch))
- {
- numargs = gdbarch_frame_num_args (gdbarch, frame);
- gdb_assert (numargs >= 0);
- }
- else
- numargs = -1;
-
- {
- ui_out_emit_list list_emitter (uiout, "args");
- try
- {
- print_frame_args (fp_opts, func, frame, numargs, gdb_stdout);
- }
- catch (const gdb_exception_error &e)
- {
- }
- /* FIXME: ARGS must be a list. If one argument is a string it
- will have " that will not be properly escaped. */
- }
- QUIT;
- }
- uiout->text (")");
- if (print_what != SHORT_LOCATION && sal.symtab)
- {
- const char *filename_display;
-
- filename_display = symtab_to_filename_for_display (sal.symtab);
- annotate_frame_source_begin ();
- uiout->wrap_hint (3);
- uiout->text (" at ");
- annotate_frame_source_file ();
- uiout->field_string ("file", filename_display,
- file_name_style.style ());
- if (uiout->is_mi_like_p ())
- {
- const char *fullname = symtab_to_fullname (sal.symtab);
- uiout->field_string ("fullname", fullname);
- }
- annotate_frame_source_file_end ();
- uiout->text (":");
- annotate_frame_source_line ();
- uiout->field_signed ("line", sal.line);
- annotate_frame_source_end ();
- }
- if (print_what != SHORT_LOCATION
- && pc_p && (funname == NULL || sal.symtab == NULL))
- {
- char *lib = solib_name_from_address (get_frame_program_space (frame),
- get_frame_pc (frame));
- if (lib)
- {
- annotate_frame_where ();
- uiout->wrap_hint (2);
- uiout->text (" from ");
- uiout->field_string ("from", lib, file_name_style.style ());
- }
- }
- if (uiout->is_mi_like_p ())
- uiout->field_string ("arch",
- (gdbarch_bfd_arch_info (gdbarch))->printable_name);
- }
- uiout->text ("\n");
- }
- /* Completion function for "frame function", "info frame function", and
- "select-frame function" commands. */
- static void
- frame_selection_by_function_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char *word)
- {
- /* This is used to complete function names within a stack. It would be
- nice if we only offered functions that were actually in the stack.
- However, this would mean unwinding the stack to completion, which
- could take too long, or on a corrupted stack, possibly not end.
- Instead, we offer all symbol names as a safer choice. */
- collect_symbol_completion_matches (tracker,
- complete_symbol_mode::EXPRESSION,
- symbol_name_match_type::EXPRESSION,
- text, word);
- }
- /* Core of all the "info frame" sub-commands. Print information about a
- frame FI. If SELECTED_FRAME_P is true then the user didn't provide a
- frame specification, they just entered 'info frame'. If the user did
- provide a frame specification (for example 'info frame 0', 'info frame
- level 1') then SELECTED_FRAME_P will be false. */
- static void
- info_frame_command_core (struct frame_info *fi, bool selected_frame_p)
- {
- struct symbol *func;
- struct symtab *s;
- struct frame_info *calling_frame_info;
- int numregs;
- const char *funname = 0;
- enum language funlang = language_unknown;
- const char *pc_regname;
- struct gdbarch *gdbarch;
- CORE_ADDR frame_pc;
- int frame_pc_p;
- /* Initialize it to avoid "may be used uninitialized" warning. */
- CORE_ADDR caller_pc = 0;
- int caller_pc_p = 0;
- gdbarch = get_frame_arch (fi);
- /* Name of the value returned by get_frame_pc(). Per comments, "pc"
- is not a good name. */
- if (gdbarch_pc_regnum (gdbarch) >= 0)
- /* OK, this is weird. The gdbarch_pc_regnum hardware register's value can
- easily not match that of the internal value returned by
- get_frame_pc(). */
- pc_regname = gdbarch_register_name (gdbarch, gdbarch_pc_regnum (gdbarch));
- else
- /* But then, this is weird to. Even without gdbarch_pc_regnum, an
- architectures will often have a hardware register called "pc",
- and that register's value, again, can easily not match
- get_frame_pc(). */
- pc_regname = "pc";
- frame_pc_p = get_frame_pc_if_available (fi, &frame_pc);
- func = get_frame_function (fi);
- symtab_and_line sal = find_frame_sal (fi);
- s = sal.symtab;
- gdb::unique_xmalloc_ptr<char> func_only;
- if (func)
- {
- funname = func->print_name ();
- funlang = func->language ();
- if (funlang == language_cplus)
- {
- /* It seems appropriate to use print_name() here,
- to display the demangled name that we already have
- stored in the symbol table, but we stored a version
- with DMGL_PARAMS turned on, and here we don't want to
- display parameters. So remove the parameters. */
- func_only = cp_remove_params (funname);
- if (func_only)
- funname = func_only.get ();
- }
- }
- else if (frame_pc_p)
- {
- struct bound_minimal_symbol msymbol;
- msymbol = lookup_minimal_symbol_by_pc (frame_pc);
- if (msymbol.minsym != NULL)
- {
- funname = msymbol.minsym->print_name ();
- funlang = msymbol.minsym->language ();
- }
- }
- calling_frame_info = get_prev_frame (fi);
- if (selected_frame_p && frame_relative_level (fi) >= 0)
- {
- gdb_printf (_("Stack level %d, frame at "),
- frame_relative_level (fi));
- }
- else
- {
- gdb_printf (_("Stack frame at "));
- }
- gdb_puts (paddress (gdbarch, get_frame_base (fi)));
- gdb_printf (":\n");
- gdb_printf (" %s = ", pc_regname);
- if (frame_pc_p)
- gdb_puts (paddress (gdbarch, get_frame_pc (fi)));
- else
- fputs_styled ("<unavailable>", metadata_style.style (), gdb_stdout);
- gdb_stdout->wrap_here (3);
- if (funname)
- {
- gdb_printf (" in ");
- gdb_puts (funname);
- }
- gdb_stdout->wrap_here (3);
- if (sal.symtab)
- gdb_printf
- (" (%ps:%d)",
- styled_string (file_name_style.style (),
- symtab_to_filename_for_display (sal.symtab)),
- sal.line);
- gdb_puts ("; ");
- gdb_stdout->wrap_here (4);
- gdb_printf ("saved %s = ", pc_regname);
- if (!frame_id_p (frame_unwind_caller_id (fi)))
- val_print_not_saved (gdb_stdout);
- else
- {
- try
- {
- caller_pc = frame_unwind_caller_pc (fi);
- caller_pc_p = 1;
- }
- catch (const gdb_exception_error &ex)
- {
- switch (ex.error)
- {
- case NOT_AVAILABLE_ERROR:
- val_print_unavailable (gdb_stdout);
- break;
- case OPTIMIZED_OUT_ERROR:
- val_print_not_saved (gdb_stdout);
- break;
- default:
- fprintf_styled (gdb_stdout, metadata_style.style (),
- _("<error: %s>"),
- ex.what ());
- break;
- }
- }
- }
- if (caller_pc_p)
- gdb_puts (paddress (gdbarch, caller_pc));
- gdb_printf ("\n");
- if (calling_frame_info == NULL)
- {
- enum unwind_stop_reason reason;
- reason = get_frame_unwind_stop_reason (fi);
- if (reason != UNWIND_NO_REASON)
- gdb_printf (_(" Outermost frame: %s\n"),
- frame_stop_reason_string (fi));
- }
- else if (get_frame_type (fi) == TAILCALL_FRAME)
- gdb_puts (" tail call frame");
- else if (get_frame_type (fi) == INLINE_FRAME)
- gdb_printf (" inlined into frame %d",
- frame_relative_level (get_prev_frame (fi)));
- else
- {
- gdb_printf (" called by frame at ");
- gdb_puts (paddress (gdbarch, get_frame_base (calling_frame_info)));
- }
- if (get_next_frame (fi) && calling_frame_info)
- gdb_puts (",");
- gdb_stdout->wrap_here (3);
- if (get_next_frame (fi))
- {
- gdb_printf (" caller of frame at ");
- gdb_puts (paddress (gdbarch, get_frame_base (get_next_frame (fi))));
- }
- if (get_next_frame (fi) || calling_frame_info)
- gdb_puts ("\n");
- if (s)
- gdb_printf (" source language %s.\n",
- language_str (s->language ()));
- {
- /* Address of the argument list for this frame, or 0. */
- CORE_ADDR arg_list = get_frame_args_address (fi);
- /* Number of args for this frame, or -1 if unknown. */
- int numargs;
- if (arg_list == 0)
- gdb_printf (" Arglist at unknown address.\n");
- else
- {
- gdb_printf (" Arglist at ");
- gdb_puts (paddress (gdbarch, arg_list));
- gdb_printf (",");
- if (!gdbarch_frame_num_args_p (gdbarch))
- {
- numargs = -1;
- gdb_puts (" args: ");
- }
- else
- {
- numargs = gdbarch_frame_num_args (gdbarch, fi);
- gdb_assert (numargs >= 0);
- if (numargs == 0)
- gdb_puts (" no args.");
- else if (numargs == 1)
- gdb_puts (" 1 arg: ");
- else
- gdb_printf (" %d args: ", numargs);
- }
- print_frame_args (user_frame_print_options,
- func, fi, numargs, gdb_stdout);
- gdb_puts ("\n");
- }
- }
- {
- /* Address of the local variables for this frame, or 0. */
- CORE_ADDR arg_list = get_frame_locals_address (fi);
- if (arg_list == 0)
- gdb_printf (" Locals at unknown address,");
- else
- {
- gdb_printf (" Locals at ");
- gdb_puts (paddress (gdbarch, arg_list));
- gdb_printf (",");
- }
- }
- /* Print as much information as possible on the location of all the
- registers. */
- {
- int count;
- int i;
- int need_nl = 1;
- int sp_regnum = gdbarch_sp_regnum (gdbarch);
- /* The sp is special; what's displayed isn't the save address, but
- the value of the previous frame's sp. This is a legacy thing,
- at one stage the frame cached the previous frame's SP instead
- of its address, hence it was easiest to just display the cached
- value. */
- if (sp_regnum >= 0)
- {
- struct value *value = frame_unwind_register_value (fi, sp_regnum);
- gdb_assert (value != NULL);
- if (!value_optimized_out (value) && value_entirely_available (value))
- {
- if (VALUE_LVAL (value) == not_lval)
- {
- CORE_ADDR sp;
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int sp_size = register_size (gdbarch, sp_regnum);
- sp = extract_unsigned_integer
- (value_contents_all (value).data (), sp_size, byte_order);
- gdb_printf (" Previous frame's sp is ");
- gdb_puts (paddress (gdbarch, sp));
- gdb_printf ("\n");
- }
- else if (VALUE_LVAL (value) == lval_memory)
- {
- gdb_printf (" Previous frame's sp at ");
- gdb_puts (paddress (gdbarch, value_address (value)));
- gdb_printf ("\n");
- }
- else if (VALUE_LVAL (value) == lval_register)
- {
- gdb_printf (" Previous frame's sp in %s\n",
- gdbarch_register_name (gdbarch,
- VALUE_REGNUM (value)));
- }
- release_value (value);
- need_nl = 0;
- }
- /* else keep quiet. */
- }
- count = 0;
- numregs = gdbarch_num_cooked_regs (gdbarch);
- for (i = 0; i < numregs; i++)
- if (i != sp_regnum
- && gdbarch_register_reggroup_p (gdbarch, i, all_reggroup))
- {
- enum lval_type lval;
- int optimized;
- int unavailable;
- CORE_ADDR addr;
- int realnum;
- /* Find out the location of the saved register without
- fetching the corresponding value. */
- frame_register_unwind (fi, i, &optimized, &unavailable,
- &lval, &addr, &realnum, NULL);
- /* For moment, only display registers that were saved on the
- stack. */
- if (!optimized && !unavailable && lval == lval_memory)
- {
- if (count == 0)
- gdb_puts (" Saved registers:\n ");
- else
- gdb_puts (",");
- gdb_stdout->wrap_here (1);
- gdb_printf (" %s at ",
- gdbarch_register_name (gdbarch, i));
- gdb_puts (paddress (gdbarch, addr));
- count++;
- }
- }
- if (count || need_nl)
- gdb_puts ("\n");
- }
- }
- /* Return the innermost frame at level LEVEL. */
- static struct frame_info *
- leading_innermost_frame (int level)
- {
- struct frame_info *leading;
- leading = get_current_frame ();
- gdb_assert (level >= 0);
- while (leading != nullptr && level)
- {
- QUIT;
- leading = get_prev_frame (leading);
- level--;
- }
- return leading;
- }
- /* Return the starting frame needed to handle COUNT outermost frames. */
- static struct frame_info *
- trailing_outermost_frame (int count)
- {
- struct frame_info *current;
- struct frame_info *trailing;
- trailing = get_current_frame ();
- gdb_assert (count > 0);
- current = trailing;
- while (current != nullptr && count--)
- {
- QUIT;
- current = get_prev_frame (current);
- }
- /* Will stop when CURRENT reaches the top of the stack.
- TRAILING will be COUNT below it. */
- while (current != nullptr)
- {
- QUIT;
- trailing = get_prev_frame (trailing);
- current = get_prev_frame (current);
- }
- return trailing;
- }
- /* The core of all the "select-frame" sub-commands. Just wraps a call to
- SELECT_FRAME. */
- static void
- select_frame_command_core (struct frame_info *fi, bool ignored)
- {
- frame_info *prev_frame = get_selected_frame ();
- select_frame (fi);
- if (get_selected_frame () != prev_frame)
- gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
- }
- /* The core of all the "frame" sub-commands. Select frame FI, and if this
- means we change frame send out a change notification (otherwise, just
- reprint the current frame summary). */
- static void
- frame_command_core (struct frame_info *fi, bool ignored)
- {
- frame_info *prev_frame = get_selected_frame ();
- select_frame (fi);
- if (get_selected_frame () != prev_frame)
- gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
- else
- print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
- }
- /* The three commands 'frame', 'select-frame', and 'info frame' all have a
- common set of sub-commands that allow a specific frame to be selected.
- All of the sub-command functions are static methods within this class
- template which is then instantiated below. The template parameter is a
- callback used to implement the functionality of the base command
- ('frame', 'select-frame', or 'info frame').
- In the template parameter FI is the frame being selected. The
- SELECTED_FRAME_P flag is true if the frame being selected was done by
- default, which happens when the user uses the base command with no
- arguments. For example the commands 'info frame', 'select-frame',
- 'frame' will all cause SELECTED_FRAME_P to be true. In all other cases
- SELECTED_FRAME_P is false. */
- template <void (*FPTR) (struct frame_info *fi, bool selected_frame_p)>
- class frame_command_helper
- {
- public:
- /* The "frame level" family of commands. The ARG is an integer that is
- the frame's level in the stack. */
- static void
- level (const char *arg, int from_tty)
- {
- int level = value_as_long (parse_and_eval (arg));
- struct frame_info *fid
- = find_relative_frame (get_current_frame (), &level);
- if (level != 0)
- error (_("No frame at level %s."), arg);
- FPTR (fid, false);
- }
- /* The "frame address" family of commands. ARG is a stack-pointer
- address for an existing frame. This command does not allow new
- frames to be created. */
- static void
- address (const char *arg, int from_tty)
- {
- CORE_ADDR addr = value_as_address (parse_and_eval (arg));
- struct frame_info *fid = find_frame_for_address (addr);
- if (fid == NULL)
- error (_("No frame at address %s."), arg);
- FPTR (fid, false);
- }
- /* The "frame view" family of commands. ARG is one or two addresses and
- is used to view a frame that might be outside the current backtrace.
- The addresses are stack-pointer address, and (optional) pc-address. */
- static void
- view (const char *args, int from_tty)
- {
- struct frame_info *fid;
- if (args == NULL)
- error (_("Missing address argument to view a frame"));
- gdb_argv argv (args);
- if (argv.count () == 2)
- {
- CORE_ADDR addr[2];
- addr [0] = value_as_address (parse_and_eval (argv[0]));
- addr [1] = value_as_address (parse_and_eval (argv[1]));
- fid = create_new_frame (addr[0], addr[1]);
- }
- else
- {
- CORE_ADDR addr = value_as_address (parse_and_eval (argv[0]));
- fid = create_new_frame (addr, false);
- }
- FPTR (fid, false);
- }
- /* The "frame function" family of commands. ARG is the name of a
- function within the stack, the first function (searching from frame
- 0) with that name will be selected. */
- static void
- function (const char *arg, int from_tty)
- {
- if (arg == NULL)
- error (_("Missing function name argument"));
- struct frame_info *fid = find_frame_for_function (arg);
- if (fid == NULL)
- error (_("No frame for function \"%s\"."), arg);
- FPTR (fid, false);
- }
- /* The "frame" base command, that is, when no sub-command is specified.
- If one argument is provided then we assume that this is a frame's
- level as historically, this was the supported command syntax that was
- used most often.
- If no argument is provided, then the current frame is selected. */
- static void
- base_command (const char *arg, int from_tty)
- {
- if (arg == NULL)
- FPTR (get_selected_frame (_("No stack.")), true);
- else
- level (arg, from_tty);
- }
- };
- /* Instantiate three FRAME_COMMAND_HELPER instances to implement the
- sub-commands for 'info frame', 'frame', and 'select-frame' commands. */
- static frame_command_helper <info_frame_command_core> info_frame_cmd;
- static frame_command_helper <frame_command_core> frame_cmd;
- static frame_command_helper <select_frame_command_core> select_frame_cmd;
- /* Print briefly all stack frames or just the innermost COUNT_EXP
- frames. */
- static void
- backtrace_command_1 (const frame_print_options &fp_opts,
- const backtrace_cmd_options &bt_opts,
- const char *count_exp, int from_tty)
- {
- struct frame_info *fi;
- int count;
- int py_start = 0, py_end = 0;
- enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
- if (!target_has_stack ())
- error (_("No stack."));
- if (count_exp)
- {
- count = parse_and_eval_long (count_exp);
- if (count < 0)
- py_start = count;
- else
- {
- py_start = 0;
- /* The argument to apply_ext_lang_frame_filter is the number
- of the final frame to print, and frames start at 0. */
- py_end = count - 1;
- }
- }
- else
- {
- py_end = -1;
- count = -1;
- }
- frame_filter_flags flags = 0;
- if (bt_opts.full)
- flags |= PRINT_LOCALS;
- if (bt_opts.hide)
- flags |= PRINT_HIDE;
- if (!bt_opts.no_filters)
- {
- enum ext_lang_frame_args arg_type;
- flags |= PRINT_LEVEL | PRINT_FRAME_INFO | PRINT_ARGS;
- if (from_tty)
- flags |= PRINT_MORE_FRAMES;
- if (fp_opts.print_frame_arguments == print_frame_arguments_scalars)
- arg_type = CLI_SCALAR_VALUES;
- else if (fp_opts.print_frame_arguments == print_frame_arguments_all)
- arg_type = CLI_ALL_VALUES;
- else if (fp_opts.print_frame_arguments == print_frame_arguments_presence)
- arg_type = CLI_PRESENCE;
- else if (fp_opts.print_frame_arguments == print_frame_arguments_none)
- arg_type = NO_VALUES;
- else
- gdb_assert (0);
- result = apply_ext_lang_frame_filter (get_current_frame (), flags,
- arg_type, current_uiout,
- py_start, py_end);
- }
- /* Run the inbuilt backtrace if there are no filters registered, or
- "-no-filters" has been specified from the command. */
- if (bt_opts.no_filters || result == EXT_LANG_BT_NO_FILTERS)
- {
- struct frame_info *trailing;
- /* The following code must do two things. First, it must set the
- variable TRAILING to the frame from which we should start
- printing. Second, it must set the variable count to the number
- of frames which we should print, or -1 if all of them. */
- if (count_exp != NULL && count < 0)
- {
- trailing = trailing_outermost_frame (-count);
- count = -1;
- }
- else
- trailing = get_current_frame ();
- for (fi = trailing; fi && count--; fi = get_prev_frame (fi))
- {
- QUIT;
- /* Don't use print_stack_frame; if an error() occurs it probably
- means further attempts to backtrace would fail (on the other
- hand, perhaps the code does or could be fixed to make sure
- the frame->prev field gets set to NULL in that case). */
- print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0);
- if ((flags & PRINT_LOCALS) != 0)
- {
- struct frame_id frame_id = get_frame_id (fi);
- print_frame_local_vars (fi, false, NULL, NULL, 1, gdb_stdout);
- /* print_frame_local_vars invalidates FI. */
- fi = frame_find_by_id (frame_id);
- if (fi == NULL)
- {
- trailing = NULL;
- warning (_("Unable to restore previously selected frame."));
- break;
- }
- }
- /* Save the last frame to check for error conditions. */
- trailing = fi;
- }
- /* If we've stopped before the end, mention that. */
- if (fi && from_tty)
- gdb_printf (_("(More stack frames follow...)\n"));
- /* If we've run out of frames, and the reason appears to be an error
- condition, print it. */
- if (fi == NULL && trailing != NULL)
- {
- enum unwind_stop_reason reason;
- reason = get_frame_unwind_stop_reason (trailing);
- if (reason >= UNWIND_FIRST_ERROR)
- gdb_printf (_("Backtrace stopped: %s\n"),
- frame_stop_reason_string (trailing));
- }
- }
- }
- /* Create an option_def_group array grouping all the "backtrace"
- options, with FP_OPTS, BT_CMD_OPT, SET_BT_OPTS as contexts. */
- static inline std::array<gdb::option::option_def_group, 3>
- make_backtrace_options_def_group (frame_print_options *fp_opts,
- backtrace_cmd_options *bt_cmd_opts,
- set_backtrace_options *set_bt_opts)
- {
- return {{
- { {frame_print_option_defs}, fp_opts },
- { {set_backtrace_option_defs}, set_bt_opts },
- { {backtrace_command_option_defs}, bt_cmd_opts }
- }};
- }
- /* Parse the backtrace command's qualifiers. Returns ARG advanced
- past the qualifiers, if any. BT_CMD_OPTS, if not null, is used to
- store the parsed qualifiers. */
- static const char *
- parse_backtrace_qualifiers (const char *arg,
- backtrace_cmd_options *bt_cmd_opts = nullptr)
- {
- while (true)
- {
- const char *save_arg = arg;
- std::string this_arg = extract_arg (&arg);
- if (this_arg.empty ())
- return arg;
- if (subset_compare (this_arg.c_str (), "no-filters"))
- {
- if (bt_cmd_opts != nullptr)
- bt_cmd_opts->no_filters = true;
- }
- else if (subset_compare (this_arg.c_str (), "full"))
- {
- if (bt_cmd_opts != nullptr)
- bt_cmd_opts->full = true;
- }
- else if (subset_compare (this_arg.c_str (), "hide"))
- {
- if (bt_cmd_opts != nullptr)
- bt_cmd_opts->hide = true;
- }
- else
- {
- /* Not a recognized qualifier, so stop. */
- return save_arg;
- }
- }
- }
- static void
- backtrace_command (const char *arg, int from_tty)
- {
- frame_print_options fp_opts = user_frame_print_options;
- backtrace_cmd_options bt_cmd_opts;
- set_backtrace_options set_bt_opts = user_set_backtrace_options;
- auto grp
- = make_backtrace_options_def_group (&fp_opts, &bt_cmd_opts, &set_bt_opts);
- gdb::option::process_options
- (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
- /* Parse non-'-'-prefixed qualifiers, for backwards
- compatibility. */
- if (arg != NULL)
- {
- arg = parse_backtrace_qualifiers (arg, &bt_cmd_opts);
- if (*arg == '\0')
- arg = NULL;
- }
- /* These options are handled quite deep in the unwind machinery, so
- we get to pass them down by swapping globals. */
- scoped_restore restore_set_backtrace_options
- = make_scoped_restore (&user_set_backtrace_options, set_bt_opts);
- backtrace_command_1 (fp_opts, bt_cmd_opts, arg, from_tty);
- }
- /* Completer for the "backtrace" command. */
- static void
- backtrace_command_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char */*word*/)
- {
- const auto group
- = make_backtrace_options_def_group (nullptr, nullptr, nullptr);
- if (gdb::option::complete_options
- (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
- return;
- if (*text != '\0')
- {
- const char *p = skip_to_space (text);
- if (*p == '\0')
- {
- static const char *const backtrace_cmd_qualifier_choices[] = {
- "full", "no-filters", "hide", nullptr,
- };
- complete_on_enum (tracker, backtrace_cmd_qualifier_choices,
- text, text);
- if (tracker.have_completions ())
- return;
- }
- else
- {
- const char *cmd = parse_backtrace_qualifiers (text);
- tracker.advance_custom_word_point_by (cmd - text);
- text = cmd;
- }
- }
- const char *word = advance_to_expression_complete_word_point (tracker, text);
- expression_completer (ignore, tracker, text, word);
- }
- /* Iterate over the local variables of a block B, calling CB. */
- static void
- iterate_over_block_locals (const struct block *b,
- iterate_over_block_arg_local_vars_cb cb)
- {
- struct block_iterator iter;
- struct symbol *sym;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- switch (sym->aclass ())
- {
- case LOC_CONST:
- case LOC_LOCAL:
- case LOC_REGISTER:
- case LOC_STATIC:
- case LOC_COMPUTED:
- case LOC_OPTIMIZED_OUT:
- if (sym->is_argument ())
- break;
- if (sym->domain () == COMMON_BLOCK_DOMAIN)
- break;
- cb (sym->print_name (), sym);
- break;
- default:
- /* Ignore symbols which are not locals. */
- break;
- }
- }
- }
- /* Iterate over all the local variables in block B, including all its
- superblocks, stopping when the top-level block is reached. */
- void
- iterate_over_block_local_vars (const struct block *block,
- iterate_over_block_arg_local_vars_cb cb)
- {
- while (block)
- {
- iterate_over_block_locals (block, cb);
- /* After handling the function's top-level block, stop. Don't
- continue to its superblock, the block of per-file
- symbols. */
- if (BLOCK_FUNCTION (block))
- break;
- block = BLOCK_SUPERBLOCK (block);
- }
- }
- /* Data to be passed around in the calls to the locals and args
- iterators. */
- struct print_variable_and_value_data
- {
- gdb::optional<compiled_regex> preg;
- gdb::optional<compiled_regex> treg;
- struct frame_id frame_id;
- int num_tabs;
- struct ui_file *stream;
- int values_printed;
- void operator() (const char *print_name, struct symbol *sym);
- };
- /* The callback for the locals and args iterators. */
- void
- print_variable_and_value_data::operator() (const char *print_name,
- struct symbol *sym)
- {
- struct frame_info *frame;
- if (preg.has_value ()
- && preg->exec (sym->natural_name (), 0, NULL, 0) != 0)
- return;
- if (treg.has_value ()
- && !treg_matches_sym_type_name (*treg, sym))
- return;
- if (language_def (sym->language ())->symbol_printing_suppressed (sym))
- return;
- frame = frame_find_by_id (frame_id);
- if (frame == NULL)
- {
- warning (_("Unable to restore previously selected frame."));
- return;
- }
- print_variable_and_value (print_name, sym, frame, stream, num_tabs);
- /* print_variable_and_value invalidates FRAME. */
- frame = NULL;
- values_printed = 1;
- }
- /* Prepares the regular expression REG from REGEXP.
- If REGEXP is NULL, it results in an empty regular expression. */
- static void
- prepare_reg (const char *regexp, gdb::optional<compiled_regex> *reg)
- {
- if (regexp != NULL)
- {
- int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
- ? REG_ICASE : 0);
- reg->emplace (regexp, cflags, _("Invalid regexp"));
- }
- else
- reg->reset ();
- }
- /* Print all variables from the innermost up to the function block of FRAME.
- Print them with values to STREAM indented by NUM_TABS.
- If REGEXP is not NULL, only print local variables whose name
- matches REGEXP.
- If T_REGEXP is not NULL, only print local variables whose type
- matches T_REGEXP.
- If no local variables have been printed and !QUIET, prints a message
- explaining why no local variables could be printed.
- This function will invalidate FRAME. */
- static void
- print_frame_local_vars (struct frame_info *frame,
- bool quiet,
- const char *regexp, const char *t_regexp,
- int num_tabs, struct ui_file *stream)
- {
- struct print_variable_and_value_data cb_data;
- const struct block *block;
- CORE_ADDR pc;
- if (!get_frame_pc_if_available (frame, &pc))
- {
- if (!quiet)
- gdb_printf (stream,
- _("PC unavailable, cannot determine locals.\n"));
- return;
- }
- block = get_frame_block (frame, 0);
- if (block == 0)
- {
- if (!quiet)
- gdb_printf (stream, "No symbol table info available.\n");
- return;
- }
- prepare_reg (regexp, &cb_data.preg);
- prepare_reg (t_regexp, &cb_data.treg);
- cb_data.frame_id = get_frame_id (frame);
- cb_data.num_tabs = 4 * num_tabs;
- cb_data.stream = stream;
- cb_data.values_printed = 0;
- /* Temporarily change the selected frame to the given FRAME.
- This allows routines that rely on the selected frame instead
- of being given a frame as parameter to use the correct frame. */
- scoped_restore_selected_frame restore_selected_frame;
- select_frame (frame);
- iterate_over_block_local_vars (block, cb_data);
- if (!cb_data.values_printed && !quiet)
- {
- if (regexp == NULL && t_regexp == NULL)
- gdb_printf (stream, _("No locals.\n"));
- else
- gdb_printf (stream, _("No matching locals.\n"));
- }
- }
- /* Structure to hold the values of the options used by the 'info
- variables' command and other similar commands. These correspond to the
- -q and -t options. */
- struct info_print_options
- {
- bool quiet = false;
- std::string type_regexp;
- };
- /* The options used by the 'info locals' and 'info args' commands. */
- static const gdb::option::option_def info_print_options_defs[] = {
- gdb::option::boolean_option_def<info_print_options> {
- "q",
- [] (info_print_options *opt) { return &opt->quiet; },
- nullptr, /* show_cmd_cb */
- nullptr /* set_doc */
- },
- gdb::option::string_option_def<info_print_options> {
- "t",
- [] (info_print_options *opt) { return &opt->type_regexp; },
- nullptr, /* show_cmd_cb */
- nullptr /* set_doc */
- }
- };
- /* Returns the option group used by 'info locals' and 'info args'
- commands. */
- static gdb::option::option_def_group
- make_info_print_options_def_group (info_print_options *opts)
- {
- return {{info_print_options_defs}, opts};
- }
- /* Command completer for 'info locals' and 'info args'. */
- static void
- info_print_command_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char * /* word */)
- {
- const auto group
- = make_info_print_options_def_group (nullptr);
- if (gdb::option::complete_options
- (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
- return;
- const char *word = advance_to_expression_complete_word_point (tracker, text);
- symbol_completer (ignore, tracker, text, word);
- }
- /* Implement the 'info locals' command. */
- void
- info_locals_command (const char *args, int from_tty)
- {
- info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
- gdb::option::process_options
- (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
- if (args != nullptr && *args == '\0')
- args = nullptr;
- print_frame_local_vars
- (get_selected_frame (_("No frame selected.")),
- opts.quiet, args,
- opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
- 0, gdb_stdout);
- }
- /* Iterate over all the argument variables in block B. */
- void
- iterate_over_block_arg_vars (const struct block *b,
- iterate_over_block_arg_local_vars_cb cb)
- {
- struct block_iterator iter;
- struct symbol *sym, *sym2;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- /* Don't worry about things which aren't arguments. */
- if (sym->is_argument ())
- {
- /* We have to look up the symbol because arguments can have
- two entries (one a parameter, one a local) and the one we
- want is the local, which lookup_symbol will find for us.
- This includes gcc1 (not gcc2) on the sparc when passing a
- small structure and gcc2 when the argument type is float
- and it is passed as a double and converted to float by
- the prologue (in the latter case the type of the LOC_ARG
- symbol is double and the type of the LOC_LOCAL symbol is
- float). There are also LOC_ARG/LOC_REGISTER pairs which
- are not combined in symbol-reading. */
- sym2 = lookup_symbol_search_name (sym->search_name (),
- b, VAR_DOMAIN).symbol;
- cb (sym->print_name (), sym2);
- }
- }
- }
- /* Print all argument variables of the function of FRAME.
- Print them with values to STREAM.
- If REGEXP is not NULL, only print argument variables whose name
- matches REGEXP.
- If T_REGEXP is not NULL, only print argument variables whose type
- matches T_REGEXP.
- If no argument variables have been printed and !QUIET, prints a message
- explaining why no argument variables could be printed.
- This function will invalidate FRAME. */
- static void
- print_frame_arg_vars (struct frame_info *frame,
- bool quiet,
- const char *regexp, const char *t_regexp,
- struct ui_file *stream)
- {
- struct print_variable_and_value_data cb_data;
- struct symbol *func;
- CORE_ADDR pc;
- gdb::optional<compiled_regex> preg;
- gdb::optional<compiled_regex> treg;
- if (!get_frame_pc_if_available (frame, &pc))
- {
- if (!quiet)
- gdb_printf (stream,
- _("PC unavailable, cannot determine args.\n"));
- return;
- }
- func = get_frame_function (frame);
- if (func == NULL)
- {
- if (!quiet)
- gdb_printf (stream, _("No symbol table info available.\n"));
- return;
- }
- prepare_reg (regexp, &cb_data.preg);
- prepare_reg (t_regexp, &cb_data.treg);
- cb_data.frame_id = get_frame_id (frame);
- cb_data.num_tabs = 0;
- cb_data.stream = stream;
- cb_data.values_printed = 0;
- iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func), cb_data);
- /* do_print_variable_and_value invalidates FRAME. */
- frame = NULL;
- if (!cb_data.values_printed && !quiet)
- {
- if (regexp == NULL && t_regexp == NULL)
- gdb_printf (stream, _("No arguments.\n"));
- else
- gdb_printf (stream, _("No matching arguments.\n"));
- }
- }
- /* Implement the 'info args' command. */
- void
- info_args_command (const char *args, int from_tty)
- {
- info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
- gdb::option::process_options
- (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
- if (args != nullptr && *args == '\0')
- args = nullptr;
- print_frame_arg_vars
- (get_selected_frame (_("No frame selected.")),
- opts.quiet, args,
- opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
- gdb_stdout);
- }
- /* Return the symbol-block in which the selected frame is executing.
- Can return zero under various legitimate circumstances.
- If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the relevant
- code address within the block returned. We use this to decide
- which macros are in scope. */
- const struct block *
- get_selected_block (CORE_ADDR *addr_in_block)
- {
- if (!has_stack_frames ())
- return 0;
- return get_frame_block (get_selected_frame (NULL), addr_in_block);
- }
- /* Find a frame a certain number of levels away from FRAME.
- LEVEL_OFFSET_PTR points to an int containing the number of levels.
- Positive means go to earlier frames (up); negative, the reverse.
- The int that contains the number of levels is counted toward
- zero as the frames for those levels are found.
- If the top or bottom frame is reached, that frame is returned,
- but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
- how much farther the original request asked to go. */
- struct frame_info *
- find_relative_frame (struct frame_info *frame, int *level_offset_ptr)
- {
- /* Going up is simple: just call get_prev_frame enough times or
- until the initial frame is reached. */
- while (*level_offset_ptr > 0)
- {
- struct frame_info *prev = get_prev_frame (frame);
- if (!prev)
- break;
- (*level_offset_ptr)--;
- frame = prev;
- }
- /* Going down is just as simple. */
- while (*level_offset_ptr < 0)
- {
- struct frame_info *next = get_next_frame (frame);
- if (!next)
- break;
- (*level_offset_ptr)++;
- frame = next;
- }
- return frame;
- }
- /* Select the frame up one or COUNT_EXP stack levels from the
- previously selected frame, and print it briefly. */
- static void
- up_silently_base (const char *count_exp)
- {
- struct frame_info *frame;
- int count = 1;
- if (count_exp)
- count = parse_and_eval_long (count_exp);
- frame = find_relative_frame (get_selected_frame ("No stack."), &count);
- if (count != 0 && count_exp == NULL)
- error (_("Initial frame selected; you cannot go up."));
- select_frame (frame);
- }
- static void
- up_silently_command (const char *count_exp, int from_tty)
- {
- up_silently_base (count_exp);
- }
- static void
- up_command (const char *count_exp, int from_tty)
- {
- up_silently_base (count_exp);
- gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
- }
- /* Select the frame down one or COUNT_EXP stack levels from the previously
- selected frame, and print it briefly. */
- static void
- down_silently_base (const char *count_exp)
- {
- struct frame_info *frame;
- int count = -1;
- if (count_exp)
- count = -parse_and_eval_long (count_exp);
- frame = find_relative_frame (get_selected_frame ("No stack."), &count);
- if (count != 0 && count_exp == NULL)
- {
- /* We only do this if COUNT_EXP is not specified. That way
- "down" means to really go down (and let me know if that is
- impossible), but "down 9999" can be used to mean go all the
- way down without getting an error. */
- error (_("Bottom (innermost) frame selected; you cannot go down."));
- }
- select_frame (frame);
- }
- static void
- down_silently_command (const char *count_exp, int from_tty)
- {
- down_silently_base (count_exp);
- }
- static void
- down_command (const char *count_exp, int from_tty)
- {
- down_silently_base (count_exp);
- gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
- }
- void
- return_command (const char *retval_exp, int from_tty)
- {
- /* Initialize it just to avoid a GCC false warning. */
- enum return_value_convention rv_conv = RETURN_VALUE_STRUCT_CONVENTION;
- struct frame_info *thisframe;
- struct gdbarch *gdbarch;
- struct symbol *thisfun;
- struct value *return_value = NULL;
- struct value *function = NULL;
- std::string query_prefix;
- thisframe = get_selected_frame ("No selected frame.");
- thisfun = get_frame_function (thisframe);
- gdbarch = get_frame_arch (thisframe);
- if (get_frame_type (get_current_frame ()) == INLINE_FRAME)
- error (_("Can not force return from an inlined function."));
- /* Compute the return value. If the computation triggers an error,
- let it bail. If the return type can't be handled, set
- RETURN_VALUE to NULL, and QUERY_PREFIX to an informational
- message. */
- if (retval_exp)
- {
- expression_up retval_expr = parse_expression (retval_exp);
- struct type *return_type = NULL;
- /* Compute the return value. Should the computation fail, this
- call throws an error. */
- return_value = evaluate_expression (retval_expr.get ());
- /* Cast return value to the return type of the function. Should
- the cast fail, this call throws an error. */
- if (thisfun != NULL)
- return_type = TYPE_TARGET_TYPE (thisfun->type ());
- if (return_type == NULL)
- {
- if (retval_expr->first_opcode () != UNOP_CAST
- && retval_expr->first_opcode () != UNOP_CAST_TYPE)
- error (_("Return value type not available for selected "
- "stack frame.\n"
- "Please use an explicit cast of the value to return."));
- return_type = value_type (return_value);
- }
- return_type = check_typedef (return_type);
- return_value = value_cast (return_type, return_value);
- /* Make sure the value is fully evaluated. It may live in the
- stack frame we're about to pop. */
- if (value_lazy (return_value))
- value_fetch_lazy (return_value);
- if (thisfun != NULL)
- function = read_var_value (thisfun, NULL, thisframe);
- rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
- if (return_type->code () == TYPE_CODE_VOID)
- /* If the return-type is "void", don't try to find the
- return-value's location. However, do still evaluate the
- return expression so that, even when the expression result
- is discarded, side effects such as "return i++" still
- occur. */
- return_value = NULL;
- else if (thisfun != NULL)
- {
- if (is_nocall_function (check_typedef (value_type (function))))
- {
- query_prefix =
- string_printf ("Function '%s' does not follow the target "
- "calling convention.\n"
- "If you continue, setting the return value "
- "will probably lead to unpredictable "
- "behaviors.\n",
- thisfun->print_name ());
- }
- rv_conv = struct_return_convention (gdbarch, function, return_type);
- if (rv_conv == RETURN_VALUE_STRUCT_CONVENTION
- || rv_conv == RETURN_VALUE_ABI_RETURNS_ADDRESS)
- {
- query_prefix = "The location at which to store the "
- "function's return value is unknown.\n"
- "If you continue, the return value "
- "that you specified will be ignored.\n";
- return_value = NULL;
- }
- }
- }
- /* Does an interactive user really want to do this? Include
- information, such as how well GDB can handle the return value, in
- the query message. */
- if (from_tty)
- {
- int confirmed;
- if (thisfun == NULL)
- confirmed = query (_("%sMake selected stack frame return now? "),
- query_prefix.c_str ());
- else
- {
- if (TYPE_NO_RETURN (thisfun->type ()))
- warning (_("Function does not return normally to caller."));
- confirmed = query (_("%sMake %s return now? "),
- query_prefix.c_str (),
- thisfun->print_name ());
- }
- if (!confirmed)
- error (_("Not confirmed"));
- }
- /* Discard the selected frame and all frames inner-to it. */
- frame_pop (get_selected_frame (NULL));
- /* Store RETURN_VALUE in the just-returned register set. */
- if (return_value != NULL)
- {
- struct type *return_type = value_type (return_value);
- struct gdbarch *cache_arch = get_current_regcache ()->arch ();
- gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION
- && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS);
- gdbarch_return_value (cache_arch, function, return_type,
- get_current_regcache (), NULL /*read*/,
- value_contents (return_value).data () /*write*/);
- }
- /* If we are at the end of a call dummy now, pop the dummy frame
- too. */
- if (get_frame_type (get_current_frame ()) == DUMMY_FRAME)
- frame_pop (get_current_frame ());
- select_frame (get_current_frame ());
- /* If interactive, print the frame that is now current. */
- if (from_tty)
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
- }
- /* Find the most inner frame in the current stack for a function called
- FUNCTION_NAME. If no matching frame is found return NULL. */
- static struct frame_info *
- find_frame_for_function (const char *function_name)
- {
- /* Used to hold the lower and upper addresses for each of the
- SYMTAB_AND_LINEs found for functions matching FUNCTION_NAME. */
- struct function_bounds
- {
- CORE_ADDR low, high;
- };
- struct frame_info *frame;
- bool found = false;
- int level = 1;
- gdb_assert (function_name != NULL);
- frame = get_current_frame ();
- std::vector<symtab_and_line> sals
- = decode_line_with_current_source (function_name,
- DECODE_LINE_FUNFIRSTLINE);
- gdb::def_vector<function_bounds> func_bounds (sals.size ());
- for (size_t i = 0; i < sals.size (); i++)
- {
- if (sals[i].pspace != current_program_space)
- func_bounds[i].low = func_bounds[i].high = 0;
- else if (sals[i].pc == 0
- || find_pc_partial_function (sals[i].pc, NULL,
- &func_bounds[i].low,
- &func_bounds[i].high) == 0)
- func_bounds[i].low = func_bounds[i].high = 0;
- }
- do
- {
- for (size_t i = 0; (i < sals.size () && !found); i++)
- found = (get_frame_pc (frame) >= func_bounds[i].low
- && get_frame_pc (frame) < func_bounds[i].high);
- if (!found)
- {
- level = 1;
- frame = find_relative_frame (frame, &level);
- }
- }
- while (!found && level == 0);
- if (!found)
- frame = NULL;
- return frame;
- }
- /* The qcs command line flags for the "frame apply" commands. Keep
- this in sync with the "thread apply" commands. */
- using qcs_flag_option_def
- = gdb::option::flag_option_def<qcs_flags>;
- static const gdb::option::option_def fr_qcs_flags_option_defs[] = {
- qcs_flag_option_def {
- "q", [] (qcs_flags *opt) { return &opt->quiet; },
- N_("Disables printing the frame location information."),
- },
- qcs_flag_option_def {
- "c", [] (qcs_flags *opt) { return &opt->cont; },
- N_("Print any error raised by COMMAND and continue."),
- },
- qcs_flag_option_def {
- "s", [] (qcs_flags *opt) { return &opt->silent; },
- N_("Silently ignore any errors or empty output produced by COMMAND."),
- },
- };
- /* Create an option_def_group array for all the "frame apply" options,
- with FLAGS and SET_BT_OPTS as context. */
- static inline std::array<gdb::option::option_def_group, 2>
- make_frame_apply_options_def_group (qcs_flags *flags,
- set_backtrace_options *set_bt_opts)
- {
- return {{
- { {fr_qcs_flags_option_defs}, flags },
- { {set_backtrace_option_defs}, set_bt_opts },
- }};
- }
- /* Apply a GDB command to all stack frames, or a set of identified frames,
- or innermost COUNT frames.
- With a negative COUNT, apply command on outermost -COUNT frames.
- frame apply 3 info frame Apply 'info frame' to frames 0, 1, 2
- frame apply -3 info frame Apply 'info frame' to outermost 3 frames.
- frame apply all x/i $pc Apply 'x/i $pc' cmd to all frames.
- frame apply all -s p local_var_no_idea_in_which_frame
- If a frame has a local variable called
- local_var_no_idea_in_which_frame, print frame
- and value of local_var_no_idea_in_which_frame.
- frame apply all -s -q p local_var_no_idea_in_which_frame
- Same as before, but only print the variable value.
- frame apply level 2-5 0 4-7 -s p i = i + 1
- Adds 1 to the variable i in the specified frames.
- Note that i will be incremented twice in
- frames 4 and 5. */
- /* Apply a GDB command to COUNT stack frames, starting at TRAILING.
- CMD starts with 0 or more qcs flags followed by the GDB command to apply.
- COUNT -1 means all frames starting at TRAILING. WHICH_COMMAND is used
- for error messages. */
- static void
- frame_apply_command_count (const char *which_command,
- const char *cmd, int from_tty,
- struct frame_info *trailing, int count)
- {
- qcs_flags flags;
- set_backtrace_options set_bt_opts = user_set_backtrace_options;
- auto group = make_frame_apply_options_def_group (&flags, &set_bt_opts);
- gdb::option::process_options
- (&cmd, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
- validate_flags_qcs (which_command, &flags);
- if (cmd == NULL || *cmd == '\0')
- error (_("Please specify a command to apply on the selected frames"));
- /* The below will restore the current inferior/thread/frame.
- Usually, only the frame is effectively to be restored.
- But in case CMD switches of inferior/thread, better restore
- these also. */
- scoped_restore_current_thread restore_thread;
- /* These options are handled quite deep in the unwind machinery, so
- we get to pass them down by swapping globals. */
- scoped_restore restore_set_backtrace_options
- = make_scoped_restore (&user_set_backtrace_options, set_bt_opts);
- for (frame_info *fi = trailing; fi && count--; fi = get_prev_frame (fi))
- {
- QUIT;
- select_frame (fi);
- try
- {
- std::string cmd_result;
- {
- /* In case CMD switches of inferior/thread/frame, the below
- restores the inferior/thread/frame. FI can then be
- set to the selected frame. */
- scoped_restore_current_thread restore_fi_current_frame;
- execute_command_to_string
- (cmd_result, cmd, from_tty, gdb_stdout->term_out ());
- }
- fi = get_selected_frame (_("frame apply "
- "unable to get selected frame."));
- if (!flags.silent || cmd_result.length () > 0)
- {
- if (!flags.quiet)
- print_stack_frame (fi, 1, LOCATION, 0);
- gdb_printf ("%s", cmd_result.c_str ());
- }
- }
- catch (const gdb_exception_error &ex)
- {
- fi = get_selected_frame (_("frame apply "
- "unable to get selected frame."));
- if (!flags.silent)
- {
- if (!flags.quiet)
- print_stack_frame (fi, 1, LOCATION, 0);
- if (flags.cont)
- gdb_printf ("%s\n", ex.what ());
- else
- throw;
- }
- }
- }
- }
- /* Completer for the "frame apply ..." commands. */
- static void
- frame_apply_completer (completion_tracker &tracker, const char *text)
- {
- const auto group = make_frame_apply_options_def_group (nullptr, nullptr);
- if (gdb::option::complete_options
- (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
- return;
- complete_nested_command_line (tracker, text);
- }
- /* Completer for the "frame apply" commands. */
- static void
- frame_apply_level_cmd_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char */*word*/)
- {
- /* Do this explicitly because there's an early return below. */
- tracker.set_use_custom_word_point (true);
- number_or_range_parser levels (text);
- /* Skip the LEVEL list to find the options and command args. */
- try
- {
- while (!levels.finished ())
- {
- /* Call for effect. */
- levels.get_number ();
- if (levels.in_range ())
- levels.skip_range ();
- }
- }
- catch (const gdb_exception_error &ex)
- {
- /* get_number throws if it parses a negative number, for
- example. But a seemingly negative number may be the start of
- an option instead. */
- }
- const char *cmd = levels.cur_tok ();
- if (cmd == text)
- {
- /* No level list yet. */
- return;
- }
- /* Check if we're past a valid LEVEL already. */
- if (levels.finished ()
- && cmd > text && !isspace (cmd[-1]))
- return;
- /* We're past LEVELs, advance word point. */
- tracker.advance_custom_word_point_by (cmd - text);
- text = cmd;
- frame_apply_completer (tracker, text);
- }
- /* Completer for the "frame apply all" command. */
- void
- frame_apply_all_cmd_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char */*word*/)
- {
- frame_apply_completer (tracker, text);
- }
- /* Completer for the "frame apply COUNT" command. */
- static void
- frame_apply_cmd_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char */*word*/)
- {
- const char *cmd = text;
- int count = get_number_trailer (&cmd, 0);
- if (count == 0)
- return;
- /* Check if we're past a valid COUNT already. */
- if (cmd > text && !isspace (cmd[-1]))
- return;
- /* We're past COUNT, advance word point. */
- tracker.advance_custom_word_point_by (cmd - text);
- text = cmd;
- frame_apply_completer (tracker, text);
- }
- /* Implementation of the "frame apply level" command. */
- static void
- frame_apply_level_command (const char *cmd, int from_tty)
- {
- if (!target_has_stack ())
- error (_("No stack."));
- bool level_found = false;
- const char *levels_str = cmd;
- number_or_range_parser levels (levels_str);
- /* Skip the LEVEL list to find the flags and command args. */
- while (!levels.finished ())
- {
- /* Call for effect. */
- levels.get_number ();
- level_found = true;
- if (levels.in_range ())
- levels.skip_range ();
- }
- if (!level_found)
- error (_("Missing or invalid LEVEL... argument"));
- cmd = levels.cur_tok ();
- /* Redo the LEVELS parsing, but applying COMMAND. */
- levels.init (levels_str);
- while (!levels.finished ())
- {
- const int level_beg = levels.get_number ();
- int n_frames;
- if (levels.in_range ())
- {
- n_frames = levels.end_value () - level_beg + 1;
- levels.skip_range ();
- }
- else
- n_frames = 1;
- frame_apply_command_count ("frame apply level", cmd, from_tty,
- leading_innermost_frame (level_beg), n_frames);
- }
- }
- /* Implementation of the "frame apply all" command. */
- static void
- frame_apply_all_command (const char *cmd, int from_tty)
- {
- if (!target_has_stack ())
- error (_("No stack."));
- frame_apply_command_count ("frame apply all", cmd, from_tty,
- get_current_frame (), INT_MAX);
- }
- /* Implementation of the "frame apply" command. */
- static void
- frame_apply_command (const char* cmd, int from_tty)
- {
- int count;
- struct frame_info *trailing;
- if (!target_has_stack ())
- error (_("No stack."));
- if (cmd == NULL)
- error (_("Missing COUNT argument."));
- count = get_number_trailer (&cmd, 0);
- if (count == 0)
- error (_("Invalid COUNT argument."));
- if (count < 0)
- {
- trailing = trailing_outermost_frame (-count);
- count = -1;
- }
- else
- trailing = get_current_frame ();
- frame_apply_command_count ("frame apply", cmd, from_tty,
- trailing, count);
- }
- /* Implementation of the "faas" command. */
- static void
- faas_command (const char *cmd, int from_tty)
- {
- if (cmd == NULL || *cmd == '\0')
- error (_("Please specify a command to apply on all frames"));
- std::string expanded = std::string ("frame apply all -s ") + cmd;
- execute_command (expanded.c_str (), from_tty);
- }
- /* Find inner-mode frame with frame address ADDRESS. Return NULL if no
- matching frame can be found. */
- static struct frame_info *
- find_frame_for_address (CORE_ADDR address)
- {
- struct frame_id id;
- struct frame_info *fid;
- id = frame_id_build_wild (address);
- /* If (s)he specifies the frame with an address, he deserves
- what (s)he gets. Still, give the highest one that matches.
- (NOTE: cagney/2004-10-29: Why highest, or outer-most, I don't
- know). */
- for (fid = get_current_frame ();
- fid != NULL;
- fid = get_prev_frame (fid))
- {
- if (frame_id_eq (id, get_frame_id (fid)))
- {
- struct frame_info *prev_frame;
- while (1)
- {
- prev_frame = get_prev_frame (fid);
- if (!prev_frame
- || !frame_id_eq (id, get_frame_id (prev_frame)))
- break;
- fid = prev_frame;
- }
- return fid;
- }
- }
- return NULL;
- }
- /* Commands with a prefix of `frame apply'. */
- static struct cmd_list_element *frame_apply_cmd_list = NULL;
- /* Commands with a prefix of `frame'. */
- static struct cmd_list_element *frame_cmd_list = NULL;
- /* Commands with a prefix of `select frame'. */
- static struct cmd_list_element *select_frame_cmd_list = NULL;
- /* Commands with a prefix of `info frame'. */
- static struct cmd_list_element *info_frame_cmd_list = NULL;
- void _initialize_stack ();
- void
- _initialize_stack ()
- {
- struct cmd_list_element *cmd;
- add_com ("return", class_stack, return_command, _("\
- Make selected stack frame return to its caller.\n\
- Control remains in the debugger, but when you continue\n\
- execution will resume in the frame above the one now selected.\n\
- If an argument is given, it is an expression for the value to return."));
- add_com ("up", class_stack, up_command, _("\
- Select and print stack frame that called this one.\n\
- An argument says how many frames up to go."));
- add_com ("up-silently", class_support, up_silently_command, _("\
- Same as the `up' command, but does not print anything.\n\
- This is useful in command scripts."));
- cmd_list_element *down_cmd
- = add_com ("down", class_stack, down_command, _("\
- Select and print stack frame called by this one.\n\
- An argument says how many frames down to go."));
- add_com_alias ("do", down_cmd, class_stack, 1);
- add_com_alias ("dow", down_cmd, class_stack, 1);
- add_com ("down-silently", class_support, down_silently_command, _("\
- Same as the `down' command, but does not print anything.\n\
- This is useful in command scripts."));
- cmd_list_element *frame_cmd_el
- = add_prefix_cmd ("frame", class_stack,
- &frame_cmd.base_command, _("\
- Select and print a stack frame.\n\
- With no argument, print the selected stack frame. (See also \"info frame\").\n\
- A single numerical argument specifies the frame to select."),
- &frame_cmd_list, 1, &cmdlist);
- add_com_alias ("f", frame_cmd_el, class_stack, 1);
- #define FRAME_APPLY_OPTION_HELP "\
- Prints the frame location information followed by COMMAND output.\n\
- \n\
- By default, an error raised during the execution of COMMAND\n\
- aborts \"frame apply\".\n\
- \n\
- Options:\n\
- %OPTIONS%"
- const auto frame_apply_opts
- = make_frame_apply_options_def_group (nullptr, nullptr);
- static std::string frame_apply_cmd_help = gdb::option::build_help (_("\
- Apply a command to a number of frames.\n\
- Usage: frame apply COUNT [OPTION]... COMMAND\n\
- With a negative COUNT argument, applies the command on outermost -COUNT frames.\n"
- FRAME_APPLY_OPTION_HELP),
- frame_apply_opts);
- cmd = add_prefix_cmd ("apply", class_stack, frame_apply_command,
- frame_apply_cmd_help.c_str (),
- &frame_apply_cmd_list, 1,
- &frame_cmd_list);
- set_cmd_completer_handle_brkchars (cmd, frame_apply_cmd_completer);
- static std::string frame_apply_all_cmd_help = gdb::option::build_help (_("\
- Apply a command to all frames.\n\
- \n\
- Usage: frame apply all [OPTION]... COMMAND\n"
- FRAME_APPLY_OPTION_HELP),
- frame_apply_opts);
- cmd = add_cmd ("all", class_stack, frame_apply_all_command,
- frame_apply_all_cmd_help.c_str (),
- &frame_apply_cmd_list);
- set_cmd_completer_handle_brkchars (cmd, frame_apply_all_cmd_completer);
- static std::string frame_apply_level_cmd_help = gdb::option::build_help (_("\
- Apply a command to a list of frames.\n\
- \n\
- Usage: frame apply level LEVEL... [OPTION]... COMMAND\n\
- LEVEL is a space-separated list of levels of frames to apply COMMAND on.\n"
- FRAME_APPLY_OPTION_HELP),
- frame_apply_opts);
- cmd = add_cmd ("level", class_stack, frame_apply_level_command,
- frame_apply_level_cmd_help.c_str (),
- &frame_apply_cmd_list);
- set_cmd_completer_handle_brkchars (cmd, frame_apply_level_cmd_completer);
- cmd = add_com ("faas", class_stack, faas_command, _("\
- Apply a command to all frames (ignoring errors and empty output).\n\
- Usage: faas [OPTION]... COMMAND\n\
- shortcut for 'frame apply all -s [OPTION]... COMMAND'\n\
- See \"help frame apply all\" for available options."));
- set_cmd_completer_handle_brkchars (cmd, frame_apply_all_cmd_completer);
- add_cmd ("address", class_stack, &frame_cmd.address,
- _("\
- Select and print a stack frame by stack address.\n\
- \n\
- Usage: frame address STACK-ADDRESS"),
- &frame_cmd_list);
- add_cmd ("view", class_stack, &frame_cmd.view,
- _("\
- View a stack frame that might be outside the current backtrace.\n\
- \n\
- Usage: frame view STACK-ADDRESS\n\
- frame view STACK-ADDRESS PC-ADDRESS"),
- &frame_cmd_list);
- cmd = add_cmd ("function", class_stack, &frame_cmd.function,
- _("\
- Select and print a stack frame by function name.\n\
- \n\
- Usage: frame function NAME\n\
- \n\
- The innermost frame that visited function NAME is selected."),
- &frame_cmd_list);
- set_cmd_completer (cmd, frame_selection_by_function_completer);
- add_cmd ("level", class_stack, &frame_cmd.level,
- _("\
- Select and print a stack frame by level.\n\
- \n\
- Usage: frame level LEVEL"),
- &frame_cmd_list);
- cmd = add_prefix_cmd_suppress_notification ("select-frame", class_stack,
- &select_frame_cmd.base_command, _("\
- Select a stack frame without printing anything.\n\
- A single numerical argument specifies the frame to select."),
- &select_frame_cmd_list, 1, &cmdlist,
- &cli_suppress_notification.user_selected_context);
- add_cmd_suppress_notification ("address", class_stack,
- &select_frame_cmd.address, _("\
- Select a stack frame by stack address.\n\
- \n\
- Usage: select-frame address STACK-ADDRESS"),
- &select_frame_cmd_list,
- &cli_suppress_notification.user_selected_context);
- add_cmd_suppress_notification ("view", class_stack,
- &select_frame_cmd.view, _("\
- Select a stack frame that might be outside the current backtrace.\n\
- \n\
- Usage: select-frame view STACK-ADDRESS\n\
- select-frame view STACK-ADDRESS PC-ADDRESS"),
- &select_frame_cmd_list,
- &cli_suppress_notification.user_selected_context);
- cmd = add_cmd_suppress_notification ("function", class_stack,
- &select_frame_cmd.function, _("\
- Select a stack frame by function name.\n\
- \n\
- Usage: select-frame function NAME"),
- &select_frame_cmd_list,
- &cli_suppress_notification.user_selected_context);
- set_cmd_completer (cmd, frame_selection_by_function_completer);
- add_cmd_suppress_notification ("level", class_stack,
- &select_frame_cmd.level, _("\
- Select a stack frame by level.\n\
- \n\
- Usage: select-frame level LEVEL"),
- &select_frame_cmd_list,
- &cli_suppress_notification.user_selected_context);
- const auto backtrace_opts
- = make_backtrace_options_def_group (nullptr, nullptr, nullptr);
- static std::string backtrace_help
- = gdb::option::build_help (_("\
- Print backtrace of all stack frames, or innermost COUNT frames.\n\
- Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]\n\
- \n\
- Options:\n\
- %OPTIONS%\n\
- \n\
- For backward compatibility, the following qualifiers are supported:\n\
- \n\
- full - same as -full option.\n\
- no-filters - same as -no-filters option.\n\
- hide - same as -hide.\n\
- \n\
- With a negative COUNT, print outermost -COUNT frames."),
- backtrace_opts);
- cmd_list_element *backtrace_cmd
- = add_com ("backtrace", class_stack, backtrace_command,
- backtrace_help.c_str ());
- set_cmd_completer_handle_brkchars (backtrace_cmd, backtrace_command_completer);
- add_com_alias ("bt", backtrace_cmd, class_stack, 0);
- add_com_alias ("where", backtrace_cmd, class_stack, 0);
- cmd_list_element *info_stack_cmd
- = add_info ("stack", backtrace_command,
- _("Backtrace of the stack, or innermost COUNT frames."));
- add_info_alias ("s", info_stack_cmd, 1);
- cmd_list_element *info_frame_cmd_el
- = add_prefix_cmd ("frame", class_info, &info_frame_cmd.base_command,
- _("All about the selected stack frame.\n\
- With no arguments, displays information about the currently selected stack\n\
- frame. Alternatively a frame specification may be provided (See \"frame\")\n\
- the information is then printed about the specified frame."),
- &info_frame_cmd_list, 1, &infolist);
- add_info_alias ("f", info_frame_cmd_el, 1);
- add_cmd ("address", class_stack, &info_frame_cmd.address,
- _("\
- Print information about a stack frame selected by stack address.\n\
- \n\
- Usage: info frame address STACK-ADDRESS"),
- &info_frame_cmd_list);
- add_cmd ("view", class_stack, &info_frame_cmd.view,
- _("\
- Print information about a stack frame outside the current backtrace.\n\
- \n\
- Usage: info frame view STACK-ADDRESS\n\
- info frame view STACK-ADDRESS PC-ADDRESS"),
- &info_frame_cmd_list);
- cmd = add_cmd ("function", class_stack, &info_frame_cmd.function,
- _("\
- Print information about a stack frame selected by function name.\n\
- \n\
- Usage: info frame function NAME"),
- &info_frame_cmd_list);
- set_cmd_completer (cmd, frame_selection_by_function_completer);
- add_cmd ("level", class_stack, &info_frame_cmd.level,
- _("\
- Print information about a stack frame selected by level.\n\
- \n\
- Usage: info frame level LEVEL"),
- &info_frame_cmd_list);
- cmd = add_info ("locals", info_locals_command,
- info_print_args_help (_("\
- All local variables of current stack frame or those matching REGEXPs.\n\
- Usage: info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
- Prints the local variables of the current stack frame.\n"),
- _("local variables"),
- false));
- set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
- cmd = add_info ("args", info_args_command,
- info_print_args_help (_("\
- All argument variables of current stack frame or those matching REGEXPs.\n\
- Usage: info args [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
- Prints the argument variables of the current stack frame.\n"),
- _("argument variables"),
- false));
- set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
- /* Install "set print raw frame-arguments", a deprecated spelling of
- "set print raw-frame-arguments". */
- set_show_commands set_show_frame_args
- = add_setshow_boolean_cmd
- ("frame-arguments", no_class,
- &user_frame_print_options.print_raw_frame_arguments,
- _("\
- Set whether to print frame arguments in raw form."), _("\
- Show whether to print frame arguments in raw form."), _("\
- If set, frame arguments are printed in raw form, bypassing any\n\
- pretty-printers for that value."),
- NULL, NULL,
- &setprintrawlist, &showprintrawlist);
- deprecate_cmd (set_show_frame_args.set, "set print raw-frame-arguments");
- add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack,
- &disassemble_next_line, _("\
- Set whether to disassemble next source line or insn when execution stops."),
- _("\
- Show whether to disassemble next source line or insn when execution stops."),
- _("\
- If ON, GDB will display disassembly of the next source line, in addition\n\
- to displaying the source line itself. If the next source line cannot\n\
- be displayed (e.g., source is unavailable or there's no line info), GDB\n\
- will display disassembly of next instruction instead of showing the\n\
- source line.\n\
- If AUTO, display disassembly of next instruction only if the source line\n\
- cannot be displayed.\n\
- If OFF (which is the default), never display the disassembly of the next\n\
- source line."),
- NULL,
- show_disassemble_next_line,
- &setlist, &showlist);
- disassemble_next_line = AUTO_BOOLEAN_FALSE;
- gdb::option::add_setshow_cmds_for_options
- (class_stack, &user_frame_print_options,
- frame_print_option_defs, &setprintlist, &showprintlist);
- }
|