summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/amd64/rtld_start.S
blob: 2481f09417dc6d2a1c95c8c199afd294c67017e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*-
 * Copyright 1996-1998 John D. Polstra.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD$
 */

	.text
	.align	4
	.globl	.rtld_start
	.type	.rtld_start,@function
.rtld_start:
	xorq	%rbp,%rbp		# Clear frame pointer for good form
	subq	$24,%rsp		# A place to store exit procedure addr
	movq	%rdi,%r12
	movq	%rsp,%rsi		# save address of exit proc
	movq	%rsp,%rdx		# construct address of obj_main
	addq	$8,%rdx
	call	_rtld@PLT		# Call rtld(sp); returns entry point
	popq	%rsi			# Get exit procedure address
	movq	%r12,%rdi		# *ap
/*
 * At this point, %rax contains the entry point of the main program, and
 * %rdx contains a pointer to a termination function that should be
 * registered with atexit().  (crt1.o registers it.)
 */
.globl .rtld_goto_main
.rtld_goto_main:	# This symbol exists just to make debugging easier.
	jmp	*%rax			# Enter main program


/*
 * Binder entry point.  Control is transferred to here by code in the PLT.
 * On entry, there are two arguments on the stack.  In ascending address
 * order, they are (1) "obj", a pointer to the calling object's Obj_Entry,
 * and (2) "reloff", the byte offset of the appropriate relocation entry
 * in the PLT relocation table.
 *
 * We are careful to preserve all registers, even the caller-save
 * registers.  That is because this code may be invoked by low-level
 * assembly-language code that is not ABI-compliant.
 *
 * Stack map:
 * reloff       0x60
 * obj          0x58
 * spare	0x50
 * rflags       0x48
 * rax          0x40
 * rdx          0x38
 * rcx          0x30
 * rsi          0x28
 * rdi          0x20
 * r8           0x18
 * r9           0x10
 * r10          0x8
 * r11          0x0
 */
	.align	4
	.globl	_rtld_bind_start
	.type	_rtld_bind_start,@function
_rtld_bind_start:
	.cfi_startproc
	.cfi_adjust_cfa_offset	16
	subq	$8,%rsp
	.cfi_adjust_cfa_offset	8
	pushfq				# Save rflags
	.cfi_adjust_cfa_offset	8
	pushq	%rax			# Save %rax
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%rax,-32
	pushq	%rdx			# Save %rdx
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%rdx,-40
	pushq	%rcx			# Save %rcx
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%rcx,-48
	pushq	%rsi			# Save %rsi
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%rsi,-56
	pushq	%rdi			# Save %rdi
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%rdi,-64
	pushq	%r8			# Save %r8
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%r8,-72
	pushq	%r9			# Save %r9
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%r9,-80
	pushq	%r10			# Save %r10
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%r10,-88
	pushq	%r11			# Save %r11
	.cfi_adjust_cfa_offset 8
	.cfi_offset	%r11,-96

	movq	0x58(%rsp),%rdi		# Fetch obj argument
	movq	0x60(%rsp),%rsi		# Fetch reloff argument
	leaq	(%rsi,%rsi,2),%rsi	# multiply by 3
	leaq	(,%rsi,8),%rsi		# now 8, for 24 (sizeof Elf_Rela)

	call	_rtld_bind@PLT		# Transfer control to the binder
	/* Now %rax contains the entry point of the function being called. */

	movq	%rax,0x60(%rsp)		# Store target over reloff argument
	popq	%r11			# Restore %r11
	.cfi_adjust_cfa_offset -8
	.cfi_restore %r11
	popq	%r10			# Restore %r10
	.cfi_adjust_cfa_offset -8
	.cfi_restore %r10
	popq	%r9			# Restore %r9
	.cfi_adjust_cfa_offset -8
	.cfi_restore %r9
	popq	%r8			# Restore %r8
	.cfi_adjust_cfa_offset -8
	.cfi_restore %r8
	popq	%rdi			# Restore %rdi
	.cfi_adjust_cfa_offset -8
	.cfi_restore %rdi
	popq	%rsi			# Restore %rsi
	.cfi_adjust_cfa_offset -8
	.cfi_restore %rsi
	popq	%rcx			# Restore %rcx
	.cfi_adjust_cfa_offset -8
	.cfi_restore %rcx
	popq	%rdx			# Restore %rdx
	.cfi_adjust_cfa_offset -8
	.cfi_restore %rdx
	popq	%rax			# Restore %rax
	.cfi_adjust_cfa_offset -8
	.cfi_restore %rax
	popfq				# Restore rflags
	.cfi_adjust_cfa_offset -8
	leaq	16(%rsp),%rsp		# Discard spare, obj, do not change rflags
	ret				# "Return" to target address
	.cfi_endproc
	.size	_rtld_bind_start, . - _rtld_bind_start

	.section .note.GNU-stack,"",%progbits
OpenPOWER on IntegriCloud