xref: /openbsd/libexec/ld.so/powerpc/archdep.h (revision c6ba0247)
1*c6ba0247Srahnds /*	$OpenBSD: archdep.h,v 1.2 2000/10/01 00:54:35 rahnds Exp $ */
289c547eeSrahnds 
389c547eeSrahnds /*
489c547eeSrahnds  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
589c547eeSrahnds  *
689c547eeSrahnds  * Redistribution and use in source and binary forms, with or without
789c547eeSrahnds  * modification, are permitted provided that the following conditions
889c547eeSrahnds  * are met:
989c547eeSrahnds  * 1. Redistributions of source code must retain the above copyright
1089c547eeSrahnds  *    notice, this list of conditions and the following disclaimer.
1189c547eeSrahnds  * 2. Redistributions in binary form must reproduce the above copyright
1289c547eeSrahnds  *    notice, this list of conditions and the following disclaimer in the
1389c547eeSrahnds  *    documentation and/or other materials provided with the distribution.
1489c547eeSrahnds  * 3. All advertising materials mentioning features or use of this software
1589c547eeSrahnds  *    must display the following acknowledgement:
1689c547eeSrahnds  *	This product includes software developed under OpenBSD by
1789c547eeSrahnds  *	Per Fogelstrom, Opsycon AB, Sweden.
1889c547eeSrahnds  * 4. The name of the author may not be used to endorse or promote products
1989c547eeSrahnds  *    derived from this software without specific prior written permission.
2089c547eeSrahnds  *
2189c547eeSrahnds  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
2289c547eeSrahnds  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2389c547eeSrahnds  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2489c547eeSrahnds  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
2589c547eeSrahnds  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2689c547eeSrahnds  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2789c547eeSrahnds  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2889c547eeSrahnds  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2989c547eeSrahnds  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3089c547eeSrahnds  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3189c547eeSrahnds  * SUCH DAMAGE.
3289c547eeSrahnds  *
3389c547eeSrahnds  */
3489c547eeSrahnds 
3589c547eeSrahnds #ifndef _POWERPC_ARCHDEP_H_
3689c547eeSrahnds #define _POWERPC_ARCHDEP_H_
3789c547eeSrahnds 
3889c547eeSrahnds #define	DL_MALLOC_ALIGN	4	/* Arch constraint or otherwise */
3989c547eeSrahnds 
4089c547eeSrahnds #define	MACHID	EM_PPC	/* ELF e_machine ID value checked */
4189c547eeSrahnds 
4289c547eeSrahnds #define	RELTYPE	Elf32_Rela
4389c547eeSrahnds #define	RELSIZE	sizeof(Elf32_Rela)
4489c547eeSrahnds 
4589c547eeSrahnds #include <elf_abi.h>
4689c547eeSrahnds #include <machine/reloc.h>
4789c547eeSrahnds 
4889c547eeSrahnds /* HACK */
4989c547eeSrahnds #define DT_PROCNUM 0
5089c547eeSrahnds #ifndef DT_BIND_NOW
5189c547eeSrahnds #define DT_BIND_NOW 0
5289c547eeSrahnds #endif
5389c547eeSrahnds 
5489c547eeSrahnds /*
5589c547eeSrahnds  *	Simple reloc of REL32's. Used by bootstrapping.
5689c547eeSrahnds  */
5789c547eeSrahnds #define	SIMPLE_RELOC(r, s, p, v)					\
5889c547eeSrahnds 	if(ELF32_R_TYPE((r)->r_info) == RELOC_32) {			\
5989c547eeSrahnds 		if((ELF32_ST_BIND((s)->st_info) == STB_LOCAL) &&	\
6089c547eeSrahnds 		   (ELF32_ST_TYPE((s)->st_info) == STT_SECTION ||	\
6189c547eeSrahnds 		    ELF32_ST_TYPE((s)->st_info) == STT_NOTYPE) ) {	\
6289c547eeSrahnds 			*(p) += (v);					\
6389c547eeSrahnds 		}							\
6489c547eeSrahnds 		else {							\
6589c547eeSrahnds 			*(p) = (v) + (s)->st_value;			\
6689c547eeSrahnds 		}							\
6789c547eeSrahnds 	}
6889c547eeSrahnds 
6989c547eeSrahnds /*
7089c547eeSrahnds  *	The following functions are declared inline so they can
7189c547eeSrahnds  *	be used before bootstrap linking has been finished.
7289c547eeSrahnds  */
7389c547eeSrahnds static inline void
7489c547eeSrahnds _dl_dcbf(Elf32_Addr *addr)
7589c547eeSrahnds {
76*c6ba0247Srahnds   __asm__ volatile ("dcbst 0, %0\n\t"
77*c6ba0247Srahnds 		    "sync\n\t"
78*c6ba0247Srahnds 		    "icbi 0, %0\n\t"
79*c6ba0247Srahnds 		    "sync\n\t"
80*c6ba0247Srahnds 		    "isync"
8189c547eeSrahnds                     : : "r" (addr) : "0");
8289c547eeSrahnds }
8389c547eeSrahnds 
8489c547eeSrahnds static inline int _dl_write (int fd, const char* buf, int len);
8589c547eeSrahnds static inline void
8689c547eeSrahnds _dl_wrstderr(const char *s)
8789c547eeSrahnds {
8889c547eeSrahnds 	while(*s) {
8989c547eeSrahnds 		_dl_write(2, s, 1);
9089c547eeSrahnds 		s++;
9189c547eeSrahnds 	}
9289c547eeSrahnds }
9389c547eeSrahnds 
9489c547eeSrahnds static inline void *
9589c547eeSrahnds _dl_memset(void *p, const char v, size_t c)
9689c547eeSrahnds {
9789c547eeSrahnds 	char *ip = p;
9889c547eeSrahnds 
9989c547eeSrahnds 	while(c--)
10089c547eeSrahnds 		*ip++ = v;
10189c547eeSrahnds 	return(p);
10289c547eeSrahnds }
10389c547eeSrahnds 
10489c547eeSrahnds static inline int
10589c547eeSrahnds _dl_strlen(const char *p)
10689c547eeSrahnds {
10789c547eeSrahnds 	const char *s = p;
10889c547eeSrahnds 
10989c547eeSrahnds 	while(*s != '\0')
11089c547eeSrahnds 		s++;
11189c547eeSrahnds 	return(s - p);
11289c547eeSrahnds }
11389c547eeSrahnds 
11489c547eeSrahnds static inline char *
11589c547eeSrahnds _dl_strcpy(char *d, const char *s)
11689c547eeSrahnds {
11789c547eeSrahnds 	char *rd = d;
11889c547eeSrahnds 
11989c547eeSrahnds 	while((*d++ = *s++) != '\0');
12089c547eeSrahnds 
12189c547eeSrahnds 	return(rd);
12289c547eeSrahnds }
12389c547eeSrahnds 
12489c547eeSrahnds static inline int
12589c547eeSrahnds _dl_strncmp(const char *d, const char *s, int c)
12689c547eeSrahnds {
12789c547eeSrahnds 	while(c-- && *d && *d++ == *s++) {};
12889c547eeSrahnds 	if(c < 0) {
12989c547eeSrahnds 		return(0);
13089c547eeSrahnds 	}
13189c547eeSrahnds 	return(d[-1] - s[-1]);
13289c547eeSrahnds }
13389c547eeSrahnds 
13489c547eeSrahnds static inline int
13589c547eeSrahnds _dl_strcmp(const char *d, const char *s)
13689c547eeSrahnds {
13789c547eeSrahnds 	while(*d && *d++ == *s++) {};
13889c547eeSrahnds 	return(d[-1] - s[-1]);
13989c547eeSrahnds }
14089c547eeSrahnds 
14189c547eeSrahnds static inline const char *
14289c547eeSrahnds _dl_strchr(const char *p, const int c)
14389c547eeSrahnds {
14489c547eeSrahnds 	while(*p) {
14589c547eeSrahnds 		if(*p == c) {
14689c547eeSrahnds 			return(p);
14789c547eeSrahnds 		}
14889c547eeSrahnds 		p++;
14989c547eeSrahnds 	}
15089c547eeSrahnds 	return(0);
15189c547eeSrahnds }
15289c547eeSrahnds 
15389c547eeSrahnds static inline void
15489c547eeSrahnds RELOC_RELA(Elf32_Rela *r,
15589c547eeSrahnds 	const Elf32_Sym *s, Elf32_Addr *p, int v)
15689c547eeSrahnds {
15789c547eeSrahnds 	if(ELF32_R_TYPE((r)->r_info) == RELOC_RELATIVE) {
15889c547eeSrahnds 		if((ELF32_ST_BIND((s)->st_info) == STB_LOCAL) &&
15989c547eeSrahnds 		   ((ELF32_ST_TYPE((s)->st_info) == STT_SECTION) ||
16089c547eeSrahnds 		   (ELF32_ST_TYPE((s)->st_info) == STT_NOTYPE)) ) {
16189c547eeSrahnds 			*(p) = (v) + (r)->r_addend;
16289c547eeSrahnds 		} else {
16389c547eeSrahnds 			*(p) = (v) + (s)->st_value + (r)->r_addend;
16489c547eeSrahnds 		}
16589c547eeSrahnds 	} else if(ELF32_R_TYPE((r)->r_info) == RELOC_JMP_SLOT) {
16689c547eeSrahnds 		Elf32_Addr val = (v) + (s)->st_value + (r)->r_addend -
16789c547eeSrahnds 			(Elf32_Addr)(p);
16889c547eeSrahnds 		if (((val & 0xfe000000) != 0) &&
16989c547eeSrahnds 			((val & 0xfe000000) != 0xfe000000))
17089c547eeSrahnds 		{
17189c547eeSrahnds 			/* invalid offset */
17289c547eeSrahnds 			_dl_exit(20);
17389c547eeSrahnds 		}
17489c547eeSrahnds 		val &= ~0xfc000000;
17589c547eeSrahnds 		val |=  0x48000000;
17689c547eeSrahnds 		*(p) = val;
17789c547eeSrahnds 		_dl_dcbf(p);
17889c547eeSrahnds 	} else if(ELF32_R_TYPE((r)->r_info) == RELOC_GLOB_DAT) {
17989c547eeSrahnds 		*(p) = (v) + (s)->st_value + (r)->r_addend;
18089c547eeSrahnds 	} else {
18189c547eeSrahnds 		/* error */
18289c547eeSrahnds 	}
18389c547eeSrahnds }
18489c547eeSrahnds 
18589c547eeSrahnds #endif /* _POWERPC_ARCHDEP_H_ */
186