Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

cmd_strace.c

/*
 * $Id: cmd_strace.c,v 1.1 2004/12/21 23:26:19 tjm Exp $
 *
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, and others
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <lcrash.h>

/* Forward declaration
 */
void strace_usage(command_t *);

/* 
 * strace_cmd() -- Command for building stack traces. It either builds
 *                 all possible stack traces (with or without errors)
 *                 contained in a given a stack.  Or, it builds a specific
 *                 backtrace -- using PC, SP and STACK addresses.
 */
int
strace_cmd(command_t *cmd)
{
      int level = 3;
      kaddr_t pc, sp, saddr;
      uint64_t value;
      trace_t *trace; 

      if (cmd->flags & C_LIST) {
            GET_VALUE(cmd->args[0], &value);
            if (KL_ERROR) {
                  strace_usage(cmd);
                  return(1);
            }
            saddr = (kaddr_t)value;
            DO_LIST(saddr, STACK_SIZE, cmd->ofp);
      } else if (cmd->nargs <= 2) {
            GET_VALUE(cmd->args[0], &value);
            if (KL_ERROR) {
                  strace_usage(cmd);
                  return(1);
            }
            saddr = (kaddr_t)value;
            if (cmd->nargs == 2) {
                  GET_VALUE(cmd->args[1], &value);
                  level = (int)value;
            }
            PRINT_TRACES(saddr, level, cmd->flags, cmd->ofp);
      } else if (KL_ARCH == KL_ARCH_IA64) {

            kaddr_t bsp, cfm, task;

            if (cmd->nargs != 4) {
                  strace_usage(cmd);
                  return(1);
            }
            GET_VALUE(cmd->args[0], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_PC;
                  return(1);
            }
            pc = (kaddr_t)value;
            GET_VALUE(cmd->args[1], &value);
            if (KL_ERROR) {
                  return(1);
            }
            bsp = (kaddr_t)value;
            GET_VALUE(cmd->args[2], &value);
            if (KL_ERROR) {
                  return(1);
            }
            cfm = (kaddr_t)value;
            GET_VALUE(cmd->args[3], &value);
            if (KL_ERROR) {
                  return(1);
            }
            task = (kaddr_t)value;
            trace = (trace_t *)alloc_trace_rec(K_TEMP);
            if (!trace) {
                  fprintf(KL_ERRORFP, "Could not alloc trace rec!\n");
            } else {
                  saddr = KL_KERNELSTACK_UINT64(task);
                  SETUP_TRACE_REC(saddr, task, 0, trace);
                  FIND_TRACE(pc, bsp, cfm, 0, trace, 0);
                  if (KL_ERROR) {
                        fprintf(KL_ERRORFP, 
                              "Could not find a valid trace!\n");
                        return(1);  
                  }
                  fprintf(cmd->ofp, "\nPC="); 
                  print_kaddr(pc, cmd->ofp, 0);
                  fprintf(cmd->ofp, "  BSP="); 
                  print_kaddr(bsp, cmd->ofp, 0);
                  fprintf(cmd->ofp, "  CFM="); 
                  print_kaddr(cfm, cmd->ofp, 0);
                  fprintf(cmd->ofp, "\n");
                  trace_banner(cmd->ofp);
                  PRINT_TRACE(trace, cmd->flags, cmd->ofp);
                  trace_banner(cmd->ofp);
                  free_trace_rec(trace);
            }
      } else if (cmd->nargs == 3) {
            GET_VALUE(cmd->args[0], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_PC;
                  return(1);
            }
            pc = (kaddr_t)value; 
            GET_VALUE(cmd->args[1], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_SP;
                  return(1);
            }
            sp = (kaddr_t)value;
            GET_VALUE(cmd->args[2], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_SADDR;
                  return(1);
            }
            saddr = (kaddr_t)value;

            trace = (trace_t *)alloc_trace_rec(K_TEMP);
            if (!trace) {
                  fprintf(KL_ERRORFP, "Could not alloc trace rec!\n");
                  return(1);
            } else {
                  SETUP_TRACE_REC(saddr, 0, 0, trace);
                  FIND_TRACE(pc, sp, 0, 0, trace, 0);
                  if (KL_ERROR) {
                        return(1);  
                  }
                  fprintf(cmd->ofp, "\nPC="); 
                  print_kaddr(pc, cmd->ofp, 0);
                  fprintf(cmd->ofp, "  SP="); 
                  print_kaddr(sp, cmd->ofp, 0);
                  fprintf(cmd->ofp, "  SADDR="); 
                  print_kaddr(saddr, cmd->ofp, 0);
                  fprintf(cmd->ofp, "\n");
                  trace_banner(cmd->ofp);
                  PRINT_TRACE(trace, cmd->flags, cmd->ofp);
                  trace_banner(cmd->ofp);
                  free_trace_rec(trace);
            }
      } else {
            strace_usage(cmd);
            return(1);
      } 
      return(0);
}

