5   # Place a '<' marker on the current task

 6   #  if ($arg0 == current)

 7   # For PowerPC, register r2 points to the 'current' task

 8   if ($arg0 == $r2)

 9     printf '<'

10   else

11     printf ' '

12   end

13

14   # State

15   if ($arg0->state == 0)

16     printf 'Running   '

17   else

18     if ($arg0->state == 1)

19       printf 'Sleeping  '

20     else

21       if ($arg0->state == 2)

22         printf 'Disksleep '

23       else

24         if ($arg0->state == 4)

25           printf 'Zombie    '

26         else

27           if ($arg0->state == 8)

28             printf 'sTopped   '

29           else

30             if ($arg0->state == 16)

31               printf 'Wpaging   '

32             else

33               printf '%2d        ', $arg0->state

34             end

35           end

36         end

37       end

38     end

39   end

40

41   # User NIP

42   if ($arg0->thread.regs)

43     printf '0x%08X ', $arg0->thread.regs->nip

44   else

45     printf '           '

46   end

47

48   # Display the kernel stack pointer

49   printf '0x%08X ', $arg0->thread.ksp

50

51   # device

52   if ($arg0->signal->tty)

53     printf '%s   ', $arg0->signal->tty->name

54   else

55     printf '(none) '

56   end

57

58   # comm

59   printf '%s ', $arg0->comm

60 end

Line 3 displays the address of the task_struct. Lines 8 through 12 display the process ID. If this is the current process (the process that was currently running on this CPU at the time the breakpoint was hit), it is marked with a < character.

Lines 14 through 39 decode and display the state of the process. This is followed by displaying the user process next instruction pointer (NIP) and the kernel stack pointer (SP). Finally, the device associated with the process is displayed, followed by the name of the process (stored in the ->comm element of the task_struct .)

It is important to note that this macro is architecture dependent, as shown in lines 7 and 8. In general, macros such as these are highly architecture- and version-dependent. Any time a change in the underlying structure is made, macros such as these must be updated. However, if you spend a lot of time debugging the kernel using gdb, the payback is often worth the effort.

For completeness, we present the find_next_task macro. Its implementation is less than obvious and deserves explanation. (It is assumed that you can easily deduce the task_struct_header that completes the series necessary for the ps macro presented in this section. It is nothing more than a single line arranging the column headers with the correct amount of whitespace.) Listing 14-15 presents the find_next_task macro used in our ps and find_task macros.

Listing 14-15. gdb find_next_task Macro

define find_next_task

  # Given a task address, find the next task in the linked list

  set $t = (struct task_struct *)$arg0

  set $offset=((char *)&$t->tasks - (char *)$t)

  set $t=(struct task_struct *)((char *)$t->tasks.next- (char *)$offset)

end

The function performed by this macro is simple. The implementation is slightly less than straightforward. The goal is to return the ->next pointer, which points to the next task_struct on the linked list. However, the task_struct structures are linked by the address of the struct list_head member called tasks, as opposed to the common practice of being linked by the starting address of the task_struct itself. Because the ->next pointer points to the address of the task structure element in the next task_struct on the list, we must subtract to get the address of the top of the task_struct itself. The value we subtract from the ->next pointer is the offset from that pointer's address to the top of task_struct. First we calculate the offset and then we use that offset to adjust the ->next pointer to point to the top of task_struct. Figure 14-5 should make this clear.

Figure 14-5. Task structure list linking

Now we present one final macro that will be useful in the next section when we discuss debugging loadable modules. Listing 14-16 is a simple macro that displays the kernel's list of currently installed loadable modules.

Listing 14-16. gdb List Modules Macro

1 define lsmod

2   printf 'Address Module '

3   set $m=(struct list_head *)&modules

4   set $done=0

5   while (!$done)

6     # list_head is 4-bytes into struct module

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату