123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366 |
- /* Memory-access and commands for "inferior" process, for GDB.
- 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 "arch-utils.h"
- #include "symtab.h"
- #include "gdbtypes.h"
- #include "frame.h"
- #include "inferior.h"
- #include "infrun.h"
- #include "gdbsupport/environ.h"
- #include "value.h"
- #include "gdbcmd.h"
- #include "symfile.h"
- #include "gdbcore.h"
- #include "target.h"
- #include "language.h"
- #include "objfiles.h"
- #include "completer.h"
- #include "ui-out.h"
- #include "regcache.h"
- #include "reggroups.h"
- #include "block.h"
- #include "solib.h"
- #include <ctype.h>
- #include "observable.h"
- #include "target-descriptions.h"
- #include "user-regs.h"
- #include "gdbthread.h"
- #include "valprint.h"
- #include "inline-frame.h"
- #include "tracepoint.h"
- #include "inf-loop.h"
- #include "linespec.h"
- #include "thread-fsm.h"
- #include "top.h"
- #include "interps.h"
- #include "skip.h"
- #include "gdbsupport/gdb_optional.h"
- #include "source.h"
- #include "cli/cli-style.h"
- /* Local functions: */
- static void until_next_command (int);
- static void step_1 (int, int, const char *);
- #define ERROR_NO_INFERIOR \
- if (!target_has_execution ()) error (_("The program is not being run."));
- /* Scratch area where string containing arguments to give to the
- program will be stored by 'set args'. As soon as anything is
- stored, notice_args_set will move it into per-inferior storage.
- Arguments are separated by spaces. Empty string (pointer to '\0')
- means no args. */
- static std::string inferior_args_scratch;
- /* Scratch area where the new cwd will be stored by 'set cwd'. */
- static std::string inferior_cwd_scratch;
- /* Scratch area where 'set inferior-tty' will store user-provided value.
- We'll immediate copy it into per-inferior storage. */
- static std::string inferior_io_terminal_scratch;
- /* Pid of our debugged inferior, or 0 if no inferior now.
- Since various parts of infrun.c test this to see whether there is a program
- being debugged it should be nonzero (currently 3 is used) for remote
- debugging. */
- ptid_t inferior_ptid;
- /* Nonzero if stopped due to completion of a stack dummy routine. */
- enum stop_stack_kind stop_stack_dummy;
- /* Nonzero if stopped due to a random (unexpected) signal in inferior
- process. */
- int stopped_by_random_signal;
- static void
- set_inferior_tty_command (const char *args, int from_tty,
- struct cmd_list_element *c)
- {
- /* CLI has assigned the user-provided value to inferior_io_terminal_scratch.
- Now route it to current inferior. */
- current_inferior ()->set_tty (inferior_io_terminal_scratch);
- }
- static void
- show_inferior_tty_command (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- /* Note that we ignore the passed-in value in favor of computing it
- directly. */
- const std::string &inferior_tty = current_inferior ()->tty ();
- gdb_printf (file,
- _("Terminal for future runs of program being debugged "
- "is \"%s\".\n"), inferior_tty.c_str ());
- }
- void
- set_inferior_args_vector (int argc, char **argv)
- {
- gdb::array_view<char * const> args (argv, argc);
- std::string n = construct_inferior_arguments (args);
- current_inferior ()->set_args (std::move (n));
- }
- /* Notice when `set args' is run. */
- static void
- set_args_command (const char *args, int from_tty, struct cmd_list_element *c)
- {
- /* CLI has assigned the user-provided value to inferior_args_scratch.
- Now route it to current inferior. */
- current_inferior ()->set_args (inferior_args_scratch);
- }
- /* Notice when `show args' is run. */
- static void
- show_args_command (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- /* Note that we ignore the passed-in value in favor of computing it
- directly. */
- deprecated_show_value_hack (file, from_tty, c,
- current_inferior ()->args ().c_str ());
- }
- /* See gdbsupport/common-inferior.h. */
- const std::string &
- get_inferior_cwd ()
- {
- return current_inferior ()->cwd ();
- }
- /* Handle the 'set cwd' command. */
- static void
- set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c)
- {
- current_inferior ()->set_cwd (inferior_cwd_scratch);
- }
- /* Handle the 'show cwd' command. */
- static void
- show_cwd_command (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- const std::string &cwd = current_inferior ()->cwd ();
- if (cwd.empty ())
- gdb_printf (file,
- _("\
- You have not set the inferior's current working directory.\n\
- The inferior will inherit GDB's cwd if native debugging, or the remote\n\
- server's cwd if remote debugging.\n"));
- else
- gdb_printf (file,
- _("Current working directory that will be used "
- "when starting the inferior is \"%s\".\n"),
- cwd.c_str ());
- }
- /* This function strips the '&' character (indicating background
- execution) that is added as *the last* of the arguments ARGS of a
- command. A copy of the incoming ARGS without the '&' is returned,
- unless the resulting string after stripping is empty, in which case
- NULL is returned. *BG_CHAR_P is an output boolean that indicates
- whether the '&' character was found. */
- static gdb::unique_xmalloc_ptr<char>
- strip_bg_char (const char *args, int *bg_char_p)
- {
- const char *p;
- if (args == NULL || *args == '\0')
- {
- *bg_char_p = 0;
- return NULL;
- }
- p = args + strlen (args);
- if (p[-1] == '&')
- {
- p--;
- while (p > args && isspace (p[-1]))
- p--;
- *bg_char_p = 1;
- if (p != args)
- return gdb::unique_xmalloc_ptr<char>
- (savestring (args, p - args));
- else
- return gdb::unique_xmalloc_ptr<char> (nullptr);
- }
- *bg_char_p = 0;
- return make_unique_xstrdup (args);
- }
- /* Common actions to take after creating any sort of inferior, by any
- means (running, attaching, connecting, et cetera). The target
- should be stopped. */
- void
- post_create_inferior (int from_tty)
- {
- /* Be sure we own the terminal in case write operations are performed. */
- target_terminal::ours_for_output ();
- /* If the target hasn't taken care of this already, do it now.
- Targets which need to access registers during to_open,
- to_create_inferior, or to_attach should do it earlier; but many
- don't need to. */
- target_find_description ();
- /* Now that we know the register layout, retrieve current PC. But
- if the PC is unavailable (e.g., we're opening a core file with
- missing registers info), ignore it. */
- thread_info *thr = inferior_thread ();
- thr->clear_stop_pc ();
- try
- {
- regcache *rc = get_thread_regcache (thr);
- thr->set_stop_pc (regcache_read_pc (rc));
- }
- catch (const gdb_exception_error &ex)
- {
- if (ex.error != NOT_AVAILABLE_ERROR)
- throw;
- }
- if (current_program_space->exec_bfd ())
- {
- const unsigned solib_add_generation
- = current_program_space->solib_add_generation;
- scoped_restore restore_in_initial_library_scan
- = make_scoped_restore (¤t_inferior ()->in_initial_library_scan,
- true);
- /* Create the hooks to handle shared library load and unload
- events. */
- solib_create_inferior_hook (from_tty);
- if (current_program_space->solib_add_generation == solib_add_generation)
- {
- /* The platform-specific hook should load initial shared libraries,
- but didn't. FROM_TTY will be incorrectly 0 but such solib
- targets should be fixed anyway. Call it only after the solib
- target has been initialized by solib_create_inferior_hook. */
- if (info_verbose)
- warning (_("platform-specific solib_create_inferior_hook did "
- "not load initial shared libraries."));
- /* If the solist is global across processes, there's no need to
- refetch it here. */
- if (!gdbarch_has_global_solist (target_gdbarch ()))
- solib_add (NULL, 0, auto_solib_add);
- }
- }
- /* If the user sets watchpoints before execution having started,
- then she gets software watchpoints, because GDB can't know which
- target will end up being pushed, or if it supports hardware
- watchpoints or not. breakpoint_re_set takes care of promoting
- watchpoints to hardware watchpoints if possible, however, if this
- new inferior doesn't load shared libraries or we don't pull in
- symbols from any other source on this target/arch,
- breakpoint_re_set is never called. Call it now so that software
- watchpoints get a chance to be promoted to hardware watchpoints
- if the now pushed target supports hardware watchpoints. */
- breakpoint_re_set ();
- gdb::observers::inferior_created.notify (current_inferior ());
- }
- /* Kill the inferior if already running. This function is designed
- to be called when we are about to start the execution of the program
- from the beginning. Ask the user to confirm that he wants to restart
- the program being debugged when FROM_TTY is non-null. */
- static void
- kill_if_already_running (int from_tty)
- {
- if (inferior_ptid != null_ptid && target_has_execution ())
- {
- /* Bail out before killing the program if we will not be able to
- restart it. */
- target_require_runnable ();
- if (from_tty
- && !query (_("The program being debugged has been started already.\n\
- Start it from the beginning? ")))
- error (_("Program not restarted."));
- target_kill ();
- }
- }
- /* See inferior.h. */
- void
- prepare_execution_command (struct target_ops *target, int background)
- {
- /* If we get a request for running in the bg but the target
- doesn't support it, error out. */
- if (background && !target_can_async_p (target))
- error (_("Asynchronous execution not supported on this target."));
- if (!background)
- {
- /* If we get a request for running in the fg, then we need to
- simulate synchronous (fg) execution. Note no cleanup is
- necessary for this. stdin is re-enabled whenever an error
- reaches the top level. */
- all_uis_on_sync_execution_starting ();
- }
- }
- /* Determine how the new inferior will behave. */
- enum run_how
- {
- /* Run program without any explicit stop during startup. */
- RUN_NORMAL,
- /* Stop at the beginning of the program's main function. */
- RUN_STOP_AT_MAIN,
- /* Stop at the first instruction of the program. */
- RUN_STOP_AT_FIRST_INSN
- };
- /* Implement the "run" command. Force a stop during program start if
- requested by RUN_HOW. */
- static void
- run_command_1 (const char *args, int from_tty, enum run_how run_how)
- {
- const char *exec_file;
- struct ui_out *uiout = current_uiout;
- struct target_ops *run_target;
- int async_exec;
- dont_repeat ();
- scoped_disable_commit_resumed disable_commit_resumed ("running");
- kill_if_already_running (from_tty);
- init_wait_for_inferior ();
- clear_breakpoint_hit_counts ();
- /* Clean up any leftovers from other runs. Some other things from
- this function should probably be moved into target_pre_inferior. */
- target_pre_inferior (from_tty);
- /* The comment here used to read, "The exec file is re-read every
- time we do a generic_mourn_inferior, so we just have to worry
- about the symbol file." The `generic_mourn_inferior' function
- gets called whenever the program exits. However, suppose the
- program exits, and *then* the executable file changes? We need
- to check again here. Since reopen_exec_file doesn't do anything
- if the timestamp hasn't changed, I don't see the harm. */
- reopen_exec_file ();
- reread_symbols (from_tty);
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
- args = stripped.get ();
- /* Do validation and preparation before possibly changing anything
- in the inferior. */
- run_target = find_run_target ();
- prepare_execution_command (run_target, async_exec);
- if (non_stop && !run_target->supports_non_stop ())
- error (_("The target does not support running in non-stop mode."));
- /* Done. Can now set breakpoints, change inferior args, etc. */
- /* Insert temporary breakpoint in main function if requested. */
- if (run_how == RUN_STOP_AT_MAIN)
- {
- std::string arg = string_printf ("-qualified %s", main_name ());
- tbreak_command (arg.c_str (), 0);
- }
- exec_file = get_exec_file (0);
- /* We keep symbols from add-symbol-file, on the grounds that the
- user might want to add some symbols before running the program
- (right?). But sometimes (dynamic loading where the user manually
- introduces the new symbols with add-symbol-file), the code which
- the symbols describe does not persist between runs. Currently
- the user has to manually nuke all symbols between runs if they
- want them to go away (PR 2207). This is probably reasonable. */
- /* If there were other args, beside '&', process them. */
- if (args != NULL)
- current_inferior ()->set_args (args);
- if (from_tty)
- {
- uiout->field_string (NULL, "Starting program");
- uiout->text (": ");
- if (exec_file)
- uiout->field_string ("execfile", exec_file,
- file_name_style.style ());
- uiout->spaces (1);
- uiout->field_string ("infargs", current_inferior ()->args ());
- uiout->text ("\n");
- uiout->flush ();
- }
- run_target->create_inferior (exec_file,
- current_inferior ()->args (),
- current_inferior ()->environment.envp (),
- from_tty);
- /* to_create_inferior should push the target, so after this point we
- shouldn't refer to run_target again. */
- run_target = NULL;
- /* We're starting off a new process. When we get out of here, in
- non-stop mode, finish the state of all threads of that process,
- but leave other threads alone, as they may be stopped in internal
- events --- the frontend shouldn't see them as stopped. In
- all-stop, always finish the state of all threads, as we may be
- resuming more than just the new process. */
- process_stratum_target *finish_target;
- ptid_t finish_ptid;
- if (non_stop)
- {
- finish_target = current_inferior ()->process_target ();
- finish_ptid = ptid_t (current_inferior ()->pid);
- }
- else
- {
- finish_target = nullptr;
- finish_ptid = minus_one_ptid;
- }
- scoped_finish_thread_state finish_state (finish_target, finish_ptid);
- /* Pass zero for FROM_TTY, because at this point the "run" command
- has done its thing; now we are setting up the running program. */
- post_create_inferior (0);
- /* Queue a pending event so that the program stops immediately. */
- if (run_how == RUN_STOP_AT_FIRST_INSN)
- {
- thread_info *thr = inferior_thread ();
- target_waitstatus ws;
- ws.set_stopped (GDB_SIGNAL_0);
- thr->set_pending_waitstatus (ws);
- }
- /* Start the target running. Do not use -1 continuation as it would skip
- breakpoint right at the entry point. */
- proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0);
- /* Since there was no error, there's no need to finish the thread
- states here. */
- finish_state.release ();
- disable_commit_resumed.reset_and_commit ();
- }
- static void
- run_command (const char *args, int from_tty)
- {
- run_command_1 (args, from_tty, RUN_NORMAL);
- }
- /* Start the execution of the program up until the beginning of the main
- program. */
- static void
- start_command (const char *args, int from_tty)
- {
- /* Some languages such as Ada need to search inside the program
- minimal symbols for the location where to put the temporary
- breakpoint before starting. */
- if (!have_minimal_symbols ())
- error (_("No symbol table loaded. Use the \"file\" command."));
- /* Run the program until reaching the main procedure... */
- run_command_1 (args, from_tty, RUN_STOP_AT_MAIN);
- }
- /* Start the execution of the program stopping at the first
- instruction. */
- static void
- starti_command (const char *args, int from_tty)
- {
- run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN);
- }
- static int
- proceed_thread_callback (struct thread_info *thread, void *arg)
- {
- /* We go through all threads individually instead of compressing
- into a single target `resume_all' request, because some threads
- may be stopped in internal breakpoints/events, or stopped waiting
- for its turn in the displaced stepping queue (that is, they are
- running && !executing). The target side has no idea about why
- the thread is stopped, so a `resume_all' command would resume too
- much. If/when GDB gains a way to tell the target `hold this
- thread stopped until I say otherwise', then we can optimize
- this. */
- if (thread->state != THREAD_STOPPED)
- return 0;
- if (!thread->inf->has_execution ())
- return 0;
- switch_to_thread (thread);
- clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- return 0;
- }
- static void
- ensure_valid_thread (void)
- {
- if (inferior_ptid == null_ptid
- || inferior_thread ()->state == THREAD_EXITED)
- error (_("Cannot execute this command without a live selected thread."));
- }
- /* If the user is looking at trace frames, any resumption of execution
- is likely to mix up recorded and live target data. So simply
- disallow those commands. */
- static void
- ensure_not_tfind_mode (void)
- {
- if (get_traceframe_number () >= 0)
- error (_("Cannot execute this command while looking at trace frames."));
- }
- /* Throw an error indicating the current thread is running. */
- static void
- error_is_running (void)
- {
- error (_("Cannot execute this command while "
- "the selected thread is running."));
- }
- /* Calls error_is_running if the current thread is running. */
- static void
- ensure_not_running (void)
- {
- if (inferior_thread ()->state == THREAD_RUNNING)
- error_is_running ();
- }
- void
- continue_1 (int all_threads)
- {
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- if (non_stop && all_threads)
- {
- /* Don't error out if the current thread is running, because
- there may be other stopped threads. */
- /* Backup current thread and selected frame and restore on scope
- exit. */
- scoped_restore_current_thread restore_thread;
- scoped_disable_commit_resumed disable_commit_resumed
- ("continue all threads in non-stop");
- iterate_over_threads (proceed_thread_callback, NULL);
- if (current_ui->prompt_state == PROMPT_BLOCKED)
- {
- /* If all threads in the target were already running,
- proceed_thread_callback ends up never calling proceed,
- and so nothing calls this to put the inferior's terminal
- settings in effect and remove stdin from the event loop,
- which we must when running a foreground command. E.g.:
- (gdb) c -a&
- Continuing.
- <all threads are running now>
- (gdb) c -a
- Continuing.
- <no thread was resumed, but the inferior now owns the terminal>
- */
- target_terminal::inferior ();
- }
- disable_commit_resumed.reset_and_commit ();
- }
- else
- {
- ensure_valid_thread ();
- ensure_not_running ();
- clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- }
- /* continue [-a] [proceed-count] [&] */
- static void
- continue_command (const char *args, int from_tty)
- {
- int async_exec;
- bool all_threads_p = false;
- ERROR_NO_INFERIOR;
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
- args = stripped.get ();
- if (args != NULL)
- {
- if (startswith (args, "-a"))
- {
- all_threads_p = true;
- args += sizeof ("-a") - 1;
- if (*args == '\0')
- args = NULL;
- }
- }
- if (!non_stop && all_threads_p)
- error (_("`-a' is meaningless in all-stop mode."));
- if (args != NULL && all_threads_p)
- error (_("Can't resume all threads and specify "
- "proceed count simultaneously."));
- /* If we have an argument left, set proceed count of breakpoint we
- stopped at. */
- if (args != NULL)
- {
- bpstat *bs = nullptr;
- int num, stat;
- int stopped = 0;
- struct thread_info *tp;
- if (non_stop)
- tp = inferior_thread ();
- else
- {
- process_stratum_target *last_target;
- ptid_t last_ptid;
- get_last_target_status (&last_target, &last_ptid, nullptr);
- tp = find_thread_ptid (last_target, last_ptid);
- }
- if (tp != NULL)
- bs = tp->control.stop_bpstat;
- while ((stat = bpstat_num (&bs, &num)) != 0)
- if (stat > 0)
- {
- set_ignore_count (num,
- parse_and_eval_long (args) - 1,
- from_tty);
- /* set_ignore_count prints a message ending with a period.
- So print two spaces before "Continuing.". */
- if (from_tty)
- gdb_printf (" ");
- stopped = 1;
- }
- if (!stopped && from_tty)
- {
- gdb_printf
- ("Not stopped at any breakpoint; argument ignored.\n");
- }
- }
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- if (!non_stop || !all_threads_p)
- {
- ensure_valid_thread ();
- ensure_not_running ();
- }
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- if (from_tty)
- gdb_printf (_("Continuing.\n"));
- continue_1 (all_threads_p);
- }
- /* Record in TP the starting point of a "step" or "next" command. */
- static void
- set_step_frame (thread_info *tp)
- {
- /* This can be removed once this function no longer implicitly relies on the
- inferior_ptid value. */
- gdb_assert (inferior_ptid == tp->ptid);
- frame_info *frame = get_current_frame ();
- symtab_and_line sal = find_frame_sal (frame);
- set_step_info (tp, frame, sal);
- CORE_ADDR pc = get_frame_pc (frame);
- tp->control.step_start_function = find_pc_function (pc);
- }
- /* Step until outside of current statement. */
- static void
- step_command (const char *count_string, int from_tty)
- {
- step_1 (0, 0, count_string);
- }
- /* Likewise, but skip over subroutine calls as if single instructions. */
- static void
- next_command (const char *count_string, int from_tty)
- {
- step_1 (1, 0, count_string);
- }
- /* Likewise, but step only one instruction. */
- static void
- stepi_command (const char *count_string, int from_tty)
- {
- step_1 (0, 1, count_string);
- }
- static void
- nexti_command (const char *count_string, int from_tty)
- {
- step_1 (1, 1, count_string);
- }
- /* Data for the FSM that manages the step/next/stepi/nexti
- commands. */
- struct step_command_fsm : public thread_fsm
- {
- /* How many steps left in a "step N"-like command. */
- int count;
- /* If true, this is a next/nexti, otherwise a step/stepi. */
- int skip_subroutines;
- /* If true, this is a stepi/nexti, otherwise a step/step. */
- int single_inst;
- explicit step_command_fsm (struct interp *cmd_interp)
- : thread_fsm (cmd_interp)
- {
- }
- void clean_up (struct thread_info *thread) override;
- bool should_stop (struct thread_info *thread) override;
- enum async_reply_reason do_async_reply_reason () override;
- };
- /* Prepare for a step/next/etc. command. Any target resource
- allocated here is undone in the FSM's clean_up method. */
- static void
- step_command_fsm_prepare (struct step_command_fsm *sm,
- int skip_subroutines, int single_inst,
- int count, struct thread_info *thread)
- {
- sm->skip_subroutines = skip_subroutines;
- sm->single_inst = single_inst;
- sm->count = count;
- /* Leave the si command alone. */
- if (!sm->single_inst || sm->skip_subroutines)
- set_longjmp_breakpoint (thread, get_frame_id (get_current_frame ()));
- thread->control.stepping_command = 1;
- }
- static int prepare_one_step (thread_info *, struct step_command_fsm *sm);
- static void
- step_1 (int skip_subroutines, int single_inst, const char *count_string)
- {
- int count;
- int async_exec;
- struct thread_info *thr;
- struct step_command_fsm *step_sm;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- gdb::unique_xmalloc_ptr<char> stripped
- = strip_bg_char (count_string, &async_exec);
- count_string = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- count = count_string ? parse_and_eval_long (count_string) : 1;
- clear_proceed_status (1);
- /* Setup the execution command state machine to handle all the COUNT
- steps. */
- thr = inferior_thread ();
- step_sm = new step_command_fsm (command_interp ());
- thr->set_thread_fsm (std::unique_ptr<thread_fsm> (step_sm));
- step_command_fsm_prepare (step_sm, skip_subroutines,
- single_inst, count, thr);
- /* Do only one step for now, before returning control to the event
- loop. Let the continuation figure out how many other steps we
- need to do, and handle them one at the time, through
- step_once. */
- if (!prepare_one_step (thr, step_sm))
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- else
- {
- int proceeded;
- /* Stepped into an inline frame. Pretend that we've
- stopped. */
- thr->thread_fsm ()->clean_up (thr);
- proceeded = normal_stop ();
- if (!proceeded)
- inferior_event_handler (INF_EXEC_COMPLETE);
- all_uis_check_sync_execution_done ();
- }
- }
- /* Implementation of the 'should_stop' FSM method for stepping
- commands. Called after we are done with one step operation, to
- check whether we need to step again, before we print the prompt and
- return control to the user. If count is > 1, returns false, as we
- will need to keep going. */
- bool
- step_command_fsm::should_stop (struct thread_info *tp)
- {
- if (tp->control.stop_step)
- {
- /* There are more steps to make, and we did stop due to
- ending a stepping range. Do another step. */
- if (--count > 0)
- return prepare_one_step (tp, this);
- set_finished ();
- }
- return true;
- }
- /* Implementation of the 'clean_up' FSM method for stepping commands. */
- void
- step_command_fsm::clean_up (struct thread_info *thread)
- {
- if (!single_inst || skip_subroutines)
- delete_longjmp_breakpoint (thread->global_num);
- }
- /* Implementation of the 'async_reply_reason' FSM method for stepping
- commands. */
- enum async_reply_reason
- step_command_fsm::do_async_reply_reason ()
- {
- return EXEC_ASYNC_END_STEPPING_RANGE;
- }
- /* Prepare for one step in "step N". The actual target resumption is
- done by the caller. Return true if we're done and should thus
- report a stop to the user. Returns false if the target needs to be
- resumed. */
- static int
- prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
- {
- /* This can be removed once this function no longer implicitly relies on the
- inferior_ptid value. */
- gdb_assert (inferior_ptid == tp->ptid);
- if (sm->count > 0)
- {
- struct frame_info *frame = get_current_frame ();
- set_step_frame (tp);
- if (!sm->single_inst)
- {
- CORE_ADDR pc;
- /* Step at an inlined function behaves like "down". */
- if (!sm->skip_subroutines
- && inline_skipped_frames (tp))
- {
- ptid_t resume_ptid;
- const char *fn = NULL;
- symtab_and_line sal;
- struct symbol *sym;
- /* Pretend that we've ran. */
- resume_ptid = user_visible_resume_ptid (1);
- set_running (tp->inf->process_target (), resume_ptid, true);
- step_into_inline_frame (tp);
- frame = get_current_frame ();
- sal = find_frame_sal (frame);
- sym = get_frame_function (frame);
- if (sym != NULL)
- fn = sym->print_name ();
- if (sal.line == 0
- || !function_name_is_marked_for_skip (fn, sal))
- {
- sm->count--;
- return prepare_one_step (tp, sm);
- }
- }
- pc = get_frame_pc (frame);
- find_pc_line_pc_range (pc,
- &tp->control.step_range_start,
- &tp->control.step_range_end);
- /* There's a problem in gcc (PR gcc/98780) that causes missing line
- table entries, which results in a too large stepping range.
- Use inlined_subroutine info to make the range more narrow. */
- if (inline_skipped_frames (tp) > 0)
- {
- symbol *sym = inline_skipped_symbol (tp);
- if (sym->aclass () == LOC_BLOCK)
- {
- const block *block = SYMBOL_BLOCK_VALUE (sym);
- if (BLOCK_END (block) < tp->control.step_range_end)
- tp->control.step_range_end = BLOCK_END (block);
- }
- }
- tp->control.may_range_step = 1;
- /* If we have no line info, switch to stepi mode. */
- if (tp->control.step_range_end == 0 && step_stop_if_no_debug)
- {
- tp->control.step_range_start = tp->control.step_range_end = 1;
- tp->control.may_range_step = 0;
- }
- else if (tp->control.step_range_end == 0)
- {
- const char *name;
- if (find_pc_partial_function (pc, &name,
- &tp->control.step_range_start,
- &tp->control.step_range_end) == 0)
- error (_("Cannot find bounds of current function"));
- target_terminal::ours_for_output ();
- gdb_printf (_("Single stepping until exit from function %s,"
- "\nwhich has no line number information.\n"),
- name);
- }
- }
- else
- {
- /* Say we are stepping, but stop after one insn whatever it does. */
- tp->control.step_range_start = tp->control.step_range_end = 1;
- if (!sm->skip_subroutines)
- /* It is stepi.
- Don't step over function calls, not even to functions lacking
- line numbers. */
- tp->control.step_over_calls = STEP_OVER_NONE;
- }
- if (sm->skip_subroutines)
- tp->control.step_over_calls = STEP_OVER_ALL;
- return 0;
- }
- /* Done. */
- sm->set_finished ();
- return 1;
- }
- /* Continue program at specified address. */
- static void
- jump_command (const char *arg, int from_tty)
- {
- struct gdbarch *gdbarch = get_current_arch ();
- CORE_ADDR addr;
- struct symbol *fn;
- struct symbol *sfn;
- int async_exec;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
- arg = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- if (!arg)
- error_no_arg (_("starting address"));
- std::vector<symtab_and_line> sals
- = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE);
- if (sals.size () != 1)
- error (_("Unreasonable jump request"));
- symtab_and_line &sal = sals[0];
- if (sal.symtab == 0 && sal.pc == 0)
- error (_("No source file has been specified."));
- resolve_sal_pc (&sal); /* May error out. */
- /* See if we are trying to jump to another function. */
- fn = get_frame_function (get_current_frame ());
- sfn = find_pc_function (sal.pc);
- if (fn != NULL && sfn != fn)
- {
- if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line,
- fn->print_name ()))
- {
- error (_("Not confirmed."));
- /* NOTREACHED */
- }
- }
- if (sfn != NULL)
- {
- struct obj_section *section;
- fixup_symbol_section (sfn, 0);
- section = sfn->obj_section (symbol_objfile (sfn));
- if (section_is_overlay (section)
- && !section_is_mapped (section))
- {
- if (!query (_("WARNING!!! Destination is in "
- "unmapped overlay! Jump anyway? ")))
- {
- error (_("Not confirmed."));
- /* NOTREACHED */
- }
- }
- }
- addr = sal.pc;
- if (from_tty)
- {
- gdb_printf (_("Continuing at "));
- gdb_puts (paddress (gdbarch, addr));
- gdb_printf (".\n");
- }
- clear_proceed_status (0);
- proceed (addr, GDB_SIGNAL_0);
- }
- /* Continue program giving it specified signal. */
- static void
- signal_command (const char *signum_exp, int from_tty)
- {
- enum gdb_signal oursig;
- int async_exec;
- dont_repeat (); /* Too dangerous. */
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped
- = strip_bg_char (signum_exp, &async_exec);
- signum_exp = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- if (!signum_exp)
- error_no_arg (_("signal number"));
- /* It would be even slicker to make signal names be valid expressions,
- (the type could be "enum $signal" or some such), then the user could
- assign them to convenience variables. */
- oursig = gdb_signal_from_name (signum_exp);
- if (oursig == GDB_SIGNAL_UNKNOWN)
- {
- /* No, try numeric. */
- int num = parse_and_eval_long (signum_exp);
- if (num == 0)
- oursig = GDB_SIGNAL_0;
- else
- oursig = gdb_signal_from_command (num);
- }
- /* Look for threads other than the current that this command ends up
- resuming too (due to schedlock off), and warn if they'll get a
- signal delivered. "signal 0" is used to suppress a previous
- signal, but if the current thread is no longer the one that got
- the signal, then the user is potentially suppressing the signal
- of the wrong thread. */
- if (!non_stop)
- {
- int must_confirm = 0;
- /* This indicates what will be resumed. Either a single thread,
- a whole process, or all threads of all processes. */
- ptid_t resume_ptid = user_visible_resume_ptid (0);
- process_stratum_target *resume_target
- = user_visible_resume_target (resume_ptid);
- thread_info *current = inferior_thread ();
- for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
- {
- if (tp == current)
- continue;
- if (tp->stop_signal () != GDB_SIGNAL_0
- && signal_pass_state (tp->stop_signal ()))
- {
- if (!must_confirm)
- gdb_printf (_("Note:\n"));
- gdb_printf (_(" Thread %s previously stopped with signal %s, %s.\n"),
- print_thread_id (tp),
- gdb_signal_to_name (tp->stop_signal ()),
- gdb_signal_to_string (tp->stop_signal ()));
- must_confirm = 1;
- }
- }
- if (must_confirm
- && !query (_("Continuing thread %s (the current thread) with specified signal will\n"
- "still deliver the signals noted above to their respective threads.\n"
- "Continue anyway? "),
- print_thread_id (inferior_thread ())))
- error (_("Not confirmed."));
- }
- if (from_tty)
- {
- if (oursig == GDB_SIGNAL_0)
- gdb_printf (_("Continuing with no signal.\n"));
- else
- gdb_printf (_("Continuing with signal %s.\n"),
- gdb_signal_to_name (oursig));
- }
- clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, oursig);
- }
- /* Queue a signal to be delivered to the current thread. */
- static void
- queue_signal_command (const char *signum_exp, int from_tty)
- {
- enum gdb_signal oursig;
- struct thread_info *tp;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- if (signum_exp == NULL)
- error_no_arg (_("signal number"));
- /* It would be even slicker to make signal names be valid expressions,
- (the type could be "enum $signal" or some such), then the user could
- assign them to convenience variables. */
- oursig = gdb_signal_from_name (signum_exp);
- if (oursig == GDB_SIGNAL_UNKNOWN)
- {
- /* No, try numeric. */
- int num = parse_and_eval_long (signum_exp);
- if (num == 0)
- oursig = GDB_SIGNAL_0;
- else
- oursig = gdb_signal_from_command (num);
- }
- if (oursig != GDB_SIGNAL_0
- && !signal_pass_state (oursig))
- error (_("Signal handling set to not pass this signal to the program."));
- tp = inferior_thread ();
- tp->set_stop_signal (oursig);
- }
- /* Data for the FSM that manages the until (with no argument)
- command. */
- struct until_next_fsm : public thread_fsm
- {
- /* The thread that as current when the command was executed. */
- int thread;
- until_next_fsm (struct interp *cmd_interp, int thread)
- : thread_fsm (cmd_interp),
- thread (thread)
- {
- }
- bool should_stop (struct thread_info *thread) override;
- void clean_up (struct thread_info *thread) override;
- enum async_reply_reason do_async_reply_reason () override;
- };
- /* Implementation of the 'should_stop' FSM method for the until (with
- no arg) command. */
- bool
- until_next_fsm::should_stop (struct thread_info *tp)
- {
- if (tp->control.stop_step)
- set_finished ();
- return true;
- }
- /* Implementation of the 'clean_up' FSM method for the until (with no
- arg) command. */
- void
- until_next_fsm::clean_up (struct thread_info *thread)
- {
- delete_longjmp_breakpoint (thread->global_num);
- }
- /* Implementation of the 'async_reply_reason' FSM method for the until
- (with no arg) command. */
- enum async_reply_reason
- until_next_fsm::do_async_reply_reason ()
- {
- return EXEC_ASYNC_END_STEPPING_RANGE;
- }
- /* Proceed until we reach a different source line with pc greater than
- our current one or exit the function. We skip calls in both cases.
- Note that eventually this command should probably be changed so
- that only source lines are printed out when we hit the breakpoint
- we set. This may involve changes to wait_for_inferior and the
- proceed status code. */
- static void
- until_next_command (int from_tty)
- {
- struct frame_info *frame;
- CORE_ADDR pc;
- struct symbol *func;
- struct symtab_and_line sal;
- struct thread_info *tp = inferior_thread ();
- int thread = tp->global_num;
- struct until_next_fsm *sm;
- clear_proceed_status (0);
- set_step_frame (tp);
- frame = get_current_frame ();
- /* Step until either exited from this function or greater
- than the current line (if in symbolic section) or pc (if
- not). */
- pc = get_frame_pc (frame);
- func = find_pc_function (pc);
- if (!func)
- {
- struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
- if (msymbol.minsym == NULL)
- error (_("Execution is not within a known function."));
- tp->control.step_range_start = BMSYMBOL_VALUE_ADDRESS (msymbol);
- /* The upper-bound of step_range is exclusive. In order to make PC
- within the range, set the step_range_end with PC + 1. */
- tp->control.step_range_end = pc + 1;
- }
- else
- {
- sal = find_pc_line (pc, 0);
- tp->control.step_range_start = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func));
- tp->control.step_range_end = sal.end;
- /* By setting the step_range_end based on the current pc, we are
- assuming that the last line table entry for any given source line
- will have is_stmt set to true. This is not necessarily the case,
- there may be additional entries for the same source line with
- is_stmt set false. Consider the following code:
- for (int i = 0; i < 10; i++)
- loop_body ();
- Clang-13, will generate multiple line table entries at the end of
- the loop all associated with the 'for' line. The first of these
- entries is marked is_stmt true, but the other entries are is_stmt
- false.
- If we only use the values in SAL, then our stepping range may not
- extend to the end of the loop. The until command will reach the
- end of the range, find a non is_stmt instruction, and step to the
- next is_stmt instruction. This stopping point, however, will be
- inside the loop, which is not what we wanted.
- Instead, we now check any subsequent line table entries to see if
- they are for the same line. If they are, and they are marked
- is_stmt false, then we extend the end of our stepping range.
- When we finish this process the end of the stepping range will
- point either to a line with a different line number, or, will
- point at an address for the same line number that is marked as a
- statement. */
- struct symtab_and_line final_sal
- = find_pc_line (tp->control.step_range_end, 0);
- while (final_sal.line == sal.line && final_sal.symtab == sal.symtab
- && !final_sal.is_stmt)
- {
- tp->control.step_range_end = final_sal.end;
- final_sal = find_pc_line (final_sal.end, 0);
- }
- }
- tp->control.may_range_step = 1;
- tp->control.step_over_calls = STEP_OVER_ALL;
- set_longjmp_breakpoint (tp, get_frame_id (frame));
- delete_longjmp_breakpoint_cleanup lj_deleter (thread);
- sm = new until_next_fsm (command_interp (), tp->global_num);
- tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm));
- lj_deleter.release ();
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- static void
- until_command (const char *arg, int from_tty)
- {
- int async_exec;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
- arg = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- if (arg)
- until_break_command (arg, from_tty, 0);
- else
- until_next_command (from_tty);
- }
- static void
- advance_command (const char *arg, int from_tty)
- {
- int async_exec;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- if (arg == NULL)
- error_no_arg (_("a location"));
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
- arg = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- until_break_command (arg, from_tty, 1);
- }
- /* See inferior.h. */
- struct value *
- get_return_value (struct symbol *func_symbol, struct value *function)
- {
- regcache *stop_regs = get_current_regcache ();
- struct gdbarch *gdbarch = stop_regs->arch ();
- struct value *value;
- struct type *value_type
- = check_typedef (TYPE_TARGET_TYPE (func_symbol->type ()));
- gdb_assert (value_type->code () != TYPE_CODE_VOID);
- if (is_nocall_function (check_typedef (::value_type (function))))
- {
- warning (_("Function '%s' does not follow the target calling "
- "convention, cannot determine its returned value."),
- func_symbol->print_name ());
- return nullptr;
- }
- /* FIXME: 2003-09-27: When returning from a nested inferior function
- call, it's possible (with no help from the architecture vector)
- to locate and return/print a "struct return" value. This is just
- a more complicated case of what is already being done in the
- inferior function call code. In fact, when inferior function
- calls are made async, this will likely be made the norm. */
- switch (gdbarch_return_value (gdbarch, function, value_type,
- NULL, NULL, NULL))
- {
- case RETURN_VALUE_REGISTER_CONVENTION:
- case RETURN_VALUE_ABI_RETURNS_ADDRESS:
- case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
- value = allocate_value (value_type);
- gdbarch_return_value (gdbarch, function, value_type, stop_regs,
- value_contents_raw (value).data (), NULL);
- break;
- case RETURN_VALUE_STRUCT_CONVENTION:
- value = NULL;
- break;
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
- return value;
- }
- /* The captured function return value/type and its position in the
- value history. */
- struct return_value_info
- {
- /* The captured return value. May be NULL if we weren't able to
- retrieve it. See get_return_value. */
- struct value *value;
- /* The return type. In some cases, we'll not be able extract the
- return value, but we always know the type. */
- struct type *type;
- /* If we captured a value, this is the value history index. */
- int value_history_index;
- };
- /* Helper for print_return_value. */
- static void
- print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv)
- {
- if (rv->value != NULL)
- {
- struct value_print_options opts;
- /* Print it. */
- uiout->text ("Value returned is ");
- uiout->field_fmt ("gdb-result-var", "$%d",
- rv->value_history_index);
- uiout->text (" = ");
- get_user_print_options (&opts);
- if (opts.finish_print)
- {
- string_file stb;
- value_print (rv->value, &stb, &opts);
- uiout->field_stream ("return-value", stb);
- }
- else
- uiout->field_string ("return-value", _("<not displayed>"),
- metadata_style.style ());
- uiout->text ("\n");
- }
- else
- {
- std::string type_name = type_to_string (rv->type);
- uiout->text ("Value returned has type: ");
- uiout->field_string ("return-type", type_name);
- uiout->text (".");
- uiout->text (" Cannot determine contents\n");
- }
- }
- /* Print the result of a function at the end of a 'finish' command.
- RV points at an object representing the captured return value/type
- and its position in the value history. */
- void
- print_return_value (struct ui_out *uiout, struct return_value_info *rv)
- {
- if (rv->type == NULL
- || check_typedef (rv->type)->code () == TYPE_CODE_VOID)
- return;
- try
- {
- /* print_return_value_1 can throw an exception in some
- circumstances. We need to catch this so that we still
- delete the breakpoint. */
- print_return_value_1 (uiout, rv);
- }
- catch (const gdb_exception &ex)
- {
- exception_print (gdb_stdout, ex);
- }
- }
- /* Data for the FSM that manages the finish command. */
- struct finish_command_fsm : public thread_fsm
- {
- /* The momentary breakpoint set at the function's return address in
- the caller. */
- breakpoint_up breakpoint;
- /* The function that we're stepping out of. */
- struct symbol *function = nullptr;
- /* If the FSM finishes successfully, this stores the function's
- return value. */
- struct return_value_info return_value_info {};
- explicit finish_command_fsm (struct interp *cmd_interp)
- : thread_fsm (cmd_interp)
- {
- }
- bool should_stop (struct thread_info *thread) override;
- void clean_up (struct thread_info *thread) override;
- struct return_value_info *return_value () override;
- enum async_reply_reason do_async_reply_reason () override;
- };
- /* Implementation of the 'should_stop' FSM method for the finish
- commands. Detects whether the thread stepped out of the function
- successfully, and if so, captures the function's return value and
- marks the FSM finished. */
- bool
- finish_command_fsm::should_stop (struct thread_info *tp)
- {
- struct return_value_info *rv = &return_value_info;
- if (function != NULL
- && bpstat_find_breakpoint (tp->control.stop_bpstat,
- breakpoint.get ()) != NULL)
- {
- /* We're done. */
- set_finished ();
- rv->type = TYPE_TARGET_TYPE (function->type ());
- if (rv->type == NULL)
- internal_error (__FILE__, __LINE__,
- _("finish_command: function has no target type"));
- if (check_typedef (rv->type)->code () != TYPE_CODE_VOID)
- {
- struct value *func;
- func = read_var_value (function, NULL, get_current_frame ());
- rv->value = get_return_value (function, func);
- if (rv->value != NULL)
- rv->value_history_index = record_latest_value (rv->value);
- }
- }
- else if (tp->control.stop_step)
- {
- /* Finishing from an inline frame, or reverse finishing. In
- either case, there's no way to retrieve the return value. */
- set_finished ();
- }
- return true;
- }
- /* Implementation of the 'clean_up' FSM method for the finish
- commands. */
- void
- finish_command_fsm::clean_up (struct thread_info *thread)
- {
- breakpoint.reset ();
- delete_longjmp_breakpoint (thread->global_num);
- }
- /* Implementation of the 'return_value' FSM method for the finish
- commands. */
- struct return_value_info *
- finish_command_fsm::return_value ()
- {
- return &return_value_info;
- }
- /* Implementation of the 'async_reply_reason' FSM method for the
- finish commands. */
- enum async_reply_reason
- finish_command_fsm::do_async_reply_reason ()
- {
- if (execution_direction == EXEC_REVERSE)
- return EXEC_ASYNC_END_STEPPING_RANGE;
- else
- return EXEC_ASYNC_FUNCTION_FINISHED;
- }
- /* finish_backward -- helper function for finish_command. */
- static void
- finish_backward (struct finish_command_fsm *sm)
- {
- struct symtab_and_line sal;
- struct thread_info *tp = inferior_thread ();
- CORE_ADDR pc;
- CORE_ADDR func_addr;
- pc = get_frame_pc (get_current_frame ());
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0)
- error (_("Cannot find bounds of current function"));
- sal = find_pc_line (func_addr, 0);
- tp->control.proceed_to_finish = 1;
- /* Special case: if we're sitting at the function entry point,
- then all we need to do is take a reverse singlestep. We
- don't need to set a breakpoint, and indeed it would do us
- no good to do so.
- Note that this can only happen at frame #0, since there's
- no way that a function up the stack can have a return address
- that's equal to its entry point. */
- if (sal.pc != pc)
- {
- struct frame_info *frame = get_selected_frame (NULL);
- struct gdbarch *gdbarch = get_frame_arch (frame);
- /* Set a step-resume at the function's entry point. Once that's
- hit, we'll do one more step backwards. */
- symtab_and_line sr_sal;
- sr_sal.pc = sal.pc;
- sr_sal.pspace = get_frame_program_space (frame);
- insert_step_resume_breakpoint_at_sal (gdbarch,
- sr_sal, null_frame_id);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- else
- {
- /* We're almost there -- we just need to back up by one more
- single-step. */
- tp->control.step_range_start = tp->control.step_range_end = 1;
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- }
- /* finish_forward -- helper function for finish_command. FRAME is the
- frame that called the function we're about to step out of. */
- static void
- finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
- {
- struct frame_id frame_id = get_frame_id (frame);
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct symtab_and_line sal;
- struct thread_info *tp = inferior_thread ();
- sal = find_pc_line (get_frame_pc (frame), 0);
- sal.pc = get_frame_pc (frame);
- sm->breakpoint = set_momentary_breakpoint (gdbarch, sal,
- get_stack_frame_id (frame),
- bp_finish);
- /* set_momentary_breakpoint invalidates FRAME. */
- frame = NULL;
- set_longjmp_breakpoint (tp, frame_id);
- /* We want to print return value, please... */
- tp->control.proceed_to_finish = 1;
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- /* Skip frames for "finish". */
- static struct frame_info *
- skip_finish_frames (struct frame_info *frame)
- {
- struct frame_info *start;
- do
- {
- start = frame;
- frame = skip_tailcall_frames (frame);
- if (frame == NULL)
- break;
- frame = skip_unwritable_frames (frame);
- if (frame == NULL)
- break;
- }
- while (start != frame);
- return frame;
- }
- /* "finish": Set a temporary breakpoint at the place the selected
- frame will return to, then continue. */
- static void
- finish_command (const char *arg, int from_tty)
- {
- struct frame_info *frame;
- int async_exec;
- struct finish_command_fsm *sm;
- struct thread_info *tp;
- ERROR_NO_INFERIOR;
- ensure_not_tfind_mode ();
- ensure_valid_thread ();
- ensure_not_running ();
- /* Find out whether we must run in the background. */
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
- arg = stripped.get ();
- prepare_execution_command (current_inferior ()->top_target (), async_exec);
- if (arg)
- error (_("The \"finish\" command does not take any arguments."));
- frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
- if (frame == 0)
- error (_("\"finish\" not meaningful in the outermost frame."));
- clear_proceed_status (0);
- tp = inferior_thread ();
- sm = new finish_command_fsm (command_interp ());
- tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm));
- /* Finishing from an inline frame is completely different. We don't
- try to show the "return value" - no way to locate it. */
- if (get_frame_type (get_selected_frame (_("No selected frame.")))
- == INLINE_FRAME)
- {
- /* Claim we are stepping in the calling frame. An empty step
- range means that we will stop once we aren't in a function
- called by that frame. We don't use the magic "1" value for
- step_range_end, because then infrun will think this is nexti,
- and not step over the rest of this inlined function call. */
- set_step_info (tp, frame, {});
- tp->control.step_range_start = get_frame_pc (frame);
- tp->control.step_range_end = tp->control.step_range_start;
- tp->control.step_over_calls = STEP_OVER_ALL;
- /* Print info on the selected frame, including level number but not
- source. */
- if (from_tty)
- {
- gdb_printf (_("Run till exit from "));
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
- }
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- return;
- }
- /* Find the function we will return from. */
- sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
- /* Print info on the selected frame, including level number but not
- source. */
- if (from_tty)
- {
- if (execution_direction == EXEC_REVERSE)
- gdb_printf (_("Run back to call of "));
- else
- {
- if (sm->function != NULL && TYPE_NO_RETURN (sm->function->type ())
- && !query (_("warning: Function %s does not return normally.\n"
- "Try to finish anyway? "),
- sm->function->print_name ()))
- error (_("Not confirmed."));
- gdb_printf (_("Run till exit from "));
- }
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
- }
- if (execution_direction == EXEC_REVERSE)
- finish_backward (sm);
- else
- {
- frame = skip_finish_frames (frame);
- if (frame == NULL)
- error (_("Cannot find the caller frame."));
- finish_forward (sm, frame);
- }
- }
- static void
- info_program_command (const char *args, int from_tty)
- {
- bpstat *bs;
- int num, stat;
- ptid_t ptid;
- process_stratum_target *proc_target;
- if (!target_has_execution ())
- {
- gdb_printf (_("The program being debugged is not being run.\n"));
- return;
- }
- if (non_stop)
- {
- ptid = inferior_ptid;
- proc_target = current_inferior ()->process_target ();
- }
- else
- get_last_target_status (&proc_target, &ptid, nullptr);
- if (ptid == null_ptid || ptid == minus_one_ptid)
- error (_("No selected thread."));
- thread_info *tp = find_thread_ptid (proc_target, ptid);
- if (tp->state == THREAD_EXITED)
- error (_("Invalid selected thread."));
- else if (tp->state == THREAD_RUNNING)
- error (_("Selected thread is running."));
- bs = tp->control.stop_bpstat;
- stat = bpstat_num (&bs, &num);
- target_files_info ();
- gdb_printf (_("Program stopped at %s.\n"),
- paddress (target_gdbarch (), tp->stop_pc ()));
- if (tp->control.stop_step)
- gdb_printf (_("It stopped after being stepped.\n"));
- else if (stat != 0)
- {
- /* There may be several breakpoints in the same place, so this
- isn't as strange as it seems. */
- while (stat != 0)
- {
- if (stat < 0)
- {
- gdb_printf (_("It stopped at a breakpoint "
- "that has since been deleted.\n"));
- }
- else
- gdb_printf (_("It stopped at breakpoint %d.\n"), num);
- stat = bpstat_num (&bs, &num);
- }
- }
- else if (tp->stop_signal () != GDB_SIGNAL_0)
- {
- gdb_printf (_("It stopped with signal %s, %s.\n"),
- gdb_signal_to_name (tp->stop_signal ()),
- gdb_signal_to_string (tp->stop_signal ()));
- }
- if (from_tty)
- {
- gdb_printf (_("Type \"info stack\" or \"info "
- "registers\" for more information.\n"));
- }
- }
- static void
- environment_info (const char *var, int from_tty)
- {
- if (var)
- {
- const char *val = current_inferior ()->environment.get (var);
- if (val)
- {
- gdb_puts (var);
- gdb_puts (" = ");
- gdb_puts (val);
- gdb_puts ("\n");
- }
- else
- {
- gdb_puts ("Environment variable \"");
- gdb_puts (var);
- gdb_puts ("\" not defined.\n");
- }
- }
- else
- {
- char **envp = current_inferior ()->environment.envp ();
- for (int idx = 0; envp[idx] != NULL; ++idx)
- {
- gdb_puts (envp[idx]);
- gdb_puts ("\n");
- }
- }
- }
- static void
- set_environment_command (const char *arg, int from_tty)
- {
- const char *p, *val;
- int nullset = 0;
- if (arg == 0)
- error_no_arg (_("environment variable and value"));
- /* Find separation between variable name and value. */
- p = (char *) strchr (arg, '=');
- val = (char *) strchr (arg, ' ');
- if (p != 0 && val != 0)
- {
- /* We have both a space and an equals. If the space is before the
- equals, walk forward over the spaces til we see a nonspace
- (possibly the equals). */
- if (p > val)
- while (*val == ' ')
- val++;
- /* Now if the = is after the char following the spaces,
- take the char following the spaces. */
- if (p > val)
- p = val - 1;
- }
- else if (val != 0 && p == 0)
- p = val;
- if (p == arg)
- error_no_arg (_("environment variable to set"));
- if (p == 0 || p[1] == 0)
- {
- nullset = 1;
- if (p == 0)
- p = arg + strlen (arg); /* So that savestring below will work. */
- }
- else
- {
- /* Not setting variable value to null. */
- val = p + 1;
- while (*val == ' ' || *val == '\t')
- val++;
- }
- while (p != arg && (p[-1] == ' ' || p[-1] == '\t'))
- p--;
- std::string var (arg, p - arg);
- if (nullset)
- {
- gdb_printf (_("Setting environment variable "
- "\"%s\" to null value.\n"),
- var.c_str ());
- current_inferior ()->environment.set (var.c_str (), "");
- }
- else
- current_inferior ()->environment.set (var.c_str (), val);
- }
- static void
- unset_environment_command (const char *var, int from_tty)
- {
- if (var == 0)
- {
- /* If there is no argument, delete all environment variables.
- Ask for confirmation if reading from the terminal. */
- if (!from_tty || query (_("Delete all environment variables? ")))
- current_inferior ()->environment.clear ();
- }
- else
- current_inferior ()->environment.unset (var);
- }
- /* Handle the execution path (PATH variable). */
- static const char path_var_name[] = "PATH";
- static void
- path_info (const char *args, int from_tty)
- {
- gdb_puts ("Executable and object file path: ");
- gdb_puts (current_inferior ()->environment.get (path_var_name));
- gdb_puts ("\n");
- }
- /* Add zero or more directories to the front of the execution path. */
- static void
- path_command (const char *dirname, int from_tty)
- {
- const char *env;
- dont_repeat ();
- env = current_inferior ()->environment.get (path_var_name);
- /* Can be null if path is not set. */
- if (!env)
- env = "";
- std::string exec_path = env;
- mod_path (dirname, exec_path);
- current_inferior ()->environment.set (path_var_name, exec_path.c_str ());
- if (from_tty)
- path_info (NULL, from_tty);
- }
- static void
- pad_to_column (string_file &stream, int col)
- {
- /* At least one space must be printed to separate columns. */
- stream.putc (' ');
- const int size = stream.size ();
- if (size < col)
- stream.puts (n_spaces (col - size));
- }
- /* Print out the register NAME with value VAL, to FILE, in the default
- fashion. */
- static void
- default_print_one_register_info (struct ui_file *file,
- const char *name,
- struct value *val)
- {
- struct type *regtype = value_type (val);
- int print_raw_format;
- string_file format_stream;
- enum tab_stops
- {
- value_column_1 = 15,
- /* Give enough room for "0x", 16 hex digits and two spaces in
- preceding column. */
- value_column_2 = value_column_1 + 2 + 16 + 2,
- };
- format_stream.puts (name);
- pad_to_column (format_stream, value_column_1);
- print_raw_format = (value_entirely_available (val)
- && !value_optimized_out (val));
- /* If virtual format is floating, print it that way, and in raw
- hex. */
- if (regtype->code () == TYPE_CODE_FLT
- || regtype->code () == TYPE_CODE_DECFLOAT)
- {
- struct value_print_options opts;
- const gdb_byte *valaddr = value_contents_for_printing (val).data ();
- enum bfd_endian byte_order = type_byte_order (regtype);
- get_user_print_options (&opts);
- opts.deref_ref = 1;
- common_val_print (val, &format_stream, 0, &opts, current_language);
- if (print_raw_format)
- {
- pad_to_column (format_stream, value_column_2);
- format_stream.puts ("(raw ");
- print_hex_chars (&format_stream, valaddr, TYPE_LENGTH (regtype),
- byte_order, true);
- format_stream.putc (')');
- }
- }
- else
- {
- struct value_print_options opts;
- /* Print the register in hex. */
- get_formatted_print_options (&opts, 'x');
- opts.deref_ref = 1;
- common_val_print (val, &format_stream, 0, &opts, current_language);
- /* If not a vector register, print it also according to its
- natural format. */
- if (print_raw_format && regtype->is_vector () == 0)
- {
- pad_to_column (format_stream, value_column_2);
- get_user_print_options (&opts);
- opts.deref_ref = 1;
- common_val_print (val, &format_stream, 0, &opts, current_language);
- }
- }
- gdb_puts (format_stream.c_str (), file);
- gdb_printf (file, "\n");
- }
- /* Print out the machine register regnum. If regnum is -1, print all
- registers (print_all == 1) or all non-float and non-vector
- registers (print_all == 0).
- For most machines, having all_registers_info() print the
- register(s) one per line is good enough. If a different format is
- required, (eg, for MIPS or Pyramid 90x, which both have lots of
- regs), or there is an existing convention for showing all the
- registers, define the architecture method PRINT_REGISTERS_INFO to
- provide that format. */
- void
- default_print_registers_info (struct gdbarch *gdbarch,
- struct ui_file *file,
- struct frame_info *frame,
- int regnum, int print_all)
- {
- int i;
- const int numregs = gdbarch_num_cooked_regs (gdbarch);
- for (i = 0; i < numregs; i++)
- {
- /* Decide between printing all regs, non-float / vector regs, or
- specific reg. */
- if (regnum == -1)
- {
- if (print_all)
- {
- if (!gdbarch_register_reggroup_p (gdbarch, i, all_reggroup))
- continue;
- }
- else
- {
- if (!gdbarch_register_reggroup_p (gdbarch, i, general_reggroup))
- continue;
- }
- }
- else
- {
- if (i != regnum)
- continue;
- }
- /* If the register name is empty, it is undefined for this
- processor, so don't display anything. */
- if (gdbarch_register_name (gdbarch, i) == NULL
- || *(gdbarch_register_name (gdbarch, i)) == '\0')
- continue;
- default_print_one_register_info (file,
- gdbarch_register_name (gdbarch, i),
- value_of_register (i, frame));
- }
- }
- void
- registers_info (const char *addr_exp, int fpregs)
- {
- struct frame_info *frame;
- struct gdbarch *gdbarch;
- if (!target_has_registers ())
- error (_("The program has no registers now."));
- frame = get_selected_frame (NULL);
- gdbarch = get_frame_arch (frame);
- if (!addr_exp)
- {
- gdbarch_print_registers_info (gdbarch, gdb_stdout,
- frame, -1, fpregs);
- return;
- }
- while (*addr_exp != '\0')
- {
- const char *start;
- const char *end;
- /* Skip leading white space. */
- addr_exp = skip_spaces (addr_exp);
- /* Discard any leading ``$''. Check that there is something
- resembling a register following it. */
- if (addr_exp[0] == '$')
- addr_exp++;
- if (isspace ((*addr_exp)) || (*addr_exp) == '\0')
- error (_("Missing register name"));
- /* Find the start/end of this register name/num/group. */
- start = addr_exp;
- while ((*addr_exp) != '\0' && !isspace ((*addr_exp)))
- addr_exp++;
- end = addr_exp;
- /* Figure out what we've found and display it. */
- /* A register name? */
- {
- int regnum = user_reg_map_name_to_regnum (gdbarch, start, end - start);
- if (regnum >= 0)
- {
- /* User registers lie completely outside of the range of
- normal registers. Catch them early so that the target
- never sees them. */
- if (regnum >= gdbarch_num_cooked_regs (gdbarch))
- {
- struct value *regval = value_of_user_reg (regnum, frame);
- const char *regname = user_reg_map_regnum_to_name (gdbarch,
- regnum);
- /* Print in the same fashion
- gdbarch_print_registers_info's default
- implementation prints. */
- default_print_one_register_info (gdb_stdout,
- regname,
- regval);
- }
- else
- gdbarch_print_registers_info (gdbarch, gdb_stdout,
- frame, regnum, fpregs);
- continue;
- }
- }
- /* A register group? */
- {
- const struct reggroup *group = nullptr;
- for (const struct reggroup *g : gdbarch_reggroups (gdbarch))
- {
- /* Don't bother with a length check. Should the user
- enter a short register group name, go with the first
- group that matches. */
- if (strncmp (start, g->name (), end - start) == 0)
- {
- group = g;
- break;
- }
- }
- if (group != NULL)
- {
- int regnum;
- for (regnum = 0;
- regnum < gdbarch_num_cooked_regs (gdbarch);
- regnum++)
- {
- if (gdbarch_register_reggroup_p (gdbarch, regnum, group))
- gdbarch_print_registers_info (gdbarch,
- gdb_stdout, frame,
- regnum, fpregs);
- }
- continue;
- }
- }
- /* Nothing matched. */
- error (_("Invalid register `%.*s'"), (int) (end - start), start);
- }
- }
- static void
- info_all_registers_command (const char *addr_exp, int from_tty)
- {
- registers_info (addr_exp, 1);
- }
- static void
- info_registers_command (const char *addr_exp, int from_tty)
- {
- registers_info (addr_exp, 0);
- }
- static void
- print_vector_info (struct ui_file *file,
- struct frame_info *frame, const char *args)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- if (gdbarch_print_vector_info_p (gdbarch))
- gdbarch_print_vector_info (gdbarch, file, frame, args);
- else
- {
- int regnum;
- int printed_something = 0;
- for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
- {
- if (gdbarch_register_reggroup_p (gdbarch, regnum, vector_reggroup))
- {
- printed_something = 1;
- gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
- }
- }
- if (!printed_something)
- gdb_printf (file, "No vector information\n");
- }
- }
- static void
- info_vector_command (const char *args, int from_tty)
- {
- if (!target_has_registers ())
- error (_("The program has no registers now."));
- print_vector_info (gdb_stdout, get_selected_frame (NULL), args);
- }
- /* Kill the inferior process. Make us have no inferior. */
- static void
- kill_command (const char *arg, int from_tty)
- {
- /* FIXME: This should not really be inferior_ptid (or target_has_execution).
- It should be a distinct flag that indicates that a target is active, cuz
- some targets don't have processes! */
- if (inferior_ptid == null_ptid)
- error (_("The program is not being run."));
- if (!query (_("Kill the program being debugged? ")))
- error (_("Not confirmed."));
- int pid = current_inferior ()->pid;
- /* Save the pid as a string before killing the inferior, since that
- may unpush the current target, and we need the string after. */
- std::string pid_str = target_pid_to_str (ptid_t (pid));
- int infnum = current_inferior ()->num;
- target_kill ();
- bfd_cache_close_all ();
- if (print_inferior_events)
- gdb_printf (_("[Inferior %d (%s) killed]\n"),
- infnum, pid_str.c_str ());
- }
- /* Used in `attach&' command. Proceed threads of inferior INF iff
- they stopped due to debugger request, and when they did, they
- reported a clean stop (GDB_SIGNAL_0). Do not proceed threads that
- have been explicitly been told to stop. */
- static void
- proceed_after_attach (inferior *inf)
- {
- /* Don't error out if the current thread is running, because
- there may be other stopped threads. */
- /* Backup current thread and selected frame. */
- scoped_restore_current_thread restore_thread;
- for (thread_info *thread : inf->non_exited_threads ())
- if (!thread->executing ()
- && !thread->stop_requested
- && thread->stop_signal () == GDB_SIGNAL_0)
- {
- switch_to_thread (thread);
- clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- }
- /* See inferior.h. */
- void
- setup_inferior (int from_tty)
- {
- struct inferior *inferior;
- inferior = current_inferior ();
- inferior->needs_setup = 0;
- /* If no exec file is yet known, try to determine it from the
- process itself. */
- if (get_exec_file (0) == NULL)
- exec_file_locate_attach (inferior_ptid.pid (), 1, from_tty);
- else
- {
- reopen_exec_file ();
- reread_symbols (from_tty);
- }
- /* Take any necessary post-attaching actions for this platform. */
- target_post_attach (inferior_ptid.pid ());
- post_create_inferior (from_tty);
- }
- /* What to do after the first program stops after attaching. */
- enum attach_post_wait_mode
- {
- /* Do nothing. Leaves threads as they are. */
- ATTACH_POST_WAIT_NOTHING,
- /* Re-resume threads that are marked running. */
- ATTACH_POST_WAIT_RESUME,
- /* Stop all threads. */
- ATTACH_POST_WAIT_STOP,
- };
- /* Called after we've attached to a process and we've seen it stop for
- the first time. Resume, stop, or don't touch the threads according
- to MODE. */
- static void
- attach_post_wait (int from_tty, enum attach_post_wait_mode mode)
- {
- struct inferior *inferior;
- inferior = current_inferior ();
- inferior->control.stop_soon = NO_STOP_QUIETLY;
- if (inferior->needs_setup)
- setup_inferior (from_tty);
- if (mode == ATTACH_POST_WAIT_RESUME)
- {
- /* The user requested an `attach&', so be sure to leave threads
- that didn't get a signal running. */
- /* Immediately resume all suspended threads of this inferior,
- and this inferior only. This should have no effect on
- already running threads. If a thread has been stopped with a
- signal, leave it be. */
- if (non_stop)
- proceed_after_attach (inferior);
- else
- {
- if (inferior_thread ()->stop_signal () == GDB_SIGNAL_0)
- {
- clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
- }
- }
- }
- else if (mode == ATTACH_POST_WAIT_STOP)
- {
- /* The user requested a plain `attach', so be sure to leave
- the inferior stopped. */
- /* At least the current thread is already stopped. */
- /* In all-stop, by definition, all threads have to be already
- stopped at this point. In non-stop, however, although the
- selected thread is stopped, others may still be executing.
- Be sure to explicitly stop all threads of the process. This
- should have no effect on already stopped threads. */
- if (non_stop)
- target_stop (ptid_t (inferior->pid));
- else if (target_is_non_stop_p ())
- {
- struct thread_info *lowest = inferior_thread ();
- stop_all_threads ("attaching");
- /* It's not defined which thread will report the attach
- stop. For consistency, always select the thread with
- lowest GDB number, which should be the main thread, if it
- still exists. */
- for (thread_info *thread : current_inferior ()->non_exited_threads ())
- if (thread->inf->num < lowest->inf->num
- || thread->per_inf_num < lowest->per_inf_num)
- lowest = thread;
- switch_to_thread (lowest);
- }
- /* Tell the user/frontend where we're stopped. */
- normal_stop ();
- if (deprecated_attach_hook)
- deprecated_attach_hook ();
- }
- }
- /* "attach" command entry point. Takes a program started up outside
- of gdb and ``attaches'' to it. This stops it cold in its tracks
- and allows us to start debugging it. */
- void
- attach_command (const char *args, int from_tty)
- {
- int async_exec;
- struct target_ops *attach_target;
- struct inferior *inferior = current_inferior ();
- enum attach_post_wait_mode mode;
- dont_repeat (); /* Not for the faint of heart */
- scoped_disable_commit_resumed disable_commit_resumed ("attaching");
- if (gdbarch_has_global_solist (target_gdbarch ()))
- /* Don't complain if all processes share the same symbol
- space. */
- ;
- else if (target_has_execution ())
- {
- if (query (_("A program is being debugged already. Kill it? ")))
- target_kill ();
- else
- error (_("Not killed."));
- }
- /* Clean up any leftovers from other runs. Some other things from
- this function should probably be moved into target_pre_inferior. */
- target_pre_inferior (from_tty);
- gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
- args = stripped.get ();
- attach_target = find_attach_target ();
- prepare_execution_command (attach_target, async_exec);
- if (non_stop && !attach_target->supports_non_stop ())
- error (_("Cannot attach to this target in non-stop mode"));
- attach_target->attach (args, from_tty);
- /* to_attach should push the target, so after this point we
- shouldn't refer to attach_target again. */
- attach_target = NULL;
- if (debug_infrun)
- {
- infrun_debug_printf ("immediately after attach:");
- for (thread_info *thread : inferior->non_exited_threads ())
- infrun_debug_printf (" thread %s, executing = %d, resumed = %d, "
- "state = %s",
- thread->ptid.to_string ().c_str (),
- thread->executing (),
- thread->resumed (),
- thread_state_string (thread->state));
- }
- /* Enable async mode if it is supported by the target. */
- if (target_can_async_p ())
- target_async (1);
- /* Set up the "saved terminal modes" of the inferior
- based on what modes we are starting it with. */
- target_terminal::init ();
- /* Install inferior's terminal modes. This may look like a no-op,
- as we've just saved them above, however, this does more than
- restore terminal settings:
- - installs a SIGINT handler that forwards SIGINT to the inferior.
- Otherwise a Ctrl-C pressed just while waiting for the initial
- stop would end up as a spurious Quit.
- - removes stdin from the event loop, which we need if attaching
- in the foreground, otherwise on targets that report an initial
- stop on attach (which are most) we'd process input/commands
- while we're in the event loop waiting for that stop. That is,
- before the attach continuation runs and the command is really
- finished. */
- target_terminal::inferior ();
- /* Set up execution context to know that we should return from
- wait_for_inferior as soon as the target reports a stop. */
- init_wait_for_inferior ();
- inferior->needs_setup = 1;
- if (target_is_non_stop_p ())
- {
- /* If we find that the current thread isn't stopped, explicitly
- do so now, because we're going to install breakpoints and
- poke at memory. */
- if (async_exec)
- /* The user requested an `attach&'; stop just one thread. */
- target_stop (inferior_ptid);
- else
- /* The user requested an `attach', so stop all threads of this
- inferior. */
- target_stop (ptid_t (inferior_ptid.pid ()));
- }
- /* Check for exec file mismatch, and let the user solve it. */
- validate_exec_file (from_tty);
- mode = async_exec ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_STOP;
- /* Some system don't generate traps when attaching to inferior.
- E.g. Mach 3 or GNU hurd. */
- if (!target_attach_no_wait ())
- {
- /* Careful here. See comments in inferior.h. Basically some
- OSes don't ignore SIGSTOPs on continue requests anymore. We
- need a way for handle_inferior_event to reset the stop_signal
- variable after an attach, and this is what
- STOP_QUIETLY_NO_SIGSTOP is for. */
- inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP;
- /* Wait for stop. */
- inferior->add_continuation ([=] ()
- {
- attach_post_wait (from_tty, mode);
- });
- /* Let infrun consider waiting for events out of this
- target. */
- inferior->process_target ()->threads_executing = true;
- if (!target_is_async_p ())
- mark_infrun_async_event_handler ();
- return;
- }
- else
- attach_post_wait (from_tty, mode);
- disable_commit_resumed.reset_and_commit ();
- }
- /* We had just found out that the target was already attached to an
- inferior. PTID points at a thread of this new inferior, that is
- the most likely to be stopped right now, but not necessarily so.
- The new inferior is assumed to be already added to the inferior
- list at this point. If LEAVE_RUNNING, then leave the threads of
- this inferior running, except those we've explicitly seen reported
- as stopped. */
- void
- notice_new_inferior (thread_info *thr, bool leave_running, int from_tty)
- {
- enum attach_post_wait_mode mode
- = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
- gdb::optional<scoped_restore_current_thread> restore_thread;
- if (inferior_ptid != null_ptid)
- restore_thread.emplace ();
- /* Avoid reading registers -- we haven't fetched the target
- description yet. */
- switch_to_thread_no_regs (thr);
- /* When we "notice" a new inferior we need to do all the things we
- would normally do if we had just attached to it. */
- if (thr->executing ())
- {
- struct inferior *inferior = current_inferior ();
- /* We're going to install breakpoints, and poke at memory,
- ensure that the inferior is stopped for a moment while we do
- that. */
- target_stop (inferior_ptid);
- inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
- /* Wait for stop before proceeding. */
- inferior->add_continuation ([=] ()
- {
- attach_post_wait (from_tty, mode);
- });
- return;
- }
- attach_post_wait (from_tty, mode);
- }
- /*
- * detach_command --
- * takes a program previously attached to and detaches it.
- * The program resumes execution and will no longer stop
- * on signals, etc. We better not have left any breakpoints
- * in the program or it'll die when it hits one. For this
- * to work, it may be necessary for the process to have been
- * previously attached. It *might* work if the program was
- * started via the normal ptrace (PTRACE_TRACEME).
- */
- void
- detach_command (const char *args, int from_tty)
- {
- dont_repeat (); /* Not for the faint of heart. */
- if (inferior_ptid == null_ptid)
- error (_("The program is not being run."));
- scoped_disable_commit_resumed disable_commit_resumed ("detaching");
- query_if_trace_running (from_tty);
- disconnect_tracing ();
- /* Hold a strong reference to the target while (maybe)
- detaching the parent. Otherwise detaching could close the
- target. */
- auto target_ref
- = target_ops_ref::new_reference (current_inferior ()->process_target ());
- /* Save this before detaching, since detaching may unpush the
- process_stratum target. */
- bool was_non_stop_p = target_is_non_stop_p ();
- target_detach (current_inferior (), from_tty);
- /* The current inferior process was just detached successfully. Get
- rid of breakpoints that no longer make sense. Note we don't do
- this within target_detach because that is also used when
- following child forks, and in that case we will want to transfer
- breakpoints to the child, not delete them. */
- breakpoint_init_inferior (inf_exited);
- /* If the solist is global across inferiors, don't clear it when we
- detach from a single inferior. */
- if (!gdbarch_has_global_solist (target_gdbarch ()))
- no_shared_libraries (NULL, from_tty);
- if (deprecated_detach_hook)
- deprecated_detach_hook ();
- if (!was_non_stop_p)
- restart_after_all_stop_detach (as_process_stratum_target (target_ref.get ()));
- disable_commit_resumed.reset_and_commit ();
- }
- /* Disconnect from the current target without resuming it (leaving it
- waiting for a debugger).
- We'd better not have left any breakpoints in the program or the
- next debugger will get confused. Currently only supported for some
- remote targets, since the normal attach mechanisms don't work on
- stopped processes on some native platforms (e.g. GNU/Linux). */
- static void
- disconnect_command (const char *args, int from_tty)
- {
- dont_repeat (); /* Not for the faint of heart. */
- query_if_trace_running (from_tty);
- disconnect_tracing ();
- target_disconnect (args, from_tty);
- no_shared_libraries (NULL, from_tty);
- init_thread_list ();
- if (deprecated_detach_hook)
- deprecated_detach_hook ();
- }
- /* Stop PTID in the current target, and tag the PTID threads as having
- been explicitly requested to stop. PTID can be a thread, a
- process, or minus_one_ptid, meaning all threads of all inferiors of
- the current target. */
- static void
- stop_current_target_threads_ns (ptid_t ptid)
- {
- target_stop (ptid);
- /* Tag the thread as having been explicitly requested to stop, so
- other parts of gdb know not to resume this thread automatically,
- if it was stopped due to an internal event. Limit this to
- non-stop mode, as when debugging a multi-threaded application in
- all-stop mode, we will only get one stop event --- it's undefined
- which thread will report the event. */
- set_stop_requested (current_inferior ()->process_target (),
- ptid, 1);
- }
- /* See inferior.h. */
- void
- interrupt_target_1 (bool all_threads)
- {
- scoped_disable_commit_resumed disable_commit_resumed ("interrupting");
- if (non_stop)
- {
- if (all_threads)
- {
- scoped_restore_current_thread restore_thread;
- for (inferior *inf : all_inferiors ())
- {
- switch_to_inferior_no_thread (inf);
- stop_current_target_threads_ns (minus_one_ptid);
- }
- }
- else
- stop_current_target_threads_ns (inferior_ptid);
- }
- else
- target_interrupt ();
- disable_commit_resumed.reset_and_commit ();
- }
- /* interrupt [-a]
- Stop the execution of the target while running in async mode, in
- the background. In all-stop, stop the whole process. In non-stop
- mode, stop the current thread only by default, or stop all threads
- if the `-a' switch is used. */
- static void
- interrupt_command (const char *args, int from_tty)
- {
- if (target_can_async_p ())
- {
- int all_threads = 0;
- dont_repeat (); /* Not for the faint of heart. */
- if (args != NULL
- && startswith (args, "-a"))
- all_threads = 1;
- if (!non_stop && all_threads)
- error (_("-a is meaningless in all-stop mode."));
- interrupt_target_1 (all_threads);
- }
- }
- /* See inferior.h. */
- void
- default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
- struct frame_info *frame, const char *args)
- {
- int regnum;
- int printed_something = 0;
- for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
- {
- if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
- {
- printed_something = 1;
- gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
- }
- }
- if (!printed_something)
- gdb_printf (file, "No floating-point info "
- "available for this processor.\n");
- }
- static void
- info_float_command (const char *args, int from_tty)
- {
- struct frame_info *frame;
- if (!target_has_registers ())
- error (_("The program has no registers now."));
- frame = get_selected_frame (NULL);
- gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args);
- }
- /* Implement `info proc' family of commands. */
- static void
- info_proc_cmd_1 (const char *args, enum info_proc_what what, int from_tty)
- {
- struct gdbarch *gdbarch = get_current_arch ();
- if (!target_info_proc (args, what))
- {
- if (gdbarch_info_proc_p (gdbarch))
- gdbarch_info_proc (gdbarch, args, what);
- else
- error (_("Not supported on this target."));
- }
- }
- /* Implement `info proc' when given without any further parameters. */
- static void
- info_proc_cmd (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_MINIMAL, from_tty);
- }
- /* Implement `info proc mappings'. */
- static void
- info_proc_cmd_mappings (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_MAPPINGS, from_tty);
- }
- /* Implement `info proc stat'. */
- static void
- info_proc_cmd_stat (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_STAT, from_tty);
- }
- /* Implement `info proc status'. */
- static void
- info_proc_cmd_status (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_STATUS, from_tty);
- }
- /* Implement `info proc cwd'. */
- static void
- info_proc_cmd_cwd (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_CWD, from_tty);
- }
- /* Implement `info proc cmdline'. */
- static void
- info_proc_cmd_cmdline (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_CMDLINE, from_tty);
- }
- /* Implement `info proc exe'. */
- static void
- info_proc_cmd_exe (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_EXE, from_tty);
- }
- /* Implement `info proc files'. */
- static void
- info_proc_cmd_files (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_FILES, from_tty);
- }
- /* Implement `info proc all'. */
- static void
- info_proc_cmd_all (const char *args, int from_tty)
- {
- info_proc_cmd_1 (args, IP_ALL, from_tty);
- }
- /* Implement `show print finish'. */
- static void
- show_print_finish (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
- {
- gdb_printf (file, _("\
- Printing of return value after `finish' is %s.\n"),
- value);
- }
- /* This help string is used for the run, start, and starti commands.
- It is defined as a macro to prevent duplication. */
- #define RUN_ARGS_HELP \
- "You may specify arguments to give it.\n\
- Args may include \"*\", or \"[...]\"; they are expanded using the\n\
- shell that will start the program (specified by the \"$SHELL\" environment\n\
- variable). Input and output redirection with \">\", \"<\", or \">>\"\n\
- are also allowed.\n\
- \n\
- With no arguments, uses arguments last specified (with \"run\" or \n\
- \"set args\"). To cancel previous arguments and run with no arguments,\n\
- use \"set args\" without arguments.\n\
- \n\
- To start the inferior without using a shell, use \"set startup-with-shell off\"."
- void _initialize_infcmd ();
- void
- _initialize_infcmd ()
- {
- static struct cmd_list_element *info_proc_cmdlist;
- struct cmd_list_element *c = NULL;
- const char *cmd_name;
- /* Add the filename of the terminal connected to inferior I/O. */
- add_setshow_optional_filename_cmd ("inferior-tty", class_run,
- &inferior_io_terminal_scratch, _("\
- Set terminal for future runs of program being debugged."), _("\
- Show terminal for future runs of program being debugged."), _("\
- Usage: set inferior-tty [TTY]\n\n\
- If TTY is omitted, the default behavior of using the same terminal as GDB\n\
- is restored."),
- set_inferior_tty_command,
- show_inferior_tty_command,
- &setlist, &showlist);
- cmd_name = "inferior-tty";
- c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- add_alias_cmd ("tty", c, class_run, 0, &cmdlist);
- cmd_name = "args";
- add_setshow_string_noescape_cmd (cmd_name, class_run,
- &inferior_args_scratch, _("\
- Set argument list to give program being debugged when it is started."), _("\
- Show argument list to give program being debugged when it is started."), _("\
- Follow this command with any number of args, to be passed to the program."),
- set_args_command,
- show_args_command,
- &setlist, &showlist);
- c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- set_cmd_completer (c, filename_completer);
- cmd_name = "cwd";
- add_setshow_string_noescape_cmd (cmd_name, class_run,
- &inferior_cwd_scratch, _("\
- Set the current working directory to be used when the inferior is started.\n\
- Changing this setting does not have any effect on inferiors that are\n\
- already running."),
- _("\
- Show the current working directory that is used when the inferior is started."),
- _("\
- Use this command to change the current working directory that will be used\n\
- when the inferior is started. This setting does not affect GDB's current\n\
- working directory."),
- set_cwd_command,
- show_cwd_command,
- &setlist, &showlist);
- c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- set_cmd_completer (c, filename_completer);
- c = add_cmd ("environment", no_class, environment_info, _("\
- The environment to give the program, or one variable's value.\n\
- With an argument VAR, prints the value of environment variable VAR to\n\
- give the program being debugged. With no arguments, prints the entire\n\
- environment to be given to the program."), &showlist);
- set_cmd_completer (c, noop_completer);
- add_basic_prefix_cmd ("unset", no_class,
- _("Complement to certain \"set\" commands."),
- &unsetlist, 0, &cmdlist);
- c = add_cmd ("environment", class_run, unset_environment_command, _("\
- Cancel environment variable VAR for the program.\n\
- This does not affect the program until the next \"run\" command."),
- &unsetlist);
- set_cmd_completer (c, noop_completer);
- c = add_cmd ("environment", class_run, set_environment_command, _("\
- Set environment variable value to give the program.\n\
- Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
- VALUES of environment variables are uninterpreted strings.\n\
- This does not affect the program until the next \"run\" command."),
- &setlist);
- set_cmd_completer (c, noop_completer);
- c = add_com ("path", class_files, path_command, _("\
- Add directory DIR(s) to beginning of search path for object files.\n\
- $cwd in the path means the current working directory.\n\
- This path is equivalent to the $PATH shell variable. It is a list of\n\
- directories, separated by colons. These directories are searched to find\n\
- fully linked executable files and separately compiled object files as \
- needed."));
- set_cmd_completer (c, filename_completer);
- c = add_cmd ("paths", no_class, path_info, _("\
- Current search path for finding object files.\n\
- $cwd in the path means the current working directory.\n\
- This path is equivalent to the $PATH shell variable. It is a list of\n\
- directories, separated by colons. These directories are searched to find\n\
- fully linked executable files and separately compiled object files as \
- needed."),
- &showlist);
- set_cmd_completer (c, noop_completer);
- add_prefix_cmd ("kill", class_run, kill_command,
- _("Kill execution of program being debugged."),
- &killlist, 0, &cmdlist);
- add_com ("attach", class_run, attach_command, _("\
- Attach to a process or file outside of GDB.\n\
- This command attaches to another target, of the same type as your last\n\
- \"target\" command (\"info files\" will show your target stack).\n\
- The command may take as argument a process id or a device file.\n\
- For a process id, you must have permission to send the process a signal,\n\
- and it must have the same effective uid as the debugger.\n\
- When using \"attach\" with a process id, the debugger finds the\n\
- program running in the process, looking first in the current working\n\
- directory, or (if not found there) using the source file search path\n\
- (see the \"directory\" command). You can also use the \"file\" command\n\
- to specify the program, and to load its symbol table."));
- add_prefix_cmd ("detach", class_run, detach_command, _("\
- Detach a process or file previously attached.\n\
- If a process, it is no longer traced, and it continues its execution. If\n\
- you were debugging a file, the file is closed and gdb no longer accesses it."),
- &detachlist, 0, &cmdlist);
- add_com ("disconnect", class_run, disconnect_command, _("\
- Disconnect from a target.\n\
- The target will wait for another debugger to connect. Not available for\n\
- all targets."));
- c = add_com ("signal", class_run, signal_command, _("\
- Continue program with the specified signal.\n\
- Usage: signal SIGNAL\n\
- The SIGNAL argument is processed the same as the handle command.\n\
- \n\
- An argument of \"0\" means continue the program without sending it a signal.\n\
- This is useful in cases where the program stopped because of a signal,\n\
- and you want to resume the program while discarding the signal.\n\
- \n\
- In a multi-threaded program the signal is delivered to, or discarded from,\n\
- the current thread only."));
- set_cmd_completer (c, signal_completer);
- c = add_com ("queue-signal", class_run, queue_signal_command, _("\
- Queue a signal to be delivered to the current thread when it is resumed.\n\
- Usage: queue-signal SIGNAL\n\
- The SIGNAL argument is processed the same as the handle command.\n\
- It is an error if the handling state of SIGNAL is \"nopass\".\n\
- \n\
- An argument of \"0\" means remove any currently queued signal from\n\
- the current thread. This is useful in cases where the program stopped\n\
- because of a signal, and you want to resume it while discarding the signal.\n\
- \n\
- In a multi-threaded program the signal is queued with, or discarded from,\n\
- the current thread only."));
- set_cmd_completer (c, signal_completer);
- cmd_list_element *stepi_cmd
- = add_com ("stepi", class_run, stepi_command, _("\
- Step one instruction exactly.\n\
- Usage: stepi [N]\n\
- Argument N means step N times (or till program stops for another \
- reason)."));
- add_com_alias ("si", stepi_cmd, class_run, 0);
- cmd_list_element *nexti_cmd
- = add_com ("nexti", class_run, nexti_command, _("\
- Step one instruction, but proceed through subroutine calls.\n\
- Usage: nexti [N]\n\
- Argument N means step N times (or till program stops for another \
- reason)."));
- add_com_alias ("ni", nexti_cmd, class_run, 0);
- cmd_list_element *finish_cmd
- = add_com ("finish", class_run, finish_command, _("\
- Execute until selected stack frame returns.\n\
- Usage: finish\n\
- Upon return, the value returned is printed and put in the value history."));
- add_com_alias ("fin", finish_cmd, class_run, 1);
- cmd_list_element *next_cmd
- = add_com ("next", class_run, next_command, _("\
- Step program, proceeding through subroutine calls.\n\
- Usage: next [N]\n\
- Unlike \"step\", if the current source line calls a subroutine,\n\
- this command does not enter the subroutine, but instead steps over\n\
- the call, in effect treating it as a single source line."));
- add_com_alias ("n", next_cmd, class_run, 1);
- cmd_list_element *step_cmd
- = add_com ("step", class_run, step_command, _("\
- Step program until it reaches a different source line.\n\
- Usage: step [N]\n\
- Argument N means step N times (or till program stops for another \
- reason)."));
- add_com_alias ("s", step_cmd, class_run, 1);
- cmd_list_element *until_cmd
- = add_com ("until", class_run, until_command, _("\
- Execute until past the current line or past a LOCATION.\n\
- Execute until the program reaches a source line greater than the current\n\
- or a specified location (same args as break command) within the current \
- frame."));
- set_cmd_completer (until_cmd, location_completer);
- add_com_alias ("u", until_cmd, class_run, 1);
- c = add_com ("advance", class_run, advance_command, _("\
- Continue the program up to the given location (same form as args for break \
- command).\n\
- Execution will also stop upon exit from the current stack frame."));
- set_cmd_completer (c, location_completer);
- cmd_list_element *jump_cmd
- = add_com ("jump", class_run, jump_command, _("\
- Continue program being debugged at specified line or address.\n\
- Usage: jump LOCATION\n\
- Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
- for an address to start at."));
- set_cmd_completer (jump_cmd, location_completer);
- add_com_alias ("j", jump_cmd, class_run, 1);
- cmd_list_element *continue_cmd
- = add_com ("continue", class_run, continue_command, _("\
- Continue program being debugged, after signal or breakpoint.\n\
- Usage: continue [N]\n\
- If proceeding from breakpoint, a number N may be used as an argument,\n\
- which means to set the ignore count of that breakpoint to N - 1 (so that\n\
- the breakpoint won't break until the Nth time it is reached).\n\
- \n\
- If non-stop mode is enabled, continue only the current thread,\n\
- otherwise all the threads in the program are continued. To \n\
- continue all stopped threads in non-stop mode, use the -a option.\n\
- Specifying -a and an ignore count simultaneously is an error."));
- add_com_alias ("c", continue_cmd, class_run, 1);
- add_com_alias ("fg", continue_cmd, class_run, 1);
- cmd_list_element *run_cmd
- = add_com ("run", class_run, run_command, _("\
- Start debugged program.\n"
- RUN_ARGS_HELP));
- set_cmd_completer (run_cmd, filename_completer);
- add_com_alias ("r", run_cmd, class_run, 1);
- c = add_com ("start", class_run, start_command, _("\
- Start the debugged program stopping at the beginning of the main procedure.\n"
- RUN_ARGS_HELP));
- set_cmd_completer (c, filename_completer);
- c = add_com ("starti", class_run, starti_command, _("\
- Start the debugged program stopping at the first instruction.\n"
- RUN_ARGS_HELP));
- set_cmd_completer (c, filename_completer);
- add_com ("interrupt", class_run, interrupt_command,
- _("Interrupt the execution of the debugged program.\n\
- If non-stop mode is enabled, interrupt only the current thread,\n\
- otherwise all the threads in the program are stopped. To \n\
- interrupt all running threads in non-stop mode, use the -a option."));
- cmd_list_element *info_registers_cmd
- = add_info ("registers", info_registers_command, _("\
- List of integer registers and their contents, for selected stack frame.\n\
- One or more register names as argument means describe the given registers.\n\
- One or more register group names as argument means describe the registers\n\
- in the named register groups."));
- add_info_alias ("r", info_registers_cmd, 1);
- set_cmd_completer (info_registers_cmd, reg_or_group_completer);
- c = add_info ("all-registers", info_all_registers_command, _("\
- List of all registers and their contents, for selected stack frame.\n\
- One or more register names as argument means describe the given registers.\n\
- One or more register group names as argument means describe the registers\n\
- in the named register groups."));
- set_cmd_completer (c, reg_or_group_completer);
- add_info ("program", info_program_command,
- _("Execution status of the program."));
- add_info ("float", info_float_command,
- _("Print the status of the floating point unit."));
- add_info ("vector", info_vector_command,
- _("Print the status of the vector unit."));
- add_prefix_cmd ("proc", class_info, info_proc_cmd,
- _("\
- Show additional information about a process.\n\
- Specify any process id, or use the program being debugged by default."),
- &info_proc_cmdlist,
- 1/*allow-unknown*/, &infolist);
- add_cmd ("mappings", class_info, info_proc_cmd_mappings, _("\
- List memory regions mapped by the specified process."),
- &info_proc_cmdlist);
- add_cmd ("stat", class_info, info_proc_cmd_stat, _("\
- List process info from /proc/PID/stat."),
- &info_proc_cmdlist);
- add_cmd ("status", class_info, info_proc_cmd_status, _("\
- List process info from /proc/PID/status."),
- &info_proc_cmdlist);
- add_cmd ("cwd", class_info, info_proc_cmd_cwd, _("\
- List current working directory of the specified process."),
- &info_proc_cmdlist);
- add_cmd ("cmdline", class_info, info_proc_cmd_cmdline, _("\
- List command line arguments of the specified process."),
- &info_proc_cmdlist);
- add_cmd ("exe", class_info, info_proc_cmd_exe, _("\
- List absolute filename for executable of the specified process."),
- &info_proc_cmdlist);
- add_cmd ("files", class_info, info_proc_cmd_files, _("\
- List files opened by the specified process."),
- &info_proc_cmdlist);
- add_cmd ("all", class_info, info_proc_cmd_all, _("\
- List all available info about the specified process."),
- &info_proc_cmdlist);
- add_setshow_boolean_cmd ("finish", class_support,
- &user_print_options.finish_print, _("\
- Set whether `finish' prints the return value."), _("\
- Show whether `finish' prints the return value."), NULL,
- NULL,
- show_print_finish,
- &setprintlist, &showprintlist);
- }
|