pmap.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * pmap implementation for busybox
  3. *
  4. * Copyright (C) 2010 Nokia Corporation. All rights reserved.
  5. * Written by Alexander Shishkin <virtuoso@slind.org>
  6. *
  7. * Licensed under GPLv2 or later, see the LICENSE file in this source tree
  8. * for details.
  9. */
  10. //config:config PMAP
  11. //config: bool "pmap (6 kb)"
  12. //config: default y
  13. //config: help
  14. //config: Display processes' memory mappings.
  15. //applet:IF_PMAP(APPLET(pmap, BB_DIR_USR_BIN, BB_SUID_DROP))
  16. //kbuild:lib-$(CONFIG_PMAP) += pmap.o
  17. //usage:#define pmap_trivial_usage
  18. //usage: "[-xq] PID..."
  19. //usage:#define pmap_full_usage "\n\n"
  20. //usage: "Display process memory usage"
  21. //usage: "\n"
  22. //usage: "\n -x Show details"
  23. //usage: "\n -q Quiet"
  24. #include "libbb.h"
  25. #if ULONG_MAX == 0xffffffff
  26. # define TABS "\t"
  27. # define AFMT "8"
  28. # define DASHES ""
  29. #else
  30. # define TABS "\t\t"
  31. # define AFMT "16"
  32. # define DASHES "--------"
  33. #endif
  34. enum {
  35. OPT_x = 1 << 0,
  36. OPT_q = 1 << 1,
  37. };
  38. static void print_smaprec(struct smaprec *currec, void *data)
  39. {
  40. unsigned opt = (uintptr_t)data;
  41. printf("%0" AFMT "lx ", currec->smap_start);
  42. if (opt & OPT_x)
  43. printf("%7lu %7lu %7lu %7lu ",
  44. currec->smap_size,
  45. currec->smap_pss,
  46. currec->private_dirty,
  47. currec->smap_swap);
  48. else
  49. printf("%7luK", currec->smap_size);
  50. printf(" %.4s %s\n", currec->smap_mode, currec->smap_name);
  51. }
  52. static int procps_get_maps(pid_t pid, unsigned opt)
  53. {
  54. struct smaprec total;
  55. int ret;
  56. char buf[256];
  57. read_cmdline(buf, sizeof(buf), pid, NULL);
  58. printf("%u: %s\n", (int)pid, buf);
  59. if (!(opt & OPT_q) && (opt & OPT_x))
  60. puts("Address" TABS " Kbytes PSS Dirty Swap Mode Mapping");
  61. memset(&total, 0, sizeof(total));
  62. ret = procps_read_smaps(pid, &total, print_smaprec, (void*)(uintptr_t)opt);
  63. if (ret)
  64. return ret;
  65. if (!(opt & OPT_q)) {
  66. if (opt & OPT_x)
  67. printf("--------" DASHES " ------ ------ ------ ------\n"
  68. "total" TABS " %7lu %7lu %7lu %7lu\n",
  69. total.smap_size, total.smap_pss, total.private_dirty, total.smap_swap);
  70. else
  71. printf("mapped: %luK\n", total.smap_size);
  72. }
  73. return 0;
  74. }
  75. int pmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  76. int pmap_main(int argc UNUSED_PARAM, char **argv)
  77. {
  78. unsigned opts;
  79. int ret;
  80. opts = getopt32(argv, "^" "xq" "\0" "-1"); /* min one arg */
  81. argv += optind;
  82. ret = 0;
  83. while (*argv) {
  84. pid_t pid = xatoi_positive(*argv++);
  85. /* GNU pmap returns 42 if any of the pids failed */
  86. if (procps_get_maps(pid, opts) != 0)
  87. ret = 42;
  88. }
  89. return ret;
  90. }