pmap.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. #if ULLONG_MAX == 0xffffffff
  35. # define AFMTLL "8"
  36. #else
  37. # define AFMTLL "16"
  38. #endif
  39. enum {
  40. OPT_x = 1 << 0,
  41. OPT_q = 1 << 1,
  42. };
  43. static void print_smaprec(struct smaprec *currec, void *data)
  44. {
  45. unsigned opt = (uintptr_t)data;
  46. printf("%0" AFMTLL "llx ", currec->smap_start);
  47. if (opt & OPT_x)
  48. printf("%7lu %7lu %7lu %7lu ",
  49. currec->smap_size,
  50. currec->smap_pss,
  51. currec->private_dirty,
  52. currec->smap_swap);
  53. else
  54. printf("%7luK", currec->smap_size);
  55. printf(" %.4s %s\n", currec->smap_mode, currec->smap_name);
  56. }
  57. static int procps_get_maps(pid_t pid, unsigned opt)
  58. {
  59. struct smaprec total;
  60. int ret;
  61. char buf[256];
  62. read_cmdline(buf, sizeof(buf), pid, NULL);
  63. printf("%u: %s\n", (int)pid, buf);
  64. if (!(opt & OPT_q) && (opt & OPT_x))
  65. puts("Address" TABS " Kbytes PSS Dirty Swap Mode Mapping");
  66. memset(&total, 0, sizeof(total));
  67. ret = procps_read_smaps(pid, &total, print_smaprec, (void*)(uintptr_t)opt);
  68. if (ret)
  69. return ret;
  70. if (!(opt & OPT_q)) {
  71. if (opt & OPT_x)
  72. printf("--------" DASHES " ------ ------ ------ ------\n"
  73. "total" TABS " %7lu %7lu %7lu %7lu\n",
  74. total.smap_size, total.smap_pss, total.private_dirty, total.smap_swap);
  75. else
  76. printf("mapped: %luK\n", total.smap_size);
  77. }
  78. return 0;
  79. }
  80. int pmap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  81. int pmap_main(int argc UNUSED_PARAM, char **argv)
  82. {
  83. unsigned opts;
  84. int ret;
  85. opts = getopt32(argv, "^" "xq" "\0" "-1"); /* min one arg */
  86. argv += optind;
  87. ret = 0;
  88. while (*argv) {
  89. pid_t pid = xatoi_positive(*argv++);
  90. /* GNU pmap returns 42 if any of the pids failed */
  91. if (procps_get_maps(pid, opts) != 0)
  92. ret = 42;
  93. }
  94. return ret;
  95. }