-fsection-anchors broken on ARM

Johannes Pfau avatarJohannes Pfau created an issue

When running a program on ARM, the GC immediately enters an infinite loop. Debugging shows that the entered loop is in gcx.d line 2179:

for (; p < ptop; p += size)
{
     (cast(List *)p).next = *b;
     *b = cast(List *)p;
}

p and ptop are correct, but size is 0. size is set in line 2174:

size_t size = binsize[bin];

binsize is just an array of uints:

immutable uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];

bin was 3 in my tests, a correct index value. Still the array entry lookup somehow fails. This only happens with optimization turned on though: If druntime is compiled with -O0 the gc works fine.

Testing with optimization enabled:

I added code to make a copy of binsize and looked at that copy with gdb:

$1 = {0 <repeats 12 times>}

So I looked at the binsize symbol:

readelf -s -w ./hello_d | grep binsize
  5665: 00050c64    48 OBJECT  GLOBAL DEFAULT   14 _D2gc3gcx7binsizeyG12k

lets have a look at section 14:

readelf -S hello_d
There are 41 section headers, starting at offset 0x175464:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [14] .rodata           PROGBITS        00049db8 041db8 0089d0 00   A  0   0  8

Dump it:

readelf -x 14 hello_d
...
  0x00050c58 00000000 00000000 00000000 10000000 ................
  0x00050c68 20000000 40000000 80000000 00010000  ...@...........
  0x00050c78 00020000 00040000 00080000 00100000 ................
  0x00050c88 00000000 00000000 00000000 00000000 ................
  0x00050c98 00000000 00000000 00000000 00000000 ................

seems to be correct though.

asm dump of function allocPage:

