17d62b00eSchristos /* List of target connections for GDB. 27d62b00eSchristos 3*6881a400Schristos Copyright (C) 2017-2023 Free Software Foundation, Inc. 47d62b00eSchristos 57d62b00eSchristos This file is part of GDB. 67d62b00eSchristos 77d62b00eSchristos This program is free software; you can redistribute it and/or modify 87d62b00eSchristos it under the terms of the GNU General Public License as published by 97d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 107d62b00eSchristos (at your option) any later version. 117d62b00eSchristos 127d62b00eSchristos This program is distributed in the hope that it will be useful, 137d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157d62b00eSchristos GNU General Public License for more details. 167d62b00eSchristos 177d62b00eSchristos You should have received a copy of the GNU General Public License 187d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos #include "defs.h" 217d62b00eSchristos #include "target-connection.h" 227d62b00eSchristos 237d62b00eSchristos #include <map> 247d62b00eSchristos 257d62b00eSchristos #include "inferior.h" 267d62b00eSchristos #include "target.h" 27*6881a400Schristos #include "observable.h" 287d62b00eSchristos 297d62b00eSchristos /* A map between connection number and representative process_stratum 307d62b00eSchristos target. */ 317d62b00eSchristos static std::map<int, process_stratum_target *> process_targets; 327d62b00eSchristos 337d62b00eSchristos /* The highest connection number ever given to a target. */ 347d62b00eSchristos static int highest_target_connection_num; 357d62b00eSchristos 367d62b00eSchristos /* See target-connection.h. */ 377d62b00eSchristos 387d62b00eSchristos void 397d62b00eSchristos connection_list_add (process_stratum_target *t) 407d62b00eSchristos { 417d62b00eSchristos if (t->connection_number == 0) 427d62b00eSchristos { 437d62b00eSchristos t->connection_number = ++highest_target_connection_num; 447d62b00eSchristos process_targets[t->connection_number] = t; 457d62b00eSchristos } 467d62b00eSchristos } 477d62b00eSchristos 487d62b00eSchristos /* See target-connection.h. */ 497d62b00eSchristos 507d62b00eSchristos void 517d62b00eSchristos connection_list_remove (process_stratum_target *t) 527d62b00eSchristos { 53*6881a400Schristos /* Notify about the connection being removed before we reset the 54*6881a400Schristos connection number to zero. */ 55*6881a400Schristos gdb::observers::connection_removed.notify (t); 567d62b00eSchristos process_targets.erase (t->connection_number); 577d62b00eSchristos t->connection_number = 0; 587d62b00eSchristos } 597d62b00eSchristos 607d62b00eSchristos /* See target-connection.h. */ 617d62b00eSchristos 627d62b00eSchristos std::string 637d62b00eSchristos make_target_connection_string (process_stratum_target *t) 647d62b00eSchristos { 657d62b00eSchristos if (t->connection_string () != NULL) 667d62b00eSchristos return string_printf ("%s %s", t->shortname (), 677d62b00eSchristos t->connection_string ()); 687d62b00eSchristos else 697d62b00eSchristos return t->shortname (); 707d62b00eSchristos } 717d62b00eSchristos 727d62b00eSchristos /* Prints the list of target connections and their details on UIOUT. 737d62b00eSchristos 747d62b00eSchristos If REQUESTED_CONNECTIONS is not NULL, it's a list of GDB ids of the 757d62b00eSchristos target connections that should be printed. Otherwise, all target 767d62b00eSchristos connections are printed. */ 777d62b00eSchristos 787d62b00eSchristos static void 797d62b00eSchristos print_connection (struct ui_out *uiout, const char *requested_connections) 807d62b00eSchristos { 817d62b00eSchristos int count = 0; 827d62b00eSchristos size_t what_len = 0; 837d62b00eSchristos 847d62b00eSchristos /* Compute number of lines we will print. */ 857d62b00eSchristos for (const auto &it : process_targets) 867d62b00eSchristos { 877d62b00eSchristos if (!number_is_in_list (requested_connections, it.first)) 887d62b00eSchristos continue; 897d62b00eSchristos 907d62b00eSchristos ++count; 917d62b00eSchristos 927d62b00eSchristos process_stratum_target *t = it.second; 937d62b00eSchristos 94*6881a400Schristos size_t l = make_target_connection_string (t).length (); 957d62b00eSchristos if (l > what_len) 967d62b00eSchristos what_len = l; 977d62b00eSchristos } 987d62b00eSchristos 997d62b00eSchristos if (count == 0) 1007d62b00eSchristos { 1017d62b00eSchristos uiout->message (_("No connections.\n")); 1027d62b00eSchristos return; 1037d62b00eSchristos } 1047d62b00eSchristos 1057d62b00eSchristos ui_out_emit_table table_emitter (uiout, 4, process_targets.size (), 1067d62b00eSchristos "connections"); 1077d62b00eSchristos 1087d62b00eSchristos uiout->table_header (1, ui_left, "current", ""); 1097d62b00eSchristos uiout->table_header (4, ui_left, "number", "Num"); 1107d62b00eSchristos /* The text in the "what" column may include spaces. Add one extra 1117d62b00eSchristos space to visually separate the What and Description columns a 1127d62b00eSchristos little better. Compare: 1137d62b00eSchristos "* 1 remote :9999 Remote serial target in gdb-specific protocol" 1147d62b00eSchristos "* 1 remote :9999 Remote serial target in gdb-specific protocol" 1157d62b00eSchristos */ 1167d62b00eSchristos uiout->table_header (what_len + 1, ui_left, "what", "What"); 1177d62b00eSchristos uiout->table_header (17, ui_left, "description", "Description"); 1187d62b00eSchristos 1197d62b00eSchristos uiout->table_body (); 1207d62b00eSchristos 1217d62b00eSchristos for (const auto &it : process_targets) 1227d62b00eSchristos { 1237d62b00eSchristos process_stratum_target *t = it.second; 1247d62b00eSchristos 1257d62b00eSchristos if (!number_is_in_list (requested_connections, t->connection_number)) 1267d62b00eSchristos continue; 1277d62b00eSchristos 1287d62b00eSchristos ui_out_emit_tuple tuple_emitter (uiout, NULL); 1297d62b00eSchristos 1307d62b00eSchristos if (current_inferior ()->process_target () == t) 1317d62b00eSchristos uiout->field_string ("current", "*"); 1327d62b00eSchristos else 1337d62b00eSchristos uiout->field_skip ("current"); 1347d62b00eSchristos 1357d62b00eSchristos uiout->field_signed ("number", t->connection_number); 1367d62b00eSchristos 137*6881a400Schristos uiout->field_string ("what", make_target_connection_string (t)); 1387d62b00eSchristos 1397d62b00eSchristos uiout->field_string ("description", t->longname ()); 1407d62b00eSchristos 1417d62b00eSchristos uiout->text ("\n"); 1427d62b00eSchristos } 1437d62b00eSchristos } 1447d62b00eSchristos 1457d62b00eSchristos /* The "info connections" command. */ 1467d62b00eSchristos 1477d62b00eSchristos static void 1487d62b00eSchristos info_connections_command (const char *args, int from_tty) 1497d62b00eSchristos { 1507d62b00eSchristos print_connection (current_uiout, args); 1517d62b00eSchristos } 1527d62b00eSchristos 1537d62b00eSchristos void _initialize_target_connection (); 1547d62b00eSchristos 1557d62b00eSchristos void 1567d62b00eSchristos _initialize_target_connection () 1577d62b00eSchristos { 1587d62b00eSchristos add_info ("connections", info_connections_command, 1597d62b00eSchristos _("\ 1607d62b00eSchristos Target connections in use.\n\ 1617d62b00eSchristos Shows the list of target connections currently in use.")); 1627d62b00eSchristos } 163