pcprofile.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /* Profile PC and write result to FIFO.
  2. Copyright (C) 1999-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <stdint.h>
  18. #include <stdlib.h>
  19. #include <unistd.h>
  20. /* Nonzero if we are actually doing something. */
  21. static int active;
  22. /* The file descriptor of the FIFO. */
  23. static int fd;
  24. static void
  25. __attribute__ ((constructor))
  26. install (void)
  27. {
  28. /* See whether the environment variable `PCPROFILE_OUTPUT' is defined.
  29. If yes, it should name a FIFO. We open it and mark ourself as active. */
  30. const char *outfile = getenv ("PCPROFILE_OUTPUT");
  31. if (outfile != NULL && *outfile != '\0')
  32. {
  33. fd = open (outfile, O_RDWR | O_CREAT, 0666);
  34. if (fd != -1)
  35. {
  36. uint32_t word;
  37. active = 1;
  38. /* Write a magic word which tells the reader about the byte
  39. order and the size of the following entries. */
  40. word = 0xdeb00000 | sizeof (void *);
  41. if (TEMP_FAILURE_RETRY (write (fd, &word, 4)) != 4)
  42. {
  43. /* If even this fails we shouldn't try further. */
  44. close (fd);
  45. fd = -1;
  46. active = 0;
  47. }
  48. }
  49. }
  50. }
  51. static void
  52. __attribute__ ((destructor))
  53. uninstall (void)
  54. {
  55. if (active)
  56. close (fd);
  57. }
  58. void
  59. __cyg_profile_func_enter (void *this_fn, void *call_site)
  60. {
  61. void *buf[2];
  62. if (! active)
  63. return;
  64. /* Now write out the current position and that of the caller. We do
  65. this now, and don't cache the because we want real-time output. */
  66. buf[0] = this_fn;
  67. buf[1] = call_site;
  68. write (fd, buf, sizeof buf);
  69. }
  70. /* We don't handle entry and exit differently here. */
  71. strong_alias (__cyg_profile_func_enter, __cyg_profile_func_exit)