Page 1 of 1

What is my linker doing?? (x86_64)

Posted: Tue Jun 30, 2015 6:47 am
by mariuszp
I thought I'd ask this on those forums, as everyone here has a very detailed grasp of this low-level stuff.

I was writing a compiler for a custom high-level object-oriented language, which produces GNU assembler code, then after assembling, links it with a runtime library written in C, using 'gcc'.

It's all going well, but there is literally one function that would never link. HelloWorld.main() calls System.exit(), which then calls Posix.exit(), and Posix.exit() is written in C. Here's the assembly code for the relevant signature of System.exit():

Code: Select all

.globl _Elec_Static_4elec2rt6System_4exit_3int
_Elec_Static_4elec2rt6System_4exit_3int:
	pushq	%rbp
	movq	%rsp,	%rbp
	subq	$48,	%rsp
	xor	%rax,	%rax
	movq	%rax,	-48(%rbp)
	movq	%rax,	-40(%rbp)
	movq	%rax,	-32(%rbp)
	movq	%rbx,	-8(%rbp)
	movq	%r15,	-16(%rbp)
	movq	%r14,	-24(%rbp)
	movq	%r13,	-32(%rbp)
	movq	%r12,	-40(%rbp)
	movq	%rdi,	-48(%rbp)
	movq	-48(%rbp),	%rax
	pushq	%rax

	popq	%rdi
	call	_Elec_Static_4elec2rt5Posix_4exit_3int@PLT
	addq	$0,	%rsp
	xor	%rax,	%rax
S_6:
	movq	%rbp,	%rdi
	call	S_7
	movq	-16(%rbp),	%r15
	movq	-24(%rbp),	%r14
	movq	-32(%rbp),	%r13
	movq	-40(%rbp),	%r12
	movq	-8(%rbp),	%rbx
	addq	$48,	%rsp
	popq	%rbp
	ret
S_7:
	// cleanup function
	ret
S_8:
.size _Elec_Static_4elec2rt6System_4exit_3int, .-_Elec_Static_4elec2rt6System_4exit_3int
This code is in a library called "libelecstd.so" (hence the "@PLT"). Posix.exit() is written in C:

Code: Select all

_ELEC_ABI void _Elec_Static_4elec2rt5Posix_4exit_3int(_Elec_int status)
{
	exit((int)status);
};
Which, in assembly generated by GCC, is:

Code: Select all

	.globl	_Elec_Static_4elec2rt5Posix_4exit_3int
	.type	_Elec_Static_4elec2rt5Posix_4exit_3int, @function
_Elec_Static_4elec2rt5Posix_4exit_3int:
.LFB5:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movq	%rdi, -8(%rbp)
	movq	-8(%rbp), %rax
	movl	%eax, %edi
	call	exit@PLT
	.cfi_endproc
.LFE5:
	.size	_Elec_Static_4elec2rt5Posix_4exit_3int, .-_Elec_Static_4elec2rt5Posix_4exit_3int
It all looks good (I understand there is no prologue because exit() never returns), but the program simply crashes. The symbol _Elec_Static_4elec2rt6Posix_4exit_3int in the "callq" instruction resolves the "_Elec_TypeDef_4elec2rt9Exception+48" for some reason, and then once flow jumps to that symbol, the next instruction is a call to some random address without a symbol, and when flow jumps to there, that area is filled with zeroes (which disassembly to some "add" instruction repeatedly).

Does anyone see any reason why this might be happening??

Re: What is my linker doing?? (x86_64)

Posted: Wed Jul 01, 2015 12:55 pm
by jnc100
As you are calling via the PLT I assume you are writing position-independent code. Do you have a dynamic linker which correctly populates the GOT table addresses?

Regards,
John.

Re: What is my linker doing?? (x86_64)

Posted: Wed Jul 01, 2015 12:57 pm
by mariuszp
jnc100 wrote:As you are calling via the PLT I assume you are writing position-independent code. Do you have a dynamic linker which correctly populates the GOT table addresses?

Regards,
John.
Yes, it is invoked via GCC. My compiler (elecom) does a fork-exec to run GCC to do the linking (which of course calls ld internally). It worked for every other function, I don't know why this ONE function is an exception.

EDIT: This is by the way ran on Linux. The dynamic linker must obviously work. I could also try it on my OS later to see what happens..