[Crash-utility] Re: [PATCH] crash_target: Support for GDB debugging of all tasks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Alexey,

On Tue, Mar 19, 2024 at 6:00 AM Alexey Makhalov
<alexey.makhalov@xxxxxxxxxxxx> wrote:
>
> Hi Tao,
>
> I like the idea of having just one thread at a time from the gdb side, and it can be replaced by a "set" crash command.
> Single semantics will work for both live and offline debugging and for both types of tasks: active or scheduled out.
> Need to be careful with lifetime for the data (gdb caches). I'm experimenting with live debugging these days.
> Aditya, Tao, let me know what is the latest patchset I should use from you folks?

You can use https://github.com/liutgnu/crash-dev/commits/one-thread
directly. The one-thread branch takes Aditya's v10 patchset and my v1
patchset, as well as the trial "one gdb thread/CPUS" patch. You can
revert the trial one patch for testing.

Thanks,
Tao Liu

>
> Thanks,
> --Alexey
>
> On Mon, Mar 18, 2024 at 2:56 AM Tao Liu <ltao@xxxxxxxxxx> wrote:
>>
>> Hi Aditya and Alexey,
>>
>> On Mon, Mar 18, 2024 at 11:35:41AM +0800, Tao Liu wrote:
>> > On Sun, Mar 17, 2024 at 03:40:52PM +0530, Aditya Gupta wrote:
>> > > Hi Tao and Alexey,
>> > >
>> > > On Fri, Mar 15, 2024 at 03:15:19PM -0700, Alexey Makhalov wrote:
>> > > > Hi Tao,
>> > > >
>> > > > Thanks for the details. Agree, my approach is targeted primarily for
>> > > > offline debugging.
>> > > > Create/exit monitoring sounds like an overkill. And from the other side,
>> > > > maintaining a static list of threads (CPUs or Tasks) does not work for live
>> > > > debugging.
>> > > > "ps" followed by "set" where GDB will receive just one inferior/thread at a
>> > > > time is probably the right universal approach.
>> > > > Let me experiment with a combination of my and your patches and come back
>> > > > to you.
>> > >
>> > > Sorry I noticed a bug late while trying the combination of tao's and my
>> > > patches.
>> > >
>> > > I agree with Tao that current approach might not be good for live
>> > > debugging, but I think the approach of having all tasks in 'info
>> > > threads' is a good advantage for offline debugging, since then gdb knows
>> > > about all tasks (similar behaviour as usual gdb), and makes it easier
>> > > to synchronise crash <-> gdb context.
>> > >
>> > > I had refrained from changing the format of 'info threads' from active
>> > > tasks to all tasks, but there are some issues with crash <-> gdb sync,
>> > > when doing arbitrary task unwinding.
>> > >
>> > > 'set 1' (let's assume it's an INACTIVE task on CPU 5)
>> > >
>> > > 'info threads'
>> > > -> when it switches to CPU 5, it asks crash to sync, ie. `set_cpu(5)`
>> > > -> crash will return CPU 5's active tasks registers
>> > > -> WRONG registers for CPU 5, since we wanted registers for PID 1 (which
>> > > is an inactive task on CPU 5)
>> >
>> > What do you mean of "WRONG registers"? Isn't the CPU5's regcache be pid
>> > 1's context after 'set 1'? If it isn't then it's a bug.
>> >
>> > After crash finished loading and we see crash> prompt, the cpu regcaches
>> > will be all active tasks', which are running on each cpu. That is what we saw
>> > using "info threads", like:
>> >
>> >     crash> info threads
>> >       Id   Target Id         Frame
>> >     ....
>> >     * 8    CPU 7             blk_mq_rq_timed_out (req=0xffff880fdb246000, reserved=reserved@entry=false) at block/blk-mq.c:640
>> >     ....
>> >       14   CPU 13            native_safe_halt () at arch/x86/include/asm/irqflags.h:54
>> >     ....
>> >
>> > Then we use "set <pid>" to switch to task <pid>, its cpu regcache will be
>> > flushed, and if we use command "info threads" again, it will show the status
>> > after the flushing. E.g in the following, task pid 1's cpu is #13, so
>> > cpu #13 is flushed after "set 1":
>> >
>> >     crash> ps
>> >           PID    PPID  CPU       TASK        ST  %MEM      VSZ      RSS  COMM
>> >             1       0  13  ffff880169b30000  IN   0.0   193052     4180  systemd
>> >
>> >     crash> set 1
>> >     crash> info threads
>> >       Id   Target Id         Frame
>> >     ....
>> >     8    CPU 7             blk_mq_rq_timed_out (req=0xffff880fdb246000, reserved=reserved@entry=false) at block/blk-mq.c:640
>> >     ....
>> >     * 14   CPU 13            0xffffffff816a8f65 in context_switch (rq=0x0, next=0x0, prev=0xffff880169b30000) at kernel/sched/core.c:2527
>> >                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
>> >     ....
>> >
>> > When design, I assume the CPUs/threads are like power slots, its number is
>> > constant, but the contents can be changed. We don't need to prepare the
>> > "slots" as many as our tasks quantity (I don't know the maxinum threads that
>> > a gdb can accept, e.g. on a system which have 65K tasks, but for most
>> > tasks we'd never switch to it in order to view its stack trace, I guess
>> > it would be a waste to call add_thread_silent (target, ...) 65K times).
>> >
>> > Currently the gdb CPUs/threads(slots) equals to the system's cpu number. But
>> > if a system which have thousands of cpus, which we think is unnecessary to
>> > call add_thread_silent 1K times, we can even shrink the slots to be less.
>> >
>>
>> I made a trial patch of leaving only 1 gdb CPUs/threads(slots) in [1].
>> And it can also view arbitrary tasks stack unwinding. In this case,
>> "info threads" and "thread XX" will have no meaning to be kept.
>>
>> Please see my test results:
>>
>>       KERNEL: /home/ltao/kernel/linux-next-next-20220914/vmlinux
>>     DUMPFILE: /proc/kcore
>>         CPUS: 4
>>         ^^^^^^^ there are 4 cpus in the system
>> crash> ps
>>       PID    PPID  CPU       TASK        ST  %MEM      VSZ      RSS  COMM
>> ...
>>         1       0   1  ffff9908002a6500  IN   0.1   253024    19444  systemd
>> ...
>>         5       2   0  ffff9908002a0000  ID   0.0        0        0  [netns]
>> ...
>>         ^^^^^^^^^^^^^ we use pid 1 and pid 5, which belongs to 2 different cpus
>> crash> set 1
>> crash> gdb bt
>> #0  context_switch (rf=0xffffbf750001bd68, next=0xffff99080032cbc0, prev=0x0, rq=0xffff990b6fcafe80) at kernel/sched/core.c:5201
>> #1  __schedule (sched_mode=sched_mode@entry=0) at kernel/sched/core.c:6510
>> #2  0xffffffffb3cf0603 in schedule () at kernel/sched/core.c:6586
>> #3  0xffffffffb3cf6ab9 in schedule_hrtimeout_range_clock (expires=expires@entry=0x0, delta=delta@entry=0, mode=mode@entry=HRTIMER_MODE_ABS, clock_id=clock_id@entry=1) at kernel/time/hrtimer.c:2296
>> ...
>> crash> bt
>> PID: 1        TASK: ffff9908002a6500  CPU: 1    COMMAND: "systemd"
>>  #0 [ffffbf750001bdb0] schedule at ffffffffb3cf0603
>>  #1 [ffffbf750001bdc0] schedule_hrtimeout_range_clock at ffffffffb3cf6ab9
>> ...
>> ^^^ we can view pid 1's stack trace with no problem
>> crash> info threads
>>   Id   Target Id         Frame
>> * 1    CPU 0             context_switch (rf=0xffffbf750001bd68, next=0xffffffffb4c18a00 <init_task>, prev=0x0, rq=0xffff990b6fc2fe80) at kernel/sched/core.c:5201
>>
>> crash> set 5
>> crash> gdb bt
>> #0  context_switch (rf=0xffffbf750003be58, next=0xffff9908002d6500, prev=0x0, rq=0xffff990b6fc2fe80) at kernel/sched/core.c:5201
>> #1  __schedule (sched_mode=sched_mode@entry=0) at kernel/sched/core.c:6510
>> #2  0xffffffffb3cf0603 in schedule () at kernel/sched/core.c:6586
>> #3  0xffffffffb3308752 in rescuer_thread (__rescuer=0xffff9908001f7480) at kernel/workqueue.c:2599
>> ...
>> crash> bt
>> PID: 5        TASK: ffff9908002a0000  CPU: 0    COMMAND: "netns"
>>  #0 [ffffbf750003bea0] schedule at ffffffffb3cf0603
>>  #1 [ffffbf750003beb0] rescuer_thread at ffffffffb3308752
>> ...
>> ^^^ we can view pid 5's stack trace with no problem
>> crash> info threads
>>   Id   Target Id         Frame
>> * 1    CPU 0             context_switch (rf=0xffffbf750003be58, next=0xffff9908002d6500, prev=0x0, rq=0xffff990b6fc2fe80) at kernel/sched/core.c:5201
>>                                          ^^^^^^^^^^^^^^^^^^^^^ now its pid 5's context
>>
>> From my view, I think we can keep the current "gdb thread/CPUs = nr_cpus", or
>> be more ambitious, leaving "gdb thread/CPUs = 1", in case there are
>> systems with thousands of cpus, and we only need this in task.c:
>>
>> +       gdb_refresh_regcache(0);
>> -       for (int i = 0; i < get_cpus_online(); i++)
>> -               gdb_refresh_regcache(i);
>>
>> Do you have any thoughts?
>>
>> [1]: https://github.com/liutgnu/crash-dev/commits/one-thread
>>
>> Thanks,
>> Tao Liu
>>
>> > Thanks,
>> > Tao Liu
>> >
>> >
>> > >
>> > > I can think of solving it in two ways:
>> > > 1. Having a array in crash_target, which tells what CPU in gdb maps to
>> > > which task in crash, this can be done without requiring changes to 'info
>> > > threads', while we do the 'add_thread_silent'
>> > > 2. Having all tasks in gdb itself, so it's a one-to-one, so `set_cpu`
>> > > will then refer to the task ID, I will have to explore more on this.
>> > >
>> > > Any comments ?
>> > >
>> > > Thanks,
>> > > Aditya Gupta
>> > >
>> > > >
>> > > > Thanks,
>> > > > --Alexey
>> > > >
>> > > >
>> > > > On Thu, Mar 14, 2024 at 9:22 PM Tao Liu <ltao@xxxxxxxxxx> wrote:
>> > > >
>> > > > > Hi Alexey,
>> > > > >
>> > > > > On Thu, Mar 14, 2024 at 6:29 PM Alexey Makhalov
>> > > > > <alexey.makhalov@xxxxxxxxxxxx> wrote:
>> > > > > >
>> > > > > > Support for GDB debugging of all tasks active and inactive.
>> > > > > > Before this commit only active tasks were listed by "info threads"
>> > > > > > with "CPU #" as a Target Id.
>> > > > > >
>> > > > > > "info threads" will now show all tasks, similar to "ps", example:
>> > > > > > crash> info threads
>> > > > > >   Id   Target Id               Frame
>> > > > > > * 1          0 swapper/0       0xffffffffadba19d4 in default_idle () at
>> > > > > arch/x86/kernel/process.c:731
>> > > > > >   2          0 swapper/1       0xffffffffadba19d4 in default_idle () at
>> > > > > arch/x86/kernel/process.c:731
>> > > > > >   3          0 swapper/2       0xffffffffadba19d4 in default_idle () at
>> > > > > arch/x86/kernel/process.c:731
>> > > > > >   4          0 swapper/3       0xffffffffadba19d4 in default_idle () at
>> > > > > arch/x86/kernel/process.c:731
>> > > > > >   5          0 swapper/4       0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf0000f3e88, next=0xffff9ecb04908000, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > > ...
>> > > > > >   730   970325 taskset         0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf006a0fd18, next=0xffff9ecb0aec0000, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > >   731   975217 sleep           0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf005743c20, next=0xffff9ecac0692880, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > >   732   975228 sleep           0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf00696fb58, next=0xffff9ecac0690000, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > > ...
>> > > > > >   876   976084 docker          0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf0153dbd10, next=0xffff9ecac0645100, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > >   877   976085 systemd-userwor 0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf0153cbc58, next=0xffff9ecac0645100, prev=<optimized out>,
>> > > > > rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > >   878   976086 systemd-userwor 0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf0153e3c58, next=0xffffffffaec15a40 <init_task>,
>> > > > > prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > >   879   976087 systemd-userwor 0xffffffffadb97292 in context_switch
>> > > > > (rf=0xffffbaf0153ebc58, next=0xffffffffaec15a40 <init_task>,
>> > > > > prev=<optimized out>, rq=<optimized out>) at kernel/sched/core.c:5372
>> > > > > > Where "Target ID" contains "PID COMM" of the task
>> > > > > >
>> > > > >
>> > > > > I see here, we chose a different tech path of viewing arbitrary tasks.
>> > > > > You improved the "info threads" as an alternative to crash "ps" cmd,
>> > > > > and use "thread X" to switch to task X and view its stacktrace.
>> > > > > However mine is using crash "ps" cmd first, getting specific tasks pid
>> > > > > or task struct, then using crash cmd "set <pid>" or "set
>> > > > > <task_struct>" to switch to task X and view its stacktrace.
>> > > > >
>> > > > > I notice there is one problem of using the "info threads as ps" tech
>> > > > > path, it is difficult to handle the live debug, see the comment below:
>> > > > >
>> > > > > > Example of "731   975217 sleep" debugging, real case, trying to
>> > > > > > figure out why sleep was stuck in uninterruptable sleep.
>> > > > > > Backtrace using crash:
>> > > > > > crash> ps | grep 975217
>> > > > > >    975217  969797   3  ffff9ecb3956a880  UN   0.0        0        0
>> > > > > sleep
>> > > > > > crash> bt 975217
>> > > > > > PID: 975217   TASK: ffff9ecb3956a880  CPU: 3    COMMAND: "sleep"
>> > > > > >  #0 [ffffbaf005743ba0] __schedule at ffffffffadb97292
>> > > > > >  #1 [ffffbaf005743c60] schedule at ffffffffadb982b8
>> > > > > >  #2 [ffffbaf005743c80] rwbase_write_lock at ffffffffadb9aed7
>> > > > > >  #3 [ffffbaf005743cc0] down_write at ffffffffadb9b133
>> > > > > >  #4 [ffffbaf005743cd0] unlink_file_vma at ffffffffad2b0e2e
>> > > > > >  #5 [ffffbaf005743cf8] free_pgtables at ffffffffad2a47b0
>> > > > > >  #6 [ffffbaf005743d88] exit_mmap at ffffffffad2b3b8d
>> > > > > >  #7 [ffffbaf005743e80] mmput at ffffffffad08c81f
>> > > > > >  #8 [ffffbaf005743e98] do_exit at ffffffffad09636c
>> > > > > >  #9 [ffffbaf005743ef8] do_group_exit at ffffffffad096c78
>> > > > > >     RIP: 00007f111c70ddf9  RSP: 00007fff451817e8  RFLAGS: 00000246
>> > > > > >     RAX: ffffffffffffffda  RBX: 00007f111c8089e0  RCX: 00007f111c70ddf9
>> > > > > >     RDX: 000000000000003c  RSI: 00000000000000e7  RDI: 0000000000000000
>> > > > > >     RBP: 0000000000000000   R8: ffffffffffffff80   R9: 0000000000000000
>> > > > > >     R10: 00007fff451817b0  R11: 0000000000000246  R12: 00007f111c8089e0
>> > > > > >     R13: 00007f111c80e2e0  R14: 0000000000000002  R15: 00007f111c80e2c8
>> > > > > >     ORIG_RAX: 00000000000000e7  CS: 0033  SS: 002b
>> > > > > >
>> > > > > > Backtrace using gdb (pay attention, task must be selected by thread Id):
>> > > > > > crash> thread 731
>> > > > > > [Switching to thread 731 ( 975217 sleep)]
>> > > > > > 5372            switch_to(prev, next, prev);
>> > > > > > crash> gdb bt
>> > > > > >  #0  0xffffffffadb97292 in context_switch (rf=0xffffbaf005743c20,
>> > > > > next=0xffff9ecac0692880, prev=<optimized out>, rq=<optimized out>) at
>> > > > > kernel/sched/core.c:5372
>> > > > > >  #1  __schedule (sched_mode=sched_mode@entry=0) at
>> > > > > kernel/sched/core.c:6696
>> > > > > >  #2  0xffffffffadb982b8 in schedule () at kernel/sched/core.c:6772
>> > > > > >  #3  0xffffffffadb9aed7 in rwbase_write_lock (rwb=rwb@entry=0xffff9ecaf1831430,
>> > > > > state=state@entry=2) at kernel/locking/rwbase_rt.c:259
>> > > > > >  #4  0xffffffffadb9b133 in __down_write (sem=sem@entry=0xffff9ecaf1831430)
>> > > > > at kernel/locking/rwsem.c:1474
>> > > > > >  #5  down_write (sem=sem@entry=0xffff9ecaf1831430) at
>> > > > > kernel/locking/rwsem.c:1574
>> > > > > >  #6  0xffffffffad2b0e2e in i_mmap_lock_write (mapping=<optimized out>)
>> > > > > at ./include/linux/fs.h:466
>> > > > > >  #7  unlink_file_vma (vma=vma@entry=0xffff9ecadd566090) at mm/mmap.c:127
>> > > > > >  #8  0xffffffffad2a47b0 in free_pgtables (tlb=tlb@entry=0xffffbaf005743dd0,
>> > > > > mt=mt@entry=0xffff9ecb28e3b180, vma=0xffff9ecadd566090, vma@entry=0xffff9ecadd566000,
>> > > > > floor=floor@entry=0, ceiling=ceiling@entry=0) at mm/memory.c:431
>> > > > > >  #9  0xffffffffad2b3b8d in exit_mmap (mm=mm@entry=0xffff9ecb28e3b180)
>> > > > > at mm/mmap.c:3237
>> > > > > >  #10 0xffffffffad08c81f in __mmput (mm=0xffff9ecb28e3b180) at
>> > > > > kernel/fork.c:1204
>> > > > > >  #11 mmput (mm=mm@entry=0xffff9ecb28e3b180) at kernel/fork.c:1226
>> > > > > >  #12 0xffffffffad09636c in exit_mm () at kernel/exit.c:563
>> > > > > >  #13 do_exit (code=code@entry=0) at kernel/exit.c:856
>> > > > > >  #14 0xffffffffad096c78 in do_group_exit (exit_code=0) at
>> > > > > kernel/exit.c:1019
>> > > > > >  #15 0xffffffffad096cf8 in __do_sys_exit_group (error_code=<optimized
>> > > > > out>) at kernel/exit.c:1030
>> > > > > >  #16 __se_sys_exit_group (error_code=<optimized out>) at
>> > > > > kernel/exit.c:1028
>> > > > > >  #17 __x64_sys_exit_group (regs=<optimized out>) at kernel/exit.c:1028
>> > > > > >  #18 0xffffffffadb8a327 in do_syscall_x64 (nr=<optimized out>,
>> > > > > regs=0xffffbaf005743f58) at arch/x86/entry/common.c:51
>> > > > > >  #19 do_syscall_64 (regs=0xffffbaf005743f58, nr=<optimized out>) at
>> > > > > arch/x86/entry/common.c:81
>> > > > > >  #20 0xffffffffadc000dc in entry_SYSCALL_64 () at
>> > > > > arch/x86/entry/entry_64.S:120
>> > > > > >  #21 0x00007f111c80e2c8 in ?? ()
>> > > > > >  #22 0x0000000000000002 in ?? ()
>> > > > > >  #23 0x00007f111c80e2e0 in ?? ()
>> > > > > >  #24 0x00007f111c8089e0 in ?? ()
>> > > > > >  #25 0x0000000000000000 in ?? ()
>> > > > > > crash> f 3
>> > > > > > 259                     rwbase_schedule();
>> > > > > > crash> p *rwb
>> > > > > > $1 = {
>> > > > > >   readers = {
>> > > > > >     counter = 1
>> > > > > >   },
>> > > > > >   rtmutex = {
>> > > > > >     wait_lock = {
>> > > > > >       raw_lock = {
>> > > > > >         {
>> > > > > >           val = {
>> > > > > >             counter = 0
>> > > > > >           },
>> > > > > >           {
>> > > > > >             locked = 0 '\000',
>> > > > > >             pending = 0 '\000'
>> > > > > >           },
>> > > > > >           {
>> > > > > >             locked_pending = 0,
>> > > > > >             tail = 0
>> > > > > >           }
>> > > > > >         }
>> > > > > >       }
>> > > > > >     },
>> > > > > >     waiters = {
>> > > > > >       rb_root = {
>> > > > > >         rb_node = 0xffffbaf006977be0
>> > > > > >       },
>> > > > > >       rb_leftmost = 0xffffbaf00696fbe0
>> > > > > >     },
>> > > > > >     owner = 0xffff9ecb3956a881
>> > > > > >   }
>> > > > > > }
>> > > > > >
>> > > > > > Additional changes:
>> > > > > > 1. Allow gdb "frame" command.
>> > > > > > 2. Blacklist useless gdb "gcore" command. Use gcore plugin instead.
>> > > > > > 3. Move crash_target_init() to later time as crash target requires a
>> > > > > list of
>> > > > > >    tasks to be initialized.
>> > > > > >
>> > > > > > Known issues and TBD items:
>> > > > > > 1. "info threads" may bail out first time throwing errors trying to
>> > > > > access
>> > > > > >    userspace address during unwind process. Following "info threads"
>> > > > > >    invokations run without issues.
>> > > > > > 2. To unwind a stack of inactive task, only modern Linux versions, which
>> > > > > use
>> > > > > >    inactive_task_frame, are supported and only x86_64 architecture.
>> > > > > > 3. gdb bt unwinder does not stop properly and may show invalid frames
>> > > > > (21-25
>> > > > > >    on example above). Not a regression, existed before.
>> > > > > > 4. gdb bt unwinder does not work on active tasks in userspace. Not a
>> > > > > regression,
>> > > > > >    existed before.
>> > > > > > 5. Only x86_64 architecture supported. machdep->get_task_reg() must be
>> > > > > >    implemented for others. Not a regression, existed before.
>> > > > > > 6. Active tasks registers fetching imlemented only for VMware dumps, see
>> > > > > >    x86_64_get_task_reg() for more details. Not a regression, existed
>> > > > > before.
>> > > > > >
>> > > > > > Signed-off-by: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx>
>> > > > > > ---
>> > > > > >  crash_target.c  | 39 ++++++++++++++++++++---------
>> > > > > >  defs.h          | 10 ++++++--
>> > > > > >  gdb-10.2.patch  |  7 ++----
>> > > > > >  gdb_interface.c | 63 ++++++++++++++++++++++++++++++----------------
>> > > > > >  help.c          |  1 +
>> > > > > >  main.c          |  1 +
>> > > > > >  task.c          |  1 +
>> > > > > >  x86_64.c        | 66 +++++++++++++++++++++++++++++++++++++++++++------
>> > > > > >  8 files changed, 140 insertions(+), 48 deletions(-)
>> > > > > >
>> > > > > > diff --git a/crash_target.c b/crash_target.c
>> > > > > > index 4554806..2fdf203 100644
>> > > > > > --- a/crash_target.c
>> > > > > > +++ b/crash_target.c
>> > > > > > @@ -2,6 +2,8 @@
>> > > > > >   * crash_target.c
>> > > > > >   *
>> > > > > >   * Copyright (c) 2021 VMware, Inc.
>> > > > > > + * Copyright (c) 2024 Broadcom. All Rights Reserved. The term "Broadcom"
>> > > > > > + * refers to Broadcom Inc. and/or its subsidiaries.
>> > > > > >   *
>> > > > > >   * 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
>> > > > > > @@ -13,7 +15,7 @@
>> > > > > >   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> > > > > >   * GNU General Public License for more details.
>> > > > > >   *
>> > > > > > - * Author: Alexey Makhalov <amakhalov@xxxxxxxxxx>
>> > > > > > + * Author: Alexey Makhalov <alexey.makhalov@xxxxxxxxxxxx>
>> > > > > >   */
>> > > > > >
>> > > > > >  #include <defs.h>
>> > > > > > @@ -23,11 +25,11 @@
>> > > > > >  #include "regcache.h"
>> > > > > >  #include "gdbarch.h"
>> > > > > >
>> > > > > > -void crash_target_init (void);
>> > > > > > -
>> > > > > > +extern "C" void crash_target_init (void);
>> > > > > >  extern "C" int gdb_readmem_callback(unsigned long, void *, int, int);
>> > > > > > -extern "C" int crash_get_nr_cpus(void);
>> > > > > > -extern "C" int crash_get_cpu_reg (int cpu, int regno, const char
>> > > > > *regname,
>> > > > > > +extern "C" int crash_get_nr_tasks(void);
>> > > > > > +extern "C" void crash_get_task_info(int task_nr, unsigned long *pid,
>> > > > > char **comm);
>> > > > > > +extern "C" int crash_get_task_reg (int task_nr, int regno, const char
>> > > > > *regname,
>> > > > > >                                    int regsize, void *val);
>> > > > > >
>> > > > > >
>> > > > > > @@ -60,7 +62,13 @@ public:
>> > > > > >    bool has_registers () override { return true; }
>> > > > > >    bool thread_alive (ptid_t ptid) override { return true; }
>> > > > > >    std::string pid_to_str (ptid_t ptid) override
>> > > > > > -  { return string_printf ("CPU %ld", ptid.tid ()); }
>> > > > > > +  {
>> > > > > > +    unsigned long pid;
>> > > > > > +    char *comm;
>> > > > > > +
>> > > > > > +    crash_get_task_info(ptid.tid(), &pid, &comm);
>> > > > > > +    return string_printf ("%7ld %s", pid, comm);
>> > > > > > +  }
>> > > > > >
>> > > > > >  };
>> > > > > >
>> > > > > > @@ -68,18 +76,25 @@ public:
>> > > > > >  void
>> > > > > >  crash_target::fetch_registers (struct regcache *regcache, int regno)
>> > > > > >  {
>> > > > > > +  int r;
>> > > > > >    gdb_byte regval[16];
>> > > > > > -  int cpu = inferior_ptid.tid();
>> > > > > > +  int task_nr = inferior_ptid.tid();
>> > > > > >    struct gdbarch *arch = regcache->arch ();
>> > > > > >
>> > > > > > -  for (int r = 0; r < gdbarch_num_regs (arch); r++)
>> > > > > > +  if (regno >= 0) {
>> > > > > > +    r = regno;
>> > > > > > +    goto onetime;
>> > > > > > +  }
>> > > > > > +
>> > > > > > +  for (r = 0; regno == -1 && r < gdbarch_num_regs (arch); r++)
>> > > > > >      {
>> > > > > > +onetime:
>> > > > > >        const char *regname = gdbarch_register_name(arch, r);
>> > > > > >        int regsize = register_size (arch, r);
>> > > > > >        if (regsize > sizeof (regval))
>> > > > > >          error (_("fatal error: buffer size is not enough to fit
>> > > > > register value"));
>> > > > > >
>> > > > > > -      if (crash_get_cpu_reg (cpu, r, regname, regsize, (void *)&regval))
>> > > > > > +      if (crash_get_task_reg (task_nr, r, regname, regsize, (void
>> > > > > *)&regval))
>> > > > > >          regcache->raw_supply (r, regval);
>> > > > > >        else
>> > > > > >          regcache->raw_supply (r, NULL);
>> > > > > > @@ -107,10 +122,10 @@ crash_target::xfer_partial (enum target_object
>> > > > > object, const char *annex,
>> > > > > >
>> > > > > >  #define CRASH_INFERIOR_PID 1
>> > > > > >
>> > > > > > -void
>> > > > > > +extern "C" void
>> > > > > >  crash_target_init (void)
>> > > > > >  {
>> > > > > > -  int nr_cpus = crash_get_nr_cpus();
>> > > > > > +  int nr_tasks = crash_get_nr_tasks();
>> > > > > >    crash_target *target = new crash_target ();
>> > > > > >
>> > > > > >    /* Own the target until it is successfully pushed.  */
>> > > > > > @@ -119,7 +134,7 @@ crash_target_init (void)
>> > > > > >    push_target (std::move (target_holder));
>> > > > > >
>> > > > > >    inferior_appeared (current_inferior (), CRASH_INFERIOR_PID);
>> > > > > > -  for (int i = 0; i < nr_cpus; i++)
>> > > > > > +  for (int i = 0; i < nr_tasks; i++)
>> > > > > >      {
>> > > > > >        thread_info *thread = add_thread_silent (target,
>> > > > > >                                          ptid_t(CRASH_INFERIOR_PID, 0,
>> > > > > i));
>> > > > > > diff --git a/defs.h b/defs.h
>> > > > > > index 98650e8..2b3f247 100644
>> > > > > > --- a/defs.h
>> > > > > > +++ b/defs.h
>> > > > > > @@ -1080,7 +1080,7 @@ struct machdep_table {
>> > > > > >          void (*get_irq_affinity)(int);
>> > > > > >          void (*show_interrupts)(int, ulong *);
>> > > > > >         int (*is_page_ptr)(ulong, physaddr_t *);
>> > > > > > -       int (*get_cpu_reg)(int, int, const char *, int, void *);
>> > > > > > +       int (*get_task_reg)(struct task_context *, int, const char *,
>> > > > > int, void *);
>> > > > > >         int (*is_cpu_prstatus_valid)(int cpu);
>> > > > > >  };
>> > > > > >
>> > > > > > @@ -2263,6 +2263,7 @@ struct size_table {         /* stash of
>> > > > > commonly-used sizes */
>> > > > > >         long pt_regs;
>> > > > > >         long task_struct;
>> > > > > >         long thread_info;
>> > > > > > +       long inactive_task_frame;
>> > > > > >         long softirq_state;
>> > > > > >         long desc_struct;
>> > > > > >         long umode_t;
>> > > > > > @@ -8001,9 +8002,14 @@ extern int have_full_symbols(void);
>> > > > > >  #define XEN_HYPERVISOR_ARCH
>> > > > > >  #endif
>> > > > > >
>> > > > > > +/*
>> > > > > > + *  crash_target.c
>> > > > > > + */
>> > > > > > +extern void crash_target_init (void);
>> > > > > > +
>> > > > > >  /*
>> > > > > >   * Register numbers must be in sync with gdb/features/i386/64bit-core.c
>> > > > > > - * to make crash_target->fetch_registers() ---> machdep->get_cpu_reg()
>> > > > > > + * to make crash_target->fetch_registers() ---> machdep->get_task_reg()
>> > > > > >   * working properly.
>> > > > > >   */
>> > > > > >  enum x86_64_regnum {
>> > > > > > diff --git a/gdb-10.2.patch b/gdb-10.2.patch
>> > > > > > index a7018a2..ecf673d 100644
>> > > > > > --- a/gdb-10.2.patch
>> > > > > > +++ b/gdb-10.2.patch
>> > > > > > @@ -221,7 +221,7 @@ exit 0
>> > > > > >           warning (_("\
>> > > > > >  --- gdb-10.2/gdb/main.c.orig
>> > > > > >  +++ gdb-10.2/gdb/main.c
>> > > > > > -@@ -392,6 +392,14 @@ start_event_loop ()
>> > > > > > +@@ -392,6 +392,13 @@ start_event_loop ()
>> > > > > >     return;
>> > > > > >   }
>> > > > > >
>> > > > > > @@ -230,7 +230,6 @@ exit 0
>> > > > > >  +extern "C" void main_loop(void);
>> > > > > >  +extern "C" unsigned long crash_get_kaslr_offset(void);
>> > > > > >  +extern "C" int console(const char *, ...);
>> > > > > > -+void crash_target_init (void);
>> > > > > >  +#endif
>> > > > > >  +
>> > > > > >   /* Call command_loop.  */
>> > > > > > @@ -316,7 +315,7 @@ exit 0
>> > > > > >         }
>> > > > > >       }
>> > > > > >
>> > > > > > -@@ -1242,6 +1274,16 @@ captured_main (void *data)
>> > > > > > +@@ -1242,6 +1274,14 @@ captured_main (void *data)
>> > > > > >
>> > > > > >     captured_main_1 (context);
>> > > > > >
>> > > > > > @@ -324,8 +323,6 @@ exit 0
>> > > > > >  +  /* Relocate the vmlinux. */
>> > > > > >  +  objfile_rebase (symfile_objfile, crash_get_kaslr_offset());
>> > > > > >  +
>> > > > > > -+  crash_target_init();
>> > > > > > -+
>> > > > > >  +  /* Back to crash.  */
>> > > > > >  +  main_loop();
>> > > > > >  +#endif
>> > > > > > diff --git a/gdb_interface.c b/gdb_interface.c
>> > > > > > index b14319c..03178f5 100644
>> > > > > > --- a/gdb_interface.c
>> > > > > > +++ b/gdb_interface.c
>> > > > > > @@ -3,6 +3,8 @@
>> > > > > >   * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
>> > > > > >   * Copyright (C) 2002-2015,2018-2019 David Anderson
>> > > > > >   * Copyright (C) 2002-2015,2018-2019 Red Hat, Inc. All rights reserved.
>> > > > > > + * Copyright (c) 2024 Broadcom. All Rights Reserved. The term "Broadcom"
>> > > > > > + * refers to Broadcom Inc. and/or its subsidiaries.
>> > > > > >   *
>> > > > > >   * 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
>> > > > > > @@ -711,7 +713,7 @@ static char *prohibited_list[] = {
>> > > > > >         "watch", "rwatch", "awatch", "attach", "continue", "c", "fg",
>> > > > > "detach",
>> > > > > >         "finish", "handle", "interrupt", "jump", "kill", "next", "nexti",
>> > > > > >         "signal", "step", "s", "stepi", "target", "until", "delete",
>> > > > > > -       "clear", "disable", "enable", "condition", "ignore", "frame",
>> > > > > "catch",
>> > > > > > +       "clear", "disable", "enable", "condition", "ignore", "gcore",
>> > > > > "catch",
>> > > > > >         "tcatch", "return", "file", "exec-file", "core-file",
>> > > > > "symbol-file",
>> > > > > >         "load", "si", "ni", "shell", "sy",
>> > > > > >         NULL  /* must be last */
>> > > > > > @@ -877,6 +879,7 @@ gdb_readmem_callback(ulong addr, void *buf, int len,
>> > > > > int write)
>> > > > > >         switch (len)
>> > > > > >         {
>> > > > > >         case SIZEOF_8BIT:
>> > > > > > +               fprintf(fp, "%s\n", pc->curcmd);
>> > > > > >                 if (STREQ(pc->curcmd, "bt")) {
>> > > > > >                         if (readmem(addr, memtype, buf, SIZEOF_8BIT,
>> > > > > >                             "gdb_readmem_callback", readflags))
>> > > > > > @@ -1063,34 +1066,52 @@ get_frame_offset(ulong pc)
>> > > > > >  unsigned long crash_get_kaslr_offset(void);
>> > > > > >  unsigned long crash_get_kaslr_offset(void)
>> > > > > >  {
>> > > > > > -        return kt->relocate * -1;
>> > > > > > +       return kt->relocate * -1;
>> > > > > >  }
>> > > > > >
>> > > > > >  /* Callbacks for crash_target */
>> > > > > > -int crash_get_nr_cpus(void);
>> > > > > > -int crash_get_cpu_reg (int cpu, int regno, const char *regname,
>> > > > > > +int crash_get_nr_tasks(void);
>> > > > > > +void crash_get_task_info(int task_nr, unsigned long *pid, char **comm);
>> > > > > > +int crash_get_task_reg (int task_nr, int regno, const char *regname,
>> > > > > >                         int regsize, void *val);
>> > > > > >
>> > > > > > -int crash_get_nr_cpus(void)
>> > > > > > +int crash_get_nr_tasks(void)
>> > > > > >  {
>> > > > > > -        if (SADUMP_DUMPFILE())
>> > > > > > -                return sadump_get_nr_cpus();
>> > > > > > -        else if (DISKDUMP_DUMPFILE())
>> > > > > > -                return diskdump_get_nr_cpus();
>> > > > > > -        else if (KDUMP_DUMPFILE())
>> > > > > > -                return kdump_get_nr_cpus();
>> > > > > > -        else if (VMSS_DUMPFILE())
>> > > > > > -                return vmware_vmss_get_nr_cpus();
>> > > > > > -
>> > > > > > -        /* Just CPU #0 */
>> > > > > ()> -        return 1;
>> > > > > > +       return RUNNING_TASKS();
>> > > > > >  }
>> > > > >
>> > > > > The crash_get_nr_tasks() will return a fixed number of running tasks,
>> > > > > which is the task status when crash is loading. However for live debug
>> > > > > mode, there will always be tasks exit and create, so we need to sync
>> > > > > the tasks number with the "info threads". I guess it is not an easy
>> > > > > work because that will involve:
>> > > > >
>> > > > > when crash loading:
>> > > > > for (int i = 0; i < nr_tasks; i++)
>> > > > > {
>> > > > >     thread_info *thread = add_thread_silent (target, ...
>> > > > > }
>> > > > >
>> > > > > when new task create:
>> > > > > thread_info *thread = add_thread_silent (target, ...
>> > > > >
>> > > > > when task exit:
>> > > > > delete_thread(...)
>> > > > >
>> > > > > We may monitor those task create/exit events and do thread add/delete
>> > > > > in a callback function or we just always do all tasks delete/add when
>> > > > > "info thread" is invoked. But I guess none of these are as simple as
>> > > > > using crash "ps" cmd and "set <pid>", there won't be any problem.
>> > > > > Because crash "ps" can always show the current tasks status, and set
>> > > > > <pid> can switch the task context to it.
>> > > > >
>> > > > > What do you think?
>> > > > >
>> > > > > Thanks,
>> > > > > Tao Liu
>> > > > >
>> > > > > >
>> > > > > > -int crash_get_cpu_reg (int cpu, int regno, const char *regname,
>> > > > > > -                       int regsize, void *value)
>> > > > > > +/* Get task information by its index number in TT */
>> > > > > > +void crash_get_task_info(int task_nr, unsigned long *pid, char **comm)
>> > > > > >  {
>> > > > > > -        if (!machdep->get_cpu_reg)
>> > > > > > -                return FALSE;
>> > > > > > -        return machdep->get_cpu_reg(cpu, regno, regname, regsize,
>> > > > > value);
>> > > > > > +       int i;
>> > > > > > +       struct task_context *tc;
>> > > > > > +
>> > > > > > +       tc = FIRST_CONTEXT();
>> > > > > > +       for (i = 0; i < RUNNING_TASKS(); i++, tc++)
>> > > > > > +               if (i == task_nr) {
>> > > > > > +                       *pid = tc->pid;
>> > > > > > +                       *comm = tc->comm;
>> > > > > > +                       return;
>> > > > > > +               }
>> > > > > > +       *pid = 0;
>> > > > > > +       *comm = NULL;
>> > > > > > +       return;
>> > > > > > +}
>> > > > > > +
>> > > > > > +int crash_get_task_reg (int task_nr, int regno, const char *regname,
>> > > > > > +                       int regsize, void *value)
>> > > > > > +{
>> > > > > > +       int i;
>> > > > > > +       struct task_context *tc;
>> > > > > > +
>> > > > > > +       if (!machdep->get_task_reg)
>> > > > > > +               return FALSE;
>> > > > > > +
>> > > > > > +       tc = FIRST_CONTEXT();
>> > > > > > +       for (i = 0; i < RUNNING_TASKS(); i++, tc++)
>> > > > > > +               if (i == task_nr) {
>> > > > > > +                       return machdep->get_task_reg(tc, regno, regname,
>> > > > > regsize, value);
>> > > > > > +               }
>> > > > > > +       return FALSE;
>> > > > > >  }
>> > > > > >
>> > > > > > diff --git a/help.c b/help.c
>> > > > > > index a9c4d30..85dbda5 100644
>> > > > > > --- a/help.c
>> > > > > > +++ b/help.c
>> > > > > > @@ -8520,6 +8520,7 @@ char *version_info[] = {
>> > > > > >  "Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.",
>> > > > > >  "Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.",
>> > > > > >  "Copyright (C) 2015, 2021  VMware, Inc.",
>> > > > > > +"Copyright (C) 2024  Broadcom, Inc.",
>> > > > > >  "This program is free software, covered by the GNU General Public
>> > > > > License,",
>> > > > > >  "and you are welcome to change it and/or distribute copies of it under",
>> > > > > >  "certain conditions.  Enter \"help copying\" to see the conditions.",
>> > > > > > diff --git a/main.c b/main.c
>> > > > > > index 0b6b927..13acd2d 100644
>> > > > > > --- a/main.c
>> > > > > > +++ b/main.c
>> > > > > > @@ -794,6 +794,7 @@ main_loop(void)
>> > > > > >         } else
>> > > > > >                 SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
>> > > > > >
>> > > > > > +       crash_target_init();
>> > > > > >          /*
>> > > > > >           *  Display system statistics and current context.
>> > > > > >           */
>> > > > > > diff --git a/task.c b/task.c
>> > > > > > index ebdb5be..5d26c52 100644
>> > > > > > --- a/task.c
>> > > > > > +++ b/task.c
>> > > > > > @@ -298,6 +298,7 @@ task_init(void)
>> > > > > >                 tt->flags |= THREAD_INFO;
>> > > > > >         }
>> > > > > >
>> > > > > > +       STRUCT_SIZE_INIT(inactive_task_frame, "inactive_task_frame");
>> > > > > >          MEMBER_OFFSET_INIT(task_struct_state, "task_struct", "state");
>> > > > > >         MEMBER_SIZE_INIT(task_struct_state, "task_struct", "state");
>> > > > > >         if (INVALID_MEMBER(task_struct_state)) {
>> > > > > > diff --git a/x86_64.c b/x86_64.c
>> > > > > > index 502817d..b6e36a5 100644
>> > > > > > --- a/x86_64.c
>> > > > > > +++ b/x86_64.c
>> > > > > > @@ -126,7 +126,7 @@ static int x86_64_get_framesize(struct bt_info *,
>> > > > > ulong, ulong, char *);
>> > > > > >  static void x86_64_framesize_debug(struct bt_info *);
>> > > > > >  static void x86_64_get_active_set(void);
>> > > > > >  static int x86_64_get_kvaddr_ranges(struct vaddr_range *);
>> > > > > > -static int x86_64_get_cpu_reg(int, int, const char *, int, void *);
>> > > > > > +static int x86_64_get_task_reg(struct task_context *, int, const char
>> > > > > *, int, void *);
>> > > > > >  static int x86_64_verify_paddr(uint64_t);
>> > > > > >  static void GART_init(void);
>> > > > > >  static void x86_64_exception_stacks_init(void);
>> > > > > > @@ -195,7 +195,7 @@ x86_64_init(int when)
>> > > > > >                 machdep->machspec->irq_eframe_link = UNINITIALIZED;
>> > > > > >                 machdep->machspec->irq_stack_gap = UNINITIALIZED;
>> > > > > >                 machdep->get_kvaddr_ranges = x86_64_get_kvaddr_ranges;
>> > > > > > -               machdep->get_cpu_reg = x86_64_get_cpu_reg;
>> > > > > > +               machdep->get_task_reg = x86_64_get_task_reg;
>> > > > > >                  if (machdep->cmdline_args[0])
>> > > > > >                          parse_cmdline_args();
>> > > > > >                 if ((string = pc->read_vmcoreinfo("relocate"))) {
>> > > > > > @@ -891,7 +891,7 @@ x86_64_dump_machdep_table(ulong arg)
>> > > > > >          fprintf(fp, "        is_page_ptr: x86_64_is_page_ptr()\n");
>> > > > > >          fprintf(fp, "       verify_paddr: x86_64_verify_paddr()\n");
>> > > > > >          fprintf(fp, "  get_kvaddr_ranges:
>> > > > > x86_64_get_kvaddr_ranges()\n");
>> > > > > > -       fprintf(fp, "        get_cpu_reg: x86_64_get_cpu_reg()\n");
>> > > > > > +       fprintf(fp, "       get_task_reg: x86_64_get_task_reg()\n");
>> > > > > >          fprintf(fp, "    init_kernel_pgd: x86_64_init_kernel_pgd()\n");
>> > > > > >          fprintf(fp, "clear_machdep_cache:
>> > > > > x86_64_clear_machdep_cache()\n");
>> > > > > >         fprintf(fp, " xendump_p2m_create: %s\n", PVOPS_XEN() ?
>> > > > > > @@ -6398,6 +6398,9 @@ x86_64_ORC_init(void)
>> > > > > >         };
>> > > > > >         struct ORC_data *orc;
>> > > > > >
>> > > > > > +       MEMBER_OFFSET_INIT(inactive_task_frame_bp,
>> > > > > "inactive_task_frame", "bp");
>> > > > > > +       MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr,
>> > > > > "inactive_task_frame", "ret_addr");
>> > > > > > +
>> > > > > >         if (machdep->flags & FRAMEPOINTER)
>> > > > > >                 return;
>> > > > > >
>> > > > > > @@ -6455,9 +6458,6 @@ x86_64_ORC_init(void)
>> > > > > >         orc->__stop_orc_unwind = symbol_value("__stop_orc_unwind");
>> > > > > >         orc->orc_lookup = symbol_value("orc_lookup");
>> > > > > >
>> > > > > > -       MEMBER_OFFSET_INIT(inactive_task_frame_bp,
>> > > > > "inactive_task_frame", "bp");
>> > > > > > -       MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr,
>> > > > > "inactive_task_frame", "ret_addr");
>> > > > > > -
>> > > > > >         orc->has_signal = MEMBER_EXISTS("orc_entry", "signal"); /* added
>> > > > > at 6.3 */
>> > > > > >         orc->has_end = MEMBER_EXISTS("orc_entry", "end");       /*
>> > > > > removed at 6.4 */
>> > > > > >
>> > > > > > @@ -9070,14 +9070,64 @@ x86_64_get_kvaddr_ranges(struct vaddr_range *vrp)
>> > > > > >  }
>> > > > > >
>> > > > > >  static int
>> > > > > > -x86_64_get_cpu_reg(int cpu, int regno, const char *name,
>> > > > > > +x86_64_get_task_reg(struct task_context *tc, int regno, const char
>> > > > > *name,
>> > > > > >                     int size, void *value)
>> > > > > >  {
>> > > > > >          if (regno >= LAST_REGNUM)
>> > > > > >                  return FALSE;
>> > > > > >
>> > > > > > +       /*
>> > > > > > +        * For inactive task, grab rip, rbp, rbx, r12, r13, r14 and r15
>> > > > > from
>> > > > > > +        * inactive_task_frame (see __switch_to_asm). Other regs saved on
>> > > > > > +        * regular frame.
>> > > > > > +        */
>> > > > > > +       if (!is_task_active(tc->task)) {
>> > > > > > +               int frame_size = STRUCT_SIZE("inactive_task_frame");
>> > > > > > +
>> > > > > > +               /* Only modern kernels supported. */
>> > > > > > +               if (tt->flags & THREAD_INFO && frame_size == 7 * 8) {
>> > > > > > +                       ulong rsp;
>> > > > > > +                       int offset = 0;
>> > > > > > +                       switch (regno) {
>> > > > > > +                               case RSP_REGNUM:
>> > > > > > +                                       readmem(tc->task +
>> > > > > OFFSET(task_struct_thread) +
>> > > > > > +
>> > > > >  OFFSET(thread_struct_rsp), KVADDR,
>> > > > > > +                                               &rsp, sizeof(void *),
>> > > > > > +                                               "thread_struct rsp",
>> > > > > FAULT_ON_ERROR);
>> > > > > > +                                       rsp += frame_size;
>> > > > > > +                                       memcpy(value, &rsp, size);
>> > > > > > +                                       return TRUE;
>> > > > > > +                               case RIP_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case RBP_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case RBX_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case R12_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case R13_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case R14_REGNUM:
>> > > > > > +                                       offset += 8;
>> > > > > > +                               case R15_REGNUM:
>> > > > > > +                                       readmem(tc->task +
>> > > > > OFFSET(task_struct_thread) +
>> > > > > > +
>> > > > >  OFFSET(thread_struct_rsp), KVADDR,
>> > > > > > +                                               &rsp, sizeof(void *),
>> > > > > > +                                               "thread_struct rsp",
>> > > > > FAULT_ON_ERROR);
>> > > > > > +                                       readmem(rsp + offset, KVADDR,
>> > > > > value, sizeof(void *),
>> > > > > > +
>> > > > >  "inactive_thread_frame saved regs", FAULT_ON_ERROR);
>> > > > > > +                                       return TRUE;
>> > > > > > +                       }
>> > > > > > +               }
>> > > > > > +               /* TBD: older kernels support. */
>> > > > > > +               return FALSE;
>> > > > > > +       }
>> > > > > > +
>> > > > > > +       /*
>> > > > > > +        * Task is active, grab CPU's registers
>> > > > > > +        */
>> > > > > >          if (VMSS_DUMPFILE())
>> > > > > > -                return vmware_vmss_get_cpu_reg(cpu, regno, name, size,
>> > > > > value);
>> > > > > > +                return vmware_vmss_get_cpu_reg(tc->processor, regno,
>> > > > > name, size, value);
>> > > > > >
>> > > > > >          return FALSE;
>> > > > > >  }
>> > > > > > --
>> > > > > > 2.39.0
>> > > > > >
>> > > > >
>> > > > >
>> > >
>>
--
Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux