diff options
author | <gerald.jelinek@sun.com> | 2010-04-21 07:18:39 -0600 |
---|---|---|
committer | <gerald.jelinek@sun.com> | 2010-04-21 07:18:39 -0600 |
commit | 80e2ca8596e3435bc3b76f3c597833ea0a87f85e (patch) | |
tree | d9cf766b43816c0fb08ec9b5dc9a97500c55853d | |
parent | c0dd49bdd68c0d758a67d56f07826f3b45cfc664 (diff) | |
download | illumos-joyent-80e2ca8596e3435bc3b76f3c597833ea0a87f85e.tar.gz |
6927649 merge common code from solaris10 and sn1 brands
6916737 s10_indir function in s10_brand library invokes incorrect argument
--HG--
rename : usr/src/lib/brand/sn1/Makefile => usr/src/lib/brand/shared/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/Makefile => usr/src/lib/brand/shared/brand/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/Makefile.com => usr/src/lib/brand/shared/brand/Makefile.com
rename : usr/src/lib/brand/sn1/sn1_brand/amd64/Makefile => usr/src/lib/brand/shared/brand/amd64/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_crt.s => usr/src/lib/brand/shared/brand/amd64/crt.s
rename : usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s => usr/src/lib/brand/shared/brand/amd64/handler.s
rename : usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_runexe.s => usr/src/lib/brand/shared/brand/amd64/runexe.s
rename : usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c => usr/src/lib/brand/shared/brand/common/brand_util.c
rename : usr/src/lib/brand/sn1/sn1_brand/common/offsets.in => usr/src/lib/brand/shared/brand/common/offsets.in
rename : usr/src/lib/brand/sn1/sn1_brand/i386/Makefile => usr/src/lib/brand/shared/brand/i386/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/i386/sn1_crt.s => usr/src/lib/brand/shared/brand/i386/crt.s
rename : usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s => usr/src/lib/brand/shared/brand/i386/handler.s
rename : usr/src/lib/brand/sn1/sn1_brand/i386/sn1_runexe.s => usr/src/lib/brand/shared/brand/i386/runexe.s
rename : usr/src/lib/brand/sn1/sn1_brand/sparc/Makefile => usr/src/lib/brand/shared/brand/sparc/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_crt.s => usr/src/lib/brand/shared/brand/sparc/crt.s
rename : usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_handler.s => usr/src/lib/brand/shared/brand/sparc/handler.s
rename : usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_runexe.s => usr/src/lib/brand/shared/brand/sparc/runexe.s
rename : usr/src/lib/brand/sn1/sn1_brand/sparcv9/Makefile => usr/src/lib/brand/shared/brand/sparcv9/Makefile
rename : usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h => usr/src/lib/brand/shared/brand/sys/brand_misc.h
rename : usr/src/lib/brand/sn1/librtld_db/Makefile.com => usr/src/lib/brand/shared/librtld_db/Makefile.com
rename : usr/src/lib/brand/sn1/librtld_db/common/sn1_librtld_db.c => usr/src/lib/brand/shared/librtld_db/common/brand_librtld_db.c
rename : usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers => usr/src/lib/brand/shared/librtld_db/common/mapfile-vers
rename : usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers.64 => usr/src/lib/brand/shared/librtld_db/common/mapfile-vers.64
rename : usr/src/lib/brand/sn1/Makefile => usr/src/lib/brand/shared/zone/Makefile
rename : usr/src/lib/brand/shared/common.ksh => usr/src/lib/brand/shared/zone/common.ksh
rename : usr/src/lib/brand/shared/query.ksh => usr/src/lib/brand/shared/zone/query.ksh
rename : usr/src/lib/brand/shared/uninstall.ksh => usr/src/lib/brand/shared/zone/uninstall.ksh
rename : usr/src/uts/intel/brand/common/brand_asm.h => usr/src/uts/intel/brand/common/brand_solaris.s
rename : usr/src/uts/sun4/brand/sn1/sn1_brand_asm.s => usr/src/uts/sun4/brand/common/brand_solaris.s
86 files changed, 2535 insertions, 5129 deletions
diff --git a/usr/src/lib/brand/Makefile b/usr/src/lib/brand/Makefile index bf01723084..cd19a0bf2c 100644 --- a/usr/src/lib/brand/Makefile +++ b/usr/src/lib/brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # lib/brand/Makefile # @@ -34,7 +33,7 @@ include ../../Makefile.master i386_SUBDIRS= lx i386_MSGSUBDIRS= lx -SUBDIRS= sn1 solaris10 ipkg labeled shared $($(MACH)_SUBDIRS) +SUBDIRS= shared .WAIT sn1 solaris10 ipkg labeled $($(MACH)_SUBDIRS) MSGSUBDIRS= solaris10 shared $($(MACH)_MSGSUBDIRS) all := TARGET= all diff --git a/usr/src/lib/brand/Makefile.brand b/usr/src/lib/brand/Makefile.brand index a2cf9bd250..08a994899b 100644 --- a/usr/src/lib/brand/Makefile.brand +++ b/usr/src/lib/brand/Makefile.brand @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # include $(SRC)/Makefile.master @@ -38,6 +37,8 @@ ROOTXMLDOCS= $(XMLDOCS:%=$(ROOTBRANDDIR)/%) ROOTSHARED= $(SHARED:%=$(ROOTSHAREDDIR)/%) ETCUSER= $(USERFILES:%=$(ETCBRANDDIR)/%) +BRAND_SHARED= $(SRC)/lib/brand/shared + ROOTTEMPLATES= $(TEMPLATES:%=$(ROOTTEMPLATEDIR)/%) $(ROOTBRANDDIR) := FILEMODE = 755 diff --git a/usr/src/lib/brand/shared/Makefile b/usr/src/lib/brand/shared/Makefile index 6c0aa73c13..9cb19dc163 100644 --- a/usr/src/lib/brand/shared/Makefile +++ b/usr/src/lib/brand/shared/Makefile @@ -18,38 +18,32 @@ # # CDDL HEADER END # - # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -PROG=query -SHARED= common.ksh query uninstall.ksh -CLOBBERFILES= query - -include $(SRC)/cmd/Makefile.cmd -include ../Makefile.brand - -$(ROOTSHAREDDIR)/common.ksh := FILEMODE = 0444 -$(ROOTSHAREDDIR)/uninstall.ksh := FILEMODE = 0444 +default: all -CLOBBERFILES= $(ROOTSHARED) $(PROG) +# Build everything in parallel; use .WAIT for dependencies +.PARALLEL: -POFILES= common.po query.po uninstall.po -POFILE= shared.po +SUBDIRS = brand zone +MSGSUBDIRS = zone -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint +_msg := TARGET= _msg -all: $(PROG) +.KEEP_STATE: -install: $(ROOTSHARED) +all install clean clobber lint: $(SUBDIRS) -clean: - -$(RM) $(PROG) $(POFILES) +_msg: $(MSGSUBDIRS) -lint: +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) -include $(SRC)/cmd/Makefile.targ +FRC: diff --git a/usr/src/lib/brand/solaris10/librtld_db/common/mapfile-vers.64 b/usr/src/lib/brand/shared/brand/Makefile index 51e0c2c3cc..1bb18cd84d 100644 --- a/usr/src/lib/brand/solaris10/librtld_db/common/mapfile-vers.64 +++ b/usr/src/lib/brand/shared/brand/Makefile @@ -19,25 +19,28 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# +include $(SRC)/lib/Makefile.lib + +default: all + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg + +.KEEP_STATE: + +all install clean clobber lint _msg: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) -SUNWprivate_1.1 { - global: - rtld_db_brand_ops64; -}; +FRC: diff --git a/usr/src/lib/brand/shared/brand/Makefile.com b/usr/src/lib/brand/shared/brand/Makefile.com new file mode 100644 index 0000000000..de2decae37 --- /dev/null +++ b/usr/src/lib/brand/shared/brand/Makefile.com @@ -0,0 +1,73 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +COBJS = brand_util.o +ASOBJS = crt.o handler.o runexe.o +OFFSETS_SRC = ../common/offsets.in +OFFSETS_H = assym.h +OBJECTS = $(COBJS) $(ASOBJS) +CLOBBERFILES += $(OFFSETS_H) + +include $(SRC)/lib/Makefile.lib + +SRCDIR = ../common +CSRCS = $(COBJS:%o=../common/%c) +ASSRCS = $(ASOBJS:%o=$(ISASRCDIR)/%s) +SRCS = $(CSRCS) $(ASSRCS) + +# +# Ugh, this is a gross hack. Our assembly routines uses lots of defines +# to simplify variable access. All these defines work fine for amd64 +# compiles because when compiling for amd64 we use the GNU assembler, +# gas. For 32-bit code we use the Sun assembler, as. Unfortunatly +# as does not handle certian constructs that gas does. So rather than +# make our code less readable, we'll just use gas to compile our 32-bit +# code as well. +# +i386_AS = $(amd64_AS) + +CPPFLAGS += -D_REENTRANT -U_ASM -I. -I../sys +CFLAGS += $(CCVERBOSE) +ASFLAGS = -P $(ASFLAGS_$(CURTYPE)) -D_ASM -I. -I../sys + +.KEEP_STATE: + +# +# build the offset header before trying to compile any files. (it's included +# by brand_misc.h, so it's needed for all objects, not just assembly ones.) +# +all: $(OFFSETS_H) pics .WAIT $(PICS) + +lint: lintcheck + +$(OBJECTS:%=pics/%): $(OFFSETS_H) + +$(OFFSETS_H): $(OFFSETS_SRC) + $(OFFSETS_CREATE) $(CTF_FLAGS) < $(OFFSETS_SRC) >$@ + +pics/%.o: $(ISASRCDIR)/%.s + $(COMPILE.s) -o $@ $< + $(POST_PROCESS_O) + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/brand/solaris10/librtld_db/common/mapfile-vers b/usr/src/lib/brand/shared/brand/amd64/Makefile index 4f3ef01e3c..3a6cd15af6 100644 --- a/usr/src/lib/brand/solaris10/librtld_db/common/mapfile-vers +++ b/usr/src/lib/brand/shared/brand/amd64/Makefile @@ -19,39 +19,14 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# +ISASRCDIR = . + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 -SUNWprivate_1.1 { - global: - rtld_db_brand_ops32; - local: - *; -}; +CPPFLAGS += -D_SYSCALL32 -#Externally defined symbols -{ - global: - ps_pauxv = NODIRECT PARENT; - ps_pdmodel = NODIRECT PARENT; - ps_pglobal_lookup = NODIRECT PARENT; - ps_pglobal_sym = NODIRECT PARENT; - ps_plog = NODIRECT PARENT; - ps_pread = NODIRECT PARENT; - ps_pwrite = NODIRECT PARENT; -}; +install: all diff --git a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_crt.s b/usr/src/lib/brand/shared/brand/amd64/crt.s index 059eb8fe53..831aa6b240 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_crt.s +++ b/usr/src/lib/brand/shared/brand/amd64/crt.s @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> @@ -40,7 +39,7 @@ _start(void) * This platform specific assembly entry point exists just to invoke * the common brand library startup routine. That routine expects to * be called with the following arguments: - * s10_init(int argc, char *argv[], char *envp[]) + * brand_init(int argc, char *argv[], char *envp[]) * * There are no arguments explicitly passed to this entry point, * routine, but we do know how our initial stack has been setup by @@ -66,7 +65,7 @@ _start(void) movq 16(%rbp), %rdi / argc in %rax (1st param) leaq 24(%rbp), %rsi / &argv[0] in %rbx (2nd param) leaq 32(%rbp,%rdi,8), %rdx / envp in %rcx (3rd param) - call s10_init + call brand_init /*NOTREACHED*/ SET_SIZE(_start) diff --git a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s b/usr/src/lib/brand/shared/brand/amd64/handler.s index 1853801302..fb5d3c2bb4 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_handler.s +++ b/usr/src/lib/brand/shared/brand/amd64/handler.s @@ -19,18 +19,17 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ -#include <sn1_misc.h> +#include <brand_misc.h> /* * Each JMP must occupy 16 bytes */ #define JMP \ - pushq $_CONST(. - sn1_handler_table); \ - jmp sn1_handler; \ + pushq $_CONST(. - brand_handler_table); \ + jmp brand_handler; \ .align 16; #define JMP4 JMP; JMP; JMP; JMP @@ -41,11 +40,11 @@ #if defined(lint) void -sn1_handler_table(void) +brand_handler_table(void) {} void -sn1_handler(void) +brand_handler(void) { } @@ -58,9 +57,9 @@ sn1_handler(void) * entries. */ .align 16 - ENTRY_NP(sn1_handler_table) + ENTRY_NP(brand_handler_table) JMP256 - SET_SIZE(sn1_handler_table) + SET_SIZE(brand_handler_table) /* * %rax - userland return address @@ -70,7 +69,7 @@ sn1_handler(void) * %rsp+0 | syscall number | * -------------------------------------- */ - ENTRY_NP(sn1_handler) + ENTRY_NP(brand_handler) pushq %rbp /* allocate stack frame */ movq %rsp, %rbp @@ -116,11 +115,11 @@ sn1_handler(void) movq $0, EH_LOCALS_GREG(REG_GSBASE)(%rbp) /* - * The kernel drops us into the middle of the sn1_handle_table + * The kernel drops us into the middle of the brand_handle_table * above that then pushes that table offset onto the stack, and calls - * into sn1_handler. That offset indicates the system call number while - * %rax holds the return address for the system call. We replace the - * value on the stack with the return address, and use the value to + * into brand_handler. That offset indicates the system call number + * while %rax holds the return address for the system call. We replace + * the value on the stack with the return address, and use the value to * compute the system call number by dividing by the table entry size. */ xchgq CPTRSIZE(%rbp), %rax /* swap JMP table offset and ret addr */ @@ -133,12 +132,12 @@ sn1_handler(void) * because a "sub" operation can modify flags and we wanted to * save the flags into the gregset_t above before they get modified. * - * Our stack frame format is documented in sn1_misc.h. + * Our stack frame format is documented in brand_misc.h. */ subq $EH_LOCALS_SIZE, %rsp /* Look up the system call's entry in the sysent table */ - movq sn1_sysent_table@GOTPCREL(%rip), %r11 /* %r11 = sysent_table */ + movq brand_sysent_table@GOTPCREL(%rip), %r11 /* %r11 = sysent_tbl */ shlq $4, %rax /* each entry is 16 bytes */ addq %rax, %r11 /* %r11 = sysent entry address */ @@ -180,7 +179,7 @@ sn1_handler(void) addq $EH_LOCALS_SYSRET, %rdi /* arg0 == sysret_t ptr */ /* invoke the emulation routine */ - ALTENTRY(sn1_handler_savepc) + ALTENTRY(brand_handler_savepc) call *(%r11) /* restore scratch and parameter registers */ @@ -213,7 +212,7 @@ return: movq %rbp, %rsp /* restore stack */ popq %rbp ret /* ret to instr after syscall */ - SET_SIZE(sn1_handler) + SET_SIZE(brand_handler) #endif /* lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_runexe.s b/usr/src/lib/brand/shared/brand/amd64/runexe.s index 4798d4fe87..418c8726e1 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_runexe.s +++ b/usr/src/lib/brand/shared/brand/amd64/runexe.s @@ -20,18 +20,17 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> -#include <sn1_misc.h> +#include <brand_misc.h> #if defined(lint) /*ARGSUSED*/ void -sn1_runexe(void *argv, ulong_t entry) +brand_runexe(void *argv, ulong_t entry) { } @@ -52,7 +51,7 @@ sn1_runexe(void *argv, ulong_t entry) * frame pointers to their values when this processes first started * execution. */ - ENTRY_NP(sn1_runexe) + ENTRY_NP(brand_runexe) movq %rdi, %rax / %rax = &argv[0] movq %rsi, %rbx / Brand app entry point in %rbx @@ -76,5 +75,5 @@ sn1_runexe(void *argv, ulong_t entry) /* * target will never return. */ - SET_SIZE(sn1_runexe) + SET_SIZE(brand_runexe) #endif /* lint */ diff --git a/usr/src/lib/brand/shared/brand/common/brand_util.c b/usr/src/lib/brand/shared/brand/common/brand_util.c new file mode 100644 index 0000000000..051cbccb21 --- /dev/null +++ b/usr/src/lib/brand/shared/brand/common/brand_util.c @@ -0,0 +1,452 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> +#include <sys/auxv.h> +#include <sys/bitmap.h> +#include <sys/brand.h> +#include <sys/inttypes.h> +#include <sys/lwp.h> +#include <sys/syscall.h> +#include <sys/systm.h> +#include <sys/utsname.h> +#include <fcntl.h> +#include <brand_misc.h> +#include <sys/brand.h> + +extern brand_sysent_table_t brand_sysent_table[]; + +/*LINTED: static unused*/ +static volatile int brand_abort_err; +/*LINTED: static unused*/ +static volatile const char *brand_abort_msg; +/*LINTED: static unused*/ +static volatile const char *brand_abort_file; +/*LINTED: static unused*/ +static volatile int brand_abort_line; + +/* + * Principles of emulation 101. + * + * + * *** Setting errno + * + * Just don't do it. This emulation library is loaded onto a + * seperate link map from the application who's address space we're + * running in. We have our own private copy of libc, so there for, + * the errno value accessible from here is is also private and changing + * it will not affect any errno value that the processes who's address + * space we are running in will see. To return an error condition we + * should return the errno value we'd like the system to return. + * For more information about this see the comments in brand_misc.h. + * Basically, when we return to the caller that initiated the system + * call it's their responsibility to set errno. + * + * + * *** Recursion Considerations + * + * When emulating system calls we need to be very careful about what + * library calls we invoke. Library calls should be kept to a minimum. + * One issue is that library calls can invoke system calls, so if we're + * emulating a system call and we invoke a library call that depends on + * that system call we will probably enter a recursive loop, which would + * be bad. + * + * + * *** Return Values. + * + * See brand_misc.h. + * + * *** Agent lwp considerations + * + * It is currently impossible to do any emulation for these system call + * when they are being invoked on behalf of an agent lwp. To understand why + * it's impossible you have to understand how agent lwp syscalls work. + * + * The agent lwp syscall process works as follows: + * 1 The controlling process stops the target. + * 2 The controlling process injects an agent lwp which is also stopped. + * This agent lwp assumes the userland stack and register values + * of another stopped lwp in the current process. + * 3 The controlling process configures the agent lwp to start + * executing the requested system call. + * 4 The controlling process configure /proc to stop the agent lwp when + * it enters the requested system call. + * 5 The controlling processes allows the agent lwp to start executing. + * 6 The agent lwp traps into the kernel to perform the requested system + * call and immediately stop. + * 7 The controlling process copies all the arguments for the requested + * system call onto the agent lwp's stack. + * 8 The controlling process configures /proc to stop the agent lwp + * when it completes the requested system call. + * 9 The controlling processes allows the agent lwp to start executing. + * 10 The agent lwp executes the system call and then stop before returning + * to userland. + * 11 The controlling process copies the return value and return arguments + * back from the agent lwps stack. + * 12 The controlling process destroys the agent lwp and restarts + * the target process. + * + * The fundamental problem is that when the agent executes the request + * system call in step 5, if we're emulating that system call then the + * lwp is redirected back to our emulation layer without blocking + * in the kernel. But our emulation layer can't access the arguments + * for the system call because they haven't been copied to the stack + * yet and they still only exist in the controlling processes address + * space. This prevents us from being able to do any emulation of + * agent lwp system calls. Hence, currently our brand trap interposition + * callback (XXX_brand_syscall_callback_common) will detect if a system + * call is being made by an agent lwp, and if this is the case it will + * never redirect the system call to this emulation library. + * + * In the future, if this proves to be a problem the the easiest solution + * would probably be to replace the branded versions of these application + * with their native counterparts. Ie, truss, plimit, and pfiles could be + * replace with wrapper scripts that execute the native versions of these + * applications. In the case of plimit and pfiles this should be pretty + * strait forward. Truss would probably be more tricky since it can + * execute applications which would be branded applications, so in that + * case it might be necessary to create a loadable library which could + * be LD_PRELOADed into truss and this library would interpose on the + * exec() system call to allow truss to correctly execute branded + * processes. It should be pointed out that this solution could work + * because "native agent lwps" (ie, agent lwps created by native + * processes) can be treated differently from "branded aged lwps" (ie, + * agent lwps created by branded processes), since native agent lwps + * would presumably be making native system calls and hence not need + * any interposition. + * + * *** General considerations + * + * One of the differences between the lx brand and the s10 + * brand, is that the s10 brand only interposes on syscalls + * that need some kind of emulation, whereas the lx brand interposes + * on _all_ system calls. Lx branded system calls that don't need + * any emulation are then redirected back to the kernel from the + * userland library via the IN_KERNEL_SYSCALL macro. The lx-syscall + * dtrace provider depends on this behavior. + * + */ + +/*ARGSUSED*/ +void +_brand_abort(int err, const char *msg, const char *file, int line) +{ + sysret_t rval; + + /* Save the error message into convenient globals */ + brand_abort_err = err; + brand_abort_msg = msg; + brand_abort_file = file; + brand_abort_line = line; + + /* kill ourselves */ + abort(); + + /* If abort() didn't work, try something stronger. */ + (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGKILL); +} + +int +brand_uucopy(const void *from, void *to, size_t size) +{ + sysret_t rval; + + if (__systemcall(&rval, SYS_uucopy + 1024, from, to, size) != 0) + return (EFAULT); + return (0); +} + +/* + * ATTENTION: uucopystr() does NOT ensure that string are null terminated! + */ +int +brand_uucopystr(const void *from, void *to, size_t size) +{ + sysret_t rval; + + if (__systemcall(&rval, SYS_uucopystr + 1024, from, to, size) != 0) + return (EFAULT); + return (0); +} + +/* + * This function is defined to be NOSYS but it won't be called from the + * the kernel since the NOSYS system calls are not enabled in the kernel. + * Thus, the only time this function is called is directly from within the + * indirect system call path. + */ +/*ARGSUSED*/ +long +brand_unimpl(sysret_t *rv, uintptr_t p1) +{ + sysret_t rval; + + /* + * We'd like to print out some kind of error message here like + * "unsupported syscall", but we can't because it's not safe to + * assume that stderr or STDERR_FILENO actually points to something + * that is a terminal, and if we wrote to those files we could + * inadvertantly write to some applications open files, which would + * be bad. + * + * Normally, if an application calls an invalid system call + * it get a SIGSYS sent to it. So we'll just go ahead and send + * ourselves a signal here. Note that this is far from ideal since + * if the application has registered a signal handler, that signal + * handler may recieve a ucontext_t as the third parameter to + * indicate the context of the process when the signal was + * generated, and in this case that context will not be what the + * application is expecting. Hence, we should probably create a + * brandsys() kernel function that can deliver the signal to us + * with the correct ucontext_t. + */ + (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGSYS); + return (ENOSYS); +} + +#if defined(__sparc) && !defined(__sparcv9) +/* + * Yuck. For 32-bit sparc applications, handle indirect system calls. + * Note that we declare this interface to use the maximum number of + * system call arguments. If we recieve a system call that uses less + * arguments, then the additional arguments will be garbage, but they + * will also be ignored so that should be ok. + */ +long +brand_indir(sysret_t *rv, int code, + uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, + uintptr_t a5, uintptr_t a6, uintptr_t a7) +{ + brand_sysent_table_t *sst = &(brand_sysent_table[code]); + + brand_assert(code < NSYSCALL); + switch (sst->st_args & NARGS_MASK) { + case 0: + return ((sst->st_callc)(rv)); + case 1: + return ((sst->st_callc)(rv, a0)); + case 2: + return ((sst->st_callc)(rv, a0, a1)); + case 3: + return ((sst->st_callc)(rv, a0, a1, a2)); + case 4: + return ((sst->st_callc)(rv, a0, a1, a2, a3)); + case 5: + return ((sst->st_callc)(rv, a0, a1, a2, a3, a4)); + case 6: + return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5)); + case 7: + return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6)); + case 8: + return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6, a7)); + } + brand_abort(0, "invalid entry in brand_sysent_table"); + return (EINVAL); +} +#endif /* __sparc && !__sparcv9 */ + +/* + * Close a libc file handle, but don't actually close the underlying + * file descriptor. + */ +static void +brand_close_fh(FILE *file) +{ + int fd, fd_new; + + if (file == NULL) + return; + + if ((fd = fileno(file)) < 0) + return; + + /* + * We're a branded process but our handler isn't installed yet. We + * can't use the dup() syscall since it no longer exists. + */ + fd_new = fcntl(fd, F_DUPFD, 0); + if (fd_new == -1) + return; + + (void) fclose(file); + (void) dup2(fd_new, fd); + (void) close(fd_new); +} + +/*ARGSUSED*/ +void +brand_pre_init() +{ + int i; + + /* Sanity check our translation table return value codes */ + for (i = 0; i < NSYSCALL; i++) { + brand_sysent_table_t *est = &(brand_sysent_table[i]); + brand_assert(BIT_ONLYONESET(est->st_args & RV_MASK)); + } + + /* + * We need to shutdown all libc stdio. libc stdio normally goes to + * file descriptors, but since we're actually part of a another + * process we don't own these file descriptors and we can't make + * any assumptions about their state. + */ + brand_close_fh(stdin); + brand_close_fh(stdout); + brand_close_fh(stderr); +} + +/*ARGSUSED*/ +ulong_t +brand_post_init(int version, int argc, char *argv[], char *envp[]) +{ + sysret_t rval; + brand_proc_reg_t reg; + brand_elf_data_t sed; + auxv_t *ap; + uintptr_t *p; + int err; + + /* + * Register our syscall emulation table with the kernel. + * Note that we don't have to do invoke (syscall_number + 1024) + * until we've actually establised a syscall emulation callback + * handler address, which is what we're doing with this brand + * syscall. + */ + reg.sbr_version = version; +#ifdef __x86 + reg.sbr_handler = (caddr_t)brand_handler_table; +#else /* !__x86 */ + reg.sbr_handler = (caddr_t)brand_handler; +#endif /* !__x86 */ + + if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, ®)) != 0) { + brand_abort(err, "Failed to brand current process"); + + /*NOTREACHED*/ + } + + /* Get data about the executable we're running from the kernel. */ + if ((err = __systemcall(&rval, SYS_brand + 1024, + B_ELFDATA, (void *)&sed)) != 0) { + brand_abort(err, + "Failed to get required brand ELF data from the kernel"); + /*NOTREACHED*/ + } + + /* + * Find the aux vector on the stack. + */ + p = (uintptr_t *)envp; + while (*p != NULL) + p++; + + /* + * p is now pointing at the 0 word after the environ pointers. + * After that is the aux vectors. + * + * The aux vectors are currently pointing to the brand emulation + * library and associated linker. We're going to change them to + * point to the brand executable and associated linker (or to no + * linker for static binaries). This matches the process data + * stored within the kernel and visible from /proc, which was + * all setup in sn1_elfexec(). We do this so that when a debugger + * attaches to the process it sees the process as a normal solaris + * process, this brand emulation library and everything on it's + * link map will not be visible, unless our librtld_db plugin + * is used. Note that this is very different from how Linux + * branded processes are implemented within lx branded zones. + * In that situation, the primary linkmap of the process is the + * brand emulation libraries linkmap, not the Linux applications + * linkmap. + * + * We also need to clear the AF_SUN_NOPLM flag from the AT_SUN_AUXFLAGS + * aux vector. This flag told our linker that we don't have a + * primary link map. Now that our linker is done initializing, we + * want to clear this flag before we transfer control to the + * applications copy of the linker, since we want that linker to have + * a primary link map which will be the link map for the application + * we're running. + */ + p++; + for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) { + switch (ap->a_type) { + case AT_BASE: + /* Hide AT_BASE if static binary */ + if (sed.sed_base == NULL) { + ap->a_type = AT_IGNORE; + ap->a_un.a_val = NULL; + } else { + ap->a_un.a_val = sed.sed_base; + } + break; + case AT_ENTRY: + ap->a_un.a_val = sed.sed_entry; + break; + case AT_PHDR: + ap->a_un.a_val = sed.sed_phdr; + break; + case AT_PHENT: + ap->a_un.a_val = sed.sed_phent; + break; + case AT_PHNUM: + ap->a_un.a_val = sed.sed_phnum; + break; + case AT_SUN_AUXFLAGS: + ap->a_un.a_val &= ~AF_SUN_NOPLM; + break; + case AT_SUN_EMULATOR: + /* + * ld.so.1 inspects AT_SUN_EMULATOR to see if + * if it is the linker for the brand emulation + * library. Hide AT_SUN_EMULATOR, as the + * linker we are about to jump to is the linker + * for the binary. + */ + ap->a_type = AT_IGNORE; + ap->a_un.a_val = NULL; + break; + case AT_SUN_LDDATA: + /* Hide AT_SUN_LDDATA if static binary */ + if (sed.sed_lddata == NULL) { + ap->a_type = AT_IGNORE; + ap->a_un.a_val = NULL; + } else { + ap->a_un.a_val = sed.sed_lddata; + } + break; + default: + break; + } + } + + return (sed.sed_ldentry); +} diff --git a/usr/src/lib/brand/sn1/sn1_brand/common/offsets.in b/usr/src/lib/brand/shared/brand/common/offsets.in index 2897555874..ec47a6adca 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/common/offsets.in +++ b/usr/src/lib/brand/shared/brand/common/offsets.in @@ -1,6 +1,5 @@ \ -\ Copyright 2008 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. +\ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. \ \ CDDL HEADER START \ diff --git a/usr/src/lib/brand/shared/brand/i386/Makefile b/usr/src/lib/brand/shared/brand/i386/Makefile new file mode 100644 index 0000000000..b049d76f71 --- /dev/null +++ b/usr/src/lib/brand/shared/brand/i386/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +ISASRCDIR = . + +include ../Makefile.com + +install: all diff --git a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_crt.s b/usr/src/lib/brand/shared/brand/i386/crt.s index d237aed543..ed1ec1e18a 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_crt.s +++ b/usr/src/lib/brand/shared/brand/i386/crt.s @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> @@ -40,7 +39,7 @@ _start(void) * This platform specific assembly entry point exists just to invoke * the common brand library startup routine. That routine expects to * be called with the following arguments: - * s10_init(int argc, char *argv[], char *envp[]) + * brand_init(int argc, char *argv[], char *envp[]) * * There are no arguments explicitly passed to this entry point, * routine, but we do know how our initial stack has been setup by @@ -70,7 +69,7 @@ _start(void) pushl %ecx / push envp (3rd param) pushl %ebx / push argv (2nd param) pushl %eax / push argc (1st param) - call s10_init + call brand_init /*NOTREACHED*/ SET_SIZE(_start) diff --git a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s b/usr/src/lib/brand/shared/brand/i386/handler.s index 66bef79ad1..f2e51ac367 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_handler.s +++ b/usr/src/lib/brand/shared/brand/i386/handler.s @@ -20,18 +20,17 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ -#include <sn1_misc.h> +#include <brand_misc.h> /* * Each JMP must occupy 16 bytes */ #define JMP \ - pushl $_CONST(. - sn1_handler_table); \ - jmp sn1_handler; \ + pushl $_CONST(. - brand_handler_table); \ + jmp brand_handler; \ .align 16; #define JMP4 JMP; JMP; JMP; JMP @@ -42,11 +41,11 @@ #if defined(lint) void -sn1_handler_table(void) +brand_handler_table(void) {} void -sn1_handler(void) +brand_handler(void) { } @@ -59,9 +58,9 @@ sn1_handler(void) * entries. */ .align 16 - ENTRY_NP(sn1_handler_table) + ENTRY_NP(brand_handler_table) JMP256 - SET_SIZE(sn1_handler_table) + SET_SIZE(brand_handler_table) #define PIC_SETUP(r) \ call 9f; \ @@ -77,7 +76,7 @@ sn1_handler(void) * %esp+0 | syscall number | * -------------------------------------- */ - ENTRY_NP(sn1_handler) + ENTRY_NP(brand_handler) pushl %ebp /* allocate a stack frame */ movl %esp, %ebp @@ -104,11 +103,11 @@ sn1_handler(void) movl %ecx, EH_LOCALS_GREG(ESP)(%ebp) /* - * The kernel drops us into the middle of the sn1_handle_table + * The kernel drops us into the middle of the brand_handle_table * above that then pushes that table offset onto the stack, and calls - * into sn1_handler. That offset indicates the system call number while - * %eax holds the return address for the system call. We replace the - * value on the stack with the return address, and use the value to + * into brand_handler. That offset indicates the system call number + * while %eax holds the return address for the system call. We replace + * the value on the stack with the return address, and use the value to * compute the system call number by dividing by the table entry size. */ xchgl CPTRSIZE(%ebp), %eax /* swap JMP table offset and ret addr */ @@ -121,13 +120,13 @@ sn1_handler(void) * because a "sub" operation can modify flags and we wanted to * save the flags into the gregset_t above before they get modified. * - * Our stack frame format is documented in sn1_misc.h. + * Our stack frame format is documented in brand_misc.h. */ subl $EH_LOCALS_SIZE, %esp /* Look up the system call's entry in the sysent table */ PIC_SETUP(%ecx) - movl sn1_sysent_table@GOT(%ecx), %edx /* %edx = sysent_table */ + movl brand_sysent_table@GOT(%ecx), %edx /* %edx = sysent_table */ shll $3, %eax /* each entry is 8 bytes */ add %eax, %edx /* %edx = sysent entry address */ @@ -164,7 +163,7 @@ sn1_handler(void) movl %ecx, EH_ARGS_OFFSET(0)(%esp) /* arg0 == sysret_t ptr */ /* invoke the emulation routine */ - ALTENTRY(sn1_handler_savepc) + ALTENTRY(brand_handler_savepc) call *(%edx) /* call emulation routine */ /* restore scratch registers */ @@ -190,7 +189,7 @@ return: movl %ebp, %esp /* restore stack */ popl %ebp ret /* ret to instr after syscall */ - SET_SIZE(sn1_handler) + SET_SIZE(brand_handler) #endif /* lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_runexe.s b/usr/src/lib/brand/shared/brand/i386/runexe.s index 8e9eec3f6d..b7e0408bf2 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_runexe.s +++ b/usr/src/lib/brand/shared/brand/i386/runexe.s @@ -20,18 +20,17 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> -#include <sn1_misc.h> +#include <brand_misc.h> #if defined(lint) /*ARGSUSED*/ void -sn1_runexe(void *argv, ulong_t entry) +brand_runexe(void *argv, ulong_t entry) { } @@ -52,7 +51,7 @@ sn1_runexe(void *argv, ulong_t entry) * frame pointers to their values when this processes first started * execution. */ - ENTRY_NP(sn1_runexe) + ENTRY_NP(brand_runexe) movl 4(%esp), %eax / %eax = &argv[0] movl 8(%esp), %ebx / Brand app entry point in %ebx @@ -76,5 +75,5 @@ sn1_runexe(void *argv, ulong_t entry) /* * target will never return. */ - SET_SIZE(sn1_runexe) + SET_SIZE(brand_runexe) #endif /* lint */ diff --git a/usr/src/lib/brand/shared/brand/sparc/Makefile b/usr/src/lib/brand/shared/brand/sparc/Makefile new file mode 100644 index 0000000000..89efaf5adc --- /dev/null +++ b/usr/src/lib/brand/shared/brand/sparc/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +ISASRCDIR = . + +include ../Makefile.com + +ASFLAGS += -xarch=v8plus ${AS_PICFLAGS} + +install: all diff --git a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_crt.s b/usr/src/lib/brand/shared/brand/sparc/crt.s index e4931d67b3..7845f1a7c6 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_crt.s +++ b/usr/src/lib/brand/shared/brand/sparc/crt.s @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> @@ -42,7 +41,7 @@ _start(void) * This platform specific assembly entry point exists just to invoke * the common brand library startup routine. That routine expects to * be called with the following arguments: - * sn1_init(int argc, char *argv[], char *envp[]) + * brand_init(int argc, char *argv[], char *envp[]) * * There are no arguments explicitly passed to this entry point, * routine, but we do know how our initial stack has been setup by @@ -72,7 +71,7 @@ _start(void) sll %l0, CPTRSHIFT, %l0 ! multiply argc by pointer size add %o1, %l0, %o2 ! and add to argv to get first env ptr - call sn1_init + call brand_init nop /*NOTREACHED*/ diff --git a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_handler.s b/usr/src/lib/brand/shared/brand/sparc/handler.s index 4d70ed5e68..8bea770587 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_handler.s +++ b/usr/src/lib/brand/shared/brand/sparc/handler.s @@ -19,16 +19,15 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ -#include <s10_misc.h> +#include <brand_misc.h> #if defined(lint) void -s10_handler(void) +brand_handler(void) { } @@ -66,13 +65,13 @@ s10_handler(void) * %g5 should contain the address immediately after the trap * instruction. */ - ENTRY_NP(s10_handler) + ENTRY_NP(brand_handler) /* * 64-bit sparc may need to save 3 parameters on the stack. * 32-bit sparc may need to save 4 parameters on the stack. * - * Our stack frame format is documented in s10_misc.h. + * Our stack frame format is documented in brand_misc.h. */ save %sp, -SA(MINFRAME + EH_LOCALS_SIZE), %sp @@ -113,7 +112,7 @@ s10_handler(void) * and obtain the address of the proper emulation routine (%l2). */ mov %g1, %l5 /* save syscall number */ - GET_SYM_ADDR(%l1, %l2, s10_sysent_table) + GET_SYM_ADDR(%l1, %l2, brand_sysent_table) mov %l5, %g1 /* restore syscall number */ sll %g1, (1 + CLONGSHIFT), %l2 /* Each entry has 2 longs */ add %l2, %l1, %l2 /* index to proper entry */ @@ -186,7 +185,7 @@ args_copied: * * invoke the emulation routine. */ - ALTENTRY(s10_handler_savepc) + ALTENTRY(brand_handler_savepc) call %l2 add %sp, EH_LOCALS_SYSRET, %o0 /* arg0 == sysret_t ptr */ @@ -219,7 +218,7 @@ return: ldn [%sp + EH_LOCALS_GREG(REG_nPC)], %g5 jmp %g5 restore /* delay slot */ - SET_SIZE(s10_handler) + SET_SIZE(brand_handler) #endif /* !lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_runexe.s b/usr/src/lib/brand/shared/brand/sparc/runexe.s index f18b441105..b29c416122 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_runexe.s +++ b/usr/src/lib/brand/shared/brand/sparc/runexe.s @@ -20,24 +20,23 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> -#include <s10_misc.h> +#include <brand_misc.h> #if defined(lint) /*ARGSUSED*/ void -s10_runexe(void *argv, ulong_t entry) +brand_runexe(void *argv, ulong_t entry) { } #else /* lint */ .section ".text" - ENTRY_NP(s10_runexe) + ENTRY_NP(brand_runexe) /* * Prepare to jump to the target program we actually want to run. * If this program is dynamically linked then we'll be jumping to @@ -78,5 +77,5 @@ s10_runexe(void *argv, ulong_t entry) /* * target will never return. */ - SET_SIZE(s10_runexe) + SET_SIZE(brand_runexe) #endif /* lint */ diff --git a/usr/src/lib/brand/shared/brand/sparcv9/Makefile b/usr/src/lib/brand/shared/brand/sparcv9/Makefile new file mode 100644 index 0000000000..82473698ab --- /dev/null +++ b/usr/src/lib/brand/shared/brand/sparcv9/Makefile @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +ISASRCDIR = ../sparc + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +ASFLAGS_$(CURTYPE) += ${AS_PICFLAGS} + +install: all + echo $(PICS) diff --git a/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h b/usr/src/lib/brand/shared/brand/sys/brand_misc.h index 7a420b168c..483c8976f1 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/sys/sn1_misc.h +++ b/usr/src/lib/brand/shared/brand/sys/brand_misc.h @@ -19,12 +19,11 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ -#ifndef _SN1_MISC_H -#define _SN1_MISC_H +#ifndef _BRAND_MISC_H +#define _BRAND_MISC_H #ifdef __cplusplus extern "C" { @@ -37,6 +36,9 @@ extern "C" { #include <sys/asm_linkage.h> #include <sys/regset.h> #include <sys/syscall.h> +#if !defined(_ASM) +#include <sys/brand.h> +#endif #include "assym.h" /* @@ -119,15 +121,28 @@ extern "C" { #define EH_LOCALS_END (EH_LOCALS_RVFLAG + CPTRSIZE) #if (EH_LOCALS_END != EH_LOCALS_END_TGT) -#error "sn1_misc.h EH_LOCALS_* macros don't add up" +#error "brand_misc.h EH_LOCALS_* macros don't add up" #endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */ /* - * The second parameter of each entry in the sn1_sysent_table + * The second parameter of each entry in the {BRAND}_sysent_table * contains the number of parameters and flags that describe the - * syscall return value encoding. See the block comments at the - * top of ../common/sn1_brand.c for more information about the - * syscall return value flags and when they should be used. + * syscall return value encoding. + * + * When declaring new syscall emulation functions, it is very important + * to to set the proper RV_* flags in the brand_sysent_table. Upon failure, + * syscall emulation fuctions should return an errno value. Upon success + * syscall emulation functions should return 0 and set the sysret_t return + * value parameters accordingly. + * + * There are five possible syscall macro wrappers used in the kernel's system + * call sysent table. These turn into the following return values: + * SYSENT_CL -> SYSENT_C or SYSENT_CI + * SYSENT_C SE_64RVAL RV_DEFAULT + * SYSENT_CI SE_32RVAL1 RV_DEFAULT + * SYSENT_2CI SE_32RVAL1|SE_32RVAL2 RV_32RVAL2 + * SYSENT_AP SE_64RVAL RV_64RVAL + * */ #define NARGS_MASK 0x000000FF /* Mask for syscalls argument count */ #define RV_MASK 0x0000FF00 /* Mask for return value flags */ @@ -143,27 +158,70 @@ extern "C" { * emit messages to random file descriptors, and second localizing a message * requires allocating memory and we can't do that either. */ -#define sn1_assert(ex) (void)((ex) || \ - (_sn1_abort(0, #ex, __FILE__, __LINE__), 0)) -#define sn1_abort(err, msg) _sn1_abort((err), (msg), __FILE__, __LINE__) +#define brand_assert(ex) (void)((ex) || \ + (_brand_abort(0, #ex, __FILE__, __LINE__), 0)) +#define brand_abort(err, msg) _brand_abort((err), (msg), __FILE__, __LINE__) +#define EMULATE(cb, args) { (sysent_cb_t)(cb), (args) } +#define NOSYS EMULATE(brand_unimpl, (0 | RV_DEFAULT)) + +typedef long (*sysent_cb_t)(); +typedef struct brand_sysent_table { + sysent_cb_t st_callc; + uintptr_t st_args; +} brand_sysent_table_t; + +/* + * These macros invoke a brandsys subcommand, B_TRUSS_POINT, used to expose + * a call to an interpositioned syscall that would have otherwise gone + * unnoticed by truss(1) because the interpositioned system call did not call + * any system calls before returning. + */ +#define B_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \ + __systemcall(rval, SYS_brand + 1024, \ + B_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \ + (a4)) + +#define B_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \ + B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0) + +#define B_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \ + B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0) + +#define B_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \ + B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0) + +#define B_TRUSS_POINT_1(rval, syscall_num, err, a0) \ + B_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0) + +#define B_TRUSS_POINT_0(rval, syscall_num, err) \ + B_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0) /* - * From sn1_runexe.s + * From runexe.s */ -extern void sn1_runexe(void *, ulong_t); +extern void brand_runexe(void *, ulong_t); /* - * From sn1_handler.s + * From handler.s */ -extern void sn1_handler_table(void); -extern void sn1_handler(void); -extern void sn1_error(void); -extern void sn1_success(void); +extern void brand_handler_table(void); +extern void brand_handler(void); +extern void brand_error(void); +extern void brand_success(void); /* - * From sn1_brand.c + * From brand_util.c */ -extern void _sn1_abort(int, const char *, const char *, int); +extern long brand_unimpl(sysret_t *rv, uintptr_t p1); +extern void _brand_abort(int, const char *, const char *, int); +extern int brand_uucopy(const void *, void *, size_t); +extern int brand_uucopystr(const void *, void *, size_t); +extern void brand_pre_init(); +extern ulong_t brand_post_init(int, int, char **, char **); +#if defined(__sparc) && !defined(__sparcv9) +extern long brand_indir(sysret_t *, int, uintptr_t, uintptr_t, uintptr_t, + uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +#endif /* __sparc && !__sparcv9 */ #endif /* !_ASM */ @@ -171,4 +229,4 @@ extern void _sn1_abort(int, const char *, const char *, int); } #endif -#endif /* _SN1_MISC_H */ +#endif /* _BRAND_MISC_H */ diff --git a/usr/src/lib/brand/shared/librtld_db/Makefile.com b/usr/src/lib/brand/shared/librtld_db/Makefile.com new file mode 100644 index 0000000000..dc34726f4e --- /dev/null +++ b/usr/src/lib/brand/shared/librtld_db/Makefile.com @@ -0,0 +1,76 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include $(SRC)/lib/Makefile.lib + +LIBRARY = $(BRAND)_librtld_db.a +VERS = .1 + +CSRCS = $(COBJS:%o=$(BRAND_SHARED)/librtld_db/common/%c) +SRCS = $(CSRCS) + +SRCDIR = $(BRAND_SHARED)/librtld_db/common +UTSBASE = $(SRC)/uts + +# +# ATTENTION: +# Librtl_db brand plugin libraries should NOT directly invoke any +# libproc.so interfaces or be linked against libproc. If a librtl_db +# brand plugin library uses libproc.so interfaces then it may break +# any other librtld_db consumers (like mdb) that tries to attach +# to a branded process. The only safe interfaces that the a librtld_db +# brand plugin library can use to access a target process are the +# proc_service(3PROC) apis. +# +DYNFLAGS += $(VERSREF) -M$(BRAND_SHARED)/librtld_db/common/mapfile-vers +LIBS = $(DYNLIB) +LDLIBS += -lc -lrtld_db +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT \ + -I$(SRC)/cmd/sgs/librtld_db/common \ + -I$(SRC)/cmd/sgs/include \ + -I$(SRC)/cmd/sgs/include/$(MACH) + +ROOTLIBDIR = $(ROOT)/usr/lib/brand/$(BRAND) +ROOTLIBDIR64 = $(ROOT)/usr/lib/brand/$(BRAND)/$(MACH64) + +# +# The top level Makefiles define define TEXT_DOMAIN. But librtld_db.so.1 +# isn't internationalized and this library won't be either. The only +# messages that this library can generate are messages used for debugging +# the operation of the library itself. +# +DTEXTDOM = + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +pics/%64.o: $(BRAND_SHARED)/librtld_db/common/%.c + $(COMPILE.c) -D_ELF64 $(PICFLAGS) -o $@ $< + $(POST_PROCESS_O) + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/brand/sn1/librtld_db/common/sn1_librtld_db.c b/usr/src/lib/brand/shared/librtld_db/common/brand_librtld_db.c index c4678b78ab..e428330c8f 100644 --- a/usr/src/lib/brand/sn1/librtld_db/common/sn1_librtld_db.c +++ b/usr/src/lib/brand/shared/librtld_db/common/brand_librtld_db.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <assert.h> @@ -35,8 +34,7 @@ #include <sys/types.h> #include <sys/link.h> #include <rtld_db.h> - -#include <sn1_brand.h> +#include <sys/brand.h> /* * ATTENTION: @@ -86,10 +84,10 @@ #define dummy_ldb_fini32 dummy_ldb_fini64 #define dummy_ldb_loadobj_iter32 dummy_ldb_loadobj_iter64 #define dummy_ldb_get_dyns32 dummy_ldb_get_dyns64 -#define sn1_ldb_init32 sn1_ldb_init64 -#define sn1_ldb_fini32 sn1_ldb_fini64 -#define sn1_ldb_loadobj_iter32 sn1_ldb_loadobj_iter64 -#define sn1_ldb_get_dyns32 sn1_ldb_get_dyns64 +#define brand_ldb_init32 brand_ldb_init64 +#define brand_ldb_fini32 brand_ldb_fini64 +#define brand_ldb_loadobj_iter32 brand_ldb_loadobj_iter64 +#define brand_ldb_get_dyns32 brand_ldb_get_dyns64 #endif /* _ELF64 */ #endif /* _LP64 */ @@ -135,7 +133,7 @@ static rd_helper_ops_t dummy_ldb32 = { }; static uint32_t -sn1_ldb_getauxval32(struct ps_prochandle *php, int type) +brand_ldb_getauxval32(struct ps_prochandle *php, int type) { const auxv_t *auxvp = NULL; @@ -158,18 +156,18 @@ sn1_ldb_getauxval32(struct ps_prochandle *php, int type) * library is always linked against the native linker, and when the * process was first executed we saved off a pointer to the brand linkers * rdebug structure in one of our brand specific aux vectors, - * AT_SUN_BRAND_SN1_LDDATA. So we'll just look that up here. + * AT_SUN_BRAND_COMMON_LDDATA. So we'll just look that up here. */ /*ARGSUSED*/ static rd_helper_data_t -sn1_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) +brand_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) { struct rd_agent *rap_new; uint32_t lddata_addr; int rd_dmodel; if (ps_pdmodel(php, &rd_dmodel) != PS_OK) { - ps_plog("sn1_ldb_init: lookup of data model failed"); + ps_plog("brand_ldb_init: lookup of data model failed"); return (NULL); } #ifdef _ELF64 @@ -178,12 +176,12 @@ sn1_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) assert(rd_dmodel == PR_MODEL_ILP32); #endif /* !_ELF64 */ - lddata_addr = sn1_ldb_getauxval32(php, AT_SUN_BRAND_SN1_LDDATA); + lddata_addr = brand_ldb_getauxval32(php, AT_SUN_BRAND_COMMON_LDDATA); if (lddata_addr == (uint32_t)-1) { - ps_plog("sn1_ldb_init: no LDDATA found in aux vector"); + ps_plog("brand_ldb_init: no LDDATA found in aux vector"); return (NULL); } - ps_plog("sn1_ldb_init: found LDDATA auxv ld.so.1 data seg " + ps_plog("brand_ldb_init: found LDDATA auxv ld.so.1 data seg " "at: 0x%p", lddata_addr); /* @@ -203,7 +201,7 @@ sn1_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) * that we want to use happy. */ if ((rap_new = calloc(sizeof (*rap_new), 1)) == NULL) { - ps_plog("sn1_ldb_init: can't allocate memory"); + ps_plog("brand_ldb_init: can't allocate memory"); return (NULL); } rap_new->rd_dmodel = rd_dmodel; @@ -231,31 +229,31 @@ sn1_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) * rd_flags, rd_rdebugvers, rd_rtlddbpriv */ if (validate_rdebug32(rap_new) != RD_OK) { - ps_plog("sn1_ldb_init: can't find valid r_debug data"); + ps_plog("brand_ldb_init: can't find valid r_debug data"); free(rap_new); return (NULL); } - ps_plog("sn1_ldb_init: finished, helper_data=0x%p", rap_new); + ps_plog("brand_ldb_init: finished, helper_data=0x%p", rap_new); return ((rd_helper_data_t)rap_new); } static void -sn1_ldb_fini32(rd_helper_data_t rhd) +brand_ldb_fini32(rd_helper_data_t rhd) { struct rd_agent *rap = (struct rd_agent *)rhd; - ps_plog("lx_ldb_fini: cleaning up sn1 helper"); + ps_plog("brand_ldb_fini: cleaning up brand helper"); free(rap); } /*ARGSUSED*/ static int -sn1_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data) +brand_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data) { struct rd_agent *rap = (struct rd_agent *)rhd; int err; - ps_plog("sn1_ldb_loadobj_iter(helper_data=0x%p)", rhd); + ps_plog("brand_ldb_loadobj_iter(helper_data=0x%p)", rhd); assert(rap->rd_psp == php); RDAGLOCK(rap); /* @@ -266,21 +264,21 @@ sn1_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data) */ err = _rd_loadobj_iter32(rap, cb, client_data); RDAGUNLOCK(rap); - ps_plog("sn1_ldb_loadobj_iter: finished, err = %d", err); + ps_plog("brand_ldb_loadobj_iter: finished, err = %d", err); return (err); } /*ARGSUSED*/ static rd_err_e -sn1_ldb_get_dyns32(rd_helper_data_t rhd, +brand_ldb_get_dyns32(rd_helper_data_t rhd, psaddr_t addr, void **dynpp, size_t *dynpp_sz) { struct rd_agent *rap = (struct rd_agent *)rhd; int err; - ps_plog("sn1_ldb_get_dyns(helper_data=0x%p)", rhd); + ps_plog("brand_ldb_get_dyns(helper_data=0x%p)", rhd); err = _rd_get_dyns32(rap, addr, (Elf32_Dyn **)dynpp, dynpp_sz); - ps_plog("sn1_ldb_get_dyns: finished, err = %d", err); + ps_plog("brand_ldb_get_dyns: finished, err = %d", err); return (err); } @@ -292,8 +290,8 @@ sn1_ldb_get_dyns32(rd_helper_data_t rhd, */ rd_helper_ops_t RTLD_DB_BRAND_OPS = { LM_ID_NONE, - sn1_ldb_init32, - sn1_ldb_fini32, - sn1_ldb_loadobj_iter32, - sn1_ldb_get_dyns32 + brand_ldb_init32, + brand_ldb_fini32, + brand_ldb_loadobj_iter32, + brand_ldb_get_dyns32 }; diff --git a/usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers b/usr/src/lib/brand/shared/librtld_db/common/mapfile-vers index 4f3ef01e3c..571267a133 100644 --- a/usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers +++ b/usr/src/lib/brand/shared/librtld_db/common/mapfile-vers @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # # diff --git a/usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers.64 b/usr/src/lib/brand/shared/librtld_db/common/mapfile-vers.64 index 51e0c2c3cc..ca437818fc 100644 --- a/usr/src/lib/brand/sn1/librtld_db/common/mapfile-vers.64 +++ b/usr/src/lib/brand/shared/librtld_db/common/mapfile-vers.64 @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # # diff --git a/usr/src/lib/brand/shared/zone/Makefile b/usr/src/lib/brand/shared/zone/Makefile new file mode 100644 index 0000000000..9a768d62dd --- /dev/null +++ b/usr/src/lib/brand/shared/zone/Makefile @@ -0,0 +1,54 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +PROG=query +SHARED= common.ksh query uninstall.ksh +CLOBBERFILES= query + +include $(SRC)/cmd/Makefile.cmd +include ../../Makefile.brand + +$(ROOTSHAREDDIR)/common.ksh := FILEMODE = 0444 +$(ROOTSHAREDDIR)/uninstall.ksh := FILEMODE = 0444 + +CLOBBERFILES= $(ROOTSHARED) $(PROG) + +POFILES= common.po query.po uninstall.po +POFILE= shared.po + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +all: $(PROG) + +install: $(ROOTSHARED) + +clean: + -$(RM) $(PROG) $(POFILES) + +lint: + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/lib/brand/shared/common.ksh b/usr/src/lib/brand/shared/zone/common.ksh index 95abe86351..d9bc1abbef 100644 --- a/usr/src/lib/brand/shared/common.ksh +++ b/usr/src/lib/brand/shared/zone/common.ksh @@ -18,8 +18,7 @@ # # CDDL HEADER END # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # # diff --git a/usr/src/lib/brand/shared/query.ksh b/usr/src/lib/brand/shared/zone/query.ksh index fe79f1bc71..480fbda955 100644 --- a/usr/src/lib/brand/shared/query.ksh +++ b/usr/src/lib/brand/shared/zone/query.ksh @@ -20,8 +20,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # PATH=/usr/bin:/usr/sbin diff --git a/usr/src/lib/brand/shared/uninstall.ksh b/usr/src/lib/brand/shared/zone/uninstall.ksh index 0ad45a790d..468a7ed92f 100644 --- a/usr/src/lib/brand/shared/uninstall.ksh +++ b/usr/src/lib/brand/shared/zone/uninstall.ksh @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # # diff --git a/usr/src/lib/brand/sn1/librtld_db/Makefile.com b/usr/src/lib/brand/sn1/librtld_db/Makefile.com index 171f23bb92..37c809c301 100644 --- a/usr/src/lib/brand/sn1/librtld_db/Makefile.com +++ b/usr/src/lib/brand/sn1/librtld_db/Makefile.com @@ -19,62 +19,11 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # -LIBRARY = sn1_librtld_db.a -VERS = .1 -COBJS = sn1_librtld_db.o +COBJS = brand_librtld_db.o OBJECTS = $(COBJS) $(COBJS64) -include $(SRC)/lib/Makefile.lib include ../../Makefile.sn1 - -CSRCS = $(COBJS:%o=../common/%c) -SRCS = $(CSRCS) - -SRCDIR = ../common -UTSBASE = $(SRC)/uts - -# -# ATTENTION: -# Librtl_db brand plugin libraries should NOT directly invoke any -# libproc.so interfaces or be linked against libproc. If a librtl_db -# brand plugin library uses libproc.so interfaces then it may break -# any other librtld_db consumers (like mdb) that tries to attach -# to a branded process. The only safe interfaces that the a librtld_db -# brand plugin library can use to access a target process are the -# proc_service(3PROC) apis. -# -DYNFLAGS += $(VERSREF) -M../common/mapfile-vers -LIBS = $(DYNLIB) -LDLIBS += -lc -lrtld_db -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -I../ -I$(UTSBASE)/common/brand/sn1 \ - -I$(SRC)/cmd/sgs/librtld_db/common \ - -I$(SRC)/cmd/sgs/include \ - -I$(SRC)/cmd/sgs/include/$(MACH) - -ROOTLIBDIR = $(ROOT)/usr/lib/brand/sn1 -ROOTLIBDIR64 = $(ROOT)/usr/lib/brand/sn1/$(MACH64) - -# -# The top level Makefiles define define TEXT_DOMAIN. But librtld_db.so.1 -# isn't internationalized and this library won't be either. The only -# messages that this library can generate are messages used for debugging -# the operation of the library itself. -# -DTEXTDOM = - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -pics/%64.o: ../common/%.c - $(COMPILE.c) -D_ELF64 $(PICFLAGS) -o $@ $< - $(POST_PROCESS_O) - -include $(SRC)/lib/Makefile.targ +include $(BRAND_SHARED)/librtld_db/Makefile.com diff --git a/usr/src/lib/brand/sn1/librtld_db/amd64/Makefile b/usr/src/lib/brand/sn1/librtld_db/amd64/Makefile index d1b2579c29..2f81f1df30 100644 --- a/usr/src/lib/brand/sn1/librtld_db/amd64/Makefile +++ b/usr/src/lib/brand/sn1/librtld_db/amd64/Makefile @@ -19,16 +19,15 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # -COBJS64 = sn1_librtld_db64.o +COBJS64 = brand_librtld_db64.o include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 CLOBBERFILES = $(ROOTLIBDIR64)/$(DYNLIB) -DYNFLAGS += -M../common/mapfile-vers.64 +DYNFLAGS += -M$(BRAND_SHARED)/librtld_db/common/mapfile-vers.64 install: all $(ROOTLIBS64) diff --git a/usr/src/lib/brand/sn1/librtld_db/sparcv9/Makefile b/usr/src/lib/brand/sn1/librtld_db/sparcv9/Makefile index d1b2579c29..2f81f1df30 100644 --- a/usr/src/lib/brand/sn1/librtld_db/sparcv9/Makefile +++ b/usr/src/lib/brand/sn1/librtld_db/sparcv9/Makefile @@ -19,16 +19,15 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # -COBJS64 = sn1_librtld_db64.o +COBJS64 = brand_librtld_db64.o include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 CLOBBERFILES = $(ROOTLIBDIR64)/$(DYNLIB) -DYNFLAGS += -M../common/mapfile-vers.64 +DYNFLAGS += -M$(BRAND_SHARED)/librtld_db/common/mapfile-vers.64 install: all $(ROOTLIBS64) diff --git a/usr/src/lib/brand/sn1/sn1_brand/Makefile.com b/usr/src/lib/brand/sn1/sn1_brand/Makefile.com index 4059dff444..4d26a454b0 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/Makefile.com +++ b/usr/src/lib/brand/sn1/sn1_brand/Makefile.com @@ -19,18 +19,14 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # LIBRARY = sn1_brand.a VERS = .1 COBJS = sn1_brand.o -ASOBJS = sn1_crt.o sn1_handler.o sn1_runexe.o -OFFSETS_SRC = ../common/offsets.in -OFFSETS_H = assym.h -OBJECTS = $(COBJS) $(ASOBJS) -CLOBBERFILES += $(OFFSETS_H) +ASOBJS = crt.o handler.o runexe.o brand_util.o +OBJECTS = $(COBJS) include ../../Makefile.sn1 include $(SRC)/lib/Makefile.lib @@ -40,19 +36,8 @@ UTSBASE = $(SRC)/uts LIBS = $(DYNLIB) CSRCS = $(COBJS:%o=../common/%c) -ASSRCS = $(ASOBJS:%o=$(ISASRCDIR)/%s) -SRCS = $(CSRCS) $(ASSRCS) - -# -# Ugh, this is a gross hack. Our assembly routines uses lots of defines -# to simplify variable access. All these defines work fine for amd64 -# compiles because when compiling for amd64 we use the GNU assembler, -# gas. For 32-bit code we use the Sun assembler, as. Unfortunatly -# as does not handle certian constructs that gas does. So rather than -# make our code less readable, we'll just use gas to compile our 32-bit -# code as well. -# -i386_AS = $(amd64_AS) +SHAREDOBJS = $(ASOBJS:%o=$(ISAOBJDIR)/%o) +SRCS = $(CSRCS) # # Note that the architecture specific makefiles MUST update DYNFLAGS to @@ -76,30 +61,20 @@ i386_AS = $(amd64_AS) # regular and suid binaries). # NATIVE_DIR = /.SUNWnative -CPPFLAGS += -D_REENTRANT -U_ASM -I. -I../sys -I$(UTSBASE)/common/brand/sn1 +CPPFLAGS += -D_REENTRANT -U_ASM \ + -I. -I$(BRAND_SHARED)/brand/sys -I$(UTSBASE)/common/brand/sn1 CFLAGS += $(CCVERBOSE) -ASFLAGS = -P $(ASFLAGS_$(CURTYPE)) -D_ASM -I. -I../sys DYNFLAGS += $(DYNFLAGS_$(CLASS)) DYNFLAGS += $(BLOCAL) $(ZNOVERSION) -Wl,-e_start #DYNFLAGS += -R$(NATIVE_DIR)/lib -R$(NATIVE_DIR)/usr/lib LDLIBS += -lc -lmapmalloc +$(LIBS):= PICS += $(SHAREDOBJS) + .KEEP_STATE: all: $(LIBS) lint: lintcheck -# -# build the offset header before trying to compile any files. (it's included -# by sn1_misc.h, so it's needed for all objects, not just assembly ones.) -# -$(OBJECTS:%=pics/%): $(OFFSETS_H) -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) $(CTF_FLAGS) < $(OFFSETS_SRC) >$@ - -pics/%.o: $(ISASRCDIR)/%.s - $(COMPILE.s) -o $@ $< - $(POST_PROCESS_O) - include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/brand/sn1/sn1_brand/amd64/Makefile b/usr/src/lib/brand/sn1/sn1_brand/amd64/Makefile index e82bb23093..5b3c3c0ba3 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/amd64/Makefile +++ b/usr/src/lib/brand/sn1/sn1_brand/amd64/Makefile @@ -19,16 +19,17 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # lib/brand/sn1/amd64/Makefile -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/amd64/pics/ include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 +CPPFLAGS += -I$(BRAND_SHARED)/brand/amd64 + # # see ../Makefile.com for why we MUST explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_crt.s b/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_crt.s deleted file mode 100644 index 48dbe8e104..0000000000 --- a/usr/src/lib/brand/sn1/sn1_brand/amd64/sn1_crt.s +++ /dev/null @@ -1,73 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> - -#if defined(lint) - -void -_start(void) -{ -} - -#else /* lint */ - /* - * Initial entry point for the brand emulation library. - * - * This platform specific assembly entry point exists just to invoke - * the common brand library startup routine. That routine expects to - * be called with the following arguments: - * sn1_init(int argc, char *argv[], char *envp[]) - * - * There are no arguments explicitly passed to this entry point, - * routine, but we do know how our initial stack has been setup by - * the kernel. The stack format is documented in: - * usr/src/cmd/sgs/rtld/amd64/boot.s - * - * So this routine will troll through the stack to setup the argument - * values for the common brand library startup routine and then invoke - * it. This routine is modeled after the default crt1.s`_start() - * routines. - */ - ENTRY_NP(_start) - - /* Make stack traces look pretty, build a fake stack frame. */ - pushq $0 / Build a stack frame. retpc = NULL - pushq $0 / fp = NULL - movq %rsp, %rbp / first stack frame - - /* - * Calculate the location of the envp array by adding the size of - * the argv array to the start of the argv array. - */ - movq 16(%rbp), %rdi / argc in %rax (1st param) - leaq 24(%rbp), %rsi / &argv[0] in %rbx (2nd param) - leaq 32(%rbp,%rdi,8), %rdx / envp in %rcx (3rd param) - call sn1_init - - /*NOTREACHED*/ - SET_SIZE(_start) -#endif /* lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c b/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c index 45a3213987..e3941063d2 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c +++ b/usr/src/lib/brand/sn1/sn1_brand/common/sn1_brand.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <errno.h> @@ -40,115 +39,14 @@ #include <fcntl.h> #include <sn1_brand.h> -#include <sn1_misc.h> +#include <brand_misc.h> /* - * Principles of emulation 101. - * - * - * *** Setting errno - * - * Just don't do it. This emulation library is loaded onto a - * seperate link map from the application who's address space we're - * running in. We have our own private copy of libc, so there for, - * the errno value accessible from here is is also private and changing - * it will not affect any errno value that the processes who's address - * space we are running in will see. To return an error condition we - * should return the negated errno value we'd like the system to return. - * For more information about this see the comment in sn1_handler(). - * Basically, when we return to the caller that initiated the system - * call it's their responsibility to set errno. - * - * - * *** Recursion Considerations - * - * When emulating system calls we need to be very careful about what - * library calls we invoke. Library calls should be kept to a minimum. - * One issue is that library calls can invoke system calls, so if we're - * emulating a system call and we invoke a library call that depends on - * that system call we will probably enter a recursive loop, which would - * be bad. - * - * - * *** Return Values. - * - * When declaring new syscall emulation functions, it is very important - * to to set the proper RV_* flags in the sn1_sysent_table. Upon failure, - * syscall emulation fuctions should return an errno value. Upon success - * syscall emulation functions should return 0 and set the sysret_t return - * value parameters accordingly. - * - * - * *** Agent lwp considerations - * - * It is currently impossible to do any emulation for these system call - * when they are being invoked on behalf of an agent lwp. To understand why - * it's impossible you have to understand how agent lwp syscalls work. - * - * The agent lwp syscall process works as follows: - * 1 The controlling process stops the target. - * 2 The controlling process injects an agent lwp which is also stopped. - * This agent lwp assumes the userland stack and register values - * of another stopped lwp in the current process. - * 3 The controlling process configures the agent lwp to start - * executing the requested system call. - * 4 The controlling process configure /proc to stop the agent lwp when - * it enters the requested system call. - * 5 The controlling processes allows the agent lwp to start executing. - * 6 The agent lwp traps into the kernel to perform the requested system - * call and immediately stop. - * 7 The controlling process copies all the arguments for the requested - * system call onto the agent lwp's stack. - * 8 The controlling process configures /proc to stop the agent lwp - * when it completes the requested system call. - * 9 The controlling processes allows the agent lwp to start executing. - * 10 The agent lwp executes the system call and then stop before returning - * to userland. - * 11 The controlling process copies the return value and return arguments - * back from the agent lwps stack. - * 12 The controlling process destroys the agent lwp and restarts - * the target process. - * - * The fundamental problem is that when the agent executes the request - * system call in step 5, if we're emulating that system call then the - * lwp is redirected back to our emulation layer without blocking - * in the kernel. But our emulation layer can't access the arguments - * for the system call because they haven't been copied to the stack - * yet and they still only exist in the controlling processes address - * space. This prevents us from being able to do any emulation of - * agent lwp system calls. Hence, currently our brand trap interposition - * callback (sn1_brand_syscall_callback_common) will detect if a system - * call is being made by an agent lwp, and if this is the case it will - * never redirect the system call to this emulation library. - * - * In the future, if this proves to be a problem the the easiest solution - * would probably be to replace the branded versions of these application - * with their native counterparts. Ie, truss, plimit, and pfiles could be - * replace with wrapper scripts that execute the native versions of these - * applications. In the case of plimit and pfiles this should be pretty - * strait forward. Truss would probably be more tricky since it can - * execute applications which would be branded applications, so in that - * case it might be necessary to create a loadable library which could - * be LD_PRELOADed into truss and this library would interpose on the - * exec() system call to allow truss to correctly execute branded - * processes. It should be pointed out that this solution could work - * because "native agent lwps" (ie, agent lwps created by native - * processes) can be treated differently from "branded aged lwps" (ie, - * agent lwps created by branded processes), since native agent lwps - * would presumably be making native system calls and hence not need - * any interposition. - * + * See usr/src/lib/brand/shared/brand/common/brand_util.c for general + * emulation notes. * * *** sn1 brand emulation scope considerations * - * One of the differences between the lx brand and the s8 and s9 - * brands, is that the s8 and s9 brands only interpose on syscalls - * that need some kind of emulation, where as the lx brand interposes - * on _all_ system calls. Lx branded system calls that don't need - * any emulation are then redirected back to the kernel from the - * userland library via the IN_KERNEL_SYSCALL macro. The lx-syscall - * dtrace provider depends on this behavior. - * * Given that the sn1 brand exists for testing purposes, it should * eventually be enhanced to redirect all system calls through the * brand emulation library. This will ensure the maximum testing @@ -157,126 +55,10 @@ * - Folding the sn1 brand into the native brand and only enabling * it on DEBUG builds. * - Modifying the zones test suite to use sn1 branded zones by default, - * any adapting functional test harnesses to use sn1 branded zones + * and adapting functional test harnesses to use sn1 branded zones * by default instead of native zones. */ -#define EMULATE(cb, args) { (sysent_cb_t)(cb), (args) } -#define NOSYS EMULATE(sn1_unimpl, (0 | RV_DEFAULT)) - -typedef long (*sysent_cb_t)(); -typedef struct sn1_sysent_table { - sysent_cb_t st_callc; - uintptr_t st_args; -} sn1_sysent_table_t; -sn1_sysent_table_t sn1_sysent_table[]; - -/*LINTED: static unused*/ -static volatile int sn1_abort_err; -/*LINTED: static unused*/ -static volatile const char *sn1_abort_msg; -/*LINTED: static unused*/ -static volatile const char *sn1_abort_file; -/*LINTED: static unused*/ -static volatile int sn1_abort_line; - -extern int errno; - -/*ARGSUSED*/ -void -_sn1_abort(int err, const char *msg, const char *file, int line) -{ - sysret_t rval; - - /* Save the error message into convenient globals */ - sn1_abort_err = err; - sn1_abort_msg = msg; - sn1_abort_file = file; - sn1_abort_line = line; - - /* kill ourselves */ - abort(); - - /* If abort() didn't work, try something stronger. */ - (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGKILL); -} - -/* - * This function is defined to be NOSYS but it won't be called from the - * the kernel since the NOSYS system calls are not enabled in the kernel. - * Thus, the only time this function is called is directly from within the - * indirect system call path. - */ -/*ARGSUSED*/ -static long -sn1_unimpl(sysret_t *rv, uintptr_t p1) -{ - sysret_t rval; - - /* - * We'd like to print out some kind of error message here like - * "unsupported syscall", but we can't because it's not safe to - * assume that stderr or STDERR_FILENO actually points to something - * that is a terminal, and if we wrote to those files we could - * inadvertantly write to some applications open files, which would - * be bad. - * - * Normally, if an application calls an invalid system call - * it get a SIGSYS sent to it. So we'll just go ahead and send - * ourselves a signal here. Note that this is far from ideal since - * if the application has registered a signal handler, that signal - * handler may recieve a ucontext_t as the third parameter to - * indicate the context of the process when the signal was - * generated, and in this case that context will not be what the - * application is expecting. Hence, we should probably create a - * brandsys() kernel function that can deliver the signal to us - * with the correct ucontext_t. - */ - (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGSYS); - return (ENOSYS); -} - -#if defined(__sparc) && !defined(__sparcv9) -/* - * Yuck. For 32-bit sparc applications, handle indirect system calls. - * Note that we declare this interface to use the maximum number of - * system call arguments. If we recieve a system call that uses less - * arguments, then the additional arguments will be garbage, but they - * will also be ignored so that should be ok. - */ -static long -sn1_indir(sysret_t *rv, int code, - uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, - uintptr_t a5, uintptr_t a6, uintptr_t a7) -{ - sn1_sysent_table_t *sst = &(sn1_sysent_table[code]); - - sn1_assert(code < NSYSCALL); - switch (sst->st_args & NARGS_MASK) { - case 0: - return ((sst->st_callc)(rv)); - case 1: - return ((sst->st_callc)(rv, a0)); - case 2: - return ((sst->st_callc)(rv, a0, a1)); - case 3: - return ((sst->st_callc)(rv, a0, a1, a2)); - case 4: - return ((sst->st_callc)(rv, a0, a1, a2, a3)); - case 5: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4)); - case 6: - return ((sst->st_callc)(rv, rv, a0, a1, a2, a3, a4, a5)); - case 7: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6)); - case 8: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6, a7)); - } - sn1_abort(0, "invalid entry in sn1_sysent_table"); - return (EINVAL); -} -#endif /* __sparc && !__sparcv9 */ - static long sn1_uname(sysret_t *rv, uintptr_t p1) { @@ -287,7 +69,7 @@ sn1_uname(sysret_t *rv, uintptr_t p1) return (err); rev = atoi(&un.release[2]); - sn1_assert(rev >= 10); + brand_assert(rev >= 10); (void) sprintf(un.release, "5.%d", rev - 1); if (uucopy(&un, unp, sizeof (un)) != 0) @@ -295,177 +77,18 @@ sn1_uname(sysret_t *rv, uintptr_t p1) return (0); } -/* - * Close a libc file handle, but don't actually close the underlying - * file descriptor. - */ -static void -sn1_close_fh(FILE *file) -{ - int fd, fd_new; - - if (file == NULL) - return; - - if ((fd = fileno(file)) < 0) - return; - - /* - * While we could use dup() since we're linked with the native libc, - * the dup() syscall itself no longer exists so this would be - * problematic for any brands built from sn1. - */ - fd_new = fcntl(fd, F_DUPFD, 0); - if (fd_new == -1) - return; - - (void) fclose(file); - (void) dup2(fd_new, fd); - (void) close(fd_new); -} - /*ARGSUSED*/ int -sn1_init(int argc, char *argv[], char *envp[]) +brand_init(int argc, char *argv[], char *envp[]) { - sysret_t rval; - sn1_brand_reg_t reg; - sn1_elf_data_t sed; - auxv_t *ap; - uintptr_t *p; - int i, err; - - /* Sanity check our translation table return value codes */ - for (i = 0; i < NSYSCALL; i++) { - sn1_sysent_table_t *est = &(sn1_sysent_table[i]); - sn1_assert(BIT_ONLYONESET(est->st_args & RV_MASK)); - } - - /* - * We need to shutdown all libc stdio. libc stdio normally goes to - * file descriptors, but since we're actually part of a another - * process we don't own these file descriptors and we can't make - * any assumptions about their state. - */ - sn1_close_fh(stdin); - sn1_close_fh(stdout); - sn1_close_fh(stderr); - - /* - * Register our syscall emulation table with the kernel. - * Note that we don't have to do invoke (syscall_number + 1024) - * until we've actually establised a syscall emulation callback - * handler address, which is what we're doing with this brand - * syscall. - */ - reg.sbr_version = SN1_VERSION; -#ifdef __x86 - reg.sbr_handler = (caddr_t)sn1_handler_table; -#else /* !__x86 */ - reg.sbr_handler = (caddr_t)sn1_handler; -#endif /* !__x86 */ - if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, ®)) != 0) { - sn1_abort(err, "Failed to brand current process"); - /*NOTREACHED*/ - } - - /* Get data about the executable we're running from the kernel. */ - if ((err = __systemcall(&rval, SYS_brand + 1024, - B_ELFDATA, (void *)&sed)) != 0) { - sn1_abort(err, - "Failed to get required brand ELF data from the kernel"); - /*NOTREACHED*/ - } - - /* - * Find the aux vector on the stack. - */ - p = (uintptr_t *)envp; - while (*p != NULL) - p++; + ulong_t ldentry; - /* - * p is now pointing at the 0 word after the environ pointers. - * After that is the aux vectors. - * - * The aux vectors are currently pointing to the brand emulation - * library and associated linker. We're going to change them to - * point to the brand executable and associated linker (or to no - * linker for static binaries). This matches the process data - * stored within the kernel and visible from /proc, which was - * all setup in sn1_elfexec(). We do this so that when a debugger - * attaches to the process it sees the process as a normal solaris - * process, this brand emulation library and everything on it's - * link map will not be visible, unless our librtld_db plugin - * is used. Note that this is very different from how Linux - * branded processes are implemented within lx branded zones. - * In that situation, the primary linkmap of the process is the - * brand emulation libraries linkmap, not the Linux applications - * linkmap. - * - * We also need to clear the AF_SUN_NOPLM flag from the AT_SUN_AUXFLAGS - * aux vector. This flag told our linker that we don't have a - * primary link map. Now that our linker is done initializing, we - * want to clear this flag before we transfer control to the - * applications copy of the linker, since we want that linker to have - * a primary link map which will be the link map for the application - * we're running. - */ - p++; - for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) { - switch (ap->a_type) { - case AT_BASE: - /* Hide AT_BASE if static binary */ - if (sed.sed_base == NULL) { - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - } else { - ap->a_un.a_val = sed.sed_base; - } - break; - case AT_ENTRY: - ap->a_un.a_val = sed.sed_entry; - break; - case AT_PHDR: - ap->a_un.a_val = sed.sed_phdr; - break; - case AT_PHENT: - ap->a_un.a_val = sed.sed_phent; - break; - case AT_PHNUM: - ap->a_un.a_val = sed.sed_phnum; - break; - case AT_SUN_AUXFLAGS: - ap->a_un.a_val &= ~AF_SUN_NOPLM; - break; - case AT_SUN_EMULATOR: - /* - * ld.so.1 inspects AT_SUN_EMULATOR to see if - * if it is the linker for the brand emulation - * library. Hide AT_SUN_EMULATOR, as the - * linker we are about to jump to is the linker - * for the binary. - */ - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - break; - case AT_SUN_LDDATA: - /* Hide AT_SUN_LDDATA if static binary */ - if (sed.sed_lddata == NULL) { - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - } else { - ap->a_un.a_val = sed.sed_lddata; - } - break; - default: - break; - } - } + brand_pre_init(); + ldentry = brand_post_init(SN1_VERSION, argc, argv, envp); - sn1_runexe(argv, sed.sed_ldentry); + brand_runexe(argv, ldentry); /*NOTREACHED*/ - sn1_abort(0, "sn1_runexe() returned"); + brand_abort(0, "brand_runexe() returned"); return (-1); } @@ -499,15 +122,15 @@ IN_KERNEL_SYSCALL(waitid, SYS_waitid) /* 107 */ /* * This table must have at least NSYSCALL entries in it. * - * The second parameter of each entry in the sn1_sysent_table + * The second parameter of each entry in the brand_sysent_table * contains the number of parameters and flags that describe the * syscall return value encoding. See the block comments at the * top of this file for more information about the syscall return * value flags and when they should be used. */ -sn1_sysent_table_t sn1_sysent_table[] = { +brand_sysent_table_t brand_sysent_table[] = { #if defined(__sparc) && !defined(__sparcv9) - EMULATE(sn1_indir, 9 | RV_64RVAL), /* 0 */ + EMULATE(brand_indir, 9 | RV_64RVAL), /* 0 */ #else /* !__sparc || __sparcv9 */ NOSYS, /* 0 */ #endif /* !__sparc || __sparcv9 */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/i386/Makefile b/usr/src/lib/brand/sn1/sn1_brand/i386/Makefile index e5f9fdb455..9175087c0b 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/i386/Makefile +++ b/usr/src/lib/brand/sn1/sn1_brand/i386/Makefile @@ -19,15 +19,16 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # lib/brand/sn1/i386/Makefile -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/i386/pics include ../Makefile.com +CPPFLAGS += -I$(BRAND_SHARED)/brand/i386 + # # see ../Makefile.com for why we explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_crt.s b/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_crt.s deleted file mode 100644 index f4c6e8d408..0000000000 --- a/usr/src/lib/brand/sn1/sn1_brand/i386/sn1_crt.s +++ /dev/null @@ -1,77 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> - -#if defined(lint) - -void -_start(void) -{ -} - -#else /* lint */ - /* - * Initial entry point for the brand emulation library. - * - * This platform specific assembly entry point exists just to invoke - * the common brand library startup routine. That routine expects to - * be called with the following arguments: - * sn1_init(int argc, char *argv[], char *envp[]) - * - * There are no arguments explicitly passed to this entry point, - * routine, but we do know how our initial stack has been setup by - * the kernel. The stack format is documented in: - * usr/src/cmd/sgs/rtld/i386/boot.s - * - * So this routine will troll through the stack to setup the argument - * values for the common brand library startup routine and then invoke - * it. This routine is modeled after the default crt1.s`_start() - * routines. - */ - ENTRY_NP(_start) - - /* Make stack traces look pretty, build a fake stack frame. */ - pushl $0 / retpc = NULL - pushl $0 / fp = NULL - movl %esp, %ebp / first stack frame - - /* - * Calculate the location of the envp array by adding the size of - * the argv array to the start of the argv array. - */ - movl 8(%ebp), %eax / argc in %eax - leal 12(%ebp), %ebx / &argv[0] in %ebx - leal 16(%ebp,%eax,4), %ecx / envp in %ecx - - pushl %ecx / push envp (3rd param) - pushl %ebx / push argv (2nd param) - pushl %eax / push argc (1st param) - call sn1_init - - /*NOTREACHED*/ - SET_SIZE(_start) -#endif /* lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/sparc/Makefile b/usr/src/lib/brand/sn1/sn1_brand/sparc/Makefile index 1f2a6c7f89..0ee543b052 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/sparc/Makefile +++ b/usr/src/lib/brand/sn1/sn1_brand/sparc/Makefile @@ -19,15 +19,16 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # lib/brand/sn1/sparc/Makefile -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/sparc/pics include ../Makefile.com +CPPFLAGS += -I$(BRAND_SHARED)/brand/sparc + # # see ../Makefile.com for why we MUST explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_handler.s b/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_handler.s deleted file mode 100644 index b96782c037..0000000000 --- a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_handler.s +++ /dev/null @@ -1,225 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sn1_misc.h> - -#if defined(lint) - -void -sn1_handler(void) -{ -} - -#else /* !lint */ - -#define PIC_SETUP(r) \ - mov %o7, %g1; \ -9: call 8f; \ - sethi %hi(_GLOBAL_OFFSET_TABLE_ - (9b - .)), r; \ -8: or r, %lo(_GLOBAL_OFFSET_TABLE_ - (9b - .)), r; \ - add r, %o7, r; \ - mov %g1, %o7 - -/* - * Translate a global symbol into an address. The resulting address - * is returned in the first register parameter. The second register - * is just for scratch space. - */ -#if defined(__sparcv9) -#define GET_SYM_ADDR(r1, r2, name) \ - PIC_SETUP(r1) ;\ - sethi %hi(name), r2 ;\ - or r2, %lo(name), r2 ;\ - ldn [r2 + r1], r1 -#else /* !__sparcv9 */ -#define GET_SYM_ADDR(r1, r2, name) \ - PIC_SETUP(r1); \ - ld [r1 + name], r1 -#endif /* !__sparcv9 */ - - .section ".text" - - /* - * When we get here, %g1 should contain the system call and - * %g5 should contain the address immediately after the trap - * instruction. - */ - ENTRY_NP(sn1_handler) - - /* - * 64-bit sparc may need to save 3 parameters on the stack. - * 32-bit sparc may need to save 4 parameters on the stack. - * - * Our stack frame format is documented in sn1_misc.h. - */ - save %sp, -SA(MINFRAME + EH_LOCALS_SIZE), %sp - - /* - * Save the current caller state into gregs and gwins. - * Note that this state isn't exact, %g1 and %g5 have been - * already been lost. Also, we've pushed a stack frame so - * the callers output registers are our input registers. - */ - stn %g0, [%sp + EH_LOCALS_GREG(REG_G1)] /* %g1 is lost */ - stn %g2, [%sp + EH_LOCALS_GREG(REG_G2)] - stn %g3, [%sp + EH_LOCALS_GREG(REG_G3)] - stn %g4, [%sp + EH_LOCALS_GREG(REG_G4)] - stn %g0, [%sp + EH_LOCALS_GREG(REG_G5)] /* %g5 is lost */ - stn %g6, [%sp + EH_LOCALS_GREG(REG_G6)] - stn %g7, [%sp + EH_LOCALS_GREG(REG_G7)] - stn %i0, [%sp + EH_LOCALS_GREG(REG_O0)] - stn %i1, [%sp + EH_LOCALS_GREG(REG_O1)] - stn %i2, [%sp + EH_LOCALS_GREG(REG_O2)] - stn %i3, [%sp + EH_LOCALS_GREG(REG_O3)] - stn %i4, [%sp + EH_LOCALS_GREG(REG_O4)] - stn %i5, [%sp + EH_LOCALS_GREG(REG_O5)] - stn %i6, [%sp + EH_LOCALS_GREG(REG_O6)] - stn %i7, [%sp + EH_LOCALS_GREG(REG_O7)] - sub %g5, 4, %o0 - stn %o0, [%sp + EH_LOCALS_GREG(REG_PC)] - stn %g5, [%sp + EH_LOCALS_GREG(REG_nPC)] - rd %y, %o0 - stn %o0, [%sp + EH_LOCALS_GREG(REG_Y)] -#if defined(__sparcv9) - stn %g0, [%sp + EH_LOCALS_GREG(REG_ASI)] - rd %fprs, %o0 - stn %o0, [%sp + EH_LOCALS_GREG(REG_FPRS)] -#endif /* __sparcv9 */ - - /* - * Look up the system call's entry in the sysent table - * and obtain the address of the proper emulation routine (%l2). - */ - mov %g1, %l5 /* save syscall number */ - GET_SYM_ADDR(%l1, %l2, sn1_sysent_table) - mov %l5, %g1 /* restore syscall number */ - sll %g1, (1 + CLONGSHIFT), %l2 /* Each entry has 2 longs */ - add %l2, %l1, %l2 /* index to proper entry */ - ldn [%l2], %l2 /* emulation func address */ - - /* - * Look up the system call's entry in the sysent table, - * taking into account the posibility of indirect system calls, and - * obtain the number of arguments (%l4) and return value flag (%l3). - */ -#if defined(__sparcv9) - mov %g1, %l3 /* %g1 == syscall number */ -#else /* !__sparcv9 */ - /* - * Check for indirect system calls, in which case the real syscall - * number is the first parameter to the indirect system call. - */ - cmp %g1, %g0 /* saved syscall number */ - bne,a,pt %icc, no_indir /* indirect syscall? */ - mov %g1, %l3 /* %g1 == syscall number */ - mov %i0, %l3 /* %i0 == syscall number */ -no_indir: -#endif /* !__sparcv9 */ - sll %l3, (1 + CLONGSHIFT), %l3 /* Each entry has 2 longs */ - add %l3, %l1, %l3 /* index to proper entry */ - ldn [%l3 + CPTRSIZE], %l4 /* number of args + rv flag */ - sethi %hi(RV_MASK), %l5 - or %l5, %lo(RV_MASK), %l5 - andcc %l4, %l5, %l3 /* strip out number of args*/ - andcc %l4, NARGS_MASK, %l4 /* strip out rv flag */ - - /* - * Setup arguments for our emulation call. Our input arguments, - * 0 to N, will become emulation call arguments 1 to N+1. - * %l4 == number of arguments. - */ - mov %i0, %o1 - mov %i1, %o2 - mov %i2, %o3 - mov %i3, %o4 - mov %i4, %o5 - - /* 7th argument and above get passed on the stack */ - cmp %l4, 0x6 - bl,pt %ncc, args_copied - nop - stn %i5, [%sp + EH_ARGS_OFFSET(0)] /* copy 6th syscall arg */ - cmp %l4, 0x7 - bl,pt %ncc, args_copied - nop - ldn [%fp + EH_ARGS_OFFSET(0)], %l5 /* copy 7th syscall arg */ - stn %l5, [%sp + EH_ARGS_OFFSET(1)] - cmp %l4, 0x8 - bl,pt %ncc, args_copied - nop - ldn [%fp + EH_ARGS_OFFSET(1)], %l5 - stn %l5, [%sp + EH_ARGS_OFFSET(2)] /* copy 8th syscall arg */ -#if !defined(__sparcv9) - cmp %l4, 0x9 - bl,pt %ncc, args_copied - nop - ldn [%fp + EH_ARGS_OFFSET(2)], %l5 - stn %l5, [%sp + EH_ARGS_OFFSET(3)] /* copy 9th syscall arg */ -#endif /* !__sparcv9 */ - -args_copied: - /* - * The first parameter to the emulation callback function is a - * pointer to a sysret_t structure. - * - * invoke the emulation routine. - */ - ALTENTRY(sn1_handler_savepc) - call %l2 - add %sp, EH_LOCALS_SYSRET, %o0 /* arg0 == sysret_t ptr */ - - /* Check for syscall emulation success or failure */ - cmp %g0, %o0 - be success - nop - subcc %g0, 1, %g0 /* failure, set carry flag */ - ba return - mov %o0, %i0 /* return, %o0 == errno */ - -success: - /* There is always at least one return value. */ - ldn [%sp + EH_LOCALS_SYSRET1], %i0 /* %i0 == sys_rval1 */ - cmp %l3, RV_DEFAULT /* check rv flag */ - be,a clear_carry - mov %g0, %i1 /* clear second rval */ - ldn [%sp + EH_LOCALS_SYSRET2], %i1 /* %i1 == sys_rval2 */ -clear_carry: - addcc %g0, %g0, %g0 /* success, clear carry flag */ - -return: - /* - * Our syscall emulation is complete. Return to the caller that - * originally invoked a system which needed emulation. Note that - * we have to load the return address that we saved earlier because - * it's possible that %g5 was overwritten by a nested call into - * this emulation library. - */ - ldn [%sp + EH_LOCALS_GREG(REG_nPC)], %g5 - jmp %g5 - restore /* delay slot */ - SET_SIZE(sn1_handler) - - -#endif /* !lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_runexe.s b/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_runexe.s deleted file mode 100644 index 67dcb8895d..0000000000 --- a/usr/src/lib/brand/sn1/sn1_brand/sparc/sn1_runexe.s +++ /dev/null @@ -1,82 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> -#include <sn1_misc.h> - -#if defined(lint) - -/*ARGSUSED*/ -void -sn1_runexe(void *argv, ulong_t entry) -{ -} - -#else /* lint */ - .section ".text" - ENTRY_NP(sn1_runexe) - /* - * Prepare to jump to the target program we actually want to run. - * If this program is dynamically linked then we'll be jumping to - * another copy of the linker. If it's a statically linked program - * we'll be jumping directy to it's main entry point. In any case, - * we need to reset our current state stack and register state to - * something similar to the initial process state setup by the kernel - * and documented at: - * usr/src/cmd/sgs/rtld/sparc/boot.s - * usr/src/cmd/sgs/rtld/sparcv9/boot.s - * - * Of course this is the same stack format as when this executable - * was first started, so here we'll just roll back the stack and - * frame pointers to their values when this processes first started - * execution. - * - * Our input parameters are stored in the %o? registers since we - * don't bother to allocate a new stack frame. - */ - sub %o0, CPTRSIZE + WINDOWSIZE + STACK_BIAS, %sp - clr %fp - - /* - * We also have to make sure to clear %g1 since nornally ld.so.1 will - * set that to non-zero if there is an exit function that should be - * invoked when the process is terminating. This isn't actually - * necessary if the target program we're jumping to is a dynamically - * linked program since in that case we're actually jumping to another - * copy of ld.so.1 and it will just reset %g1, but if the target - * program we're jumping to is a statically linked binary that uses - * the standard sun compiler supplied crt1.o`_start(), it will check - * to see if %g1 is set. - */ - clr %g1 - - jmp %o1 ! jump to the target processes entry point - nop - /* - * target will never return. - */ - SET_SIZE(sn1_runexe) -#endif /* lint */ diff --git a/usr/src/lib/brand/sn1/sn1_brand/sparcv9/Makefile b/usr/src/lib/brand/sn1/sn1_brand/sparcv9/Makefile index 90c9270c00..1d9c1aa3b8 100644 --- a/usr/src/lib/brand/sn1/sn1_brand/sparcv9/Makefile +++ b/usr/src/lib/brand/sn1/sn1_brand/sparcv9/Makefile @@ -19,16 +19,17 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # lib/brand/sn1/sparcv9/Makefile -ISASRCDIR = ../sparc +ISAOBJDIR = $(BRAND_SHARED)/brand/sparcv9/pics include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 +CPPFLAGS += -I$(BRAND_SHARED)/brand/sparcv9 + # # see ../Makefile.com for why we explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/solaris10/librtld_db/Makefile.com b/usr/src/lib/brand/solaris10/librtld_db/Makefile.com index f03de8ab6b..9399d772a9 100644 --- a/usr/src/lib/brand/solaris10/librtld_db/Makefile.com +++ b/usr/src/lib/brand/solaris10/librtld_db/Makefile.com @@ -19,62 +19,11 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -LIBRARY = solaris10_librtld_db.a -VERS = .1 -COBJS = solaris10_librtld_db.o +COBJS = brand_librtld_db.o OBJECTS = $(COBJS) $(COBJS64) -include $(SRC)/lib/Makefile.lib include ../../Makefile.s10 - -CSRCS = $(COBJS:%o=../common/%c) -SRCS = $(CSRCS) - -SRCDIR = ../common -UTSBASE = $(SRC)/uts - -# -# ATTENTION: -# Librtl_db brand plugin libraries should NOT directly invoke any -# libproc.so interfaces or be linked against libproc. If a librtl_db -# brand plugin library uses libproc.so interfaces then it may break -# any other librtld_db consumers (like mdb) that tries to attach -# to a branded process. The only safe interfaces that the a librtld_db -# brand plugin library can use to access a target process are the -# proc_service(3PROC) apis. -# -DYNFLAGS += $(VERSREF) -M../common/mapfile-vers -LIBS = $(DYNLIB) -LDLIBS += -lc -lrtld_db -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -I../ -I$(UTSBASE)/common/brand/solaris10 \ - -I$(SRC)/cmd/sgs/librtld_db/common \ - -I$(SRC)/cmd/sgs/include \ - -I$(SRC)/cmd/sgs/include/$(MACH) - -ROOTLIBDIR = $(ROOT)/usr/lib/brand/solaris10 -ROOTLIBDIR64 = $(ROOT)/usr/lib/brand/solaris10/$(MACH64) - -# -# The top level Makefiles define define TEXT_DOMAIN. But librtld_db.so.1 -# isn't internationalized and this library won't be either. The only -# messages that this library can generate are messages used for debugging -# the operation of the library itself. -# -DTEXTDOM = - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -pics/%64.o: ../common/%.c - $(COMPILE.c) -D_ELF64 $(PICFLAGS) -o $@ $< - $(POST_PROCESS_O) - -include $(SRC)/lib/Makefile.targ +include $(BRAND_SHARED)/librtld_db/Makefile.com diff --git a/usr/src/lib/brand/solaris10/librtld_db/amd64/Makefile b/usr/src/lib/brand/solaris10/librtld_db/amd64/Makefile index de7282752c..5bae7648ff 100644 --- a/usr/src/lib/brand/solaris10/librtld_db/amd64/Makefile +++ b/usr/src/lib/brand/solaris10/librtld_db/amd64/Makefile @@ -19,16 +19,15 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -COBJS64 = solaris10_librtld_db64.o +COBJS64 = brand_librtld_db64.o include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 CLOBBERFILES = $(ROOTLIBDIR64)/$(DYNLIB) -DYNFLAGS += -M../common/mapfile-vers.64 +DYNFLAGS += -M$(BRAND_SHARED)/librtld_db/common/mapfile-vers.64 install: all $(ROOTLIBS64) diff --git a/usr/src/lib/brand/solaris10/librtld_db/common/solaris10_librtld_db.c b/usr/src/lib/brand/solaris10/librtld_db/common/solaris10_librtld_db.c deleted file mode 100644 index e20a6ac142..0000000000 --- a/usr/src/lib/brand/solaris10/librtld_db/common/solaris10_librtld_db.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <libproc.h> -#include <proc_service.h> -#include <synch.h> -#include <sys/types.h> -#include <sys/link.h> -#include <rtld_db.h> - -#include <s10_brand.h> - -/* - * ATTENTION: - * Librtl_db brand plugin libraries should NOT directly invoke any - * libproc.so interfaces or be linked against libproc. If a librtl_db - * brand plugin library uses libproc.so interfaces then it may break - * any other librtld_db consumers (like mdb) that tries to attach - * to a branded process. The only safe interfaces that the a librtld_db - * brand plugin library can use to access a target process are the - * proc_service(3PROC) apis. - */ - -/* - * M_DATA comes from some streams header file but is also redifined in - * _rtld_db.h, so nuke the old streams definition here. - */ -#ifdef M_DATA -#undef M_DATA -#endif /* M_DATA */ - -/* - * For 32-bit versions of this library, this file get's compiled once. - * For 64-bit versions of this library, this file get's compiled twice, - * once with _ELF64 defined and once without. The expectation is that - * the 64-bit version of the library can properly deal with both 32-bit - * and 64-bit elf files, hence in the 64-bit library there are two copies - * of all the interfaces in this file, one set named *32 and one named *64. - * - * This also means that we need to be careful when declaring local pointers - * that point to objects in another processes address space, since these - * pointers may not match the current processes pointer width. Basically, - * we should not use any objects that change size between 32 and 64 bit - * modes like: long, void *, uintprt_t, caddr_t, psaddr_t, size_t, etc. - * Instead we should declare all pointers as uint32_t. Then when we - * are compiled to deal with 64-bit targets we'll re-define uing32_t - * to be a uint64_t. - */ -#ifdef _LP64 -#ifdef _ELF64 -#define uint32_t uint64_t -#define Elf32_Dyn Elf64_Dyn -#define validate_rdebug32 validate_rdebug64 -#define _rd_loadobj_iter32 _rd_loadobj_iter64 -#define _rd_get_dyns32 _rd_get_dyns64 -#define dummy_ldb32 dummy_ldb64 -#define dummy_ldb_init32 dummy_ldb_init64 -#define dummy_ldb_fini32 dummy_ldb_fini64 -#define dummy_ldb_loadobj_iter32 dummy_ldb_loadobj_iter64 -#define dummy_ldb_get_dyns32 dummy_ldb_get_dyns64 -#define s10_ldb_init32 s10_ldb_init64 -#define s10_ldb_fini32 s10_ldb_fini64 -#define s10_ldb_loadobj_iter32 s10_ldb_loadobj_iter64 -#define s10_ldb_get_dyns32 s10_ldb_get_dyns64 -#endif /* _ELF64 */ -#endif /* _LP64 */ - -/* Included from usr/src/cmd/sgs/librtld_db/common */ -#include <_rtld_db.h> - -/*ARGSUSED*/ -static rd_helper_data_t -dummy_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) -{ - return (NULL); -} - -/*ARGSUSED*/ -static void -dummy_ldb_fini32(rd_helper_data_t rhd) -{ -} - -/*ARGSUSED*/ -static int -dummy_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data) -{ - return (RD_OK); -} - -/*ARGSUSED*/ -static rd_err_e -dummy_ldb_get_dyns32(rd_helper_data_t rhd, - psaddr_t addr, void **dynpp, size_t *dynpp_sz) -{ - *dynpp = NULL; - *dynpp_sz = 0; - return (RD_OK); -} - -static rd_helper_ops_t dummy_ldb32 = { - LM_ID_BRAND, - dummy_ldb_init32, - dummy_ldb_fini32, - dummy_ldb_loadobj_iter32, - dummy_ldb_get_dyns32 -}; - -static uint32_t -s10_ldb_getauxval32(struct ps_prochandle *php, int type) -{ - const auxv_t *auxvp = NULL; - - if (ps_pauxv(php, &auxvp) != PS_OK) - return ((uint32_t)-1); - - while (auxvp->a_type != AT_NULL) { - if (auxvp->a_type == type) - return ((uint32_t)(uintptr_t)auxvp->a_un.a_ptr); - auxvp++; - } - return ((uint32_t)-1); -} - -/* - * Normally, the native Solaris librtldb_db plugin uses a bunch of different - * methods to try and find the rdebug structure associated with the target - * process we're debugging. For details on the different methods see - * _rd_reset32(). Thankfully our job is easier. We know that the brand - * library is always linked against the native linker, and when the - * process was first executed we saved off a pointer to the brand linkers - * rdebug structure in one of our brand specific aux vectors, - * AT_SUN_BRAND_S10_LDDATA. So we'll just look that up here. - */ -/*ARGSUSED*/ -static rd_helper_data_t -s10_ldb_init32(rd_agent_t *rap, struct ps_prochandle *php) -{ - struct rd_agent *rap_new; - uint32_t lddata_addr; - int rd_dmodel; - - if (ps_pdmodel(php, &rd_dmodel) != PS_OK) { - ps_plog("s10_ldb_init: lookup of data model failed"); - return (NULL); - } -#ifdef _ELF64 - assert(rd_dmodel == PR_MODEL_LP64); -#else /* !_ELF64 */ - assert(rd_dmodel == PR_MODEL_ILP32); -#endif /* !_ELF64 */ - - lddata_addr = s10_ldb_getauxval32(php, AT_SUN_BRAND_S10_LDDATA); - if (lddata_addr == (uint32_t)-1) { - ps_plog("s10_ldb_init: no LDDATA found in aux vector"); - return (NULL); - } - ps_plog("s10_ldb_init: found LDDATA auxv ld.so.1 data seg " - "at: 0x%p", lddata_addr); - - /* - * Ok. So this is kinda ugly. Basically we know that we're going to - * be parsing data from link maps that are generated by a Solaris - * linker. As it turns out, that's exactly what the default - * Solaris librtld_db library is designed to do. So rather than - * duplicate all that link map parsing code here we'll simply - * invoke the native librtld_db that normally does this, and when - * we do we'll point them at our emulation libraries link map. - * - * Of course these interfacess aren't really public interfaces - * and they take a "struct rd_agent" as a parameter. So here - * we'll allocate and initialize a new "struct rd_agent", point - * it at our emulation libraries link map, and initialize just - * enough of the structure to make the librtld_db interfaces - * that we want to use happy. - */ - if ((rap_new = calloc(sizeof (*rap_new), 1)) == NULL) { - ps_plog("s10_ldb_init: can't allocate memory"); - return (NULL); - } - rap_new->rd_dmodel = rd_dmodel; - rap_new->rd_psp = php; - rap_new->rd_rdebug = lddata_addr; - (void) mutex_init(&rap_new->rd_mutex, USYNC_THREAD, 0); - - /* - * When we get invoked from librtld_db, and we call back into it, - * librtld_db will once again check if there is a plugin and - * invoke it. Since we don't want to enter a recursive loop - * we're going to specify a different plugin interface for - * our linkmap, and these new plugin interfaces won't actually - * do anything other than return. - */ - rap_new->rd_helper.rh_ops = &dummy_ldb32; - - /* - * validate_rdebug32() requires the following "struct rd_agent" - * members to be initialized: - * rd_psp, rd_rdebug - * - * validate_rdebug32() initializes the following "struct rd_agent" - * members: - * rd_flags, rd_rdebugvers, rd_rtlddbpriv - */ - if (validate_rdebug32(rap_new) != RD_OK) { - ps_plog("s10_ldb_init: can't find valid r_debug data"); - free(rap_new); - return (NULL); - } - - ps_plog("s10_ldb_init: finished, helper_data=0x%p", rap_new); - return ((rd_helper_data_t)rap_new); -} - -static void -s10_ldb_fini32(rd_helper_data_t rhd) -{ - struct rd_agent *rap = (struct rd_agent *)rhd; - ps_plog("s10_ldb_fini: cleaning up s10 helper"); - free(rap); -} - -/*ARGSUSED*/ -static int -s10_ldb_loadobj_iter32(rd_helper_data_t rhd, rl_iter_f *cb, void *client_data) -{ - struct rd_agent *rap = (struct rd_agent *)rhd; - int err; - - ps_plog("s10_ldb_loadobj_iter(helper_data=0x%p)", rhd); - assert(rap->rd_psp == php); - RDAGLOCK(rap); - /* - * _rd_loadobj_iter32() requires the following "struct rd_agent" - * members to be initialized: - * rd_rtlddbpriv, rd_rdebugvers, rd_flags, - * rd_helper.rh_ops, rd_dmodel - */ - err = _rd_loadobj_iter32(rap, cb, client_data); - RDAGUNLOCK(rap); - ps_plog("s10_ldb_loadobj_iter: finished, err = %d", err); - return (err); -} - -/*ARGSUSED*/ -static rd_err_e -s10_ldb_get_dyns32(rd_helper_data_t rhd, - psaddr_t addr, void **dynpp, size_t *dynpp_sz) -{ - struct rd_agent *rap = (struct rd_agent *)rhd; - int err; - - ps_plog("s10_ldb_get_dyns(helper_data=0x%p)", rhd); - err = _rd_get_dyns32(rap, addr, (Elf32_Dyn **)dynpp, dynpp_sz); - ps_plog("s10_ldb_get_dyns: finished, err = %d", err); - return (err); -} - -/* - * Librtld_db plugin linkage struct. - * - * When we get loaded by librtld_db, it will look for the symbol below - * to find our plugin entry points. - */ -rd_helper_ops_t RTLD_DB_BRAND_OPS = { - LM_ID_NONE, - s10_ldb_init32, - s10_ldb_fini32, - s10_ldb_loadobj_iter32, - s10_ldb_get_dyns32 -}; diff --git a/usr/src/lib/brand/solaris10/librtld_db/sparcv9/Makefile b/usr/src/lib/brand/solaris10/librtld_db/sparcv9/Makefile index de7282752c..5bae7648ff 100644 --- a/usr/src/lib/brand/solaris10/librtld_db/sparcv9/Makefile +++ b/usr/src/lib/brand/solaris10/librtld_db/sparcv9/Makefile @@ -19,16 +19,15 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -COBJS64 = solaris10_librtld_db64.o +COBJS64 = brand_librtld_db64.o include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 CLOBBERFILES = $(ROOTLIBDIR64)/$(DYNLIB) -DYNFLAGS += -M../common/mapfile-vers.64 +DYNFLAGS += -M$(BRAND_SHARED)/librtld_db/common/mapfile-vers.64 install: all $(ROOTLIBS64) diff --git a/usr/src/lib/brand/solaris10/s10_brand/Makefile.com b/usr/src/lib/brand/solaris10/s10_brand/Makefile.com index a90d56d4cd..f031d769f0 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/Makefile.com +++ b/usr/src/lib/brand/solaris10/s10_brand/Makefile.com @@ -19,18 +19,14 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # LIBRARY = s10_brand.a VERS = .1 COBJS = s10_brand.o s10_deleted.o s10_signal.o -ASOBJS = s10_crt.o s10_handler.o s10_runexe.o -OFFSETS_SRC = ../common/offsets.in -OFFSETS_H = assym.h -OBJECTS = $(COBJS) $(ASOBJS) -CLOBBERFILES += $(OFFSETS_H) +ASOBJS = crt.o handler.o runexe.o brand_util.o +OBJECTS = $(COBJS) include ../../Makefile.s10 include $(SRC)/lib/Makefile.lib @@ -40,19 +36,8 @@ UTSBASE = $(SRC)/uts LIBS = $(DYNLIB) CSRCS = $(COBJS:%o=../common/%c) -ASSRCS = $(ASOBJS:%o=$(ISASRCDIR)/%s) -SRCS = $(CSRCS) $(ASSRCS) - -# -# Ugh, this is a gross hack. Our assembly routines uses lots of defines -# to simplify variable access. All these defines work fine for amd64 -# compiles because when compiling for amd64 we use the GNU assembler, -# gas. For 32-bit code we use the Sun assembler, as. Unfortunatly -# as does not handle certian constructs that gas does. So rather than -# make our code less readable, we'll just use gas to compile our 32-bit -# code as well. -# -i386_AS = $(amd64_AS) +SHAREDOBJS = $(ASOBJS:%o=$(ISAOBJDIR)/%o) +SRCS = $(CSRCS) # # Note that the architecture specific makefiles MUST update DYNFLAGS to @@ -87,33 +72,23 @@ i386_AS = $(amd64_AS) # via mmap() instead of brk(). # CPPFLAGS += -D_REENTRANT -U_ASM \ - -I. -I../sys -I$(UTSBASE)/common/brand/solaris10 \ + -I. -I$(BRAND_SHARED)/brand/sys -I../sys \ + -I$(UTSBASE)/common/brand/solaris10 \ -I$(SRC)/uts/common/fs/zfs CFLAGS += $(CCVERBOSE) # Needed to handle zfs include files C99MODE= -xc99=%all C99LMODE= -Xc99=%all -ASFLAGS = -P $(ASFLAGS_$(CURTYPE)) -D_ASM -I. -I../sys DYNFLAGS += $(DYNFLAGS_$(CLASS)) DYNFLAGS += $(BLOCAL) $(ZNOVERSION) -Wl,-e_start LDLIBS += -lc -lmapmalloc +$(LIBS):= PICS += $(SHAREDOBJS) + .KEEP_STATE: all: $(LIBS) lint: lintcheck -# -# build the offset header before trying to compile any files. (it's included -# by s10_misc.h, so it's needed for all objects, not just assembly ones.) -# -$(OBJECTS:%=pics/%): $(OFFSETS_H) -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) $(CTF_FLAGS) < $(OFFSETS_SRC) >$@ - -pics/%.o: $(ISASRCDIR)/%.s - $(COMPILE.s) -o $@ $< - $(POST_PROCESS_O) - include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/brand/solaris10/s10_brand/amd64/Makefile b/usr/src/lib/brand/solaris10/s10_brand/amd64/Makefile index 6d760f7e28..abb83be149 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/amd64/Makefile +++ b/usr/src/lib/brand/solaris10/s10_brand/amd64/Makefile @@ -19,15 +19,16 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/amd64/pics/ include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 +CPPFLAGS += -I$(BRAND_SHARED)/brand/amd64 + # # see ../Makefile.com for why we MUST explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s b/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s deleted file mode 100644 index 76b2dcfe1e..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_handler.s +++ /dev/null @@ -1,219 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <s10_misc.h> - -/* - * Each JMP must occupy 16 bytes - */ -#define JMP \ - pushq $_CONST(. - s10_handler_table); \ - jmp s10_handler; \ - .align 16; - -#define JMP4 JMP; JMP; JMP; JMP -#define JMP16 JMP4; JMP4; JMP4; JMP4 -#define JMP64 JMP16; JMP16; JMP16; JMP16 -#define JMP256 JMP64; JMP64; JMP64; JMP64 - -#if defined(lint) - -void -s10_handler_table(void) -{} - -void -s10_handler(void) -{ -} - -#else /* lint */ - - /* - * On entry to this table, %rax will hold the return address. The - * location where we enter the table is a function of the system - * call number. The table needs the same alignment as the individual - * entries. - */ - .align 16 - ENTRY_NP(s10_handler_table) - JMP256 - SET_SIZE(s10_handler_table) - - /* - * %rax - userland return address - * stack contains: - * | -------------------------------------- - * v 8 | syscall arguments | - * %rsp+0 | syscall number | - * -------------------------------------- - */ - ENTRY_NP(s10_handler) - pushq %rbp /* allocate stack frame */ - movq %rsp, %rbp - - /* Save registers at the time of the syscall. */ - movq $0, EH_LOCALS_GREG(REG_TRAPNO)(%rbp) - movq $0, EH_LOCALS_GREG(REG_ERR)(%rbp) - movq %r15, EH_LOCALS_GREG(REG_R15)(%rbp) - movq %r14, EH_LOCALS_GREG(REG_R14)(%rbp) - movq %r13, EH_LOCALS_GREG(REG_R13)(%rbp) - movq %r12, EH_LOCALS_GREG(REG_R12)(%rbp) - movq %r11, EH_LOCALS_GREG(REG_R11)(%rbp) - movq %r10, EH_LOCALS_GREG(REG_R10)(%rbp) - movq %r9, EH_LOCALS_GREG(REG_R9)(%rbp) - movq %r8, EH_LOCALS_GREG(REG_R8)(%rbp) - movq %rdi, EH_LOCALS_GREG(REG_RDI)(%rbp) - movq %rsi, EH_LOCALS_GREG(REG_RSI)(%rbp) - movq %rbx, EH_LOCALS_GREG(REG_RBX)(%rbp) - movq %rcx, EH_LOCALS_GREG(REG_RCX)(%rbp) - movq %rdx, EH_LOCALS_GREG(REG_RDX)(%rbp) - xorq %rcx, %rcx - movw %cs, %cx - movq %rcx, EH_LOCALS_GREG(REG_CS)(%rbp) - movw %ds, %cx - movq %rcx, EH_LOCALS_GREG(REG_DS)(%rbp) - movw %es, %cx - movq %rcx, EH_LOCALS_GREG(REG_ES)(%rbp) - movw %fs, %cx - movq %rcx, EH_LOCALS_GREG(REG_FS)(%rbp) - movw %gs, %cx - movq %rcx, EH_LOCALS_GREG(REG_GS)(%rbp) - movw %ss, %cx - movq %rcx, EH_LOCALS_GREG(REG_SS)(%rbp) - pushfq /* save syscall flags */ - popq %r12 - movq %r12, EH_LOCALS_GREG(REG_RFL)(%rbp) - movq EH_ARGS_OFFSET(0)(%rbp), %r12 /* save syscall rbp */ - movq %r12, EH_LOCALS_GREG(REG_RBP)(%rbp) - movq %rbp, %r12 /* save syscall rsp */ - addq $CPTRSIZE, %r12 - movq %r12, EH_LOCALS_GREG(REG_RSP)(%rbp) - movq %fs:0, %r12 /* save syscall fsbase */ - movq %r12, EH_LOCALS_GREG(REG_FSBASE)(%rbp) - movq $0, EH_LOCALS_GREG(REG_GSBASE)(%rbp) - - /* - * The kernel drops us into the middle of the s10_handle_table - * above that then pushes that table offset onto the stack, and calls - * into s10_handler. That offset indicates the system call number while - * %rax holds the return address for the system call. We replace the - * value on the stack with the return address, and use the value to - * compute the system call number by dividing by the table entry size. - */ - xchgq CPTRSIZE(%rbp), %rax /* swap JMP table offset and ret addr */ - shrq $4, %rax /* table_offset/size = syscall num */ - movq %rax, EH_LOCALS_GREG(REG_RAX)(%rbp) /* save syscall num */ - - /* - * Finish setting up our stack frame. We would normally do this - * upon entry to this function, but in this case we delayed it - * because a "sub" operation can modify flags and we wanted to - * save the flags into the gregset_t above before they get modified. - * - * Our stack frame format is documented in s10_misc.h. - */ - subq $EH_LOCALS_SIZE, %rsp - - /* Look up the system call's entry in the sysent table */ - movq s10_sysent_table@GOTPCREL(%rip), %r11 /* %r11 = sysent_table */ - shlq $4, %rax /* each entry is 16 bytes */ - addq %rax, %r11 /* %r11 = sysent entry address */ - - /* - * Get the return value flag and the number of arguments from the - * sysent table. - */ - movq CPTRSIZE(%r11), %r12 /* number of args + rv flag */ - andq $RV_MASK, %r12 /* strip out number of args */ - movq %r12, EH_LOCALS_RVFLAG(%rbp) /* save rv flag */ - - /* - * Setup arguments for our emulation call. Our input arguments, - * 0 to N, will become emulation call arguments 1 to N+1. - * - * Note: Syscall argument passing is different from function call - * argument passing on amd64. For function calls, the fourth arg - * is passed via %rcx, but for system calls the 4th argument is - * passed via %r10. This is because in amd64, the syscall - * instruction puts lower 32 bit of %rflags in %r11 and puts the - * %rip value to %rcx. - */ - movq EH_ARGS_OFFSET(4)(%rbp), %r12 /* copy 8th arg */ - movq %r12, EH_ARGS_OFFSET(2)(%rsp) - movq EH_ARGS_OFFSET(3)(%rbp), %r12 /* copy 7th arg */ - movq %r12, EH_ARGS_OFFSET(1)(%rsp) - movq %r9, EH_ARGS_OFFSET(0)(%rsp) - movq %r8, %r9 - movq %r10, %r8 - movq %rdx, %rcx - movq %rsi, %rdx - movq %rdi, %rsi - - /* - * The first parameter to the emulation callback function is a - * pointer to a sysret_t structure. - */ - movq %rbp, %rdi - addq $EH_LOCALS_SYSRET, %rdi /* arg0 == sysret_t ptr */ - - /* invoke the emulation routine */ - ALTENTRY(s10_handler_savepc) - call *(%r11) - - /* restore scratch and parameter registers */ - movq EH_LOCALS_GREG(REG_R12)(%rbp), %r12 /* restore %r12 */ - movq EH_LOCALS_GREG(REG_R11)(%rbp), %r11 /* restore %r11 */ - movq EH_LOCALS_GREG(REG_R10)(%rbp), %r10 /* restore %r10 */ - movq EH_LOCALS_GREG(REG_R9)(%rbp), %r9 /* restore %r9 */ - movq EH_LOCALS_GREG(REG_R8)(%rbp), %r8 /* restore %r8 */ - movq EH_LOCALS_GREG(REG_RCX)(%rbp), %rcx /* restore %rcx */ - movq EH_LOCALS_GREG(REG_RDX)(%rbp), %rdx /* restore %rdx */ - movq EH_LOCALS_GREG(REG_RSI)(%rbp), %rsi /* restore %rsi */ - movq EH_LOCALS_GREG(REG_RDI)(%rbp), %rdi /* restore %rdi */ - - /* Check for syscall emulation success or failure */ - cmpq $0, %rax - je success - stc /* failure, set carry flag */ - jmp return /* return, %rax == errno */ - -success: - /* There is always at least one return value. */ - movq EH_LOCALS_SYSRET1(%rbp), %rax /* %rax == sys_rval1 */ - cmpq $RV_DEFAULT, EH_LOCALS_RVFLAG(%rbp) /* check rv flag */ - je clear_carry - mov EH_LOCALS_SYSRET2(%rbp), %rdx /* %rdx == sys_rval2 */ -clear_carry: - clc /* success, clear carry flag */ - -return: - movq %rbp, %rsp /* restore stack */ - popq %rbp - ret /* ret to instr after syscall */ - SET_SIZE(s10_handler) - - -#endif /* lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_runexe.s b/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_runexe.s deleted file mode 100644 index a8aad19ef2..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/amd64/s10_runexe.s +++ /dev/null @@ -1,80 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> -#include <s10_misc.h> - -#if defined(lint) - -/*ARGSUSED*/ -void -s10_runexe(void *argv, ulong_t entry) -{ -} - -#else /* lint */ - /* - * Prepare to jump to the target program we actually want to run. - * If this program is dynamically linked then we'll be jumping to - * another copy of the linker. If it's a statically linked program - * we'll be jumping directy to it's main entry point. In any case, - * we need to reset our current state stack and register state to - * something similar to the initial process state setup by the kernel - * and documented at: - * usr/src/cmd/sgs/rtld/i386/boot.s - * usr/src/cmd/sgs/rtld/sparcv9/boot.s - * - * Of course this is the same stack format as when this executable - * was first started, so here we'll just roll back the stack and - * frame pointers to their values when this processes first started - * execution. - */ - ENTRY_NP(s10_runexe) - - movq %rdi, %rax / %rax = &argv[0] - movq %rsi, %rbx / Brand app entry point in %rbx - subq $8, %rax / Top of stack - must point at argc - movq %rax, %rsp / Set %rsp to what linkers expect - - /* - * We also have to make sure to clear %rdx since nornally ld.so.1 will - * set that to non-zero if there is an exit function that should be - * invoked when the process is terminating. This isn't actually - * necessary if the target program we're jumping to is a dynamically - * linked program since in that case we're actually jumping to another - * copy of ld.so.1 and it will just reset %rdx, but if the target - * program we're jumping to is a statically linked binary that uses - * the standard sun compiler supplied crt1.o`_start(), it will check - * to see if %g1 is set. - */ - movq $0, %rdx - - jmp *%rbx / And away we go... - /* - * target will never return. - */ - SET_SIZE(s10_runexe) -#endif /* lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/offsets.in b/usr/src/lib/brand/solaris10/s10_brand/common/offsets.in deleted file mode 100644 index 50bd417af3..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/common/offsets.in +++ /dev/null @@ -1,35 +0,0 @@ -\ -\ Copyright 2009 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. -\ -\ CDDL HEADER START -\ -\ The contents of this file are subject to the terms of the -\ Common Development and Distribution License (the "License"). -\ You may not use this file except in compliance with the License. -\ -\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -\ or http://www.opensolaris.org/os/licensing. -\ See the License for the specific language governing permissions -\ and limitations under the License. -\ -\ When distributing Covered Code, include this CDDL HEADER in each -\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. -\ If applicable, add the following below this CDDL HEADER, with the -\ fields enclosed by brackets "[]" replaced with your own identifying -\ information: Portions Copyright [yyyy] [name of copyright owner] -\ -\ CDDL HEADER END -\ - - -#include <sys/types.h> -#include <sys/regset.h> -#include <sys/ucontext.h> -#include <sys/syscall.h> - -greg_t SIZEOF_GREG_T - -gregset_t SIZEOF_GREGSET_T - -sysret_t SIZEOF_SYSRET_T diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c index 105ffec277..34326099f2 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c +++ b/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <errno.h> @@ -60,113 +59,13 @@ #include <atomic.h> #include <s10_brand.h> +#include <brand_misc.h> #include <s10_misc.h> #include <s10_signal.h> /* - * Principles of emulation 101. - * - * - * *** Setting errno - * - * Just don't do it. This emulation library is loaded onto a - * seperate link map from the application who's address space we're - * running in. We have our own private copy of libc, so there for, - * the errno value accessible from here is is also private and changing - * it will not affect any errno value that the processes who's address - * space we are running in will see. To return an error condition we - * should return the negated errno value we'd like the system to return. - * For more information about this see the comment in s10_handler(). - * Basically, when we return to the caller that initiated the system - * call it's their responsibility to set errno. - * - * - * *** Recursion Considerations - * - * When emulating system calls we need to be very careful about what - * library calls we invoke. Library calls should be kept to a minimum. - * One issue is that library calls can invoke system calls, so if we're - * emulating a system call and we invoke a library call that depends on - * that system call we will probably enter a recursive loop, which would - * be bad. - * - * - * *** Return Values. - * - * When declaring new syscall emulation functions, it is very important - * to to set the proper RV_* flags in the s10_sysent_table. Upon failure, - * syscall emulation fuctions should return an errno value. Upon success - * syscall emulation functions should return 0 and set the sysret_t return - * value parameters accordingly. - * - * There are five possible syscall macro wrappers used in the kernel's system - * call sysent table. These turn into the following return values: - * SYSENT_CL -> SYSENT_C or SYSENT_CI - * SYSENT_C SE_64RVAL RV_DEFAULT - * SYSENT_CI SE_32RVAL1 RV_DEFAULT - * SYSENT_2CI SE_32RVAL1|SE_32RVAL2 RV_32RVAL2 - * SYSENT_AP SE_64RVAL RV_64RVAL - * - * - * *** Agent lwp considerations - * - * It is currently impossible to do any emulation for these system call - * when they are being invoked on behalf of an agent lwp. To understand why - * it's impossible you have to understand how agent lwp syscalls work. - * - * The agent lwp syscall process works as follows: - * 1 The controlling process stops the target. - * 2 The controlling process injects an agent lwp which is also stopped. - * This agent lwp assumes the userland stack and register values - * of another stopped lwp in the current process. - * 3 The controlling process configures the agent lwp to start - * executing the requested system call. - * 4 The controlling process configure /proc to stop the agent lwp when - * it enters the requested system call. - * 5 The controlling processes allows the agent lwp to start executing. - * 6 The agent lwp traps into the kernel to perform the requested system - * call and immediately stop. - * 7 The controlling process copies all the arguments for the requested - * system call onto the agent lwp's stack. - * 8 The controlling process configures /proc to stop the agent lwp - * when it completes the requested system call. - * 9 The controlling processes allows the agent lwp to start executing. - * 10 The agent lwp executes the system call and then stop before returning - * to userland. - * 11 The controlling process copies the return value and return arguments - * back from the agent lwps stack. - * 12 The controlling process destroys the agent lwp and restarts - * the target process. - * - * The fundamental problem is that when the agent executes the request - * system call in step 5, if we're emulating that system call then the - * lwp is redirected back to our emulation layer without blocking - * in the kernel. But our emulation layer can't access the arguments - * for the system call because they haven't been copied to the stack - * yet and they still only exist in the controlling processes address - * space. This prevents us from being able to do any emulation of - * agent lwp system calls. Hence, currently our brand trap interposition - * callback (s10_brand_syscall_callback_common) will detect if a system - * call is being made by an agent lwp, and if this is the case it will - * never redirect the system call to this emulation library. - * - * In the future, if this proves to be a problem the the easiest solution - * would probably be to replace the branded versions of these application - * with their native counterparts. Ie, truss, plimit, and pfiles could be - * replace with wrapper scripts that execute the native versions of these - * applications. In the case of plimit and pfiles this should be pretty - * strait forward. Truss would probably be more tricky since it can - * execute applications which would be branded applications, so in that - * case it might be necessary to create a loadable library which could - * be LD_PRELOADed into truss and this library would interpose on the - * exec() system call to allow truss to correctly execute branded - * processes. It should be pointed out that this solution could work - * because "native agent lwps" (ie, agent lwps created by native - * processes) can be treated differently from "branded aged lwps" (ie, - * agent lwps created by branded processes), since native agent lwps - * would presumably be making native system calls and hence not need - * any interposition. - * + * See usr/src/lib/brand/shared/brand/common/brand_util.c for general + * emulation notes. */ static zoneid_t zoneid; @@ -214,72 +113,11 @@ pid_t zone_init_pid; ((emul_bitmap[(s10_emulated_features_constant) >> 3] & \ (1 << ((s10_emulated_features_constant) & 0x7))) != 0) -#define EMULATE(cb, args) { (sysent_cb_t)(cb), (args) } -#define NOSYS EMULATE(s10_unimpl, (0 | RV_DEFAULT)) - -typedef long (*sysent_cb_t)(); -typedef struct s10_sysent_table { - sysent_cb_t st_callc; - uintptr_t st_args; -} s10_sysent_table_t; -s10_sysent_table_t s10_sysent_table[]; +brand_sysent_table_t brand_sysent_table[]; #define S10_UTS_RELEASE "5.10" #define S10_UTS_VERSION "Generic_Virtual" -/*LINTED: static unused*/ -static volatile int s10_abort_err; -/*LINTED: static unused*/ -static volatile const char *s10_abort_msg; -/*LINTED: static unused*/ -static volatile const char *s10_abort_file; -/*LINTED: static unused*/ -static volatile int s10_abort_line; - -extern int errno; - -/*ARGSUSED*/ -void -_s10_abort(int err, const char *msg, const char *file, int line) -{ - sysret_t rval; - - /* Save the error message into convenient globals */ - s10_abort_err = err; - s10_abort_msg = msg; - s10_abort_file = file; - s10_abort_line = line; - - /* kill ourselves */ - abort(); - - /* If abort() didn't work, try something stronger. */ - (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGKILL); -} - -int -s10_uucopy(const void *from, void *to, size_t size) -{ - sysret_t rval; - - if (__systemcall(&rval, SYS_uucopy + 1024, from, to, size) != 0) - return (EFAULT); - return (0); -} - -/* - * ATTENTION: uucopystr() does NOT ensure that string are null terminated! - */ -int -s10_uucopystr(const void *from, void *to, size_t size) -{ - sysret_t rval; - - if (__systemcall(&rval, SYS_uucopystr + 1024, from, to, size) != 0) - return (EFAULT); - return (0); -} - /* * Figures out the PID of init for the zone. Also returns a boolean * indicating whether this process currently has that pid: if so, @@ -301,7 +139,7 @@ get_initpid_info(void) */ if ((err = __systemcall(&rval, SYS_brand, B_S10_PIDINFO, &pid, &zone_init_pid)) != 0) { - s10_abort(err, "Failed to get init's pid"); + brand_abort(err, "Failed to get init's pid"); } /* @@ -316,82 +154,6 @@ get_initpid_info(void) return (B_FALSE); } -/* - * This function is defined to be NOSYS but it won't be called from the - * the kernel since the NOSYS system calls are not enabled in the kernel. - * Thus, the only time this function is called is directly from within the - * indirect system call path. - */ -/*ARGSUSED*/ -static long -s10_unimpl(sysret_t *rv, uintptr_t p1) -{ - sysret_t rval; - - /* - * We'd like to print out some kind of error message here like - * "unsupported syscall", but we can't because it's not safe to - * assume that stderr or STDERR_FILENO actually points to something - * that is a terminal, and if we wrote to those files we could - * inadvertantly write to some applications open files, which would - * be bad. - * - * Normally, if an application calls an invalid system call - * it get a SIGSYS sent to it. So we'll just go ahead and send - * ourselves a signal here. Note that this is far from ideal since - * if the application has registered a signal handler, that signal - * handler may recieve a ucontext_t as the third parameter to - * indicate the context of the process when the signal was - * generated, and in this case that context will not be what the - * application is expecting. Hence, we should probably create a - * brandsys() kernel function that can deliver the signal to us - * with the correct ucontext_t. - */ - (void) __systemcall(&rval, SYS_lwp_kill + 1024, _lwp_self(), SIGSYS); - return (ENOSYS); -} - -#if defined(__sparc) && !defined(__sparcv9) -/* - * Yuck. For 32-bit sparc applications, handle indirect system calls. - * Note that we declare this interface to use the maximum number of - * system call arguments. If we recieve a system call that uses less - * arguments, then the additional arguments will be garbage, but they - * will also be ignored so that should be ok. - */ -static long -s10_indir(sysret_t *rv, int code, - uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, - uintptr_t a5, uintptr_t a6, uintptr_t a7) -{ - s10_sysent_table_t *sst = &(s10_sysent_table[code]); - - s10_assert(code < NSYSCALL); - switch (sst->st_args & NARGS_MASK) { - case 0: - return ((sst->st_callc)(rv)); - case 1: - return ((sst->st_callc)(rv, a0)); - case 2: - return ((sst->st_callc)(rv, a0, a1)); - case 3: - return ((sst->st_callc)(rv, a0, a1, a2)); - case 4: - return ((sst->st_callc)(rv, a0, a1, a2, a3)); - case 5: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4)); - case 6: - return ((sst->st_callc)(rv, rv, a0, a1, a2, a3, a4, a5)); - case 7: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6)); - case 8: - return ((sst->st_callc)(rv, a0, a1, a2, a3, a4, a5, a6, a7)); - } - s10_abort(0, "invalid entry in s10_sysent_table"); - return (EINVAL); -} -#endif /* __sparc && !__sparcv9 */ - /* Free the thread-local storage provided by mntfs_get_mntentbuf(). */ static void mntfs_free_mntentbuf(void *arg) @@ -514,7 +276,7 @@ mntfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) * therefore need to check the user-supplied address now since the * one we'll be providing is guaranteed to work. */ - if (s10_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0) + if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0) return (EFAULT); /* @@ -537,7 +299,7 @@ mntfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) } } - if (s10_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0) + if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0) return (EFAULT); return (0); @@ -666,7 +428,8 @@ crypto_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) if (major(sbuf.st_rdev) != crypto_dev) goto nonemuioctl; - if (s10_uucopy((const void *)arg, &s10_param, sizeof (s10_param)) != 0) + if (brand_uucopy((const void *)arg, &s10_param, sizeof (s10_param)) + != 0) return (EFAULT); struct_assign(native_param, s10_param, fl_provider_id); if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, @@ -753,7 +516,7 @@ crypto_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) struct_assign(s10_param, native_param, fl_list.prov_hash_threshold); struct_assign(s10_param, native_param, fl_list.prov_hash_limit); - return (s10_uucopy(&s10_param, (void *)arg, sizeof (s10_param))); + return (brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param))); nonemuioctl: return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg)); @@ -795,7 +558,7 @@ ctfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) if (strcmp(statbuf.st_fstype, MNTTYPE_CTFS) != 0) return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg)); - if (s10_uucopy((const void *)arg, &s10param, sizeof (s10param)) != 0) + if (brand_uucopy((const void *)arg, &s10param, sizeof (s10param)) != 0) return (EFAULT); param.ctpm_id = s10param.ctpm_id; param.ctpm_size = sizeof (uint64_t); @@ -805,7 +568,8 @@ ctfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) return (err); if (cmd == CT_TGET) - return (s10_uucopy(&s10param, (void *)arg, sizeof (s10param))); + return (brand_uucopy(&s10param, (void *)arg, + sizeof (s10param))); return (0); } @@ -938,7 +702,8 @@ zfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) * copy the individual fields to a Solaris Next ZFS ioctl * structure. */ - if (s10_uucopy((const void *)arg, &s10_param, sizeof (s10_param)) != 0) + if (brand_uucopy((const void *)arg, &s10_param, sizeof (s10_param)) + != 0) return (EFAULT); /* @@ -1037,7 +802,7 @@ zfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg) * Copy the S10 structure from the stack to the location * specified by the S10 process. */ - (void) s10_uucopy(&s10_param, (void *)arg, sizeof (s10_param)); + (void) brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param)); return (err); passthruioctl: @@ -1180,7 +945,7 @@ s10_getdents_common(sysret_t *rval, int fd, char *buf, size_t nbyte, * use ENOMEM even though getdents(2) doesn't use it because it * best describes the failure. */ - (void) S10_TRUSS_POINT_3(rval, getdents_syscall_id, ENOMEM, fd, + (void) B_TRUSS_POINT_3(rval, getdents_syscall_id, ENOMEM, fd, buf, nbyte); rval->sys_rval1 = -1; rval->sys_rval2 = 0; @@ -1240,7 +1005,7 @@ s10_getdents_common(sysret_t *rval, int fd, char *buf, size_t nbyte, * Copy local_buf into buf so that the calling process can see * the results. */ - if ((err = s10_uucopy(local_buf, buf, buf_size)) != 0) { + if ((err = brand_uucopy(local_buf, buf, buf_size)) != 0) { free(local_buf); rval->sys_rval1 = -1; rval->sys_rval2 = 0; @@ -1326,7 +1091,7 @@ s10_acctctl(sysret_t *rval, int cmd, void *buf, size_t bufsz) mode = AC_FLOW; break; default: - return (S10_TRUSS_POINT_3(rval, SYS_acctctl, EINVAL, cmd, buf, + return (B_TRUSS_POINT_3(rval, SYS_acctctl, EINVAL, cmd, buf, bufsz)); } @@ -1383,12 +1148,12 @@ s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2) &m, a2)) != 0) return (err); m = ((m & S10_AUDIT_HMASK) << 1) | (m & S10_AUDIT_LMASK); - if (s10_uucopy(&m, (void *)a1, sizeof (m)) != 0) + if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0) return (EFAULT); return (0); } else if ((int)a0 == A_SETPOLICY) { - if (s10_uucopy((const void *)a1, &m, sizeof (m)) != 0) + if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0) return (EFAULT); m = ((m >> 1) & S10_AUDIT_HMASK) | (m & S10_AUDIT_LMASK); return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m, @@ -1399,11 +1164,11 @@ s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2) return (err); if (m == AUC_NOSPACE) m = S10_AUC_NOSPACE; - if (s10_uucopy(&m, (void *)a1, sizeof (m)) != 0) + if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0) return (EFAULT); return (0); } else if ((int)a0 == A_SETCOND) { - if (s10_uucopy((const void *)a1, &m, sizeof (m)) != 0) + if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0) return (EFAULT); if (m == S10_AUC_NOSPACE) m = AUC_NOSPACE; @@ -1431,7 +1196,7 @@ s10_exec_native(sysret_t *rval, const char *fname, const char **argp, /* Get a copy of the executable we're trying to run */ path[0] = '\0'; - (void) s10_uucopystr(filename, path, sizeof (path)); + (void) brand_uucopystr(filename, path, sizeof (path)); /* Check if we're trying to run a native binary */ if (strncmp(path, "/.SUNWnative/usr/lib/brand/solaris10/s10_native", @@ -1445,13 +1210,13 @@ s10_exec_native(sysret_t *rval, const char *fname, const char **argp, * The the path of the dynamic linker is the second parameter * of s10_native_exec(). */ - if (s10_uucopy(argp, &filename, sizeof (char *)) != 0) + if (brand_uucopy(argp, &filename, sizeof (char *)) != 0) return (EFAULT); /* If an exec call succeeds, it never returns */ err = __systemcall(rval, SYS_brand + 1024, B_EXEC_NATIVE, filename, argp, envp, NULL, NULL, NULL); - s10_assert(err != 0); + brand_assert(err != 0); return (err); } @@ -1468,7 +1233,7 @@ s10_exec(sysret_t *rval, const char *fname, const char **argp) /* If an exec call succeeds, it never returns */ err = __systemcall(rval, SYS_execve + 1024, fname, argp, NULL); - s10_assert(err != 0); + brand_assert(err != 0); return (err); } @@ -1486,7 +1251,7 @@ s10_execve(sysret_t *rval, const char *fname, const char **argp, /* If an exec call succeeds, it never returns */ err = __systemcall(rval, SYS_execve + 1024, fname, argp, envp); - s10_assert(err != 0); + brand_assert(err != 0); return (err); } @@ -1510,14 +1275,14 @@ s10_uname(sysret_t *rv, uintptr_t p1) return (err); rev = atoi(&un.release[2]); - s10_assert(rev >= 11); + brand_assert(rev >= 11); bzero(un.release, _SYS_NMLN); (void) strlcpy(un.release, S10_UTS_RELEASE, _SYS_NMLN); bzero(un.version, _SYS_NMLN); (void) strlcpy(un.version, S10_UTS_VERSION, _SYS_NMLN); /* copy out the modified uname info */ - return (s10_uucopy(&un, unp, sizeof (un))); + return (brand_uucopy(&un, unp, sizeof (un))); } int @@ -1544,7 +1309,7 @@ s10_sysconfig(sysret_t *rv, int which) return (__systemcall(rv, SYS_sysconfig + 1024, which)); } - (void) S10_TRUSS_POINT_1(rv, SYS_sysconfig, 0, which); + (void) B_TRUSS_POINT_1(rv, SYS_sysconfig, 0, which); rv->sys_rval1 = value; rv->sys_rval2 = 0; @@ -1582,11 +1347,14 @@ s10_sysinfo(sysret_t *rv, int command, char *buf, long count) len = strlen(value) + 1; if (count > 0) { - if (s10_uucopystr(value, buf, count) != 0) + if (brand_uucopystr(value, buf, count) != 0) return (EFAULT); - /* Assure NULL termination of buf as s10_uucopystr() doesn't. */ - if (len > count && s10_uucopy("\0", buf + (count - 1), 1) != 0) + /* + * Assure NULL termination of buf as brand_uucopystr() doesn't. + */ + if (len > count && brand_uucopy("\0", buf + (count - 1), 1) + != 0) return (EFAULT); } @@ -1594,7 +1362,7 @@ s10_sysinfo(sysret_t *rv, int command, char *buf, long count) * On success, sysinfo(2) returns the size of buffer required to hold * the complete value plus its terminating NULL byte. */ - (void) S10_TRUSS_POINT_3(rv, SYS_systeminfo, 0, command, buf, count); + (void) B_TRUSS_POINT_3(rv, SYS_systeminfo, 0, command, buf, count); rv->sys_rval1 = len; rv->sys_rval2 = 0; return (0); @@ -1700,7 +1468,7 @@ s10_lwp_create_correct_fs(sysret_t *rval, ucontext_t *ucp, int flags, * Then make s10_lwp_create_entry_point() the new LWP's entry * point. */ - if (s10_uucopy(ucp, &s10_uc, sizeof (s10_uc)) != 0) + if (brand_uucopy(ucp, &s10_uc, sizeof (s10_uc)) != 0) return (EFAULT); s10_uc.uc_mcontext.gregs[REG_R14] = s10_uc.uc_mcontext.gregs[REG_RIP]; @@ -1740,7 +1508,7 @@ s10_lwp_private(sysret_t *rval, int cmd, int which, uintptr_t base) * Solaris 10 libc with which we're working functions correctly when %fs * is zero by calling thr_main() after issuing the SYS_lwp_private * syscall. If thr_main() barfs (returns -1), then change the LWP's %fs - * register via SYS_brand and patch s10_sysent_table so that issuing + * register via SYS_brand and patch brand_sysent_table so that issuing * SYS_lwp_create executes s10_lwp_create_correct_fs() rather than the * default s10_lwp_create(). s10_lwp_create_correct_fs() will * guarantee that new LWPs will have correct %fs values. @@ -1754,14 +1522,14 @@ s10_lwp_private(sysret_t *rval, int cmd, int which, uintptr_t base) * executed when libc is first loaded by ld.so.1. Thus we * are guaranteed to be single-threaded at this point. Even * if we were multithreaded at this point, writing a 64-bit - * value to the st_callc field of a s10_sysent_table + * value to the st_callc field of a brand_sysent_table * entry is guaranteed to be atomic on 64-bit x86 chips * as long as the field is not split across cache lines * (It shouldn't be.). See chapter 8, section 1.1 of * "The Intel 64 and IA32 Architectures Software Developer's * Manual," Volume 3A for more details. */ - s10_sysent_table[SYS_lwp_create].st_callc = + brand_sysent_table[SYS_lwp_create].st_callc = (sysent_cb_t)s10_lwp_create_correct_fs; return (__systemcall(rval, SYS_brand + 1024, B_S10_FSREGCORRECTION)); @@ -1820,7 +1588,7 @@ s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3, switch (cmd) { case ZONE_LOOKUP: - (void) S10_TRUSS_POINT_1(rval, SYS_zone, 0, cmd); + (void) B_TRUSS_POINT_1(rval, SYS_zone, 0, cmd); rval->sys_rval1 = GLOBAL_ZONEID; rval->sys_rval2 = 0; return (0); @@ -1855,7 +1623,7 @@ s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3, goto passthru; } - (void) S10_TRUSS_POINT_5(rval, SYS_zone, 0, cmd, zid, attr, + (void) B_TRUSS_POINT_5(rval, SYS_zone, 0, cmd, zid, attr, buf, bufsize); len = strlen(aval) + 1; @@ -1864,17 +1632,17 @@ s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3, if (buf != NULL) { if (len == 1) { - if (s10_uucopy("\0", buf, 1) != 0) + if (brand_uucopy("\0", buf, 1) != 0) return (EFAULT); } else { - if (s10_uucopystr(aval, buf, len) != 0) + if (brand_uucopystr(aval, buf, len) != 0) return (EFAULT); /* * Assure NULL termination of "buf" as - * s10_uucopystr() does NOT. + * brand_uucopystr() does NOT. */ - if (s10_uucopy("\0", buf + (len - 1), 1) != 0) + if (brand_uucopy("\0", buf + (len - 1), 1) != 0) return (EFAULT); } } @@ -1892,61 +1660,16 @@ passthru: arg4)); } -/* - * Close a libc file handle, but don't actually close the underlying - * file descriptor. - */ -static void -s10_close_fh(FILE *file) -{ - int fd, fd_new; - - if (file == NULL) - return; - - if ((fd = fileno(file)) < 0) - return; - - /* - * We're a branded process but our handler isn't installed yet. We - * can't use the dup() syscall since it no longer exists. - */ - fd_new = fcntl(fd, F_DUPFD, 0); - if (fd_new == -1) - return; - - (void) fclose(file); - (void) dup2(fd_new, fd); - (void) close(fd_new); -} - /*ARGSUSED*/ int -s10_init(int argc, char *argv[], char *envp[]) +brand_init(int argc, char *argv[], char *envp[]) { sysret_t rval; - s10_brand_reg_t reg; - s10_elf_data_t sed; - auxv_t *ap; - uintptr_t *p; - int i, err; + ulong_t ldentry; + int err; char *bname; - /* Sanity check our translation table return value codes */ - for (i = 0; i < NSYSCALL; i++) { - s10_sysent_table_t *est = &(s10_sysent_table[i]); - s10_assert(BIT_ONLYONESET(est->st_args & RV_MASK)); - } - - /* - * We need to shutdown all libc stdio. libc stdio normally goes to - * file descriptors, but since we're actually part of a another - * process we don't own these file descriptors and we can't make - * any assumptions about their state. - */ - s10_close_fh(stdin); - s10_close_fh(stdout); - s10_close_fh(stderr); + brand_pre_init(); /* * Cache the pid of the zone's init process and determine if @@ -1957,13 +1680,13 @@ s10_init(int argc, char *argv[], char *envp[]) /* get the current zoneid */ err = __systemcall(&rval, SYS_zone, ZONE_LOOKUP, NULL); - s10_assert(err == 0); + brand_assert(err == 0); zoneid = (zoneid_t)rval.sys_rval1; /* Get the zone's emulation bitmap. */ if ((err = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid, S10_EMUL_BITMAP, emul_bitmap, sizeof (emul_bitmap))) != 0) { - s10_abort(err, "The zone's patch level is unsupported"); + brand_abort(err, "The zone's patch level is unsupported"); /*NOTREACHED*/ } @@ -1992,137 +1715,26 @@ s10_init(int argc, char *argv[], char *envp[]) strcmp("patchadd", bname) == 0 || strcmp("patchrm", bname) == 0) emul_global_zone = B_TRUE; - /* - * Register our syscall emulation table with the kernel. - * Note that we don't have to do invoke (syscall_number + 1024) - * until we've actually establised a syscall emulation callback - * handler address, which is what we're doing with this brand - * syscall. - */ - reg.sbr_version = S10_VERSION; -#ifdef __x86 - reg.sbr_handler = (caddr_t)s10_handler_table; -#else /* !__x86 */ - reg.sbr_handler = (caddr_t)s10_handler; -#endif /* !__x86 */ - - if ((err = __systemcall(&rval, SYS_brand, B_REGISTER, ®)) != 0) { - s10_abort(err, "Failed to brand current process"); - /*NOTREACHED*/ - } - - /* Get data about the executable we're running from the kernel. */ - if ((err = __systemcall(&rval, SYS_brand + 1024, - B_ELFDATA, (void *)&sed)) != 0) { - s10_abort(err, - "Failed to get required brand ELF data from the kernel"); - /*NOTREACHED*/ - } - - /* - * Find the aux vector on the stack. - */ - p = (uintptr_t *)envp; - while (*p != NULL) - p++; - - /* - * p is now pointing at the 0 word after the environ pointers. - * After that is the aux vectors. - * - * The aux vectors are currently pointing to the brand emulation - * library and associated linker. We're going to change them to - * point to the brand executable and associated linker (or to no - * linker for static binaries). This matches the process data - * stored within the kernel and visible from /proc, which was - * all setup in s10_elfexec(). We do this so that when a debugger - * attaches to the process it sees the process as a normal solaris - * process, this brand emulation library and everything on it's - * link map will not be visible, unless our librtld_db plugin - * is used. Note that this is very different from how Linux - * branded processes are implemented within lx branded zones. - * In that situation, the primary linkmap of the process is the - * brand emulation libraries linkmap, not the Linux applications - * linkmap. - * - * We also need to clear the AF_SUN_NOPLM flag from the AT_SUN_AUXFLAGS - * aux vector. This flag told our linker that we don't have a - * primary link map. Now that our linker is done initializing, we - * want to clear this flag before we transfer control to the - * applications copy of the linker, since we want that linker to have - * a primary link map which will be the link map for the application - * we're running. - */ - p++; - for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) { - switch (ap->a_type) { - case AT_BASE: - /* Hide AT_BASE if static binary */ - if (sed.sed_base == NULL) { - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - } else { - ap->a_un.a_val = sed.sed_base; - } - break; - case AT_ENTRY: - ap->a_un.a_val = sed.sed_entry; - break; - case AT_PHDR: - ap->a_un.a_val = sed.sed_phdr; - break; - case AT_PHENT: - ap->a_un.a_val = sed.sed_phent; - break; - case AT_PHNUM: - ap->a_un.a_val = sed.sed_phnum; - break; - case AT_SUN_AUXFLAGS: - ap->a_un.a_val &= ~AF_SUN_NOPLM; - break; - case AT_SUN_EMULATOR: - /* - * ld.so.1 inspects AT_SUN_EMULATOR to see if - * if it is the linker for the brand emulation - * library. Hide AT_SUN_EMULATOR, as the - * linker we are about to jump to is the linker - * for the binary. - */ - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - break; - case AT_SUN_LDDATA: - /* Hide AT_SUN_LDDATA if static binary */ - if (sed.sed_lddata == NULL) { - ap->a_type = AT_IGNORE; - ap->a_un.a_val = NULL; - } else { - ap->a_un.a_val = sed.sed_lddata; - } - break; - default: - break; - } - } + ldentry = brand_post_init(S10_VERSION, argc, argv, envp); - s10_runexe(argv, sed.sed_ldentry); + brand_runexe(argv, ldentry); /*NOTREACHED*/ - s10_abort(0, "s10_runexe() returned"); + brand_abort(0, "brand_runexe() returned"); return (-1); } /* * This table must have at least NSYSCALL entries in it. * - * The second parameter of each entry in the s10_sysent_table + * The second parameter of each entry in the brand_sysent_table * contains the number of parameters and flags that describe the * syscall return value encoding. See the block comments at the * top of this file for more information about the syscall return * value flags and when they should be used. */ -s10_sysent_table_t s10_sysent_table[] = { +brand_sysent_table_t brand_sysent_table[] = { #if defined(__sparc) && !defined(__sparcv9) - EMULATE(s10_indir, 9 | RV_64RVAL), /* 0 */ + EMULATE(brand_indir, 9 | RV_64RVAL), /* 0 */ #else NOSYS, /* 0 */ #endif diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/s10_deleted.c b/usr/src/lib/brand/solaris10/s10_brand/common/s10_deleted.c index fbd9a4de6d..d75413a22f 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/common/s10_deleted.c +++ b/usr/src/lib/brand/solaris10/s10_brand/common/s10_deleted.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdio.h> @@ -38,6 +37,7 @@ #include <sys/syscall.h> #include <s10_brand.h> +#include <brand_misc.h> #include <s10_misc.h> /* @@ -293,7 +293,7 @@ s10_utime(sysret_t *rval, const char *path, const struct utimbuf *times) if (times == NULL) { tsp = NULL; } else { - if (s10_uucopy(times, <imes, sizeof (ltimes)) != 0) + if (brand_uucopy(times, <imes, sizeof (ltimes)) != 0) return (EFAULT); ts[0].tv_sec = ltimes.actime; ts[0].tv_nsec = 0; @@ -316,7 +316,7 @@ s10_utimes(sysret_t *rval, const char *path, const struct timeval times[2]) if (times == NULL) { tsp = NULL; } else { - if (s10_uucopy(times, ltimes, sizeof (ltimes)) != 0) + if (brand_uucopy(times, ltimes, sizeof (ltimes)) != 0) return (EFAULT); ts[0].tv_sec = ltimes[0].tv_sec; ts[0].tv_nsec = ltimes[0].tv_usec * 1000; @@ -340,7 +340,7 @@ s10_futimesat(sysret_t *rval, if (times == NULL) { tsp = NULL; } else { - if (s10_uucopy(times, ltimes, sizeof (ltimes)) != 0) + if (brand_uucopy(times, ltimes, sizeof (ltimes)) != 0) return (EFAULT); ts[0].tv_sec = ltimes[0].tv_sec; ts[0].tv_nsec = ltimes[0].tv_usec * 1000; diff --git a/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c b/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c index ff012812d7..d5b337cc6c 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c +++ b/usr/src/lib/brand/solaris10/s10_brand/common/s10_signal.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -35,6 +34,7 @@ #include <signal.h> #include <s10_brand.h> +#include <brand_misc.h> #include <s10_misc.h> #include <s10_signal.h> @@ -192,7 +192,7 @@ s10sigset_to_native(const sigset_t *s10_set, sigset_t *native_set) int nativesig; sigset_t srcset, newset; - if (s10_uucopy(s10_set, &srcset, sizeof (sigset_t)) != 0) + if (brand_uucopy(s10_set, &srcset, sizeof (sigset_t)) != 0) return (EFAULT); (void) sigemptyset(&newset); @@ -217,7 +217,7 @@ s10sigset_to_native(const sigset_t *s10_set, sigset_t *native_set) SIGADDSET(&newset, nativesig); } - if (s10_uucopy(&newset, native_set, sizeof (sigset_t)) != 0) + if (brand_uucopy(&newset, native_set, sizeof (sigset_t)) != 0) return (EFAULT); return (0); @@ -263,7 +263,7 @@ nativesigset_to_s10(const sigset_t *native_set, sigset_t *s10_set) int s10sig; sigset_t srcset, newset; - if (s10_uucopy(native_set, &srcset, sizeof (sigset_t)) != 0) + if (brand_uucopy(native_set, &srcset, sizeof (sigset_t)) != 0) return (EFAULT); (void) sigemptyset(&newset); @@ -288,7 +288,7 @@ nativesigset_to_s10(const sigset_t *native_set, sigset_t *s10_set) SIGADDSET(&newset, s10sig); } - if (s10_uucopy(&newset, s10_set, sizeof (sigset_t)) != 0) + if (brand_uucopy(&newset, s10_set, sizeof (sigset_t)) != 0) return (EFAULT); return (0); @@ -307,7 +307,7 @@ s10_sigacthandler(int sig, siginfo_t *sip, void *uvp) s10_sig = nativesig_to_s10(sig); if (s10_sig <= 0) /* can't happen? */ - s10_abort(sig, "Received an impossible signal"); + brand_abort(sig, "Received an impossible signal"); if (sip != NULL) { /* * All we really have to do is map the signal number, @@ -316,7 +316,7 @@ s10_sigacthandler(int sig, siginfo_t *sip, void *uvp) * same between s10 and native. */ if (sip->si_signo != sig) /* can't happen? */ - s10_abort(sig, "Received an impossible siginfo"); + brand_abort(sig, "Received an impossible siginfo"); sip->si_signo = s10_sig; } if ((ucp = uvp) != NULL && @@ -404,7 +404,7 @@ s10_sigsuspend(sysret_t *rval, const sigset_t *set) int err; if ((err = s10sigset_to_native(set, &sigset_set)) != 0) { - (void) S10_TRUSS_POINT_1(rval, SYS_sigsuspend, err, set); + (void) B_TRUSS_POINT_1(rval, SYS_sigsuspend, err, set); return (err); } @@ -439,7 +439,7 @@ s10_sigaction(sysret_t *rval, void (*handler)(); if ((nativesig = s10sig_to_native(sig)) < 0) { - (void) S10_TRUSS_POINT_3(rval, SYS_sigaction, EINVAL, + (void) B_TRUSS_POINT_3(rval, SYS_sigaction, EINVAL, sig, act, oact); return (EINVAL); } @@ -449,12 +449,12 @@ s10_sigaction(sysret_t *rval, } else { sigactp = &sigact; - if (s10_uucopy(act, sigactp, sizeof (struct sigaction)) != 0) + if (brand_uucopy(act, sigactp, sizeof (struct sigaction)) != 0) return (EFAULT); if ((err = s10sigset_to_native(&sigactp->sa_mask, &sigactp->sa_mask)) != 0) { - (void) S10_TRUSS_POINT_3(rval, SYS_sigaction, err, + (void) B_TRUSS_POINT_3(rval, SYS_sigaction, err, sig, act, oact); return (err); } @@ -488,8 +488,8 @@ s10_sigaction(sysret_t *rval, if (osigactp->sa_handler == s10_sigacthandler) osigactp->sa_handler = s10_handlers[sig - 1]; - if (err == 0 && - s10_uucopy(osigactp, oact, sizeof (struct sigaction)) != 0) + if (err == 0 && brand_uucopy(osigactp, oact, + sizeof (struct sigaction)) != 0) err = EFAULT; } @@ -541,7 +541,7 @@ s10_sigsendsys(sysret_t *rval, procset_t *psp, int sig) int nativesig; if ((nativesig = s10sig_to_native(sig)) < 0) { - (void) S10_TRUSS_POINT_2(rval, SYS_sigsendsys, EINVAL, + (void) B_TRUSS_POINT_2(rval, SYS_sigsendsys, EINVAL, psp, sig); return (EINVAL); } @@ -639,7 +639,7 @@ s10_sigtimedwait(sysret_t *rval, int err, sig; if ((err = s10sigset_to_native(set, &sigset_set)) != 0) { - (void) S10_TRUSS_POINT_3(rval, SYS_sigtimedwait, err, + (void) B_TRUSS_POINT_3(rval, SYS_sigtimedwait, err, set, info, timeout); return (err); } @@ -682,7 +682,7 @@ s10_sigqueue(sysret_t *rval, pid_t pid, int signo, void *value, int si_code) int nativesig; if ((nativesig = s10sig_to_native(signo)) < 0) { - (void) S10_TRUSS_POINT_4(rval, SYS_sigqueue, EINVAL, + (void) B_TRUSS_POINT_4(rval, SYS_sigqueue, EINVAL, pid, signo, value, si_code); return (EINVAL); } @@ -715,11 +715,11 @@ s10_signotify(sysret_t *rval, if (cmd == SN_PROC) { int nativesig; - if (s10_uucopy(infop, &info, sizeof (siginfo_t)) != 0) + if (brand_uucopy(infop, &info, sizeof (siginfo_t)) != 0) return (EFAULT); if ((nativesig = s10sig_to_native(info.si_signo)) < 0) { - (void) S10_TRUSS_POINT_3(rval, SYS_signotify, EINVAL, + (void) B_TRUSS_POINT_3(rval, SYS_signotify, EINVAL, cmd, siginfo, sn_id); return (EINVAL); } @@ -740,7 +740,7 @@ s10_kill(sysret_t *rval, pid_t pid, int sig) int nativesig; if ((nativesig = s10sig_to_native(sig)) < 0) { - (void) S10_TRUSS_POINT_2(rval, SYS_kill, EINVAL, pid, sig); + (void) B_TRUSS_POINT_2(rval, SYS_kill, EINVAL, pid, sig); return (EINVAL); } @@ -761,7 +761,7 @@ s10_lwp_create(sysret_t *rval, ucontext_t *ucp, int flags, id_t *new_lwp) { ucontext_t s10_uc; - if (s10_uucopy(ucp, &s10_uc, sizeof (ucontext_t)) != 0) + if (brand_uucopy(ucp, &s10_uc, sizeof (ucontext_t)) != 0) return (EFAULT); if (s10_uc.uc_flags & UC_SIGMASK) @@ -781,7 +781,7 @@ s10_lwp_kill(sysret_t *rval, id_t lwpid, int sig) int nativesig; if ((nativesig = s10sig_to_native(sig)) < 0) { - (void) S10_TRUSS_POINT_2(rval, SYS_lwp_kill, EINVAL, + (void) B_TRUSS_POINT_2(rval, SYS_lwp_kill, EINVAL, lwpid, sig); return (EINVAL); } diff --git a/usr/src/lib/brand/solaris10/s10_brand/i386/Makefile b/usr/src/lib/brand/solaris10/s10_brand/i386/Makefile index 2d41a3f455..8f6a505876 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/i386/Makefile +++ b/usr/src/lib/brand/solaris10/s10_brand/i386/Makefile @@ -19,14 +19,15 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/i386/pics include ../Makefile.com +CPPFLAGS += -I$(BRAND_SHARED)/brand/i386 + # # see ../Makefile.com for why we explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s b/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s deleted file mode 100644 index 1b2f5e5313..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_handler.s +++ /dev/null @@ -1,195 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <s10_misc.h> - -/* - * Each JMP must occupy 16 bytes - */ -#define JMP \ - pushl $_CONST(. - s10_handler_table); \ - jmp s10_handler; \ - .align 16; - -#define JMP4 JMP; JMP; JMP; JMP -#define JMP16 JMP4; JMP4; JMP4; JMP4 -#define JMP64 JMP16; JMP16; JMP16; JMP16 -#define JMP256 JMP64; JMP64; JMP64; JMP64 - -#if defined(lint) - -void -s10_handler_table(void) -{} - -void -s10_handler(void) -{ -} - -#else /* lint */ - - /* - * On entry to this table, %eax will hold the return address. The - * location where we enter the table is a function of the system - * call number. The table needs the same alignment as the individual - * entries. - */ - .align 16 - ENTRY_NP(s10_handler_table) - JMP256 - SET_SIZE(s10_handler_table) - -#define PIC_SETUP(r) \ - call 9f; \ -9: \ - popl r; \ - addl $_GLOBAL_OFFSET_TABLE_ + [. - 9b], r - - /* - * %eax - userland return address - * stack contains: - * | -------------------------------------- - * v 4 | syscall arguments | - * %esp+0 | syscall number | - * -------------------------------------- - */ - ENTRY_NP(s10_handler) - pushl %ebp /* allocate a stack frame */ - movl %esp, %ebp - - /* Save registers at the time of the syscall. */ - movl $0, EH_LOCALS_GREG(TRAPNO)(%ebp) - movl $0, EH_LOCALS_GREG(ERR)(%ebp) - movl %ebx, EH_LOCALS_GREG(EBX)(%ebp) - movl %ecx, EH_LOCALS_GREG(ECX)(%ebp) - movl %edx, EH_LOCALS_GREG(EDX)(%ebp) - movl %edi, EH_LOCALS_GREG(EDI)(%ebp) - movl %esi, EH_LOCALS_GREG(ESI)(%ebp) - mov %cs, EH_LOCALS_GREG(CS)(%ebp) - mov %ds, EH_LOCALS_GREG(DS)(%ebp) - mov %es, EH_LOCALS_GREG(ES)(%ebp) - mov %fs, EH_LOCALS_GREG(FS)(%ebp) - mov %gs, EH_LOCALS_GREG(GS)(%ebp) - pushfl /* save syscall flags */ - popl %ecx - movl %ecx, EH_LOCALS_GREG(EFL)(%ebp) - movl EH_ARGS_OFFSET(0)(%ebp), %ecx /* save syscall ebp */ - movl %ecx, EH_LOCALS_GREG(EBP)(%ebp) - movl %ebp, %ecx /* save syscall esp */ - addl $CPTRSIZE, %ecx - movl %ecx, EH_LOCALS_GREG(ESP)(%ebp) - - /* - * The kernel drops us into the middle of the s10_handle_table - * above that then pushes that table offset onto the stack, and calls - * into s10_handler. That offset indicates the system call number while - * %eax holds the return address for the system call. We replace the - * value on the stack with the return address, and use the value to - * compute the system call number by dividing by the table entry size. - */ - xchgl CPTRSIZE(%ebp), %eax /* swap JMP table offset and ret addr */ - shrl $4, %eax /* table_offset/size = syscall num */ - movl %eax, EH_LOCALS_GREG(EAX)(%ebp) /* save syscall num */ - - /* - * Finish setting up our stack frame. We would normally do this - * upon entry to this function, but in this case we delayed it - * because a "sub" operation can modify flags and we wanted to - * save the flags into the gregset_t above before they get modified. - * - * Our stack frame format is documented in s10_misc.h. - */ - subl $EH_LOCALS_SIZE, %esp - - /* Look up the system call's entry in the sysent table */ - PIC_SETUP(%ecx) - movl s10_sysent_table@GOT(%ecx), %edx /* %edx = sysent_table */ - shll $3, %eax /* each entry is 8 bytes */ - add %eax, %edx /* %edx = sysent entry address */ - - /* - * Get the return value flag and the number of arguments from the - * sysent table. - */ - movl CPTRSIZE(%edx), %ecx /* number of args + rv flag */ - andl $RV_MASK, %ecx /* strip out number of args */ - movl %ecx, EH_LOCALS_RVFLAG(%ebp) /* save rv flag */ - movl CPTRSIZE(%edx), %ecx /* number of args + rv flag */ - andl $NARGS_MASK, %ecx /* strip out rv flag */ - - /* - * Setup arguments for our emulation call. Our input arguments, - * 0 to N, will become emulation call arguments 1 to N+1. - * %ecx == number of arguments. - */ - movl %ebp, %esi /* args are at 12(%ebp) */ - addl $EH_ARGS_OFFSET(3), %esi - movl %esp, %edi /* copy args to 4(%esp) */ - addl $EH_ARGS_OFFSET(1), %edi - rep; smovl /* copy: (%esi) -> (%edi) */ - /* copy: %ecx 32-bit words */ - movl EH_LOCALS_GREG(ESI)(%ebp), %esi /* restore %esi */ - movl EH_LOCALS_GREG(EDI)(%ebp), %edi /* restore %edi */ - - /* - * The first parameter to the emulation callback function is a - * pointer to a sysret_t structure. - */ - movl %ebp, %ecx - addl $EH_LOCALS_SYSRET, %ecx - movl %ecx, EH_ARGS_OFFSET(0)(%esp) /* arg0 == sysret_t ptr */ - - /* invoke the emulation routine */ - ALTENTRY(s10_handler_savepc) - call *(%edx) /* call emulation routine */ - - /* restore scratch registers */ - movl EH_LOCALS_GREG(ECX)(%ebp), %ecx /* restore %ecx */ - movl EH_LOCALS_GREG(EDX)(%ebp), %edx /* restore %edx */ - - /* Check for syscall emulation success or failure */ - cmpl $0, %eax /* check for an error */ - je success - stc /* failure, set carry flag */ - jmp return /* return, %rax == errno */ - -success: - /* There is always at least one return value. */ - movl EH_LOCALS_SYSRET1(%ebp), %eax /* %eax == sys_rval1 */ - cmpl $RV_DEFAULT, EH_LOCALS_RVFLAG(%ebp) /* check rv flag */ - je clear_carry - mov EH_LOCALS_SYSRET2(%ebp), %edx /* %edx == sys_rval2 */ -clear_carry: - clc /* success, clear carry flag */ - -return: - movl %ebp, %esp /* restore stack */ - popl %ebp - ret /* ret to instr after syscall */ - SET_SIZE(s10_handler) - - -#endif /* lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_runexe.s b/usr/src/lib/brand/solaris10/s10_brand/i386/s10_runexe.s deleted file mode 100644 index 13cfb9d4b8..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/i386/s10_runexe.s +++ /dev/null @@ -1,80 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> -#include <s10_misc.h> - -#if defined(lint) - -/*ARGSUSED*/ -void -s10_runexe(void *argv, ulong_t entry) -{ -} - -#else /* lint */ - /* - * Prepare to jump to the target program we actually want to run. - * If this program is dynamically linked then we'll be jumping to - * another copy of the linker. If it's a statically linked program - * we'll be jumping directy to it's main entry point. In any case, - * we need to reset our current state stack and register state to - * something similar to the initial process state setup by the kernel - * and documented at: - * usr/src/cmd/sgs/rtld/i386/boot.s - * usr/src/cmd/sgs/rtld/sparcv9/boot.s - * - * Of course this is the same stack format as when this executable - * was first started, so here we'll just roll back the stack and - * frame pointers to their values when this processes first started - * execution. - */ - ENTRY_NP(s10_runexe) - - movl 4(%esp), %eax / %eax = &argv[0] - movl 8(%esp), %ebx / Brand app entry point in %ebx - subl $4, %eax / Top of stack - must point at argc - movl %eax, %esp / Set %esp to what linkers expect - - /* - * We also have to make sure to clear %edx since nornally ld.so.1 will - * set that to non-zero if there is an exit function that should be - * invoked when the process is terminating. This isn't actually - * necessary if the target program we're jumping to is a dynamically - * linked program since in that case we're actually jumping to another - * copy of ld.so.1 and it will just reset %edx, but if the target - * program we're jumping to is a statically linked binary that uses - * the standard sun compiler supplied crt1.o`_start(), it will check - * to see if %g1 is set. - */ - movl $0, %edx - - jmp *%ebx / And away we go... - /* - * target will never return. - */ - SET_SIZE(s10_runexe) -#endif /* lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/sparc/Makefile b/usr/src/lib/brand/solaris10/s10_brand/sparc/Makefile index 3cfd1f8496..52a71ae1bc 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/sparc/Makefile +++ b/usr/src/lib/brand/solaris10/s10_brand/sparc/Makefile @@ -19,14 +19,15 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -ISASRCDIR = . +ISAOBJDIR = $(BRAND_SHARED)/brand/sparc/pics include ../Makefile.com +CPPFLAGS += -I$(BRAND_SHARED)/brand/sparc + # # see ../Makefile.com for why we MUST explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_crt.s b/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_crt.s deleted file mode 100644 index 7d44642286..0000000000 --- a/usr/src/lib/brand/solaris10/s10_brand/sparc/s10_crt.s +++ /dev/null @@ -1,80 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/asm_linkage.h> -#include <sys/link.h> - -#if defined(lint) - -void -_start(void) -{ -} - -#else /* lint */ - .section ".text" - /* - * Initial entry point for the brand emulation library. - * - * This platform specific assembly entry point exists just to invoke - * the common brand library startup routine. That routine expects to - * be called with the following arguments: - * s10_init(int argc, char *argv[], char *envp[]) - * - * There are no arguments explicitly passed to this entry point, - * routine, but we do know how our initial stack has been setup by - * the kernel. The stack format is documented in: - * usr/src/cmd/sgs/rtld/sparc/boot.s - * usr/src/cmd/sgs/rtld/sparcv9/boot.s - * - * So this routine will troll through the stack to setup the argument - * values for the common brand library startup routine and then invoke - * it. - */ - ENTRY_NP(_start) -#if defined (__sparcv9) - save %sp, -SA(MINFRAME + EB_MAX_SIZE64), %sp -#else /* !__sparcv9 */ - save %sp, -SA(MINFRAME + EB_MAX_SIZE32), %sp -#endif /* !__sparcv9 */ - - /* get argc */ - ldn [%fp + WINDOWSIZE + STACK_BIAS], %o0 - - /* get argv */ - add %fp, + WINDOWSIZE + CPTRSIZE + STACK_BIAS, %o1 - - /* get envp */ - add %o0, 1, %l0 ! add 1 to argc for last element of 0 - sll %l0, CPTRSHIFT, %l0 ! multiply argc by pointer size - add %o1, %l0, %o2 ! and add to argv to get first env ptr - - call s10_init - nop - - /*NOTREACHED*/ - SET_SIZE(_start) -#endif /* lint */ diff --git a/usr/src/lib/brand/solaris10/s10_brand/sparcv9/Makefile b/usr/src/lib/brand/solaris10/s10_brand/sparcv9/Makefile index 5d62c05faa..a6d7c0b1b5 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/sparcv9/Makefile +++ b/usr/src/lib/brand/solaris10/s10_brand/sparcv9/Makefile @@ -19,15 +19,16 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # -ISASRCDIR = ../sparc +ISAOBJDIR = $(BRAND_SHARED)/brand/sparcv9/pics include ../Makefile.com include $(SRC)/lib/Makefile.lib.64 +CPPFLAGS += -I$(BRAND_SHARED)/brand/sparcv9 + # # see ../Makefile.com for why we explicity make ld.so.1 our interpreter # diff --git a/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h b/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h index 972fa03d4c..d68833060f 100644 --- a/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h +++ b/usr/src/lib/brand/solaris10/s10_brand/sys/s10_misc.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _S10_MISC_H @@ -30,170 +29,9 @@ extern "C" { #endif -/* - * This header file must uses _ASM defines to allow it to be included - * in assmebly source files - */ -#include <sys/asm_linkage.h> -#include <sys/regset.h> -#include <sys/syscall.h> -#include "assym.h" - -/* - * Our syscall emulation callback handler adds one argument to each - * system call, so we'll need to allocate space for one more argument - * above the maximum number of arguments that a system call can normally - * take. Also, we assume that each syscall argument is a long, ie, we - * don't support long long syscall parameters. - */ -#if defined(__sparc) -/* - * 32-bit and 64-bit sparc syscalls can take up to 8 arguments. - * 32-bit sparc indirect syscalls can take up to 9 arguments. - * Arguments 1 - 6 are passed via %o0 - %o5. - * Additional arguments are passed on the stack. - * So make space for 4 arguments on the stack. - */ -#define EH_ARGS_COUNT 4 -#elif defined(__amd64) -/* - * amd64 syscalls can take up to 8 arguments. - * Arguments 1 - 6 are passed via: %rdi, %rsi, %rdx, %r10, %r8, %r9 - * Additional arguments are passed on the stack. - * So make space for 3 arguments on the stack. - */ -#define EH_ARGS_COUNT 3 -#else /* !__sparc && !__amd64 */ -/* - * ia32 syscalls can take up to 8 arguments. - * All arguments are passed on the stack. - * So make space for 9 arguments on the stack. - */ -#define EH_ARGS_COUNT 9 -#endif /* !__sparc && !__amd64 */ - - -#define EH_ARGS_SIZE (CPTRSIZE * EH_ARGS_COUNT) -#define EH_ARGS_OFFSET(x) (STACK_BIAS + MINFRAME + (CPTRSIZE * (x))) -#define EH_LOCALS_SIZE (EH_ARGS_SIZE + SIZEOF_GREGSET_T + \ - SIZEOF_SYSRET_T + CPTRSIZE) - -#if defined(__sparc) -/* - * On sparc, all emulation callback handler variable access is done - * relative to %sp, so access offsets are positive. - */ -#define EH_LOCALS_START (STACK_BIAS + MINFRAME + EH_ARGS_SIZE) -#define EH_LOCALS_END_TGT (STACK_BIAS + MINFRAME + EH_LOCALS_SIZE) -#else /* !__sparc */ -/* - * On x86, all emulation callback handler variable access is done - * relative to %ebp/%rbp, so access offsets are negative. - */ -#define EH_LOCALS_START (-(EH_LOCALS_SIZE - \ - (STACK_BIAS + MINFRAME + EH_ARGS_SIZE))) -#define EH_LOCALS_END_TGT 0 -#endif /* !__sparc */ - -/* - * In our emulation callback handler, our stack will look like: - * ------------------------------------------------- - * %bp | long rvflag | - * | | sysret_t sysret | - * v | gregset_t gregs | - * %sp | long callback args[EH_ARGS_COUNT] | - * ------------------------------------------------- - * For ia32, use %ebp and %esp instead of %bp and %sp. - * For amd64, use %rbp and %rsp instead of %bp and %sp. - * - * Our emulation callback handler always saves enough space to hold the - * maximum number of stack arguments to a system call. This is architecture - * specific and is defined via EH_ARGS_COUNT. - */ -#define EH_LOCALS_GREGS (EH_LOCALS_START) -#define EH_LOCALS_GREG(x) (EH_LOCALS_GREGS + (SIZEOF_GREG_T * (x))) -#define EH_LOCALS_SYSRET (EH_LOCALS_GREGS + SIZEOF_GREGSET_T) -#define EH_LOCALS_SYSRET1 (EH_LOCALS_SYSRET) -#define EH_LOCALS_SYSRET2 (EH_LOCALS_SYSRET + CPTRSIZE) -#define EH_LOCALS_RVFLAG (EH_LOCALS_SYSRET + SIZEOF_SYSRET_T) -#define EH_LOCALS_END (EH_LOCALS_RVFLAG + CPTRSIZE) - -#if (EH_LOCALS_END != EH_LOCALS_END_TGT) -#error "s10_misc.h EH_LOCALS_* macros don't add up" -#endif /* (EH_LOCALS_END != EH_LOCALS_END_TGT) */ - -/* - * The second parameter of each entry in the s10_sysent_table - * contains the number of parameters and flags that describe the - * syscall return value encoding. See the block comments at the - * top of ../common/s10_brand.c for more information about the - * syscall return value flags and when they should be used. - */ -#define NARGS_MASK 0x000000FF /* Mask for syscalls argument count */ -#define RV_MASK 0x0000FF00 /* Mask for return value flags */ -#define RV_DEFAULT 0x00000100 /* syscall returns "default" values */ -#define RV_32RVAL2 0x00000200 /* syscall returns two 32-bit values */ -#define RV_64RVAL 0x00000400 /* syscall returns a 64-bit value */ - #if !defined(_ASM) /* - * We define our own version of assert because the default one will - * try to emit a localized message. That is bad because first, we can't - * emit messages to random file descriptors, and second localizing a message - * requires allocating memory and we can't do that either. - */ -#define s10_assert(ex) (void)((ex) || \ - (_s10_abort(0, #ex, __FILE__, __LINE__), 0)) -#define s10_abort(err, msg) _s10_abort((err), (msg), __FILE__, __LINE__) - -/* - * These macros invoke a brandsys subcommand, B_S10_TRUSS_POINT, used to expose - * a call to an interpositioned syscall that would have otherwise gone - * unnoticed by truss(1) because the interpositioned system call did not call - * any system calls before returning. - */ -#define S10_TRUSS_POINT_5(rval, syscall_num, err, a0, a1, a2, a3, a4) \ - __systemcall(rval, SYS_brand + 1024, \ - B_S10_TRUSS_POINT, (syscall_num), (err), (a0), (a1), (a2), (a3), \ - (a4)) - -#define S10_TRUSS_POINT_4(rval, syscall_num, err, a0, a1, a2, a3) \ - S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), (a3), 0) - -#define S10_TRUSS_POINT_3(rval, syscall_num, err, a0, a1, a2) \ - S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), (a2), 0, 0) - -#define S10_TRUSS_POINT_2(rval, syscall_num, err, a0, a1) \ - S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), (a1), 0, 0, 0) - -#define S10_TRUSS_POINT_1(rval, syscall_num, err, a0) \ - S10_TRUSS_POINT_5(rval, (syscall_num), (err), (a0), 0, 0, 0, 0) - -#define S10_TRUSS_POINT_0(rval, syscall_num, err) \ - S10_TRUSS_POINT_5(rval, (syscall_num), (err), 0, 0, 0, 0, 0) - -/* - * From s10_runexe.s - */ -extern void s10_runexe(void *, ulong_t); - -/* - * From s10_handler.s - */ -extern void s10_handler_table(void); -extern void s10_handler(void); -extern void s10_error(void); -extern void s10_success(void); - -/* - * From s10_brand.c - */ -extern void _s10_abort(int, const char *, const char *, int); -extern int s10_uucopy(const void *, void *, size_t); -extern int s10_uucopystr(const void *, void *, size_t); - -/* * From s10_deleted.c */ extern int s10_stat(); diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.c b/usr/src/uts/common/brand/sn1/sn1_brand.c index afc3cf48f3..bcca361192 100644 --- a/usr/src/uts/common/brand/sn1/sn1_brand.c +++ b/usr/src/uts/common/brand/sn1/sn1_brand.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/errno.h> @@ -135,17 +134,7 @@ static struct modlinkage modlinkage = { void sn1_setbrand(proc_t *p) { - ASSERT(p->p_brand == &sn1_brand); - ASSERT(p->p_brand_data == NULL); - - /* - * We should only be called from exec(), when we know the process - * is single-threaded. - */ - ASSERT(p->p_tlist == p->p_tlist->t_forw); - - p->p_brand_data = kmem_zalloc(sizeof (sn1_proc_data_t), KM_SLEEP); - (void) sn1_initlwp(p->p_tlist->t_lwp); + brand_solaris_setbrand(p, &sn1_brand); } /* ARGSUSED */ @@ -162,213 +151,62 @@ sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize) return (EINVAL); } -/* - * Get the address of the user-space system call handler from the user - * process and attach it to the proc structure. - */ /*ARGSUSED*/ int sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6) { - sn1_proc_data_t *spd; - sn1_brand_reg_t reg; - proc_t *p = curproc; - int err; + int res; *rval = 0; - /* - * There is one operation that is suppored for non-branded - * process. B_EXEC_BRAND. This brand operaion is redundant - * since the kernel assumes a native process doing an exec - * in a branded zone is going to run a branded processes. - * hence we don't support this operation. - */ - if (cmd == B_EXEC_BRAND) - return (ENOSYS); - - /* For all other operations this must be a branded process. */ - if (p->p_brand == &native_brand) - return (ENOSYS); - - ASSERT(p->p_brand == &sn1_brand); - ASSERT(p->p_brand_data != NULL); - - spd = (sn1_proc_data_t *)p->p_brand_data; - - switch (cmd) { - case B_EXEC_NATIVE: - err = exec_common( - (char *)arg1, (const char **)arg2, (const char **)arg3, - EBA_NATIVE); - return (err); - - case B_REGISTER: - if (p->p_model == DATAMODEL_NATIVE) { - if (copyin((void *)arg1, ®, sizeof (reg)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - sn1_brand_reg32_t reg32; - - if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0) - return (EFAULT); - reg.sbr_version = reg32.sbr_version; - reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler; -#endif /* _LP64 */ - } - - if (reg.sbr_version != SN1_VERSION) - return (ENOTSUP); - spd->spd_handler = reg.sbr_handler; - return (0); - case B_ELFDATA: - if (p->p_model == DATAMODEL_NATIVE) { - if (copyout(&spd->spd_elf_data, (void *)arg1, - sizeof (sn1_elf_data_t)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - sn1_elf_data32_t sed32; - - sed32.sed_phdr = spd->spd_elf_data.sed_phdr; - sed32.sed_phent = spd->spd_elf_data.sed_phent; - sed32.sed_phnum = spd->spd_elf_data.sed_phnum; - sed32.sed_entry = spd->spd_elf_data.sed_entry; - sed32.sed_base = spd->spd_elf_data.sed_base; - sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry; - sed32.sed_lddata = spd->spd_elf_data.sed_lddata; - if (copyout(&sed32, (void *)arg1, sizeof (sed32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - return (0); - } + res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &sn1_brand, SN1_VERSION); + if (res >= 0) + return (res); return (EINVAL); } -/* - * Copy the per-process brand data from a parent proc to a child. - */ void sn1_copy_procdata(proc_t *child, proc_t *parent) { - sn1_proc_data_t *spd; - - ASSERT(parent->p_brand == &sn1_brand); - ASSERT(child->p_brand == &sn1_brand); - ASSERT(parent->p_brand_data != NULL); - ASSERT(child->p_brand_data == NULL); - - /* Just duplicate all the proc data of the parent for the child */ - spd = kmem_alloc(sizeof (sn1_proc_data_t), KM_SLEEP); - bcopy(parent->p_brand_data, spd, sizeof (sn1_proc_data_t)); - child->p_brand_data = spd; + brand_solaris_copy_procdata(child, parent, &sn1_brand); } -/*ARGSUSED*/ void sn1_proc_exit(struct proc *p, klwp_t *l) { - ASSERT(p->p_brand == &sn1_brand); - ASSERT(p->p_brand_data != NULL); - - /* - * We should only be called from proc_exit(), when we know that - * process is single-threaded. - */ - ASSERT(p->p_tlist == p->p_tlist->t_forw); - - /* upon exit, free our lwp brand data */ - (void) sn1_freelwp(ttolwp(curthread)); - - /* upon exit, free our proc brand data */ - kmem_free(p->p_brand_data, sizeof (sn1_proc_data_t)); - p->p_brand_data = NULL; + brand_solaris_proc_exit(p, l, &sn1_brand); } void sn1_exec() { - sn1_proc_data_t *spd = curproc->p_brand_data; - - ASSERT(curproc->p_brand == &sn1_brand); - ASSERT(curproc->p_brand_data != NULL); - ASSERT(ttolwp(curthread)->lwp_brand != NULL); - - /* - * We should only be called from exec(), when we know the process - * is single-threaded. - */ - ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw); - - /* Upon exec, reset our lwp brand data. */ - (void) sn1_freelwp(ttolwp(curthread)); - (void) sn1_initlwp(ttolwp(curthread)); - - /* - * Upon exec, reset all the proc brand data, except for the elf - * data associated with the executable we are exec'ing. - */ - spd->spd_handler = NULL; + brand_solaris_exec(&sn1_brand); } -/*ARGSUSED*/ int sn1_initlwp(klwp_t *l) { - ASSERT(l->lwp_procp->p_brand == &sn1_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand == NULL); - l->lwp_brand = (void *)-1; - return (0); + return (brand_solaris_initlwp(l, &sn1_brand)); } -/*ARGSUSED*/ void sn1_forklwp(klwp_t *p, klwp_t *c) { - ASSERT(p->lwp_procp->p_brand == &sn1_brand); - ASSERT(c->lwp_procp->p_brand == &sn1_brand); - - ASSERT(p->lwp_procp->p_brand_data != NULL); - ASSERT(c->lwp_procp->p_brand_data != NULL); - - /* Both LWPs have already had been initialized via sn1_initlwp() */ - ASSERT(p->lwp_brand != NULL); - ASSERT(c->lwp_brand != NULL); + brand_solaris_forklwp(p, c, &sn1_brand); } -/*ARGSUSED*/ void sn1_freelwp(klwp_t *l) { - ASSERT(l->lwp_procp->p_brand == &sn1_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand != NULL); - l->lwp_brand = NULL; + brand_solaris_freelwp(l, &sn1_brand); } -/*ARGSUSED*/ void sn1_lwpexit(klwp_t *l) { - proc_t *p = l->lwp_procp; - - ASSERT(l->lwp_procp->p_brand == &sn1_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand != NULL); - - /* - * We should never be called for the last thread in a process. - * (That case is handled by sn1_proc_exit().) There for this lwp - * must be exiting from a multi-threaded process. - */ - ASSERT(p->p_tlist != p->p_tlist->t_forw); - - l->lwp_brand = NULL; + brand_solaris_lwpexit(l, &sn1_brand); } /*ARGSUSED*/ @@ -383,384 +221,16 @@ sn1_init_brand_data(zone_t *zone) { } -#if defined(_LP64) -static void -Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst) -{ - bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident)); - dst->e_type = src->e_type; - dst->e_machine = src->e_machine; - dst->e_version = src->e_version; - dst->e_entry = src->e_entry; - dst->e_phoff = src->e_phoff; - dst->e_shoff = src->e_shoff; - dst->e_flags = src->e_flags; - dst->e_ehsize = src->e_ehsize; - dst->e_phentsize = src->e_phentsize; - dst->e_phnum = src->e_phnum; - dst->e_shentsize = src->e_shentsize; - dst->e_shnum = src->e_shnum; - dst->e_shstrndx = src->e_shstrndx; -} -#endif /* _LP64 */ - int sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred, int brand_action) { - vnode_t *nvp; - Ehdr ehdr; - Addr uphdr_vaddr; - intptr_t voffset; - int interp; - int i, err; - struct execenv env; - struct user *up = PTOU(curproc); - sn1_proc_data_t *spd; - sn1_elf_data_t sed, *sedp; - char *linker; - uintptr_t lddata; /* lddata of executable's linker */ - - ASSERT(curproc->p_brand == &sn1_brand); - ASSERT(curproc->p_brand_data != NULL); - - spd = (sn1_proc_data_t *)curproc->p_brand_data; - sedp = &spd->spd_elf_data; - - args->brandname = SN1_BRANDNAME; - - /* - * We will exec the brand library and then map in the target - * application and (optionally) the brand's default linker. - */ - if (args->to_model == DATAMODEL_NATIVE) { - args->emulator = SN1_LIB; - linker = SN1_LINKER; -#if defined(_LP64) - } else { - args->emulator = SN1_LIB32; - linker = SN1_LINKER32; -#endif /* _LP64 */ - } - - if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, NULLVPP, - &nvp)) != 0) { - uprintf("%s: not found.", args->emulator); - return (err); - } - - if (args->to_model == DATAMODEL_NATIVE) { - err = elfexec(nvp, uap, args, idatap, level + 1, execsz, - setid, exec_file, cred, brand_action); -#if defined(_LP64) - } else { - err = elf32exec(nvp, uap, args, idatap, level + 1, execsz, - setid, exec_file, cred, brand_action); -#endif /* _LP64 */ - } - VN_RELE(nvp); - if (err != 0) - return (err); - - /* - * The u_auxv vectors are set up by elfexec to point to the brand - * emulation library and linker. Save these so they can be copied to - * the specific brand aux vectors. - */ - bzero(&sed, sizeof (sed)); - for (i = 0; i < __KERN_NAUXV_IMPL; i++) { - switch (up->u_auxv[i].a_type) { - case AT_SUN_LDDATA: - sed.sed_lddata = up->u_auxv[i].a_un.a_val; - break; - case AT_BASE: - sed.sed_base = up->u_auxv[i].a_un.a_val; - break; - case AT_ENTRY: - sed.sed_entry = up->u_auxv[i].a_un.a_val; - break; - case AT_PHDR: - sed.sed_phdr = up->u_auxv[i].a_un.a_val; - break; - case AT_PHENT: - sed.sed_phent = up->u_auxv[i].a_un.a_val; - break; - case AT_PHNUM: - sed.sed_phnum = up->u_auxv[i].a_un.a_val; - break; - default: - break; - } - } - /* Make sure the emulator has an entry point */ - ASSERT(sed.sed_entry != NULL); - ASSERT(sed.sed_phdr != NULL); - - bzero(&env, sizeof (env)); - if (args->to_model == DATAMODEL_NATIVE) { - err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, &voffset, - exec_file, &interp, &env.ex_bssbase, &env.ex_brkbase, - &env.ex_brksize, NULL); -#if defined(_LP64) - } else { - Elf32_Ehdr ehdr32; - Elf32_Addr uphdr_vaddr32; - err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32, - &voffset, exec_file, &interp, &env.ex_bssbase, - &env.ex_brkbase, &env.ex_brksize, NULL); - Ehdr32to64(&ehdr32, &ehdr); - if (uphdr_vaddr32 == (Elf32_Addr)-1) - uphdr_vaddr = (Addr)-1; - else - uphdr_vaddr = uphdr_vaddr32; -#endif /* _LP64 */ - } - if (err != 0) - return (err); - - /* - * Save off the important properties of the executable. The brand - * library will ask us for this data later, when it is initializing - * and getting ready to transfer control to the brand application. - */ - if (uphdr_vaddr == (Addr)-1) - sedp->sed_phdr = voffset + ehdr.e_phoff; - else - sedp->sed_phdr = voffset + uphdr_vaddr; - sedp->sed_entry = voffset + ehdr.e_entry; - sedp->sed_phent = ehdr.e_phentsize; - sedp->sed_phnum = ehdr.e_phnum; - - if (interp) { - if (ehdr.e_type == ET_DYN) { - /* - * This is a shared object executable, so we need to - * pick a reasonable place to put the heap. Just don't - * use the first page. - */ - env.ex_brkbase = (caddr_t)PAGESIZE; - env.ex_bssbase = (caddr_t)PAGESIZE; - } - - /* - * If the program needs an interpreter (most do), map it in and - * store relevant information about it in the aux vector, where - * the brand library can find it. - */ - if ((err = lookupname(linker, UIO_SYSSPACE, - FOLLOW, NULLVPP, &nvp)) != 0) { - uprintf("%s: not found.", SN1_LINKER); - return (err); - } - if (args->to_model == DATAMODEL_NATIVE) { - err = mapexec_brand(nvp, args, &ehdr, - &uphdr_vaddr, &voffset, exec_file, &interp, - NULL, NULL, NULL, &lddata); -#if defined(_LP64) - } else { - Elf32_Ehdr ehdr32; - Elf32_Addr uphdr_vaddr32; - err = mapexec32_brand(nvp, args, &ehdr32, - &uphdr_vaddr32, &voffset, exec_file, &interp, - NULL, NULL, NULL, &lddata); - Ehdr32to64(&ehdr32, &ehdr); - if (uphdr_vaddr32 == (Elf32_Addr)-1) - uphdr_vaddr = (Addr)-1; - else - uphdr_vaddr = uphdr_vaddr32; -#endif /* _LP64 */ - } - VN_RELE(nvp); - if (err != 0) - return (err); - - /* - * Now that we know the base address of the brand's linker, - * place it in the aux vector. - */ - sedp->sed_base = voffset; - sedp->sed_ldentry = voffset + ehdr.e_entry; - sedp->sed_lddata = voffset + lddata; - } else { - /* - * This program has no interpreter. The brand library will - * jump to the address in the AT_SUN_BRAND_LDENTRY aux vector, - * so in this case, put the entry point of the main executable - * there. - */ - if (ehdr.e_type == ET_EXEC) { - /* - * An executable with no interpreter, this must be a - * statically linked executable, which means we loaded - * it at the address specified in the elf header, in - * which case the e_entry field of the elf header is an - * absolute address. - */ - sedp->sed_ldentry = ehdr.e_entry; - sedp->sed_entry = ehdr.e_entry; - sedp->sed_lddata = NULL; - sedp->sed_base = NULL; - } else { - /* - * A shared object with no interpreter, we use the - * calculated address from above. - */ - sedp->sed_ldentry = sedp->sed_entry; - sedp->sed_entry = NULL; - sedp->sed_phdr = NULL; - sedp->sed_phent = NULL; - sedp->sed_phnum = NULL; - sedp->sed_lddata = NULL; - sedp->sed_base = voffset; - - if (ehdr.e_type == ET_DYN) { - /* - * Delay setting the brkbase until the first - * call to brk(); see elfexec() for details. - */ - env.ex_bssbase = (caddr_t)0; - env.ex_brkbase = (caddr_t)0; - env.ex_brksize = 0; - } - } - } - - env.ex_magic = elfmagic; - env.ex_vp = vp; - setexecenv(&env); - - /* - * It's time to manipulate the process aux vectors. First - * we need to update the AT_SUN_AUXFLAGS aux vector to set - * the AF_SUN_NOPLM flag. - */ - if (args->to_model == DATAMODEL_NATIVE) { - auxv_t auxflags_auxv; - - if (copyin(args->auxp_auxflags, &auxflags_auxv, - sizeof (auxflags_auxv)) != 0) - return (EFAULT); - - ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS); - auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM; - if (copyout(&auxflags_auxv, args->auxp_auxflags, - sizeof (auxflags_auxv)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - auxv32_t auxflags_auxv32; - - if (copyin(args->auxp_auxflags, &auxflags_auxv32, - sizeof (auxflags_auxv32)) != 0) - return (EFAULT); - - ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS); - auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM; - if (copyout(&auxflags_auxv32, args->auxp_auxflags, - sizeof (auxflags_auxv32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - - /* Second, copy out the brand specific aux vectors. */ - if (args->to_model == DATAMODEL_NATIVE) { - auxv_t sn1_auxv[] = { - { AT_SUN_BRAND_AUX1, 0 }, - { AT_SUN_BRAND_AUX2, 0 }, - { AT_SUN_BRAND_AUX3, 0 } - }; - - ASSERT(sn1_auxv[0].a_type == AT_SUN_BRAND_SN1_LDDATA); - sn1_auxv[0].a_un.a_val = sed.sed_lddata; - - if (copyout(&sn1_auxv, args->auxp_brand, - sizeof (sn1_auxv)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - auxv32_t sn1_auxv32[] = { - { AT_SUN_BRAND_AUX1, 0 }, - { AT_SUN_BRAND_AUX2, 0 }, - { AT_SUN_BRAND_AUX3, 0 } - }; - - ASSERT(sn1_auxv32[0].a_type == AT_SUN_BRAND_SN1_LDDATA); - sn1_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata; - if (copyout(&sn1_auxv32, args->auxp_brand, - sizeof (sn1_auxv32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - - /* - * Third, the the /proc aux vectors set up by elfexec() point to brand - * emulation library and it's linker. Copy these to the /proc brand - * specific aux vector, and update the regular /proc aux vectors to - * point to the executable (and it's linker). This will enable - * debuggers to access the executable via the usual /proc or elf notes - * aux vectors. - * - * The brand emulation library's linker will get it's aux vectors off - * the stack, and then update the stack with the executable's aux - * vectors before jumping to the executable's linker. - * - * Debugging the brand emulation library must be done from - * the global zone, where the librtld_db module knows how to fetch the - * brand specific aux vectors to access the brand emulation libraries - * linker. - */ - for (i = 0; i < __KERN_NAUXV_IMPL; i++) { - ulong_t val; - - switch (up->u_auxv[i].a_type) { - case AT_SUN_BRAND_SN1_LDDATA: - up->u_auxv[i].a_un.a_val = sed.sed_lddata; - continue; - case AT_BASE: - val = sedp->sed_base; - break; - case AT_ENTRY: - val = sedp->sed_entry; - break; - case AT_PHDR: - val = sedp->sed_phdr; - break; - case AT_PHENT: - val = sedp->sed_phent; - break; - case AT_PHNUM: - val = sedp->sed_phnum; - break; - case AT_SUN_LDDATA: - val = sedp->sed_lddata; - break; - default: - continue; - } - - up->u_auxv[i].a_un.a_val = val; - if (val == NULL) { - /* Hide the entry for static binaries */ - up->u_auxv[i].a_type = AT_IGNORE; - } - } - - /* - * The last thing we do here is clear spd->spd_handler. This is - * important because if we're already a branded process and if this - * exec succeeds, there is a window between when the exec() first - * returns to the userland of the new process and when our brand - * library get's initialized, during which we don't want system - * calls to be re-directed to our brand library since it hasn't - * been initialized yet. - */ - spd->spd_handler = NULL; - - return (0); + return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz, + setid, exec_file, cred, brand_action, &sn1_brand, SN1_BRANDNAME, + SN1_LIB, SN1_LIB32, SN1_LINKER, SN1_LINKER32)); } - int _init(void) { @@ -804,21 +274,6 @@ _info(struct modinfo *modinfop) int _fini(void) { - int err; - - /* - * If there are any zones using this brand, we can't allow it to be - * unloaded. - */ - if (brand_zone_count(&sn1_brand)) - return (EBUSY); - - kmem_free(sn1_emulation_table, NSYSCALL); - sn1_emulation_table = NULL; - - err = mod_remove(&modlinkage); - if (err) - cmn_err(CE_WARN, "Couldn't unload sn1 brand module"); - - return (err); + return (brand_solaris_fini(&sn1_emulation_table, &modlinkage, + &sn1_brand)); } diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.h b/usr/src/uts/common/brand/sn1/sn1_brand.h index 01c3b6f401..b487745e21 100644 --- a/usr/src/uts/common/brand/sn1/sn1_brand.h +++ b/usr/src/uts/common/brand/sn1/sn1_brand.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SN1_BRAND_H @@ -30,21 +29,20 @@ extern "C" { #endif -#include <sys/types.h> +#include <sys/brand.h> #define SN1_BRANDNAME "sn1" #define SN1_VERSION_1 1 #define SN1_VERSION SN1_VERSION_1 -#define SN1_NATIVE_DIR "/.SUNWnative/" #define SN1_LIB_NAME "sn1_brand.so.1" #define SN1_LINKER_NAME "ld.so.1" -#define SN1_LIB32 SN1_NATIVE_DIR "usr/lib/" SN1_LIB_NAME +#define SN1_LIB32 BRAND_NATIVE_DIR "usr/lib/" SN1_LIB_NAME #define SN1_LINKER32 "/lib/" SN1_LINKER_NAME -#define SN1_LIB64 SN1_NATIVE_DIR "usr/lib/64/" SN1_LIB_NAME +#define SN1_LIB64 BRAND_NATIVE_DIR "usr/lib/64/" SN1_LIB_NAME #define SN1_LINKER64 "/lib/64/" SN1_LINKER_NAME #if defined(_LP64) @@ -55,58 +53,7 @@ extern "C" { #define SN1_LINKER SN1_LINKER32 #endif /* !_LP64 */ -/* - * Aux vector containing lddata pointer of brand library linkmap. - * Used by lx_librtld_db. - */ -#define AT_SUN_BRAND_SN1_LDDATA AT_SUN_BRAND_AUX1 - -/* - * Information needed by the sn1 library to launch an executable. - */ -typedef struct sn1_elf_data { - ulong_t sed_phdr; - ulong_t sed_phent; - ulong_t sed_phnum; - ulong_t sed_entry; - ulong_t sed_base; - ulong_t sed_ldentry; - ulong_t sed_lddata; -} sn1_elf_data_t; - -/* - * Structure used to register a branded processes - */ -typedef struct sn1_brand_reg { - uint_t sbr_version; /* version number */ - caddr_t sbr_handler; /* base address of handler */ -} sn1_brand_reg_t; - #if defined(_KERNEL) -#if defined(_SYSCALL32) -typedef struct sn1_elf_data32 { - uint32_t sed_phdr; - uint32_t sed_phent; - uint32_t sed_phnum; - uint32_t sed_entry; - uint32_t sed_base; - uint32_t sed_ldentry; - uint32_t sed_lddata; -} sn1_elf_data32_t; - -typedef struct sn1_brand_reg32 { - uint32_t sbr_version; /* version number */ - caddr32_t sbr_handler; /* base address of handler */ -} sn1_brand_reg32_t; -#endif /* _SYSCALL32 */ - -/* - * Information associated with all sn1 branded processes - */ -typedef struct sn1_proc_data { - caddr_t spd_handler; /* address of user-space handler */ - sn1_elf_data_t spd_elf_data; /* ELF data for sn1 application */ -} sn1_proc_data_t; void sn1_brand_syscall_callback(void); void sn1_brand_syscall32_callback(void); diff --git a/usr/src/uts/common/brand/sn1/sn1_offsets.in b/usr/src/uts/common/brand/sn1/sn1_offsets.in deleted file mode 100644 index 0e531f26fd..0000000000 --- a/usr/src/uts/common/brand/sn1/sn1_offsets.in +++ /dev/null @@ -1,30 +0,0 @@ -\ -\ Copyright 2008 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. -\ -\ CDDL HEADER START -\ -\ The contents of this file are subject to the terms of the -\ Common Development and Distribution License (the "License"). -\ You may not use this file except in compliance with the License. -\ -\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -\ or http://www.opensolaris.org/os/licensing. -\ See the License for the specific language governing permissions -\ and limitations under the License. -\ -\ When distributing Covered Code, include this CDDL HEADER in each -\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. -\ If applicable, add the following below this CDDL HEADER, with the -\ fields enclosed by brackets "[]" replaced with your own identifying -\ information: Portions Copyright [yyyy] [name of copyright owner] -\ -\ CDDL HEADER END -\ -\ Sn1 brand structure offset for use in assembly code. -\ - -#include <sn1_brand.h> - -sn1_proc_data_t - spd_handler diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.c b/usr/src/uts/common/brand/solaris10/s10_brand.c index aace5abe3a..0e8b91f2dd 100644 --- a/usr/src/uts/common/brand/solaris10/s10_brand.c +++ b/usr/src/uts/common/brand/solaris10/s10_brand.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/errno.h> @@ -140,17 +139,7 @@ static struct modlinkage modlinkage = { void s10_setbrand(proc_t *p) { - ASSERT(p->p_brand == &s10_brand); - ASSERT(p->p_brand_data == NULL); - - /* - * We should only be called from exec(), when we know the process - * is single-threaded. - */ - ASSERT(p->p_tlist == p->p_tlist->t_forw); - - p->p_brand_data = kmem_zalloc(sizeof (s10_proc_data_t), KM_SLEEP); - (void) s10_initlwp(p->p_tlist->t_lwp); + brand_solaris_setbrand(p, &s10_brand); } /*ARGSUSED*/ @@ -223,7 +212,7 @@ s10_native() char *args_new, *comm_new, *p; int len; - len = sizeof (S10_NATIVE_LINKER32 " ") - 1; + len = sizeof (BRAND_NATIVE_LINKER32 " ") - 1; /* * Make sure that the process' interpreter is the native dynamic linker. @@ -236,9 +225,10 @@ s10_native() */ if (strcmp(up->u_comm, S10_LINKER_NAME) != 0) return (0); - if (strncmp(up->u_psargs, S10_NATIVE_LINKER64 " /", len + 4) == 0) + if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER64 " /", len + 4) == 0) len += 3; /* to account for "/64" in the path */ - else if (strncmp(up->u_psargs, S10_NATIVE_LINKER32 " /", len + 1) != 0) + else if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER32 " /", len + 1) + != 0) return (0); args_new = strdup(&up->u_psargs[len]); @@ -263,92 +253,24 @@ s10_native() return (0); } -/* - * Get the address of the user-space system call handler from the user - * process and attach it to the proc structure. - */ /*ARGSUSED*/ int s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6) { - s10_proc_data_t *spd; - s10_brand_reg_t reg; - proc_t *p = curproc; - int err; + proc_t *p = curproc; + int res; *rval = 0; - /* - * B_EXEC_BRAND is redundant - * since the kernel assumes a native process doing an exec - * in a branded zone is going to run a branded processes. - * hence we don't support this operation. - */ - if (cmd == B_EXEC_BRAND) - return (ENOSYS); - if (cmd == B_S10_NATIVE) return (s10_native()); - /* For all other operations this must be a branded process. */ - if (p->p_brand == &native_brand) - return (ENOSYS); - - ASSERT(p->p_brand == &s10_brand); - ASSERT(p->p_brand_data != NULL); - - spd = (s10_proc_data_t *)p->p_brand_data; - - switch (cmd) { - case B_EXEC_NATIVE: - err = exec_common( - (char *)arg1, (const char **)arg2, (const char **)arg3, - EBA_NATIVE); - return (err); - - case B_REGISTER: - if (p->p_model == DATAMODEL_NATIVE) { - if (copyin((void *)arg1, ®, sizeof (reg)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - s10_brand_reg32_t reg32; - - if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0) - return (EFAULT); - reg.sbr_version = reg32.sbr_version; - reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler; -#endif /* _LP64 */ - } - - if (reg.sbr_version != S10_VERSION) - return (ENOTSUP); - spd->spd_handler = reg.sbr_handler; - return (0); - - case B_ELFDATA: - if (p->p_model == DATAMODEL_NATIVE) { - if (copyout(&spd->spd_elf_data, (void *)arg1, - sizeof (s10_elf_data_t)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - s10_elf_data32_t sed32; - - sed32.sed_phdr = spd->spd_elf_data.sed_phdr; - sed32.sed_phent = spd->spd_elf_data.sed_phent; - sed32.sed_phnum = spd->spd_elf_data.sed_phnum; - sed32.sed_entry = spd->spd_elf_data.sed_entry; - sed32.sed_base = spd->spd_elf_data.sed_base; - sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry; - sed32.sed_lddata = spd->spd_elf_data.sed_lddata; - if (copyout(&sed32, (void *)arg1, sizeof (sed32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - return (0); + res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &s10_brand, S10_VERSION); + if (res >= 0) + return (res); + switch ((cmd)) { case B_S10_PIDINFO: /* * The s10 brand needs to be able to get the pid of the @@ -367,23 +289,6 @@ s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, return (EFAULT); return (0); - case B_S10_TRUSS_POINT: - /* - * This subcommand exists so that we can see truss output - * from interposed system calls that return without first - * calling any other system call, meaning they would be - * invisible to truss(1). - * - * If the second argument is set non-zero, set errno to that - * value as well. - * - * Arguments are: - * - * arg1: syscall number - * arg2: errno - */ - return ((arg2 == 0) ? 0 : set_errno((uint_t)arg2)); - case B_S10_ISFDXATTRDIR: { /* * This subcommand enables the userland brand emulation library @@ -418,96 +323,34 @@ s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, return (EINVAL); } -/* - * Copy the per-process brand data from a parent proc to a child. - */ void s10_copy_procdata(proc_t *child, proc_t *parent) { - s10_proc_data_t *spd; - - ASSERT(parent->p_brand == &s10_brand); - ASSERT(child->p_brand == &s10_brand); - ASSERT(parent->p_brand_data != NULL); - ASSERT(child->p_brand_data == NULL); - - /* Just duplicate all the proc data of the parent for the child */ - spd = kmem_alloc(sizeof (s10_proc_data_t), KM_SLEEP); - bcopy(parent->p_brand_data, spd, sizeof (s10_proc_data_t)); - child->p_brand_data = spd; + brand_solaris_copy_procdata(child, parent, &s10_brand); } -/*ARGSUSED*/ void s10_proc_exit(struct proc *p, klwp_t *l) { - ASSERT(p->p_brand == &s10_brand); - ASSERT(p->p_brand_data != NULL); - - /* - * We should only be called from proc_exit(), when we know that - * process is single-threaded. - */ - ASSERT(p->p_tlist == p->p_tlist->t_forw); - - /* upon exit, free our lwp brand data */ - (void) s10_freelwp(ttolwp(curthread)); - - /* upon exit, free our proc brand data */ - kmem_free(p->p_brand_data, sizeof (s10_proc_data_t)); - p->p_brand_data = NULL; + brand_solaris_proc_exit(p, l, &s10_brand); } void s10_exec() { - s10_proc_data_t *spd = curproc->p_brand_data; - - ASSERT(curproc->p_brand == &s10_brand); - ASSERT(curproc->p_brand_data != NULL); - ASSERT(ttolwp(curthread)->lwp_brand != NULL); - - /* - * We should only be called from exec(), when we know the process - * is single-threaded. - */ - ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw); - - /* Upon exec, reset our lwp brand data. */ - (void) s10_freelwp(ttolwp(curthread)); - (void) s10_initlwp(ttolwp(curthread)); - - /* - * Upon exec, reset all the proc brand data, except for the elf - * data associated with the executable we are exec'ing. - */ - spd->spd_handler = NULL; + brand_solaris_exec(&s10_brand); } -/*ARGSUSED*/ int s10_initlwp(klwp_t *l) { - ASSERT(l->lwp_procp->p_brand == &s10_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand == NULL); - l->lwp_brand = (void *)-1; - return (0); + return (brand_solaris_initlwp(l, &s10_brand)); } -/*ARGSUSED*/ void s10_forklwp(klwp_t *p, klwp_t *c) { - ASSERT(p->lwp_procp->p_brand == &s10_brand); - ASSERT(c->lwp_procp->p_brand == &s10_brand); - - ASSERT(p->lwp_procp->p_brand_data != NULL); - ASSERT(c->lwp_procp->p_brand_data != NULL); - - /* Both LWPs have already had been initialized via s10_initlwp() */ - ASSERT(p->lwp_brand != NULL); - ASSERT(c->lwp_brand != NULL); + brand_solaris_forklwp(p, c, &s10_brand); #ifdef __amd64 /* @@ -522,32 +365,16 @@ s10_forklwp(klwp_t *p, klwp_t *c) #endif /* __amd64 */ } -/*ARGSUSED*/ void s10_freelwp(klwp_t *l) { - ASSERT(l->lwp_procp->p_brand == &s10_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand != NULL); - l->lwp_brand = NULL; + brand_solaris_freelwp(l, &s10_brand); } -/*ARGSUSED*/ void s10_lwpexit(klwp_t *l) { - ASSERT(l->lwp_procp->p_brand == &s10_brand); - ASSERT(l->lwp_procp->p_brand_data != NULL); - ASSERT(l->lwp_brand != NULL); - - /* - * We should never be called for the last thread in a process. - * (That case is handled by s10_proc_exit().) There for this lwp - * must be exiting from a multi-threaded process. - */ - ASSERT(l->lwp_procp->p_tlist != l->lwp_procp->p_tlist->t_forw); - - l->lwp_brand = NULL; + brand_solaris_lwpexit(l, &s10_brand); } void @@ -564,381 +391,14 @@ s10_init_brand_data(zone_t *zone) zone->zone_brand_data = kmem_zalloc(sizeof (s10_zone_data_t), KM_SLEEP); } -#if defined(_LP64) -static void -Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst) -{ - bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident)); - dst->e_type = src->e_type; - dst->e_machine = src->e_machine; - dst->e_version = src->e_version; - dst->e_entry = src->e_entry; - dst->e_phoff = src->e_phoff; - dst->e_shoff = src->e_shoff; - dst->e_flags = src->e_flags; - dst->e_ehsize = src->e_ehsize; - dst->e_phentsize = src->e_phentsize; - dst->e_phnum = src->e_phnum; - dst->e_shentsize = src->e_shentsize; - dst->e_shnum = src->e_shnum; - dst->e_shstrndx = src->e_shstrndx; -} -#endif /* _LP64 */ - int s10_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred, int brand_action) { - vnode_t *nvp; - Ehdr ehdr; - Addr uphdr_vaddr; - intptr_t voffset; - int interp; - int i, err; - struct execenv env; - struct user *up = PTOU(curproc); - s10_proc_data_t *spd; - s10_elf_data_t sed, *sedp; - char *linker; - uintptr_t lddata; /* lddata of executable's linker */ - - ASSERT(curproc->p_brand == &s10_brand); - ASSERT(curproc->p_brand_data != NULL); - - spd = (s10_proc_data_t *)curproc->p_brand_data; - sedp = &spd->spd_elf_data; - - args->brandname = S10_BRANDNAME; - - /* - * We will exec the brand library and then map in the target - * application and (optionally) the brand's default linker. - */ - if (args->to_model == DATAMODEL_NATIVE) { - args->emulator = S10_LIB; - linker = S10_LINKER; -#if defined(_LP64) - } else { - args->emulator = S10_LIB32; - linker = S10_LINKER32; -#endif /* _LP64 */ - } - - if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, NULLVPP, - &nvp)) != 0) { - uprintf("%s: not found.", args->emulator); - return (err); - } - - if (args->to_model == DATAMODEL_NATIVE) { - err = elfexec(nvp, uap, args, idatap, level + 1, execsz, - setid, exec_file, cred, brand_action); -#if defined(_LP64) - } else { - err = elf32exec(nvp, uap, args, idatap, level + 1, execsz, - setid, exec_file, cred, brand_action); -#endif /* _LP64 */ - } - VN_RELE(nvp); - if (err != 0) - return (err); - - /* - * The u_auxv vectors are set up by elfexec to point to the brand - * emulation library and linker. Save these so they can be copied to - * the specific brand aux vectors. - */ - bzero(&sed, sizeof (sed)); - for (i = 0; i < __KERN_NAUXV_IMPL; i++) { - switch (up->u_auxv[i].a_type) { - case AT_SUN_LDDATA: - sed.sed_lddata = up->u_auxv[i].a_un.a_val; - break; - case AT_BASE: - sed.sed_base = up->u_auxv[i].a_un.a_val; - break; - case AT_ENTRY: - sed.sed_entry = up->u_auxv[i].a_un.a_val; - break; - case AT_PHDR: - sed.sed_phdr = up->u_auxv[i].a_un.a_val; - break; - case AT_PHENT: - sed.sed_phent = up->u_auxv[i].a_un.a_val; - break; - case AT_PHNUM: - sed.sed_phnum = up->u_auxv[i].a_un.a_val; - break; - default: - break; - } - } - /* Make sure the emulator has an entry point */ - ASSERT(sed.sed_entry != NULL); - ASSERT(sed.sed_phdr != NULL); - - bzero(&env, sizeof (env)); - if (args->to_model == DATAMODEL_NATIVE) { - err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, &voffset, - exec_file, &interp, &env.ex_bssbase, &env.ex_brkbase, - &env.ex_brksize, NULL); -#if defined(_LP64) - } else { - Elf32_Ehdr ehdr32; - Elf32_Addr uphdr_vaddr32; - err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32, - &voffset, exec_file, &interp, &env.ex_bssbase, - &env.ex_brkbase, &env.ex_brksize, NULL); - Ehdr32to64(&ehdr32, &ehdr); - if (uphdr_vaddr32 == (Elf32_Addr)-1) - uphdr_vaddr = (Addr)-1; - else - uphdr_vaddr = uphdr_vaddr32; -#endif /* _LP64 */ - } - if (err != 0) - return (err); - - /* - * Save off the important properties of the executable. The brand - * library will ask us for this data later, when it is initializing - * and getting ready to transfer control to the brand application. - */ - if (uphdr_vaddr == (Addr)-1) - sedp->sed_phdr = voffset + ehdr.e_phoff; - else - sedp->sed_phdr = voffset + uphdr_vaddr; - sedp->sed_entry = voffset + ehdr.e_entry; - sedp->sed_phent = ehdr.e_phentsize; - sedp->sed_phnum = ehdr.e_phnum; - - if (interp) { - if (ehdr.e_type == ET_DYN) { - /* - * This is a shared object executable, so we need to - * pick a reasonable place to put the heap. Just don't - * use the first page. - */ - env.ex_brkbase = (caddr_t)PAGESIZE; - env.ex_bssbase = (caddr_t)PAGESIZE; - } - - /* - * If the program needs an interpreter (most do), map it in and - * store relevant information about it in the aux vector, where - * the brand library can find it. - */ - if ((err = lookupname(linker, UIO_SYSSPACE, - FOLLOW, NULLVPP, &nvp)) != 0) { - uprintf("%s: not found.", S10_LINKER); - return (err); - } - if (args->to_model == DATAMODEL_NATIVE) { - err = mapexec_brand(nvp, args, &ehdr, - &uphdr_vaddr, &voffset, exec_file, &interp, - NULL, NULL, NULL, &lddata); -#if defined(_LP64) - } else { - Elf32_Ehdr ehdr32; - Elf32_Addr uphdr_vaddr32; - err = mapexec32_brand(nvp, args, &ehdr32, - &uphdr_vaddr32, &voffset, exec_file, &interp, - NULL, NULL, NULL, &lddata); - Ehdr32to64(&ehdr32, &ehdr); - if (uphdr_vaddr32 == (Elf32_Addr)-1) - uphdr_vaddr = (Addr)-1; - else - uphdr_vaddr = uphdr_vaddr32; -#endif /* _LP64 */ - } - VN_RELE(nvp); - if (err != 0) - return (err); - - /* - * Now that we know the base address of the brand's linker, - * place it in the aux vector. - */ - sedp->sed_base = voffset; - sedp->sed_ldentry = voffset + ehdr.e_entry; - sedp->sed_lddata = voffset + lddata; - } else { - /* - * This program has no interpreter. The brand library will - * jump to the address in the AT_SUN_BRAND_LDENTRY aux vector, - * so in this case, put the entry point of the main executable - * there. - */ - if (ehdr.e_type == ET_EXEC) { - /* - * An executable with no interpreter, this must be a - * statically linked executable, which means we loaded - * it at the address specified in the elf header, in - * which case the e_entry field of the elf header is an - * absolute address. - */ - sedp->sed_ldentry = ehdr.e_entry; - sedp->sed_entry = ehdr.e_entry; - sedp->sed_lddata = NULL; - sedp->sed_base = NULL; - } else { - /* - * A shared object with no interpreter, we use the - * calculated address from above. - */ - sedp->sed_ldentry = sedp->sed_entry; - sedp->sed_entry = NULL; - sedp->sed_phdr = NULL; - sedp->sed_phent = NULL; - sedp->sed_phnum = NULL; - sedp->sed_lddata = NULL; - sedp->sed_base = voffset; - - if (ehdr.e_type == ET_DYN) { - /* - * Delay setting the brkbase until the first - * call to brk(); see elfexec() for details. - */ - env.ex_bssbase = (caddr_t)0; - env.ex_brkbase = (caddr_t)0; - env.ex_brksize = 0; - } - } - } - - env.ex_magic = elfmagic; - env.ex_vp = vp; - setexecenv(&env); - - /* - * It's time to manipulate the process aux vectors. First - * we need to update the AT_SUN_AUXFLAGS aux vector to set - * the AF_SUN_NOPLM flag. - */ - if (args->to_model == DATAMODEL_NATIVE) { - auxv_t auxflags_auxv; - - if (copyin(args->auxp_auxflags, &auxflags_auxv, - sizeof (auxflags_auxv)) != 0) - return (EFAULT); - - ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS); - auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM; - if (copyout(&auxflags_auxv, args->auxp_auxflags, - sizeof (auxflags_auxv)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - auxv32_t auxflags_auxv32; - - if (copyin(args->auxp_auxflags, &auxflags_auxv32, - sizeof (auxflags_auxv32)) != 0) - return (EFAULT); - - ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS); - auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM; - if (copyout(&auxflags_auxv32, args->auxp_auxflags, - sizeof (auxflags_auxv32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - - /* Second, copy out the brand specific aux vectors. */ - if (args->to_model == DATAMODEL_NATIVE) { - auxv_t s10_auxv[] = { - { AT_SUN_BRAND_AUX1, 0 }, - { AT_SUN_BRAND_AUX2, 0 }, - { AT_SUN_BRAND_AUX3, 0 } - }; - - ASSERT(s10_auxv[0].a_type == AT_SUN_BRAND_S10_LDDATA); - s10_auxv[0].a_un.a_val = sed.sed_lddata; - - if (copyout(&s10_auxv, args->auxp_brand, - sizeof (s10_auxv)) != 0) - return (EFAULT); -#if defined(_LP64) - } else { - auxv32_t s10_auxv32[] = { - { AT_SUN_BRAND_AUX1, 0 }, - { AT_SUN_BRAND_AUX2, 0 }, - { AT_SUN_BRAND_AUX3, 0 } - }; - - ASSERT(s10_auxv32[0].a_type == AT_SUN_BRAND_S10_LDDATA); - s10_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata; - if (copyout(&s10_auxv32, args->auxp_brand, - sizeof (s10_auxv32)) != 0) - return (EFAULT); -#endif /* _LP64 */ - } - - /* - * Third, the the /proc aux vectors set up by elfexec() point to brand - * emulation library and it's linker. Copy these to the /proc brand - * specific aux vector, and update the regular /proc aux vectors to - * point to the executable (and it's linker). This will enable - * debuggers to access the executable via the usual /proc or elf notes - * aux vectors. - * - * The brand emulation library's linker will get it's aux vectors off - * the stack, and then update the stack with the executable's aux - * vectors before jumping to the executable's linker. - * - * Debugging the brand emulation library must be done from - * the global zone, where the librtld_db module knows how to fetch the - * brand specific aux vectors to access the brand emulation libraries - * linker. - */ - for (i = 0; i < __KERN_NAUXV_IMPL; i++) { - ulong_t val; - - switch (up->u_auxv[i].a_type) { - case AT_SUN_BRAND_S10_LDDATA: - up->u_auxv[i].a_un.a_val = sed.sed_lddata; - continue; - case AT_BASE: - val = sedp->sed_base; - break; - case AT_ENTRY: - val = sedp->sed_entry; - break; - case AT_PHDR: - val = sedp->sed_phdr; - break; - case AT_PHENT: - val = sedp->sed_phent; - break; - case AT_PHNUM: - val = sedp->sed_phnum; - break; - case AT_SUN_LDDATA: - val = sedp->sed_lddata; - break; - default: - continue; - } - - up->u_auxv[i].a_un.a_val = val; - if (val == NULL) { - /* Hide the entry for static binaries */ - up->u_auxv[i].a_type = AT_IGNORE; - } - } - - /* - * The last thing we do here is clear spd->spd_handler. This is - * important because if we're already a branded process and if this - * exec succeeds, there is a window between when the exec() first - * returns to the userland of the new process and when our brand - * library get's initialized, during which we don't want system - * calls to be re-directed to our brand library since it hasn't - * been initialized yet. - */ - spd->spd_handler = NULL; - - return (0); + return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz, + setid, exec_file, cred, brand_action, &s10_brand, S10_BRANDNAME, + S10_LIB, S10_LIB32, S10_LINKER, S10_LINKER32)); } void @@ -1110,21 +570,6 @@ _info(struct modinfo *modinfop) int _fini(void) { - int err; - - /* - * If there are any zones using this brand, we can't allow it to be - * unloaded. - */ - if (brand_zone_count(&s10_brand)) - return (EBUSY); - - kmem_free(s10_emulation_table, NSYSCALL); - s10_emulation_table = NULL; - - err = mod_remove(&modlinkage); - if (err) - cmn_err(CE_WARN, "Couldn't unload s10 brand module"); - - return (err); + return (brand_solaris_fini(&s10_emulation_table, &modlinkage, + &s10_brand)); } diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.h b/usr/src/uts/common/brand/solaris10/s10_brand.h index 9559881e98..3686c3600e 100644 --- a/usr/src/uts/common/brand/solaris10/s10_brand.h +++ b/usr/src/uts/common/brand/solaris10/s10_brand.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _S10_BRAND_H @@ -30,24 +29,21 @@ extern "C" { #endif -#include <sys/types.h> +#include <sys/brand.h> #define S10_BRANDNAME "solaris10" #define S10_VERSION_1 1 #define S10_VERSION S10_VERSION_1 -#define S10_NATIVE_DIR "/.SUNWnative/" #define S10_LIB_NAME "s10_brand.so.1" #define S10_LINKER_NAME "ld.so.1" -#define S10_LIB32 S10_NATIVE_DIR "usr/lib/" S10_LIB_NAME +#define S10_LIB32 BRAND_NATIVE_DIR "usr/lib/" S10_LIB_NAME #define S10_LINKER32 "/lib/" S10_LINKER_NAME -#define S10_NATIVE_LINKER32 S10_NATIVE_DIR "lib/" S10_LINKER_NAME -#define S10_LIB64 S10_NATIVE_DIR "usr/lib/64/" S10_LIB_NAME +#define S10_LIB64 BRAND_NATIVE_DIR "usr/lib/64/" S10_LIB_NAME #define S10_LINKER64 "/lib/64/" S10_LINKER_NAME -#define S10_NATIVE_LINKER64 S10_NATIVE_DIR "lib/64/" S10_LINKER_NAME #if defined(_LP64) #define S10_LIB S10_LIB64 @@ -69,7 +65,6 @@ extern "C" { * Brand system call subcodes. 0-127 are reserved for generic subcodes. */ #define B_S10_PIDINFO 128 -#define B_S10_TRUSS_POINT 129 #define B_S10_NATIVE 130 #define B_S10_FSREGCORRECTION 131 #define B_S10_ISFDXATTRDIR 132 @@ -103,12 +98,6 @@ enum s10_emulated_features { #define S10_CPU_REG_SAVE_SIZE (sizeof (ulong_t) * 4) /* - * Aux vector containing lddata pointer of brand library linkmap. - * Used by s10_librtld_db. - */ -#define AT_SUN_BRAND_S10_LDDATA AT_SUN_BRAND_AUX1 - -/* * S10 system call codes for S10 traps that have been removed or reassigned, * or that are to be removed or reassigned after the dtrace syscall provider * has been reengineered to deal properly with syscall::open (for example). @@ -155,27 +144,6 @@ enum s10_emulated_features { #define S10_EMUL_BITMAP ZONE_ATTR_BRAND_ATTRS /* - * Information needed by the s10 library to launch an executable. - */ -typedef struct s10_elf_data { - ulong_t sed_phdr; - ulong_t sed_phent; - ulong_t sed_phnum; - ulong_t sed_entry; - ulong_t sed_base; - ulong_t sed_ldentry; - ulong_t sed_lddata; -} s10_elf_data_t; - -/* - * Structure used to register a branded processes - */ -typedef struct s10_brand_reg { - uint_t sbr_version; /* version number */ - caddr_t sbr_handler; /* base address of handler */ -} s10_brand_reg_t; - -/* * s10_emul_bitmap represents an emulation feature bitmap. Each constant * in s10_emulated_features defines a bit index in this bitmap. If a bit is * set, then the feature associated with the s10_emulated_features constant @@ -200,30 +168,6 @@ typedef struct s10_brand_reg { typedef uint8_t s10_emul_bitmap_t[(S10_NUM_EMUL_FEATURES >> 3) + 1]; #if defined(_KERNEL) -#if defined(_SYSCALL32) -typedef struct s10_elf_data32 { - uint32_t sed_phdr; - uint32_t sed_phent; - uint32_t sed_phnum; - uint32_t sed_entry; - uint32_t sed_base; - uint32_t sed_ldentry; - uint32_t sed_lddata; -} s10_elf_data32_t; - -typedef struct s10_brand_reg32 { - uint32_t sbr_version; /* version number */ - caddr32_t sbr_handler; /* base address of handler */ -} s10_brand_reg32_t; -#endif /* _SYSCALL32 */ - -/* - * Information associated with all s10 branded processes - */ -typedef struct s10_proc_data { - caddr_t spd_handler; /* address of user-space handler */ - s10_elf_data_t spd_elf_data; /* ELF data for s10 application */ -} s10_proc_data_t; /* brand specific data */ typedef struct s10_zone_data { diff --git a/usr/src/uts/common/brand/solaris10/s10_offsets.in b/usr/src/uts/common/brand/solaris10/s10_offsets.in deleted file mode 100644 index db5144d670..0000000000 --- a/usr/src/uts/common/brand/solaris10/s10_offsets.in +++ /dev/null @@ -1,30 +0,0 @@ -\ -\ Copyright 2009 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. -\ -\ CDDL HEADER START -\ -\ The contents of this file are subject to the terms of the -\ Common Development and Distribution License (the "License"). -\ You may not use this file except in compliance with the License. -\ -\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -\ or http://www.opensolaris.org/os/licensing. -\ See the License for the specific language governing permissions -\ and limitations under the License. -\ -\ When distributing Covered Code, include this CDDL HEADER in each -\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. -\ If applicable, add the following below this CDDL HEADER, with the -\ fields enclosed by brackets "[]" replaced with your own identifying -\ information: Portions Copyright [yyyy] [name of copyright owner] -\ -\ CDDL HEADER END -\ -\ s10 brand structure offset for use in assembly code. -\ - -#include <s10_brand.h> - -s10_proc_data_t - spd_handler diff --git a/usr/src/uts/common/os/brand.c b/usr/src/uts/common/os/brand.c index b2bc8cc7d0..32e5b32fcb 100644 --- a/usr/src/uts/common/os/brand.c +++ b/usr/src/uts/common/os/brand.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/kmem.h> @@ -32,6 +31,7 @@ #include <sys/modctl.h> #include <sys/rwlock.h> #include <sys/zone.h> +#include <sys/pathname.h> #define SUPPORTED_BRAND_VERSION BRAND_VER_1 @@ -425,3 +425,675 @@ brand_plat_interposition_disable(void) syscall_trap32_patch_instr_orig, 4); } #endif /* __sparcv9 */ + +/* + * The following functions can be shared among kernel brand modules which + * implement Solaris-derived brands, all of which need to do similar tasks + * to manage the brand. + */ + +#if defined(_LP64) +static void +Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst) +{ + bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident)); + dst->e_type = src->e_type; + dst->e_machine = src->e_machine; + dst->e_version = src->e_version; + dst->e_entry = src->e_entry; + dst->e_phoff = src->e_phoff; + dst->e_shoff = src->e_shoff; + dst->e_flags = src->e_flags; + dst->e_ehsize = src->e_ehsize; + dst->e_phentsize = src->e_phentsize; + dst->e_phnum = src->e_phnum; + dst->e_shentsize = src->e_shentsize; + dst->e_shnum = src->e_shnum; + dst->e_shstrndx = src->e_shstrndx; +} +#endif /* _LP64 */ + +/* + * Return -1 if the cmd was not handled by this function. + */ +/*ARGSUSED*/ +int +brand_solaris_cmd(int cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, + struct brand *pbrand, int brandvers) +{ + brand_proc_data_t *spd; + brand_proc_reg_t reg; + proc_t *p = curproc; + int err; + + /* + * There is one operation that is supported for a native + * process; B_EXEC_BRAND. This brand operaion is redundant + * since the kernel assumes a native process doing an exec + * in a branded zone is going to run a branded processes. + * hence we don't support this operation. + */ + if (cmd == B_EXEC_BRAND) + return (ENOSYS); + + /* For all other operations this must be a branded process. */ + if (p->p_brand == &native_brand) + return (ENOSYS); + + ASSERT(p->p_brand == pbrand); + ASSERT(p->p_brand_data != NULL); + + spd = (brand_proc_data_t *)p->p_brand_data; + + switch ((cmd)) { + case B_EXEC_NATIVE: + err = exec_common((char *)arg1, (const char **)arg2, + (const char **)arg3, EBA_NATIVE); + return (err); + + /* + * Get the address of the user-space system call handler from + * the user process and attach it to the proc structure. + */ + case B_REGISTER: + if (p->p_model == DATAMODEL_NATIVE) { + if (copyin((void *)arg1, ®, sizeof (reg)) != 0) + return (EFAULT); + } +#if defined(_LP64) + else { + brand_common_reg32_t reg32; + + if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0) + return (EFAULT); + reg.sbr_version = reg32.sbr_version; + reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler; + } +#endif /* _LP64 */ + + if (reg.sbr_version != brandvers) + return (ENOTSUP); + spd->spd_handler = reg.sbr_handler; + return (0); + + case B_ELFDATA: + if (p->p_model == DATAMODEL_NATIVE) { + if (copyout(&spd->spd_elf_data, (void *)arg1, + sizeof (brand_elf_data_t)) != 0) + return (EFAULT); + } +#if defined(_LP64) + else { + brand_elf_data32_t sed32; + + sed32.sed_phdr = spd->spd_elf_data.sed_phdr; + sed32.sed_phent = spd->spd_elf_data.sed_phent; + sed32.sed_phnum = spd->spd_elf_data.sed_phnum; + sed32.sed_entry = spd->spd_elf_data.sed_entry; + sed32.sed_base = spd->spd_elf_data.sed_base; + sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry; + sed32.sed_lddata = spd->spd_elf_data.sed_lddata; + if (copyout(&sed32, (void *)arg1, sizeof (sed32)) + != 0) + return (EFAULT); + } +#endif /* _LP64 */ + return (0); + + /* + * The B_TRUSS_POINT subcommand exists so that we can see + * truss output from interposed system calls that return + * without first calling any other system call, meaning they + * would be invisible to truss(1). + * If the second argument is set non-zero, set errno to that + * value as well. + * + * Common arguments seen with truss are: + * + * arg1: syscall number + * arg2: errno + */ + case B_TRUSS_POINT: + return ((arg2 == 0) ? 0 : set_errno((uint_t)arg2)); + } + + return (-1); +} + +/*ARGSUSED*/ +void +brand_solaris_copy_procdata(proc_t *child, proc_t *parent, struct brand *pbrand) +{ + brand_proc_data_t *spd; + + ASSERT(parent->p_brand == pbrand); + ASSERT(child->p_brand == pbrand); + ASSERT(parent->p_brand_data != NULL); + ASSERT(child->p_brand_data == NULL); + + /* + * Just duplicate all the proc data of the parent for the + * child + */ + spd = kmem_alloc(sizeof (brand_proc_data_t), KM_SLEEP); + bcopy(parent->p_brand_data, spd, sizeof (brand_proc_data_t)); + child->p_brand_data = spd; +} + +/*ARGSUSED*/ +int +brand_solaris_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, + intpdata_t *idatap, int level, long *execsz, int setid, caddr_t exec_file, + cred_t *cred, int brand_action, struct brand *pbrand, char *bname, + char *brandlib, char *brandlib32, char *brandlinker, char *brandlinker32) +{ + + vnode_t *nvp; + Ehdr ehdr; + Addr uphdr_vaddr; + intptr_t voffset; + int interp; + int i, err; + struct execenv env; + struct user *up = PTOU(curproc); + brand_proc_data_t *spd; + brand_elf_data_t sed, *sedp; + char *linker; + uintptr_t lddata; /* lddata of executable's linker */ + + ASSERT(curproc->p_brand == pbrand); + ASSERT(curproc->p_brand_data != NULL); + + spd = (brand_proc_data_t *)curproc->p_brand_data; + sedp = &spd->spd_elf_data; + + args->brandname = bname; + + /* + * We will exec the brand library and then map in the target + * application and (optionally) the brand's default linker. + */ + if (args->to_model == DATAMODEL_NATIVE) { + args->emulator = brandlib; + linker = brandlinker; + } +#if defined(_LP64) + else { + args->emulator = brandlib32; + linker = brandlinker32; + } +#endif /* _LP64 */ + + if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, + NULLVPP, &nvp)) != 0) { + uprintf("%s: not found.", args->emulator); + return (err); + } + + if (args->to_model == DATAMODEL_NATIVE) { + err = elfexec(nvp, uap, args, idatap, level + 1, execsz, + setid, exec_file, cred, brand_action); + } +#if defined(_LP64) + else { + err = elf32exec(nvp, uap, args, idatap, level + 1, execsz, + setid, exec_file, cred, brand_action); + } +#endif /* _LP64 */ + VN_RELE(nvp); + if (err != 0) + return (err); + + /* + * The u_auxv veCTors are set up by elfexec to point to the + * brand emulation library and linker. Save these so they can + * be copied to the specific brand aux vectors. + */ + bzero(&sed, sizeof (sed)); + for (i = 0; i < __KERN_NAUXV_IMPL; i++) { + switch (up->u_auxv[i].a_type) { + case AT_SUN_LDDATA: + sed.sed_lddata = up->u_auxv[i].a_un.a_val; + break; + case AT_BASE: + sed.sed_base = up->u_auxv[i].a_un.a_val; + break; + case AT_ENTRY: + sed.sed_entry = up->u_auxv[i].a_un.a_val; + break; + case AT_PHDR: + sed.sed_phdr = up->u_auxv[i].a_un.a_val; + break; + case AT_PHENT: + sed.sed_phent = up->u_auxv[i].a_un.a_val; + break; + case AT_PHNUM: + sed.sed_phnum = up->u_auxv[i].a_un.a_val; + break; + default: + break; + } + } + /* Make sure the emulator has an entry point */ + ASSERT(sed.sed_entry != NULL); + ASSERT(sed.sed_phdr != NULL); + + bzero(&env, sizeof (env)); + if (args->to_model == DATAMODEL_NATIVE) { + err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, + &voffset, exec_file, &interp, &env.ex_bssbase, + &env.ex_brkbase, &env.ex_brksize, NULL); + } +#if defined(_LP64) + else { + Elf32_Ehdr ehdr32; + Elf32_Addr uphdr_vaddr32; + err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32, + &voffset, exec_file, &interp, &env.ex_bssbase, + &env.ex_brkbase, &env.ex_brksize, NULL); + Ehdr32to64(&ehdr32, &ehdr); + + if (uphdr_vaddr32 == (Elf32_Addr)-1) + uphdr_vaddr = (Addr)-1; + else + uphdr_vaddr = uphdr_vaddr32; + } +#endif /* _LP64 */ + if (err != 0) + return (err); + + /* + * Save off the important properties of the executable. The + * brand library will ask us for this data later, when it is + * initializing and getting ready to transfer control to the + * brand application. + */ + if (uphdr_vaddr == (Addr)-1) + sedp->sed_phdr = voffset + ehdr.e_phoff; + else + sedp->sed_phdr = voffset + uphdr_vaddr; + sedp->sed_entry = voffset + ehdr.e_entry; + sedp->sed_phent = ehdr.e_phentsize; + sedp->sed_phnum = ehdr.e_phnum; + + if (interp) { + if (ehdr.e_type == ET_DYN) { + /* + * This is a shared object executable, so we + * need to pick a reasonable place to put the + * heap. Just don't use the first page. + */ + env.ex_brkbase = (caddr_t)PAGESIZE; + env.ex_bssbase = (caddr_t)PAGESIZE; + } + + /* + * If the program needs an interpreter (most do), map + * it in and store relevant information about it in the + * aux vector, where the brand library can find it. + */ + if ((err = lookupname(linker, UIO_SYSSPACE, + FOLLOW, NULLVPP, &nvp)) != 0) { + uprintf("%s: not found.", brandlinker); + return (err); + } + if (args->to_model == DATAMODEL_NATIVE) { + err = mapexec_brand(nvp, args, &ehdr, + &uphdr_vaddr, &voffset, exec_file, &interp, + NULL, NULL, NULL, &lddata); + } +#if defined(_LP64) + else { + Elf32_Ehdr ehdr32; + Elf32_Addr uphdr_vaddr32; + err = mapexec32_brand(nvp, args, &ehdr32, + &uphdr_vaddr32, &voffset, exec_file, &interp, + NULL, NULL, NULL, &lddata); + Ehdr32to64(&ehdr32, &ehdr); + + if (uphdr_vaddr32 == (Elf32_Addr)-1) + uphdr_vaddr = (Addr)-1; + else + uphdr_vaddr = uphdr_vaddr32; + } +#endif /* _LP64 */ + VN_RELE(nvp); + if (err != 0) + return (err); + + /* + * Now that we know the base address of the brand's + * linker, place it in the aux vector. + */ + sedp->sed_base = voffset; + sedp->sed_ldentry = voffset + ehdr.e_entry; + sedp->sed_lddata = voffset + lddata; + } else { + /* + * This program has no interpreter. The brand library + * will jump to the address in the AT_SUN_BRAND_LDENTRY + * aux vector, so in this case, put the entry point of + * the main executable there. + */ + if (ehdr.e_type == ET_EXEC) { + /* + * An executable with no interpreter, this must + * be a statically linked executable, which + * means we loaded it at the address specified + * in the elf header, in which case the e_entry + * field of the elf header is an absolute + * address. + */ + sedp->sed_ldentry = ehdr.e_entry; + sedp->sed_entry = ehdr.e_entry; + sedp->sed_lddata = NULL; + sedp->sed_base = NULL; + } else { + /* + * A shared object with no interpreter, we use + * the calculated address from above. + */ + sedp->sed_ldentry = sedp->sed_entry; + sedp->sed_entry = NULL; + sedp->sed_phdr = NULL; + sedp->sed_phent = NULL; + sedp->sed_phnum = NULL; + sedp->sed_lddata = NULL; + sedp->sed_base = voffset; + + if (ehdr.e_type == ET_DYN) { + /* + * Delay setting the brkbase until the + * first call to brk(); see elfexec() + * for details. + */ + env.ex_bssbase = (caddr_t)0; + env.ex_brkbase = (caddr_t)0; + env.ex_brksize = 0; + } + } + } + + env.ex_magic = elfmagic; + env.ex_vp = vp; + setexecenv(&env); + + /* + * It's time to manipulate the process aux vectors. First + * we need to update the AT_SUN_AUXFLAGS aux vector to set + * the AF_SUN_NOPLM flag. + */ + if (args->to_model == DATAMODEL_NATIVE) { + auxv_t auxflags_auxv; + + if (copyin(args->auxp_auxflags, &auxflags_auxv, + sizeof (auxflags_auxv)) != 0) + return (EFAULT); + + ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS); + auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM; + if (copyout(&auxflags_auxv, args->auxp_auxflags, + sizeof (auxflags_auxv)) != 0) + return (EFAULT); + } +#if defined(_LP64) + else { + auxv32_t auxflags_auxv32; + + if (copyin(args->auxp_auxflags, &auxflags_auxv32, + sizeof (auxflags_auxv32)) != 0) + return (EFAULT); + + ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS); + auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM; + if (copyout(&auxflags_auxv32, args->auxp_auxflags, + sizeof (auxflags_auxv32)) != 0) + return (EFAULT); + } +#endif /* _LP64 */ + + /* Second, copy out the brand specific aux vectors. */ + if (args->to_model == DATAMODEL_NATIVE) { + auxv_t brand_auxv[] = { + { AT_SUN_BRAND_AUX1, 0 }, + { AT_SUN_BRAND_AUX2, 0 }, + { AT_SUN_BRAND_AUX3, 0 } + }; + + ASSERT(brand_auxv[0].a_type == + AT_SUN_BRAND_COMMON_LDDATA); + brand_auxv[0].a_un.a_val = sed.sed_lddata; + + if (copyout(&brand_auxv, args->auxp_brand, + sizeof (brand_auxv)) != 0) + return (EFAULT); + } +#if defined(_LP64) + else { + auxv32_t brand_auxv32[] = { + { AT_SUN_BRAND_AUX1, 0 }, + { AT_SUN_BRAND_AUX2, 0 }, + { AT_SUN_BRAND_AUX3, 0 } + }; + + ASSERT(brand_auxv32[0].a_type == AT_SUN_BRAND_COMMON_LDDATA); + brand_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata; + if (copyout(&brand_auxv32, args->auxp_brand, + sizeof (brand_auxv32)) != 0) + return (EFAULT); + } +#endif /* _LP64 */ + + /* + * Third, the /proc aux vectors set up by elfexec() point to + * brand emulation library and it's linker. Copy these to the + * /proc brand specific aux vector, and update the regular + * /proc aux vectors to point to the executable (and it's + * linker). This will enable debuggers to access the + * executable via the usual /proc or elf notes aux vectors. + * + * The brand emulation library's linker will get it's aux + * vectors off the stack, and then update the stack with the + * executable's aux vectors before jumping to the executable's + * linker. + * + * Debugging the brand emulation library must be done from + * the global zone, where the librtld_db module knows how to + * fetch the brand specific aux vectors to access the brand + * emulation libraries linker. + */ + for (i = 0; i < __KERN_NAUXV_IMPL; i++) { + ulong_t val; + + switch (up->u_auxv[i].a_type) { + case AT_SUN_BRAND_COMMON_LDDATA: + up->u_auxv[i].a_un.a_val = sed.sed_lddata; + continue; + case AT_BASE: + val = sedp->sed_base; + break; + case AT_ENTRY: + val = sedp->sed_entry; + break; + case AT_PHDR: + val = sedp->sed_phdr; + break; + case AT_PHENT: + val = sedp->sed_phent; + break; + case AT_PHNUM: + val = sedp->sed_phnum; + break; + case AT_SUN_LDDATA: + val = sedp->sed_lddata; + break; + default: + continue; + } + + up->u_auxv[i].a_un.a_val = val; + if (val == NULL) { + /* Hide the entry for static binaries */ + up->u_auxv[i].a_type = AT_IGNORE; + } + } + + /* + * The last thing we do here is clear spd->spd_handler. This + * is important because if we're already a branded process and + * if this exec succeeds, there is a window between when the + * exec() first returns to the userland of the new process and + * when our brand library get's initialized, during which we + * don't want system calls to be re-directed to our brand + * library since it hasn't been initialized yet. + */ + spd->spd_handler = NULL; + + return (0); +} + +void +brand_solaris_exec(struct brand *pbrand) +{ + brand_proc_data_t *spd = curproc->p_brand_data; + + ASSERT(curproc->p_brand == pbrand); + ASSERT(curproc->p_brand_data != NULL); + ASSERT(ttolwp(curthread)->lwp_brand != NULL); + + /* + * We should only be called from exec(), when we know the process + * is single-threaded. + */ + ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw); + + /* Upon exec, reset our lwp brand data. */ + (void) brand_solaris_freelwp(ttolwp(curthread), pbrand); + (void) brand_solaris_initlwp(ttolwp(curthread), pbrand); + + /* + * Upon exec, reset all the proc brand data, except for the elf + * data associated with the executable we are exec'ing. + */ + spd->spd_handler = NULL; +} + +int +brand_solaris_fini(char **emul_table, struct modlinkage *modlinkage, + struct brand *pbrand) +{ + int err; + + /* + * If there are any zones using this brand, we can't allow it + * to be unloaded. + */ + if (brand_zone_count(pbrand)) + return (EBUSY); + + kmem_free(*emul_table, NSYSCALL); + *emul_table = NULL; + + err = mod_remove(modlinkage); + if (err) + cmn_err(CE_WARN, "Couldn't unload brand module"); + + return (err); +} + +/*ARGSUSED*/ +void +brand_solaris_forklwp(klwp_t *p, klwp_t *c, struct brand *pbrand) +{ + ASSERT(p->lwp_procp->p_brand == pbrand); + ASSERT(c->lwp_procp->p_brand == pbrand); + + ASSERT(p->lwp_procp->p_brand_data != NULL); + ASSERT(c->lwp_procp->p_brand_data != NULL); + + /* + * Both LWPs have already had been initialized via + * brand_solaris_initlwp(). + */ + ASSERT(p->lwp_brand != NULL); + ASSERT(c->lwp_brand != NULL); +} + +/*ARGSUSED*/ +void +brand_solaris_freelwp(klwp_t *l, struct brand *pbrand) +{ + ASSERT(l->lwp_procp->p_brand == pbrand); + ASSERT(l->lwp_procp->p_brand_data != NULL); + ASSERT(l->lwp_brand != NULL); + l->lwp_brand = NULL; +} + +/*ARGSUSED*/ +int +brand_solaris_initlwp(klwp_t *l, struct brand *pbrand) +{ + ASSERT(l->lwp_procp->p_brand == pbrand); + ASSERT(l->lwp_procp->p_brand_data != NULL); + ASSERT(l->lwp_brand == NULL); + l->lwp_brand = (void *)-1; + return (0); +} + +/*ARGSUSED*/ +void +brand_solaris_lwpexit(klwp_t *l, struct brand *pbrand) +{ + proc_t *p = l->lwp_procp; + + ASSERT(l->lwp_procp->p_brand == pbrand); + ASSERT(l->lwp_procp->p_brand_data != NULL); + ASSERT(l->lwp_brand != NULL); + + /* + * We should never be called for the last thread in a process. + * (That case is handled by brand_solaris_proc_exit().) + * Therefore this lwp must be exiting from a multi-threaded + * process. + */ + ASSERT(p->p_tlist != p->p_tlist->t_forw); + + l->lwp_brand = NULL; +} + +/*ARGSUSED*/ +void +brand_solaris_proc_exit(struct proc *p, klwp_t *l, struct brand *pbrand) +{ + ASSERT(p->p_brand == pbrand); + ASSERT(p->p_brand_data != NULL); + + /* + * We should only be called from proc_exit(), when we know that + * process is single-threaded. + */ + ASSERT(p->p_tlist == p->p_tlist->t_forw); + + /* upon exit, free our lwp brand data */ + (void) brand_solaris_freelwp(ttolwp(curthread), pbrand); + + /* upon exit, free our proc brand data */ + kmem_free(p->p_brand_data, sizeof (brand_proc_data_t)); + p->p_brand_data = NULL; +} + +void +brand_solaris_setbrand(proc_t *p, struct brand *pbrand) +{ + ASSERT(p->p_brand == pbrand); + ASSERT(p->p_brand_data == NULL); + + /* + * We should only be called from exec(), when we know the process + * is single-threaded. + */ + ASSERT(p->p_tlist == p->p_tlist->t_forw); + + p->p_brand_data = kmem_zalloc(sizeof (brand_proc_data_t), KM_SLEEP); + (void) brand_solaris_initlwp(p->p_tlist->t_lwp, pbrand); +} diff --git a/usr/src/uts/common/sys/brand.h b/usr/src/uts/common/sys/brand.h index ee56189df7..32e0f045e9 100644 --- a/usr/src/uts/common/sys/brand.h +++ b/usr/src/uts/common/sys/brand.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_BRAND_H @@ -33,6 +32,7 @@ extern "C" { #include <sys/proc.h> #include <sys/exec.h> +#include <sys/modctl.h> /* * All Brands supported by this kernel must use BRAND_VER_1. @@ -49,6 +49,7 @@ extern "C" { #define B_ELFDATA 3 #define B_EXEC_NATIVE 4 #define B_EXEC_BRAND 5 +#define B_TRUSS_POINT 6 /* * Structure used by zoneadmd to communicate the name of a brand and the @@ -65,10 +66,34 @@ struct brand_attr { /* What we call the labeled brand. */ #define LABELED_BRAND_NAME "labeled" -#ifdef _KERNEL +/* + * Aux vector containing lddata pointer of brand library linkmap. + * Used by common {brand}_librtld_db. + */ +#define AT_SUN_BRAND_COMMON_LDDATA AT_SUN_BRAND_AUX1 + +/* + * Information needed by the brand library to launch an executable. + */ +typedef struct brand_elf_data { + ulong_t sed_phdr; + ulong_t sed_phent; + ulong_t sed_phnum; + ulong_t sed_entry; + ulong_t sed_base; + ulong_t sed_ldentry; + ulong_t sed_lddata; +} brand_elf_data_t; + +/* + * Common structure used to register a branded processes + */ +typedef struct brand_proc_reg { + uint_t sbr_version; /* version number */ + caddr_t sbr_handler; /* base address of handler */ +} brand_proc_reg_t; -/* Root for branded zone's native binaries */ -#define NATIVE_ROOT "/native/" +#ifdef _KERNEL struct proc; struct uarg; @@ -141,6 +166,59 @@ extern void brand_unregister_zone(brand_t *); extern int brand_zone_count(brand_t *); extern void brand_setbrand(proc_t *); extern void brand_clearbrand(proc_t *); + +/* + * The following functions can be shared among kernel brand modules which + * implement Solaris-derived brands, all of which need to do similar tasks to + * manage the brand. + */ +extern int brand_solaris_cmd(int, uintptr_t, uintptr_t, uintptr_t, + struct brand *, int); +extern void brand_solaris_copy_procdata(proc_t *, proc_t *, + struct brand *); +extern int brand_solaris_elfexec(vnode_t *, execa_t *, uarg_t *, + intpdata_t *, int, long *, int, caddr_t, cred_t *, int, + struct brand *, char *, char *, char *, char *, char *); +extern void brand_solaris_exec(struct brand *); +extern int brand_solaris_fini(char **, struct modlinkage *, + struct brand *); +extern void brand_solaris_forklwp(klwp_t *, klwp_t *, struct brand *); +extern void brand_solaris_freelwp(klwp_t *, struct brand *); +extern int brand_solaris_initlwp(klwp_t *, struct brand *); +extern void brand_solaris_lwpexit(klwp_t *, struct brand *); +extern void brand_solaris_proc_exit(struct proc *, klwp_t *, + struct brand *); +extern void brand_solaris_setbrand(proc_t *, struct brand *); + +#if defined(_SYSCALL32) +typedef struct brand_elf_data32 { + uint32_t sed_phdr; + uint32_t sed_phent; + uint32_t sed_phnum; + uint32_t sed_entry; + uint32_t sed_base; + uint32_t sed_ldentry; + uint32_t sed_lddata; +} brand_elf_data32_t; + +typedef struct brand_common_reg32 { + uint32_t sbr_version; /* version number */ + caddr32_t sbr_handler; /* base address of handler */ +} brand_common_reg32_t; +#endif /* _SYSCALL32 */ + +/* + * Common information associated with all branded processes + */ +typedef struct brand_proc_data { + caddr_t spd_handler; /* address of user-space handler */ + brand_elf_data_t spd_elf_data; /* common ELF data for branded app. */ +} brand_proc_data_t; + +#define BRAND_NATIVE_DIR "/.SUNWnative/" +#define BRAND_NATIVE_LINKER32 BRAND_NATIVE_DIR "lib/ld.so.1" +#define BRAND_NATIVE_LINKER64 BRAND_NATIVE_DIR "lib/64/ld.so.1" + #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/i86pc/ml/offsets.in b/usr/src/uts/i86pc/ml/offsets.in index 029193b35e..ceefce6d3c 100644 --- a/usr/src/uts/i86pc/ml/offsets.in +++ b/usr/src/uts/i86pc/ml/offsets.in @@ -1,6 +1,5 @@ \ -\ Copyright 2009 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. +\ Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. \ \ CDDL HEADER START \ @@ -388,6 +387,9 @@ copyops brand b_machops +brand_proc_data_t + spd_handler + fastboot_file_t fb_va fb_pte_list_va diff --git a/usr/src/uts/intel/brand/common/brand_asm.h b/usr/src/uts/intel/brand/common/brand_asm.h index a6e5385f20..1d540db2a9 100644 --- a/usr/src/uts/intel/brand/common/brand_asm.h +++ b/usr/src/uts/intel/brand/common/brand_asm.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _COMMON_BRAND_ASM_H @@ -237,64 +236,6 @@ extern "C" { shl $4, SYSCALL_REG; /* syscall_num * 16 */ \ add SYSCALL_REG, scr /* leave return addr in scr reg. */ -#if defined(__amd64) - -/* - * To 'return' to our user-space handler, we just need to place its address - * into 'retreg'. The original return address is passed back in SYSCALL_REG. - */ -#define SYSCALL_EMUL(emul_table, handler, retreg) \ - CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ - CALC_TABLE_ADDR(SCR_REG, handler); \ - mov retreg, SYSCALL_REG; /* save orig return addr in syscall_reg */\ - mov SCR_REG, retreg; /* place new return addr in retreg */\ - mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */\ - mov V_SSP(SP_REG), SP_REG /* restore user stack pointer */ - -/* - * To 'return' to our user-space handler we need to update the user's %eip - * pointer in the saved interrupt state on the stack. The interrupt state was - * pushed onto our stack automatically when the interrupt occured; see the - * comments above. The original return address is passed back in SYSCALL_REG. - */ -#define INT_EMUL(emul_table, handler) \ - CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ - CALC_TABLE_ADDR(SCR_REG, handler); /* new return addr is in scratch */ \ - mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ \ - mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ \ - mov V_SSP(SP_REG), SP_REG; /* restore intr stack pointer */ \ - /*CSTYLED*/ \ - xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ - -#else /* !__amd64 */ - -/* - * To 'return' to our user-space handler, we just need to place its address - * into 'retreg'. The original return address is passed back in SYSCALL_REG. - */ -#define SYSCALL_EMUL(emul_table, handler, retreg) \ - CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ - mov retreg, SCR_REG; /* save orig return addr in scr reg */ \ - CALC_TABLE_ADDR(retreg, handler); /* new return addr is in retreg */ \ - mov SCR_REG, SYSCALL_REG; /* save orig return addr in %eax */ \ - GET_V(SP_REG, 0, V_U_EBX, SCR_REG) /* restore scratch register */ - -/* - * To 'return' to our user-space handler, we need to replace the - * iret target address. - * The original return address is passed back in %eax. - */ -#define INT_EMUL(emul_table, handler) \ - CALLBACK_PROLOGUE(emul_table, handler, SYSCALL_REG, SCR_REG, SCR_REGB);\ - CALC_TABLE_ADDR(SCR_REG, handler); /* new return addr is in scratch */ \ - mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ \ - GET_V(SP_REG, 0, V_U_EBX, SCR_REG); /* restore scratch register */ \ - add $V_END, SP_REG; /* restore intr stack pointer */ \ - /*CSTYLED*/ \ - xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ - -#endif /* !__amd64 */ - #endif /* _ASM */ #ifdef __cplusplus diff --git a/usr/src/uts/intel/brand/common/brand_solaris.s b/usr/src/uts/intel/brand/common/brand_solaris.s new file mode 100644 index 0000000000..eb4c6b6844 --- /dev/null +++ b/usr/src/uts/intel/brand/common/brand_solaris.s @@ -0,0 +1,195 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * This is an assembly file that gets #include-ed into the brand-specific + * assembly files (e.g. sn1_brand_asm.s) for Solaris-derived brands. + * We can't make these into functions since in the trap context there's + * no easy place to save the extra parameters that would be required, so + * each brand module needs its own copy of this code. We #include this and + * use brand-specific #defines to replace the XXX_brand_... definitions. + */ + +#ifdef lint + +#include <sys/systm.h> + +#else /* !lint */ + +#include <sys/asm_linkage.h> +#include <sys/privregs.h> +#include <sys/segments.h> +#include "assym.h" +#include "brand_asm.h" + +#endif /* !lint */ + +#ifdef lint + +void +XXX_brand_sysenter_callback(void) +{ +} + +void +XXX_brand_syscall_callback(void) +{ +} + +#if defined(__amd64) +void +XXX_brand_syscall32_callback(void) +{ +} +#endif /* amd64 */ + +void +XXX_brand_int91_callback(void) +{ +} + +#else /* !lint */ + +#ifdef _ASM /* The remainder of this file is only for assembly files */ + +#if defined(__amd64) + +/* + * syscall handler for 32-bit user processes: + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. + * To 'return' to our user-space handler, we just need to place its address + * into %rcx. The original return address is passed back in SYSCALL_REG. + */ +ENTRY(XXX_brand_syscall32_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); + mov %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */ + mov SCR_REG, %rcx; /* place new return addr in %rcx */ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ + mov V_SSP(SP_REG), SP_REG /* restore user stack pointer */ + jmp nopop_sys_syscall32_swapgs_sysretl +9: + retq +SET_SIZE(XXX_brand_syscall32_callback) + +/* + * syscall handler for 64-bit user processes: + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. + * To 'return' to our user-space handler, we just need to place its address + * into %rcx. The original return address is passed back in SYSCALL_REG. + */ +ENTRY(XXX_brand_syscall_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); + mov %rcx, SYSCALL_REG; /* save orig return addr in syscall_reg */ + mov SCR_REG, %rcx; /* place new return addr in %rcx */ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ + mov V_SSP(SP_REG), SP_REG /* restore user stack pointer */ + jmp nopop_sys_syscall_swapgs_sysretq +9: + retq +SET_SIZE(XXX_brand_syscall_callback) + +/* + * See "64-BIT INTERPOSITION STACK" in brand_asm.h. + * To 'return' to our user-space handler, we just need to place its address + * into %rdx. The original return address is passed back in SYSCALL_REG. + */ +ENTRY(XXX_brand_sysenter_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); + mov %rdx, SYSCALL_REG; /* save orig return addr in syscall_reg */ + mov SCR_REG, %rdx; /* place new return addr in %rdx */ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ + mov V_SSP(SP_REG), SP_REG /* restore user stack pointer */ + jmp sys_sysenter_swapgs_sysexit +9: + ret +SET_SIZE(XXX_brand_sysenter_callback) + +/* + * To 'return' to our user-space handler we need to update the user's %eip + * pointer in the saved interrupt state on the stack. The interrupt state was + * pushed onto our stack automatically when the interrupt occured; see the + * comments above. The original return address is passed back in SYSCALL_REG. + * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h. + */ +ENTRY(XXX_brand_int91_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); /* new ret addr is in scratch */ + mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ + mov %gs:CPU_RTMP_R15, SCR_REG; /* restore scratch register */ + mov V_SSP(SP_REG), SP_REG; /* restore intr stack pointer */ + /*CSTYLED*/ + xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ + jmp sys_sysint_swapgs_iret +9: + retq +SET_SIZE(XXX_brand_int91_callback) + +#else /* !__amd64 */ + +/* + * To 'return' to our user-space handler, we need to replace the iret target + * address. The original return address is passed back in %eax. + * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h. + */ +ENTRY(XXX_brand_syscall_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + CALC_TABLE_ADDR(SCR_REG, SPD_HANDLER); /* new ret addr is in scratch */ + mov SCR_REG, SYSCALL_REG; /* place new ret addr in syscallreg */ + GET_V(SP_REG, 0, V_U_EBX, SCR_REG); /* restore scratch register */ + add $V_END, SP_REG; /* restore intr stack pointer */ + /*CSTYLED*/ + xchg (SP_REG), SYSCALL_REG /* swap new and orig. return addrs */ + jmp nopop_sys_rtt_syscall +9: + ret +SET_SIZE(XXX_brand_syscall_callback) + +/* + * To 'return' to our user-space handler, we just need to place its address + * into %edx. The original return address is passed back in SYSCALL_REG. + * See "32-BIT INTERPOSITION STACK" in brand_asm.h. + */ +ENTRY(XXX_brand_sysenter_callback) + CALLBACK_PROLOGUE(XXX_emulation_table, SPD_HANDLER, SYSCALL_REG, + SCR_REG, SCR_REGB); + mov %edx, SCR_REG; /* save orig return addr in scr reg */ + CALC_TABLE_ADDR(%edx, SPD_HANDLER); /* new return addr is in %edx */ + mov SCR_REG, SYSCALL_REG; /* save orig return addr in %eax */ + GET_V(SP_REG, 0, V_U_EBX, SCR_REG) /* restore scratch register */ + sysexit +9: + ret +SET_SIZE(XXX_brand_sysenter_callback) + +#endif /* !__amd64 */ +#endif /* _ASM */ +#endif /* !lint */ diff --git a/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s b/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s index 8432554132..a211a075b1 100644 --- a/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s +++ b/usr/src/uts/intel/brand/sn1/sn1_brand_asm.s @@ -19,116 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(lint) +#define XXX_emulation_table sn1_emulation_table +#define XXX_brand_syscall32_callback sn1_brand_syscall32_callback +#define XXX_brand_syscall_callback sn1_brand_syscall_callback +#define XXX_brand_sysenter_callback sn1_brand_sysenter_callback +#define XXX_brand_int91_callback sn1_brand_int91_callback -#include <sys/systm.h> - -#else /* lint */ - -#include <sn1_offsets.h> -#include "../common/brand_asm.h" - -#endif /* lint */ - -#ifdef lint - -void -sn1_brand_sysenter_callback(void) -{ -} - -void -sn1_brand_syscall_callback(void) -{ -} - -#if defined(__amd64) -void -sn1_brand_syscall32_callback(void) -{ -} -#endif /* amd64 */ - -void -sn1_brand_int91_callback(void) -{ -} - -#else /* lint */ - -#if defined(__amd64) - -/* - * syscall handler for 32-bit user processes: - * %rcx - the address of the instruction after the syscall - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_syscall32_callback) - SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rcx) - jmp nopop_sys_syscall32_swapgs_sysretl -9: - retq -SET_SIZE(sn1_brand_syscall32_callback) - -/* - * syscall handler for 64-bit user processes: - * %rcx - the address of the instruction after the syscall - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_syscall_callback) - SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rcx) - jmp nopop_sys_syscall_swapgs_sysretq -9: - retq -SET_SIZE(sn1_brand_syscall_callback) - -/* - * %rdx - user space return address - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_sysenter_callback) - SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %rdx) - jmp sys_sysenter_swapgs_sysexit -9: - ret -SET_SIZE(sn1_brand_sysenter_callback) - -/* - * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_int91_callback) - INT_EMUL(sn1_emulation_table, SPD_HANDLER) - jmp sys_sysint_swapgs_iret -9: - retq -SET_SIZE(sn1_brand_int91_callback) - -#else /* !__amd64 */ - -/* - * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_syscall_callback) - INT_EMUL(sn1_emulation_table, SPD_HANDLER) - jmp nopop_sys_rtt_syscall -9: - ret -SET_SIZE(sn1_brand_syscall_callback) - -/* - * %edx - user space return address - * See "32-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(sn1_brand_sysenter_callback) - SYSCALL_EMUL(sn1_emulation_table, SPD_HANDLER, %edx) - sysexit -9: - ret -SET_SIZE(sn1_brand_sysenter_callback) - -#endif /* !__amd64 */ -#endif /* lint */ +#include "../common/brand_solaris.s" diff --git a/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s b/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s index d4a3b2eb5c..6fae877da2 100644 --- a/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s +++ b/usr/src/uts/intel/brand/solaris10/s10_brand_asm.s @@ -19,116 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(lint) +#define XXX_emulation_table s10_emulation_table +#define XXX_brand_syscall32_callback s10_brand_syscall32_callback +#define XXX_brand_syscall_callback s10_brand_syscall_callback +#define XXX_brand_sysenter_callback s10_brand_sysenter_callback +#define XXX_brand_int91_callback s10_brand_int91_callback -#include <sys/systm.h> - -#else /* lint */ - -#include <s10_offsets.h> -#include "../common/brand_asm.h" - -#endif /* lint */ - -#ifdef lint - -void -s10_brand_sysenter_callback(void) -{ -} - -void -s10_brand_syscall_callback(void) -{ -} - -#if defined(__amd64) -void -s10_brand_syscall32_callback(void) -{ -} -#endif /* amd64 */ - -void -s10_brand_int91_callback(void) -{ -} - -#else /* lint */ - -#if defined(__amd64) - -/* - * syscall handler for 32-bit user processes: - * %rcx - the address of the instruction after the syscall - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(s10_brand_syscall32_callback) - SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rcx) - jmp nopop_sys_syscall32_swapgs_sysretl -9: - retq -SET_SIZE(s10_brand_syscall32_callback) - -/* - * syscall handler for 64-bit user processes: - * %rcx - the address of the instruction after the syscall - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(s10_brand_syscall_callback) - SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rcx) - jmp nopop_sys_syscall_swapgs_sysretq -9: - retq -SET_SIZE(s10_brand_syscall_callback) - -/* - * %rdx - user space return address - * See "64-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(s10_brand_sysenter_callback) - SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %rdx) - jmp sys_sysenter_swapgs_sysexit -9: - ret -SET_SIZE(s10_brand_sysenter_callback) - -/* - * See "64-BIT INTERPOSITION STACK" and "64-BIT INT STACK" in brand_asm.h. - */ -ENTRY(s10_brand_int91_callback) - INT_EMUL(s10_emulation_table, SPD_HANDLER) - jmp sys_sysint_swapgs_iret -9: - retq -SET_SIZE(s10_brand_int91_callback) - -#else /* !__amd64 */ - -/* - * See "32-BIT INTERPOSITION STACK" and "32-BIT INT STACK" in brand_asm.h. - */ -ENTRY(s10_brand_syscall_callback) - INT_EMUL(s10_emulation_table, SPD_HANDLER) - jmp nopop_sys_rtt_syscall -9: - ret -SET_SIZE(s10_brand_syscall_callback) - -/* - * %edx - user space return address - * See "32-BIT INTERPOSITION STACK" in brand_asm.h. - */ -ENTRY(s10_brand_sysenter_callback) - SYSCALL_EMUL(s10_emulation_table, SPD_HANDLER, %edx) - sysexit -9: - ret -SET_SIZE(s10_brand_sysenter_callback) - -#endif /* !__amd64 */ -#endif /* lint */ +#include "../common/brand_solaris.s" diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index 807cb8f790..3151f3b4e3 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/asm_linkage.h> @@ -1423,6 +1422,18 @@ fcnname/**/_info: \ END_MODULE(ksocket); #endif +/* + * Stubs for elfexec + */ +#ifndef ELFEXEC_MODULE + MODULE(elfexec,exec); + STUB(elfexec, elfexec, nomod_einval); + STUB(elfexec, elf32exec, nomod_einval); + STUB(elfexec, mapexec_brand, nomod_einval); + STUB(elfexec, mapexec32_brand, nomod_einval); + END_MODULE(elfexec); +#endif + / this is just a marker for the area of text that contains stubs ENTRY_NP(stubs_end) diff --git a/usr/src/uts/intel/s10_brand/Makefile b/usr/src/uts/intel/s10_brand/Makefile index 7ed668ed74..ffda173a95 100644 --- a/usr/src/uts/intel/s10_brand/Makefile +++ b/usr/src/uts/intel/s10_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the Solaris 10 brand @@ -36,8 +35,6 @@ S10_BASE = $(UTSBASE)/common/brand/solaris10 # Define the module and object file sets. # MODULE = s10_brand -OFFSETS_H = $(OBJS_DIR)/s10_offsets.h -OFFSETS_SRC = $(S10_BASE)/s10_offsets.in OBJECTS = $(S10_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(S10_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(USR_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/intel/Makefile.intel # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # @@ -95,12 +92,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/sn1_brand/Makefile b/usr/src/uts/intel/sn1_brand/Makefile index b7c9afab6e..b0b3ca2635 100644 --- a/usr/src/uts/intel/sn1_brand/Makefile +++ b/usr/src/uts/intel/sn1_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the N-1 Solaris brand @@ -36,8 +35,6 @@ SN1_BASE = $(UTSBASE)/common/brand/sn1 # Define the module and object file sets. # MODULE = sn1_brand -OFFSETS_H = $(OBJS_DIR)/sn1_offsets.h -OFFSETS_SRC = $(SN1_BASE)/sn1_offsets.in OBJECTS = $(SN1_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(SN1_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(USR_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/intel/Makefile.intel # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # @@ -95,12 +92,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index c04ceea2c9..8b63f25931 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ #if !defined(lint) @@ -1296,6 +1295,18 @@ stubs_base: END_MODULE(ksocket); #endif +/* + * Stubs for elfexec + */ +#ifndef ELFEXEC_MODULE + MODULE(elfexec,exec); + STUB(elfexec, elfexec, nomod_einval); + STUB(elfexec, elf32exec, nomod_einval); + STUB(elfexec, mapexec_brand, nomod_einval); + STUB(elfexec, mapexec32_brand, nomod_einval); + END_MODULE(elfexec); +#endif + ! this is just a marker for the area of text that contains stubs .seg ".text" .global stubs_end diff --git a/usr/src/uts/sun4/brand/common/brand_solaris.s b/usr/src/uts/sun4/brand/common/brand_solaris.s new file mode 100644 index 0000000000..889218bc5f --- /dev/null +++ b/usr/src/uts/sun4/brand/common/brand_solaris.s @@ -0,0 +1,302 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * This is an assembly file that gets #include-ed into the brand-specific + * assembly files (e.g. sn1_brand_asm.s) for Solaris-derived brands. + * We can't make these into functions since in the trap context there's + * no easy place to save the extra parameters that would be required, so + * each brand module needs its own copy of this code. We #include this and + * use brand-specific #defines to replace the XXX_brand_... definitions. + */ + +#ifdef lint + +#include <sys/systm.h> + +void +XXX_brand_syscall32_callback(void) +{ +} + +void +XXX_brand_syscall_callback(void) +{ +} + +#else /* !lint */ + +#include <sys/asm_linkage.h> +#include <sys/machthread.h> +#include <sys/privregs.h> +#include "assym.h" + +#ifdef _ASM /* The remainder of this file is only for assembly files */ + +#if defined(sun4v) + +#define GLOBALS_SWAP(reg) \ + rdpr %gl, reg; \ + wrpr reg, 1, %gl + +/* + * The GLOBALS_RESTORE macro can only be one instruction since it's + * used in a delay slot. + */ +#define GLOBALS_RESTORE(reg) \ + wrpr reg, 0, %gl + +#else /* !sun4v */ + +#define GLOBALS_SWAP(reg) \ + rdpr %pstate, reg; \ + wrpr reg, PSTATE_AG, %pstate + +/* + * The GLOBALS_RESTORE macro can only be one instruction since it's + * used in a delay slot. + */ +#define GLOBALS_RESTORE(reg) \ + wrpr reg, %g0, %pstate + +#endif /* !sun4v */ + +/* + * Input parameters: + * %g1: return point + * %g2: pointer to our cpu structure + */ +ENTRY(XXX_brand_syscall32_callback) + /* + * If the trapping thread has the address mask bit clear, then it's + * a 64-bit process, and has no business calling 32-bit syscalls. + */ + rdpr %tstate, %g3; /* %tstate.am is the trapping */ + andcc %g3, TSTATE_AM, %g3; /* threads address mask bit */ + bne,pt %xcc, _entry; + nop; + jmp %g1; /* 64 bit process, bail out */ + nop; +SET_SIZE(XXX_brand_syscall32_callback) + +/* + * Input parameters: + * %g1: return point + * %g2: pointer to our cpu structure + */ +ENTRY(XXX_brand_syscall_callback) + /* + * If the trapping thread has the address mask bit set, then it's + * a 32-bit process, and has no business calling 64-bit syscalls. + */ + rdpr %tstate, %g3; /* %tstate.am is the trapping */ + andcc %g3, TSTATE_AM, %g3; /* threads address mask bit */ + be,pt %xcc, _entry; + nop; + jmp %g1; /* 32 bit process, bail out */ + nop; +SET_SIZE(XXX_brand_syscall_callback) + +ENTRY(XXX_brand_syscall_callback_common) +_entry: + /* + * Input parameters: + * %g1: return point + * %g2: pointer to our cpu structure + * + * Note that we're free to use any %g? registers as long as + * we are are executing with alternate globals. If we're + * executing with user globals we need to backup any registers + * that we want to use so that we can restore them when we're + * done. + * + * Save some locals in the CPU tmp area to give us a little + * room to work. + */ + stn %l0, [%g2 + CPU_TMP1]; + stn %l1, [%g2 + CPU_TMP2]; + +#if defined(sun4v) + /* + * On sun4v save our input parameters (which are stored in the + * alternate globals) since we'll need to switch between alternate + * globals and normal globals, and on sun4v the alternate globals + * are not preserved across these types of switches. + */ + stn %l2, [%g2 + CPU_TMP3]; + stn %l3, [%g2 + CPU_TMP4]; + + mov %g1, %l2; /* save %g1 in %l2 */ + mov %g2, %l3; /* save %g2 in %l3 */ +#endif /* sun4v */ + + /* + * Switch from the alternate to user globals to grab the syscall + * number. + */ + GLOBALS_SWAP(%l0); /* switch to normal globals */ + + /* + * If the system call number is >= 1024, then it is a native + * syscall that doesn't need emulation. + */ + cmp %g1, 1024; /* is this a native syscall? */ + bl,a _indirect_check; /* probably not, continue checking */ + mov %g1, %l1; /* delay slot - grab syscall number */ + + /* + * This is a native syscall, probably from the emulation library. + * Subtract 1024 from the syscall number and let it go through. + */ + sub %g1, 1024, %g1; /* convert magic num to real syscall */ + ba _exit; /* jump back into syscall path */ + GLOBALS_RESTORE(%l0); /* delay slot - */ + /* switch back to alternate globals */ + +_indirect_check: + /* + * If the system call number is 0 (SYS_syscall), then this might be + * an indirect syscall, in which case the actual syscall number + * would be stored in %o0, in which case we need to redo the + * the whole >= 1024 check. + */ + brnz,pt %g1, _emulation_check; /* is this an indirect syscall? */ + nop; /* if not, goto the emulation check */ + + /* + * Indirect syscalls are only supported for 32 bit processes so + * consult the tstate address mask again. + */ + rdpr %tstate, %l1; /* %tstate.am is the trapping */ + andcc %l1, TSTATE_AM, %l1; /* threads address mask bit */ + be,a,pn %xcc, _exit; + GLOBALS_RESTORE(%l0); /* delay slot - */ + /* switch back to alternate globals */ + + /* + * The caller is 32 bit and this an indirect system call. + */ + cmp %o0, 1024; /* is this a native syscall? */ + bl,a _emulation_check; /* no, goto the emulation check */ + mov %o0, %l1; /* delay slot - grab syscall number */ + + /* + * This is native indirect syscall, probably from the emulation + * library. Subtract 1024 from the syscall number and let it go + * through. + */ + sub %o0, 1024, %o0; /* convert magic num to real syscall */ + ba _exit; /* jump back into syscall path */ + GLOBALS_RESTORE(%l0); /* delay slot - */ + /* switch back to alternate globals */ + +_emulation_check: + GLOBALS_RESTORE(%l0); /* switch back to alternate globals */ + + /* + * Check to see if we want to interpose on this system call. If + * not, we jump back into the normal syscall path and pretend + * nothing happened. %l1 contains the syscall we're invoking. + */ + set XXX_emulation_table, %g3; + ldn [%g3], %g3; + add %g3, %l1, %g3; + ldub [%g3], %g3; + brz %g3, _exit; + nop; + + /* + * Find the address of the userspace handler. + * cpu->cpu_thread->t_procp->p_brand_data->spd_handler. + */ +#if defined(sun4v) + /* restore the alternate global registers after incrementing %gl */ + mov %l3, %g2; +#endif /* sun4v */ + ldn [%g2 + CPU_THREAD], %g3; /* get thread ptr */ + ldn [%g3 + T_PROCP], %g4; /* get proc ptr */ + ldn [%g4 + P_BRAND_DATA], %g5; /* get brand data ptr */ + ldn [%g5 + SPD_HANDLER], %g5; /* get userland brnd hdlr ptr */ + brz %g5, _exit; /* has it been set? */ + nop; + + /* + * Make sure this isn't an agent lwp. We can't do syscall + * interposition for system calls made by a agent lwp. See + * the block comments in the top of the brand emulation library + * for more information. + */ + ldn [%g4 + P_AGENTTP], %g4; /* get agent thread ptr */ + cmp %g3, %g4; /* is this an agent thread? */ + be,pn %xcc, _exit; /* if so don't emulate */ + nop; + + /* + * Now the magic happens. Grab the trap return address and then + * reset it to point to the user space handler. When we execute + * the 'done' instruction, we will jump into our handler instead of + * the user's code. We also stick the old return address in %g5, + * so we can return to the proper instruction in the user's code. + * Note: we also pass back the base address of the syscall + * emulation table. This is a performance hack to avoid having to + * look it up on every call. + */ + rdpr %tnpc, %l1; /* save old tnpc */ + wrpr %g0, %g5, %tnpc; /* setup tnpc */ + GLOBALS_SWAP(%l0); /* switch to normal globals */ + mov %l1, %g5; /* pass tnpc to user code in %g5 */ + GLOBALS_RESTORE(%l0); /* switch back to alternate globals */ + + /* Update the address we're going to return to */ +#if defined(sun4v) + set fast_trap_done_chk_intr, %l2; +#else /* !sun4v */ + set fast_trap_done_chk_intr, %g1; +#endif /* !sun4v */ + +_exit: + /* + * Restore registers before returning. + * + * Note that %g2 should be loaded with the CPU struct addr and + * %g1 should be loaded the address we're going to return to. + */ +#if defined(sun4v) + /* restore the alternate global registers after incrementing %gl */ + mov %l2, %g1; /* restore %g1 from %l2 */ + mov %l3, %g2; /* restore %g2 from %l3 */ + + ldn [%g2 + CPU_TMP4], %l3; /* restore locals */ + ldn [%g2 + CPU_TMP3], %l2; +#endif /* sun4v */ + + ldn [%g2 + CPU_TMP2], %l1; /* restore locals */ + ldn [%g2 + CPU_TMP1], %l0; + + jmp %g1; + nop; +SET_SIZE(XXX_brand_syscall_callback_common) + +#endif /* _ASM */ +#endif /* !lint */ diff --git a/usr/src/uts/sun4/brand/sn1/sn1_brand_asm.s b/usr/src/uts/sun4/brand/sn1/sn1_brand_asm.s index f1052a3332..b1af356944 100644 --- a/usr/src/uts/sun4/brand/sn1/sn1_brand_asm.s +++ b/usr/src/uts/sun4/brand/sn1/sn1_brand_asm.s @@ -19,272 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(lint) +#define XXX_emulation_table sn1_emulation_table +#define XXX_brand_syscall32_callback sn1_brand_syscall32_callback +#define XXX_brand_syscall_callback sn1_brand_syscall_callback +#define XXX_brand_syscall_callback_common sn1_brand_syscall_callback_common -#include <sys/systm.h> - -void -sn1_brand_syscall32_callback(void) -{ -} - -void -sn1_brand_syscall_callback(void) -{ -} - -#else /* !lint */ - -#include <sys/asm_linkage.h> -#include <sys/machthread.h> -#include <sys/privregs.h> -#include <sn1_offsets.h> -#include "assym.h" - -#if defined(sun4v) - -#define GLOBALS_SWAP(reg) \ - rdpr %gl, reg ;\ - wrpr reg, 1, %gl - -/* - * The GLOBALS_RESTORE macro can only be one instruction since it's - * used in a delay slot. - */ -#define GLOBALS_RESTORE(reg) \ - wrpr reg, 0, %gl - -#else /* !sun4v */ - -#define GLOBALS_SWAP(reg) \ - rdpr %pstate, reg ;\ - wrpr reg, PSTATE_AG, %pstate - -/* - * The GLOBALS_RESTORE macro can only be one instruction since it's - * used in a delay slot. - */ -#define GLOBALS_RESTORE(reg) \ - wrpr reg, %g0, %pstate - -#endif /* !sun4v */ - - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - */ - ENTRY(sn1_brand_syscall32_callback) - /* - * If the trapping thread has the address mask bit clear, then it's - * a 64-bit process, and has no business calling 32-bit syscalls. - */ - rdpr %tstate, %g3 ! %tstate.am is the trapping - andcc %g3, TSTATE_AM, %g3 ! threads address mask bit - bne,pt %xcc, _entry - nop - jmp %g1 ! 64 bit process, bail out - nop - SET_SIZE(sn1_brand_syscall32_callback) - - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - */ - ENTRY(sn1_brand_syscall_callback) - /* - * If the trapping thread has the address mask bit set, then it's - * a 32-bit process, and has no business calling 64-bit syscalls. - */ - rdpr %tstate, %g3 ! %tstate.am is the trapping - andcc %g3, TSTATE_AM, %g3 ! threads address mask bit - be,pt %xcc, _entry - nop - jmp %g1 ! 32 bit process, bail out - nop - SET_SIZE(sn1_brand_syscall_callback) - - ENTRY(sn1_brand_syscall_callback_common) -_entry: - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - * - * Note that we're free to use any %g? registers as long as - * we are are executing with alternate globals. If we're - * executing with user globals we need to backup any registers - * that we want to use so that we can restore them when we're - * done. - * - * Save some locals in the CPU tmp area to give us a little - * room to work. - */ - stn %l0, [%g2 + CPU_TMP1] - stn %l1, [%g2 + CPU_TMP2] - -#if defined(sun4v) - /* - * On sun4v save our input parameters (which are stored in the - * alternate globals) since we'll need to switch between alternate - * globals and normal globals, and on sun4v the alternate globals - * are not preserved across these types of switches. - */ - stn %l2, [%g2 + CPU_TMP3] - stn %l3, [%g2 + CPU_TMP4] - - mov %g1, %l2 ! save %g1 in %l2 - mov %g2, %l3 ! save %g2 in %l3 -#endif /* sun4v */ - - /* - * Switch from the alternate to user globals to grab the syscall - * number. - */ - GLOBALS_SWAP(%l0) ! switch to normal globals - - /* - * If the system call number is >= 1024, then it is a native - * syscall that doesn't need emulation. - */ - cmp %g1, 1024 ! is this a native syscall? - bl,a _indirect_check ! probably not, continue checking - mov %g1, %l1 ! delay slot - grab syscall number - - /* - * This is a native syscall, probably from the emulation library. - * Subtract 1024 from the syscall number and let it go through. - */ - sub %g1, 1024, %g1 ! convert magic num to real syscall - ba _exit ! jump back into syscall path - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - -_indirect_check: - /* - * If the system call number is 0 (SYS_syscall), then this might be - * an indirect syscall, in which case the actual syscall number - * would be stored in %o0, in which case we need to redo the - * the whole >= 1024 check. - */ - brnz,pt %g1, _emulation_check ! is this an indirect syscall? - nop ! if not, goto the emulation check - - /* - * Indirect syscalls are only supported for 32 bit processes so - * consult the tstate address mask again. - */ - rdpr %tstate, %l1 ! %tstate.am is the trapping - andcc %l1, TSTATE_AM, %l1 ! threads address mask bit - be,a,pn %xcc, _exit - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - - /* - * The caller is 32 bit and this an indirect system call. - */ - cmp %o0, 1024 ! is this a native syscall? - bl,a _emulation_check ! no, goto the emulation check - mov %o0, %l1 ! delay slot - grab syscall number - - /* - * This is native indirect syscall, probably from the emulation library. - * Subtract 1024 from the syscall number and let it go through. - */ - sub %o0, 1024, %o0 ! convert magic num to real syscall - ba _exit ! jump back into syscall path - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - -_emulation_check: - GLOBALS_RESTORE(%l0) ! switch back to alternate globals - - /* - * Check to see if we want to interpose on this system call. If - * not, we jump back into the normal syscall path and pretend - * nothing happened. %l1 contains the syscall we're invoking. - */ - set sn1_emulation_table, %g3 - ldn [%g3], %g3 - add %g3, %l1, %g3 - ldub [%g3], %g3 - brz %g3, _exit - nop - - /* - * Find the address of the userspace handler. - * cpu->cpu_thread->t_procp->p_brand_data->spd_handler. - */ -#if defined(sun4v) - ! restore the alternate global registers after incrementing %gl - mov %l3, %g2 -#endif /* sun4v */ - ldn [%g2 + CPU_THREAD], %g3 ! get thread ptr - ldn [%g3 + T_PROCP], %g4 ! get proc ptr - ldn [%g4 + P_BRAND_DATA], %g5 ! get brand data ptr - ldn [%g5 + SPD_HANDLER], %g5 ! get userland brand handler ptr - brz %g5, _exit ! has it been set? - nop - - /* - * Make sure this isn't an agent lwp. We can't do syscall - * interposition for system calls made by a agent lwp. See - * the block comments in the top of the brand emulation library - * for more information. - */ - ldn [%g4 + P_AGENTTP], %g4 ! get agent thread ptr - cmp %g3, %g4 ! is this an agent thread? - be,pn %xcc, _exit ! if so don't emulate - nop - - /* - * Now the magic happens. Grab the trap return address and then - * reset it to point to the user space handler. When we execute - * the 'done' instruction, we will jump into our handler instead of - * the user's code. We also stick the old return address in %g5, - * so we can return to the proper instruction in the user's code. - * Note: we also pass back the base address of the syscall - * emulation table. This is a performance hack to avoid having to - * look it up on every call. - */ - rdpr %tnpc, %l1 ! save old tnpc - wrpr %g0, %g5, %tnpc ! setup tnpc - GLOBALS_SWAP(%l0) ! switch to normal globals - mov %l1, %g5 ! pass tnpc to user code in %g5 - GLOBALS_RESTORE(%l0) ! switch back to alternate globals - - /* Update the address we're going to return to */ -#if defined(sun4v) - set fast_trap_done_chk_intr, %l2 -#else /* !sun4v */ - set fast_trap_done_chk_intr, %g1 -#endif /* !sun4v */ - -_exit: - /* - * Restore registers before returning. - * - * Note that %g2 should be loaded with the CPU struct addr and - * %g1 should be loaded the address we're going to return to. - */ -#if defined(sun4v) - ! restore the alternate global registers after incrementing %gl - mov %l2, %g1 ! restore %g1 from %l2 - mov %l3, %g2 ! restore %g2 from %l3 - - ldn [%g2 + CPU_TMP4], %l3 ! restore locals - ldn [%g2 + CPU_TMP3], %l2 -#endif /* sun4v */ - - ldn [%g2 + CPU_TMP2], %l1 ! restore locals - ldn [%g2 + CPU_TMP1], %l0 - - jmp %g1 - nop - SET_SIZE(sn1_brand_syscall_callback_common) -#endif /* !lint */ +#include "../common/brand_solaris.s" diff --git a/usr/src/uts/sun4/brand/solaris10/s10_brand_asm.s b/usr/src/uts/sun4/brand/solaris10/s10_brand_asm.s index 9ab99b225c..7fd817bac6 100644 --- a/usr/src/uts/sun4/brand/solaris10/s10_brand_asm.s +++ b/usr/src/uts/sun4/brand/solaris10/s10_brand_asm.s @@ -19,272 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(lint) +#define XXX_emulation_table s10_emulation_table +#define XXX_brand_syscall32_callback s10_brand_syscall32_callback +#define XXX_brand_syscall_callback s10_brand_syscall_callback +#define XXX_brand_syscall_callback_common s10_brand_syscall_callback_common -#include <sys/systm.h> - -void -s10_brand_syscall32_callback(void) -{ -} - -void -s10_brand_syscall_callback(void) -{ -} - -#else /* !lint */ - -#include <sys/asm_linkage.h> -#include <sys/machthread.h> -#include <sys/privregs.h> -#include <s10_offsets.h> -#include "assym.h" - -#if defined(sun4v) - -#define GLOBALS_SWAP(reg) \ - rdpr %gl, reg ;\ - wrpr reg, 1, %gl - -/* - * The GLOBALS_RESTORE macro can only be one instruction since it's - * used in a delay slot. - */ -#define GLOBALS_RESTORE(reg) \ - wrpr reg, 0, %gl - -#else /* !sun4v */ - -#define GLOBALS_SWAP(reg) \ - rdpr %pstate, reg ;\ - wrpr reg, PSTATE_AG, %pstate - -/* - * The GLOBALS_RESTORE macro can only be one instruction since it's - * used in a delay slot. - */ -#define GLOBALS_RESTORE(reg) \ - wrpr reg, %g0, %pstate - -#endif /* !sun4v */ - - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - */ - ENTRY(s10_brand_syscall32_callback) - /* - * If the trapping thread has the address mask bit clear, then it's - * a 64-bit process, and has no business calling 32-bit syscalls. - */ - rdpr %tstate, %g3 ! %tstate.am is the trapping - andcc %g3, TSTATE_AM, %g3 ! threads address mask bit - bne,pt %xcc, _entry - nop - jmp %g1 ! 64 bit process, bail out - nop - SET_SIZE(s10_brand_syscall32_callback) - - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - */ - ENTRY(s10_brand_syscall_callback) - /* - * If the trapping thread has the address mask bit set, then it's - * a 32-bit process, and has no business calling 64-bit syscalls. - */ - rdpr %tstate, %g3 ! %tstate.am is the trapping - andcc %g3, TSTATE_AM, %g3 ! threads address mask bit - be,pt %xcc, _entry - nop - jmp %g1 ! 32 bit process, bail out - nop - SET_SIZE(s10_brand_syscall_callback) - - ENTRY(s10_brand_syscall_callback_common) -_entry: - /* - * Input parameters: - * %g1: return point - * %g2: pointer to our cpu structure - * - * Note that we're free to use any %g? registers as long as - * we are are executing with alternate globals. If we're - * executing with user globals we need to backup any registers - * that we want to use so that we can restore them when we're - * done. - * - * Save some locals in the CPU tmp area to give us a little - * room to work. - */ - stn %l0, [%g2 + CPU_TMP1] - stn %l1, [%g2 + CPU_TMP2] - -#if defined(sun4v) - /* - * On sun4v save our input parameters (which are stored in the - * alternate globals) since we'll need to switch between alternate - * globals and normal globals, and on sun4v the alternate globals - * are not preserved across these types of switches. - */ - stn %l2, [%g2 + CPU_TMP3] - stn %l3, [%g2 + CPU_TMP4] - - mov %g1, %l2 ! save %g1 in %l2 - mov %g2, %l3 ! save %g2 in %l3 -#endif /* sun4v */ - - /* - * Switch from the alternate to user globals to grab the syscall - * number. - */ - GLOBALS_SWAP(%l0) ! switch to normal globals - - /* - * If the system call number is >= 1024, then it is a native - * syscall that doesn't need emulation. - */ - cmp %g1, 1024 ! is this a native syscall? - bl,a _indirect_check ! probably not, continue checking - mov %g1, %l1 ! delay slot - grab syscall number - - /* - * This is a native syscall, probably from the emulation library. - * Subtract 1024 from the syscall number and let it go through. - */ - sub %g1, 1024, %g1 ! convert magic num to real syscall - ba _exit ! jump back into syscall path - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - -_indirect_check: - /* - * If the system call number is 0 (SYS_syscall), then this might be - * an indirect syscall, in which case the actual syscall number - * would be stored in %o0, in which case we need to redo the - * the whole >= 1024 check. - */ - brnz,pt %g1, _emulation_check ! is this an indirect syscall? - nop ! if not, goto the emulation check - - /* - * Indirect syscalls are only supported for 32 bit processes so - * consult the tstate address mask again. - */ - rdpr %tstate, %l1 ! %tstate.am is the trapping - andcc %l1, TSTATE_AM, %l1 ! threads address mask bit - be,a,pn %xcc, _exit - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - - /* - * The caller is 32 bit and this an indirect system call. - */ - cmp %o0, 1024 ! is this a native syscall? - bl,a _emulation_check ! no, goto the emulation check - mov %o0, %l1 ! delay slot - grab syscall number - - /* - * This is native indirect syscall, probably from the emulation library. - * Subtract 1024 from the syscall number and let it go through. - */ - sub %o0, 1024, %o0 ! convert magic num to real syscall - ba _exit ! jump back into syscall path - GLOBALS_RESTORE(%l0) ! delay slot - - ! switch back to alternate globals - -_emulation_check: - GLOBALS_RESTORE(%l0) ! switch back to alternate globals - - /* - * Check to see if we want to interpose on this system call. If - * not, we jump back into the normal syscall path and pretend - * nothing happened. %l1 contains the syscall we're invoking. - */ - set s10_emulation_table, %g3 - ldn [%g3], %g3 - add %g3, %l1, %g3 - ldub [%g3], %g3 - brz %g3, _exit - nop - - /* - * Find the address of the userspace handler. - * cpu->cpu_thread->t_procp->p_brand_data->spd_handler. - */ -#if defined(sun4v) - ! restore the alternate global registers after incrementing %gl - mov %l3, %g2 -#endif /* sun4v */ - ldn [%g2 + CPU_THREAD], %g3 ! get thread ptr - ldn [%g3 + T_PROCP], %g4 ! get proc ptr - ldn [%g4 + P_BRAND_DATA], %g5 ! get brand data ptr - ldn [%g5 + SPD_HANDLER], %g5 ! get userland brand handler ptr - brz %g5, _exit ! has it been set? - nop - - /* - * Make sure this isn't an agent lwp. We can't do syscall - * interposition for system calls made by a agent lwp. See - * the block comments in the top of the brand emulation library - * for more information. - */ - ldn [%g4 + P_AGENTTP], %g4 ! get agent thread ptr - cmp %g3, %g4 ! is this an agent thread? - be,pn %xcc, _exit ! if so don't emulate - nop - - /* - * Now the magic happens. Grab the trap return address and then - * reset it to point to the user space handler. When we execute - * the 'done' instruction, we will jump into our handler instead of - * the user's code. We also stick the old return address in %g5, - * so we can return to the proper instruction in the user's code. - * Note: we also pass back the base address of the syscall - * emulation table. This is a performance hack to avoid having to - * look it up on every call. - */ - rdpr %tnpc, %l1 ! save old tnpc - wrpr %g0, %g5, %tnpc ! setup tnpc - GLOBALS_SWAP(%l0) ! switch to normal globals - mov %l1, %g5 ! pass tnpc to user code in %g5 - GLOBALS_RESTORE(%l0) ! switch back to alternate globals - - /* Update the address we're going to return to */ -#if defined(sun4v) - set fast_trap_done_chk_intr, %l2 -#else /* !sun4v */ - set fast_trap_done_chk_intr, %g1 -#endif /* !sun4v */ - -_exit: - /* - * Restore registers before returning. - * - * Note that %g2 should be loaded with the CPU struct addr and - * %g1 should be loaded the address we're going to return to. - */ -#if defined(sun4v) - ! restore the alternate global registers after incrementing %gl - mov %l2, %g1 ! restore %g1 from %l2 - mov %l3, %g2 ! restore %g2 from %l3 - - ldn [%g2 + CPU_TMP4], %l3 ! restore locals - ldn [%g2 + CPU_TMP3], %l2 -#endif /* sun4v */ - - ldn [%g2 + CPU_TMP2], %l1 ! restore locals - ldn [%g2 + CPU_TMP1], %l0 - - jmp %g1 - nop - SET_SIZE(s10_brand_syscall_callback_common) -#endif /* !lint */ +#include "../common/brand_solaris.s" diff --git a/usr/src/uts/sun4/ml/offsets.in b/usr/src/uts/sun4/ml/offsets.in index c4ce99506e..974c48672e 100644 --- a/usr/src/uts/sun4/ml/offsets.in +++ b/usr/src/uts/sun4/ml/offsets.in @@ -1,6 +1,5 @@ \ offsets.in: input file to produce assym.h using the stabs program -\ Copyright 2009 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. +\ Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. \ \ CDDL HEADER START \ @@ -555,3 +554,6 @@ copyops brand BRAND_SIZE b_machops + +brand_proc_data_t + spd_handler diff --git a/usr/src/uts/sun4u/s10_brand/Makefile b/usr/src/uts/sun4u/s10_brand/Makefile index 9d2c189970..6fdde88f6a 100644 --- a/usr/src/uts/sun4u/s10_brand/Makefile +++ b/usr/src/uts/sun4u/s10_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the Solaris 10 brand @@ -36,8 +35,6 @@ S10_BASE = $(UTSBASE)/common/brand/solaris10 # Define the module and object file sets. # MODULE = s10_brand -OFFSETS_H = $(OBJS_DIR)/s10_offsets.h -OFFSETS_SRC = $(S10_BASE)/s10_offsets.in OBJECTS = $(S10_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(S10_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/sun4u/Makefile.sun4u # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Update compiler variables. @@ -82,12 +79,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4u/sn1_brand/Makefile b/usr/src/uts/sun4u/sn1_brand/Makefile index ad7b808e02..135ee8667b 100644 --- a/usr/src/uts/sun4u/sn1_brand/Makefile +++ b/usr/src/uts/sun4u/sn1_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the N-1 Solaris brand @@ -36,8 +35,6 @@ SN1_BASE = $(UTSBASE)/common/brand/sn1 # Define the module and object file sets. # MODULE = sn1_brand -OFFSETS_H = $(OBJS_DIR)/sn1_offsets.h -OFFSETS_SRC = $(SN1_BASE)/sn1_offsets.in OBJECTS = $(SN1_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(SN1_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/sun4u/Makefile.sun4u # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Update compiler variables. @@ -82,12 +79,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4v/s10_brand/Makefile b/usr/src/uts/sun4v/s10_brand/Makefile index c034010201..acdd849a3f 100644 --- a/usr/src/uts/sun4v/s10_brand/Makefile +++ b/usr/src/uts/sun4v/s10_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the Solaris 10 brand @@ -36,8 +35,6 @@ S10_BASE = $(UTSBASE)/common/brand/solaris10 # Define the module and object file sets. # MODULE = s10_brand -OFFSETS_H = $(OBJS_DIR)/s10_offsets.h -OFFSETS_SRC = $(S10_BASE)/s10_offsets.in OBJECTS = $(S10_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(S10_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/sun4v/Makefile.sun4v # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Update compiler variables. @@ -82,12 +79,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/sun4v/Makefile.targ diff --git a/usr/src/uts/sun4v/sn1_brand/Makefile b/usr/src/uts/sun4v/sn1_brand/Makefile index 6a9dc5e1af..bea8c2527e 100644 --- a/usr/src/uts/sun4v/sn1_brand/Makefile +++ b/usr/src/uts/sun4v/sn1_brand/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # This makefile drives the production of the kernel component of # the N-1 Solaris brand @@ -36,8 +35,6 @@ SN1_BASE = $(UTSBASE)/common/brand/sn1 # Define the module and object file sets. # MODULE = sn1_brand -OFFSETS_H = $(OBJS_DIR)/sn1_offsets.h -OFFSETS_SRC = $(SN1_BASE)/sn1_offsets.in OBJECTS = $(SN1_BRAND_OBJS:%=$(OBJS_DIR)/%) LINTS = $(SN1_BRAND_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_BRAND_DIR)/$(MODULE) @@ -50,9 +47,9 @@ include $(UTSBASE)/sun4v/Makefile.sun4v # # Define targets # -ALL_TARGET = $(OFFSETS_H) $(BINARY) +ALL_TARGET = $(BINARY) LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(OFFSETS_H) $(BINARY) $(ROOTMODULE) +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Update compiler variables. @@ -82,12 +79,6 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) # -# Create genassym.h -# -$(OFFSETS_H): $(OFFSETS_SRC) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - -# # Include common targets. # include $(UTSBASE)/sun4v/Makefile.targ |