[Bug ada/24533] FAIL: a85013b: *** glibc detected *** free(): invalid pointer: 0x00062a00 ***

dave at hiauly1 dot hia dot nrc dot ca gcc-bugzilla@gcc.gnu.org
Sun Jan 1 17:12:00 GMT 2006



------- Comment #3 from dave at hiauly1 dot hia dot nrc dot ca  2006-01-01 17:11 -------
Subject: Re:  FAIL:   a85013b: *** glibc detected *** free(): invalid pointer:
0x00062a00 ***

I've looked at the failure of a85013b.adb.

The problem seems to be that "new" is applying a kind of rounding
to the pointer returned by malloc.  Then, the rounded pointer is used
for the call to free.  This is the cause of the invalid pointer
error and the test being aborted by free().

The rounding occurs in this function:

   --------------
   -- New_ATCB --
   --------------

   function New_ATCB (Entry_Num : Task_Entry_Index) return Task_Id is
   begin
     return new Ada_Task_Control_Block (Entry_Num);
   end New_ATCB

This is the assembly code (-O0):
(gdb) disass
Dump of assembler code for function system.task_primitives.operations.new_atcb:
0x0003186c <system.task_primitives.operations.new_atcb+0>:      stw rp,-14(,sp)
0x00031870 <system.task_primitives.operations.new_atcb+4>:      copy r3,r1
0x00031874 <system.task_primitives.operations.new_atcb+8>:      copy sp,r3
0x00031878 <system.task_primitives.operations.new_atcb+12>:     stw,ma
r1,40(,sp)
0x0003187c <system.task_primitives.operations.new_atcb+16>:     stw r4,8(,r3)
0x00031880 <system.task_primitives.operations.new_atcb+20>:     stw
r26,-24(,r3)
0x00031884 <system.task_primitives.operations.new_atcb+24>:     ldw
-24(,r3),ret0
0x00031888 <system.task_primitives.operations.new_atcb+28>:     cmpiclr,<
0,ret0,r0
0x0003188c <system.task_primitives.operations.new_atcb+32>:     ldi 0,ret0
0x00031890 <system.task_primitives.operations.new_atcb+36>:     depw,z
ret0,28,29,ret0
0x00031894 <system.task_primitives.operations.new_atcb+40>:     ldo
757(ret0),ret0
0x00031898 <system.task_primitives.operations.new_atcb+44>:     depwi
0,31,4,ret0
0x0003189c <system.task_primitives.operations.new_atcb+48>:     ldo
10(ret0),ret0
0x000318a0 <system.task_primitives.operations.new_atcb+52>:     copy ret0,r26
---Type <return> to continue, or q <return> to quit---
0x000318a4 <system.task_primitives.operations.new_atcb+56>:     b,l 0x2e438
<__gnat_malloc>,rp
0x000318a8 <system.task_primitives.operations.new_atcb+60>:     nop
0x000318ac <system.task_primitives.operations.new_atcb+64>:     copy ret0,r20
0x000318b0 <system.task_primitives.operations.new_atcb+68>:     copy r20,ret0
0x000318b4 <system.task_primitives.operations.new_atcb+72>:     sub
r0,ret0,ret0
0x000318b8 <system.task_primitives.operations.new_atcb+76>:     extrw,u
ret0,31,4,r19
0x000318bc <system.task_primitives.operations.new_atcb+80>:     copy r20,ret0
0x000318c0 <system.task_primitives.operations.new_atcb+84>:     add,l
ret0,r19,ret0
0x000318c4 <system.task_primitives.operations.new_atcb+88>:     copy ret0,r4
0x000318c8 <system.task_primitives.operations.new_atcb+92>:     copy r4,ret0
0x000318cc <system.task_primitives.operations.new_atcb+96>:     copy ret0,r26
0x000318d0 <system.task_primitives.operations.new_atcb+100>:    ldw
-24(,r3),r25
0x000318d4 <system.task_primitives.operations.new_atcb+104>:    b,l 0x32698
<system__tasking__ada_task_control_blockIP>,rp
0x000318d8 <system.task_primitives.operations.new_atcb+108>:    nop
0x000318dc <system.task_primitives.operations.new_atcb+112>:    copy r4,ret0
0x000318e0 <system.task_primitives.operations.new_atcb+116>:    ldw -14(,r3),rp
0x000318e4 <system.task_primitives.operations.new_atcb+120>:    ldw 8(,r3),r4
---Type <return> to continue, or q <return> to quit---
0x000318e8 <system.task_primitives.operations.new_atcb+124>:    ldo 40(r3),sp
0x000318ec <system.task_primitives.operations.new_atcb+128>:    ldw,mb
-40(,sp),r3
0x000318f0 <system.task_primitives.operations.new_atcb+132>:    bv,n r0(rp)
End of assembler dump(gdb) bt
#0  0x000318cc in system.task_primitives.operations.new_atcb (entry_num=1)
    at s-taprop.adb:752
