pcprofiledump.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* Dump information generated by PC profiling.
  2. Copyright (C) 1999-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. /* This is mainly an example. It shows how programs which want to use
  17. the information should read the file. */
  18. #ifdef HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <argp.h>
  22. #include <byteswap.h>
  23. #include <errno.h>
  24. #include <error.h>
  25. #include <fcntl.h>
  26. #include <inttypes.h>
  27. #include <libintl.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include <stdint.h>
  32. #include "../version.h"
  33. #define PACKAGE _libc_intl_domainname
  34. #ifndef _
  35. # define _(Str) gettext (Str)
  36. #endif
  37. #ifndef N_
  38. # define N_(Str) Str
  39. #endif
  40. /* Definitions of arguments for argp functions. */
  41. static const struct argp_option options[] =
  42. {
  43. { "unbuffered", 'u', NULL, 0, N_("Don't buffer output") },
  44. { NULL, 0, NULL, 0, NULL }
  45. };
  46. /* Short description of program. */
  47. static const char doc[] = N_("Dump information generated by PC profiling.");
  48. /* Strings for arguments in help texts. */
  49. static const char args_doc[] = N_("[FILE]");
  50. /* Function to print some extra text in the help message. */
  51. static char *more_help (int key, const char *text, void *input);
  52. /* Prototype for option handler. */
  53. static error_t parse_opt (int key, char *arg, struct argp_state *state);
  54. /* Name and version of program. */
  55. static void print_version (FILE *stream, struct argp_state *state);
  56. void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
  57. /* Data structure to communicate with argp functions. */
  58. static struct argp argp =
  59. {
  60. options, parse_opt, args_doc, doc, NULL, more_help
  61. };
  62. int
  63. main (int argc, char *argv[])
  64. {
  65. /* Set locale via LC_ALL. */
  66. setlocale (LC_ALL, "");
  67. /* Set the text message domain. */
  68. textdomain (PACKAGE);
  69. /* Parse and process arguments. */
  70. int remaining;
  71. argp_parse (&argp, argc, argv, 0, &remaining, NULL);
  72. int fd;
  73. if (remaining == argc)
  74. fd = STDIN_FILENO;
  75. else if (remaining + 1 != argc)
  76. {
  77. argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
  78. program_invocation_short_name);
  79. exit (1);
  80. }
  81. else
  82. {
  83. /* Open the given file. */
  84. fd = open (argv[remaining], O_RDONLY);
  85. if (fd == -1)
  86. error (EXIT_FAILURE, errno, _("cannot open input file"));
  87. }
  88. /* Read the first 4-byte word. It contains the information about
  89. the word size and the endianess. */
  90. uint32_t word;
  91. if (TEMP_FAILURE_RETRY (read (fd, &word, 4)) != 4)
  92. error (EXIT_FAILURE, errno, _("cannot read header"));
  93. /* Check whether we have to swap the byte order. */
  94. int must_swap = (word & 0x0fffffff) == bswap_32 (0xdeb00000);
  95. if (must_swap)
  96. word = bswap_32 (word);
  97. /* We have two loops, one for 32 bit pointers, one for 64 bit pointers. */
  98. if (word == 0xdeb00004)
  99. {
  100. union
  101. {
  102. uint32_t ptrs[2];
  103. char bytes[8];
  104. } pair;
  105. while (1)
  106. {
  107. size_t len = sizeof (pair);
  108. size_t n;
  109. while (len > 0
  110. && (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
  111. len))) != 0)
  112. len -= n;
  113. if (len != 0)
  114. /* Nothing to read. */
  115. break;
  116. printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
  117. must_swap ? bswap_32 (pair.ptrs[0]) : pair.ptrs[0],
  118. must_swap ? bswap_32 (pair.ptrs[1]) : pair.ptrs[1]);
  119. }
  120. }
  121. else if (word == 0xdeb00008)
  122. {
  123. union
  124. {
  125. uint64_t ptrs[2];
  126. char bytes[16];
  127. } pair;
  128. while (1)
  129. {
  130. size_t len = sizeof (pair);
  131. size_t n;
  132. while (len > 0
  133. && (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
  134. len))) != 0)
  135. len -= n;
  136. if (len != 0)
  137. /* Nothing to read. */
  138. break;
  139. printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
  140. must_swap ? bswap_64 (pair.ptrs[0]) : pair.ptrs[0],
  141. must_swap ? bswap_64 (pair.ptrs[1]) : pair.ptrs[1]);
  142. }
  143. }
  144. else
  145. /* This should not happen. */
  146. error (EXIT_FAILURE, 0, _("invalid pointer size"));
  147. /* Clean up. */
  148. close (fd);
  149. return 0;
  150. }
  151. static error_t
  152. parse_opt (int key, char *arg, struct argp_state *state)
  153. {
  154. switch (key)
  155. {
  156. case 'u':
  157. setbuf (stdout, NULL);
  158. break;
  159. default:
  160. return ARGP_ERR_UNKNOWN;
  161. }
  162. return 0;
  163. }
  164. static char *
  165. more_help (int key, const char *text, void *input)
  166. {
  167. char *tp = NULL;
  168. switch (key)
  169. {
  170. case ARGP_KEY_HELP_EXTRA:
  171. /* We print some extra information. */
  172. if (asprintf (&tp, gettext ("\
  173. For bug reporting instructions, please see:\n\
  174. %s.\n"), REPORT_BUGS_TO) < 0)
  175. return NULL;
  176. return tp;
  177. default:
  178. break;
  179. }
  180. return (char *) text;
  181. }
  182. /* Print the version information. */
  183. static void
  184. print_version (FILE *stream, struct argp_state *state)
  185. {
  186. fprintf (stream, "pcprofiledump %s%s\n", PKGVERSION, VERSION);
  187. fprintf (stream, gettext ("\
  188. Copyright (C) %s Free Software Foundation, Inc.\n\
  189. This is free software; see the source for copying conditions. There is NO\n\
  190. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
  191. "), "2019");
  192. fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
  193. }