aarch64 start code does not set '__elfinfo'

[email protected] Wed, 22 Aug 2018 18:13:22 +0200 (CEST)
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
Hi,

trying to run a program statically linked to the dietlibc on an aarch64
board (Raspb. Pi 3 b+) I just got a segfault very early, in the function
'__get_elf_aux_value(unsigned int tag)'.

After a bit of gdb I found the problem was that the variable '__elfinfo'
was not initialized.

On the 'arm' platform '__elfinfo' is initialized in the asm function _start
in 'arm/start.S':

FUNC_START	_start
...
#ifdef WANT_ELFINFO
	mov	r6, a3			@ work on a copy of a3 so that common
					@ 'main(argc, argv, envp)' function
					@ stays valid
1:	ldr	r5, [r6], #4		@ load *envp and increment it
	cmp	r5, #0			@ read value==0?
	bne	1b
	str	r6, [ip, #4]		@ __elfinfo = envp
#endif
...

The corresponding asm code is missing for the aarch64 platform.

Here is the fixed asm for aarch64:

aarch64/start.S:

...
FUNC_START	_start
	mov	x29, #0			/* clear the frame pointer */
	mov	x30, #0			/* clear the link register */
	ldr	x0, [sp]		/* argc */
	add	x1, sp, #8		/* argv */
#ifdef __DYN_LIB
	adrp	x16, :got:environ
	ldr	x16, [x16, #:got_lo12:environ]
#else
	ldr	x16, =environ
#endif
	lsl	x9, x0, #3		/* argc * sizeof(void *) */
	add	x2, x1, x9		/* &argv[argc] */
	add	x2, x2, #8		/* envp */
	str	x2, [x16]		/* environ = envp */
#ifdef WANT_ELFINFO
	mov	x9, x2			/* work on a copy of x2 so that common */
					/* 'main(argc, argv, envp)' function   */
					/* stays valid                         */
1:	ldr	x10, [x9], #8		/* load *envp and increment it         */
	cbnz	x10, 1b			/* read value==0?                      */
	str	x9, [x16, #8]		/* __elfinfo = envp                    */
#endif
#ifdef WANT_DYNAMIC
	bl	_dyn_start
#else
	bl	CALL_IN_STARTCODE
#endif
...

The added asm is the block:

#ifdef WANT_ELFINFO
	mov	x9, x2			/* work on a copy of x2 so that common */
					/* 'main(argc, argv, envp)' function   */
					/* stays valid                         */
1:	ldr	x10, [x9], #8		/* load *envp and increment it         */
	cbnz	x10, 1b			/* read value==0?                      */
	str	x9, [x16, #8]		/* __elfinfo = envp                    */
#endif

very similar to that for arm.

This fix solves my segfault and the program runs OK.


giorgio