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

cmd_mktrace_arm.c

/*
 * cmd_mktrace_arm.c
 * 
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Ported from cmd_mktrace_i386.c
 * by Fleming Feng (fleming.feng@intel.com).
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Copyright (C) 2003, Intel Corp. All rights reserved.
 *
 * 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>

/* Local flags
 */
#define FREE_FLAG (1 << C_LFLG_SHFT)

extern trace_t *trace_list[];
extern int max_traces;
extern int next_trace;

/* Forward Declaration
 */
void mktrace_usage(command_t *);

/* 
 * mktrace_cmd() -- Command for building a stack backtrace from scratch.
 */
int
mktrace_cmd(command_t *cmd)
{
      int mode;
      kaddr_t i, saddr, sp, pc, fp, ra;
      uint64_t value;
      trace_t *trace; 
      char str[1024], *ptr;
      sframe_t *sf;

      /* List active trace records
       */
      if (cmd->flags & C_LIST) {
            fprintf(cmd->ofp, "Active trace records:\n\n");
            for (i = 0; i < next_trace; i++) {
                  fprintf(cmd->ofp, "  [%d] 0x%lx\n", 
                        (int)i, (long unsigned int)trace_list[i]);
            }
            return(0);
      } else if (cmd->nargs == 0) {
            /* Other than with C_LIST, there have to be SOME 
             * arguments.
             */
            fprintf(cmd->efp, "Must specify trace information!\n");
            mktrace_usage(cmd);
            return(1);
      }

      /* Free active trace record(s)
       */
      if (cmd->flags & FREE_FLAG) {
            if (cmd->flags & C_ALL) {
                  /* Free all trace records 
                   */
                  for (i = 0; i < next_trace; i++) {
                        if (trace_list[i]) {
                              free_trace_rec(trace_list[i]);
                              trace_list[i] = 0;
                        }
                  }
                  next_trace = 0;
                  return(0);
            } 
            if (cmd->nargs == 0) {
                  fprintf(cmd->efp, "No trace records to free!\n");
                  mktrace_usage(cmd);
                  return(1);
            }
            for (i = 0; i < cmd->nargs; i++) {
                  kl_get_value(cmd->args[i], &mode, 0, &value);
                  if (KL_ERROR || (mode != 2)) {
                        fprintf(cmd->efp, "Bad trace_t pointer %s\n", 
                              cmd->args[i]);
                        continue;
                  }
                  trace = (trace_t *)((uaddr_t)value);
                  for (i = 0; i < next_trace; i++) {
                        if (trace_list[i] == trace) {
                              free_trace_rec(trace_list[i]);
                              trace_list[i] = 0;
                              break;
                        }
                  }
                  if (i == next_trace) {
                        fprintf(cmd->efp, "trace_t pointer %s not "
                              "found\n", cmd->args[i]);
                  } else if (i == (next_trace - 1)) {
                        next_trace--;
                  }
            }
            return(0);
      }

      for (i = 0; i < next_trace; i++) {
            if (trace_list[i] == 0) {
                  break;
            }
      }
      if (i == max_traces) {
            fprintf(cmd->efp, "Maximum (%d) trace records allocated\n", 
                  max_traces);
            return(1);
      }
      trace = (trace_t *)alloc_trace_rec(C_PERM);
      if (!trace) {
            mktrace_usage(cmd);
            return(1);
      }
      GET_VALUE(cmd->args[0], &value);
      if (KL_ERROR) {
            KL_ERROR = KLE_BAD_SADDR;
            free_trace_rec(trace);
            return(1);
      }
      saddr = (kaddr_t)value;
      setup_trace_rec_arm(saddr, 0, C_PERM, trace);
      if (KL_ERROR) {
            free_trace_rec(trace);
            return(1);
      }
      if (cmd->nargs > 1) {
            if (cmd->nargs != 5) {
                  free_trace_rec(trace);
                  return(1);
            }
            GET_VALUE(cmd->args[1], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_SP;
                  free_trace_rec(trace);
                  return(1);
            }
            sp = (kaddr_t)value; 
            GET_VALUE(cmd->args[2], &value);
            if (KL_ERROR) {
                  KL_ERROR = KLE_BAD_PC;
                  free_trace_rec(trace);
                  return(1);
            }
            pc = (kaddr_t)value;
            GET_VALUE(cmd->args[3], &value);
            if (KL_ERROR) {
                  /*
                  KL_ERROR = KLE_BAD_FP;
                  */
                  free_trace_rec(trace);
                  return(1);
            }
            fp = (kaddr_t)fp;
            GET_VALUE(cmd->args[4], &value);
            if (KL_ERROR) {
                  /*
                  KL_ERROR = KLE_BAD_RA;
                  */
                  free_trace_rec(trace);
                  return(1);
            }
            ra = (kaddr_t)value;
            /* Set up first frame (which is special because we
             * have the SP and PC in addition to the FP and RA).
             */
            sf = (sframe_t *)alloc_sframe(trace, C_PERM);
            sf->sp = sp;
            sf->pc = pc;
            sf->fp = fp;
            sf->ra = ra;
            kl_enqueue((element_t **)&trace->frame, (element_t *)sf);
      }
      while (1) {
            fprintf(cmd->ofp, "Enter FP and RA: ");   
            get_string(str, 1024);
            if (str[0] == 0) {
                  break;
            }
            ptr = str;
            while(*ptr != ' ') {
                  if (*ptr == 0) {
                        return(1);
                  }
                  ptr++;
            }
            *ptr = 0;
            ptr++;
            GET_VALUE(str, &value);
            fp = (kaddr_t)value;
            GET_VALUE(ptr, &value);
            ra = (kaddr_t)value;
            add_frame_arm(trace, fp, ra);
      }
      finish_trace_arm(trace);
      fprintf(cmd->ofp, "TRACE RECORD CREATED: 0x%lx\n", 
            (unsigned long int)trace);
      trace_list[i] = trace;
      if (i == next_trace) {
            next_trace++;
      }
      return(0);
}



#define _MKTRACE_USAGE "[-l] [-w outfile] [stack_addr SP PC FP RA] | [-F [-a] [free_list]]"

/*
 * mktrace_usage() -- Print the usage string for the 'mktrace' command.
 */
void
mktrace_usage(command_t *cmd)
{
      CMD_USAGE(cmd, _MKTRACE_USAGE);
}

/*
 * mktrace_help() -- Print the help information for the 'mktrace' command.
 */
void
mktrace_help(command_t *cmd)
{
      CMD_HELP(cmd, _MKTRACE_USAGE,
            "Construct a stack backtrace from scratch using an arbitrary "
            "stack_addr, SP, PC, FP, and RA. Alternately, free a trace "
            "record that was previously allocated, list currently "
            "allocated trace records, and delete selected or all active "
            "trace records.");
}

/*
 * mktrace_parse() -- Parse the command line arguments for 'mktrace'.
 */
int
mktrace_parse(command_t *cmd)
{
      option_t *op;
      if (set_cmd_flags(cmd, (C_ALL|C_LIST), "F")) {
            return(1);
      }
      op = cmd->options;
      while (op) {
            switch(op->op_char) {
                  case 'F':
                        cmd->flags |= FREE_FLAG;
                        break;
            }
            op = op->op_next;
      }
      /* Since we will be allocating a perminate trace record, we
       * need to also set eh C_PERM flag.
       */
      cmd->flags |= C_PERM;
      return(0);
}

Generated by  Doxygen 1.6.0   Back to index