20#include "gdbsupport/common-defs.h"
24#include <sys/sysinfo.h>
32#include <netinet/in.h>
35#include "gdbsupport/xml-utils.h"
38#include "gdbsupport/filestuff.h"
41#define NAMELEN(dirent) strlen ((dirent)->d_name)
54#define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
66 sprintf (filename,
"/proc/%lld/task/%lld/stat",
69 gdb::optional<std::string> content = read_text_file_to_string (filename);
70 if (!content.has_value ())
74 std::string::size_type pos = content->find_last_of (
')');
75 if (pos == std::string::npos)
81 for (
int i = 0; i < 37; ++i)
84 pos = content->find_first_of (
' ', pos);
85 if (pos == std::string::npos)
89 pos = content->find_first_not_of (
' ', pos);
90 if (pos == std::string::npos)
94 if (sscanf (&(*content)[pos],
"%d", &core) == 0)
107 std::string stat_path = string_printf (
"/proc/%lld/stat",
pid);
108 gdb_file_up fp = gdb_fopen_cloexec (stat_path,
"r");
119 int items_read = fscanf (fp.get (),
"%lld %17s", &stat_pid, cmd);
121 if (items_read == 2 &&
pid == stat_pid)
123 cmd[strlen (cmd) - 1] =
'\0';
124 strncpy (command, cmd + 1, maxlen);
130 snprintf (command, maxlen,
"%lld",
pid);
133 command[maxlen - 1] =
'\0';
141 std::string pathname = string_printf (
"/proc/%lld/cmdline",
pid);
142 std::string commandline;
143 gdb_file_up
f = gdb_fopen_cloexec (pathname,
"r");
147 while (!feof (
f.get ()))
150 size_t read_bytes = fread (buf, 1,
sizeof (buf),
f.get ());
153 commandline.append (buf, read_bytes);
156 if (!commandline.empty ())
159 for (
char &c : commandline)
169 commandline = std::string (
"[") + cmd +
"]";
182 struct passwd *pwentry;
185 getpwuid_r (uid, &pwd, buf,
sizeof (buf), &pwentry);
189 strncpy (user, pwentry->pw_name, maxlen - 1);
191 user[maxlen - 1] =
'\0';
206 sprintf (procentry,
"/proc/%lld",
pid);
208 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
210 *owner = statbuf.st_uid;
228 sprintf (taskdir,
"/proc/%lld/task",
pid);
229 dir = opendir (taskdir);
232 while ((dp = readdir (dir)) != NULL)
237 if (!isdigit (dp->d_name[0])
241 sscanf (dp->d_name,
"%lld", &tid);
245 if (core >= 0 && core < num_cores)
260static gdb::optional<size_t>
263 gdb::optional<std::string> possible
264 = read_text_file_to_string (
"/sys/devices/system/cpu/possible");
266 if (!possible.has_value ())
278 unsigned long max_id = 0;
279 for (std::string::size_type start = 0; start < possible->size ();)
281 const char *start_p = &(*possible)[start];
286 unsigned long id = strtoul (start_p, &end_p, 10);
290 max_id = std::max (max_id,
id);
292 start += end_p - start_p;
293 gdb_assert (start <= possible->
size ());
314 if (count.has_value ())
317 return sysconf (_SC_NPROCESSORS_ONLN);
324 std::string buffer =
"<osdata type=\"processes\">\n";
326 dirp = opendir (
"/proc");
332 while ((dp = readdir (dirp)) != NULL)
336 char user[UT_NAMESIZE];
339 std::string cores_str;
342 if (!isdigit (dp->d_name[0])
346 sscanf (dp->d_name,
"%lld", &
pid);
355 cores = XCNEWVEC (
int, core_array_size);
358 for (i = 0; i < core_array_size && task_count > 0; ++i)
361 string_appendf (cores_str,
"%d", i);
363 task_count -= cores[i];
373 "<column name=\"pid\">%lld</column>"
374 "<column name=\"user\">%s</column>"
375 "<column name=\"command\">%s</column>"
376 "<column name=\"cores\">%s</column>"
387 buffer +=
"</osdata>\n";
423 return this->
pid < other.
pid;
435 std::string buffer =
"<osdata type=\"process groups\">\n";
437 dirp = opendir (
"/proc");
440 std::vector<pid_pgid_entry> process_list;
443 process_list.reserve (512);
447 while ((dp = readdir (dirp)) != NULL)
451 if (!isdigit (dp->d_name[0])
455 sscanf (dp->d_name,
"%lld", &
pid);
456 pgid = getpgid (
pid);
459 process_list.emplace_back (
pid, pgid);
465 std::sort (process_list.begin (), process_list.end ());
470 PID_T pgid = entry.pgid;
471 char leader_command[32];
479 "<column name=\"pgid\">%lld</column>"
480 "<column name=\"leader command\">%s</column>"
481 "<column name=\"pid\">%lld</column>"
482 "<column name=\"command line\">%s</column>"
491 buffer +=
"</osdata>\n";
503 std::string buffer =
"<osdata type=\"threads\">\n";
505 dirp = opendir (
"/proc");
510 while ((dp = readdir (dirp)) != NULL)
513 char procentry[
sizeof (
"/proc/4294967295")];
515 if (!isdigit (dp->d_name[0])
516 ||
NAMELEN (dp) >
sizeof (
"4294967295") - 1)
519 xsnprintf (procentry,
sizeof (procentry),
"/proc/%s",
521 if (stat (procentry, &statbuf) == 0
522 && S_ISDIR (statbuf.st_mode))
529 = string_printf (
"/proc/%s/task", dp->d_name);
531 pid = atoi (dp->d_name);
534 dirp2 = opendir (pathname.c_str ());
540 while ((dp2 = readdir (dirp2)) != NULL)
545 if (!isdigit (dp2->d_name[0])
546 ||
NAMELEN (dp2) >
sizeof (
"4294967295") - 1)
549 tid = atoi (dp2->d_name);
555 "<column name=\"pid\">%lld</column>"
556 "<column name=\"command\">%s</column>"
557 "<column name=\"tid\">%lld</column>"
558 "<column name=\"core\">%d</column>"
574 buffer +=
"</osdata>\n";
585 std::string buffer =
"<osdata type=\"cpus\">\n";
587 gdb_file_up fp = gdb_fopen_cloexec (
"/proc/cpuinfo",
"r");
594 if (fgets (buf,
sizeof (buf), fp.get ()))
600 key = strtok_r (buf,
":", &saveptr);
604 value = strtok_r (NULL,
":", &saveptr);
608 while (key[i] !=
'\t' && key[i] !=
'\0')
619 if (strcmp (key,
"processor") == 0)
624 buffer +=
"</item><item>";
629 string_xml_appendf (buffer,
630 "<column name=\"%s\">%s</column>",
635 while (!feof (fp.get ()));
641 buffer +=
"</osdata>\n";
653 std::string buffer =
"<osdata type=\"files\">\n";
655 dirp = opendir (
"/proc");
660 while ((dp = readdir (dirp)) != NULL)
663 char procentry[
sizeof (
"/proc/4294967295")];
665 if (!isdigit (dp->d_name[0])
666 ||
NAMELEN (dp) >
sizeof (
"4294967295") - 1)
669 xsnprintf (procentry,
sizeof (procentry),
"/proc/%s",
671 if (stat (procentry, &statbuf) == 0
672 && S_ISDIR (statbuf.st_mode))
678 pid = atoi (dp->d_name);
682 = string_printf (
"/proc/%s/fd", dp->d_name);
683 dirp2 = opendir (pathname.c_str ());
689 while ((dp2 = readdir (dirp2)) != NULL)
694 if (!isdigit (dp2->d_name[0]))
698 = string_printf (
"%s/%s", pathname.c_str (),
700 rslt = readlink (fdname.c_str (), buf,
708 "<column name=\"pid\">%s</column>"
709 "<column name=\"command\">%s</column>"
710 "<column name=\"file descriptor\">%s</column>"
711 "<column name=\"name\">%s</column>"
716 (rslt >= 0 ? buf : dp2->d_name));
727 buffer +=
"</osdata>\n";
754 case TCP_ESTABLISHED:
755 return "ESTABLISHED";
796 const char *proc_file;
798 if (family == AF_INET)
799 proc_file = tcp ?
"/proc/net/tcp" :
"/proc/net/udp";
800 else if (family == AF_INET6)
801 proc_file = tcp ?
"/proc/net/tcp6" :
"/proc/net/udp6";
805 gdb_file_up fp = gdb_fopen_cloexec (proc_file,
"r");
812 if (fgets (buf,
sizeof (buf), fp.get ()))
815 unsigned int local_port, remote_port, state;
816 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
820#error "local_address and remote_address buffers too small"
823 result = sscanf (buf,
824 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
825 local_address, &local_port,
826 remote_address, &remote_port,
834 char user[UT_NAMESIZE];
835 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
837 if (family == AF_INET)
839 sscanf (local_address,
"%X",
840 &locaddr.
sin.sin_addr.s_addr);
841 sscanf (remote_address,
"%X",
842 &remaddr.
sin.sin_addr.s_addr);
844 locaddr.
sin.sin_port = htons (local_port);
845 remaddr.
sin.sin_port = htons (remote_port);
847 addr_size =
sizeof (
struct sockaddr_in);
851 sscanf (local_address,
"%8X%8X%8X%8X",
852 locaddr.
sin6.sin6_addr.s6_addr32,
853 locaddr.
sin6.sin6_addr.s6_addr32 + 1,
854 locaddr.
sin6.sin6_addr.s6_addr32 + 2,
855 locaddr.
sin6.sin6_addr.s6_addr32 + 3);
856 sscanf (remote_address,
"%8X%8X%8X%8X",
857 remaddr.
sin6.sin6_addr.s6_addr32,
858 remaddr.
sin6.sin6_addr.s6_addr32 + 1,
859 remaddr.
sin6.sin6_addr.s6_addr32 + 2,
860 remaddr.
sin6.sin6_addr.s6_addr32 + 3);
862 locaddr.
sin6.sin6_port = htons (local_port);
863 remaddr.
sin6.sin6_port = htons (remote_port);
865 locaddr.
sin6.sin6_flowinfo = 0;
866 remaddr.
sin6.sin6_flowinfo = 0;
867 locaddr.
sin6.sin6_scope_id = 0;
868 remaddr.
sin6.sin6_scope_id = 0;
870 addr_size =
sizeof (
struct sockaddr_in6);
873 locaddr.
sa.sa_family = remaddr.
sa.sa_family = family;
875 result = getnameinfo (&locaddr.
sa, addr_size,
876 local_address, sizeof (local_address),
877 local_service,
sizeof (local_service),
878 NI_NUMERICHOST | NI_NUMERICSERV
879 | (tcp ? 0 : NI_DGRAM));
883 result = getnameinfo (&remaddr.
sa, addr_size,
885 sizeof (remote_address),
887 sizeof (remote_service),
888 NI_NUMERICHOST | NI_NUMERICSERV
889 | (tcp ? 0 : NI_DGRAM));
898 "<column name=\"local address\">%s</column>"
899 "<column name=\"local port\">%s</column>"
900 "<column name=\"remote address\">%s</column>"
901 "<column name=\"remote port\">%s</column>"
902 "<column name=\"state\">%s</column>"
903 "<column name=\"user\">%s</column>"
904 "<column name=\"family\">%s</column>"
905 "<column name=\"protocol\">%s</column>"
913 (family == AF_INET) ?
"INET" :
"INET6",
914 tcp ?
"STREAM" :
"DGRAM");
918 while (!feof (fp.get ()));
927 std::string buffer =
"<osdata type=\"I sockets\">\n";
934 buffer +=
"</osdata>\n";
949 time_t t = (time_t) seconds;
954 const char *time_str = ctime_r (&t, buf);
955 strncpy (time, time_str, maxlen - 1);
956 time[maxlen - 1] =
'\0';
966 struct group *grentry = getgrgid (gid);
970 strncpy (group, grentry->gr_name, maxlen - 1);
972 group[maxlen - 1] =
'\0';
984 std::string buffer =
"<osdata type=\"shared memory\">\n";
986 gdb_file_up fp = gdb_fopen_cloexec (
"/proc/sysvipc/shm",
"r");
993 if (fgets (buf,
sizeof (buf), fp.get ()))
999 int shmid,
size, nattch;
1000 TIME_T atime, dtime, ctime;
1004 items_read = sscanf (buf,
1005 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1006 &key, &shmid, &perms, &
size,
1009 &uid, &gid, &cuid, &cgid,
1010 &atime, &dtime, &ctime);
1012 if (items_read == 14)
1014 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1015 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1016 char ccmd[32], lcmd[32];
1017 char atime_str[32], dtime_str[32], ctime_str[32];
1034 "<column name=\"key\">%d</column>"
1035 "<column name=\"shmid\">%d</column>"
1036 "<column name=\"permissions\">%o</column>"
1037 "<column name=\"size\">%d</column>"
1038 "<column name=\"creator command\">%s</column>"
1039 "<column name=\"last op. command\">%s</column>"
1040 "<column name=\"num attached\">%d</column>"
1041 "<column name=\"user\">%s</column>"
1042 "<column name=\"group\">%s</column>"
1043 "<column name=\"creator user\">%s</column>"
1044 "<column name=\"creator group\">%s</column>"
1045 "<column name=\"last shmat() time\">%s</column>"
1046 "<column name=\"last shmdt() time\">%s</column>"
1047 "<column name=\"last shmctl() time\">%s</column>"
1066 while (!feof (fp.get ()));
1069 buffer +=
"</osdata>\n";
1080 std::string buffer =
"<osdata type=\"semaphores\">\n";
1082 gdb_file_up fp = gdb_fopen_cloexec (
"/proc/sysvipc/sem",
"r");
1089 if (fgets (buf,
sizeof (buf), fp.get ()))
1094 unsigned int perms, nsems;
1099 items_read = sscanf (buf,
1100 "%d %d %o %u %d %d %d %d %lld %lld",
1101 &key, &semid, &perms, &nsems,
1102 &uid, &gid, &cuid, &cgid,
1105 if (items_read == 10)
1107 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1108 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1109 char otime_str[32], ctime_str[32];
1122 "<column name=\"key\">%d</column>"
1123 "<column name=\"semid\">%d</column>"
1124 "<column name=\"permissions\">%o</column>"
1125 "<column name=\"num semaphores\">%u</column>"
1126 "<column name=\"user\">%s</column>"
1127 "<column name=\"group\">%s</column>"
1128 "<column name=\"creator user\">%s</column>"
1129 "<column name=\"creator group\">%s</column>"
1130 "<column name=\"last semop() time\">%s</column>"
1131 "<column name=\"last semctl() time\">%s</column>"
1146 while (!feof (fp.get ()));
1149 buffer +=
"</osdata>\n";
1160 std::string buffer =
"<osdata type=\"message queues\">\n";
1162 gdb_file_up fp = gdb_fopen_cloexec (
"/proc/sysvipc/msg",
"r");
1169 if (fgets (buf,
sizeof (buf), fp.get ()))
1175 unsigned int perms, cbytes, qnum;
1177 TIME_T stime, rtime, ctime;
1180 items_read = sscanf (buf,
1181 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1182 &key, &msqid, &perms, &cbytes, &qnum,
1183 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1184 &stime, &rtime, &ctime);
1186 if (items_read == 14)
1188 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1189 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1190 char lscmd[32], lrcmd[32];
1191 char stime_str[32], rtime_str[32], ctime_str[32];
1208 "<column name=\"key\">%d</column>"
1209 "<column name=\"msqid\">%d</column>"
1210 "<column name=\"permissions\">%o</column>"
1211 "<column name=\"num used bytes\">%u</column>"
1212 "<column name=\"num messages\">%u</column>"
1213 "<column name=\"last msgsnd() command\">%s</column>"
1214 "<column name=\"last msgrcv() command\">%s</column>"
1215 "<column name=\"user\">%s</column>"
1216 "<column name=\"group\">%s</column>"
1217 "<column name=\"creator user\">%s</column>"
1218 "<column name=\"creator group\">%s</column>"
1219 "<column name=\"last msgsnd() time\">%s</column>"
1220 "<column name=\"last msgrcv() time\">%s</column>"
1221 "<column name=\"last msgctl() time\">%s</column>"
1240 while (!feof (fp.get ()));
1243 buffer +=
"</osdata>\n";
1254 std::string buffer =
"<osdata type=\"modules\">\n";
1256 gdb_file_up fp = gdb_fopen_cloexec (
"/proc/modules",
"r");
1263 if (fgets (buf,
sizeof (buf), fp.get ()))
1265 char *
name, *dependencies, *
status, *tmp, *saveptr;
1267 unsigned long long address;
1270 name = strtok_r (buf,
" ", &saveptr);
1274 tmp = strtok_r (NULL,
" ", &saveptr);
1277 if (sscanf (tmp,
"%u", &
size) != 1)
1280 tmp = strtok_r (NULL,
" ", &saveptr);
1283 if (sscanf (tmp,
"%d", &uses) != 1)
1286 dependencies = strtok_r (NULL,
" ", &saveptr);
1287 if (dependencies == NULL)
1290 status = strtok_r (NULL,
" ", &saveptr);
1294 tmp = strtok_r (NULL,
"\n", &saveptr);
1297 if (sscanf (tmp,
"%llx", &address) != 1)
1300 string_xml_appendf (buffer,
1302 "<column name=\"name\">%s</column>"
1303 "<column name=\"size\">%u</column>"
1304 "<column name=\"num uses\">%d</column>"
1305 "<column name=\"dependencies\">%s</column>"
1306 "<column name=\"status\">%s</column>"
1307 "<column name=\"address\">%llx</column>"
1317 while (!feof (fp.get ()));
1320 buffer +=
"</osdata>\n";
1334 {
"types",
"Types",
"Listing of info os types you can list",
1336 {
"cpus",
"CPUs",
"Listing of all cpus/cores on the system",
1338 {
"files",
"File descriptors",
"Listing of all file descriptors",
1340 {
"modules",
"Kernel modules",
"Listing of all loaded kernel modules",
1342 {
"msg",
"Message queues",
"Listing of all message queues",
1344 {
"processes",
"Processes",
"Listing of all processes",
1346 {
"procgroups",
"Process groups",
"Listing of all process groups",
1348 {
"semaphores",
"Semaphores",
"Listing of all semaphores",
1350 {
"shm",
"Shared-memory regions",
"Listing of all shared-memory regions",
1352 {
"sockets",
"Sockets",
"Listing of all internet-domain sockets",
1354 {
"threads",
"Threads",
"Listing of all threads",
1356 { NULL, NULL, NULL }
1364 std::string buffer =
"<osdata type=\"types\">\n";
1368 string_xml_appendf (buffer,
1370 "<column name=\"Type\">%s</column>"
1371 "<column name=\"Description\">%s</column>"
1372 "<column name=\"Title\">%s</column>"
1378 buffer +=
"</osdata>\n";
1389 gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
1391 gdb_assert (readbuf);
1396 if (offset >= osd->
buffer.size ())
1403 len = std::min (len, osd->
buffer.size () - offset);
1404 memcpy (readbuf, &osd->
buffer[offset], len);
1412 ULONGEST offset, ULONGEST len)
1414 if (!annex || *annex ==
'\0')
1417 readbuf, offset, len);
1427 readbuf, offset, len);
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int status
static const char * format_socket_state(unsigned char state)
static int get_process_owner(uid_t *owner, PID_T pid)
static int get_cores_used_by_process(PID_T pid, int *cores, const int num_cores)
static LONGEST common_getter(struct osdata_type *osd, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
static std::string linux_xfer_osdata_cpus()
static gdb::optional< size_t > get_core_array_size_using_sys_possible()
static std::string linux_xfer_osdata_modules()
static void user_from_uid(char *user, int maxlen, uid_t uid)
static struct osdata_type osdata_table[]
static size_t get_core_array_size()
static std::string linux_xfer_osdata_processgroups()
static void command_from_pid(char *command, int maxlen, PID_T pid)
static void time_from_time_t(char *time, int maxlen, TIME_T seconds)
static std::string linux_xfer_osdata_sem()
LONGEST linux_common_xfer_osdata(const char *annex, gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
static std::string commandline_from_pid(PID_T pid)
static std::string linux_xfer_osdata_processes()
static std::string linux_xfer_osdata_threads()
static void print_sockets(unsigned short family, int tcp, std::string &buffer)
static std::string linux_xfer_osdata_msg()
int linux_common_core_of_thread(ptid_t ptid)
static void group_from_gid(char *group, int maxlen, gid_t gid)
static std::string linux_xfer_osdata_isockets()
static std::string linux_xfer_osdata_shm()
static std::string linux_xfer_osdata_fds()
static std::string linux_xfer_osdata_info_os_types()
std::string(* take_snapshot)()
pid_pgid_entry(PID_T pid_, PID_T pgid_)
bool operator<(const pid_pgid_entry &other) const