Blame malloc/memusagestat.c

Packit Service 82fcde
/* Generate graphic from memory profiling data.
Packit Service 82fcde
   Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Packit Service 82fcde
Packit Service 82fcde
   This program is free software; you can redistribute it and/or modify
Packit Service 82fcde
   it under the terms of the GNU General Public License as published
Packit Service 82fcde
   by the Free Software Foundation; version 2 of the License, or
Packit Service 82fcde
   (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   This program is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 82fcde
   GNU General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU General Public License
Packit Service 82fcde
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#define _FILE_OFFSET_BITS 64
Packit Service 82fcde
Packit Service 82fcde
#include <argp.h>
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <error.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <getopt.h>
Packit Service 82fcde
#include <inttypes.h>
Packit Service 82fcde
#include <libintl.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <sys/stat.h>
Packit Service 82fcde
Packit Service 82fcde
#include <gd.h>
Packit Service 82fcde
#include <gdfontl.h>
Packit Service 82fcde
#include <gdfonts.h>
Packit Service 82fcde
Packit Service 82fcde
#include "../version.h"
Packit Service 82fcde
#define PACKAGE _libc_intl_domainname
Packit Service 82fcde
Packit Service 82fcde
/* Default size of the generated image.  */
Packit Service 82fcde
#define XSIZE 800
Packit Service 82fcde
#define YSIZE 600
Packit Service 82fcde
Packit Service 82fcde
#ifndef N_
Packit Service 82fcde
# define N_(Arg) Arg
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Definitions of arguments for argp functions.  */
Packit Service 82fcde
static const struct argp_option options[] =
Packit Service 82fcde
{
Packit Service 82fcde
  { "output", 'o', N_ ("FILE"), 0, N_ ("Name output file") },
Packit Service 82fcde
  { "string", 's', N_ ("STRING"), 0, N_ ("Title string used in output graphic") },
Packit Service 82fcde
  { "time", 't', NULL, 0, N_ ("\
Packit Service 82fcde
Generate output linear to time (default is linear to number of function calls)\
Packit Service 82fcde
") },
Packit Service 82fcde
  { "total", 'T', NULL, 0,
Packit Service 82fcde
    N_ ("Also draw graph for total memory consumption") },
Packit Service 82fcde
  { "x-size", 'x', N_ ("VALUE"), 0,
Packit Service 82fcde
    N_ ("Make output graphic VALUE pixels wide") },
Packit Service 82fcde
  { "y-size", 'y', "VALUE", 0, N_ ("Make output graphic VALUE pixels high") },
Packit Service 82fcde
  { NULL, 0, NULL, 0, NULL }
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Short description of program.  */
Packit Service 82fcde
static const char doc[] = N_ ("Generate graphic from memory profiling data");
Packit Service 82fcde
Packit Service 82fcde
/* Strings for arguments in help texts.  */
Packit Service 82fcde
static const char args_doc[] = N_ ("DATAFILE [OUTFILE]");
Packit Service 82fcde
Packit Service 82fcde
/* Prototype for option handler.  */
Packit Service 82fcde
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit Service 82fcde
Packit Service 82fcde
/* Function to print some extra text in the help message.  */
Packit Service 82fcde
static char *more_help (int key, const char *text, void *input);
Packit Service 82fcde
Packit Service 82fcde
/* Name and version of program.  */
Packit Service 82fcde
static void print_version (FILE *stream, struct argp_state *state);
Packit Service 82fcde
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
Packit Service 82fcde
Packit Service 82fcde
/* Data structure to communicate with argp functions.  */
Packit Service 82fcde
static struct argp argp =
Packit Service 82fcde
{
Packit Service 82fcde
  options, parse_opt, args_doc, doc, NULL, more_help
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct entry
Packit Service 82fcde
{
Packit Service 82fcde
  uint64_t heap;
Packit Service 82fcde
  uint64_t stack;
Packit Service 82fcde
  uint32_t time_low;
Packit Service 82fcde
  uint32_t time_high;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Size of the image.  */
Packit Service 82fcde
static size_t xsize;
Packit Service 82fcde
static size_t ysize;
Packit Service 82fcde
Packit Service 82fcde
/* Name of the output file.  */
Packit Service 82fcde
static char *outname;
Packit Service 82fcde
Packit Service 82fcde
/* Title string for the graphic.  */
Packit Service 82fcde
static const char *string;
Packit Service 82fcde
Packit Service 82fcde
/* Nonzero if graph should be generated linear in time.  */
Packit Service 82fcde
static int time_based;
Packit Service 82fcde
Packit Service 82fcde
/* Nonzero if graph to display total use of memory should be drawn as well.  */
Packit Service 82fcde
static int also_total = 0;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
main (int argc, char *argv[])
Packit Service 82fcde
{
Packit Service 82fcde
  int remaining;
Packit Service 82fcde
  const char *inname;
Packit Service 82fcde
  gdImagePtr im_out;
Packit Service 82fcde
  int grey, blue, red, green, yellow, black;
Packit Service 82fcde
  int fd;
Packit Service 82fcde
  struct stat st;
Packit Service 82fcde
  size_t maxsize_heap;
Packit Service 82fcde
  size_t maxsize_stack;
Packit Service 82fcde
  size_t maxsize_total;
Packit Service 82fcde
  uint64_t total;
Packit Service 82fcde
  uint64_t cnt, cnt2;
Packit Service 82fcde
  FILE *outfile;
Packit Service 82fcde
  char buf[30];
Packit Service 82fcde
  size_t last_heap;
Packit Service 82fcde
  size_t last_stack;
Packit Service 82fcde
  size_t last_total;
Packit Service 82fcde
  struct entry headent[2];
Packit Service 82fcde
  uint64_t start_time;
Packit Service 82fcde
  uint64_t end_time;
Packit Service 82fcde
  uint64_t total_time;
Packit Service 82fcde
  const char *heap_format, *stack_format;
Packit Service 82fcde
  int heap_scale, stack_scale, line;
Packit Service 82fcde
Packit Service 82fcde
  outname = NULL;
Packit Service 82fcde
  xsize = XSIZE;
Packit Service 82fcde
  ysize = YSIZE;
Packit Service 82fcde
  string = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* Parse and process arguments.  */
Packit Service 82fcde
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit Service 82fcde
Packit Service 82fcde
  if (remaining >= argc || remaining + 2 < argc)
Packit Service 82fcde
    {
Packit Service 82fcde
      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
Packit Service 82fcde
                 program_invocation_short_name);
Packit Service 82fcde
      exit (1);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  inname = argv[remaining++];
Packit Service 82fcde
Packit Service 82fcde
  if (remaining < argc)
Packit Service 82fcde
    outname = argv[remaining];
Packit Service 82fcde
  else if (outname == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t len = strlen (inname);
Packit Service 82fcde
      outname = alloca (len + 5);
Packit Service 82fcde
      stpcpy (stpcpy (outname, inname), ".png");
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Open for read/write since we try to repair the file in case the
Packit Service 82fcde
     application hasn't terminated cleanly.  */
Packit Service 82fcde
  fd = open (inname, O_RDWR);
Packit Service 82fcde
  if (fd == -1)
Packit Service 82fcde
    error (EXIT_FAILURE, errno, "cannot open input file");
Packit Service 82fcde
  if (fstat (fd, &st) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      error (EXIT_FAILURE, errno, "cannot get size of input file");
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Test whether the file contains only full records.  */
Packit Service 82fcde
  if ((st.st_size % sizeof (struct entry)) != 0
Packit Service 82fcde
      /* The file must at least contain the two administrative records.  */
Packit Service 82fcde
      || st.st_size < 2 * sizeof (struct entry))
Packit Service 82fcde
    {
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      error (EXIT_FAILURE, 0, "input file has incorrect size");
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Compute number of data entries.  */
Packit Service 82fcde
  total = st.st_size / sizeof (struct entry) - 2;
Packit Service 82fcde
Packit Service 82fcde
  /* Read the administrative information.  */
Packit Service 82fcde
  read (fd, headent, sizeof (headent));
Packit Service 82fcde
  maxsize_heap = headent[1].heap;
Packit Service 82fcde
  maxsize_stack = headent[1].stack;
Packit Service 82fcde
  maxsize_total = headent[0].stack;
Packit Service 82fcde
Packit Service 82fcde
  if (maxsize_heap == 0 && maxsize_stack == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* The program aborted before memusage was able to write the
Packit Service 82fcde
         information about the maximum heap and stack use.  Repair
Packit Service 82fcde
         the file now.  */
Packit Service 82fcde
      struct entry next;
Packit Service 82fcde
Packit Service 82fcde
      while (1)
Packit Service 82fcde
        {
Packit Service 82fcde
          if (read (fd, &next, sizeof (next)) == 0)
Packit Service 82fcde
            break;
Packit Service 82fcde
          if (next.heap > maxsize_heap)
Packit Service 82fcde
            maxsize_heap = next.heap;
Packit Service 82fcde
          if (next.stack > maxsize_stack)
Packit Service 82fcde
            maxsize_stack = next.stack;
Packit Service 82fcde
          if (maxsize_heap + maxsize_stack > maxsize_total)
Packit Service 82fcde
            maxsize_total = maxsize_heap + maxsize_stack;
Packit Service 82fcde
        }
Packit Service 82fcde
Packit Service 82fcde
      headent[0].stack = maxsize_total;
Packit Service 82fcde
      headent[1].heap = maxsize_heap;
Packit Service 82fcde
      headent[1].stack = maxsize_stack;
Packit Service 82fcde
      headent[1].time_low = next.time_low;
Packit Service 82fcde
      headent[1].time_high = next.time_high;
Packit Service 82fcde
Packit Service 82fcde
      /* Write the computed values in the file.  */
Packit Service 82fcde
      lseek (fd, 0, SEEK_SET);
Packit Service 82fcde
      write (fd, headent, 2 * sizeof (struct entry));
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (also_total)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We use one scale and since we also draw the total amount of
Packit Service 82fcde
         memory used we have to adapt the maximum.  */
Packit Service 82fcde
      maxsize_heap = maxsize_total;
Packit Service 82fcde
      maxsize_stack = maxsize_total;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  start_time = ((uint64_t) headent[0].time_high) << 32 | headent[0].time_low;
Packit Service 82fcde
  end_time = ((uint64_t) headent[1].time_high) << 32 | headent[1].time_low;
Packit Service 82fcde
  total_time = end_time - start_time;
Packit Service 82fcde
Packit Service 82fcde
  if (xsize < 100)
Packit Service 82fcde
    xsize = 100;
Packit Service 82fcde
  if (ysize < 80)
Packit Service 82fcde
    ysize = 80;
Packit Service 82fcde
Packit Service 82fcde
  /* Create output image with the specified size.  */
Packit Service 82fcde
  im_out = gdImageCreate (xsize, ysize);
Packit Service 82fcde
Packit Service 82fcde
  /* First color allocated is background.  */
Packit Service 82fcde
  grey = gdImageColorAllocate (im_out, 224, 224, 224);
Packit Service 82fcde
Packit Service 82fcde
  /* Set transparent color. */
Packit Service 82fcde
  gdImageColorTransparent (im_out, grey);
Packit Service 82fcde
Packit Service 82fcde
  /* These are all the other colors we need (in the moment).  */
Packit Service 82fcde
  red = gdImageColorAllocate (im_out, 255, 0, 0);
Packit Service 82fcde
  green = gdImageColorAllocate (im_out, 0, 130, 0);
Packit Service 82fcde
  blue = gdImageColorAllocate (im_out, 0, 0, 255);
Packit Service 82fcde
  yellow = gdImageColorAllocate (im_out, 154, 205, 50);
Packit Service 82fcde
  black = gdImageColorAllocate (im_out, 0, 0, 0);
Packit Service 82fcde
Packit Service 82fcde
  gdImageRectangle (im_out, 40, 20, xsize - 40, ysize - 20, blue);
Packit Service 82fcde
Packit Service 82fcde
  if (maxsize_heap < 1024)
Packit Service 82fcde
    {
Packit Service 82fcde
      heap_format = "%Zu";
Packit Service 82fcde
      heap_scale = 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (maxsize_heap < 1024 * 1024 * 100)
Packit Service 82fcde
    {
Packit Service 82fcde
      heap_format = "%Zuk";
Packit Service 82fcde
      heap_scale = 1024;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      heap_format = "%ZuM";
Packit Service 82fcde
      heap_scale = 1024 * 1024;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (maxsize_stack < 1024)
Packit Service 82fcde
    {
Packit Service 82fcde
      stack_format = "%Zu";
Packit Service 82fcde
      stack_scale = 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (maxsize_stack < 1024 * 1024 * 100)
Packit Service 82fcde
    {
Packit Service 82fcde
      stack_format = "%Zuk";
Packit Service 82fcde
      stack_scale = 1024;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      stack_format = "%ZuM";
Packit Service 82fcde
      stack_scale = 1024 * 1024;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, 38, ysize - 14, (unsigned char *) "0",
Packit Service 82fcde
                 blue);
Packit Service 82fcde
  snprintf (buf, sizeof (buf), heap_format, 0);
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, maxsize_heap < 1024 ? 32 : 26,
Packit Service 82fcde
                 ysize - 26, (unsigned char *) buf, red);
Packit Service 82fcde
  snprintf (buf, sizeof (buf), stack_format, 0);
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26,
Packit Service 82fcde
                 (unsigned char *) buf, green);
Packit Service 82fcde
Packit Service 82fcde
  if (string != NULL)
Packit Service 82fcde
    gdImageString (im_out, gdFontLarge, (xsize - strlen (string) * 8) / 2,
Packit Service 82fcde
                   2, (unsigned char *) string, green);
Packit Service 82fcde
Packit Service 82fcde
  gdImageStringUp (im_out, gdFontSmall, 1, ysize / 2 - 10,
Packit Service 82fcde
                   (unsigned char *) "allocated", red);
Packit Service 82fcde
  gdImageStringUp (im_out, gdFontSmall, 11, ysize / 2 - 10,
Packit Service 82fcde
                   (unsigned char *) "memory", red);
Packit Service 82fcde
Packit Service 82fcde
  gdImageStringUp (im_out, gdFontSmall, xsize - 39, ysize / 2 - 10,
Packit Service 82fcde
                   (unsigned char *) "used", green);
Packit Service 82fcde
  gdImageStringUp (im_out, gdFontSmall, xsize - 27, ysize / 2 - 10,
Packit Service 82fcde
                   (unsigned char *) "stack", green);
Packit Service 82fcde
Packit Service 82fcde
  snprintf (buf, sizeof (buf), heap_format, maxsize_heap / heap_scale);
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6, 14,
Packit Service 82fcde
                 (unsigned char *) buf, red);
Packit Service 82fcde
  snprintf (buf, sizeof (buf), stack_format, maxsize_stack / stack_scale);
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, xsize - 37, 14,
Packit Service 82fcde
                 (unsigned char *) buf, green);
Packit Service 82fcde
Packit Service 82fcde
  for (line = 1; line <= 3; ++line)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (maxsize_heap > 0)
Packit Service 82fcde
        {
Packit Service 82fcde
          cnt = (((ysize - 40) * (maxsize_heap / 4 * line / heap_scale))
Packit Service 82fcde
                 / (maxsize_heap / heap_scale));
Packit Service 82fcde
          gdImageDashedLine (im_out, 40, ysize - 20 - cnt, xsize - 40,
Packit Service 82fcde
                             ysize - 20 - cnt, red);
Packit Service 82fcde
          snprintf (buf, sizeof (buf), heap_format,
Packit Service 82fcde
                    maxsize_heap / 4 * line / heap_scale);
Packit Service 82fcde
          gdImageString (im_out, gdFontSmall, 39 - strlen (buf) * 6,
Packit Service 82fcde
                         ysize - 26 - cnt, (unsigned char *) buf, red);
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        cnt = 0;
Packit Service 82fcde
Packit Service 82fcde
      if (maxsize_stack > 0)
Packit Service 82fcde
        cnt2 = (((ysize - 40) * (maxsize_stack / 4 * line / stack_scale))
Packit Service 82fcde
                / (maxsize_stack / stack_scale));
Packit Service 82fcde
      else
Packit Service 82fcde
        cnt2 = 0;
Packit Service 82fcde
Packit Service 82fcde
      if (cnt != cnt2)
Packit Service 82fcde
        gdImageDashedLine (im_out, 40, ysize - 20 - cnt2, xsize - 40,
Packit Service 82fcde
                           ysize - 20 - cnt2, green);
Packit Service 82fcde
      snprintf (buf, sizeof (buf), stack_format, maxsize_stack / 4 * line /
Packit Service 82fcde
                stack_scale);
Packit Service 82fcde
      gdImageString (im_out, gdFontSmall, xsize - 37, ysize - 26 - cnt2,
Packit Service 82fcde
                     (unsigned char *) buf, green);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  snprintf (buf, sizeof (buf), "%llu", (unsigned long long) total);
Packit Service 82fcde
  gdImageString (im_out, gdFontSmall, xsize - 50, ysize - 14,
Packit Service 82fcde
                 (unsigned char *) buf, blue);
Packit Service 82fcde
Packit Service 82fcde
  if (!time_based)
Packit Service 82fcde
    {
Packit Service 82fcde
      uint64_t previously = start_time;
Packit Service 82fcde
Packit Service 82fcde
      gdImageString (im_out, gdFontSmall, 40 + (xsize - 32 * 6 - 80) / 2,
Packit Service 82fcde
                     ysize - 12,
Packit Service 82fcde
                     (unsigned char *) "# memory handling function calls",
Packit Service 82fcde
                     blue);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
      last_stack = last_heap = last_total = ysize - 20;
Packit Service 82fcde
      for (cnt = 1; cnt <= total; ++cnt)
Packit Service 82fcde
        {
Packit Service 82fcde
          struct entry entry;
Packit Service 82fcde
          size_t new[2];
Packit Service 82fcde
          uint64_t now;
Packit Service 82fcde
Packit Service 82fcde
          read (fd, &entry, sizeof (entry));
Packit Service 82fcde
Packit Service 82fcde
          now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
Packit Service 82fcde
Packit Service 82fcde
          if ((((previously - start_time) * 100) / total_time) % 10 < 5)
Packit Service 82fcde
            gdImageFilledRectangle (im_out,
Packit Service 82fcde
                                    40 + ((cnt - 1) * (xsize - 80)) / total,
Packit Service 82fcde
                                    ysize - 19,
Packit Service 82fcde
                                    39 + (cnt * (xsize - 80)) / total,
Packit Service 82fcde
                                    ysize - 14, yellow);
Packit Service 82fcde
          previously = now;
Packit Service 82fcde
Packit Service 82fcde
          if (also_total && maxsize_heap > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              size_t new3;
Packit Service 82fcde
Packit Service 82fcde
              new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                                      * (entry.heap + entry.stack))
Packit Service 82fcde
                                     / maxsize_heap);
Packit Service 82fcde
              gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
Packit Service 82fcde
                           last_total,
Packit Service 82fcde
                           40 + ((xsize - 80) * cnt) / total, new3,
Packit Service 82fcde
                           black);
Packit Service 82fcde
              last_total = new3;
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          if (maxsize_heap > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              new[0] = ((ysize - 20)
Packit Service 82fcde
                        - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                            * entry.heap) / maxsize_heap));
Packit Service 82fcde
              gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
Packit Service 82fcde
                           last_heap, 40 + ((xsize - 80) * cnt) / total,
Packit Service 82fcde
                           new[0], red);
Packit Service 82fcde
              last_heap = new[0];
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          if (maxsize_stack > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              new[1] = ((ysize - 20)
Packit Service 82fcde
                        - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                            * entry.stack) / maxsize_stack));
Packit Service 82fcde
              gdImageLine (im_out, 40 + ((xsize - 80) * (cnt - 1)) / total,
Packit Service 82fcde
                           last_stack, 40 + ((xsize - 80) * cnt) / total,
Packit Service 82fcde
                           new[1], green);
Packit Service 82fcde
              last_stack = new[1];
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 82fcde
Packit Service 82fcde
      cnt = 0;
Packit Service 82fcde
      while (cnt < total)
Packit Service 82fcde
        {
Packit Service 82fcde
          gdImageLine (im_out, 40 + ((xsize - 80) * cnt) / total, ysize - 20,
Packit Service 82fcde
                       40 + ((xsize - 80) * cnt) / total, ysize - 15, blue);
Packit Service 82fcde
          cnt += MAX (1, total / 20);
Packit Service 82fcde
        }
Packit Service 82fcde
      gdImageLine (im_out, xsize - 40, ysize - 20, xsize - 40, ysize - 15,
Packit Service 82fcde
                   blue);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      uint64_t next_tick = MAX (1, total / 20);
Packit Service 82fcde
      size_t last_xpos = 40;
Packit Service 82fcde
Packit Service 82fcde
      gdImageString (im_out, gdFontSmall, 40 + (xsize - 39 * 6 - 80) / 2,
Packit Service 82fcde
                     ysize - 12,
Packit Service 82fcde
                     (unsigned char *) "				      \
Packit Service 82fcde
# memory handling function calls / time", blue);
Packit Service 82fcde
Packit Service 82fcde
      for (cnt = 0; cnt < 20; cnt += 2)
Packit Service 82fcde
        gdImageFilledRectangle (im_out,
Packit Service 82fcde
                                40 + (cnt * (xsize - 80)) / 20, ysize - 19,
Packit Service 82fcde
                                39 + ((cnt + 1) * (xsize - 80)) / 20,
Packit Service 82fcde
                                ysize - 14, yellow);
Packit Service 82fcde
Packit Service 82fcde
      last_stack = last_heap = last_total = ysize - 20;
Packit Service 82fcde
      for (cnt = 1; cnt <= total; ++cnt)
Packit Service 82fcde
        {
Packit Service 82fcde
          struct entry entry;
Packit Service 82fcde
          size_t new[2];
Packit Service 82fcde
          size_t xpos;
Packit Service 82fcde
          uint64_t now;
Packit Service 82fcde
Packit Service 82fcde
          read (fd, &entry, sizeof (entry));
Packit Service 82fcde
Packit Service 82fcde
          now = ((uint64_t) entry.time_high) << 32 | entry.time_low;
Packit Service 82fcde
          xpos = 40 + ((xsize - 80) * (now - start_time)) / total_time;
Packit Service 82fcde
Packit Service 82fcde
          if (cnt == next_tick)
Packit Service 82fcde
            {
Packit Service 82fcde
              gdImageLine (im_out, xpos, ysize - 20, xpos, ysize - 15, blue);
Packit Service 82fcde
              next_tick += MAX (1, total / 20);
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          if (also_total && maxsize_heap > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              size_t new3;
Packit Service 82fcde
Packit Service 82fcde
              new3 = (ysize - 20) - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                                      * (entry.heap + entry.stack))
Packit Service 82fcde
                                     / maxsize_heap);
Packit Service 82fcde
              gdImageLine (im_out, last_xpos, last_total, xpos, new3, black);
Packit Service 82fcde
              last_total = new3;
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          if (maxsize_heap > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              new[0] = ((ysize - 20)
Packit Service 82fcde
                        - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                            * entry.heap) / maxsize_heap));
Packit Service 82fcde
              gdImageLine (im_out, last_xpos, last_heap, xpos, new[0], red);
Packit Service 82fcde
              last_heap = new[0];
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          if (maxsize_stack > 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              new[1] = ((ysize - 20)
Packit Service 82fcde
                        - ((((unsigned long long int) (ysize - 40))
Packit Service 82fcde
                            * entry.stack) / maxsize_stack));
Packit Service 82fcde
              gdImageLine (im_out, last_xpos, last_stack, xpos, new[1],
Packit Service 82fcde
                           green);
Packit Service 82fcde
              last_stack = new[1];
Packit Service 82fcde
            }
Packit Service 82fcde
Packit Service 82fcde
          last_xpos = xpos;
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Write out the result.  */
Packit Service 82fcde
  outfile = fopen (outname, "w");
Packit Service 82fcde
  if (outfile == NULL)
Packit Service 82fcde
    error (EXIT_FAILURE, errno, "cannot open output file");
Packit Service 82fcde
Packit Service 82fcde
  gdImagePng (im_out, outfile);
Packit Service 82fcde
Packit Service 82fcde
  fclose (outfile);
Packit Service 82fcde
Packit Service 82fcde
  gdImageDestroy (im_out);
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Handle program arguments.  */
Packit Service 82fcde
static error_t
Packit Service 82fcde
parse_opt (int key, char *arg, struct argp_state *state)
Packit Service 82fcde
{
Packit Service 82fcde
  switch (key)
Packit Service 82fcde
    {
Packit Service 82fcde
    case 'o':
Packit Service 82fcde
      outname = arg;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 's':
Packit Service 82fcde
      string = arg;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 't':
Packit Service 82fcde
      time_based = 1;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 'T':
Packit Service 82fcde
      also_total = 1;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 'x':
Packit Service 82fcde
      xsize = atoi (arg);
Packit Service 82fcde
      if (xsize == 0)
Packit Service 82fcde
        xsize = XSIZE;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 'y':
Packit Service 82fcde
      ysize = atoi (arg);
Packit Service 82fcde
      if (ysize == 0)
Packit Service 82fcde
        ysize = XSIZE;
Packit Service 82fcde
      break;
Packit Service 82fcde
    default:
Packit Service 82fcde
      return ARGP_ERR_UNKNOWN;
Packit Service 82fcde
    }
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static char *
Packit Service 82fcde
more_help (int key, const char *text, void *input)
Packit Service 82fcde
{
Packit Service 82fcde
  char *tp;
Packit Service 82fcde
Packit Service 82fcde
  switch (key)
Packit Service 82fcde
    {
Packit Service 82fcde
    case ARGP_KEY_HELP_EXTRA:
Packit Service 82fcde
      /* We print some extra information.  */
Packit Service 82fcde
      if (asprintf (&tp, gettext ("\
Packit Service 82fcde
For bug reporting instructions, please see:\n\
Packit Service 82fcde
%s.\n"), REPORT_BUGS_TO) < 0)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      return tp;
Packit Service 82fcde
Packit Service 82fcde
    default:
Packit Service 82fcde
      break;
Packit Service 82fcde
    }
Packit Service 82fcde
  return (char *) text;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Print the version information.  */
Packit Service 82fcde
static void
Packit Service 82fcde
print_version (FILE *stream, struct argp_state *state)
Packit Service 82fcde
{
Packit Service 82fcde
  fprintf (stream, "memusagestat %s%s\n", PKGVERSION, VERSION);
Packit Service 82fcde
  fprintf (stream, gettext ("\
Packit Service 82fcde
Copyright (C) %s Free Software Foundation, Inc.\n\
Packit Service 82fcde
This is free software; see the source for copying conditions.  There is NO\n\
Packit Service 82fcde
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Packit Service 82fcde
"), "2018");
Packit Service 82fcde
  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
Packit Service 82fcde
}