This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC 3/7] Add basic Linux kernel support


Yao Qi <qiyaoltc@gmail.com> writes:

> I am playing your first three patches on x86_64 with some hacks.
> I write a small program with the same linux kernel "signature", and
> want GDB treat it as a linux kernel.
>

I make some progress on writing such small test case,
see the code below.  I hacked lk_try_push_target not to do the
sanity check, and not to call lk_try_push_target in
lk_observer_inferior_created, so that I can push this target layer when
I want.

(gdb) break stop^M
Breakpoint 2 at 0x400711: file /home/yao/SourceCode/gnu/gdb/git/gdb/testsuite/gdb.base/linux-kernel.c, line 104.^M
(gdb) continue^M
Continuing.^M
^M
Breakpoint 2, stop () at /home/yao/SourceCode/gnu/gdb/git/gdb/testsuite/gdb.base/linux-kernel.c:104^M
104     {}^M
(gdb) PASS: gdb.base/linux-kernel.exp: continue to breakpoint: stop

at this point, the list of tasks are set up, switch to linux-kernel
target layer,

target linux-kernel^M
[New process 8001]^M
(gdb) PASS: gdb.base/linux-kernel.exp: target linux-kernel
maintenance print target-stack^M
The current target stack is:^M
  - linux-kernel (linux kernel support)^M
  - native (Native process)^M
  - exec (Local exec file)^M
  - None (None)^M

It works!  In this way, we can test that GDB can successfully parse the
these data structures in Linux kernel without Linux kernel image at all.

Then, we can generate a coredump,

(gdb) generate-core-file 
Saved corefile core.9614

Remove the hack in lk_observer_inferior_created, so that GDB can
automatically push linux-kernel target layer,

$ ./gdb ./testsuite/outputs/gdb.base/linux-kernel/linux-kernel ./core.9614
[New LWP 9614]
[New process 9614]
Core was generated by `/scratch/yao/gdb/build-git/x86_64/gdb/testsuite/outputs/gdb.base/linux-kernel/li'.
Program terminated with signal SIGTRAP, Trace/breakpoint trap.
#0  stop () at /home/yao/SourceCode/gnu/gdb/git/gdb/testsuite/gdb.base/linux-kernel.c:104
104	{}
[Current thread is 1 (PID:  9614*, 0x602010)]
(gdb) maintenance print target-stack 
The current target stack is:
  - linux-kernel (linux kernel support)
  - core (Local core dump file)
  - exec (Local exec file)
  - None (None)

The next step would be extending the test case to a multi-threaded
program, so that we can create task lists for these threads, and
generate coredump which is similar to the kernel coredump.

-- 
Yao (齐尧)

#include <unistd.h>
#include <stdlib.h>
#include <string.h>

static char linux_banner[10];
static int _stext = 0;
static int _etext = 0;

typedef int pid_t;

struct list_head
{
  struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) (struct list_head) { &(name), &(name) }

struct thread_struct
{};

struct task_struct
{
  struct list_head tasks;
  pid_t pid;
  pid_t tgid;
  struct list_head thread_group;
  char comm[20];

  struct thread_struct thread;
};

struct rq
{
  struct task_struct *curr;
};

#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define BITS_PER_BYTE           8
#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof (long))

#define DECLARE_BITMAP(name,bits) \
  unsigned long name[BITS_TO_LONGS(bits)]

#define NR_CPUS 10

struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); };

struct cpumask __cpu_online_mask;

static void
cpumask_set_cpu (unsigned int cpu, struct cpumask* dstp)
{
  dstp->bits[cpu / (BITS_PER_BYTE * sizeof (long))]
    |= 1UL << (cpu % (BITS_PER_BYTE * sizeof (long)));
}

struct task_struct init_task;;
struct rq runqueues[NR_CPUS];
struct cpumask baz;

unsigned long __per_cpu_offset[NR_CPUS];

struct mm_struct
{};

struct mm_struct init_mm;


static void
setup (void)
{
  int i;
  struct task_struct *task;

  /* Set up __per_cpu_offset.  */
  for (i = 0; i < NR_CPUS; i++)
    __per_cpu_offset[i] = i * sizeof (runqueues[0]);

  /* Mark cpu 0 is online.  */
  cpumask_set_cpu (0, &__cpu_online_mask);

  init_task.tasks = LIST_HEAD_INIT(init_task.tasks);
  init_task.thread_group = LIST_HEAD_INIT(init_task.thread_group);

  task = malloc (sizeof (struct task_struct));
  memset (task, 0, sizeof (sizeof (struct task_struct)));

  task->pid = getpid ();

  runqueues[0].curr = task;

  /* Chain it tasks list.  */
  init_task.tasks.next = (struct list_head *) task;
  init_task.tasks.prev = (struct list_head *) task;
  task->tasks.next = (struct list_head *) &init_task;
  task->tasks.prev = (struct list_head *) &init_task;

  /* TASK is the group leader.  */
  task->thread_group = LIST_HEAD_INIT(task->thread_group);
}

static void
stop (void)
{}

int
main (void)
{
  setup ();

  stop ();
  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]