Dump of assembler code for function _D2gc3gcx3Gcx9allocPageMFhZi:
0x00042c58 <_D2gc3gcx3Gcx9allocPageMFhZi+0>:	push	{r4, r5, r6, r7, r8, lr}
0x00042c5c <_D2gc3gcx3Gcx9allocPageMFhZi+4>:	ldr	r3, [r0, #80]	; 0x50
0x00042c60 <_D2gc3gcx3Gcx9allocPageMFhZi+8>:	mov	r5, r0
0x00042c64 <_D2gc3gcx3Gcx9allocPageMFhZi+12>:	cmp	r3, #0
0x00042c68 <_D2gc3gcx3Gcx9allocPageMFhZi+16>:	mov	r7, r1
0x00042c6c <_D2gc3gcx3Gcx9allocPageMFhZi+20>:	beq	0x42d08 <_D2gc3gcx3Gcx9allocPageMFhZi+176>
0x00042c70 <_D2gc3gcx3Gcx9allocPageMFhZi+24>:	mov	r4, #0
0x00042c74 <_D2gc3gcx3Gcx9allocPageMFhZi+28>:	b	0x42c84 <_D2gc3gcx3Gcx9allocPageMFhZi+44>
0x00042c78 <_D2gc3gcx3Gcx9allocPageMFhZi+32>:	ldr	r3, [r5, #80]	; 0x50
0x00042c7c <_D2gc3gcx3Gcx9allocPageMFhZi+36>:	cmp	r3, r4
0x00042c80 <_D2gc3gcx3Gcx9allocPageMFhZi+40>:	bls	0x42d08 <_D2gc3gcx3Gcx9allocPageMFhZi+176>
0x00042c84 <_D2gc3gcx3Gcx9allocPageMFhZi+44>:	ldr	r3, [r5, #84]	; 0x54
0x00042c88 <_D2gc3gcx3Gcx9allocPageMFhZi+48>:	mov	r1, #1
0x00042c8c <_D2gc3gcx3Gcx9allocPageMFhZi+52>:	ldr	r6, [r3, r4, lsl #2]
0x00042c90 <_D2gc3gcx3Gcx9allocPageMFhZi+56>:	add	r4, r4, r1
0x00042c94 <_D2gc3gcx3Gcx9allocPageMFhZi+60>:	mov	r0, r6
0x00042c98 <_D2gc3gcx3Gcx9allocPageMFhZi+64>:	bl	0x42bfc <_D2gc3gcx4Pool10allocPagesMFkZk>
0x00042c9c <_D2gc3gcx3Gcx9allocPageMFhZi+68>:	cmn	r0, #1
0x00042ca0 <_D2gc3gcx3Gcx9allocPageMFhZi+72>:	beq	0x42c78 <_D2gc3gcx3Gcx9allocPageMFhZi+32>
0x00042ca4 <_D2gc3gcx3Gcx9allocPageMFhZi+76>:	ldr	r3, [r6, #88]	; 0x58
0x00042ca8 <_D2gc3gcx3Gcx9allocPageMFhZi+80>:	ldr	r2, [pc, #96]	; 0x42d10 <_D2gc3gcx3Gcx9allocPageMFhZi+184>
0x00042cac <_D2gc3gcx3Gcx9allocPageMFhZi+84>:	strb	r7, [r3, r0]
0x00042cb0 <_D2gc3gcx3Gcx9allocPageMFhZi+88>:	ldr	r3, [r6]
0x00042cb4 <_D2gc3gcx3Gcx9allocPageMFhZi+92>:	ldr	r2, [r2, r7, lsl #2]
0x00042cb8 <_D2gc3gcx3Gcx9allocPageMFhZi+96>:	add	r0, r3, r0, lsl #12
0x00042cbc <_D2gc3gcx3Gcx9allocPageMFhZi+100>:	add	r5, r5, #88	; 0x58
0x00042cc0 <_D2gc3gcx3Gcx9allocPageMFhZi+104>:	add	r12, r0, r2
0x00042cc4 <_D2gc3gcx3Gcx9allocPageMFhZi+108>:	ldr	r4, [r5, r7, lsl #2]
0x00042cc8 <_D2gc3gcx3Gcx9allocPageMFhZi+112>:	add	r6, r0, #4096	; 0x1000
0x00042ccc <_D2gc3gcx3Gcx9allocPageMFhZi+116>:	add	r7, r5, r7, lsl #2
0x00042cd0 <_D2gc3gcx3Gcx9allocPageMFhZi+120>:	mov	r1, r12
0x00042cd4 <_D2gc3gcx3Gcx9allocPageMFhZi+124>:	b	0x42ce0 <_D2gc3gcx3Gcx9allocPageMFhZi+136>
0x00042cd8 <_D2gc3gcx3Gcx9allocPageMFhZi+128>:	mov	r4, r3
0x00042cdc <_D2gc3gcx3Gcx9allocPageMFhZi+132>:	add	r12, r12, r2
0x00042ce0 <_D2gc3gcx3Gcx9allocPageMFhZi+136>:	add	r1, r1, r2
0x00042ce4 <_D2gc3gcx3Gcx9allocPageMFhZi+140>:	rsb	r3, r2, r1
0x00042ce8 <_D2gc3gcx3Gcx9allocPageMFhZi+144>:	cmp	r6, r3
0x00042cec <_D2gc3gcx3Gcx9allocPageMFhZi+148>:	str	r4, [r0]
0x00042cf0 <_D2gc3gcx3Gcx9allocPageMFhZi+152>:	mov	r3, r0
0x00042cf4 <_D2gc3gcx3Gcx9allocPageMFhZi+156>:	str	r0, [r7]
0x00042cf8 <_D2gc3gcx3Gcx9allocPageMFhZi+160>:	mov	r0, r12
0x00042cfc <_D2gc3gcx3Gcx9allocPageMFhZi+164>:	bhi	0x42cd8 <_D2gc3gcx3Gcx9allocPageMFhZi+128>
0x00042d00 <_D2gc3gcx3Gcx9allocPageMFhZi+168>:	mov	r0, #1
0x00042d04 <_D2gc3gcx3Gcx9allocPageMFhZi+172>:	pop	{r4, r5, r6, r7, r8, pc}
0x00042d08 <_D2gc3gcx3Gcx9allocPageMFhZi+176>:	mov	r0, #0
0x00042d0c <_D2gc3gcx3Gcx9allocPageMFhZi+180>:	pop	{r4, r5, r6, r7, r8, pc}
0x00042d10 <_D2gc3gcx3Gcx9allocPageMFhZi+184>:	ldrdeq	r0, [r5], -r4

Testing with -O0

asm dump, compiled with -O0

Dump of assembler code for function _D2gc3gcx3Gcx9allocPageMFhZi:
0x00046eb8 <_D2gc3gcx3Gcx9allocPageMFhZi+0>:	push	{r11, lr}
0x00046ebc <_D2gc3gcx3Gcx9allocPageMFhZi+4>:	add	r11, sp, #4
0x00046ec0 <_D2gc3gcx3Gcx9allocPageMFhZi+8>:	sub	sp, sp, #40	; 0x28
0x00046ec4 <_D2gc3gcx3Gcx9allocPageMFhZi+12>:	str	r0, [r11, #-40]	; 0x28
0x00046ec8 <_D2gc3gcx3Gcx9allocPageMFhZi+16>:	mov	r3, r1
0x00046ecc <_D2gc3gcx3Gcx9allocPageMFhZi+20>:	strb	r3, [r11, #-41]	; 0x29
0x00046ed0 <_D2gc3gcx3Gcx9allocPageMFhZi+24>:	mov	r3, #0
0x00046ed4 <_D2gc3gcx3Gcx9allocPageMFhZi+28>:	str	r3, [r11, #-8]
0x00046ed8 <_D2gc3gcx3Gcx9allocPageMFhZi+32>:	mov	r3, #0
0x00046edc <_D2gc3gcx3Gcx9allocPageMFhZi+36>:	str	r3, [r11, #-12]
0x00046ee0 <_D2gc3gcx3Gcx9allocPageMFhZi+40>:	mov	r3, #0
0x00046ee4 <_D2gc3gcx3Gcx9allocPageMFhZi+44>:	str	r3, [r11, #-16]
0x00046ee8 <_D2gc3gcx3Gcx9allocPageMFhZi+48>:	mov	r3, #0
0x00046eec <_D2gc3gcx3Gcx9allocPageMFhZi+52>:	str	r3, [r11, #-20]
0x00046ef0 <_D2gc3gcx3Gcx9allocPageMFhZi+56>:	mov	r3, #0
0x00046ef4 <_D2gc3gcx3Gcx9allocPageMFhZi+60>:	str	r3, [r11, #-24]
0x00046ef8 <_D2gc3gcx3Gcx9allocPageMFhZi+64>:	mov	r3, #0
0x00046efc <_D2gc3gcx3Gcx9allocPageMFhZi+68>:	str	r3, [r11, #-12]
0x00046f00 <_D2gc3gcx3Gcx9allocPageMFhZi+72>:	ldr	r3, [r11, #-40]	; 0x28
0x00046f04 <_D2gc3gcx3Gcx9allocPageMFhZi+76>:	ldr	r3, [r3, #80]	; 0x50
0x00046f08 <_D2gc3gcx3Gcx9allocPageMFhZi+80>:	ldr	r2, [r11, #-12]
0x00046f0c <_D2gc3gcx3Gcx9allocPageMFhZi+84>:	cmp	r2, r3
0x00046f10 <_D2gc3gcx3Gcx9allocPageMFhZi+88>:	movcs	r3, #0
0x00046f14 <_D2gc3gcx3Gcx9allocPageMFhZi+92>:	movcc	r3, #1
0x00046f18 <_D2gc3gcx3Gcx9allocPageMFhZi+96>:	and	r3, r3, #255	; 0xff
0x00046f1c <_D2gc3gcx3Gcx9allocPageMFhZi+100>:	eor	r3, r3, #1
0x00046f20 <_D2gc3gcx3Gcx9allocPageMFhZi+104>:	and	r3, r3, #255	; 0xff
0x00046f24 <_D2gc3gcx3Gcx9allocPageMFhZi+108>:	cmp	r3, #0
0x00046f28 <_D2gc3gcx3Gcx9allocPageMFhZi+112>:	bne	0x46f78 <_D2gc3gcx3Gcx9allocPageMFhZi+192>
0x00046f2c <_D2gc3gcx3Gcx9allocPageMFhZi+116>:	ldr	r3, [r11, #-40]	; 0x28
0x00046f30 <_D2gc3gcx3Gcx9allocPageMFhZi+120>:	ldr	r2, [r3, #84]	; 0x54
0x00046f34 <_D2gc3gcx3Gcx9allocPageMFhZi+124>:	ldr	r3, [r11, #-12]
0x00046f38 <_D2gc3gcx3Gcx9allocPageMFhZi+128>:	lsl	r3, r3, #2
0x00046f3c <_D2gc3gcx3Gcx9allocPageMFhZi+132>:	add	r3, r2, r3
0x00046f40 <_D2gc3gcx3Gcx9allocPageMFhZi+136>:	ldr	r3, [r3]
0x00046f44 <_D2gc3gcx3Gcx9allocPageMFhZi+140>:	str	r3, [r11, #-8]
0x00046f48 <_D2gc3gcx3Gcx9allocPageMFhZi+144>:	ldr	r0, [r11, #-8]
0x00046f4c <_D2gc3gcx3Gcx9allocPageMFhZi+148>:	mov	r1, #1
0x00046f50 <_D2gc3gcx3Gcx9allocPageMFhZi+152>:	bl	0x4898c <_D2gc3gcx4Pool10allocPagesMFkZk>
0x00046f54 <_D2gc3gcx3Gcx9allocPageMFhZi+156>:	mov	r3, r0
0x00046f58 <_D2gc3gcx3Gcx9allocPageMFhZi+160>:	str	r3, [r11, #-16]
0x00046f5c <_D2gc3gcx3Gcx9allocPageMFhZi+164>:	ldr	r3, [r11, #-16]
0x00046f60 <_D2gc3gcx3Gcx9allocPageMFhZi+168>:	cmn	r3, #1
0x00046f64 <_D2gc3gcx3Gcx9allocPageMFhZi+172>:	bne	0x46f80 <_D2gc3gcx3Gcx9allocPageMFhZi+200>
0x00046f68 <_D2gc3gcx3Gcx9allocPageMFhZi+176>:	ldr	r3, [r11, #-12]
0x00046f6c <_D2gc3gcx3Gcx9allocPageMFhZi+180>:	add	r3, r3, #1
0x00046f70 <_D2gc3gcx3Gcx9allocPageMFhZi+184>:	str	r3, [r11, #-12]
0x00046f74 <_D2gc3gcx3Gcx9allocPageMFhZi+188>:	b	0x46f00 <_D2gc3gcx3Gcx9allocPageMFhZi+72>
0x00046f78 <_D2gc3gcx3Gcx9allocPageMFhZi+192>:	mov	r3, #0
0x00046f7c <_D2gc3gcx3Gcx9allocPageMFhZi+196>:	b	0x4704c <_D2gc3gcx3Gcx9allocPageMFhZi+404>
0x00046f80 <_D2gc3gcx3Gcx9allocPageMFhZi+200>:	nop			; (mov r0, r0)
0x00046f84 <_D2gc3gcx3Gcx9allocPageMFhZi+204>:	ldr	r3, [r11, #-8]
0x00046f88 <_D2gc3gcx3Gcx9allocPageMFhZi+208>:	ldr	r2, [r3, #88]	; 0x58
0x00046f8c <_D2gc3gcx3Gcx9allocPageMFhZi+212>:	ldr	r3, [r11, #-16]
0x00046f90 <_D2gc3gcx3Gcx9allocPageMFhZi+216>:	add	r3, r2, r3
0x00046f94 <_D2gc3gcx3Gcx9allocPageMFhZi+220>:	ldrb	r2, [r11, #-41]	; 0x29
0x00046f98 <_D2gc3gcx3Gcx9allocPageMFhZi+224>:	strb	r2, [r3]
0x00046f9c <_D2gc3gcx3Gcx9allocPageMFhZi+228>:	ldrb	r3, [r11, #-41]	; 0x29
0x00046fa0 <_D2gc3gcx3Gcx9allocPageMFhZi+232>:	lsl	r2, r3, #2
0x00046fa4 <_D2gc3gcx3Gcx9allocPageMFhZi+236>:	ldr	r3, [pc, #172]	; 0x47058 <_D2gc3gcx3Gcx9allocPageMFhZi+416>
0x00046fa8 <_D2gc3gcx3Gcx9allocPageMFhZi+240>:	add	r3, r2, r3
0x00046fac <_D2gc3gcx3Gcx9allocPageMFhZi+244>:	ldr	r3, [r3]
0x00046fb0 <_D2gc3gcx3Gcx9allocPageMFhZi+248>:	str	r3, [r11, #-28]
0x00046fb4 <_D2gc3gcx3Gcx9allocPageMFhZi+252>:	ldr	r3, [r11, #-40]	; 0x28
0x00046fb8 <_D2gc3gcx3Gcx9allocPageMFhZi+256>:	add	r2, r3, #88	; 0x58
0x00046fbc <_D2gc3gcx3Gcx9allocPageMFhZi+260>:	ldrb	r3, [r11, #-41]	; 0x29
0x00046fc0 <_D2gc3gcx3Gcx9allocPageMFhZi+264>:	lsl	r3, r3, #2
0x00046fc4 <_D2gc3gcx3Gcx9allocPageMFhZi+268>:	add	r3, r2, r3
0x00046fc8 <_D2gc3gcx3Gcx9allocPageMFhZi+272>:	str	r3, [r11, #-32]
0x00046fcc <_D2gc3gcx3Gcx9allocPageMFhZi+276>:	ldr	r3, [r11, #-8]
0x00046fd0 <_D2gc3gcx3Gcx9allocPageMFhZi+280>:	ldr	r2, [r3]
0x00046fd4 <_D2gc3gcx3Gcx9allocPageMFhZi+284>:	ldr	r3, [r11, #-16]
0x00046fd8 <_D2gc3gcx3Gcx9allocPageMFhZi+288>:	lsl	r3, r3, #12
0x00046fdc <_D2gc3gcx3Gcx9allocPageMFhZi+292>:	add	r3, r2, r3
0x00046fe0 <_D2gc3gcx3Gcx9allocPageMFhZi+296>:	str	r3, [r11, #-20]
0x00046fe4 <_D2gc3gcx3Gcx9allocPageMFhZi+300>:	ldr	r3, [r11, #-20]
0x00046fe8 <_D2gc3gcx3Gcx9allocPageMFhZi+304>:	add	r3, r3, #4096	; 0x1000
0x00046fec <_D2gc3gcx3Gcx9allocPageMFhZi+308>:	str	r3, [r11, #-24]
0x00046ff0 <_D2gc3gcx3Gcx9allocPageMFhZi+312>:	ldr	r2, [r11, #-20]
0x00046ff4 <_D2gc3gcx3Gcx9allocPageMFhZi+316>:	ldr	r3, [r11, #-24]
0x00046ff8 <_D2gc3gcx3Gcx9allocPageMFhZi+320>:	cmp	r2, r3
0x00046ffc <_D2gc3gcx3Gcx9allocPageMFhZi+324>:	movcs	r3, #0
0x00047000 <_D2gc3gcx3Gcx9allocPageMFhZi+328>:	movcc	r3, #1
0x00047004 <_D2gc3gcx3Gcx9allocPageMFhZi+332>:	and	r3, r3, #255	; 0xff
0x00047008 <_D2gc3gcx3Gcx9allocPageMFhZi+336>:	eor	r3, r3, #1
0x0004700c <_D2gc3gcx3Gcx9allocPageMFhZi+340>:	and	r3, r3, #255	; 0xff
0x00047010 <_D2gc3gcx3Gcx9allocPageMFhZi+344>:	cmp	r3, #0
0x00047014 <_D2gc3gcx3Gcx9allocPageMFhZi+348>:	bne	0x47048 <_D2gc3gcx3Gcx9allocPageMFhZi+400>
0x00047018 <_D2gc3gcx3Gcx9allocPageMFhZi+352>:	ldr	r3, [r11, #-20]
0x0004701c <_D2gc3gcx3Gcx9allocPageMFhZi+356>:	ldr	r2, [r11, #-32]
0x00047020 <_D2gc3gcx3Gcx9allocPageMFhZi+360>:	ldr	r2, [r2]
0x00047024 <_D2gc3gcx3Gcx9allocPageMFhZi+364>:	str	r2, [r3]
0x00047028 <_D2gc3gcx3Gcx9allocPageMFhZi+368>:	ldr	r2, [r11, #-20]
0x0004702c <_D2gc3gcx3Gcx9allocPageMFhZi+372>:	ldr	r3, [r11, #-32]
0x00047030 <_D2gc3gcx3Gcx9allocPageMFhZi+376>:	str	r2, [r3]
0x00047034 <_D2gc3gcx3Gcx9allocPageMFhZi+380>:	ldr	r3, [r11, #-28]
0x00047038 <_D2gc3gcx3Gcx9allocPageMFhZi+384>:	ldr	r2, [r11, #-20]
0x0004703c <_D2gc3gcx3Gcx9allocPageMFhZi+388>:	add	r3, r2, r3
0x00047040 <_D2gc3gcx3Gcx9allocPageMFhZi+392>:	str	r3, [r11, #-20]
0x00047044 <_D2gc3gcx3Gcx9allocPageMFhZi+396>:	b	0x46ff0 <_D2gc3gcx3Gcx9allocPageMFhZi+312>
0x00047048 <_D2gc3gcx3Gcx9allocPageMFhZi+400>:	mov	r3, #1
0x0004704c <_D2gc3gcx3Gcx9allocPageMFhZi+404>:	mov	r0, r3
0x00047050 <_D2gc3gcx3Gcx9allocPageMFhZi+408>:	sub	sp, r11, #4
0x00047054 <_D2gc3gcx3Gcx9allocPageMFhZi+412>:	pop	{r11, pc}
0x00047058 <_D2gc3gcx3Gcx9allocPageMFhZi+416>:	andeq	r4, r5, r4, lsl #20

I hope this information can help to fix this bug at some time, I don't understand the asm well enough to figure the problem out by myself.

Comments (22)

  1. Iain Buclaw
    • changed status to open

    Can you backtrace with argument name/values?

    I think this is what I was referring to in the NG thread. What you should see is a parameter with a corrupt/large value.

    Also, shot in the dark, but what are your configure flags? Have you tried building with flags that closely match your ARM board spec?

    ie:

    --with-arch=armv7-a --with-float=softfp --with-fpu=vfpv3-d16 --with-mode=thumb
    

    Valid arch flags: armv[23456] | armv2a | armv3m | armv4t | armv5t | armv5te | armv6j | armv6k | armv6z | armv6zk | armv6-m | armv7 | armv7-a | armv7-r | armv7-m | iwmmxt | ep9312

    Valid float flags: soft | hard | softfp

    Valid fpu flags: fpa | fpe2 | fpe3 | maverick | vfp | vfp3 | vfpv3 | vfpv3-d16 | neon

    Valid mode flags: arm | thumb

    If in doubt, probably just use the same flags as what your system gcc was built with.

    Regards

  2. Johannes Pfau

    Is "bt full" with gdb enough? Some values are optimized out, but as the problem doesn't show with the unoptimized version:

    Full Backtrace, optimized version

    0  _D2gc3gcx3Gcx9allocPageMFhZi (this=<value optimized out>, 
        bin=<value optimized out>)
        at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:2179
            pn = <value optimized out>
            pool = <value optimized out>
            b = 0x66094
            size = 0
            ptop = 0x40235000 ""
            p = 0x40234000 ""
            n = <value optimized out>
    1  0x0004444c in _D2gc3gcx2GC12mallocNoSyncMFkkPkZPv (this=..., size=88, 
        bits=1, alloc_size=<value optimized out>)
        at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:459
            collected = false
            state = 2
            bin = 3 '\003'
            p = <value optimized out>
    2  0x000451d4 in _D2gc3gcx2GC6mallocMFkkPkZPv (this=..., size=88, bits=1, 
        alloc_size=0x0) at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:418
            __sync7 = @0x64c0c
    3  0x00041d58 in gc_malloc (sz=269656, ba=0)
        at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:188
    No locals.
    4  0x0003c1f8 in _d_newclass (ci=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/lifetime.d:125
            p = <value optimized out>
    5  0x00040c4c in thread_attachThis ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1813
            thisContext = 0xbee79628
            thisThread = <value optimized out>
    6  0x00040da0 in thread_init ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1792
            sigusr2 = {sa_handler = 0x3fde4 <thread_resumeHandler>, 
              sa_sigaction = 0x3fde4 <thread_resumeHandler>, sa_mask = {__val = {
                  2147483647, 4294967294, 4294967295 <repeats 30 times>}}, 
              sa_flags = 0, sa_restorer = 0}
            sigusr1 = {sa_handler = 0x40b94 <thread_suspendHandler>, 
              sa_sigaction = 0x40b94 <thread_suspendHandler>, sa_mask = {__val = {
                  2147483647, 4294967294, 4294967295 <repeats 30 times>}}, 
              sa_flags = 268435456, sa_restorer = 0}
    7  0x000423ac in gc_init () at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:115
            p = 0x66018
    8  0x00045f50 in runAll ()
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:498
    No locals.
    9  0x00045cec in tryExec (dg=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:438
    No locals.
    10 0x00045e84 in main (argc=<value optimized out>, argv=0xbee79944)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:515
            args = {length = 1, ptr = 0x66008}
            result = 0
            trapExceptions = true
    

    Interesting stuff, you are right, in 3 size and ba are wrong, but they are correct in 2.

    Partial backtrace, optimized version, with breakpoints

    Breakpoint 1, gc_malloc (sz=88, ba=1)
        at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:188
    188	../../../gcc-4.4.5-build/libphobos/gc/gc.d: No such file or directory.
    	in ../../../gcc-4.4.5-build/libphobos/gc/gc.d
    Current language:  auto
    The current source language is "auto; currently minimal".
    (gdb) cont
    Continuing.
    
    Breakpoint 2, _D2gc3gcx2GC6mallocMFkkPkZPv (this=..., size=88, bits=1, 
        alloc_size=0x0) at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:406
    406	../../../gcc-4.4.5-build/libphobos/gc/gcx.d: No such file or directory.
    	in ../../../gcc-4.4.5-build/libphobos/gc/gcx.d
    (gdb) bt
    0  _D2gc3gcx2GC6mallocMFkkPkZPv (this=..., size=88, bits=1, alloc_size=0x0)
        at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:406
    1  0x00041d58 in gc_malloc (sz=269656, ba=1)
        at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:188
    2  0x0003c1f8 in _d_newclass (ci=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/lifetime.d:125
    3  0x00040c4c in thread_attachThis ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1813
    4  0x00040da0 in thread_init ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1792
    5  0x000423ac in gc_init () at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:115
    6  0x00045f50 in runAll ()
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:498
    7  0x00045cec in tryExec (dg=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:438
    8  0x00045e84 in main (argc=<value optimized out>, argv=0xbe829944)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:515
    

    The value is actually correct in the gc_malloc function and it's passed on correctly, but it's corrupted in the backtrace. Strange. Doesn't happen for the unoptimized version. Also in the optimized version printf output is corrupted, maybe this all somehow belongs together.

    Full backtrace with -O0

    0  _D2gc3gcx3Gcx9allocPageMFhZi (this=..., bin=3 '\003')
        at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:2179
            pn = 0
            pool = 0x6a0f0
            b = 0x6a094
            size = 128
            ptop = 0x40235000 ""
            p = 0x40234000 ""
            n = 0
    1  0x00043414 in _D2gc3gcx2GC12mallocNoSyncMFkkPkZPv (this=..., size=88, 
        bits=1, alloc_size=0x0) at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:459
            collected = false
            state = 2
            bin = 3 '\003'
            p = 0x0
    2  0x00043298 in _D2gc3gcx2GC6mallocMFkkPkZPv (this=..., size=88, bits=1, 
        alloc_size=0x0) at ../../../gcc-4.4.5-build/libphobos/gc/gcx.d:418
            __sync7 = @0x68c00
    3  0x00042014 in gc_malloc (sz=88, ba=1)
        at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:188
    No locals.
    4  0x0003c1f8 in _d_newclass (ci=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/lifetime.d:125
            p = <value optimized out>
    5  0x00040c4c in thread_attachThis ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1813
            thisContext = 0xbee3c618
            thisThread = <value optimized out>
    6  0x00040da0 in thread_init ()
        at ../../../gcc-4.4.5-build/libphobos/core/thread.d:1792
            sigusr2 = {sa_handler = 0x3fde4 <thread_resumeHandler>, 
              sa_sigaction = 0x3fde4 <thread_resumeHandler>, sa_mask = {__val = {
                  2147483647, 4294967294, 4294967295 <repeats 30 times>}}, 
              sa_flags = 0, sa_restorer = 0}
            sigusr1 = {sa_handler = 0x40b94 <thread_suspendHandler>, 
              sa_sigaction = 0x40b94 <thread_suspendHandler>, sa_mask = {__val = {
                  2147483647, 4294967294, 4294967295 <repeats 30 times>}}, 
              sa_flags = 268435456, sa_restorer = 0}
    7  0x00041c58 in gc_init () at ../../../gcc-4.4.5-build/libphobos/gc/gc.d:115
            ci = @0x68c50
            p = 0x6a018
    8  0x0004991c in runAll ()
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:498
    No locals.
    9  0x000496b8 in tryExec (dg=...)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:438
    No locals.
    10 0x00049850 in main (argc=<value optimized out>, argv=0xbee3c944)
        at ../../../gcc-4.4.5-build/libphobos/rt/dmain2.d:515
            args = {length = 1, ptr = 0x6a008}
            result = 0
            trapExceptions = true
    

    Configure flags, native GCC

    Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-6' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs
    --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib
    --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls
    --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-sjlj-exceptions --enable-checking=release --build=arm-linux-gnueabi
    --host=arm-linux-gnueabi --target=arm-linux-gnueabi
    

    Configure flags, cross GDC

    Configured with: ../gcc-4.4.5-build/configure --prefix=/usr --target=arm-linux-gnueabi --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --enable-languages=d
    --enable-threads --disable-nls --enable-shared --enable-multiarch --disable-multilib --with-as=/usr/bin/arm-linux-gnueabi-as --with-ld=/usr/bin/arm-linux-gnueabi-ld
    --with-sysroot=/usr/i686-pc-linux-gnu/arm-linux-gnueabi
    

    The board uses a Feroceon 88FR131 rev 1, google says that's armv5te, thumb mode supported, no hardware floating point, so I should use

    --with-arch=armv5te --with-float=softfp --with-mode=thumb
    

    ? I will try that later today.

  3. Iain Buclaw

    Hmm, maybe it's all insignificant, but I can't recall why I knew that was there now. Possibly at the time (I was kindly given an ssh account to login to for testing) I may have seen that the call for: gc_malloc (sz=269656, ba=0) somehow messed things up later on. I honestly can't remember am afraid. :)

    It's certainly worth a try using using that. As it may have an affect on the ASM generated by GCC.

    Though I can see that at the very least, when I get my C̶h̶r̶i̶s̶t̶m̶a̶s̶ ̶p̶r̶e̶s̶e̶n̶t̶ Sheeva plug, will have to build phobos with -O0 and then debug/slim-down a standalone version of gcx.d

  4. Johannes Pfau

    Ok, I tried to build with those flags, but I hit this error.

    /var/abs/local/cross-arm-linux-gnueabi/cross-arm-none-linux-gnueabi-gdc2-hg/src/gcc-build/./gcc/gdc -B/var/abs/local/cross-arm-linux-gnueabi/cross-arm-none-linux-gnueabi-gdc2-hg/src/gcc-build/./gcc/ -B/usr/arm-linux-gnueabi/bin/ -B/usr/arm-linux-gnueabi/lib/ -isystem /usr/arm-linux-gnueabi/include -isystem /usr/arm-linux-gnueabi/sys-include -o std/math.o -Wall -g -frelease -O2 -fversion=GC_Use_Alloc_MMap -fversion=GC_Use_Stack_GLibC -fversion=GC_Use_Data_Fixed -nostdinc -pipe -fdeprecated -I ../../../gcc-4.4.5-build/libphobos -I ./arm-linux-gnueabi  -femit-templates -c ../../../gcc-4.4.5-build/libphobos/std/math.d
    {standard input}: Assembler messages:
    {standard input}:383: Error: selected processor does not support `mrc p10,7,r0,cr1,cr0,0'
    {standard input}:470: Error: selected processor does not support `mcr p10,7,r0,cr1,cr0,0'
    

    Interesting, I didn't know gcc can detect this. Seems like software floating point needs some special handling there. I just commented out the asm blocks and the compiler built fine. However, the GC problem still remains. Well I'll just compile without optimization until you get your sheevaplug and this can hopefully be fixed.

  5. Johannes Pfau

    Update:

    With newest hg dmd and the patches from issue 193 and gcc 4.5.2 the infinite loop is gone and instead a segmentation fault happens. The location where the segfault occurs according to gdb is just as weird as the gc infinite loop bug. Again this only occurs with -O >= 1, everything's fine with -O0.

    Further investigation showed that the problem is -fsection-anchors. With -fno-section-anchors even -O3 works fine. Interestingly -fsection-anchors is enabled by default on ARM, but not on x86. Probably this is not even an ARM specific bug. I'll recompile phobos with -fsection-anchors on x86 to see what happens there.

    (speculation:) I don't know much about compilers, machine code, etc. but reading gccs description of -fsection-anchors it seems quite possible that this optimization has caused all the trouble. The gc problem was caused by a variable being read as 0 although the static data and everything was correct. If this data was read from a wrong address that could explain the wrong value and it also explains the segfaults I'm seeing with a recent gdc.

  6. Johannes Pfau

    x86 doesn't support -fsection-anchors, even if explicitly enabled. So it could still be a problem on all architectures which support -fsection-anchors but I've got no hardware to test that.

    Iain, would it be possible to "blacklist" -fsection-anchors? Or to add "-fno-section-anchors" to the default arguments for gdc so that it would just work on ARM?

  7. Andrew Wiley

    From my understanding of ARM assembly, I would guess that they want -fsection-anchors because ARM cannot use full size pointers as immediate values in instructions, which makes statically computed addresses hard to use. That said, I'm not sure how much of a performance hit -fno-section-anchors would cause.

  8. Iain Buclaw

    Further investigation showed that the problem is -fsection-anchors. With -fno-section-anchors even -O3 works fine. Interestingly -fsection-anchors is enabled by default on ARM, but not on x86. Probably this is not even an ARM specific bug. I'll recompile phobos with -fsection-anchors on x86 to see what happens there.

    Right, turning off flag_section_anchors is the workaround. The next step would be to bastardise the gcx module into a simple program to showcase an example of what gets affected by -fsection-anchors (assuming it's just the one problem that propagates the issue).

  9. Johannes Pfau

    I still wasn't able to reduce gcx.d, but I stepped through the asm code and found the following: The exact error changes a lot depending on the compiler flags and gdc version. In this case, findBin returned 0 instead of 3, which caused the memset in mallocNoSync to fail: memset(p + size, 0, binsize[bin] - size) evaluated to binsize[0] - 88 = 16-88 so it passed a negative size to memset.

    This is the correct address & values for binTable in the findBin function:

    (gdb) info address _D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g
    Symbol "_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g" is at 0x59110 in a file compiled without debugging.
    
    (gdb) x/88db  0x59110
    
    0x59110 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g>:	0	0	0	0	0	0	0	0
    0x59118 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+8>:	0	0	0	0	0	0	0	0
    0x59120 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+16>:	0	1	1	1	1	1	1	1
    0x59128 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+24>:	1	1	1	1	1	1	1	1
    0x59130 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+32>:	1	2	2	2	2	2	2	2
    0x59138 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+40>:	2	2	2	2	2	2	2	2
    0x59140 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+48>:	2	2	2	2	2	2	2	2
    0x59148 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+56>:	2	2	2	2	2	2	2	2
    0x59150 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+64>:	2	3	3	3	3	3	3	3
    0x59158 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+72>:	3	3	3	3	3	3	3	3
    ---Type <return> to continue, or q <return> to quit---
    0x59160 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+80>:	3	3	3	3	3	3	3	3
    

    And this is the findBin function:

    (gdb) disas _D2gc3gcx3Gcx7findBinFkZh
    Dump of assembler code for function _D2gc3gcx3Gcx7findBinFkZh:
       0x0001b904 <+0>:	cmp	r0, #2048	; 0x800; size <= 2048
       //if size <= 2048 load the word at <_D2gc3gcx3Gcx7findBinFkZh+20> into r3
       0x0001b908 <+4>:	ldrls	r3, [pc, #8]	; 0x1b918 <_D2gc3gcx3Gcx7findBinFkZh+20>
       //if not, move 8(B_PAGE) into r0(return value register)
       0x0001b90c <+8>:	movhi	r0, #8
       //Load value at address r3+r0 into r0; r0 = binTable[size]
       0x0001b910 <+12>:	ldrbls r0, [r3, r0]
       //return from function
       0x0001b914 <+16>:	bx	lr
       //not an instruction, this is the base address of binTable
       0x0001b918 <+20>:	muleq	r5, r0, r0
    End of assembler dump.
    

    Let's have a look at the base address for binTable:

    (gdb) x/xw 0x0001b918
    0x1b918 <_D2gc3gcx3Gcx7findBinFkZh+20>:	0x00059090
    

    The address is 128 bytes off! And this is where the 0 returned by findBin comes from:

    (gdb) x/88db  0x00059090
    0x59090:	0	0	0	0	0	0	0	0
    0x59098:	0	0	0	0	0	0	0	0
    0x590a0 <_D2gc3gcx10notbinsizeyG12k>:	-16	-1	-1	-1	-32	-1	-1	-1
    0x590a8 <_D2gc3gcx10notbinsizeyG12k+8>:	-64	-1	-1	-1	-128	-1	-1	-1
    0x590b0 <_D2gc3gcx10notbinsizeyG12k+16>:	0	-1	-1	-1	0-2	-1	-1
    0x590b8 <_D2gc3gcx10notbinsizeyG12k+24>:	0	-4	-1	-1	0-8	-1	-1
    0x590c0 <_D2gc3gcx10notbinsizeyG12k+32>:	0	-16	-1	-1	00	0	0
    0x590c8 <_D2gc3gcx10notbinsizeyG12k+40>:	0	0	0	0	00	0	0
    0x590d0:	0	0	0	0	0	0	0	0
    0x590d8:	0	0	0	0	0	0	0	0
    0x590e0:	0	0	0	0	0	0	0	0
    

    Larger view of the memory at 0x00059090

    (gdb) x/216db  0x00059090
    0x59090:	0	0	0	0	0	0	0	0
    0x59098:	0	0	0	0	0	0	0	0
    0x590a0 <_D2gc3gcx10notbinsizeyG12k>:	-16	-1	-1	-1	-32	-1	-1	-1
    0x590a8 <_D2gc3gcx10notbinsizeyG12k+8>:	-64	-1	-1	-1	-128	-1	-1	-1
    0x590b0 <_D2gc3gcx10notbinsizeyG12k+16>:	0	-1	-1	-1	0 -2	-1	-1
    0x590b8 <_D2gc3gcx10notbinsizeyG12k+24>:	0	-4	-1	-1	0 -8	-1	-1
    0x590c0 <_D2gc3gcx10notbinsizeyG12k+32>:	0	-16	-1	-1	0 0	0	0
    0x590c8 <_D2gc3gcx10notbinsizeyG12k+40>:	0	0	0	0	0 0	0	0
    0x590d0:	0	0	0	0	0	0	0	0
    0x590d8:	0	0	0	0	0	0	0	0
    0x590e0:	0	0	0	0	0	0	0	0
    0x590e8:	0	0	0	0	0	0	0	0
    0x590f0:	0	0	0	0	0	0	0	0
    0x590f8:	0	0	0	0	0	0	0	0
    0x59100:	0	0	0	0	0	0	0	0
    ---Type <return> to continue, or q <return> to quit---
    0x59108:	0	0	0	0	0	0	0	0
    0x59110 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g>:	0	0	0	0 0	0	0	0
    0x59118 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+8>:	0	0	0	0 0	0	0	0
    0x59120 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+16>:	0	1	1	1 1	1	1	1
    0x59128 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+24>:	1	1	1	1 1	1	1	1
    0x59130 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+32>:	1	2	2	2 2	2	2	2
    0x59138 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+40>:	2	2	2	2 2	2	2	2
    0x59140 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+48>:	2	2	2	2 2	2	2	2
    0x59148 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+56>:	2	2	2	2 2	2	2	2
    0x59150 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+64>:	2	3	3	3 3	3	3	3
    0x59158 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+72>:	3	3	3	3 3	3	3	3
    ---Type <return> to continue, or q <return> to quit---
    0x59160 <_D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g+80>:	3	3	3	3 3	3	3	3
    

    Let's also have a look how relocation affects this whole thing:

    objdump -x GDC/gdc/dev/gcc-4.6.1/objdir/armv7l-unknown-linux-gnueabi/libphobos/gc/gcx.o
    SYMBOL TABLE:
    000000e0 g     O .rodata	00000801 _D2gc3gcx3Gcx7findBinFkZh8binTablexG2049g
    
    RELOCATION RECORDS FOR [.text]:
    00000c08 R_ARM_ABS32       .rodata
    

    and in gcx.o:

    Dump of assembler code for function _D2gc3gcx3Gcx7findBinFkZh:
       0x00000bf4 <+0>:	cmp	r0, #2048	; 0x800
       0x00000bf8 <+4>:	ldrls	r3, [pc, #8]	; 0xc08 <_D2gc3gcx3Gcx7findBinFkZh+20>
       0x00000bfc <+8>:	movhi	r0, #8
       0x00000c00 <+12>:	ldrbls	r0, [r3, r0]
       0x00000c04 <+16>:	bx	lr
       0x00000c08 <+20>:	andeq	r0, r0, r0, rrx
    End of assembler dump.
    (gdb) x/x 0x00000c08
    0xc08 <_D2gc3gcx3Gcx7findBinFkZh+20>:	0x00000060
    

    binTable is at offset 0x000000e0 --> 224 The address in the literal pool is 0x00000060 --> 96 So relocation doesn't change anything, the address is already off by 128 before relocation.

    Iain do you have a clue what could cause the wrong address? If not, I'll try to write a script for dustmite and let dustmite reduce that thing.

  10. Johannes Pfau

    OK, I think I tracked this thing down, but I'd be very grateful if someone else could write the gdc patch ;-)

    This is the problematic declaration in gcx.d:

    immutable uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
    

    What's special about this declaration? It's incomplete: B_MAX is 12, but the array literal only has 9 values. AFAICS gdc currently only passes a constructor with the 9 values to the backend and assumes that gcc adds the additional zeros. Long story short: it doesn't (correctly) and the zero padding should be added in the frontend.

    But what exactly happens in the backend? This code is from varasm.c function "output_constructor_regular_field":

        fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
    		* ((tree_low_cst (local->index, 0)
    		    - tree_low_cst (local->min_index, 0))));
    

    it calculates field positions for array members. tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) is the size of the elements, ((tree_low_cst (local->index, 0) is the index in the array. This works fine for the first 9 entries in our example. But, for some reason, the backend(or maybe the frontend, I'm not sure where the padding is added) added the 12 bytes final padding as one tree/element. This means, tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1) is 12 in this case and the calculation calculates 12*9=108 instead of 4*9=36. GCC detects that there's a gap between the last and the current offset and fills it with 72 zeros.

    AFAICS this should affect all architectures. What makes it catastrophic on ARM are section anchors: Section anchors refer to the arrays relative to the .rodata base address. But the section anchor code uses a different code path to calculate the offset, and ignores the zero padding added earlier. As a result, data is loaded from wrong offsets. (Although, technically, the offsets are correct, the .rodata is actually wrong)

    What needs to be done in the frontend then is this: For incomplete arrays, add the zero padding manually, so that the constructor is complete. The padding must be added as single elements of the array element size. It has to pass the same tree to the backend as [ 16,32,64,128,256,512,1024,2048,4096, 0, 0, 0 ] would.

  11. Johannes Pfau

    Yep, I can confirm this patch is working. The .rodata segment is fine now and the crash is gone :-)

    However, there still is a problem with section anchors, we may have missed a case somewhere:

    ...
    _moduleinfo_array: 71:0x8ea0c
    _moduleinfo_array: 72:0x8e79c
    _moduleinfo_array: 73:0x4           <---------------------------------
    _moduleinfo_array: 74:0x8e530
    

    That moduleinfo belongs to core.runtime. If core-runtime is compiled with -fno-section-anchors, a hello world works. It's caused by incorrect relocations again. I think the issue is caused by this symbol: _D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7ClassZ

    The length of that entry in the .data section is set to 76, but for some reason 108 bytes are output for this symbol.

    _D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ:
    	.word	_D14TypeInfo_Class6__vtblZ
    	.word	0
    	.word	4120
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__initZ
    	.word	49
    	.word	.LC1
    	.word	8
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__vtblZ
    	.word	1
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+76
    	.word	_D6Object7__ClassZ
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__dtorMFZv
    	.word	0
    	.word	60
    	.word	0
    	.word	0
    	.word	0
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__ctorMFZC4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo
    	.word	0
    	.word	_D6object9Throwable9TraceInfo11__InterfaceZ
    	.word	4
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+92
    	.word	4116
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+76
    	.word	___t.0.1431
    	.word	___t.1.1432
    	.word	___t.2.1433
    

    It doesn't happen for other ClassZ though. Any idea what could cause this?

  12. Johannes Pfau

    OK, the ClassZ size is bigger as the class implements an interface. This code

    interface A {}
    class B : A {}
    

    compiled with gdc -c -S test.d produces this

    .LC1:
    	.ascii	"test2.B\000"
    	.data
    	.align	2
    	.type	_D5test21B7__ClassZ, %object
    	.size	_D5test21B7__ClassZ, 76
    _D5test21B7__ClassZ:
    	.word	_D14TypeInfo_Class6__vtblZ
    	.word	0
    	.word	12
    	.word	_D5test21B6__initZ
    	.word	7
    	.word	.LC1
    	.word	6
    	.word	_D5test21B6__vtblZ
    	.word	1
    	.word	_D5test21B7__ClassZ+76
    	.word	_D6Object7__ClassZ
    	.word	0
    	.word	0
    	.word	54
    	.word	0
    	.word	0
    	.word	0
    	.word	0
    	.word	0
    	.word	_D5test21A11__InterfaceZ
    	.word	1
    	.word	_D5test21B7__ClassZ+92
    	.word	8
    	.word	_D5test21B7__ClassZ+76
    

    I'm concerned about this line:

    .size	_D5test21B7__ClassZ, 76
    

    as size is not 76, even in this simple example it's 96. I'm not sure if the wrong size at this position is a problem, but it seems likely that it causes the issues with anchors: Simply making DefaultTraceInfo a 'normal' class (not implementing an interface) makes the problem go away.

  13. Johannes Pfau

    Sorry I don't understand your last answer 100%. sizeof B and sizeof B.init.type are meant to be the same, aren't they? So we'd have to research why those are different / how to fix that?

  14. Anonymous

    OK, it's been 6 months since I last looked at this, so another try :-)

    I diffed the asm output of the core.runtime.d file with sections anchors enabled and with section anchors disabled. I then ported the changes from the no-anchor one to the anchor one, till the anchor one worked. I then removed the changes again, one by one, to find the minimal difference causing the issue.

    Turns out, this little asm sequence in function _D4core7runtime9modinitFZv causes the issue:

    -	movw	r3, #:lower16:.LANCHOR1
    -	movt	r3, #:upper16:.LANCHOR1
    +	movw	r3, #:lower16:__mod_ref.1703
    +	movt	r3, #:upper16:__mod_ref.1703
     	ldr	r1, [r2, #0]
    -	str	r1, [r3, #76]!
     	str	r3, [r2, #0]
    +	str	r1, [r3, #0]
    

    This code is correct, but LANCHOR1+76 != __mod_ref.1703 .

    LANCHOR1 is defined here:

    .LANCHOR1 = . + 0
    	.type	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ, %object
    	.size	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ, 76
    _D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ:
    	.word	_D14TypeInfo_Class6__vtblZ
    	.word	0
    	.word	4120
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__initZ
    	.word	49
    	.word	.LC1
    	.word	8
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__vtblZ
    	.word	1
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+76
    	.word	_D6Object7__ClassZ
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__dtorMFZv
    	.word	0
    	.word	60
    	.word	0
    	.word	0
    	.word	0
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo6__ctorMFZC4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo
    	.word	0
    	.word	_D6object9Throwable9TraceInfo11__InterfaceZ
    	.word	4
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+92
    	.word	4116
    	.word	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ+76
    	.word	___t.0.1647
    	.word	___t.1.1648
    	.word	___t.2.1649
    	.type	__mod_ref.1703, %object
    	.size	__mod_ref.1703, 8
    __mod_ref.1703:
    

    So the +76 in the anchor code is caused by this line:

    .size	_D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7__ClassZ, 76
    

    this is wrong, size of _D4core7runtime19defaultTraceHandlerFPvZC6object9Throwable9TraceInfo16DefaultTraceInfo7ClassZ isn't 76 it's 108.

    However, the size classinfo is fixed to CLASSINFO_SIZE and must be 76. Those additional 32 bytes is the interfaces[] array (see toobj.c).

    The dmd source (toobj.c, ClassDeclaration::toObjFile(int multiobj)) says

        // Put out vtblInterfaces->data[]. Must immediately follow csym, because
        // of the fixup (*)
    and
        // Put out the vtblInterfaces->data[].vtbl[]
        // This must be mirrored with ClassDeclaration::baseVtblOffset()
    

    so it seems this is correct and can't be changed in an easy way. We have to make sure GDC doesn't output 76 as the symbols size, but the correct complete size including the interface table. I guess the size is output by the call to toSymbol(); in toobj.c: ClassDeclaration::toObjFile which I guess calls ClassDeclaration::toSymbol() in the end?

  15. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.