teawater wrote:
> I think this is a hehavior of kernel.  I think change pc always a
> danger thing.  :)
>   
Yes, extremely dangeorous! ;)
But GDB supports feature such as "call <func_name>", when using it the
Joe user does not even cares the PC,
he just thinks that he makes call to some function...

Moreover the intent of changing stack by kernel is to make system call
to restart.
The kernel (in theory) could choose to not return to userland at this
point (because of no signal handlers are set by the process)
and restart syscall internally.
If it where so, all the process could have been transparent for GDB.

And this usecase is enounted quite often by users....:(

Because the nature of the problem is quite clear, it could be (once "in
theory") worked around both in kernel and in GDB.

Because the GDB does a lot of tricks and serves to thecnical puroses may
be it it the best place to implement workaround there?

Yet from point of view of kernel that's the place where either nobody
(even GDB) is supposed to intervien  the kernel internal
housekeeping, at least till the next machine instruction is executed.
So the kernel could either:
[1] not enable the GDB/ptrace to stop process and change user registers
at that point
[2] remember the state of essential registers (PC, may be others likes
FP) and revert all changes before executing the next instruction
[3] remember the state of essential registers (PC, may be others likes
FP)  and if the process was stopped
     and somebody (GDB/ptrace) changed PC before execution of the next
instruction then kernel can avoid it's own changes of PC


Anyway the problem exists and I'm trying at least to find out where
needs to be fixed
>
> infrun: clear_proceed_status_thread (process 4542)
> infrun: proceed (addr=0xffffffff, signal=144, step=0)
> infrun: resume (step=0, signal=0), trap_expected=0
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> infrun: target_wait (-1, status) =
> infrun:   4542 [process 4542],
> infrun:   status->kind = stopped, signal = SIGINT
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0xb7fe3410
> infrun: random signal 2
>
> Program received signal SIGINT, Interrupt.
> infrun: stop_stepping
> 0xb7fe3410 in __kernel_vsyscall ()
> (gdb) disas
> Dump of assembler code for function __kernel_vsyscall:
>    0xb7fe3400 <+0>:   push   %ecx
>    0xb7fe3401 <+1>:   push   %edx
>    0xb7fe3402 <+2>:   push   %ebp
>    0xb7fe3403 <+3>:   mov    %esp,%ebp
>    0xb7fe3405 <+5>:   sysenter
>    0xb7fe3407 <+7>:   nop
>    0xb7fe3408 <+8>:   nop
>    0xb7fe3409 <+9>:   nop
>    0xb7fe340a <+10>:  nop
>    0xb7fe340b <+11>:  nop
>    0xb7fe340c <+12>:  nop
>    0xb7fe340d <+13>:  nop
>    0xb7fe340e <+14>:  jmp    0xb7fe3403 <__kernel_vsyscall+3>
> => 0xb7fe3410 <+16>:  pop    %ebp
>    0xb7fe3411 <+17>:  pop    %edx
>    0xb7fe3412 <+18>:  pop    %ecx
>    0xb7fe3413 <+19>:  ret
> End of assembler dump.
> (gdb) p $pc
> $1 = (void (*)()) 0xb7fe3410 <__kernel_vsyscall+16>
> (gdb) p $pc=0xb7fe3413
> $2 = (void (*)()) 0xb7fe3413 <__kernel_vsyscall+19>
> (gdb) si
> infrun: clear_proceed_status_thread (process 4542)
> infrun: proceed (addr=0xffffffff, signal=144, step=1)
> infrun: resume (step=1, signal=0), trap_expected=0
> infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
> infrun: target_wait (-1, status) =
> infrun:   4542 [process 4542],
> infrun:   status->kind = stopped, signal = SIGTRAP
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_STOPPED
> infrun: stop_pc = 0xb7fe3412
> infrun: stepi/nexti
> infrun: stop_stepping
> 0xb7fe3412 in __kernel_vsyscall ()
>
> Thanks,
> Hui
>
>
>
> On Nov 2, 7:27 pm, Alexandre Rusev <aru...@ru.mvista.com> wrote:
>   
>> teawater wrote:
>>     
>>> This signal ctrl-c will not really send to inferior.
>>>       
>> But the result is interrupted system call which is restarted then by kernel.
>> And is user changes program counter in GDB at this point,
>> then it takes place before the modification of PC is done by kernel.
>> The result is that execution jumps neither to the point the user said in
>> GDB nor
>> to the point the kernel wishes it be due to restart the syscall.
>>
>> Is it incorrect behavior of GDB or incorrect behavior of kernel or
>> something else???
>>
>>     
>>> (gdb) help info handle
>>>       
>>> On Oct 31, 12:10 am, Alexandre Rusev <aru...@ru.mvista.com> wrote:
>>>       
>>>> Hi.
>>>>         
>>>> When the program at ht end of message debugged under GDB is stopped with
>>>> Ctrl+C
>>>> it's usually found in interrupted system call. (The same result is
>>>> observed for x86 and PPC with kernels 2.6.18 and 2.6.28)
>>>>         
>>>> (gdb) where
>>>> #0  0xb7fe2424 in __kernel_vsyscall ()
>>>> #1  0xb7f36ad0 in nanosleep () from /lib/libc.so.6
>>>> #2  0xb7f3690e in sleep () from /lib/libc.so.6
>>>> #3  0x08048600 in qqq () at testBT2.c:45
>>>> #4  0x080487a5 in eee () at testBT2.c:73
>>>> #5  0x0804846a in main () at testBT2.c:17
>>>>         
>>>> The PC is pointing at the next instruction, accordingly to GDB.
>>>> But the kernel tries to restart syscall by means of changing PC to PC-4
>>>> (in case of PowerPC and to some other value for x86)
>>>> and it does it's change to PC after the user continues execution of
>>>> program in GDB with "cont" or "si" command.
>>>>         
>>>> The issue is that if user changed PC at this point or uses "call
>>>> <func_name>" GDB command, the both changes to PC
>>>> are added (as kernel uses PC relative change i.e. PC - 4), and the
>>>> program continues execution at absolutely wrong place.
>>>>         
>>>> The issue may be gracefully observed if breakpoint is set just before
>>>> <func_name> and then PC is changed to the <func_name> address.
>>>> In such case the breakpoint is hit while it must not be.
>>>>         
>>>> #include <stdio.h>
>>>> #include <stdlib.h>
>>>>         
>>>> void qqq();
>>>> void www();
>>>> void eee();
>>>>         
>>>> void * xrealloc(void*, int);
>>>>         
>>>> int main(void)
>>>> {
>>>>         eee();
>>>>     return EXIT_SUCCESS;
>>>>         
>>>> }
>>>>         
>>>> void qqq() {
>>>>     void *a[256];
>>>>     size_t i, n;
>>>>         
>>>>     for (i = 0; i < 256; i++)
>>>>     {
>>>>         n = (size_t) ((rand() * 256.0) / (RAND_MAX + 1.0)) + 1;
>>>>         a[i] = malloc(n);
>>>>     }
>>>>     for (i = 256; i > 0; i--)
>>>>     {
>>>>         n = (size_t) ((rand() * 256.0) / (RAND_MAX + 1.0)) + 1;
>>>>         a[i - 1] = xrealloc(a[i - 1], n);
>>>>     }
>>>>     sleep(1);
>>>>     for (i = 0; i < 256; i += 2)
>>>>         free(a[i]);
>>>>     for (i = 256; i > 0; i -= 2)
>>>>         free(a[i - 1]);
>>>>     sleep(1);
>>>>         
>>>> }
>>>>         
>>>> void www() {
>>>>     void *a[256];
>>>>     size_t i, n;
>>>>         
>>>>     for (i = 0; i < 256; i++)
>>>>     {
>>>>         n = (size_t) ((rand() * 256.0) / (RAND_MAX + 1.0)) + 1;
>>>>         a[i] = malloc(n);
>>>>     }
>>>>     for (i = 256; i > 0; i--)
>>>>     {
>>>>         n = (size_t) ((rand() * 256.0) / (RAND_MAX + 1.0)) + 1;
>>>>         a[i - 1] = realloc(a[i - 1], n);
>>>>     }
>>>>     sleep(1);
>>>>     for (i = 0; i < 256; i += 2)
>>>>         free(a[i]);
>>>>     for (i = 256; i > 0; i -= 2)
>>>>         free(a[i - 1]);
>>>>     sleep(1);
>>>>         
>>>> }
>>>>         
>>>> void eee() {
>>>>         
>>>>         while (1) {
>>>>                 qqq();
>>>>         
>>>>                 www();
>>>>         
>>>>         }
>>>>         
>>>> }
>>>>         
>>>> void * xrealloc(void* addr, int n) {
>>>>         return realloc(addr, n);
>>>>         
>>>> }
>>>>         
>>> _______________________________________________
>>> bug-gdb mailing list
>>> bug-...@gnu.org
>>> http://lists.gnu.org/mailman/listinfo/bug-gdb
>>>       
>
>   

_______________________________________________
bug-gdb mailing list
bug-gdb@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-gdb

Reply via email to