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