This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[hpux] problem during unwinding from bizarre code
- From: Joel Brobecker <brobecker at adacore dot com>
- To: randolph at tausq dot org
- Cc: gdb-patches at sources dot redhat dot com
- Date: Fri, 10 Dec 2004 15:21:24 +0100
- Subject: [hpux] problem during unwinding from bizarre code
Hello Randolph,
Using the Ada code copied at the end of this message, and compiled with
the command:
% gnatmake -g task_switch
The following transcript shows that we are seeing a failure when
unwinding from pthread_mutex_unlock():
(gdb) b task_switch.adb:43
Breakpoint 1 at 0xa684: file task_switch.adb, line 43.
(gdb) run
Starting program: /[...]/task_switch
[New thread 2 (system thread 19159)]
[New thread 3 (system thread 19160)]
[Switching to thread 3 (system thread 19160)]
Breakpoint 1, task_switch.break_me () at task_switch.adb:43
43 end Break_Me;
(gdb) thread 1
[Switching to thread 1 (system thread 11738)]#0 0x7afff760 in __kwakeup ()
from /usr/lib/libc.2
(gdb) bt
#0 0x7afff760 in __kwakeup () from /usr/lib/libc.2
#1 0x7aee5fe8 in __spin_unlock () from /usr/lib/libpthread.1
#2 0x7aee45a8 in pthread_mutex_unlock () from /usr/lib/libpthread.1
#3 0x7aee45a8 in pthread_mutex_unlock () from /usr/lib/libpthread.1
Previous frame identical to this frame (corrupt stack?)
We failed during the unwind from frame 2. The unwind record for 0x7aee45a8
(frame 2) is:
$2 = {region_start = 0x7aee4594, region_end = 0x7aee45b0, Cannot_unwind = 0x0,
Millicode = 0x0, Millicode_save_sr0 = 0x0, Region_description = 0x3,
reserved1 = 0x0, Entry_SR = 0x0, Entry_FR = 0x0, Entry_GR = 0x1,
Args_stored = 0x1, Variable_Frame = 0x0, Separate_Package_Body = 0x0,
Frame_Extension_Millicode = 0x0, Stack_Overflow_Check = 0x0,
Two_Instruction_SP_Increment = 0x0, Ada_Region = 0x0, cxx_info = 0x0,
cxx_try_catch = 0x0, sched_entry_seq = 0x0, reserved2 = 0x1, Save_SP = 0x0,
Save_RP = 0x1, Save_MRP_in_frame = 0x0, extn_ptr_defined = 0x0,
Cleanup_defined = 0x0, MPE_XL_interrupt_marker = 0x0,
HP_UX_interrupt_marker = 0x0, Large_frame = 0x0, Pseudo_SP_Set = 0x0,
reserved4 = 0x1, Total_frame_size = 0x10, stub_unwind = {stub_type = 0x0,
padding = 0x0}}
When you look at the code corresponding to that region, you find:
0x7aee4594 <pthread_mutex_unlock+1084>: ldw 3c(sr0,r3),ret0
0x7aee4598 <pthread_mutex_unlock+1088>: ldo -1(ret0),r31
0x7aee459c <pthread_mutex_unlock+1092>: stw r31,3c(sr0,r3)
0x7aee45a0 <pthread_mutex_unlock+1096>: b,l 0x7aee5fa8 <__spin_unlock>,rp
0x7aee45a4 <pthread_mutex_unlock+1100>: ldo 8(r3),r26
0x7aee45a8 <pthread_mutex_unlock+1104>: ldw -20(sr0,sp),r19
0x7aee45ac <pthread_mutex_unlock+1108>:
movb,tr r0,ret0,0x7aee4518 <pthread_mutex_unlock+960>
0x7aee45b0 <pthread_mutex_unlock+1112>: ldw -94(sr0,sp),rp
It looks like one of these cases where we have a function for which
no symbol has been defined. But at the same time, the code above does
not very much look like a function to me, no?
Looking a bit closer, a collegue and myself found that the code range
that GDB thinks is pthread_mutex_unlock has several unwind records.
For instance, it starts with:
(gdb) maintenance print unwind &pthread_mutex_unlock
unwind_table_entry (0x401db134):
region_start = 0x7aee4158 <pthread_mutex_unlock>
region_end = 0x7aee42a0 <pthread_mutex_unlock+328>
flags = Args_stored Save_RP
Region_description = 0x0
Entry_FR = 0x0
Entry_GR = 0x2
Total_frame_size = 0x8
And the region end code is:
0x7aee428c <pthread_mutex_unlock+308>: ldo 0(r3),r26
0x7aee4290 <pthread_mutex_unlock+312>: ldw -20(,sp),r19
0x7aee4294 <pthread_mutex_unlock+316>: ldw -54(,sp),rp
0x7aee4298 <pthread_mutex_unlock+320>: ldw -3c(,sp),r4
0x7aee429c <pthread_mutex_unlock+324>: bv r0(rp)
0x7aee42a0 <pthread_mutex_unlock+328>: ldw,mb -40(,sp),r3
Which looks like an epilogue. The next region is:
unwind_table_entry (0x401db148):
region_start = 0x7aee42a4 <pthread_mutex_unlock+332>
region_end = 0x7aee42e4 <pthread_mutex_unlock+396>
flags = Args_stored Save_RP
Region_description = 0x0
Entry_FR = 0x0
Entry_GR = 0x3
Total_frame_size = 0x10
And the code at the start of the region is:
0x7aee42a4 <pthread_mutex_unlock+332>: stw rp,-14(,sp)
0x7aee42a8 <pthread_mutex_unlock+336>: stw,ma r3,80(,sp)
0x7aee42ac <pthread_mutex_unlock+340>: stw r4,-7c(,sp)
0x7aee42b0 <pthread_mutex_unlock+344>: stw r5,-78(,sp)
0x7aee42b4 <pthread_mutex_unlock+348>: ldi 36,r3
Which again looks like a sensible prologue to me.
But I am a bit dumbfounded with the last region. By the way,
pthread_mutex_unlock+960 is almost the end of a region:
(gdb) maintenance print unwind &pthread_mutex_unlock+960
unwind_table_entry (0x401db170):
region_start = 0x7aee4454 <pthread_mutex_unlock+764>
region_end = 0x7aee451c <pthread_mutex_unlock+964>
flags = Args_stored Save_RP
Region_description = 0x0
Entry_FR = 0x0
Entry_GR = 0x1
Total_frame_size = 0x10
And the instructions the code is jumping to are:
0x7aee4518 <pthread_mutex_unlock+960>: bv r0(rp)
0x7aee451c <pthread_mutex_unlock+964>: ldw,mb -80(,sp),r3
It's the last instructions of something that looks like a function
epilogue to me:
0x7aee450c <pthread_mutex_unlock+948>: ldw -20(,sp),r19
0x7aee4510 <pthread_mutex_unlock+952>: ldw -94(,sp),rp
0x7aee4514 <pthread_mutex_unlock+956>: ldi 0,ret0
0x7aee4518 <pthread_mutex_unlock+960>: bv r0(rp)
0x7aee451c <pthread_mutex_unlock+964>: ldw,mb -80(,sp),r3
Would you have an idea or how to find the return address?
Thanks,
--
Joel
procedure Task_Switch is
-------------------
-- Declaractions --
-------------------
task type Callee is
entry Finito;
end Callee;
type Callee_Ptr is access Callee;
task type Caller is
end Caller;
type Caller_Ptr is access Caller;
procedure Break_Me;
My_Caller : Caller_Ptr;
My_Callee : Callee_Ptr;
------------
-- Bodies --
------------
task body Callee is
begin
-- Just wait until we are told to terminate this task.
-- This is just to maintain this task alive.
accept Finito do
null;
end Finito;
end Callee;
task body Caller is
begin
Break_Me;
My_Callee.Finito;
end Caller;
procedure Break_Me is
begin
null; -- line 43
end Break_Me;
begin
-- Make sure to create the Callee task first... And then give it
-- enough time to complete its activation phase before we start
-- the Caller task.
My_Callee := new Callee;
delay 0.1;
My_Caller := new Caller;
end Task_Switch;