View of xos/kernel/debug.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   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 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include <debug.h>
 
#include <map_info_struct.h>
#include <proc.h>
#include <kmalloc.h>
#include <asm.h>
#include <errno.h>
#include <config.h>
#include <sprintf.h>
#include <string.h>
 
/* Ecrit un caractere sur le port parallele. */
static void print_char_to_parallel(char c)
{
  outb(0x04|0x08, 0x37a);
  outb(c, 0x378);
  outb(0x01, 0x37a);
}
 
static void print_string_to_parallel(const char *s, unsigned int n)
{
  while (n--)
    print_char_to_parallel(*s++);
}
 
/* Ecrit du texte sur le port parallele.
 * Cela est utile pour generer des traces avec Bochs. Dans .bochsrc, ajouter la
 * ligne:
 *   parport1: enabled=1, file=<file>
 * ou <file> est un nom de fichier (par exemple bochs.log), ou /dev/stdout.
 * cf http://f.osdev.org/viewtopic.php?f=1&t=9751.
 * Fonction inspiree de printk(). */
void __attribute__ ((format (printf, 4, 5))) _log(const char *file, int line, const char *func, const char *format, ...)
{
  int intr;
  va_list arg;
  char buf[PRINTK_BUFFER_SIZE];
  int n;
 
  disable_intr(intr);
  if ((n = snprintf(buf, PRINTK_BUFFER_SIZE, LOG_PREFIX, file, line, func)) < 0)
    goto error;
  print_string_to_parallel(buf, n);
  va_start(arg, format);
  if ((n = vsnprintf(buf, PRINTK_BUFFER_SIZE, format, arg)) < 0)
    goto error;
  va_end(arg);
  print_string_to_parallel(buf, n);
  restore_intr(intr);
  return;
 
 error:
  va_end(arg);
  restore_intr(intr);
}
 
static int print_maps(int pid, char **buf, unsigned int *size)
{
  int retval;
  struct map_info_struct *map_info_array;
  unsigned int map_info_count;
  int len;
  char *p;
  unsigned int i;
 
  if ((retval = proc_get_maps(pid, &map_info_array, &map_info_count)) < 0)
    goto end;
  len = 0;
  for (i = 0; i < map_info_count; i++)
    len += 53 + (map_info_array[i].pathname ? strlen(map_info_array[i].pathname) : 0);
  if (!(*buf = kmalloc(len + 1))) {
    retval = -ENOMEM;
    goto free;
  }
  *size = len + 1;
  p = *buf;
  for (i = 0; i < map_info_count; i++)
    p += snprintf(p, *size - (p - *buf), "%08lx-%08lx %c%c %08lx %-10u %-10lu %s\n", map_info_array[i].start_addr, map_info_array[i].end_addr, map_info_array[i].perms.read ? 'r' : '-', map_info_array[i].perms.write ? 'w' : '-', map_info_array[i].offset, map_info_array[i].dev, map_info_array[i].id, map_info_array[i].pathname ? : "");
  *p = '\0';
  retval = 0;
 
 free:
  if (map_info_array) {
    for (i = 0; i < map_info_count; i++)
      if (map_info_array[i].pathname)
        kfree(map_info_array[i].pathname, strlen(map_info_array[i].pathname) + 1);
    kfree(map_info_array, map_info_count * sizeof (struct map_info_struct));
  }
 end:
  return retval;
}
 
void _log_maps(const char *file, int line, const char *func, int pid)
{
  int intr;
  char buf[PRINTK_BUFFER_SIZE];
  char *buf1;
  unsigned int buf1_size;
  int n;
 
  disable_intr(intr);
  if ((n = snprintf(buf, PRINTK_BUFFER_SIZE, LOG_PREFIX "Maps of pid=%d\n", file, line, func, pid)) < 0)
    goto error;
  print_string_to_parallel(buf, n);
  if (print_maps(pid, &buf1, &buf1_size) < 0)
    goto error;
  print_string_to_parallel(buf1, buf1_size);
  kfree(buf1, buf1_size);
  restore_intr(intr);
  return;
 
 error:
  restore_intr(intr);
}