#1  0x000512f8 in system.tasking.stages.create_task (priority=-1,
    size=-2147483648, task_info=default_scope, num_entries=1, master=4,
    state=0xc068c746, discriminants=3228092176, elaborated=0xc068c714, chain=,
    task_image=0x5edf4, created_task=0x0) at s-tassta.adb:574
#2  0x00055498 in a85013b__tTKVIP___789 () at a85013b.adb:65
#3  0x000551c8 in a85013b () at a85013b.adb:65
#4  0x00014d84 in main ()

(gdb) p $r19
$8 = 8
(gdb) p $r20
$9 = 562904
(gdb) p $ret0
$10 = 562912

The value in r20 is the result that was returned in ret0 in the call
to __gnat_malloc.  The value in $ret0 at this point is the value that
system.task_primitives.operations.new_atcb returns and is subsequently
used in the call to free().

I don't know ada well enough to know where this bit of code comes from

0x000318b0 <system.task_primitives.operations.new_atcb+68>:     copy r20,ret0
0x000318b4 <system.task_primitives.operations.new_atcb+72>:     sub
r0,ret0,ret0
0x000318b8 <system.task_primitives.operations.new_atcb+76>:     extrw,u
ret0,31,4,r19
0x000318bc <system.task_primitives.operations.new_atcb+80>:     copy r20,ret0
0x000318c0 <system.task_primitives.operations.new_atcb+84>:     add,l
ret0,r19,ret0

but it appears to round the address returned by malloc up to a 16-byte
boundary.  The rounded address is used in the call to free.  This
is undefined:

       free() frees the memory space pointed to by ptr, which must  have  been
       returned by a previous call to malloc(), calloc() or realloc().  Other-
       wise, or  if  free(ptr)  has  already  been  called  before,  undefined
       behaviour occurs.

It seems that the 16-byte alignment used for TCBs is a result of using
16-byte alignment for atomic_lock_t.  Changing the alignment to 8 fixes
the testsuite failures.  The current glibc implementation handles lock
objects that aren't aligned to 16-byte boundaries by dynamically picking
an aligned lock word:

  /* We need 128-bit alignment for the ldcw semaphore.  At most, we are
     assured of 64-bit alignment for stack locals and malloc'd data.  Thus,
     we use a struct with four ints for the atomic lock type.  The locking
     code will figure out which of the four to use for the ldcw semaphore.  */
  typedef volatile struct {
    int lock[4];
  } __attribute__ ((aligned(16))) __atomic_lock_t;

It's unclear to me whether changing the alignment for atomic_lock_t
in s-osinte-linux-hppa.ads is correct as it changes struct layouts,
and could cause problems if an object containing an atomic_lock_t object
is copied.

It is clear that the pointer returned by malloc must be retained for
the free operation.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24533




More information about the Gcc-bugs mailing list