#define _STRACE_USAGE \
      "[-a] [-l] [-f] [-w outfile] [pc sp] stack_addr [level]"

#define _STRACE_USAGE_IA64 \
      "[-f] [-l] [-w outfile] pc bsp pfs task [level]"

#define _STRACE_USAGE_S390 \
      "[-f] [-w outfile] stack_addr [level]"

/*
 * strace_usage() -- Print the usage string for the 'strace' command.
 */
void
strace_usage(command_t *cmd)
{
        switch (KL_ARCH) {
              case KL_ARCH_S390:
              case KL_ARCH_S390X:
                    CMD_USAGE(cmd, _STRACE_USAGE_S390);
                  break;

              case KL_ARCH_IA64:
                    CMD_USAGE(cmd, _STRACE_USAGE_IA64);
                  break;

              default:
                    CMD_USAGE(cmd, _STRACE_USAGE);
      }
}

#define _STRACE_HELP_S390 \
        "Displays all complete and unique stack traces (containing level "\
        "or more stack frames) from the stack starting at stack_addr. If a "\
        "level isn't specified, then each stack trace must have at least "\
        "three frames to be considered valid."

#define _STRACE_HELP_IA64 \
        "Displays all complete and unique stack traces (containing level "\
        "or more stack frames) from the stack starting at stack_addr. If a "\
        "level isn't specified, then each stack trace must have at least "\
        "three frames to be considered valid. Alternately, use a specific "\
        "PC, BSP address, and PFS value to generate a stack trace for the "\
        "specified TASK."

#define _STRACE_HELP \
        "Displays all complete and unique stack traces (containing level "\
        "or more stack frames) from the stack starting at stack_addr. If a "\
        "level isn't specified, then each stack trace must have at least "\
        "three frames to be considered valid. Alternately, use a specific "\
        "PC and SP to generate a stack trace from the stack starting at "\
        "stack_addr. Or, when the -l command line option is specified, "\
        "displays a list of all saved return addresses contained in the "\
        "stack starting at stack_addr, along with their location in the "\
        "stack and possibly the name of the function called. Or, if the "\
        "-a option is specified, display ALL traces of level or more frames, "\
        "including invalid traces and duplicate (sub) traces."

/*
 * strace_help() -- Print the help information for the 'strace' command.
 */
void
strace_help(command_t *cmd)
{
        switch (KL_ARCH) {
              case KL_ARCH_S390:
              case KL_ARCH_S390X: {
                    CMD_HELP(cmd, _STRACE_USAGE_S390, _STRACE_HELP_S390);
                  break;
            }

              case KL_ARCH_IA64: {
                    CMD_HELP(cmd, _STRACE_USAGE_IA64, _STRACE_HELP_IA64);
                  break;
            }

              default: {
                    CMD_HELP(cmd, _STRACE_USAGE, _STRACE_HELP);
            }
      }
}

/*
 * strace_parse() -- Parse the command line arguments for 'strace'.
 */
int
strace_parse(command_t *cmd)
{
        switch (KL_ARCH) {
              case KL_ARCH_S390:
              case KL_ARCH_S390X:
                    if (set_cmd_flags(cmd, (C_TRUE|C_FULL|C_WRITE), "")) {
                          return(1);
                  }
                  break;

              case KL_ARCH_IA64:
                    if (set_cmd_flags(cmd, (C_TRUE|C_FULL|C_LIST|C_WRITE), "")) {
                          return(1);
                  }
                  break;

              default:
                    if (set_cmd_flags(cmd, (C_TRUE|C_ALL|C_FULL|C_LIST|C_WRITE), 
                                "")) {
                          return(1);
                  }
      }
      return(0);
}

/*
 * strace_complete() -- Complete arguments of 'strace' command.
 */
char *
strace_complete(command_t *cmd)
{
      char *ret;

      /* complete standard options (for example, -w option) arguments
       */
      if ((ret = complete_standard_options(cmd)) != NOT_COMPLETED) {
            return(ret);
      }
      fprintf(cmd->ofp, "\n");
      strace_usage(cmd);
      return(DRAW_NEW_ENTIRE_LINE);
}

Generated by  Doxygen 1.6.0   Back to index