xref: /openbsd/libexec/ld.so/powerpc/ldasm.S (revision cecf84d4)
1/*	$OpenBSD: ldasm.S,v 1.21 2014/07/14 03:54:51 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1999 Dale Rahn
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#define AUX_entry 9
30
31#include <machine/asm.h>
32#include <sys/syscall.h>
33
34ENTRY(_dl_start)
35	mr	19, 1
36	stwu	1, (-16 -((AUX_entry+3)*4))(1)	# Some space.
37
38	mflr	27		/* save off old link register */
39	stw	27, 4(19)	/* save in normal location */
40
41	# squirrel away the arguments for main
42	mr	20, 3	#argc
43	mr	21, 4	#argv
44	mr	22, 5	#envp
45	mr	23, 6	# ???
46
47	bl	1f
48	# this instruction never gets executed but can be used
49	# to find the virtual address where the page is loaded.
50	bl _GLOBAL_OFFSET_TABLE_@local-4
51	bl _DYNAMIC@local
521:
53	mflr	5		# this stores where we are (+4)
54	lwz	18, 0(5)	# load the instruction at offset_sym
55				# it contains an offset to the location
56				# of the GOT.
57
58	rlwinm	18,18,0,8,30	# mask off the offset portion of the instr.
59
60	/*
61	 * these adds effectively calculate the value the
62	 * bl _GLOBAL_OFFSET_TABLE_@local-4
63	 * operation that would be below would calculate.
64	 */
65	add	28, 18, 5
66	mr	6, 5		# save offset for later use
67
68	/* mprotect GOT-4 for correct execution of blrl instruction */
69	li	0, SYS_mprotect
70	mr	3, 28
71	li	4, 4
72	li	5, 7 /* (PROT_READ|PROT_WRITE|PROT_EXEC) */
73	sc
74
75	mr	5, 6
76
77	li	0, 0
78	dcbf	5, 18
79	sync
80	isync
81	icbi	5, 18		# make certain that the got table addr is
82				# not in the icache
83	sync
84	isync
85
86	/* This calculates the address of _DYNAMIC the same way
87	 * that the GLOBAL_OFFSET_TABLE was calculated.
88	 */
89	lwz	18, 4(5)
90	rlwinm	18,18,0,8,30	# mask off the offset portion of the instr.
91	add	8, 18, 5	# address of _DYNAMIC (arg6 for _dl_boot)
92	addi	18, 8, 4	# correction.
93	lwz	4, 4(28)	# load address of _DYNAMIC according to got.
94	sub	4, 18, 4	# determine load offset
95
96	mr	17, 4		# save for _dl_boot
97
98
99	subi	3, 21, 4	# Get stack pointer (arg0 for _dl_boot).
100	addi	4, 1, 8		# dl_data
101	mr	5, 18		# dynamicp
102
103	bl	_dl_boot_bind@local
104
105	mr	3, 21		# argv
106	mr	4, 22		# envp
107	mr	5, 17		# loff
108	addi	6, 1, 8		# dl_data
109
110	bl	_dl_boot@local
111
112	mtctr	3		# put return value into ctr to execute
113
114	# get back the squirreled away the arguments for main
115	mr	3, 20
116	mr	4, 21
117	mr	5, 22
118	mr	6, 23
119
120	bl	_GLOBAL_OFFSET_TABLE_@local-4
121	mflr	31
122	lwz	7, _dl_dtors@got(31)
123
124	mtlr	27
125	lwz	1, 0(1)		# Restore stack pointer.
126	bctr			# Go execute the 'real' program.
127
128ENTRY(_dl_bind_start)
129	stwu	1,-64(1)
130
131	stw	0,8(1)		# save r0 - cerror ;-)
132	mflr	0
133	stw	0,68(1)		# save	lr
134
135	stw	3,12(1)		# save	r3-r10, C calling convention
136	stw	4,20(1)		# r13 - r31 are preserved by called code
137	stw	5,24(1)
138	stw	6,28(1)
139	stw	7,32(1)
140	stw	8,36(1)
141	stw	9,40(1)
142	stw	10,44(1)
143
144	mr	3,12		# obj
145	mr	4,11		# reloff
146	bl	_dl_bind@plt	#	_rtld_bind(obj,	reloff)
147	mtctr	3
148
149	lwz	3,12(1)
150	lwz	4,20(1)
151	lwz	5,24(1)
152	lwz	6,28(1)
153	lwz	7,32(1)
154	lwz	8,36(1)
155	lwz	9,40(1)
156	lwz	10,44(1)
157
158	lwz	0,68(1)		# restore lr
159	mtlr	0
160	lwz	0,8(1)
161
162	addi	1,1,64
163	bctr
164
165#define	DL_SYSCALL(n)		DL_SYSCALL2(n,n)
166#define	DL_SYSCALL_NOERR(n)	DL_SYSCALL2_NOERR(n,n)
167#define	DL_SYSCALL2(n,c)						\
168ENTRY(_dl_##n)								\
169	li	0, SYS_##c;						\
170	sc;								\
171	cmpwi	0, 0;							\
172	beqlr+;								\
173	b	_dl_cerror
174#define	DL_SYSCALL2_NOERR(n,c)						\
175ENTRY(_dl_##n)								\
176	li	0, SYS_##c;						\
177	sc;								\
178	blr
179
180_dl_cerror:
181	neg	3, 3
182	blr
183
184ENTRY(_dl_sigprocmask)
185	/* _dl_sigprocmask does not support NULL as the new mask */
186#if 0
187	cmpwi	4, 0
188	bne+	1f
189	li	3, 1		/* SIG_BLOCK */
190	b	2f
1911:
192#endif
193	lwz	4, 0(4)
1942:
195	li	0, SYS_sigprocmask
196	sc
197	cmpwi	0, 0
198	bne-	_dl_cerror
199	cmpwi	5, 0
200	beq-	1f
201	stw	3, 0(5)
2021:
203	li	3, 0
204	blr
205
206DL_SYSCALL(close)
207DL_SYSCALL_NOERR(exit)
208DL_SYSCALL(fstat)
209DL_SYSCALL2(getcwd,__getcwd)
210DL_SYSCALL(getdents)
211DL_SYSCALL(getentropy)
212DL_SYSCALL(sendsyslog)
213DL_SYSCALL(gettimeofday)
214DL_SYSCALL_NOERR(issetugid)
215DL_SYSCALL(lstat)
216DL_SYSCALL(mmap)
217DL_SYSCALL(mprotect)
218DL_SYSCALL(munmap)
219DL_SYSCALL(open)
220DL_SYSCALL(read)
221DL_SYSCALL(readlink)
222DL_SYSCALL2(_syscall,__syscall)
223DL_SYSCALL2(sysctl,__sysctl)
224DL_SYSCALL(utrace)
225DL_SYSCALL(write)
226