Index: user/attilio/vmc-playground/Makefile.inc1 =================================================================== --- user/attilio/vmc-playground/Makefile.inc1 (revision 246333) +++ user/attilio/vmc-playground/Makefile.inc1 (revision 246334) @@ -1,1816 +1,1817 @@ # # $FreeBSD$ # # Make command line options: # -DNO_CLEANDIR run ${MAKE} clean, instead of ${MAKE} cleandir # -DNO_CLEAN do not clean at all # -DDB_FROM_SRC use the user/group databases in src/etc instead of # the system database when installing. # -DNO_SHARE do not go into share subdir # -DKERNFAST define NO_KERNEL{CONFIG,CLEAN,DEPEND,OBJ} # -DNO_KERNELCONFIG do not run config in ${MAKE} buildkernel # -DNO_KERNELCLEAN do not run ${MAKE} clean in ${MAKE} buildkernel # -DNO_KERNELDEPEND do not run ${MAKE} depend in ${MAKE} buildkernel # -DNO_KERNELOBJ do not run ${MAKE} obj in ${MAKE} buildkernel # -DNO_PORTSUPDATE do not update ports in ${MAKE} update # -DNO_ROOT install without using root privilege # -DNO_DOCUPDATE do not update doc in ${MAKE} update # -DNO_CTF do not run the DTrace CTF conversion tools on built objects # LOCAL_DIRS="list of dirs" to add additional dirs to the SUBDIR list # LOCAL_LIB_DIRS="list of dirs" to add additional dirs to libraries target # LOCAL_MTREE="list of mtree files" to process to allow local directories # to be created before files are installed # LOCAL_TOOL_DIRS="list of dirs" to add additional dirs to the build-tools # list # METALOG="path to metadata log" to write permission and ownership # when NO_ROOT is set. (default: ${DESTDIR}/METALOG) # TARGET="machine" to crossbuild world for a different machine type # TARGET_ARCH= may be required when a TARGET supports multiple endians # BUILDENV_SHELL= shell to launch for the buildenv target (def:/bin/sh) # WORLD_FLAGS= additional flags to pass to make(1) during buildworld # KERNEL_FLAGS= additional flags to pass to make(1) during buildkernel # # The intended user-driven targets are: # buildworld - rebuild *everything*, including glue to help do upgrades # installworld- install everything built by "buildworld" # doxygen - build API documentation of the kernel # update - convenient way to update your source tree (eg: cvsup/cvs) # # Standard targets (not defined here) are documented in the makefiles in # /usr/share/mk. These include: # obj depend all install clean cleandepend cleanobj # You are supposed to define both of these when calling Makefile.inc1 # directly. However, some old scripts don't. Cope for the moment, but # issue a new warning for a transition period. .if defined(TARGET) && !defined(TARGET_ARCH) .warning "You must pass both TARGET and TARGET_ARCH to Makefile.inc1. Setting TARGET_ARCH=${TARGET}." TARGET_ARCH=${TARGET} .endif .if !defined(TARGET) || !defined(TARGET_ARCH) .error "Both TARGET and TARGET_ARCH must be defined." .endif .include .include .include # We must do share/info early so that installation of info `dir' # entries works correctly. Do it first since it is less likely to # grow dependencies on include and lib than vice versa. # # We must do lib/ and libexec/ before bin/, because if installworld # installs a new /bin/sh, the 'make' command will *immediately* # use that new version. And the new (dynamically-linked) /bin/sh # will expect to find appropriate libraries in /lib and /libexec. # SUBDIR= share/info lib libexec SUBDIR+=bin .if ${MK_GAMES} != "no" SUBDIR+=games .endif .if ${MK_CDDL} != "no" SUBDIR+=cddl .endif SUBDIR+=gnu include .if ${MK_KERBEROS} != "no" SUBDIR+=kerberos5 .endif .if ${MK_RESCUE} != "no" SUBDIR+=rescue .endif SUBDIR+=sbin .if ${MK_CRYPT} != "no" SUBDIR+=secure .endif .if !defined(NO_SHARE) SUBDIR+=share .endif SUBDIR+=sys usr.bin usr.sbin .if ${MK_OFED} != "no" SUBDIR+=contrib/ofed .endif # # We must do etc/ last for install/distribute to work. # SUBDIR+=etc # These are last, since it is nice to at least get the base system # rebuilt before you do them. .for _DIR in ${LOCAL_LIB_DIRS} ${LOCAL_DIRS} .if exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} .endif .endfor .if defined(SUBDIR_OVERRIDE) SUBDIR= ${SUBDIR_OVERRIDE} .endif .if defined(NOCLEAN) NO_CLEAN= ${NOCLEAN} .endif .if defined(NO_CLEANDIR) CLEANDIR= clean cleandepend .else CLEANDIR= cleandir .endif LOCAL_TOOL_DIRS?= BUILDENV_SHELL?=/bin/sh CVS?= cvs CVSFLAGS?= -A -P -d -I! SVN?= svn SVNFLAGS?= -r HEAD SUP?= /usr/bin/csup SUPFLAGS?= -g -L 2 .if defined(SUPHOST) SUPFLAGS+= -h ${SUPHOST} .endif MAKEOBJDIRPREFIX?= /usr/obj .if !defined(OSRELDATE) .if exists(/usr/include/osreldate.h) OSRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \ /usr/include/osreldate.h .else OSRELDATE= 0 .endif .endif .if !defined(VERSION) VERSION!= uname -srp VERSION+= ${OSRELDATE} .endif KNOWN_ARCHES?= amd64 arm armeb/arm armv6/arm armv6eb/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64 .if ${TARGET} == ${TARGET_ARCH} _t= ${TARGET} .else _t= ${TARGET_ARCH}/${TARGET} .endif .for _t in ${_t} .if empty(KNOWN_ARCHES:M${_t}) .error Unknown target ${TARGET_ARCH}:${TARGET}. .endif .endfor .if ${TARGET} == ${MACHINE} TARGET_CPUTYPE?=${CPUTYPE} .else TARGET_CPUTYPE?= .endif .if !empty(TARGET_CPUTYPE) _TARGET_CPUTYPE=${TARGET_CPUTYPE} .else _TARGET_CPUTYPE=dummy .endif _CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} \ -f /dev/null -m ${.CURDIR}/share/mk -V CPUTYPE .if ${_CPUTYPE} != ${_TARGET_CPUTYPE} .error CPUTYPE global should be set with ?=. .endif .if make(buildworld) BUILD_ARCH!= uname -p .if ${MACHINE_ARCH} != ${BUILD_ARCH} .error To cross-build, set TARGET_ARCH. .endif .endif .if ${MACHINE} == ${TARGET} && ${MACHINE_ARCH} == ${TARGET_ARCH} && !defined(CROSS_BUILD_TESTING) OBJTREE= ${MAKEOBJDIRPREFIX} .else OBJTREE= ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH} .endif WORLDTMP= ${OBJTREE}${.CURDIR}/tmp # /usr/games added for fortune which depend on strfile BPATH= ${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/usr/games:${WORLDTMP}/legacy/bin XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin:${WORLDTMP}/usr/games STRICTTMPPATH= ${BPATH}:${XPATH} TMPPATH= ${STRICTTMPPATH}:${PATH} # # Avoid running mktemp(1) unless actually needed. # It may not be functional, e.g., due to new ABI # when in the middle of installing over this system. # .if make(distributeworld) || make(installworld) INSTALLTMP!= /usr/bin/mktemp -d -u -t install .endif # # Building a world goes through the following stages # # 1. legacy stage [BMAKE] # This stage is responsible for creating compatibility # shims that are needed by the bootstrap-tools, # build-tools and cross-tools stages. # 1. bootstrap-tools stage [BMAKE] # This stage is responsible for creating programs that # are needed for backward compatibility reasons. They # are not built as cross-tools. # 2. build-tools stage [TMAKE] # This stage is responsible for creating the object # tree and building any tools that are needed during # the build process. # 3. cross-tools stage [XMAKE] # This stage is responsible for creating any tools that # are needed for cross-builds. A cross-compiler is one # of them. # 4. world stage [WMAKE] # This stage actually builds the world. # 5. install stage (optional) [IMAKE] # This stage installs a previously built world. # BOOTSTRAPPING?= 0 # Common environment for world related stages CROSSENV= MAKEOBJDIRPREFIX=${OBJTREE} \ MACHINE_ARCH=${TARGET_ARCH} \ MACHINE=${TARGET} \ CPUTYPE=${TARGET_CPUTYPE} .if ${MK_GROFF} != "no" CROSSENV+= GROFF_BIN_PATH=${WORLDTMP}/legacy/usr/bin \ GROFF_FONT_PATH=${WORLDTMP}/legacy/usr/share/groff_font \ GROFF_TMAC_PATH=${WORLDTMP}/legacy/usr/share/tmac .endif # bootstrap-tools stage BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${BPATH}:${PATH} \ WORLDTMP=${WORLDTMP} \ VERSION="${VERSION}" \ MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \ COMPILER_TYPE=${COMPILER_TYPE} BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT -DWITHOUT_MAN \ -DNO_PIC -DNO_PROFILE -DNO_SHARED \ -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF -DEARLY_BUILD # build-tools stage TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ -DNO_LINT \ -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF -DEARLY_BUILD # cross-tools stage XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ -DWITHOUT_GDB # world stage WMAKEENV= ${CROSSENV} \ _SHLIBDIRPREFIX=${WORLDTMP} \ _LDSCRIPTROOT= \ VERSION="${VERSION}" \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} .if ${MK_CDDL} == "no" WMAKEENV+= NO_CTF=1 .endif .if ${CC:T:Mgcc} == "gcc" WMAKE_COMPILER_TYPE= gcc .elif ${CC:T:Mclang} == "clang" WMAKE_COMPILER_TYPE= clang .elif ${MK_CLANG_IS_CC} == "no" WMAKE_COMPILER_TYPE= gcc .else WMAKE_COMPILER_TYPE= clang .endif WMAKEENV+= COMPILER_TYPE=${WMAKE_COMPILER_TYPE} WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP} .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64" # 32 bit world LIB32TMP= ${OBJTREE}${.CURDIR}/lib32 .if ${TARGET_ARCH} == "amd64" .if empty(TARGET_CPUTYPE) LIB32CPUFLAGS= -march=i686 -mmmx -msse -msse2 .else LIB32CPUFLAGS= -march=${TARGET_CPUTYPE} .endif LIB32WMAKEENV= MACHINE=i386 MACHINE_ARCH=i386 \ MACHINE_CPU="i686 mmx sse sse2" LIB32WMAKEFLAGS= \ AS="${AS} --32" \ LD="${LD} -m elf_i386_fbsd -Y P,${LIB32TMP}/usr/lib32" .elif ${TARGET_ARCH} == "powerpc64" .if empty(TARGET_CPUTYPE) LIB32CPUFLAGS= -mcpu=powerpc .else LIB32CPUFLAGS= -mcpu=${TARGET_CPUTYPE} .endif LIB32WMAKEENV= MACHINE=powerpc MACHINE_ARCH=powerpc LIB32WMAKEFLAGS= \ LD="${LD} -m elf32ppc_fbsd" .endif LIB32FLAGS= -m32 ${LIB32CPUFLAGS} -DCOMPAT_32BIT \ -isystem ${LIB32TMP}/usr/include/ \ -L${LIB32TMP}/usr/lib32 \ -B${LIB32TMP}/usr/lib32 # Yes, the flags are redundant. LIB32WMAKEENV+= MAKEOBJDIRPREFIX=${OBJTREE}/lib32 \ _SHLIBDIRPREFIX=${LIB32TMP} \ _LDSCRIPTROOT=${LIB32TMP} \ VERSION="${VERSION}" \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} \ LIBDIR=/usr/lib32 \ SHLIBDIR=/usr/lib32 \ COMPILER_TYPE=${WMAKE_COMPILER_TYPE} LIB32WMAKEFLAGS+= \ CC="${CC} ${LIB32FLAGS}" \ CXX="${CXX} ${LIB32FLAGS}" \ DESTDIR=${LIB32TMP} \ -DCOMPAT_32BIT \ -DLIBRARIES_ONLY \ -DNO_CPU_CFLAGS \ -DNO_CTF \ -DNO_LINT LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \ -DWITHOUT_BIND -DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS \ ${IMAKE_INSTALL} .endif IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*} IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \ ${IMAKE_INSTALL} ${IMAKE_MTREE} .if empty(.MAKEFLAGS:M-n) IMAKEENV+= PATH=${STRICTTMPPATH}:${INSTALLTMP} \ LD_LIBRARY_PATH=${INSTALLTMP} \ PATH_LOCALE=${INSTALLTMP}/locale IMAKE+= __MAKE_SHELL=${INSTALLTMP}/sh .else IMAKEENV+= PATH=${TMPPATH}:${INSTALLTMP} .endif .if defined(DB_FROM_SRC) INSTALLFLAGS+= -N ${.CURDIR}/etc MTREEFLAGS+= -N ${.CURDIR}/etc .endif .if defined(NO_ROOT) METALOG?= ${DESTDIR}/${DISTDIR}/METALOG IMAKE+= -DNO_ROOT METALOG=${METALOG} INSTALL_DDIR= ${DESTDIR}/${DISTDIR} INSTALLFLAGS+= -U -M ${METALOG} -D ${INSTALL_DDIR:S://:/:g:C:/$::} MTREEFLAGS+= -W .endif .if defined(DB_FROM_SRC) || defined(NO_ROOT) IMAKE_INSTALL= INSTALL="install ${INSTALLFLAGS}" IMAKE_MTREE= MTREE_CMD="nmtree ${MTREEFLAGS}" .endif # kernel stage KMAKEENV= ${WMAKEENV} KMAKE= ${KMAKEENV} ${MAKE} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME} # # buildworld # # Attempt to rebuild the entire system, with reasonable chance of # success, regardless of how old your existing system is. # _worldtmp: .if ${.CURDIR:C/[^,]//g} != "" # The m4 build of sendmail files doesn't like it if ',' is used # anywhere in the path of it's files. @echo @echo "*** Error: path to source tree contains a comma ','" @echo false .endif @echo @echo "--------------------------------------------------------------" @echo ">>> Rebuilding the temporary build tree" @echo "--------------------------------------------------------------" .if !defined(NO_CLEAN) rm -rf ${WORLDTMP} .if defined(LIB32TMP) rm -rf ${LIB32TMP} .endif .else rm -rf ${WORLDTMP}/legacy/usr/include # XXX - These three can depend on any header file. rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/ioctl.c rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/kdump_subr.c rm -f ${OBJTREE}${.CURDIR}/usr.bin/truss/ioctl.c .endif .for _dir in \ lib usr legacy/bin legacy/usr mkdir -p ${WORLDTMP}/${_dir} .endfor mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${WORLDTMP}/legacy/usr >/dev/null .if ${MK_GROFF} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.groff.dist \ -p ${WORLDTMP}/legacy/usr >/dev/null .endif mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${WORLDTMP}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${WORLDTMP}/usr/include >/dev/null ln -sf ${.CURDIR}/sys ${WORLDTMP} .if ${MK_BIND_LIBS} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BIND.include.dist \ -p ${WORLDTMP}/usr/include >/dev/null .endif .for _mtree in ${LOCAL_MTREE} mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null .endfor _legacy: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1.1: legacy release compatibility shims" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${BMAKE} legacy _bootstrap-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1.2: bootstrap tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${BMAKE} bootstrap-tools _cleanobj: .if !defined(NO_CLEAN) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.1: cleaning up the object tree" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} ${CLEANDIR:S/^/par-/} .if defined(LIB32TMP) ${_+_}cd ${.CURDIR}; ${LIB32WMAKE} -f Makefile.inc1 ${CLEANDIR:S/^/par-/} .endif .endif _obj: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.2: rebuilding the object tree" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-obj _build-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.3: build tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${TMAKE} build-tools _cross-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3: cross tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${XMAKE} cross-tools _includes: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.1: building includes" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks par-includes _libraries: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.2: building libraries" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; \ ${WMAKE} -DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \ -DWITHOUT_MAN -DNO_PROFILE libraries _depend: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.3: make dependencies" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-depend everything: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.4: building everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-all .if defined(LIB32TMP) build32: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 5.1: building 32 bit shim libraries" @echo "--------------------------------------------------------------" mkdir -p ${LIB32TMP}/usr/include mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${LIB32TMP}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${LIB32TMP}/usr/include >/dev/null mkdir -p ${WORLDTMP} ln -sf ${.CURDIR}/sys ${WORLDTMP} .for _t in obj includes cd ${.CURDIR}/include; ${LIB32WMAKE} DIRPRFX=include/ ${_t} cd ${.CURDIR}/lib; ${LIB32WMAKE} DIRPRFX=lib/ ${_t} .if ${MK_CDDL} != "no" cd ${.CURDIR}/cddl/lib; ${LIB32WMAKE} DIRPRFX=cddl/lib/ ${_t} .endif cd ${.CURDIR}/gnu/lib; ${LIB32WMAKE} DIRPRFX=gnu/lib/ ${_t} .if ${MK_CRYPT} != "no" cd ${.CURDIR}/secure/lib; ${LIB32WMAKE} DIRPRFX=secure/lib/ ${_t} .endif .if ${MK_KERBEROS} != "no" cd ${.CURDIR}/kerberos5/lib; ${LIB32WMAKE} DIRPRFX=kerberos5/lib ${_t} .endif .endfor .for _dir in usr.bin/lex/lib cd ${.CURDIR}/${_dir}; ${LIB32WMAKE} DIRPRFX=${_dir}/ obj .endfor .for _dir in lib/ncurses/ncurses lib/ncurses/ncursesw lib/libmagic cd ${.CURDIR}/${_dir}; \ WORLDTMP=${WORLDTMP} \ MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \ MAKEOBJDIRPREFIX=${OBJTREE}/lib32 ${MAKE} SSP_CFLAGS= DESTDIR= \ DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF \ -DEARLY_BUILD build-tools .endfor cd ${.CURDIR}; \ ${LIB32WMAKE} -f Makefile.inc1 libraries .for _t in obj depend all cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} \ DIRPRFX=libexec/rtld-elf/ ${_t} cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} \ DIRPRFX=usr.bin/ldd ${_t} .endfor distribute32 install32: cd ${.CURDIR}/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .if ${MK_CDDL} != "no" cd ${.CURDIR}/cddl/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif cd ${.CURDIR}/gnu/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .if ${MK_CRYPT} != "no" cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif .if ${MK_KERBEROS} != "no" cd ${.CURDIR}/kerberos5/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif cd ${.CURDIR}/libexec/rtld-elf; \ PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//} cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} ${.TARGET:S/32$//} .endif WMAKE_TGTS= .if !defined(SUBDIR_OVERRIDE) WMAKE_TGTS+= _worldtmp _legacy _bootstrap-tools .endif WMAKE_TGTS+= _cleanobj _obj _build-tools .if !defined(SUBDIR_OVERRIDE) WMAKE_TGTS+= _cross-tools .endif WMAKE_TGTS+= _includes _libraries _depend everything .if defined(LIB32TMP) && ${MK_LIB32} != "no" WMAKE_TGTS+= build32 .endif buildworld: buildworld_prologue ${WMAKE_TGTS} buildworld_epilogue .ORDER: buildworld_prologue ${WMAKE_TGTS} buildworld_epilogue buildworld_prologue: @echo "--------------------------------------------------------------" @echo ">>> World build started on `LC_ALL=C date`" @echo "--------------------------------------------------------------" buildworld_epilogue: @echo @echo "--------------------------------------------------------------" @echo ">>> World build completed on `LC_ALL=C date`" @echo "--------------------------------------------------------------" # # We need to have this as a target because the indirection between Makefile # and Makefile.inc1 causes the correct PATH to be used, rather than a # modification of the current environment's PATH. In addition, we need # to quote multiword values. # buildenvvars: @echo ${WMAKEENV:Q} buildenv: @echo Entering world for ${TARGET_ARCH}:${TARGET} @cd ${.CURDIR} && env ${WMAKEENV} ${BUILDENV_SHELL} || true TOOLCHAIN_TGTS= ${WMAKE_TGTS:N_depend:Neverything:Nbuild32} toolchain: ${TOOLCHAIN_TGTS} kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries} # # installcheck # # Checks to be sure system is ready for installworld/installkernel. # installcheck: # # Require DESTDIR to be set if installing for a different architecture or # using the user/group database in the source tree. # .if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE} || \ defined(DB_FROM_SRC) .if !make(distributeworld) installcheck: installcheck_DESTDIR installcheck_DESTDIR: .if !defined(DESTDIR) || empty(DESTDIR) @echo "ERROR: Please set DESTDIR!"; \ false .endif .endif .endif .if !defined(DB_FROM_SRC) # # Check for missing UIDs/GIDs. # CHECK_UIDS= auditdistd CHECK_GIDS= audit .if ${MK_SENDMAIL} != "no" CHECK_UIDS+= smmsp CHECK_GIDS+= smmsp .endif .if ${MK_PF} != "no" CHECK_UIDS+= proxy CHECK_GIDS+= proxy authpf .endif installcheck: installcheck_UGID installcheck_UGID: .for uid in ${CHECK_UIDS} @if ! `id -u ${uid} >/dev/null 2>&1`; then \ echo "ERROR: Required ${uid} user is missing, see /usr/src/UPDATING."; \ false; \ fi .endfor .for gid in ${CHECK_GIDS} @if ! `find / -prune -group ${gid} >/dev/null 2>&1`; then \ echo "ERROR: Required ${gid} group is missing, see /usr/src/UPDATING."; \ false; \ fi .endfor .endif # # Required install tools to be saved in a scratch dir for safety. # .if ${MK_INFO} != "no" _install-info= install-info .endif .if ${MK_ZONEINFO} != "no" _zoneinfo= zic tzsetup .endif ITOOLS= [ awk cap_mkdb cat chflags chmod chown \ date echo egrep find grep id install ${_install-info} \ ln lockf make mkdir mtree ${_nmtree_itools} mv pwd_mkdb \ rm sed sh sysctl test true uname wc ${_zoneinfo} # # distributeworld # # Distributes everything compiled by a `buildworld'. # # installworld # # Installs everything compiled by a 'buildworld'. # # Non-base distributions produced by the base system EXTRA_DISTRIBUTIONS= doc .if ${MK_GAMES} != "no" EXTRA_DISTRIBUTIONS+= games .endif .if defined(LIB32TMP) && ${MK_LIB32} != "no" EXTRA_DISTRIBUTIONS+= lib32 .endif MTREE_MAGIC?= mtree 2.0 distributeworld installworld: installcheck mkdir -p ${INSTALLTMP} progs=$$(for prog in ${ITOOLS}; do \ if progpath=`which $$prog`; then \ echo $$progpath; \ else \ echo "Required tool $$prog not found in PATH." >&2; \ exit 1; \ fi; \ done); \ libs=$$(ldd -f "%o %p\n" -f "%o %p\n" $$progs 2>/dev/null | sort -u | \ while read line; do \ set -- $$line; \ if [ "$$2 $$3" != "not found" ]; then \ echo $$2; \ else \ echo "Required library $$1 not found." >&2; \ exit 1; \ fi; \ done); \ cp $$libs $$progs ${INSTALLTMP} cp -R $${PATH_LOCALE:-"/usr/share/locale"} ${INSTALLTMP}/locale .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${METALOG} .endif .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} -mkdir ${DESTDIR}/${DISTDIR}/${dist} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \ -p ${DESTDIR}/${DISTDIR}/${dist} >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/include >/dev/null .if defined(NO_ROOT) ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \ sed -e 's#^\./#./${dist}/#' >> ${METALOG} ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \ sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG} ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \ sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG} .endif .endfor -mkdir ${DESTDIR}/${DISTDIR}/base cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ METALOG=${METALOG} ${IMAKE_INSTALL} ${IMAKE_MTREE} \ DISTBASE=/base DESTDIR=${DESTDIR}/${DISTDIR}/base \ LOCAL_MTREE=${LOCAL_MTREE} distrib-dirs .endif ${_+_}cd ${.CURDIR}; ${IMAKE} re${.TARGET:S/world$//}; \ ${IMAKEENV} rm -rf ${INSTALLTMP} .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} find ${DESTDIR}/${DISTDIR}/${dist} -empty -delete .endfor .if defined(NO_ROOT) .for dist in base ${EXTRA_DISTRIBUTIONS} @# For each file that exists in this dist, print the corresponding @# line from the METALOG. This relies on the fact that @# a line containing only the filename will sort immediatly before @# the relevant mtree line. cd ${DESTDIR}/${DISTDIR}; \ find ./${dist} | sort -u ${METALOG} - | \ awk 'BEGIN { print "#${MTREE_MAGIC}" } !/ type=/ { file = $$1 } / type=/ { if ($$1 == file) { sub(/^\.\/${dist}\//, "./"); print } }' > \ ${DESTDIR}/${DISTDIR}/${dist}.meta .endfor .endif .endif packageworld: .for dist in base ${EXTRA_DISTRIBUTIONS} .if defined(NO_ROOT) ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz \ @${DESTDIR}/${DISTDIR}/${dist}.meta .else ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz . .endif .endfor # # reinstall # # If you have a build server, you can NFS mount the source and obj directories # and do a 'make reinstall' on the *client* to install new binaries from the # most recent server build. # reinstall: @echo "--------------------------------------------------------------" @echo ">>> Making hierarchy" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 \ LOCAL_MTREE=${LOCAL_MTREE} hierarchy @echo @echo "--------------------------------------------------------------" @echo ">>> Installing everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install .if defined(LIB32TMP) && ${MK_LIB32} != "no" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install32 .endif redistribute: @echo "--------------------------------------------------------------" @echo ">>> Distributing everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute .if defined(LIB32TMP) && ${MK_LIB32} != "no" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute32 \ DISTRIBUTION=lib32 .endif distrib-dirs distribution: cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} # # buildkernel and installkernel # # Which kernels to build and/or install is specified by setting # KERNCONF. If not defined a GENERIC kernel is built/installed. # Only the existing (depending TARGET) config files are used # for building kernels and only the first of these is designated # as the one being installed. # # Note that we have to use TARGET instead of TARGET_ARCH when # we're in kernel-land. Since only TARGET_ARCH is (expected) to # be set to cross-build, we have to make sure TARGET is set # properly. .if defined(KERNFAST) NO_KERNELCLEAN= t NO_KERNELCONFIG= t NO_KERNELDEPEND= t NO_KERNELOBJ= t # Shortcut for KERNCONF=Blah -DKERNFAST is now KERNFAST=Blah .if !defined(KERNCONF) && ${KERNFAST} != "1" KERNCONF=${KERNFAST} .endif .endif .if !defined(KERNCONF) && defined(KERNEL) KERNCONF= ${KERNEL} KERNWARN= .else .if ${TARGET_ARCH} == "powerpc64" KERNCONF?= GENERIC64 .else KERNCONF?= GENERIC .endif .endif INSTKERNNAME?= kernel KERNSRCDIR?= ${.CURDIR}/sys KRNLCONFDIR= ${KERNSRCDIR}/${TARGET}/conf KRNLOBJDIR= ${OBJTREE}${KERNSRCDIR} KERNCONFDIR?= ${KRNLCONFDIR} BUILDKERNELS= INSTALLKERNEL= .for _kernel in ${KERNCONF} .if exists(${KERNCONFDIR}/${_kernel}) BUILDKERNELS+= ${_kernel} .if empty(INSTALLKERNEL) INSTALLKERNEL= ${_kernel} .endif .endif .endfor # # buildkernel # # Builds all kernels defined by BUILDKERNELS. # buildkernel: .if empty(BUILDKERNELS) @echo "ERROR: Missing kernel configuration file(s) (${KERNCONF})."; \ false .endif .if defined(KERNWARN) @echo "--------------------------------------------------------------" @echo ">>> WARNING: KERNEL= setting should be changed to KERNCONF=" @echo "--------------------------------------------------------------" @sleep 3 .endif @echo .for _kernel in ${BUILDKERNELS} @echo "--------------------------------------------------------------" @echo ">>> Kernel build for ${_kernel} started on `LC_ALL=C date`" @echo "--------------------------------------------------------------" @echo "===> ${_kernel}" mkdir -p ${KRNLOBJDIR} .if !defined(NO_KERNELCONFIG) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1: configuring the kernel" @echo "--------------------------------------------------------------" cd ${KRNLCONFDIR}; \ PATH=${TMPPATH} \ config ${CONFIGARGS} -d ${KRNLOBJDIR}/${_kernel} \ ${KERNCONFDIR}/${_kernel} .endif .if !defined(NO_CLEAN) && !defined(NO_KERNELCLEAN) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.1: cleaning up the object tree" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} ${CLEANDIR} .endif .if !defined(NO_KERNELOBJ) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.2: rebuilding the object tree" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} obj .endif @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.3: build tools" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; \ PATH=${BPATH}:${PATH} \ MAKESRCPATH=${KERNSRCDIR}/dev/aic7xxx/aicasm \ ${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS -DNO_CTF -DEARLY_BUILD \ -f ${KERNSRCDIR}/dev/aic7xxx/aicasm/Makefile # XXX - Gratuitously builds aicasm in the ``makeoptions NO_MODULES'' case. .if !defined(MODULES_WITH_WORLD) && !defined(NO_MODULES) && exists(${KERNSRCDIR}/modules) .for target in obj depend all cd ${KERNSRCDIR}/modules/aic7xxx/aicasm; \ PATH=${BPATH}:${PATH} \ MAKEOBJDIRPREFIX=${KRNLOBJDIR}/${_kernel}/modules \ ${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS -DNO_CTF -DEARLY_BUILD ${target} .endfor .endif .if !defined(NO_KERNELDEPEND) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3.1: making dependencies" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} depend -DNO_MODULES_OBJ .endif @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3.2: building everything" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} all -DNO_MODULES_OBJ @echo "--------------------------------------------------------------" @echo ">>> Kernel build for ${_kernel} completed on `LC_ALL=C date`" @echo "--------------------------------------------------------------" .endfor # # installkernel, etc. # # Install the kernel defined by INSTALLKERNEL # installkernel installkernel.debug \ reinstallkernel reinstallkernel.debug: installcheck .if empty(INSTALLKERNEL) @echo "ERROR: No kernel \"${KERNCONF}\" to install."; \ false .endif @echo "--------------------------------------------------------------" @echo ">>> Installing kernel ${INSTALLKERNEL}" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \ ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} ${IMAKE_INSTALL} KERNEL=${INSTKERNNAME} ${.TARGET:S/kernel//} distributekernel distributekernel.debug: .if empty(INSTALLKERNEL) @echo "ERROR: No kernel \"${KERNCONF}\" to install."; \ false .endif cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \ ${CROSSENV} PATH=${TMPPATH} ${MAKE} KERNEL=${INSTKERNNAME} \ DESTDIR=${DESTDIR}/${DISTDIR}/kernel \ ${.TARGET:S/distributekernel/install/} .for _kernel in ${BUILDKERNELS:S/${INSTALLKERNEL}//} cd ${KRNLOBJDIR}/${_kernel}; \ ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ KERNEL=${INSTKERNNAME}.${_kernel} \ DESTDIR=${DESTDIR}/${DISTDIR}/kernel.${_kernel} \ ${.TARGET:S/distributekernel/install/} .endfor packagekernel: cd ${DESTDIR}/${DISTDIR}/kernel; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.txz . .for _kernel in ${BUILDKERNELS:S/${INSTALLKERNEL}//} cd ${DESTDIR}/${DISTDIR}/kernel.${_kernel}; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.txz . .endfor # # doxygen # # Build the API documentation with doxygen # doxygen: @if [ ! -x `/usr/bin/which doxygen` ]; then \ echo "You need doxygen (devel/doxygen) to generate the API documentation of the kernel." | /usr/bin/fmt; \ exit 1; \ fi cd ${.CURDIR}/tools/kerneldoc/subsys && ${MAKE} obj all # # update # # Update the source tree(s), by running cvsup/cvs/svn to update to the # latest copy. # update: .if defined(SUP_UPDATE) @echo "--------------------------------------------------------------" @echo ">>> Running ${SUP}" @echo "--------------------------------------------------------------" @echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" @echo "!! Update methods with ${SUP} are deprecated." @echo "!! Please see http://www.freebsd.org/handbook/svn.html" @echo "!! and convert your update method to SVN_UPDATE or" @echo "!! freebsd-update(8)." @echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" @sleep 5 .if defined(SUPFILE) @${SUP} ${SUPFLAGS} ${SUPFILE} .endif .if defined(SUPFILE1) @${SUP} ${SUPFLAGS} ${SUPFILE1} .endif .if defined(SUPFILE2) @${SUP} ${SUPFLAGS} ${SUPFILE2} .endif .if defined(PORTSSUPFILE) && !defined(NO_PORTSUPDATE) @${SUP} ${SUPFLAGS} ${PORTSSUPFILE} .endif .if defined(DOCSUPFILE) && !defined(NO_DOCUPDATE) @${SUP} ${SUPFLAGS} ${DOCSUPFILE} .endif .endif .if defined(CVS_UPDATE) @cd ${.CURDIR} ; \ if [ -d CVS ] ; then \ echo "--------------------------------------------------------------" ; \ echo ">>> Updating ${.CURDIR} from CVS repository" ${CVSROOT} ; \ echo "--------------------------------------------------------------" ; \ echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" ; \ echo "!! Update methods with CVS are deprecated." ; \ echo "!! Please see http://www.freebsd.org/handbook/svn.html" ; \ echo "!! and convert your update method to SVN_UPDATE or" ; \ echo "!! freebsd-update(8)." ; \ echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" ; \ sleep 5 ; \ echo ${CVS} -R -q update ${CVSFLAGS} ; \ ${CVS} -R -q update ${CVSFLAGS} ; \ fi .endif .if defined(SVN_UPDATE) @cd ${.CURDIR} ; \ if [ -d .svn ] ; then \ echo "--------------------------------------------------------------" ; \ echo ">>> Updating ${.CURDIR} using Subversion" ; \ echo "--------------------------------------------------------------" ; \ echo ${SVN} update ${SVNFLAGS} ; \ ${SVN} update ${SVNFLAGS} ; \ fi .endif # # ------------------------------------------------------------------------ # # From here onwards are utility targets used by the 'make world' and # related targets. If your 'world' breaks, you may like to try to fix # the problem and manually run the following targets to attempt to # complete the build. Beware, this is *not* guaranteed to work, you # need to have a pretty good grip on the current state of the system # to attempt to manually finish it. If in doubt, 'make world' again. # # # legacy: Build compatibility shims for the next three targets # legacy: .if ${BOOTSTRAPPING} < 700055 && ${BOOTSTRAPPING} != 0 @echo "ERROR: Source upgrades from versions prior to 7.0 not supported."; \ false .endif .for _tool in tools/build ${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,depend,all,install)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy includes; \ ${MAKE} DIRPRFX=${_tool}/ depend; \ ${MAKE} DIRPRFX=${_tool}/ all; \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install .endfor # # bootstrap-tools: Build tools needed for compatibility # .if ${MK_GAMES} != "no" _strfile= games/fortune/strfile .endif .if ${MK_CXX} != "no" _gperf= gnu/usr.bin/gperf .endif .if ${MK_GROFF} != "no" _groff= gnu/usr.bin/groff .endif .if ${BOOTSTRAPPING} < 800022 _ar= usr.bin/ar .endif .if ${BOOTSTRAPPING} < 800013 _mklocale= usr.bin/mklocale .endif .if ${BOOTSTRAPPING} < 900002 _sed= usr.bin/sed .endif .if ${BOOTSTRAPPING} < 900006 _lex= usr.bin/lex .endif .if ${BOOTSTRAPPING} < 1000013 _yacc= usr.bin/yacc .endif .if ${BOOTSTRAPPING} < 1000026 _nmtree= lib/libnetbsd \ usr.sbin/nmtree .else _nmtree_itools= nmtree .endif .if ${BOOTSTRAPPING} < 1000027 _cat= bin/cat .endif .if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 _awk= usr.bin/awk .endif .if ${MK_BSNMP} != "no" && !exists(/usr/sbin/gensnmptree) _gensnmptree= usr.sbin/bsnmpd/gensnmptree .endif .if ${MK_CLANG} != "no" _clang_tblgen= \ lib/clang/libllvmsupport \ lib/clang/libllvmtablegen \ usr.bin/clang/tblgen \ usr.bin/clang/clang-tblgen .endif # dtrace tools are required for older bootstrap env and cross-build .if ${MK_CDDL} != "no" && \ ((${BOOTSTRAPPING} < 800038 && \ !(${BOOTSTRAPPING} >= 700112 && ${BOOTSTRAPPING} < 799999)) \ || (${MACHINE} != ${TARGET} || ${MACHINE_ARCH} != ${TARGET_ARCH})) _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \ lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge .endif # Default to building the BSDL DTC, but build the GPL one if users explicitly # request it. _dtc= usr.bin/dtc .if ${MK_GPL_DTC} != "no" _dtc= gnu/usr.bin/dtc .endif .if ${MK_KERBEROS} != "no" _kerberos5_bootstrap_tools= \ kerberos5/tools/make-roken \ kerberos5/lib/libroken \ kerberos5/lib/libvers \ kerberos5/tools/asn1_compile \ kerberos5/tools/slc .endif # Please document (add comment) why something is in 'bootstrap-tools'. # Try to bound the building of the bootstrap-tool to just the # FreeBSD versions that need the tool built at this stage of the build. bootstrap-tools: .for _tool in \ ${_clang_tblgen} \ ${_kerberos5_bootstrap_tools} \ ${_dtrace_tools} \ ${_strfile} \ ${_gperf} \ ${_groff} \ ${_ar} \ ${_dtc} \ ${_awk} \ ${_cat} \ usr.bin/lorder \ usr.bin/makewhatis \ ${_mklocale} \ usr.bin/rpcgen \ ${_sed} \ ${_yacc} \ ${_lex} \ usr.bin/xinstall \ ${_gensnmptree} \ usr.sbin/config \ ${_nmtree} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ ${MAKE} DIRPRFX=${_tool}/ depend; \ ${MAKE} DIRPRFX=${_tool}/ all; \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install .endfor # # build-tools: Build special purpose build tools # .if defined(MODULES_WITH_WORLD) && exists(${KERNSRCDIR}/modules) _aicasm= sys/modules/aic7xxx/aicasm .endif .if !defined(NO_SHARE) _share= share/syscons/scrnmaps .endif .if ${MK_GCC} != "no" _gcc_tools= gnu/usr.bin/cc/cc_tools .endif .if ${MK_RESCUE} != "no" _rescue= rescue/rescue .endif build-tools: .for _tool in \ bin/csh \ bin/sh \ ${_rescue} \ ${LOCAL_TOOL_DIRS} \ lib/ncurses/ncurses \ lib/ncurses/ncursesw \ ${_share} \ ${_aicasm} \ usr.bin/awk \ lib/libmagic \ usr.bin/mkesdb_static \ usr.bin/mkcsmapper_static ${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ ${MAKE} DIRPRFX=${_tool}/ build-tools .endfor .for _tool in \ ${_gcc_tools} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ ${MAKE} DIRPRFX=${_tool}/ depend; \ ${MAKE} DIRPRFX=${_tool}/ all .endfor # # cross-tools: Build cross-building tools # .if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 800035 .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386" _btxld= usr.sbin/btxld .endif .endif .if ${TARGET_ARCH} != ${MACHINE_ARCH} .if ${MK_RESCUE} != "no" || defined(RELEASEDIR) _crunchide= usr.sbin/crunch/crunchide .endif .if ${TARGET_ARCH} == "i386" && defined(RELEASEDIR) _kgzip= usr.sbin/kgzip .endif .endif .if ${MK_BINUTILS} != "no" _binutils= gnu/usr.bin/binutils .endif .if ${MK_CLANG} != "no" && (${MK_CLANG_IS_CC} != "no" || ${CC:T:Mclang} == "clang") _clang= usr.bin/clang _clang_libs= lib/clang .endif .if ${MK_GCC} != "no" && (${MK_CLANG_IS_CC} == "no" || ${TARGET} == "pc98") _cc= gnu/usr.bin/cc .endif cross-tools: .for _tool in \ ${_clang_libs} \ ${_clang} \ ${_binutils} \ ${_cc} \ usr.bin/xlint/lint1 usr.bin/xlint/lint2 usr.bin/xlint/xlint \ ${_btxld} \ ${_crunchide} \ ${_kgzip} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool}; \ ${MAKE} DIRPRFX=${_tool}/ obj; \ ${MAKE} DIRPRFX=${_tool}/ depend; \ ${MAKE} DIRPRFX=${_tool}/ all; \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install .endfor # # hierarchy - ensure that all the needed directories are present # hierarchy hier: .if defined(NO_ROOT) cd ${.CURDIR}/etc; ${MAKE} LOCAL_MTREE=${LOCAL_MTREE} \ -DNO_ROOT METALOG=${METALOG} distrib-dirs .else cd ${.CURDIR}/etc; ${MAKE} LOCAL_MTREE=${LOCAL_MTREE} distrib-dirs .endif # # libraries - build all libraries, and install them under ${DESTDIR}. # # The list of libraries with dependents (${_prebuild_libs}) and their # interdependencies (__L) are built automatically by the # ${.CURDIR}/tools/make_libdeps.sh script. # libraries: cd ${.CURDIR}; \ ${MAKE} -f Makefile.inc1 _prereq_libs; \ ${MAKE} -f Makefile.inc1 _startup_libs; \ ${MAKE} -f Makefile.inc1 _prebuild_libs; \ ${MAKE} -f Makefile.inc1 _generic_libs; # # static libgcc.a prerequisite for shared libc # _prereq_libs= gnu/lib/libssp/libssp_nonshared gnu/lib/libgcc lib/libcompiler_rt # These dependencies are not automatically generated: # # gnu/lib/csu, gnu/lib/libgcc, lib/csu and lib/libc must be built before # all shared libraries for ELF. # _startup_libs= gnu/lib/csu .if exists(${.CURDIR}/lib/csu/${MACHINE_ARCH}-elf) _startup_libs+= lib/csu/${MACHINE_ARCH}-elf .elif exists(${.CURDIR}/lib/csu/${MACHINE_ARCH}) _startup_libs+= lib/csu/${MACHINE_ARCH} .else _startup_libs+= lib/csu/${MACHINE_CPUARCH} .endif _startup_libs+= gnu/lib/libgcc _startup_libs+= lib/libcompiler_rt _startup_libs+= lib/libc .if ${MK_LIBCPLUSPLUS} != "no" _startup_libs+= lib/libcxxrt .endif gnu/lib/libgcc__L: lib/libc__L .if ${MK_LIBCPLUSPLUS} != "no" lib/libcxxrt__L: gnu/lib/libgcc__L .endif _prebuild_libs= ${_kerberos5_lib_libasn1} \ ${_kerberos5_lib_libhdb} \ ${_kerberos5_lib_libheimbase} \ ${_kerberos5_lib_libheimntlm} \ ${_kerberos5_lib_libheimsqlite} \ ${_kerberos5_lib_libheimipcc} \ ${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \ ${_kerberos5_lib_libroken} \ ${_kerberos5_lib_libwind} \ ${_lib_atf_libatf_c} \ lib/libbz2 ${_libcom_err} lib/libcrypt \ lib/libexpat \ ${_lib_libgssapi} ${_lib_libipx} \ lib/libkiconv lib/libkvm lib/liblzma lib/libmd \ lib/ncurses/ncurses lib/ncurses/ncursesw \ lib/libopie lib/libpam ${_lib_libthr} \ lib/libradius lib/libsbuf lib/libtacplus \ ${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \ lib/libutil ${_lib_libypclnt} lib/libz lib/msun \ ${_secure_lib_libcrypto} ${_secure_lib_libssh} \ ${_secure_lib_libssl} .if ${MK_ATF} != "no" _lib_atf_libatf_c= lib/atf/libatf-c .endif .if ${MK_LIBTHR} != "no" _lib_libthr= lib/libthr .endif .if ${MK_OFED} != "no" _ofed_lib= contrib/ofed/usr.lib/ .endif _generic_libs= ${_cddl_lib} gnu/lib ${_kerberos5_lib} lib ${_secure_lib} usr.bin/lex/lib ${_ofed_lib} .for _DIR in ${LOCAL_LIB_DIRS} .if exists(${.CURDIR}/${_DIR}/Makefile) _generic_libs+= ${_DIR} .endif .endfor lib/libopie__L lib/libtacplus__L: lib/libmd__L .if ${MK_CDDL} != "no" _cddl_lib_libumem= cddl/lib/libumem _cddl_lib_libnvpair= cddl/lib/libnvpair _cddl_lib= cddl/lib .endif .if ${MK_CRYPT} != "no" .if ${MK_OPENSSL} != "no" _secure_lib_libcrypto= secure/lib/libcrypto _secure_lib_libssl= secure/lib/libssl lib/libradius__L secure/lib/libssl__L: secure/lib/libcrypto__L .if ${MK_OPENSSH} != "no" _secure_lib_libssh= secure/lib/libssh secure/lib/libssh__L: lib/libz__L secure/lib/libcrypto__L lib/libcrypt__L .if ${MK_KERBEROS_SUPPORT} != "no" secure/lib/libssh__L: lib/libgssapi__L kerberos5/lib/libkrb5__L \ kerberos5/lib/libhx509__L kerberos5/lib/libasn1__L lib/libcom_err__L \ lib/libmd__L kerberos5/lib/libroken__L .endif .endif .endif _secure_lib= secure/lib .endif .if ${MK_KERBEROS} != "no" kerberos5/lib/libasn1__L: lib/libcom_err__L kerberos5/lib/libroken__L kerberos5/lib/libhdb__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ kerberos5/lib/libkrb5__L kerberos5/lib/libroken__L \ kerberos5/lib/libwind__L kerberos5/lib/libheimsqlite__L kerberos5/lib/libheimntlm__L: secure/lib/libcrypto__L kerberos5/lib/libkrb5__L \ kerberos5/lib/libroken__L lib/libcom_err__L kerberos5/lib/libhx509__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ secure/lib/libcrypto__L kerberos5/lib/libroken__L kerberos5/lib/libwind__L kerberos5/lib/libkrb5__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ lib/libcrypt__L secure/lib/libcrypto__L kerberos5/lib/libhx509__L \ kerberos5/lib/libroken__L kerberos5/lib/libwind__L \ kerberos5/lib/libheimbase__L kerberos5/lib/libheimipcc__L kerberos5/lib/libroken__L: lib/libcrypt__L kerberos5/lib/libwind__L: kerberos5/lib/libroken__L lib/libcom_err__L kerberos5/lib/libheimbase__L: lib/libthr__L kerberos5/lib/libheimipcc__L: kerberos5/lib/libroken__L kerberos5/lib/libheimbase__L lib/libthr__L kerberos5/lib/libheimsqlite__L: lib/libthr__L .endif .if ${MK_GSSAPI} != "no" _lib_libgssapi= lib/libgssapi .endif .if ${MK_IPX} != "no" _lib_libipx= lib/libipx .endif .if ${MK_KERBEROS} != "no" _kerberos5_lib= kerberos5/lib _kerberos5_lib_libasn1= kerberos5/lib/libasn1 _kerberos5_lib_libhdb= kerberos5/lib/libhdb _kerberos5_lib_libheimbase= kerberos5/lib/libheimbase _kerberos5_lib_libkrb5= kerberos5/lib/libkrb5 _kerberos5_lib_libhx509= kerberos5/lib/libhx509 _kerberos5_lib_libroken= kerberos5/lib/libroken _kerberos5_lib_libheimntlm= kerberos5/lib/libheimntlm _kerberos5_lib_libheimsqlite= kerberos5/lib/libheimsqlite _kerberos5_lib_libheimipcc= kerberos5/lib/libheimipcc _kerberos5_lib_libwind= kerberos5/lib/libwind _libcom_err= lib/libcom_err .endif .if ${MK_NIS} != "no" _lib_libypclnt= lib/libypclnt .endif .if ${MK_OPENSSL} == "no" lib/libradius__L: lib/libmd__L .endif .for _lib in ${_prereq_libs} ${_lib}__PL: .PHONY .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib}; \ ${MAKE} DIRPRFX=${_lib}/ obj; \ ${MAKE} DIRPRFX=${_lib}/ depend; \ ${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ all; \ ${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ install .endif .endfor .for _lib in ${_startup_libs} ${_prebuild_libs:Nlib/libpam} ${_generic_libs} ${_lib}__L: .PHONY .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib}; \ ${MAKE} DIRPRFX=${_lib}/ obj; \ ${MAKE} DIRPRFX=${_lib}/ depend; \ ${MAKE} DIRPRFX=${_lib}/ all; \ ${MAKE} DIRPRFX=${_lib}/ install .endif .endfor # libpam is special: we need to build static PAM modules before # static PAM library, and dynamic PAM library before dynamic PAM # modules. lib/libpam__L: .PHONY ${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \ cd ${.CURDIR}/lib/libpam; \ ${MAKE} DIRPRFX=lib/libpam/ obj; \ ${MAKE} DIRPRFX=lib/libpam/ depend; \ ${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET all; \ ${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET install _prereq_libs: ${_prereq_libs:S/$/__PL/} _startup_libs: ${_startup_libs:S/$/__L/} _prebuild_libs: ${_prebuild_libs:S/$/__L/} _generic_libs: ${_generic_libs:S/$/__L/} .for __target in all clean cleandepend cleandir depend includes obj .for entry in ${SUBDIR} ${entry}.${__target}__D: .PHONY ${_+_}@if test -d ${.CURDIR}/${entry}.${MACHINE_ARCH}; then \ ${ECHODIR} "===> ${DIRPRFX}${entry}.${MACHINE_ARCH} (${__target})"; \ edir=${entry}.${MACHINE_ARCH}; \ cd ${.CURDIR}/$${edir}; \ else \ ${ECHODIR} "===> ${DIRPRFX}${entry} (${__target})"; \ edir=${entry}; \ cd ${.CURDIR}/$${edir}; \ fi; \ ${MAKE} ${__target} DIRPRFX=${DIRPRFX}$${edir}/ .endfor par-${__target}: ${SUBDIR:S/$/.${__target}__D/} .endfor .include .if make(check-old) || make(check-old-dirs) || \ make(check-old-files) || make(check-old-libs) || \ make(delete-old) || make(delete-old-dirs) || \ make(delete-old-files) || make(delete-old-libs) # # check for / delete old files section # .include "ObsoleteFiles.inc" OLD_LIBS_MESSAGE="Please be sure no application still uses those libraries, \ else you can not start such an application. Consult UPDATING for more \ information regarding how to cope with the removal/revision bump of a \ specific library." .if !defined(BATCH_DELETE_OLD_FILES) RM_I=-i .else RM_I=-v .endif delete-old-files: @echo ">>> Removing old files (only deletes safe to delete libs)" # Ask for every old file if the user really wants to remove it. # It's annoying, but better safe than sorry. # NB: We cannot pass the list of OLD_FILES as a parameter because the # argument list will get too long. Using .for/.endfor make "loops" will make # the Makefile parser segfault. @exec 3<&0; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \ rm ${RM_I} "${DESTDIR}/$${file}" <&3; \ fi; \ done # Remove catpages without corresponding manpages. @exec 3<&0; \ find ${DESTDIR}/usr/share/man/cat* ! -type d | \ sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \ while read catpage; do \ read manpage; \ if [ ! -e "$${manpage}" ]; then \ rm ${RM_I} $${catpage} <&3; \ fi; \ done @echo ">>> Old files removed" check-old-files: @echo ">>> Checking for old files" @${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ echo "${DESTDIR}/$${file}"; \ fi; \ done # Check for catpages without corresponding manpages. @find ${DESTDIR}/usr/share/man/cat* ! -type d | \ sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \ while read catpage; do \ read manpage; \ if [ ! -e "$${manpage}" ]; then \ echo $${catpage}; \ fi; \ done delete-old-libs: @echo ">>> Removing old libraries" @echo "${OLD_LIBS_MESSAGE}" | fmt @exec 3<&0; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_LIBS | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \ rm ${RM_I} "${DESTDIR}/$${file}" <&3; \ fi; \ done @echo ">>> Old libraries removed" check-old-libs: @echo ">>> Checking for old libraries" @${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_LIBS | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ echo "${DESTDIR}/$${file}"; \ fi; \ done delete-old-dirs: @echo ">>> Removing old directories" @${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_DIRS | xargs -n1 | \ while read dir; do \ if [ -d "${DESTDIR}/$${dir}" ]; then \ rmdir -v "${DESTDIR}/$${dir}" || true; \ elif [ -L "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir} is a link, please remove everything manually."; \ fi; \ done @echo ">>> Old directories removed" check-old-dirs: @echo ">>> Checking for old directories" @${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_DIRS | xargs -n1 | \ while read dir; do \ if [ -d "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir}"; \ elif [ -L "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir} is a link, please remove everything manually."; \ fi; \ done delete-old: delete-old-files delete-old-dirs @echo "To remove old libraries run '${MAKE} delete-old-libs'." check-old: check-old-files check-old-libs check-old-dirs @echo "To remove old files and directories run '${MAKE} delete-old'." @echo "To remove old libraries run '${MAKE} delete-old-libs'." .endif # # showconfig - show build configuration. # showconfig: @${MAKE} -n -f bsd.own.mk -V dummy -dg1 2>&1 | grep ^MK_ | sort .if !empty(KRNLOBJDIR) && !empty(KERNCONF) DTBOUTPUTPATH= ${KRNLOBJDIR}/${KERNCONF}/ .if !defined(FDT_DTS_FILE) || empty(FDT_DTS_FILE) .if exists(${KERNCONFDIR}/${KERNCONF}) FDT_DTS_FILE!= awk 'BEGIN {FS="="} /^makeoptions[[:space:]]+FDT_DTS_FILE/ {print $$2}' \ ${KERNCONFDIR}/${KERNCONF} ; echo .endif .endif .endif .if !defined(DTBOUTPUTPATH) || !exists(${DTBOUTPUTPATH}) DTBOUTPUTPATH= ${.CURDIR} .endif # # Build 'standalone' Device Tree Blob # builddtb: @if [ "${FDT_DTS_FILE}" = "" ]; then \ echo "ERROR: FDT_DTS_FILE must be specified!"; \ exit 1; \ fi; \ if [ ! -f ${.CURDIR}/sys/boot/fdt/dts/${FDT_DTS_FILE} ]; then \ echo "ERROR: Specified DTS file (${FDT_DTS_FILE}) does not \ exist!"; \ exit 1; \ fi; \ if [ "${DTBOUTPUTPATH}" = "${.CURDIR}" ]; then \ echo "WARNING: DTB will be placed in the current working \ directory"; \ fi @PATH=${TMPPATH} \ dtc -O dtb -o \ ${DTBOUTPUTPATH}/`echo ${FDT_DTS_FILE} | cut -d. -f1`.dtb -b 0 \ -p 1024 ${.CURDIR}/sys/boot/fdt/dts/${FDT_DTS_FILE} ############### .if defined(XDEV) && defined(XDEV_ARCH) .if ${XDEV} == ${MACHINE} && ${XDEV_ARCH} == ${MACHINE_ARCH} XDEV_CPUTYPE?=${CPUTYPE} .else XDEV_CPUTYPE?=${TARGET_CPUTYPE} .endif NOFUN=-DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \ -DWITHOUT_MAN -DWITHOUT_NLS -DNO_PROFILE \ -DWITHOUT_KERBEROS -DWITHOUT_RESCUE -DNO_WARNS \ TARGET=${XDEV} TARGET_ARCH=${XDEV_ARCH} \ CPUTYPE=${XDEV_CPUTYPE} XDDIR=${XDEV_ARCH}-freebsd XDTP=/usr/${XDDIR} -CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} +CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \ + INSTALL="sh ${.CURDIR}/tools/install.sh" CDENV= ${CDBENV} \ _SHLIBDIRPREFIX=${XDTP} \ TOOLS_PREFIX=${XDTP} CD2ENV=${CDENV} \ MACHINE=${XDEV} MACHINE_ARCH=${XDEV_ARCH} CDTMP= ${MAKEOBJDIRPREFIX}/${XDEV}/${.CURDIR}/tmp CDMAKE=${CDENV} ${MAKE} ${NOFUN} CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDTP}/usr/bin:${PATH} ${MAKE} ${NOFUN} XDDESTDIR=${DESTDIR}${XDTP} .if !defined(OSREL) OSREL!= uname -r | sed -e 's/[-(].*//' .endif .ORDER: xdev-build xdev-install xdev: xdev-build xdev-install .ORDER: _xb-build-tools _xb-cross-tools xdev-build: _xb-build-tools _xb-cross-tools _xb-build-tools: ${_+_}@cd ${.CURDIR}; \ ${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools _xb-cross-tools: .for _tool in \ gnu/usr.bin/binutils \ gnu/usr.bin/cc \ usr.bin/ar ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool}; \ ${CDMAKE} DIRPRFX=${_tool}/ obj; \ ${CDMAKE} DIRPRFX=${_tool}/ depend; \ ${CDMAKE} DIRPRFX=${_tool}/ all .endfor _xi-mtree: ${_+_}@${ECHODIR} "mtree populating ${XDDESTDIR}" mkdir -p ${XDDESTDIR} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \ -p ${XDDESTDIR} >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${XDDESTDIR}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${XDDESTDIR}/usr/include >/dev/null .ORDER: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-links xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-links _xi-cross-tools: @echo "_xi-cross-tools" .for _tool in \ gnu/usr.bin/binutils \ gnu/usr.bin/cc \ usr.bin/ar ${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \ cd ${.CURDIR}/${_tool}; \ ${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR} .endfor _xi-includes: ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 par-includes \ DESTDIR=${XDDESTDIR} _xi-libraries: ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 libraries \ DESTDIR=${XDDESTDIR} _xi-links: ${_+_}cd ${XDDESTDIR}/usr/bin; \ for i in *; do \ ln -sf ../../${XDTP}/usr/bin/$$i \ ../../../../usr/bin/${XDDIR}-$$i; \ ln -sf ../../${XDTP}/usr/bin/$$i \ ../../../../usr/bin/${XDDIR}${OSREL}-$$i; \ done .else xdev xdev-buil xdev-install: @echo "*** Error: Both XDEV and XDEV_ARCH must be defined for \"${.TARGET}\" target" .endif Index: user/attilio/vmc-playground/contrib/binutils/include/elf/common.h =================================================================== --- user/attilio/vmc-playground/contrib/binutils/include/elf/common.h (revision 246333) +++ user/attilio/vmc-playground/contrib/binutils/include/elf/common.h (revision 246334) @@ -1,778 +1,782 @@ /* ELF support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published in "UNIX System V Release 4, Programmers Guide: ANSI C and Programming Support Tools". This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file is part of ELF support for BFD, and contains the portions that are common to both the internal and external representations. For example, ELFMAG0 is the byte 0x7F in both the internal (in-memory) and external (in-file) representations. */ #ifndef _ELF_COMMON_H #define _ELF_COMMON_H /* Fields in e_ident[]. */ #define EI_MAG0 0 /* File identification byte 0 index */ #define ELFMAG0 0x7F /* Magic number byte 0 */ #define EI_MAG1 1 /* File identification byte 1 index */ #define ELFMAG1 'E' /* Magic number byte 1 */ #define EI_MAG2 2 /* File identification byte 2 index */ #define ELFMAG2 'L' /* Magic number byte 2 */ #define EI_MAG3 3 /* File identification byte 3 index */ #define ELFMAG3 'F' /* Magic number byte 3 */ #define EI_CLASS 4 /* File class */ #define ELFCLASSNONE 0 /* Invalid class */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encoding */ #define ELFDATANONE 0 /* Invalid data encoding */ #define ELFDATA2LSB 1 /* 2's complement, little endian */ #define ELFDATA2MSB 2 /* 2's complement, big endian */ #define EI_VERSION 6 /* File version */ #define EI_OSABI 7 /* Operating System/ABI indication */ #define ELFOSABI_NONE 0 /* UNIX System V ABI */ #define ELFOSABI_HPUX 1 /* HP-UX operating system */ #define ELFOSABI_NETBSD 2 /* NetBSD */ #define ELFOSABI_LINUX 3 /* GNU/Linux */ #define ELFOSABI_HURD 4 /* GNU/Hurd */ #define ELFOSABI_SOLARIS 6 /* Solaris */ #define ELFOSABI_AIX 7 /* AIX */ #define ELFOSABI_IRIX 8 /* IRIX */ #define ELFOSABI_FREEBSD 9 /* FreeBSD */ #define ELFOSABI_TRU64 10 /* TRU64 UNIX */ #define ELFOSABI_MODESTO 11 /* Novell Modesto */ #define ELFOSABI_OPENBSD 12 /* OpenBSD */ #define ELFOSABI_OPENVMS 13 /* OpenVMS */ #define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ #define EI_ABIVERSION 8 /* ABI version */ #define EI_PAD 9 /* Start of padding bytes */ /* Values for e_type, which identifies the object file type. */ #define ET_NONE 0 /* No file type */ #define ET_REL 1 /* Relocatable file */ #define ET_EXEC 2 /* Executable file */ #define ET_DYN 3 /* Shared object file */ #define ET_CORE 4 /* Core file */ #define ET_LOOS 0xFE00 /* Operating system-specific */ #define ET_HIOS 0xFEFF /* Operating system-specific */ #define ET_LOPROC 0xFF00 /* Processor-specific */ #define ET_HIPROC 0xFFFF /* Processor-specific */ /* Values for e_machine, which identifies the architecture. These numbers are officially assigned by registry@caldera.com. See below for a list of ad-hoc numbers used during initial development. */ #define EM_NONE 0 /* No machine */ #define EM_M32 1 /* AT&T WE 32100 */ #define EM_SPARC 2 /* SUN SPARC */ #define EM_386 3 /* Intel 80386 */ #define EM_68K 4 /* Motorola m68k family */ #define EM_88K 5 /* Motorola m88k family */ #define EM_486 6 /* Intel 80486 *//* Reserved for future use */ #define EM_860 7 /* Intel 80860 */ #define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ #define EM_S370 9 /* IBM System/370 */ #define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated */ #define EM_PARISC 15 /* HPPA */ #define EM_VPP550 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ #define EM_960 19 /* Intel 80960 */ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* 64-bit PowerPC */ #define EM_S390 22 /* IBM S/390 */ #define EM_SPU 23 /* Sony/Toshiba/IBM SPU */ #define EM_V800 36 /* NEC V800 series */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH32 */ #define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ #define EM_RCE 39 /* Old name for MCore */ #define EM_ARM 40 /* ARM */ #define EM_OLD_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Renesas (formerly Hitachi) / SuperH SH */ #define EM_SPARCV9 43 /* SPARC v9 64-bit */ #define EM_TRICORE 44 /* Siemens Tricore embedded processor */ #define EM_ARC 45 /* ARC Cores */ #define EM_H8_300 46 /* Renesas (formerly Hitachi) H8/300 */ #define EM_H8_300H 47 /* Renesas (formerly Hitachi) H8/300H */ #define EM_H8S 48 /* Renesas (formerly Hitachi) H8S */ #define EM_H8_500 49 /* Renesas (formerly Hitachi) H8/500 */ #define EM_IA_64 50 /* Intel IA-64 Processor */ #define EM_MIPS_X 51 /* Stanford MIPS-X */ #define EM_COLDFIRE 52 /* Motorola Coldfire */ #define EM_68HC12 53 /* Motorola M68HC12 */ #define EM_MMA 54 /* Fujitsu Multimedia Accelerator */ #define EM_PCP 55 /* Siemens PCP */ #define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ #define EM_NDR1 57 /* Denso NDR1 microprocesspr */ #define EM_STARCORE 58 /* Motorola Star*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ #define EM_ST100 60 /* STMicroelectronics ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor */ #define EM_X86_64 62 /* Advanced Micro Devices X86-64 processor */ #define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */ #define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */ #define EM_FX66 66 /* Siemens FX66 microcontroller */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ #define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ #define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ #define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ #define EM_SVX 73 /* Silicon Graphics SVx */ #define EM_ST19 74 /* STMicroelectronics ST19 8-bit cpu */ #define EM_VAX 75 /* Digital VAX */ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded cpu */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP processor */ #define EM_ZSP 79 /* LSI Logic's 16-bit DSP processor */ #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ #define EM_HUANY 81 /* Harvard's machine-independent format */ #define EM_PRISM 82 /* SiTera Prism */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ #define EM_FR30 84 /* Fujitsu FR30 */ #define EM_D10V 85 /* Mitsubishi D10V */ #define EM_D30V 86 /* Mitsubishi D30V */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Renesas M32R (formerly Mitsubishi M32R) */ #define EM_MN10300 89 /* Matsushita MN10300 */ #define EM_MN10200 90 /* Matsushita MN10200 */ #define EM_PJ 91 /* picoJava */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_IP2K 101 /* Ubicom IP2022 micro controller */ #define EM_CR 103 /* National Semiconductor CompactRISC */ #define EM_MSP430 105 /* TI msp430 micro controller */ #define EM_BLACKFIN 106 /* ADI Blackfin */ #define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ #define EM_CRX 114 /* National Semiconductor CRX */ #define EM_CR16 115 /* National Semiconductor CompactRISC - CR16 */ #define EM_SCORE 135 /* Sunplus Score */ /* If it is necessary to assign new unofficial EM_* values, please pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision with official or non-GNU unofficial values. NOTE: Do not just increment the most recent number by one. Somebody else somewhere will do exactly the same thing, and you will have a collision. Instead, pick a random number. Normally, each entity or maintainer responsible for a machine with an unofficial e_machine number should eventually ask registry@caldera.com for an officially blessed number to be added to the list above. */ /* Old version of Sparc v9, from before the ABI; This should be removed shortly. */ #define EM_OLD_SPARCV9 11 /* Old version of PowerPC, this should be removed shortly. */ #define EM_PPC_OLD 17 /* picoJava */ #define EM_PJ_OLD 99 /* AVR magic number. Written in the absense of an ABI. */ #define EM_AVR_OLD 0x1057 /* MSP430 magic number. Written in the absense of everything. */ #define EM_MSP430_OLD 0x1059 /* Morpho MT. Written in the absense of an ABI. */ #define EM_MT 0x2530 /* FR30 magic number - no EABI available. */ #define EM_CYGNUS_FR30 0x3330 /* OpenRISC magic number. Written in the absense of an ABI. */ #define EM_OPENRISC_OLD 0x3426 /* DLX magic number. Written in the absense of an ABI. */ #define EM_DLX 0x5aa5 /* FRV magic number - no EABI available??. */ #define EM_CYGNUS_FRV 0x5441 /* Infineon Technologies 16-bit microcontroller with C166-V2 core. */ #define EM_XC16X 0x4688 /* D10V backend magic number. Written in the absence of an ABI. */ #define EM_CYGNUS_D10V 0x7650 /* D30V backend magic number. Written in the absence of an ABI. */ #define EM_CYGNUS_D30V 0x7676 /* Ubicom IP2xxx; Written in the absense of an ABI. */ #define EM_IP2K_OLD 0x8217 /* (Deprecated) Temporary number for the OpenRISC processor. */ #define EM_OR32 0x8472 /* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ #define EM_CYGNUS_POWERPC 0x9025 /* Alpha backend magic number. Written in the absence of an ABI. */ #define EM_ALPHA 0x9026 /* Cygnus M32R ELF backend. Written in the absence of an ABI. */ #define EM_CYGNUS_M32R 0x9041 /* V850 backend magic number. Written in the absense of an ABI. */ #define EM_CYGNUS_V850 0x9080 /* old S/390 backend magic number. Written in the absence of an ABI. */ #define EM_S390_OLD 0xa390 /* Old, unofficial value for Xtensa. */ #define EM_XTENSA_OLD 0xabc7 #define EM_XSTORMY16 0xad45 /* mn10200 and mn10300 backend magic numbers. Written in the absense of an ABI. */ #define EM_CYGNUS_MN10300 0xbeef #define EM_CYGNUS_MN10200 0xdead /* Renesas M32C and M16C. */ #define EM_M32C 0xFEB0 /* Vitesse IQ2000. */ #define EM_IQ2000 0xFEBA /* NIOS magic number - no EABI available. */ #define EM_NIOS32 0xFEBB #define EM_CYGNUS_MEP 0xF00D /* Toshiba MeP */ /* See the above comment before you add a new EM_* value here. */ /* Values for e_version. */ #define EV_NONE 0 /* Invalid ELF version */ #define EV_CURRENT 1 /* Current version */ /* Values for program header, p_type field. */ #define PT_NULL 0 /* Program header table entry unused */ #define PT_LOAD 1 /* Loadable program segment */ #define PT_DYNAMIC 2 /* Dynamic linking information */ #define PT_INTERP 3 /* Program interpreter */ #define PT_NOTE 4 /* Auxiliary information */ #define PT_SHLIB 5 /* Reserved, unspecified semantics */ #define PT_PHDR 6 /* Entry for header table itself */ #define PT_TLS 7 /* Thread local storage segment */ #define PT_LOOS 0x60000000 /* OS-specific */ #define PT_HIOS 0x6fffffff /* OS-specific */ #define PT_LOPROC 0x70000000 /* Processor-specific */ #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */ #define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) /* Frame unwind information */ #define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */ #define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */ #define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */ /* Program segment permissions, in program header p_flags field. */ #define PF_X (1 << 0) /* Segment is executable */ #define PF_W (1 << 1) /* Segment is writable */ #define PF_R (1 << 2) /* Segment is readable */ /* #define PF_MASKOS 0x0F000000 *//* OS-specific reserved bits */ #define PF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ #define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */ /* Values for section header, sh_type field. */ #define SHT_NULL 0 /* Section header table entry unused */ #define SHT_PROGBITS 1 /* Program specific (private) data */ #define SHT_SYMTAB 2 /* Link editing symbol table */ #define SHT_STRTAB 3 /* A string table */ #define SHT_RELA 4 /* Relocation entries with addends */ #define SHT_HASH 5 /* A symbol hash table */ #define SHT_DYNAMIC 6 /* Information for dynamic linking */ #define SHT_NOTE 7 /* Information that marks file */ #define SHT_NOBITS 8 /* Section occupies no space in file */ #define SHT_REL 9 /* Relocation entries, no addends */ #define SHT_SHLIB 10 /* Reserved, unspecified semantics */ #define SHT_DYNSYM 11 /* Dynamic linking symbol table */ #define SHT_INIT_ARRAY 14 /* Array of ptrs to init functions */ #define SHT_FINI_ARRAY 15 /* Array of ptrs to finish functions */ #define SHT_PREINIT_ARRAY 16 /* Array of ptrs to pre-init funcs */ #define SHT_GROUP 17 /* Section contains a section group */ #define SHT_SYMTAB_SHNDX 18 /* Indicies for SHN_XINDEX entries */ #define SHT_LOOS 0x60000000 /* First of OS specific semantics */ #define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes */ #define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */ #define SHT_GNU_LIBLIST 0x6ffffff7 /* List of prelink dependencies */ /* The next three section types are defined by Solaris, and are named SHT_SUNW*. We use them in GNU code, so we also define SHT_GNU* versions. */ #define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */ #define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */ #define SHT_SUNW_versym 0x6fffffff /* Symbol versions */ #define SHT_GNU_verdef SHT_SUNW_verdef #define SHT_GNU_verneed SHT_SUNW_verneed #define SHT_GNU_versym SHT_SUNW_versym #define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */ #define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */ #define SHT_LOUSER 0x80000000 /* Application-specific semantics */ /* #define SHT_HIUSER 0x8FFFFFFF *//* Application-specific semantics */ #define SHT_HIUSER 0xFFFFFFFF /* New value, defined in Oct 4, 1999 Draft */ /* Values for section header, sh_flags field. */ #define SHF_WRITE (1 << 0) /* Writable data during execution */ #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ #define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */ #define SHF_MERGE (1 << 4) /* Data in this section can be merged */ #define SHF_STRINGS (1 << 5) /* Contains null terminated character strings */ #define SHF_INFO_LINK (1 << 6) /* sh_info holds section header table index */ #define SHF_LINK_ORDER (1 << 7) /* Preserve section ordering when linking */ #define SHF_OS_NONCONFORMING (1 << 8) /* OS specific processing required */ #define SHF_GROUP (1 << 9) /* Member of a section group */ #define SHF_TLS (1 << 10) /* Thread local storage section */ /* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */ #define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ /* Values of note segment descriptor types for core files. */ #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ #define NT_FPREGSET 2 /* Contains copy of fpregset struct */ #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ #define NT_TASKSTRUCT 4 /* Contains copy of task struct */ #define NT_AUXV 6 /* Contains copy of Elfxx_auxv_t */ #define NT_THRMISC 7 /* Contains copy of thrmisc struct */ #define NT_PRXFPREG 0x46e62b7f /* Contains a user_xfpregs_struct; */ /* note name must be "LINUX". */ /* Note segments for core files on dir-style procfs systems. */ #define NT_PSTATUS 10 /* Has a struct pstatus */ #define NT_FPREGS 12 /* Has a struct fpregset */ #define NT_PSINFO 13 /* Has a struct psinfo */ #define NT_LWPSTATUS 16 /* Has a struct lwpstatus_t */ #define NT_LWPSINFO 17 /* Has a struct lwpsinfo_t */ #define NT_WIN32PSTATUS 18 /* Has a struct win32_pstatus */ /* Note segments for core files on NetBSD systems. Note name must start with "NetBSD-CORE". */ #define NT_NETBSDCORE_PROCINFO 1 /* Has a struct procinfo */ #define NT_NETBSDCORE_FIRSTMACH 32 /* start of machdep note types */ /* Values of note segment descriptor types for object files. */ #define NT_VERSION 1 /* Contains a version string. */ #define NT_ARCH 2 /* Contains an architecture string. */ /* Values for GNU .note.ABI-tag notes. Note name is "GNU". */ #define NT_GNU_ABI_TAG 1 #define GNU_ABI_TAG_LINUX 0 #define GNU_ABI_TAG_HURD 1 #define GNU_ABI_TAG_SOLARIS 2 #define GNU_ABI_TAG_FREEBSD 3 #define GNU_ABI_TAG_NETBSD 4 /* Values for NetBSD .note.netbsd.ident notes. Note name is "NetBSD". */ #define NT_NETBSD_IDENT 1 /* Values for OpenBSD .note.openbsd.ident notes. Note name is "OpenBSD". */ #define NT_OPENBSD_IDENT 1 /* Values for FreeBSD .note.ABI-tag notes. Note name is "FreeBSD". */ #define NT_FREEBSD_ABI_TAG 1 +/* Values for FreeBSD .note.tag notes. Note name is "FreeBSD". */ + +#define NT_FREEBSD_TAG 2 + /* These three macros disassemble and assemble a symbol table st_info field, which contains the symbol binding and symbol type. The STB_ and STT_ defines identify the binding and type. */ #define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4) #define ELF_ST_TYPE(val) ((val) & 0xF) #define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF)) /* The 64bit and 32bit versions of these macros are identical, but the ELF spec defines them, so here they are. */ #define ELF32_ST_BIND ELF_ST_BIND #define ELF32_ST_TYPE ELF_ST_TYPE #define ELF32_ST_INFO ELF_ST_INFO #define ELF64_ST_BIND ELF_ST_BIND #define ELF64_ST_TYPE ELF_ST_TYPE #define ELF64_ST_INFO ELF_ST_INFO /* This macro disassembles and assembles a symbol's visibility into the st_other field. The STV_ defines specify the actual visibility. */ #define ELF_ST_VISIBILITY(v) ((v) & 0x3) /* The remaining bits in the st_other field are not currently used. They should be set to zero. */ #define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY #define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY #define STN_UNDEF 0 /* Undefined symbol index */ #define STB_LOCAL 0 /* Symbol not visible outside obj */ #define STB_GLOBAL 1 /* Symbol visible outside obj */ #define STB_WEAK 2 /* Like globals, lower precedence */ #define STB_LOOS 10 /* OS-specific semantics */ #define STB_HIOS 12 /* OS-specific semantics */ #define STB_LOPROC 13 /* Application-specific semantics */ #define STB_HIPROC 15 /* Application-specific semantics */ #define STT_NOTYPE 0 /* Symbol type is unspecified */ #define STT_OBJECT 1 /* Symbol is a data object */ #define STT_FUNC 2 /* Symbol is a code object */ #define STT_SECTION 3 /* Symbol associated with a section */ #define STT_FILE 4 /* Symbol gives a file name */ #define STT_COMMON 5 /* An uninitialised common block */ #define STT_TLS 6 /* Thread local data object */ #define STT_RELC 8 /* Complex relocation expression */ #define STT_SRELC 9 /* Signed Complex relocation expression */ #define STT_LOOS 10 /* OS-specific semantics */ #define STT_HIOS 12 /* OS-specific semantics */ #define STT_LOPROC 13 /* Application-specific semantics */ #define STT_HIPROC 15 /* Application-specific semantics */ /* Special section indices, which may show up in st_shndx fields, among other places. */ #define SHN_UNDEF 0 /* Undefined section reference */ #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */ #define SHN_HIPROC 0xFF1F /* End range of appl-specific */ #define SHN_LOOS 0xFF20 /* OS specific semantics, lo */ #define SHN_HIOS 0xFF3F /* OS specific semantics, hi */ #define SHN_ABS 0xFFF1 /* Associated symbol is absolute */ #define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ #define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */ #define SHN_BAD ((unsigned) -1) /* Used internally by bfd */ /* The following constants control how a symbol may be accessed once it has become part of an executable or shared library. */ #define STV_DEFAULT 0 /* Visibility is specified by binding type */ #define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */ #define STV_HIDDEN 2 /* Can only be seen inside currect component */ #define STV_PROTECTED 3 /* Treat as STB_LOCAL inside current component */ /* Relocation info handling macros. */ #define ELF32_R_SYM(i) ((i) >> 8) #define ELF32_R_TYPE(i) ((i) & 0xff) #define ELF32_R_INFO(s,t) (((s) << 8) + ((t) & 0xff)) #define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) #define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 31 << 1) + (bfd_vma) (t)) /* Dynamic section tags. */ #define DT_NULL 0 #define DT_NEEDED 1 #define DT_PLTRELSZ 2 #define DT_PLTGOT 3 #define DT_HASH 4 #define DT_STRTAB 5 #define DT_SYMTAB 6 #define DT_RELA 7 #define DT_RELASZ 8 #define DT_RELAENT 9 #define DT_STRSZ 10 #define DT_SYMENT 11 #define DT_INIT 12 #define DT_FINI 13 #define DT_SONAME 14 #define DT_RPATH 15 #define DT_SYMBOLIC 16 #define DT_REL 17 #define DT_RELSZ 18 #define DT_RELENT 19 #define DT_PLTREL 20 #define DT_DEBUG 21 #define DT_TEXTREL 22 #define DT_JMPREL 23 #define DT_BIND_NOW 24 #define DT_INIT_ARRAY 25 #define DT_FINI_ARRAY 26 #define DT_INIT_ARRAYSZ 27 #define DT_FINI_ARRAYSZ 28 #define DT_RUNPATH 29 #define DT_FLAGS 30 #define DT_ENCODING 32 #define DT_PREINIT_ARRAY 32 #define DT_PREINIT_ARRAYSZ 33 /* Note, the Oct 4, 1999 draft of the ELF ABI changed the values for DT_LOOS and DT_HIOS. Some implementations however, use values outside of the new range (see below). */ #define OLD_DT_LOOS 0x60000000 #define DT_LOOS 0x6000000d #define DT_HIOS 0x6ffff000 #define OLD_DT_HIOS 0x6fffffff #define DT_LOPROC 0x70000000 #define DT_HIPROC 0x7fffffff /* The next four dynamic tags are used on Solaris. We support them everywhere. Note these values lie outside of the (new) range for OS specific values. This is a deliberate special case and we maintain it for backwards compatability. */ #define DT_VALRNGLO 0x6ffffd00 #define DT_GNU_PRELINKED 0x6ffffdf5 #define DT_GNU_CONFLICTSZ 0x6ffffdf6 #define DT_GNU_LIBLISTSZ 0x6ffffdf7 #define DT_CHECKSUM 0x6ffffdf8 #define DT_PLTPADSZ 0x6ffffdf9 #define DT_MOVEENT 0x6ffffdfa #define DT_MOVESZ 0x6ffffdfb #define DT_FEATURE 0x6ffffdfc #define DT_POSFLAG_1 0x6ffffdfd #define DT_SYMINSZ 0x6ffffdfe #define DT_SYMINENT 0x6ffffdff #define DT_VALRNGHI 0x6ffffdff #define DT_ADDRRNGLO 0x6ffffe00 #define DT_GNU_HASH 0x6ffffef5 #define DT_TLSDESC_PLT 0x6ffffef6 #define DT_TLSDESC_GOT 0x6ffffef7 #define DT_GNU_CONFLICT 0x6ffffef8 #define DT_GNU_LIBLIST 0x6ffffef9 #define DT_CONFIG 0x6ffffefa #define DT_DEPAUDIT 0x6ffffefb #define DT_AUDIT 0x6ffffefc #define DT_PLTPAD 0x6ffffefd #define DT_MOVETAB 0x6ffffefe #define DT_SYMINFO 0x6ffffeff #define DT_ADDRRNGHI 0x6ffffeff #define DT_RELACOUNT 0x6ffffff9 #define DT_RELCOUNT 0x6ffffffa #define DT_FLAGS_1 0x6ffffffb #define DT_VERDEF 0x6ffffffc #define DT_VERDEFNUM 0x6ffffffd #define DT_VERNEED 0x6ffffffe #define DT_VERNEEDNUM 0x6fffffff /* This tag is a GNU extension to the Solaris version scheme. */ #define DT_VERSYM 0x6ffffff0 #define DT_LOPROC 0x70000000 #define DT_HIPROC 0x7fffffff /* These section tags are used on Solaris. We support them everywhere, and hope they do not conflict. */ #define DT_AUXILIARY 0x7ffffffd #define DT_USED 0x7ffffffe #define DT_FILTER 0x7fffffff /* Values used in DT_FEATURE .dynamic entry. */ #define DTF_1_PARINIT 0x00000001 /* From http://docs.sun.com:80/ab2/coll.45.13/LLM/@Ab2PageView/21165?Ab2Lang=C&Ab2Enc=iso-8859-1 DTF_1_CONFEXP is the same as DTF_1_PARINIT. It is a typo. The value defined here is the same as the one in on Solaris 8. */ #define DTF_1_CONFEXP 0x00000002 /* Flag values used in the DT_POSFLAG_1 .dynamic entry. */ #define DF_P1_LAZYLOAD 0x00000001 #define DF_P1_GROUPPERM 0x00000002 /* Flag value in in the DT_FLAGS_1 .dynamic entry. */ #define DF_1_NOW 0x00000001 #define DF_1_GLOBAL 0x00000002 #define DF_1_GROUP 0x00000004 #define DF_1_NODELETE 0x00000008 #define DF_1_LOADFLTR 0x00000010 #define DF_1_INITFIRST 0x00000020 #define DF_1_NOOPEN 0x00000040 #define DF_1_ORIGIN 0x00000080 #define DF_1_DIRECT 0x00000100 #define DF_1_TRANS 0x00000200 #define DF_1_INTERPOSE 0x00000400 #define DF_1_NODEFLIB 0x00000800 #define DF_1_NODUMP 0x00001000 #define DF_1_CONLFAT 0x00002000 /* Flag values for the DT_FLAGS entry. */ #define DF_ORIGIN (1 << 0) #define DF_SYMBOLIC (1 << 1) #define DF_TEXTREL (1 << 2) #define DF_BIND_NOW (1 << 3) #define DF_STATIC_TLS (1 << 4) /* These constants are used for the version number of a Elf32_Verdef structure. */ #define VER_DEF_NONE 0 #define VER_DEF_CURRENT 1 /* These constants appear in the vd_flags field of a Elf32_Verdef structure. */ #define VER_FLG_BASE 0x1 #define VER_FLG_WEAK 0x2 /* These special constants can be found in an Elf32_Versym field. */ #define VER_NDX_LOCAL 0 #define VER_NDX_GLOBAL 1 /* These constants are used for the version number of a Elf32_Verneed structure. */ #define VER_NEED_NONE 0 #define VER_NEED_CURRENT 1 /* This flag appears in a Versym structure. It means that the symbol is hidden, and is only visible with an explicit version number. This is a GNU extension. */ #define VERSYM_HIDDEN 0x8000 /* This is the mask for the rest of the Versym information. */ #define VERSYM_VERSION 0x7fff /* This is a special token which appears as part of a symbol name. It indictes that the rest of the name is actually the name of a version node, and is not part of the actual name. This is a GNU extension. For example, the symbol name `stat@ver2' is taken to mean the symbol `stat' in version `ver2'. */ #define ELF_VER_CHR '@' /* Possible values for si_boundto. */ #define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ #define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ #define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ /* Possible bitmasks for si_flags. */ #define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ #define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ #define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ #define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy loaded */ /* Syminfo version values. */ #define SYMINFO_NONE 0 #define SYMINFO_CURRENT 1 #define SYMINFO_NUM 2 /* Section Group Flags. */ #define GRP_COMDAT 0x1 /* A COMDAT group */ /* Auxv a_type values. */ #define AT_NULL 0 /* End of vector */ #define AT_IGNORE 1 /* Entry should be ignored */ #define AT_EXECFD 2 /* File descriptor of program */ #define AT_PHDR 3 /* Program headers for program */ #define AT_PHENT 4 /* Size of program header entry */ #define AT_PHNUM 5 /* Number of program headers */ #define AT_PAGESZ 6 /* System page size */ #define AT_BASE 7 /* Base address of interpreter */ #define AT_FLAGS 8 /* Flags */ #define AT_ENTRY 9 /* Entry point of program */ #define AT_NOTELF 10 /* Program is not ELF */ #define AT_UID 11 /* Real uid */ #define AT_EUID 12 /* Effective uid */ #define AT_GID 13 /* Real gid */ #define AT_EGID 14 /* Effective gid */ #define AT_CLKTCK 17 /* Frequency of times() */ #define AT_PLATFORM 15 /* String identifying platform. */ #define AT_HWCAP 16 /* Machine dependent hints about processor capabilities. */ #define AT_FPUCW 18 /* Used FPU control word. */ #define AT_DCACHEBSIZE 19 /* Data cache block size. */ #define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ #define AT_UCACHEBSIZE 21 /* Unified cache block size. */ #define AT_IGNOREPPC 22 /* Entry should be ignored */ #define AT_SECURE 23 /* Boolean, was exec setuid-like? */ /* Pointer to the global system page used for system calls and other nice things. */ #define AT_SYSINFO 32 #define AT_SYSINFO_EHDR 33 /* Pointer to ELF header of system-supplied DSO. */ #define AT_SUN_UID 2000 /* Effective user ID. */ #define AT_SUN_RUID 2001 /* Real user ID. */ #define AT_SUN_GID 2002 /* Effective group ID. */ #define AT_SUN_RGID 2003 /* Real group ID. */ #define AT_SUN_LDELF 2004 /* Dynamic linker's ELF header. */ #define AT_SUN_LDSHDR 2005 /* Dynamic linker's section headers. */ #define AT_SUN_LDNAME 2006 /* String giving name of dynamic linker. */ #define AT_SUN_LPAGESZ 2007 /* Large pagesize. */ #define AT_SUN_PLATFORM 2008 /* Platform name string. */ #define AT_SUN_HWCAP 2009 /* Machine dependent hints about processor capabilities. */ #define AT_SUN_IFLUSH 2010 /* Should flush icache? */ #define AT_SUN_CPU 2011 /* CPU name string. */ #define AT_SUN_EMUL_ENTRY 2012 /* COFF entry point address. */ #define AT_SUN_EMUL_EXECFD 2013 /* COFF executable file descriptor. */ #define AT_SUN_EXECNAME 2014 /* Canonicalized file name given to execve. */ #define AT_SUN_MMU 2015 /* String for name of MMU module. */ #define AT_SUN_LDDATA 2016 /* Dynamic linker's data segment address. */ #endif /* _ELF_COMMON_H */ Index: user/attilio/vmc-playground/contrib/binutils =================================================================== --- user/attilio/vmc-playground/contrib/binutils (revision 246333) +++ user/attilio/vmc-playground/contrib/binutils (revision 246334) Property changes on: user/attilio/vmc-playground/contrib/binutils ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /user/attilio/vmcontention/contrib/binutils:r246320-246333 Merged /head/contrib/binutils:r246295-246332 Index: user/attilio/vmc-playground/contrib/gcc/config/arm/freebsd.h =================================================================== --- user/attilio/vmc-playground/contrib/gcc/config/arm/freebsd.h (revision 246333) +++ user/attilio/vmc-playground/contrib/gcc/config/arm/freebsd.h (revision 246334) @@ -1,162 +1,163 @@ /* Definitions for StrongARM running FreeBSD using the ELF format Copyright (C) 2001, 2004 Free Software Foundation, Inc. Contributed by David E. O'Brien and BSDi. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #undef SUBTARGET_CPP_SPEC #define SUBTARGET_CPP_SPEC FBSD_CPP_SPEC #undef SUBTARGET_EXTRA_SPECS #define SUBTARGET_EXTRA_SPECS \ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \ { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, \ { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER } #undef SUBTARGET_EXTRA_ASM_SPEC #ifdef TARGET_ARM_EABI #define SUBTARGET_EXTRA_ASM_SPEC \ "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4} %{fpic|fpie:-k} %{fPIC|fPIE:-k}" #else #define SUBTARGET_EXTRA_ASM_SPEC \ "-matpcs %{fpic|fpie:-k} %{fPIC|fPIE:-k}" #endif /* Default to full FPA if -mhard-float is specified. */ #undef SUBTARGET_ASM_FLOAT_SPEC #define SUBTARGET_ASM_FLOAT_SPEC \ "%{mhard-float:-mfpu=fpa} \ %{mfloat-abi=hard:{!mfpu=*:-mfpu=fpa}} \ %{!mhard-float: %{msoft-float:-mfpu=softvfp;:-mfpu=softvfp}}" #undef LINK_SPEC #define LINK_SPEC " \ %{p:%nconsider using `-pg' instead of `-p' with gprof(1) } \ %{v:-V} \ %{assert*} %{R*} %{rpath*} %{defsym*} \ %{shared:-Bshareable %{h*} %{soname*}} \ %{!shared: \ %{!static: \ %{rdynamic:-export-dynamic} \ %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }} \ %{static:-Bstatic}} \ %{!static:--hash-style=both --enable-new-dtags} \ %{symbolic:-Bsymbolic} \ -X %{mbig-endian:-EB} %{mlittle-endian:-EL}" /************************[ Target stuff ]***********************************/ #ifndef TARGET_ENDIAN_DEFAULT #define TARGET_ENDIAN_DEFAULT 0 #endif #ifdef TARGET_ARM_EABI /* We default to a soft-float ABI so that binaries can run on all target hardware. */ #undef TARGET_DEFAULT_FLOAT_ABI #define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT #undef ARM_DEFAULT_ABI #define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX #undef TARGET_OS_CPP_BUILTINS #define TARGET_OS_CPP_BUILTINS() \ do \ { \ FBSD_TARGET_OS_CPP_BUILTINS(); \ TARGET_BPABI_CPP_BUILTINS(); \ } \ while (false) #else /* Default it to use ATPCS with soft-VFP. */ +#undef TARGET_DEFAULT #define TARGET_DEFAULT \ (MASK_APCS_FRAME \ | TARGET_ENDIAN_DEFAULT) #undef ARM_DEFAULT_ABI #define ARM_DEFAULT_ABI ARM_ABI_ATPCS #undef FPUTYPE_DEFAULT #define FPUTYPE_DEFAULT FPUTYPE_VFP #endif /* Define the actual types of some ANSI-mandated types. Needs to agree with . GCC defaults come from c-decl.c, c-common.c, and config//.h. */ /* arm.h gets this wrong for FreeBSD. We use the GCC defaults instead. */ #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "int" /* We use the GCC defaults here. */ #undef WCHAR_TYPE #if defined(FREEBSD_ARCH_armv6) #undef SUBTARGET_CPU_DEFAULT #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm1176jzs #undef FBSD_TARGET_CPU_CPP_BUILTINS #define FBSD_TARGET_CPU_CPP_BUILTINS() \ do { \ builtin_define ("__FreeBSD_ARCH_armv6__"); \ } while (0) #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)"); #else #undef SUBTARGET_CPU_DEFAULT #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9 #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)"); #endif /* FreeBSD does its profiling differently to the Acorn compiler. We don't need a word following the mcount call; and to skip it requires either an assembly stub or use of fomit-frame-pointer when compiling the profiling functions. Since we break Acorn CC compatibility below a little more won't hurt. */ #undef ARM_FUNCTION_PROFILER #define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \ { \ asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \ asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \ (TARGET_ARM && NEED_PLT_RELOC) \ ? "(PLT)" : ""); \ } /* Clear the instruction cache from `BEG' to `END'. This makes a call to the ARM_SYNC_ICACHE architecture specific syscall. */ #define CLEAR_INSN_CACHE(BEG, END) \ do \ { \ extern int sysarch(int number, void *args); \ struct \ { \ unsigned int addr; \ int len; \ } s; \ s.addr = (unsigned int)(BEG); \ s.len = (END) - (BEG); \ (void) sysarch (0, &s); \ } \ while (0) Index: user/attilio/vmc-playground/contrib/gcc/config/arm/unwind-arm.h =================================================================== --- user/attilio/vmc-playground/contrib/gcc/config/arm/unwind-arm.h (revision 246333) +++ user/attilio/vmc-playground/contrib/gcc/config/arm/unwind-arm.h (revision 246334) @@ -1,271 +1,271 @@ /* Header file for the ARM EABI unwinder Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Paul Brook This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file into combinations with other programs, and to distribute those combinations without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into a combine executable.) This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Language-independent unwinder header public defines. This contains both ABI defined objects, and GNU support routines. */ #ifndef UNWIND_ARM_H #define UNWIND_ARM_H #define __ARM_EABI_UNWINDER__ 1 #ifdef __cplusplus extern "C" { #endif typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); typedef _Unwind_Word _uw; typedef unsigned _uw64 __attribute__((mode(__DI__))); typedef unsigned _uw16 __attribute__((mode(__HI__))); typedef unsigned _uw8 __attribute__((mode(__QI__))); typedef enum { _URC_OK = 0, /* operation completed successfully */ _URC_FOREIGN_EXCEPTION_CAUGHT = 1, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9 /* unspecified failure of some kind */ } _Unwind_Reason_Code; typedef enum { _US_VIRTUAL_UNWIND_FRAME = 0, _US_UNWIND_FRAME_STARTING = 1, _US_UNWIND_FRAME_RESUME = 2, _US_ACTION_MASK = 3, _US_FORCE_UNWIND = 8, _US_END_OF_STACK = 16 } _Unwind_State; /* Provided only for for compatibility with existing code. */ typedef int _Unwind_Action; #define _UA_SEARCH_PHASE 1 #define _UA_CLEANUP_PHASE 2 #define _UA_HANDLER_FRAME 4 #define _UA_FORCE_UNWIND 8 #define _UA_END_OF_STACK 16 #define _URC_NO_REASON _URC_OK typedef struct _Unwind_Control_Block _Unwind_Control_Block; typedef struct _Unwind_Context _Unwind_Context; typedef _uw _Unwind_EHT_Header; /* UCB: */ struct _Unwind_Control_Block { - char exception_class[8]; + unsigned exception_class __attribute__((__mode__(__DI__))); void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *); /* Unwinder cache, private fields for the unwinder's use */ struct { _uw reserved1; /* Forced unwind stop fn, 0 if not forced */ _uw reserved2; /* Personality routine address */ _uw reserved3; /* Saved callsite address */ _uw reserved4; /* Forced unwind stop arg */ _uw reserved5; } unwinder_cache; /* Propagation barrier cache (valid after phase 1): */ struct { _uw sp; _uw bitpattern[5]; } barrier_cache; /* Cleanup cache (preserved over cleanup): */ struct { _uw bitpattern[4]; } cleanup_cache; /* Pr cache (for pr's benefit): */ struct { _uw fnstart; /* function start address */ _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */ _uw additional; /* additional data */ _uw reserved1; } pr_cache; long long int :0; /* Force alignment to 8-byte boundary */ }; /* Virtual Register Set*/ typedef enum { _UVRSC_CORE = 0, /* integer register */ _UVRSC_VFP = 1, /* vfp */ _UVRSC_FPA = 2, /* fpa */ _UVRSC_WMMXD = 3, /* Intel WMMX data register */ _UVRSC_WMMXC = 4 /* Intel WMMX control register */ } _Unwind_VRS_RegClass; typedef enum { _UVRSD_UINT32 = 0, _UVRSD_VFPX = 1, _UVRSD_FPAX = 2, _UVRSD_UINT64 = 3, _UVRSD_FLOAT = 4, _UVRSD_DOUBLE = 5 } _Unwind_VRS_DataRepresentation; typedef enum { _UVRSR_OK = 0, _UVRSR_NOT_IMPLEMENTED = 1, _UVRSR_FAILED = 2 } _Unwind_VRS_Result; /* Frame unwinding state. */ typedef struct { /* The current word (bytes packed msb first). */ _uw data; /* Pointer to the next word of data. */ _uw *next; /* The number of bytes left in this word. */ _uw8 bytes_left; /* The number of words pointed to by ptr. */ _uw8 words_left; } __gnu_unwind_state; typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State, _Unwind_Control_Block *, _Unwind_Context *); _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation, void *); _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation, void *); _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation); /* Support functions for the PR. */ #define _Unwind_Exception _Unwind_Control_Block - typedef char _Unwind_Exception_Class[8]; + typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); /* These two should never be used. */ _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); /* Interface functions: */ _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action, _Unwind_Exception_Class, _Unwind_Control_Block *, struct _Unwind_Context *, void *); _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, _Unwind_Stop_Fn, void *); _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); void _Unwind_Complete(_Unwind_Control_Block *ucbp); void _Unwind_DeleteException (_Unwind_Exception *); _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, _Unwind_Context *); _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *, __gnu_unwind_state *); /* Decode an R_ARM_TARGET2 relocation. */ static inline _Unwind_Word _Unwind_decode_target2 (_Unwind_Word ptr) { _Unwind_Word tmp; tmp = *(_Unwind_Word *) ptr; /* Zero values are always NULL. */ if (!tmp) return 0; #if defined(linux) || defined(__NetBSD__) /* Pc-relative indirect. */ tmp += ptr; tmp = *(_Unwind_Word *) tmp; #elif defined(__symbian__) /* Absolute pointer. Nothing more to do. */ #else /* Pc-relative pointer. */ tmp += ptr; #endif return tmp; } static inline _Unwind_Word _Unwind_GetGR (_Unwind_Context *context, int regno) { _uw val; _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); return val; } /* Return the address of the instruction, not the actual IP value. */ #define _Unwind_GetIP(context) \ (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) #define _Unwind_GetIPInfo(context, ip_before_insn) \ (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) static inline void _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val) { _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); } /* The dwarf unwinder doesn't understand arm/thumb state. We assume the landing pad uses the same instruction set as the call site. */ #define _Unwind_SetIP(context, val) \ _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) #ifdef __cplusplus } /* extern "C" */ #endif #endif /* defined UNWIND_ARM_H */ Index: user/attilio/vmc-playground/contrib/gcc =================================================================== --- user/attilio/vmc-playground/contrib/gcc (revision 246333) +++ user/attilio/vmc-playground/contrib/gcc (revision 246334) Property changes on: user/attilio/vmc-playground/contrib/gcc ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /head/contrib/gcc:r246295-246332 Merged /user/attilio/vmcontention/contrib/gcc:r246320-246333 Index: user/attilio/vmc-playground/contrib/gdb/gdb/osabi.c =================================================================== --- user/attilio/vmc-playground/contrib/gdb/gdb/osabi.c (revision 246333) +++ user/attilio/vmc-playground/contrib/gdb/gdb/osabi.c (revision 246334) @@ -1,630 +1,644 @@ /* OS ABI variant handling for GDB. Copyright 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "gdb_assert.h" #include "gdb_string.h" #include "osabi.h" #include "arch-utils.h" #include "gdbcmd.h" #include "command.h" #include "elf-bfd.h" #ifndef GDB_OSABI_DEFAULT #define GDB_OSABI_DEFAULT GDB_OSABI_UNKNOWN #endif /* State for the "set osabi" command. */ static enum { osabi_auto, osabi_default, osabi_user } user_osabi_state; static enum gdb_osabi user_selected_osabi; static const char *gdb_osabi_available_names[GDB_OSABI_INVALID + 3] = { "auto", "default", "none", NULL }; static const char *set_osabi_string; /* This table matches the indices assigned to enum gdb_osabi. Keep them in sync. */ static const char * const gdb_osabi_names[] = { "none", "SVR4", "GNU/Hurd", "Solaris", "OSF/1", "GNU/Linux", "FreeBSD a.out", "FreeBSD ELF", "NetBSD a.out", "NetBSD ELF", "OpenBSD ELF", "Windows CE", "DJGPP", "NetWare", "Irix", "LynxOS", "Interix", "HP/UX ELF", "HP/UX SOM", "ARM EABI v1", "ARM EABI v2", "ARM APCS", "QNX Neutrino", "Cygwin", "" }; const char * gdbarch_osabi_name (enum gdb_osabi osabi) { if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID) return gdb_osabi_names[osabi]; return gdb_osabi_names[GDB_OSABI_INVALID]; } /* Handler for a given architecture/OS ABI pair. There should be only one handler for a given OS ABI each architecture family. */ struct gdb_osabi_handler { struct gdb_osabi_handler *next; const struct bfd_arch_info *arch_info; enum gdb_osabi osabi; void (*init_osabi)(struct gdbarch_info, struct gdbarch *); }; static struct gdb_osabi_handler *gdb_osabi_handler_list; void gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine, enum gdb_osabi osabi, void (*init_osabi)(struct gdbarch_info, struct gdbarch *)) { struct gdb_osabi_handler **handler_p; const struct bfd_arch_info *arch_info = bfd_lookup_arch (arch, machine); const char **name_ptr; /* Registering an OS ABI handler for "unknown" is not allowed. */ if (osabi == GDB_OSABI_UNKNOWN) { internal_error (__FILE__, __LINE__, "gdbarch_register_osabi: An attempt to register a handler for " "OS ABI \"%s\" for architecture %s was made. The handler will " "not be registered", gdbarch_osabi_name (osabi), bfd_printable_arch_mach (arch, machine)); return; } gdb_assert (arch_info); for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL; handler_p = &(*handler_p)->next) { if ((*handler_p)->arch_info == arch_info && (*handler_p)->osabi == osabi) { internal_error (__FILE__, __LINE__, "gdbarch_register_osabi: A handler for OS ABI \"%s\" " "has already been registered for architecture %s", gdbarch_osabi_name (osabi), arch_info->printable_name); /* If user wants to continue, override previous definition. */ (*handler_p)->init_osabi = init_osabi; return; } } (*handler_p) = (struct gdb_osabi_handler *) xmalloc (sizeof (struct gdb_osabi_handler)); (*handler_p)->next = NULL; (*handler_p)->arch_info = arch_info; (*handler_p)->osabi = osabi; (*handler_p)->init_osabi = init_osabi; /* Add this OS ABI to the list of enum values for "set osabi", if it isn't already there. */ for (name_ptr = gdb_osabi_available_names; *name_ptr; name_ptr ++) { if (*name_ptr == gdbarch_osabi_name (osabi)) return; } *name_ptr++ = gdbarch_osabi_name (osabi); *name_ptr = NULL; } /* Sniffer to find the OS ABI for a given file's architecture and flavour. It is legal to have multiple sniffers for each arch/flavour pair, to disambiguate one OS's a.out from another, for example. The first sniffer to return something other than GDB_OSABI_UNKNOWN wins, so a sniffer should be careful to claim a file only if it knows for sure what it is. */ struct gdb_osabi_sniffer { struct gdb_osabi_sniffer *next; enum bfd_architecture arch; /* bfd_arch_unknown == wildcard */ enum bfd_flavour flavour; enum gdb_osabi (*sniffer)(bfd *); }; static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list; void gdbarch_register_osabi_sniffer (enum bfd_architecture arch, enum bfd_flavour flavour, enum gdb_osabi (*sniffer_fn)(bfd *)) { struct gdb_osabi_sniffer *sniffer; sniffer = (struct gdb_osabi_sniffer *) xmalloc (sizeof (struct gdb_osabi_sniffer)); sniffer->arch = arch; sniffer->flavour = flavour; sniffer->sniffer = sniffer_fn; sniffer->next = gdb_osabi_sniffer_list; gdb_osabi_sniffer_list = sniffer; } enum gdb_osabi gdbarch_lookup_osabi (bfd *abfd) { struct gdb_osabi_sniffer *sniffer; enum gdb_osabi osabi, match; int match_specific; /* If we aren't in "auto" mode, return the specified OS ABI. */ if (user_osabi_state == osabi_user) return user_selected_osabi; /* If we don't have a binary, return the default OS ABI (if set) or an inconclusive result (otherwise). */ if (abfd == NULL) { if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN) return GDB_OSABI_DEFAULT; else return GDB_OSABI_UNINITIALIZED; } match = GDB_OSABI_UNKNOWN; match_specific = 0; for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL; sniffer = sniffer->next) { if ((sniffer->arch == bfd_arch_unknown /* wildcard */ || sniffer->arch == bfd_get_arch (abfd)) && sniffer->flavour == bfd_get_flavour (abfd)) { osabi = (*sniffer->sniffer) (abfd); if (osabi < GDB_OSABI_UNKNOWN || osabi >= GDB_OSABI_INVALID) { internal_error (__FILE__, __LINE__, "gdbarch_lookup_osabi: invalid OS ABI (%d) from sniffer " "for architecture %s flavour %d", (int) osabi, bfd_printable_arch_mach (bfd_get_arch (abfd), 0), (int) bfd_get_flavour (abfd)); } else if (osabi != GDB_OSABI_UNKNOWN) { /* A specific sniffer always overrides a generic sniffer. Croak on multiple match if the two matches are of the same class. If the user wishes to continue, we'll use the first match. */ if (match != GDB_OSABI_UNKNOWN) { if ((match_specific && sniffer->arch != bfd_arch_unknown) || (!match_specific && sniffer->arch == bfd_arch_unknown)) { internal_error (__FILE__, __LINE__, "gdbarch_lookup_osabi: multiple %sspecific OS ABI " "match for architecture %s flavour %d: first " "match \"%s\", second match \"%s\"", match_specific ? "" : "non-", bfd_printable_arch_mach (bfd_get_arch (abfd), 0), (int) bfd_get_flavour (abfd), gdbarch_osabi_name (match), gdbarch_osabi_name (osabi)); } else if (sniffer->arch != bfd_arch_unknown) { match = osabi; match_specific = 1; } } else { match = osabi; if (sniffer->arch != bfd_arch_unknown) match_specific = 1; } } } } /* If we didn't find a match, but a default was specified at configure time, return the default. */ if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN && match == GDB_OSABI_UNKNOWN) return GDB_OSABI_DEFAULT; else return match; } /* Return non-zero if architecture A can run code written for architecture B. */ static int can_run_code_for (const struct bfd_arch_info *a, const struct bfd_arch_info *b) { /* BFD's 'A->compatible (A, B)' functions return zero if A and B are incompatible. But if they are compatible, it returns the 'more featureful' of the two arches. That is, if A can run code written for B, but B can't run code written for A, then it'll return A. struct bfd_arch_info objects are singletons: that is, there's supposed to be exactly one instance for a given machine. So you can tell whether two are equivalent by comparing pointers. */ return (a == b || a->compatible (a, b) == a); } void gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdb_osabi_handler *handler; if (info.osabi == GDB_OSABI_UNKNOWN) { /* Don't complain about an unknown OSABI. Assume the user knows what they are doing. */ return; } for (handler = gdb_osabi_handler_list; handler != NULL; handler = handler->next) { if (handler->osabi != info.osabi) continue; /* If the architecture described by ARCH_INFO can run code for the architcture we registered the handler for, then the handler is applicable. Note, though, that if the handler is for an architecture that is a superset of ARCH_INFO, we can't use that --- it would be perfectly correct for it to install gdbarch methods that refer to registers / instructions / other facilities ARCH_INFO doesn't have. NOTE: kettenis/20021027: There may be more than one machine type that is compatible with the desired machine type. Right now we simply return the first match, which is fine for now. However, we might want to do something smarter in the future. */ /* NOTE: cagney/2003-10-23: The code for "a can_run_code_for b" is implemented using BFD's compatible method (a->compatible (b) == a -- the lowest common denominator between a and b is a). That method's definition of compatible may not be as you expect. For instance the test "amd64 can run code for i386" (or more generally "64-bit ISA can run code for the 32-bit ISA"). BFD doesn't normally consider 32-bit and 64-bit "compatible" so it doesn't succeed. */ if (can_run_code_for (info.bfd_arch_info, handler->arch_info)) { (*handler->init_osabi) (info, gdbarch); return; } } warning ("A handler for the OS ABI \"%s\" is not built into this configuration\n" "of GDB. Attempting to continue with the default %s settings.\n", gdbarch_osabi_name (info.osabi), info.bfd_arch_info->printable_name); } /* Limit on the amount of data to be read. */ #define MAX_NOTESZ 128 /* Return non-zero if NOTE matches NAME, DESCSZ and TYPE. */ static int check_note (bfd *abfd, asection *sect, const char *note, const char *name, unsigned long descsz, unsigned long type) { unsigned long notesz; /* Calculate the size of this note. */ notesz = strlen (name) + 1; notesz = ((notesz + 3) & ~3); notesz += descsz; notesz = ((notesz + 3) & ~3); /* If this assertion triggers, increase MAX_NOTESZ. */ gdb_assert (notesz <= MAX_NOTESZ); /* Check whether SECT is big enough to comtain the complete note. */ if (notesz > bfd_section_size (abfd, sect)) return 0; /* Check the note name. */ if (bfd_h_get_32 (abfd, note) != (strlen (name) + 1) || strcmp (note + 12, name) != 0) return 0; /* Check the descriptor size. */ if (bfd_h_get_32 (abfd, note + 4) != descsz) return 0; /* Check the note type. */ if (bfd_h_get_32 (abfd, note + 8) != type) return 0; return 1; } /* Generic sniffer for ELF flavoured files. */ void generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj) { enum gdb_osabi *osabi = obj; const char *name; unsigned int sectsize; char *note; name = bfd_get_section_name (abfd, sect); sectsize = bfd_section_size (abfd, sect); /* Limit the amount of data to read. */ if (sectsize > MAX_NOTESZ) sectsize = MAX_NOTESZ; note = alloca (sectsize); bfd_get_section_contents (abfd, sect, note, 0, sectsize); /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */ if (strcmp (name, ".note.ABI-tag") == 0) { /* GNU. */ if (check_note (abfd, sect, note, "GNU", 16, NT_GNU_ABI_TAG)) { unsigned int abi_tag = bfd_h_get_32 (abfd, note + 16); switch (abi_tag) { case GNU_ABI_TAG_LINUX: *osabi = GDB_OSABI_LINUX; break; case GNU_ABI_TAG_HURD: *osabi = GDB_OSABI_HURD; break; case GNU_ABI_TAG_SOLARIS: *osabi = GDB_OSABI_SOLARIS; break; case GNU_ABI_TAG_FREEBSD: *osabi = GDB_OSABI_FREEBSD_ELF; break; case GNU_ABI_TAG_NETBSD: *osabi = GDB_OSABI_NETBSD_ELF; break; default: internal_error (__FILE__, __LINE__, "\ generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d", abi_tag); } return; } /* FreeBSD. */ if (check_note (abfd, sect, note, "FreeBSD", 4, NT_FREEBSD_ABI_TAG)) { /* There is no need to check the version yet. */ *osabi = GDB_OSABI_FREEBSD_ELF; return; } return; } + + /* .note.tag notes, used by FreeBSD. */ + if (strcmp (name, ".note.tag") == 0) + { + /* FreeBSD. */ + if (check_note (abfd, sect, note, "FreeBSD", 4, NT_FREEBSD_TAG)) + { + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_FREEBSD_ELF; + return; + } + + return; + } /* .note.netbsd.ident notes, used by NetBSD. */ if (strcmp (name, ".note.netbsd.ident") == 0 && check_note (abfd, sect, note, "NetBSD", 4, NT_NETBSD_IDENT)) { /* There is no need to check the version yet. */ *osabi = GDB_OSABI_NETBSD_ELF; return; } /* .note.openbsd.ident notes, used by OpenBSD. */ if (strcmp (name, ".note.openbsd.ident") == 0 && check_note (abfd, sect, note, "OpenBSD", 4, NT_OPENBSD_IDENT)) { /* There is no need to check the version yet. */ *osabi = GDB_OSABI_OPENBSD_ELF; return; } /* .note.netbsdcore.procinfo notes, used by NetBSD. */ if (strcmp (name, ".note.netbsdcore.procinfo") == 0) { *osabi = GDB_OSABI_NETBSD_ELF; return; } } static enum gdb_osabi generic_elf_osabi_sniffer (bfd *abfd) { unsigned int elfosabi; enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; switch (elfosabi) { case ELFOSABI_NONE: /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the file are conforming to the base specification for that machine (there are no OS-specific extensions). In order to determine the real OS in use we must look for OS notes that have been added. */ bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); break; case ELFOSABI_FREEBSD: osabi = GDB_OSABI_FREEBSD_ELF; break; case ELFOSABI_NETBSD: osabi = GDB_OSABI_NETBSD_ELF; break; case ELFOSABI_LINUX: osabi = GDB_OSABI_LINUX; break; case ELFOSABI_HURD: osabi = GDB_OSABI_HURD; break; case ELFOSABI_SOLARIS: osabi = GDB_OSABI_SOLARIS; break; case ELFOSABI_HPUX: osabi = GDB_OSABI_HPUX_ELF; break; } if (osabi == GDB_OSABI_UNKNOWN) { /* The FreeBSD folks have been naughty; they stored the string "FreeBSD" in the padding of the e_ident field of the ELF header to "brand" their ELF binaries in FreeBSD 3.x. */ if (strcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD") == 0) osabi = GDB_OSABI_FREEBSD_ELF; } return osabi; } static void set_osabi (char *args, int from_tty, struct cmd_list_element *c) { struct gdbarch_info info; if (strcmp (set_osabi_string, "auto") == 0) user_osabi_state = osabi_auto; else if (strcmp (set_osabi_string, "default") == 0) { user_selected_osabi = GDB_OSABI_DEFAULT; user_osabi_state = osabi_user; } else if (strcmp (set_osabi_string, "none") == 0) { user_selected_osabi = GDB_OSABI_UNKNOWN; user_osabi_state = osabi_user; } else { int i; for (i = 1; i < GDB_OSABI_INVALID; i++) if (strcmp (set_osabi_string, gdbarch_osabi_name (i)) == 0) { user_selected_osabi = i; user_osabi_state = osabi_user; break; } if (i == GDB_OSABI_INVALID) internal_error (__FILE__, __LINE__, "Invalid OS ABI \"%s\" passed to command handler.", set_osabi_string); } /* NOTE: At some point (true multiple architectures) we'll need to be more graceful here. */ gdbarch_info_init (&info); if (! gdbarch_update_p (info)) internal_error (__FILE__, __LINE__, "Updating OS ABI failed."); } static void show_osabi (char *args, int from_tty) { if (user_osabi_state == osabi_auto) printf_filtered ("The current OS ABI is \"auto\" (currently \"%s\").\n", gdbarch_osabi_name (gdbarch_osabi (current_gdbarch))); else printf_filtered ("The current OS ABI is \"%s\".\n", gdbarch_osabi_name (user_selected_osabi)); if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN) printf_filtered ("The default OS ABI is \"%s\".\n", gdbarch_osabi_name (GDB_OSABI_DEFAULT)); } extern initialize_file_ftype _initialize_gdb_osabi; /* -Wmissing-prototype */ void _initialize_gdb_osabi (void) { struct cmd_list_element *c; if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "") != 0) internal_error (__FILE__, __LINE__, "_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent"); /* Register a generic sniffer for ELF flavoured files. */ gdbarch_register_osabi_sniffer (bfd_arch_unknown, bfd_target_elf_flavour, generic_elf_osabi_sniffer); /* Register the "set osabi" command. */ c = add_set_enum_cmd ("osabi", class_support, gdb_osabi_available_names, &set_osabi_string, "Set OS ABI of target.", &setlist); set_cmd_sfunc (c, set_osabi); add_cmd ("osabi", class_support, show_osabi, "Show OS/ABI of target.", &showlist); user_osabi_state = osabi_auto; } Index: user/attilio/vmc-playground/contrib/gdb =================================================================== --- user/attilio/vmc-playground/contrib/gdb (revision 246333) +++ user/attilio/vmc-playground/contrib/gdb (revision 246334) Property changes on: user/attilio/vmc-playground/contrib/gdb ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /head/contrib/gdb:r246295-246332 Merged /user/attilio/vmcontention/contrib/gdb:r246320-246333 Index: user/attilio/vmc-playground/contrib/libstdc++/libsupc++/unwind-cxx.h =================================================================== --- user/attilio/vmc-playground/contrib/libstdc++/libsupc++/unwind-cxx.h (revision 246333) +++ user/attilio/vmc-playground/contrib/libstdc++/libsupc++/unwind-cxx.h (revision 246334) @@ -1,251 +1,253 @@ // -*- C++ -*- Exception handling and frame unwind runtime interface routines. // Copyright (C) 2001 Free Software Foundation, Inc. // // This file is part of GCC. // // GCC is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // GCC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING. If not, write to // the Free Software Foundation, 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. // This is derived from the C++ ABI for IA-64. Where we diverge // for cross-architecture compatibility are noted with "@@@". #ifndef _UNWIND_CXX_H #define _UNWIND_CXX_H 1 // Level 2: C++ ABI #include #include #include #include "unwind.h" #pragma GCC visibility push(default) namespace __cxxabiv1 { // A C++ exception object consists of a header, which is a wrapper around // an unwind object header with additional C++ specific information, // followed by the exception object itself. struct __cxa_exception { // Manage the exception object itself. std::type_info *exceptionType; void (*exceptionDestructor)(void *); // The C++ standard has entertaining rules wrt calling set_terminate // and set_unexpected in the middle of the exception cleanup process. std::unexpected_handler unexpectedHandler; std::terminate_handler terminateHandler; // The caught exception stack threads through here. __cxa_exception *nextException; // How many nested handlers have caught this exception. A negated // value is a signal that this object has been rethrown. int handlerCount; #ifdef __ARM_EABI_UNWINDER__ // Stack of exceptions in cleanups. __cxa_exception* nextPropagatingException; // The nuber of active cleanup handlers for this exception. int propagationCount; #else // Cache parsed handler data from the personality routine Phase 1 // for Phase 2 and __cxa_call_unexpected. int handlerSwitchValue; const unsigned char *actionRecord; const unsigned char *languageSpecificData; _Unwind_Ptr catchTemp; void *adjustedPtr; #endif // The generic exception header. Must be last. _Unwind_Exception unwindHeader; }; // Each thread in a C++ program has access to a __cxa_eh_globals object. struct __cxa_eh_globals { __cxa_exception *caughtExceptions; unsigned int uncaughtExceptions; #ifdef __ARM_EABI_UNWINDER__ __cxa_exception* propagatingExceptions; #endif }; // The __cxa_eh_globals for the current thread can be obtained by using // either of the following functions. The "fast" version assumes at least // one prior call of __cxa_get_globals has been made from the current // thread, so no initialization is necessary. extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw(); // Allocate memory for the exception plus the thown object. extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw(); // Free the space allocated for the exception. extern "C" void __cxa_free_exception(void *thrown_exception) throw(); // Throw the exception. extern "C" void __cxa_throw (void *thrown_exception, std::type_info *tinfo, void (*dest) (void *)) __attribute__((noreturn)); // Used to implement exception handlers. extern "C" void *__cxa_get_exception_ptr (void *) throw(); extern "C" void *__cxa_begin_catch (void *) throw(); extern "C" void __cxa_end_catch (); extern "C" void __cxa_rethrow () __attribute__((noreturn)); // These facilitate code generation for recurring situations. extern "C" void __cxa_bad_cast (); extern "C" void __cxa_bad_typeid (); // @@@ These are not directly specified by the IA-64 C++ ABI. // Handles re-checking the exception specification if unexpectedHandler // throws, and if bad_exception needs to be thrown. Called from the // compiler. extern "C" void __cxa_call_unexpected (void *) __attribute__((noreturn)); extern "C" void __cxa_call_terminate (void*) __attribute__((noreturn)); #ifdef __ARM_EABI_UNWINDER__ // Arm EABI specified routines. typedef enum { ctm_failed = 0, ctm_succeeded = 1, ctm_succeeded_with_ptr_to_base = 2 } __cxa_type_match_result; extern "C" bool __cxa_type_match(_Unwind_Exception*, const std::type_info*, bool, void**); extern "C" void __cxa_begin_cleanup (_Unwind_Exception*); extern "C" void __cxa_end_cleanup (void); #endif // Invokes given handler, dying appropriately if the user handler was // so inconsiderate as to return. extern void __terminate(std::terminate_handler) __attribute__((noreturn)); extern void __unexpected(std::unexpected_handler) __attribute__((noreturn)); // The current installed user handlers. extern std::terminate_handler __terminate_handler; extern std::unexpected_handler __unexpected_handler; // These are explicitly GNU C++ specific. // Acquire the C++ exception header from the C++ object. static inline __cxa_exception * __get_exception_header_from_obj (void *ptr) { return reinterpret_cast<__cxa_exception *>(ptr) - 1; } // Acquire the C++ exception header from the generic exception header. static inline __cxa_exception * __get_exception_header_from_ue (_Unwind_Exception *exc) { return reinterpret_cast<__cxa_exception *>(exc + 1) - 1; } -#ifdef __ARM_EABI_UNWINDER__ +#if defined(__ARM_EABI_UNWINDER__) && !defined(__FreeBSD__) static inline bool __is_gxx_exception_class(_Unwind_Exception_Class c) { // TODO: Take advantage of the fact that c will always be word aligned. return c[0] == 'G' && c[1] == 'N' && c[2] == 'U' && c[3] == 'C' && c[4] == 'C' && c[5] == '+' && c[6] == '+' && c[7] == '\0'; } static inline void __GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c) { c[0] = 'G'; c[1] = 'N'; c[2] = 'U'; c[3] = 'C'; c[4] = 'C'; c[5] = '+'; c[6] = '+'; c[7] = '\0'; } - -static inline void* -__gxx_caught_object(_Unwind_Exception* eo) -{ - return (void*)eo->barrier_cache.bitpattern[0]; -} -#else // !__ARM_EABI_UNWINDER__ +#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__ // This is the exception class we report -- "GNUCC++\0". const _Unwind_Exception_Class __gxx_exception_class = ((((((((_Unwind_Exception_Class) 'G' << 8 | (_Unwind_Exception_Class) 'N') << 8 | (_Unwind_Exception_Class) 'U') << 8 | (_Unwind_Exception_Class) 'C') << 8 | (_Unwind_Exception_Class) 'C') << 8 | (_Unwind_Exception_Class) '+') << 8 | (_Unwind_Exception_Class) '+') << 8 | (_Unwind_Exception_Class) '\0'); static inline bool __is_gxx_exception_class(_Unwind_Exception_Class c) { return c == __gxx_exception_class; } - #define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class +#endif + +#ifdef __ARM_EABI_UNWINDER__ +static inline void* +__gxx_caught_object(_Unwind_Exception* eo) +{ + return (void*)eo->barrier_cache.bitpattern[0]; +} +#else // !__ARM_EABI_UNWINDER__ // GNU C++ personality routine, Version 0. extern "C" _Unwind_Reason_Code __gxx_personality_v0 (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *); // GNU C++ sjlj personality routine, Version 0. extern "C" _Unwind_Reason_Code __gxx_personality_sj0 (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *); static inline void* __gxx_caught_object(_Unwind_Exception* eo) { __cxa_exception* header = __get_exception_header_from_ue (eo); return header->adjustedPtr; } #endif // !__ARM_EABI_UNWINDER__ } /* namespace __cxxabiv1 */ #pragma GCC visibility pop #endif // _UNWIND_CXX_H Index: user/attilio/vmc-playground/contrib/libstdc++ =================================================================== --- user/attilio/vmc-playground/contrib/libstdc++ (revision 246333) +++ user/attilio/vmc-playground/contrib/libstdc++ (revision 246334) Property changes on: user/attilio/vmc-playground/contrib/libstdc++ ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /user/attilio/vmcontention/contrib/libstdc++:r246320-246333 Merged /head/contrib/libstdc++:r244694-246332 Index: user/attilio/vmc-playground/lib/Makefile =================================================================== --- user/attilio/vmc-playground/lib/Makefile (revision 246333) +++ user/attilio/vmc-playground/lib/Makefile (revision 246334) @@ -1,249 +1,249 @@ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ .include # To satisfy shared library or ELF linkage when only the libraries being # built are visible: # # csu must be built before all shared libaries for ELF. # libc must be built before all other shared libraries. # libbsm must be built before libauditd. # libcom_err must be built before libpam. # libcrypt must be built before libpam. # libkvm must be built before libdevstat. # msun must be built before libg++ and libstdc++. # libmd must be built before libatm, libopie, libradius, and libtacplus. # ncurses must be built before libdialog, libedit and libreadline. # libnetgraph must be built before libbsnmp/modules/snmp_netgraph. # libopie must be built before libpam. # libradius must be built before libpam. # librpcsvc must be built before libpam. # libsbuf must be built before libcam. # libtacplus must be built before libpam. # libutil must be built before libpam. # libypclnt must be built before libpam. # libgssapi must be built before librpcsec_gss # # Otherwise, the SUBDIR list should be in alphabetical order. # # Except it appears bind needs to be compiled last SUBDIR_ORDERED= ${_csu} \ libc \ libbsm \ libauditd \ libcompiler_rt \ libcrypt \ libelf \ ${_libiconv_modules} \ libkvm \ msun \ libmd \ ncurses \ ${_libnetgraph} \ libradius \ librpcsvc \ libsbuf \ libtacplus \ libutil \ ${_libypclnt} \ ${_libcxxrt} \ ${_libcplusplus} .if ${MK_KERBEROS_SUPPORT} != "no" SUBDIR_ORDERED+= libcom_err .endif SUBDIR= ${SUBDIR_ORDERED} \ libalias \ libarchive \ ${_libatm} \ libbegemot \ libblocksruntime \ ${_libbluetooth} \ ${_libbsnmp} \ libbz2 \ libcalendar \ libcam \ libcompat \ libdevinfo \ libdevstat \ libdwarf \ libedit \ ${_libefi} \ libexpat \ libfetch \ libgeom \ ${_libgpib} \ ${_libgssapi} \ ${_librpcsec_gss} \ libipsec \ ${_libipx} \ libjail \ libkiconv \ liblzma \ libmagic \ libmandoc \ libmemstat \ ${_libmilter} \ ${_libmp} \ ${_libnandfs} \ libnetbsd \ ${_libngatm} \ libopie \ libpam \ libpcap \ ${_libpmc} \ ${_libproc} \ libprocstat \ librt \ ${_librtld_db} \ ${_libsdp} \ ${_libsm} \ ${_libsmdb} \ ${_libsmutil} \ libstand \ libstdbuf \ libstdthreads \ ${_libtelnet} \ ${_libthr} \ libthread_db \ libufs \ libugidfw \ libulog \ ${_libusbhid} \ ${_libusb} \ ${_libvgl} \ ${_libvmmapi} \ libwrap \ liby \ libz \ ${_atf} \ ${_bind} \ ${_clang} .if exists(${.CURDIR}/csu/${MACHINE_ARCH}-elf) _csu=csu/${MACHINE_ARCH}-elf .elif exists(${.CURDIR}/csu/${MACHINE_ARCH}) _csu=csu/${MACHINE_ARCH} .elif exists(${.CURDIR}/csu/${MACHINE_CPUARCH}/Makefile) _csu=csu/${MACHINE_CPUARCH} .else _csu=csu .endif # NB: keep these sorted by MK_* knobs .if ${MK_ATF} != "no" _atf= atf .endif .if ${MK_ATM} != "no" _libngatm= libngatm .endif .if ${MK_BIND} != "no" _bind= bind .endif .if ${MK_BLUETOOTH} != "no" _libbluetooth= libbluetooth _libsdp= libsdp .endif .if ${MK_BSNMP} != "no" _libbsnmp= libbsnmp .endif .if ${MK_CLANG} != "no" && !defined(COMPAT_32BIT) _clang= clang .endif .if ${MK_GPIB} != "no" _libgpib= libgpib .endif .if ${MK_GSSAPI} != "no" _libgssapi= libgssapi _librpcsec_gss= librpcsec_gss .endif .if ${MK_ICONV} != "no" _libiconv_modules= libiconv_modules .endif .if ${MK_IPX} != "no" _libipx= libipx .endif +.if ${MK_LIBCPLUSPLUS} != "no" +_libcxxrt= libcxxrt +_libcplusplus= libc++ +.endif + .if ${MK_LIBTHR} != "no" _libthr= libthr .endif .if ${MK_NAND} != "no" _libnandfs= libnandfs .endif .if ${MK_NETGRAPH} != "no" _libnetgraph= libnetgraph .endif .if ${MK_NIS} != "no" _libypclnt= libypclnt .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _libvgl= libvgl _libproc= libproc _librtld_db= librtld_db .endif .if ${MACHINE_CPUARCH} == "amd64" _libvmmapi= libvmmapi .endif .if ${MACHINE_CPUARCH} == "ia64" _libefi= libefi .endif .if ${MACHINE_CPUARCH} == "mips" _libproc= libproc _librtld_db= librtld_db .endif .if ${MACHINE_CPUARCH} == "powerpc" _libproc= libproc _librtld_db= librtld_db .endif .if ${MK_OPENSSL} != "no" _libmp= libmp -.endif - -.if ${MK_LIBCPLUSPLUS} != "no" -_libcxxrt= libcxxrt -_libcplusplus= libc++ .endif .if ${MK_PMC} != "no" _libpmc= libpmc .endif .if ${MK_SENDMAIL} != "no" _libmilter= libmilter _libsm= libsm _libsmdb= libsmdb _libsmutil= libsmutil .endif .if ${MK_TELNET} != "no" _libtelnet= libtelnet .endif .if ${MK_USB} != "no" _libusbhid= libusbhid _libusb= libusb .endif .include Index: user/attilio/vmc-playground/lib/libcxxrt/Version.map =================================================================== --- user/attilio/vmc-playground/lib/libcxxrt/Version.map (revision 246333) +++ user/attilio/vmc-playground/lib/libcxxrt/Version.map (revision 246334) @@ -1,321 +1,319 @@ # $FreeBSD$ # Define the same version as the libsupc++ from gcc 4.2.1 so that we can use # libcxxrt as a drop-in replacement. CXXABI_1.3 { global: # ABI functions with C linkage __cxa_allocate_exception; __cxa_bad_cast; __cxa_bad_typeid; __cxa_begin_catch; __cxa_begin_cleanup; __cxa_call_unexpected; __cxa_current_exception_type; __cxa_demangle; __cxa_end_catch; __cxa_end_cleanup; __cxa_free_exception; __cxa_get_globals; __cxa_get_globals_fast; __cxa_guard_abort; __cxa_guard_acquire; __cxa_guard_release; __cxa_pure_virtual; __cxa_rethrow; __cxa_throw; __cxa_type_match; __cxa_vec_cctor; __cxa_vec_cleanup; __cxa_vec_ctor; __cxa_vec_delete2; __cxa_vec_delete3; __cxa_vec_delete; __cxa_vec_dtor; __cxa_vec_new2; __cxa_vec_new3; __cxa_vec_new; __dynamic_cast; __gxx_personality_sj0; __gxx_personality_v0; extern "C++" { # Type info classes and their destructors "__cxxabiv1::__array_type_info"; "__cxxabiv1::__array_type_info::~__array_type_info()"; "__cxxabiv1::__class_type_info"; "__cxxabiv1::__class_type_info::~__class_type_info()"; "__cxxabiv1::__enum_type_info"; "__cxxabiv1::__enum_type_info::~__enum_type_info()"; "__cxxabiv1::__function_type_info::"; "__cxxabiv1::__function_type_info::~__function_type_info()"; "__cxxabiv1::__fundamental_type_info"; "__cxxabiv1::__fundamental_type_info::~__fundamental_type_info()"; "__cxxabiv1::__pbase_type_info"; "__cxxabiv1::__pbase_type_info::~__pbase_type_info()"; "__cxxabiv1::__pointer_to_member_type_info"; "__cxxabiv1::__pointer_to_member_type_info::~__pointer_to_member_type_info()"; "__cxxabiv1::__pointer_type_info"; "__cxxabiv1::__pointer_type_info::~__pointer_type_info()"; "__cxxabiv1::__si_class_type_info"; "__cxxabiv1::__si_class_type_info::~__si_class_type_info()"; "__cxxabiv1::__vmi_class_type_info"; "__cxxabiv1::__vmi_class_type_info::~__vmi_class_type_info()"; # vtables typeinfo classes. "vtable for __cxxabiv1::__array_type_info"; "vtable for __cxxabiv1::__class_type_info"; "vtable for __cxxabiv1::__enum_type_info"; "vtable for __cxxabiv1::__function_type_info"; "vtable for __cxxabiv1::__fundamental_type_info"; "vtable for __cxxabiv1::__pbase_type_info"; "vtable for __cxxabiv1::__pointer_to_member_type_info"; "vtable for __cxxabiv1::__pointer_type_info"; "vtable for __cxxabiv1::__si_class_type_info"; "vtable for __cxxabiv1::__vmi_class_type_info"; # Type info for built-in types "typeinfo for bool const*"; "typeinfo for bool"; "typeinfo for char const*"; "typeinfo for char"; "typeinfo for double const*"; "typeinfo for double"; "typeinfo for float const*"; "typeinfo for float"; "typeinfo for int const*"; "typeinfo for int"; "typeinfo for long const*"; "typeinfo for long double const*"; "typeinfo for long double"; "typeinfo for long long const*"; "typeinfo for long long"; "typeinfo for long"; "typeinfo for short const*"; "typeinfo for short"; "typeinfo for signed char const*"; "typeinfo for signed char"; "typeinfo for unsigned char const*"; "typeinfo for unsigned char"; "typeinfo for unsigned int const*"; "typeinfo for unsigned int"; "typeinfo for unsigned long const*"; "typeinfo for unsigned long long const*"; "typeinfo for unsigned long long"; "typeinfo for unsigned long"; "typeinfo for unsigned short const*"; "typeinfo for unsigned short"; "typeinfo for void const*"; "typeinfo for void"; "typeinfo for wchar_t const*"; "typeinfo for wchar_t"; "typeinfo for bool*"; "typeinfo for wchar_t*"; "typeinfo for short*"; "typeinfo for char*"; "typeinfo for unsigned char*"; "typeinfo for long long*"; "typeinfo for unsigned short*"; "typeinfo for long*"; "typeinfo for double*"; "typeinfo for unsigned long*"; "typeinfo for unsigned long long*"; "typeinfo for int*"; "typeinfo for long double*"; "typeinfo for signed char*"; "typeinfo for void*"; "typeinfo for unsigned int*"; "typeinfo for float*"; "typeinfo for __cxxabiv1::__array_type_info"; "typeinfo for __cxxabiv1::__class_type_info"; "typeinfo for __cxxabiv1::__enum_type_info"; "typeinfo for __cxxabiv1::__function_type_info"; "typeinfo for __cxxabiv1::__fundamental_type_info"; "typeinfo for __cxxabiv1::__pbase_type_info"; "typeinfo for __cxxabiv1::__pointer_to_member_type_info"; "typeinfo for __cxxabiv1::__pointer_type_info"; "typeinfo for __cxxabiv1::__si_class_type_info"; "typeinfo for __cxxabiv1::__vmi_class_type_info"; # Typeinfo names. "typeinfo name for unsigned char const*"; "typeinfo name for long const*"; "typeinfo name for double const*"; "typeinfo name for unsigned long long const*"; "typeinfo name for unsigned short const*"; "typeinfo name for char const*"; "typeinfo name for long long const*"; "typeinfo name for short const*"; "typeinfo name for unsigned int const*"; "typeinfo name for float const*"; "typeinfo name for bool const*"; "typeinfo name for wchar_t const*"; "typeinfo name for int const*"; "typeinfo name for unsigned long const*"; "typeinfo name for void const*"; "typeinfo name for long double const*"; "typeinfo name for signed char const*"; "typeinfo name for wchar_t"; "typeinfo name for short"; "typeinfo name for char"; "typeinfo name for float"; "typeinfo name for void"; "typeinfo name for unsigned int"; "typeinfo name for bool"; "typeinfo name for signed char"; "typeinfo name for long double"; "typeinfo name for int"; "typeinfo name for unsigned long long"; "typeinfo name for unsigned long"; "typeinfo name for unsigned char"; "typeinfo name for long"; "typeinfo name for long long"; "typeinfo name for unsigned short"; "typeinfo name for double"; "typeinfo name for bool*"; "typeinfo name for wchar_t*"; "typeinfo name for short*"; "typeinfo name for char*"; "typeinfo name for unsigned char*"; "typeinfo name for long long*"; "typeinfo name for unsigned short*"; "typeinfo name for long*"; "typeinfo name for double*"; "typeinfo name for unsigned long*"; "typeinfo name for unsigned long long*"; "typeinfo name for int*"; "typeinfo name for long double*"; "typeinfo name for signed char*"; "typeinfo name for void*"; "typeinfo name for unsigned int*"; "typeinfo name for float*"; "typeinfo name for __cxxabiv1::__array_type_info"; "typeinfo name for __cxxabiv1::__class_type_info"; "typeinfo name for __cxxabiv1::__enum_type_info"; "typeinfo name for __cxxabiv1::__function_type_info"; "typeinfo name for __cxxabiv1::__fundamental_type_info"; "typeinfo name for __cxxabiv1::__pbase_type_info"; "typeinfo name for __cxxabiv1::__pointer_to_member_type_info"; "typeinfo name for __cxxabiv1::__pointer_type_info"; "typeinfo name for __cxxabiv1::__si_class_type_info"; "typeinfo name for __cxxabiv1::__vmi_class_type_info"; "std::type_info::type_info(std::type_info const&)"; - "std::type_info::type_info(std::type_info const&)"; "std::type_info::operator=(std::type_info const&)"; # Extensions "pathscale::set_terminate(void (*)())"; "pathscale::set_unexpected(void (*)())"; "pathscale::set_use_thread_local_handlers(bool)"; }; local: *; }; CXXABI_1.3.1 { __cxa_get_exception_ptr; } CXXABI_1.3; CXXRT_1.0 { extern "C++" { "std::type_info::name() const"; "std::type_info::before(std::type_info const&) const"; "std::type_info::operator==(std::type_info const&) const"; "std::type_info::operator!=(std::type_info const&) const"; "std::bad_cast::bad_cast(std::bad_cast const&)"; "std::bad_cast::bad_cast()"; - "std::bad_cast::bad_cast(std::bad_cast const&)"; - "std::bad_cast::bad_cast()"; "std::bad_cast::operator=(std::bad_cast const&)"; + "std::bad_typeid::bad_typeid(std::bad_typeid const&)"; + "std::bad_typeid::bad_typeid()"; + "std::bad_typeid::operator=(std::bad_typeid const&)"; "std::exception::exception(std::exception const&)"; "std::exception::exception()"; - "std::exception::exception(std::exception const&)"; - "std::exception::exception()"; "std::exception::operator=(std::exception const&)"; + "std::bad_alloc::bad_alloc(std::bad_alloc const&)"; + "std::bad_alloc::bad_alloc()"; + "std::bad_alloc::operator=(std::bad_alloc const&)"; - - - - }; __cxa_allocate_dependent_exception; __cxa_current_primary_exception; __cxa_decrement_exception_refcount; __cxa_free_dependent_exception; __cxa_increment_exception_refcount; __cxa_rethrow_primary_exception; } CXXABI_1.3.1; GLIBCXX_3.4 { extern "C++" { "operator delete[](void*)"; "operator delete(void*)"; "operator new[](unsigned int)"; "operator new(unsigned int)"; "operator new(unsigned int, std::nothrow_t const&)"; "operator new[](unsigned long)"; "operator new(unsigned long)"; "operator new(unsigned long, std::nothrow_t const&)"; "std::unexpected()"; "std::get_terminate()"; "std::get_unexpected()"; "std::uncaught_exception()"; "std::terminate()"; "std::type_info::~type_info()"; "std::bad_cast::~bad_cast()"; + "std::bad_typeid::~bad_typeid()"; "std::exception::~exception()"; + "std::bad_alloc::~bad_alloc()"; + "std::exception::what() const"; + std::set_new_handler*; std::set_terminate*; std::set_unexpected*; - std::exception*; - std::bad_alloc; - std::bad_typeid; - std::type_info*; + std::type_info::__*; "vtable for std::bad_alloc"; "vtable for std::bad_cast"; "vtable for std::bad_typeid"; "vtable for std::exception"; "vtable for std::type_info"; "typeinfo for std::bad_alloc"; "typeinfo for std::bad_typeid"; - "typeinfo for std::exception"; "typeinfo for std::bad_cast"; "typeinfo for std::exception"; "typeinfo for std::type_info"; + "typeinfo name for std::bad_alloc"; "typeinfo name for std::bad_typeid"; "typeinfo name for std::bad_cast"; "typeinfo name for std::exception"; "typeinfo name for std::type_info"; }; }; GLIBCXX_3.4.9 { extern "C++" { "std::bad_typeid::what() const"; "std::bad_cast::what() const"; "std::bad_alloc::what() const"; }; } GLIBCXX_3.4; Index: user/attilio/vmc-playground/sbin/recoverdisk/recoverdisk.c =================================================================== --- user/attilio/vmc-playground/sbin/recoverdisk/recoverdisk.c (revision 246333) +++ user/attilio/vmc-playground/sbin/recoverdisk/recoverdisk.c (revision 246334) @@ -1,317 +1,322 @@ /*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static volatile sig_atomic_t aborting = 0; static size_t bigsize = 1024 * 1024; static size_t medsize; static size_t minsize = 512; struct lump { off_t start; off_t len; int state; TAILQ_ENTRY(lump) list; }; static TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); static void new_lump(off_t start, off_t len, int state) { struct lump *lp; lp = malloc(sizeof *lp); if (lp == NULL) err(1, "Malloc failed"); lp->start = start; lp->len = len; lp->state = state; TAILQ_INSERT_TAIL(&lumps, lp, list); } static struct lump *lp; static char *wworklist = NULL; static char *rworklist = NULL; #define PRINT_HEADER \ printf("%13s %7s %13s %5s %13s %13s %9s\n", \ "start", "size", "block-len", "state", "done", "remaining", "% done") #define PRINT_STATUS(start, i, len, state, d, t) \ printf("\r%13jd %7zu %13jd %5d %13jd %13jd %9.5f", \ (intmax_t)start, \ i, \ (intmax_t)len, \ state, \ (intmax_t)d, \ (intmax_t)(t - d), \ 100*(double)d/(double)t) /* Save the worklist if -w was given */ static void save_worklist(void) { FILE *file; struct lump *llp; if (wworklist != NULL) { (void)fprintf(stderr, "\nSaving worklist ..."); fflush(stderr); file = fopen(wworklist, "w"); if (file == NULL) err(1, "Error opening file %s", wworklist); TAILQ_FOREACH(llp, &lumps, list) fprintf(file, "%jd %jd %d\n", (intmax_t)llp->start, (intmax_t)llp->len, llp->state); fclose(file); (void)fprintf(stderr, " done.\n"); } } /* Read the worklist if -r was given */ static off_t read_worklist(off_t t) { off_t s, l, d; int state, lines; FILE *file; (void)fprintf(stderr, "Reading worklist ..."); fflush(stderr); file = fopen(rworklist, "r"); if (file == NULL) err(1, "Error opening file %s", rworklist); lines = 0; d = t; for (;;) { ++lines; if (3 != fscanf(file, "%jd %jd %d\n", &s, &l, &state)) { if (!feof(file)) err(1, "Error parsing file %s at line %d", rworklist, lines); else break; } new_lump(s, l, state); d -= l; } (void)fprintf(stderr, " done.\n"); /* * Return the number of bytes already read * (at least not in worklist). */ return (d); } static void usage(void) { (void)fprintf(stderr, "usage: recoverdisk [-b bigsize] [-r readlist] " "[-s interval] [-w writelist] source [destination]\n"); exit(1); } static void sighandler(__unused int sig) { aborting = 1; } int main(int argc, char * const argv[]) { int ch; int fdr, fdw; off_t t, d, start, len; size_t i, j; int error, state; u_char *buf; u_int sectorsize; + u_int stripesize; time_t t1, t2; struct stat sb; u_int n, snapshot = 60; while ((ch = getopt(argc, argv, "b:r:w:s:")) != -1) { switch (ch) { case 'b': bigsize = strtoul(optarg, NULL, 0); break; case 'r': rworklist = strdup(optarg); if (rworklist == NULL) err(1, "Cannot allocate enough memory"); break; case 's': snapshot = strtoul(optarg, NULL, 0); break; case 'w': wworklist = strdup(optarg); if (wworklist == NULL) err(1, "Cannot allocate enough memory"); break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 1 || argc > 2) usage(); fdr = open(argv[0], O_RDONLY); if (fdr < 0) err(1, "Cannot open read descriptor %s", argv[0]); error = fstat(fdr, &sb); if (error < 0) err(1, "fstat failed"); if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { error = ioctl(fdr, DIOCGSECTORSIZE, §orsize); if (error < 0) err(1, "DIOCGSECTORSIZE failed"); + + error = ioctl(fdr, DIOCGSTRIPESIZE, &stripesize); + if (error == 0 && stripesize > sectorsize) + sectorsize = stripesize; minsize = sectorsize; bigsize = (bigsize / sectorsize) * sectorsize; error = ioctl(fdr, DIOCGMEDIASIZE, &t); if (error < 0) err(1, "DIOCGMEDIASIZE failed"); } else { t = sb.st_size; } if (bigsize < minsize) bigsize = minsize; for (ch = 0; (bigsize >> ch) > minsize; ch++) continue; medsize = bigsize >> (ch / 2); medsize = (medsize / minsize) * minsize; fprintf(stderr, "Bigsize = %zu, medsize = %zu, minsize = %zu\n", bigsize, medsize, minsize); buf = malloc(bigsize); if (buf == NULL) err(1, "Cannot allocate %zu bytes buffer", bigsize); if (argc > 1) { fdw = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE); if (fdw < 0) err(1, "Cannot open write descriptor %s", argv[1]); if (ftruncate(fdw, t) < 0) err(1, "Cannot truncate output %s to %jd bytes", argv[1], (intmax_t)t); } else fdw = -1; if (rworklist != NULL) { d = read_worklist(t); } else { new_lump(0, t, 0); d = 0; } if (wworklist != NULL) signal(SIGINT, sighandler); t1 = 0; start = len = i = state = 0; PRINT_HEADER; n = 0; for (;;) { lp = TAILQ_FIRST(&lumps); if (lp == NULL) break; while (lp->len > 0 && !aborting) { /* These are only copied for printing stats */ start = lp->start; len = lp->len; state = lp->state; i = MIN(lp->len, (off_t)bigsize); if (lp->state == 1) i = MIN(lp->len, (off_t)medsize); if (lp->state > 1) i = MIN(lp->len, (off_t)minsize); time(&t2); if (t1 != t2 || lp->len < (off_t)bigsize) { PRINT_STATUS(start, i, len, state, d, t); t1 = t2; if (++n == snapshot) { save_worklist(); n = 0; } } if (i == 0) { errx(1, "BOGUS i %10jd", (intmax_t)i); } fflush(stdout); j = pread(fdr, buf, i, lp->start); if (j == i) { d += i; if (fdw >= 0) j = pwrite(fdw, buf, i, lp->start); else j = i; if (j != i) printf("\nWrite error at %jd/%zu\n", lp->start, i); lp->start += i; lp->len -= i; continue; } printf("\n%jd %zu failed (%s)\n", lp->start, i, strerror(errno)); if (errno == EINVAL) { printf("read() size too big? Try with -b 131072"); aborting = 1; } if (errno == ENXIO) aborting = 1; new_lump(lp->start, i, lp->state + 1); lp->start += i; lp->len -= i; } if (aborting) { save_worklist(); return (0); } TAILQ_REMOVE(&lumps, lp, list); free(lp); } PRINT_STATUS(start, i, len, state, d, t); save_worklist(); printf("\nCompleted\n"); return (0); } Index: user/attilio/vmc-playground/sbin =================================================================== --- user/attilio/vmc-playground/sbin (revision 246333) +++ user/attilio/vmc-playground/sbin (revision 246334) Property changes on: user/attilio/vmc-playground/sbin ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /head/sbin:r246295-246332 Merged /user/attilio/vmcontention/sbin:r246320-246333 Index: user/attilio/vmc-playground/sys/arm/arm/vm_machdep.c =================================================================== --- user/attilio/vmc-playground/sys/arm/arm/vm_machdep.c (revision 246333) +++ user/attilio/vmc-playground/sys/arm/arm/vm_machdep.c (revision 246334) @@ -1,722 +1,721 @@ /*- * Copyright (c) 1982, 1986 The Regents of the University of California. * Copyright (c) 1989, 1990 William Jolitz * Copyright (c) 1994 John Dyson * All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department, and William Jolitz. * * Redistribution and use in source and binary :forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef NSFBUFS #define NSFBUFS (512 + maxusers * 16) #endif #ifndef ARM_USE_SMALL_ALLOC static void sf_buf_init(void *arg); SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL); LIST_HEAD(sf_head, sf_buf); /* * A hash table of active sendfile(2) buffers */ static struct sf_head *sf_buf_active; static u_long sf_buf_hashmask; #define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask) static TAILQ_HEAD(, sf_buf) sf_buf_freelist; static u_int sf_buf_alloc_want; /* * A lock used to synchronize access to the hash table and free list */ static struct mtx sf_buf_lock; #endif /* * Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb, set up the stack so that the child * ready to run and return to user mode. */ void cpu_fork(register struct thread *td1, register struct proc *p2, struct thread *td2, int flags) { struct pcb *pcb2; struct trapframe *tf; struct switchframe *sf; struct mdproc *mdp2; if ((flags & RFPROC) == 0) return; pcb2 = (struct pcb *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1; #ifdef __XSCALE__ #ifndef CPU_XSCALE_CORE3 pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE); #endif #endif td2->td_pcb = pcb2; bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); mdp2 = &p2->p_md; bcopy(&td1->td_proc->p_md, mdp2, sizeof(*mdp2)); pcb2->un_32.pcb32_und_sp = td2->td_kstack + USPACE_UNDEF_STACK_TOP; pcb2->un_32.pcb32_sp = td2->td_kstack + USPACE_SVC_STACK_TOP - sizeof(*pcb2); pmap_activate(td2); td2->td_frame = tf = (struct trapframe *)pcb2->un_32.pcb32_sp - 1; *tf = *td1->td_frame; sf = (struct switchframe *)tf - 1; sf->sf_r4 = (u_int)fork_return; sf->sf_r5 = (u_int)td2; sf->sf_pc = (u_int)fork_trampoline; tf->tf_spsr &= ~PSR_C_bit; tf->tf_r0 = 0; tf->tf_r1 = 0; pcb2->un_32.pcb32_sp = (u_int)sf; /* Setup to release spin count in fork_exit(). */ td2->td_md.md_spinlock_count = 1; td2->td_md.md_saved_cspr = 0; #ifdef ARM_TP_ADDRESS td2->td_md.md_tp = *(register_t *)ARM_TP_ADDRESS; #else td2->td_md.md_tp = (register_t) get_tls(); #endif } void cpu_thread_swapin(struct thread *td) { } void cpu_thread_swapout(struct thread *td) { } /* * Detatch mapped page and release resources back to the system. */ void sf_buf_free(struct sf_buf *sf) { #ifndef ARM_USE_SMALL_ALLOC mtx_lock(&sf_buf_lock); sf->ref_count--; if (sf->ref_count == 0) { TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry); nsfbufsused--; pmap_kremove(sf->kva); sf->m = NULL; LIST_REMOVE(sf, list_entry); if (sf_buf_alloc_want > 0) wakeup(&sf_buf_freelist); } mtx_unlock(&sf_buf_lock); #endif } #ifndef ARM_USE_SMALL_ALLOC /* * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) */ static void sf_buf_init(void *arg) { struct sf_buf *sf_bufs; vm_offset_t sf_base; int i; nsfbufs = NSFBUFS; TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs); sf_buf_active = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask); TAILQ_INIT(&sf_buf_freelist); sf_base = kmem_alloc_nofault(kernel_map, nsfbufs * PAGE_SIZE); sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT | M_ZERO); for (i = 0; i < nsfbufs; i++) { sf_bufs[i].kva = sf_base + i * PAGE_SIZE; TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry); } sf_buf_alloc_want = 0; mtx_init(&sf_buf_lock, "sf_buf", NULL, MTX_DEF); } #endif /* * Get an sf_buf from the freelist. Will block if none are available. */ struct sf_buf * sf_buf_alloc(struct vm_page *m, int flags) { #ifdef ARM_USE_SMALL_ALLOC return ((struct sf_buf *)m); #else struct sf_head *hash_list; struct sf_buf *sf; int error; hash_list = &sf_buf_active[SF_BUF_HASH(m)]; mtx_lock(&sf_buf_lock); LIST_FOREACH(sf, hash_list, list_entry) { if (sf->m == m) { sf->ref_count++; if (sf->ref_count == 1) { TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); nsfbufsused++; nsfbufspeak = imax(nsfbufspeak, nsfbufsused); } goto done; } } while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { if (flags & SFB_NOWAIT) goto done; sf_buf_alloc_want++; mbstat.sf_allocwait++; error = msleep(&sf_buf_freelist, &sf_buf_lock, (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0); sf_buf_alloc_want--; /* * If we got a signal, don't risk going back to sleep. */ if (error) goto done; } TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry); if (sf->m != NULL) LIST_REMOVE(sf, list_entry); LIST_INSERT_HEAD(hash_list, sf, list_entry); sf->ref_count = 1; sf->m = m; nsfbufsused++; nsfbufspeak = imax(nsfbufspeak, nsfbufsused); pmap_kenter(sf->kva, VM_PAGE_TO_PHYS(sf->m)); done: mtx_unlock(&sf_buf_lock); return (sf); #endif } void cpu_set_syscall_retval(struct thread *td, int error) { trapframe_t *frame; int fixup; #ifdef __ARMEB__ uint32_t insn; #endif frame = td->td_frame; fixup = 0; #ifdef __ARMEB__ insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE); if ((insn & 0x000fffff) == SYS___syscall) { register_t *ap = &frame->tf_r0; register_t code = ap[_QUAD_LOWWORD]; if (td->td_proc->p_sysent->sv_mask) code &= td->td_proc->p_sysent->sv_mask; fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ? 1 : 0; } #endif switch (error) { case 0: if (fixup) { frame->tf_r0 = 0; frame->tf_r1 = td->td_retval[0]; } else { frame->tf_r0 = td->td_retval[0]; frame->tf_r1 = td->td_retval[1]; } frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ break; case ERESTART: /* * Reconstruct the pc to point at the swi. */ frame->tf_pc -= INSN_SIZE; break; case EJUSTRETURN: /* nothing to do */ break; default: frame->tf_r0 = error; frame->tf_spsr |= PSR_C_bit; /* carry bit */ break; } } /* * Initialize machine state (pcb and trap frame) for a new thread about to * upcall. Put enough state in the new thread's PCB to get it to go back * userret(), where we can intercept it again to set the return (upcall) * Address and stack, along with those from upcals that are from other sources * such as those generated in thread_userret() itself. */ void cpu_set_upcall(struct thread *td, struct thread *td0) { struct trapframe *tf; struct switchframe *sf; bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb)); tf = td->td_frame; sf = (struct switchframe *)tf - 1; sf->sf_r4 = (u_int)fork_return; sf->sf_r5 = (u_int)td; sf->sf_pc = (u_int)fork_trampoline; tf->tf_spsr &= ~PSR_C_bit; tf->tf_r0 = 0; td->td_pcb->un_32.pcb32_sp = (u_int)sf; td->td_pcb->un_32.pcb32_und_sp = td->td_kstack + USPACE_UNDEF_STACK_TOP; /* Setup to release spin count in fork_exit(). */ td->td_md.md_spinlock_count = 1; td->td_md.md_saved_cspr = 0; } /* * Set that machine state for performing an upcall that has to * be done in thread_userret() so that those upcalls generated * in thread_userret() itself can be done as well. */ void cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, stack_t *stack) { struct trapframe *tf = td->td_frame; - tf->tf_usr_sp = ((int)stack->ss_sp + stack->ss_size - - sizeof(struct trapframe)) & ~7; + tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size + - sizeof(struct trapframe)); tf->tf_pc = (int)entry; tf->tf_r0 = (int)arg; tf->tf_spsr = PSR_USR32_MODE; } int cpu_set_user_tls(struct thread *td, void *tls_base) { td->td_md.md_tp = (register_t)tls_base; if (td == curthread) { critical_enter(); #ifdef ARM_TP_ADDRESS *(register_t *)ARM_TP_ADDRESS = (register_t)tls_base; #else set_tls((void *)tls_base); #endif critical_exit(); } return (0); } void cpu_thread_exit(struct thread *td) { } void cpu_thread_alloc(struct thread *td) { td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE) - 1; - td->td_frame = (struct trapframe *) - ((u_int)td->td_kstack + USPACE_SVC_STACK_TOP - sizeof(struct pcb)) - 1; /* * Ensure td_frame is aligned to an 8 byte boundary as it will be * placed into the stack pointer which must be 8 byte aligned in * the ARM EABI. */ - td->td_frame = (struct trapframe *)((u_int)td->td_frame & ~7); + td->td_frame = (struct trapframe *)STACKALIGN((u_int)td->td_kstack + + USPACE_SVC_STACK_TOP - sizeof(struct pcb) - 1); #ifdef __XSCALE__ #ifndef CPU_XSCALE_CORE3 pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE); #endif #endif } void cpu_thread_free(struct thread *td) { } void cpu_thread_clean(struct thread *td) { } /* * Intercept the return address from a freshly forked process that has NOT * been scheduled yet. * * This is needed to make kernel threads stay in kernel mode. */ void cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg) { struct switchframe *sf; struct trapframe *tf; tf = td->td_frame; sf = (struct switchframe *)tf - 1; sf->sf_r4 = (u_int)func; sf->sf_r5 = (u_int)arg; td->td_pcb->un_32.pcb32_sp = (u_int)sf; } /* * Software interrupt handler for queued VM system processing. */ void swi_vm(void *dummy) { if (busdma_swi_pending) busdma_swi(); } void cpu_exit(struct thread *td) { } #define BITS_PER_INT (8 * sizeof(int)) vm_offset_t arm_nocache_startaddr; static int arm_nocache_allocated[ARM_NOCACHE_KVA_SIZE / (PAGE_SIZE * BITS_PER_INT)]; /* * Functions to map and unmap memory non-cached into KVA the kernel won't try * to allocate. The goal is to provide uncached memory to busdma, to honor * BUS_DMA_COHERENT. * We can allocate at most ARM_NOCACHE_KVA_SIZE bytes. * The allocator is rather dummy, each page is represented by a bit in * a bitfield, 0 meaning the page is not allocated, 1 meaning it is. * As soon as it finds enough contiguous pages to satisfy the request, * it returns the address. */ void * arm_remap_nocache(void *addr, vm_size_t size) { int i, j; size = round_page(size); for (i = 0; i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE; i++) { if (!(arm_nocache_allocated[i / BITS_PER_INT] & (1 << (i % BITS_PER_INT)))) { for (j = i; j < i + (size / (PAGE_SIZE)); j++) if (arm_nocache_allocated[j / BITS_PER_INT] & (1 << (j % BITS_PER_INT))) break; if (j == i + (size / (PAGE_SIZE))) break; } } if (i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE) { vm_offset_t tomap = arm_nocache_startaddr + i * PAGE_SIZE; void *ret = (void *)tomap; vm_paddr_t physaddr = vtophys((vm_offset_t)addr); vm_offset_t vaddr = (vm_offset_t) addr; vaddr = vaddr & ~PAGE_MASK; for (; tomap < (vm_offset_t)ret + size; tomap += PAGE_SIZE, vaddr += PAGE_SIZE, physaddr += PAGE_SIZE, i++) { cpu_idcache_wbinv_range(vaddr, PAGE_SIZE); #ifdef ARM_L2_PIPT cpu_l2cache_wbinv_range(physaddr, PAGE_SIZE); #else cpu_l2cache_wbinv_range(vaddr, PAGE_SIZE); #endif pmap_kenter_nocache(tomap, physaddr); cpu_tlb_flushID_SE(vaddr); arm_nocache_allocated[i / BITS_PER_INT] |= 1 << (i % BITS_PER_INT); } return (ret); } return (NULL); } void arm_unmap_nocache(void *addr, vm_size_t size) { vm_offset_t raddr = (vm_offset_t)addr; int i; size = round_page(size); i = (raddr - arm_nocache_startaddr) / (PAGE_SIZE); for (; size > 0; size -= PAGE_SIZE, i++) { arm_nocache_allocated[i / BITS_PER_INT] &= ~(1 << (i % BITS_PER_INT)); pmap_kremove(raddr); raddr += PAGE_SIZE; } } #ifdef ARM_USE_SMALL_ALLOC static TAILQ_HEAD(,arm_small_page) pages_normal = TAILQ_HEAD_INITIALIZER(pages_normal); static TAILQ_HEAD(,arm_small_page) pages_wt = TAILQ_HEAD_INITIALIZER(pages_wt); static TAILQ_HEAD(,arm_small_page) free_pgdesc = TAILQ_HEAD_INITIALIZER(free_pgdesc); extern uma_zone_t l2zone; struct mtx smallalloc_mtx; vm_offset_t alloc_firstaddr; #ifdef ARM_HAVE_SUPERSECTIONS #define S_FRAME L1_SUP_FRAME #define S_SIZE L1_SUP_SIZE #else #define S_FRAME L1_S_FRAME #define S_SIZE L1_S_SIZE #endif vm_offset_t arm_ptovirt(vm_paddr_t pa) { int i; vm_offset_t addr = alloc_firstaddr; KASSERT(alloc_firstaddr != 0, ("arm_ptovirt called too early ?")); for (i = 0; dump_avail[i + 1]; i += 2) { if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) break; addr += (dump_avail[i + 1] & S_FRAME) + S_SIZE - (dump_avail[i] & S_FRAME); } KASSERT(dump_avail[i + 1] != 0, ("Trying to access invalid physical address")); return (addr + (pa - (dump_avail[i] & S_FRAME))); } void arm_init_smallalloc(void) { vm_offset_t to_map = 0, mapaddr; int i; /* * We need to use dump_avail and not phys_avail, since we want to * map the whole memory and not just the memory available to the VM * to be able to do a pa => va association for any address. */ for (i = 0; dump_avail[i + 1]; i+= 2) { to_map += (dump_avail[i + 1] & S_FRAME) + S_SIZE - (dump_avail[i] & S_FRAME); } alloc_firstaddr = mapaddr = KERNBASE - to_map; for (i = 0; dump_avail[i + 1]; i+= 2) { vm_offset_t size = (dump_avail[i + 1] & S_FRAME) + S_SIZE - (dump_avail[i] & S_FRAME); vm_offset_t did = 0; while (size > 0) { #ifdef ARM_HAVE_SUPERSECTIONS pmap_kenter_supersection(mapaddr, (dump_avail[i] & L1_SUP_FRAME) + did, SECTION_CACHE); #else pmap_kenter_section(mapaddr, (dump_avail[i] & L1_S_FRAME) + did, SECTION_CACHE); #endif mapaddr += S_SIZE; did += S_SIZE; size -= S_SIZE; } } } void arm_add_smallalloc_pages(void *list, void *mem, int bytes, int pagetable) { struct arm_small_page *pg; bytes &= ~PAGE_MASK; while (bytes > 0) { pg = (struct arm_small_page *)list; pg->addr = mem; if (pagetable) TAILQ_INSERT_HEAD(&pages_wt, pg, pg_list); else TAILQ_INSERT_HEAD(&pages_normal, pg, pg_list); list = (char *)list + sizeof(*pg); mem = (char *)mem + PAGE_SIZE; bytes -= PAGE_SIZE; } } void * uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) { void *ret; struct arm_small_page *sp; TAILQ_HEAD(,arm_small_page) *head; vm_page_t m; *flags = UMA_SLAB_PRIV; /* * For CPUs where we setup page tables as write back, there's no * need to maintain two separate pools. */ if (zone == l2zone && pte_l1_s_cache_mode != pte_l1_s_cache_mode_pt) head = (void *)&pages_wt; else head = (void *)&pages_normal; mtx_lock(&smallalloc_mtx); sp = TAILQ_FIRST(head); if (!sp) { int pflags; mtx_unlock(&smallalloc_mtx); if (zone == l2zone && pte_l1_s_cache_mode != pte_l1_s_cache_mode_pt) { *flags = UMA_SLAB_KMEM; ret = ((void *)kmem_malloc(kmem_map, bytes, M_NOWAIT)); return (ret); } pflags = malloc2vm_flags(wait) | VM_ALLOC_WIRED; for (;;) { m = vm_page_alloc(NULL, 0, pflags | VM_ALLOC_NOOBJ); if (m == NULL) { if (wait & M_NOWAIT) return (NULL); VM_WAIT; } else break; } ret = (void *)arm_ptovirt(VM_PAGE_TO_PHYS(m)); if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) bzero(ret, PAGE_SIZE); return (ret); } TAILQ_REMOVE(head, sp, pg_list); TAILQ_INSERT_HEAD(&free_pgdesc, sp, pg_list); ret = sp->addr; mtx_unlock(&smallalloc_mtx); if ((wait & M_ZERO)) bzero(ret, bytes); return (ret); } void uma_small_free(void *mem, int size, u_int8_t flags) { pd_entry_t *pd; pt_entry_t *pt; if (flags & UMA_SLAB_KMEM) kmem_free(kmem_map, (vm_offset_t)mem, size); else { struct arm_small_page *sp; if ((vm_offset_t)mem >= KERNBASE) { mtx_lock(&smallalloc_mtx); sp = TAILQ_FIRST(&free_pgdesc); KASSERT(sp != NULL, ("No more free page descriptor ?")); TAILQ_REMOVE(&free_pgdesc, sp, pg_list); sp->addr = mem; pmap_get_pde_pte(kernel_pmap, (vm_offset_t)mem, &pd, &pt); if ((*pd & pte_l1_s_cache_mask) == pte_l1_s_cache_mode_pt && pte_l1_s_cache_mode_pt != pte_l1_s_cache_mode) TAILQ_INSERT_HEAD(&pages_wt, sp, pg_list); else TAILQ_INSERT_HEAD(&pages_normal, sp, pg_list); mtx_unlock(&smallalloc_mtx); } else { vm_page_t m; vm_paddr_t pa = vtophys((vm_offset_t)mem); m = PHYS_TO_VM_PAGE(pa); m->wire_count--; vm_page_free(m); atomic_subtract_int(&cnt.v_wire_count, 1); } } } #endif Index: user/attilio/vmc-playground/sys/dev/uart/uart_bus_pci.c =================================================================== --- user/attilio/vmc-playground/sys/dev/uart/uart_bus_pci.c (revision 246333) +++ user/attilio/vmc-playground/sys/dev/uart/uart_bus_pci.c (revision 246334) @@ -1,181 +1,181 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * Copyright (c) 2001 M. Warner Losh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_RCLK 1843200 static int uart_pci_probe(device_t dev); static device_method_t uart_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_pci_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_pci_driver = { uart_driver_name, uart_pci_methods, sizeof(struct uart_softc), }; struct pci_id { uint16_t vendor; uint16_t device; uint16_t subven; uint16_t subdev; const char *desc; int rid; int rclk; }; -static struct pci_id pci_ns8250_ids[] = { +static const struct pci_id pci_ns8250_ids[] = { { 0x1028, 0x0008, 0xffff, 0, "Dell Remote Access Card III", 0x14, 128 * DEFAULT_RCLK }, { 0x1028, 0x0012, 0xffff, 0, "Dell RAC 4 Daughter Card Virtual UART", 0x14, 128 * DEFAULT_RCLK }, { 0x1033, 0x0074, 0x1033, 0x8014, "NEC RCV56ACF 56k Voice Modem", 0x10 }, { 0x1033, 0x007d, 0x1033, 0x8012, "NEC RS232C", 0x10 }, { 0x103c, 0x1048, 0x103c, 0x1227, "HP Diva Serial [GSP] UART - Powerbar SP2", 0x10 }, { 0x103c, 0x1048, 0x103c, 0x1301, "HP Diva RMP3", 0x14 }, { 0x103c, 0x1290, 0xffff, 0, "HP Auxiliary Diva Serial Port", 0x18 }, { 0x11c1, 0x0480, 0xffff, 0, "Agere Systems Venus Modem (V90, 56KFlex)", 0x14 }, { 0x115d, 0x0103, 0xffff, 0, "Xircom Cardbus Ethernet + 56k Modem", 0x10 }, { 0x1282, 0x6585, 0xffff, 0, "Davicom 56PDV PCI Modem", 0x10 }, { 0x12b9, 0x1008, 0xffff, 0, "3Com 56K FaxModem Model 5610", 0x10 }, { 0x131f, 0x1000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x18 }, { 0x131f, 0x1001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x18 }, { 0x131f, 0x1002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x18 }, { 0x131f, 0x2000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x10 }, { 0x131f, 0x2001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x10 }, { 0x131f, 0x2002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x10 }, { 0x135c, 0x0190, 0xffff, 0, "Quatech SSCLP-100", 0x18 }, { 0x135c, 0x01c0, 0xffff, 0, "Quatech SSCLP-200/300", 0x18 }, { 0x135e, 0x7101, 0xffff, 0, "Sealevel Systems Single Port RS-232/422/485/530", 0x18 }, { 0x1407, 0x0110, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port A", 0x10 }, { 0x1407, 0x0111, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port B", 0x10 }, { 0x1407, 0x0510, 0xffff, 0, "Lava SP Serial 550 PCI", 0x10 }, { 0x1409, 0x7168, 0x1409, 0x4025, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x4027, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x4028, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x5025, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x5027, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1415, 0x950b, 0xffff, 0, "Oxford Semiconductor OXCB950 Cardbus 16950 UART", 0x10, 16384000 }, { 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10}, { 0x151f, 0x0000, 0xffff, 0, "TOPIC Semiconductor TP560 56k modem", 0x10 }, { 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 }, { 0x8086, 0x2e17, 0xffff, 0, "4 Series Chipset Serial KT Controller", 0x10 }, { 0x8086, 0x3b67, 0xffff, 0, "5 Series/3400 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x8811, 0xffff, 0, "Intel EG20T Serial Port 0", 0x10 }, { 0x8086, 0x8812, 0xffff, 0, "Intel EG20T Serial Port 1", 0x10 }, { 0x8086, 0x8813, 0xffff, 0, "Intel EG20T Serial Port 2", 0x10 }, { 0x8086, 0x8814, 0xffff, 0, "Intel EG20T Serial Port 3", 0x10 }, { 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 }, { 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 }, { 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 }, { 0x9710, 0x9900, 0xa000, 0x1000, "MosChip MCS9900 PCIe to Peripheral Controller", 0x10 }, { 0x9710, 0x9901, 0xa000, 0x1000, "MosChip MCS9901 PCIe to Peripheral Controller", 0x10 }, { 0x9710, 0x9904, 0xa000, 0x1000, "MosChip MCS9904 PCIe to Peripheral Controller", 0x10 }, { 0xdeaf, 0x9051, 0xffff, 0, "Middle Digital PC Weasel Serial Port", 0x10 }, { 0xffff, 0, 0xffff, 0, NULL, 0, 0} }; -static struct pci_id * -uart_pci_match(device_t dev, struct pci_id *id) +const static struct pci_id * +uart_pci_match(device_t dev, const struct pci_id *id) { uint16_t device, subdev, subven, vendor; vendor = pci_get_vendor(dev); device = pci_get_device(dev); while (id->vendor != 0xffff && (id->vendor != vendor || id->device != device)) id++; if (id->vendor == 0xffff) return (NULL); if (id->subven == 0xffff) return (id); subven = pci_get_subvendor(dev); subdev = pci_get_subdevice(dev); while (id->vendor == vendor && id->device == device && (id->subven != subven || id->subdev != subdev)) id++; return ((id->vendor == vendor && id->device == device) ? id : NULL); } static int uart_pci_probe(device_t dev) { struct uart_softc *sc; - struct pci_id *id; + const struct pci_id *id; sc = device_get_softc(dev); id = uart_pci_match(dev, pci_ns8250_ids); if (id != NULL) { sc->sc_class = &uart_ns8250_class; goto match; } /* Add checks for non-ns8250 IDs here. */ return (ENXIO); match: if (id->desc) device_set_desc(dev, id->desc); return (uart_bus_probe(dev, 0, id->rclk, id->rid, 0)); } -DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, 0, 0); +DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL); Index: user/attilio/vmc-playground/sys/kern/kern_ktr.c =================================================================== --- user/attilio/vmc-playground/sys/kern/kern_ktr.c (revision 246333) +++ user/attilio/vmc-playground/sys/kern/kern_ktr.c (revision 246334) @@ -1,490 +1,491 @@ /*- * Copyright (c) 2000 John Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * This module holds the global variables used by KTR and the ktr_tracepoint() * function that does the actual tracing. */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_ktr.h" #include "opt_alq.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __sparc64__ #include #endif #ifdef DDB #include #include #endif #ifndef KTR_BOOT_ENTRIES #define KTR_BOOT_ENTRIES 1024 #endif #ifndef KTR_ENTRIES #define KTR_ENTRIES 1024 #endif /* Limit the allocations to something manageable. */ #define KTR_ENTRIES_MAX (8 * 1024 * 1024) #ifndef KTR_MASK #define KTR_MASK (0) #endif #ifndef KTR_CPUMASK #define KTR_CPUMASK CPUSET_FSET #endif #ifndef KTR_TIME #define KTR_TIME get_cyclecount() #endif #ifndef KTR_CPU #define KTR_CPU PCPU_GET(cpuid) #endif static MALLOC_DEFINE(M_KTR, "KTR", "KTR"); FEATURE(ktr, "Kernel support for KTR kernel tracing facility"); volatile int ktr_idx = 0; int ktr_mask = KTR_MASK; int ktr_compile = KTR_COMPILE; int ktr_entries = KTR_BOOT_ENTRIES; int ktr_version = KTR_VERSION; struct ktr_entry ktr_buf_init[KTR_BOOT_ENTRIES]; struct ktr_entry *ktr_buf = ktr_buf_init; cpuset_t ktr_cpumask = CPUSET_T_INITIALIZER(KTR_CPUMASK); static char ktr_cpumask_str[CPUSETBUFSIZ]; TUNABLE_INT("debug.ktr.mask", &ktr_mask); TUNABLE_STR("debug.ktr.cpumask", ktr_cpumask_str, sizeof(ktr_cpumask_str)); static SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options"); SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, "Version of the KTR interface"); SYSCTL_UINT(_debug_ktr, OID_AUTO, compile, CTLFLAG_RD, &ktr_compile, 0, "Bitmask of KTR event classes compiled into the kernel"); static void ktr_cpumask_initializer(void *dummy __unused) { /* * TUNABLE_STR() runs with SI_ORDER_MIDDLE priority, thus it must be * already set, if necessary. */ if (ktr_cpumask_str[0] != '\0' && cpusetobj_strscan(&ktr_cpumask, ktr_cpumask_str) == -1) CPU_FILL(&ktr_cpumask); } SYSINIT(ktr_cpumask_initializer, SI_SUB_TUNABLES, SI_ORDER_ANY, ktr_cpumask_initializer, NULL); static int sysctl_debug_ktr_cpumask(SYSCTL_HANDLER_ARGS) { char lktr_cpumask_str[CPUSETBUFSIZ]; cpuset_t imask; int error; cpusetobj_strprint(lktr_cpumask_str, &ktr_cpumask); error = sysctl_handle_string(oidp, lktr_cpumask_str, sizeof(lktr_cpumask_str), req); if (error != 0 || req->newptr == NULL) return (error); if (cpusetobj_strscan(&imask, lktr_cpumask_str) == -1) return (EINVAL); CPU_COPY(&imask, &ktr_cpumask); return (error); } SYSCTL_PROC(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW | CTLFLAG_MPSAFE | CTLTYPE_STRING, NULL, 0, sysctl_debug_ktr_cpumask, "S", "Bitmask of CPUs on which KTR logging is enabled"); static int sysctl_debug_ktr_clear(SYSCTL_HANDLER_ARGS) { int clear, error; clear = 0; error = sysctl_handle_int(oidp, &clear, 0, req); if (error || !req->newptr) return (error); if (clear) { bzero(ktr_buf, sizeof(*ktr_buf) * ktr_entries); ktr_idx = 0; } return (error); } SYSCTL_PROC(_debug_ktr, OID_AUTO, clear, CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_clear, "I", "Clear KTR Buffer"); /* * This is a sysctl proc so that it is serialized as !MPSAFE along with * the other ktr sysctl procs. */ static int sysctl_debug_ktr_mask(SYSCTL_HANDLER_ARGS) { int mask, error; mask = ktr_mask; error = sysctl_handle_int(oidp, &mask, 0, req); if (error || !req->newptr) return (error); ktr_mask = mask; return (error); } SYSCTL_PROC(_debug_ktr, OID_AUTO, mask, CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_mask, "IU", "Bitmask of KTR event classes for which logging is enabled"); -#if KTR_ENTRIES != KTR_BOOT_ENTRIES +#if KTR_ENTRIES > KTR_BOOT_ENTRIES /* * A simplified version of sysctl_debug_ktr_entries. * No need to care about SMP, scheduling, etc. */ static void ktr_entries_initializer(void *dummy __unused) { int mask; /* Temporarily disable ktr in case malloc() is being traced. */ mask = ktr_mask; ktr_mask = 0; ktr_buf = malloc(sizeof(*ktr_buf) * KTR_ENTRIES, M_KTR, M_WAITOK | M_ZERO); + memcpy(ktr_buf, ktr_buf_init, sizeof(ktr_buf_init)); ktr_entries = KTR_ENTRIES; ktr_mask = mask; } SYSINIT(ktr_entries_initializer, SI_SUB_KMEM, SI_ORDER_ANY, ktr_entries_initializer, NULL); #endif static int sysctl_debug_ktr_entries(SYSCTL_HANDLER_ARGS) { int entries, error, mask; struct ktr_entry *buf, *oldbuf; entries = ktr_entries; error = sysctl_handle_int(oidp, &entries, 0, req); if (error || !req->newptr) return (error); if (entries > KTR_ENTRIES_MAX) return (ERANGE); /* Disable ktr temporarily. */ mask = ktr_mask; atomic_store_rel_int(&ktr_mask, 0); /* Wait for threads to go idle. */ if ((error = quiesce_all_cpus("ktrent", PCATCH)) != 0) { ktr_mask = mask; return (error); } if (ktr_buf != ktr_buf_init) oldbuf = ktr_buf; else oldbuf = NULL; /* Allocate a new buffer. */ buf = malloc(sizeof(*buf) * entries, M_KTR, M_WAITOK | M_ZERO); /* Install the new buffer and restart ktr. */ ktr_buf = buf; ktr_entries = entries; ktr_idx = 0; atomic_store_rel_int(&ktr_mask, mask); if (oldbuf != NULL) free(oldbuf, M_KTR); return (error); } SYSCTL_PROC(_debug_ktr, OID_AUTO, entries, CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_entries, "I", "Number of entries in the KTR buffer"); #ifdef KTR_VERBOSE int ktr_verbose = KTR_VERBOSE; TUNABLE_INT("debug.ktr.verbose", &ktr_verbose); SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, ""); #endif #ifdef KTR_ALQ struct alq *ktr_alq; char ktr_alq_file[MAXPATHLEN] = "/tmp/ktr.out"; int ktr_alq_cnt = 0; int ktr_alq_depth = KTR_ENTRIES; int ktr_alq_enabled = 0; int ktr_alq_failed = 0; int ktr_alq_max = 0; SYSCTL_INT(_debug_ktr, OID_AUTO, alq_max, CTLFLAG_RW, &ktr_alq_max, 0, "Maximum number of entries to write"); SYSCTL_INT(_debug_ktr, OID_AUTO, alq_cnt, CTLFLAG_RD, &ktr_alq_cnt, 0, "Current number of written entries"); SYSCTL_INT(_debug_ktr, OID_AUTO, alq_failed, CTLFLAG_RD, &ktr_alq_failed, 0, "Number of times we overran the buffer"); SYSCTL_INT(_debug_ktr, OID_AUTO, alq_depth, CTLFLAG_RW, &ktr_alq_depth, 0, "Number of items in the write buffer"); SYSCTL_STRING(_debug_ktr, OID_AUTO, alq_file, CTLFLAG_RW, ktr_alq_file, sizeof(ktr_alq_file), "KTR logging file"); static int sysctl_debug_ktr_alq_enable(SYSCTL_HANDLER_ARGS) { int error; int enable; enable = ktr_alq_enabled; error = sysctl_handle_int(oidp, &enable, 0, req); if (error || !req->newptr) return (error); if (enable) { if (ktr_alq_enabled) return (0); error = alq_open(&ktr_alq, (const char *)ktr_alq_file, req->td->td_ucred, ALQ_DEFAULT_CMODE, sizeof(struct ktr_entry), ktr_alq_depth); if (error == 0) { ktr_alq_cnt = 0; ktr_alq_failed = 0; ktr_alq_enabled = 1; } } else { if (ktr_alq_enabled == 0) return (0); ktr_alq_enabled = 0; alq_close(ktr_alq); ktr_alq = NULL; } return (error); } SYSCTL_PROC(_debug_ktr, OID_AUTO, alq_enable, CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_alq_enable, "I", "Enable KTR logging"); #endif void ktr_tracepoint(u_int mask, const char *file, int line, const char *format, u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5, u_long arg6) { struct ktr_entry *entry; #ifdef KTR_ALQ struct ale *ale = NULL; #endif int newindex, saveindex; #if defined(KTR_VERBOSE) || defined(KTR_ALQ) struct thread *td; #endif int cpu; if (panicstr) return; if ((ktr_mask & mask) == 0 || ktr_buf == NULL) return; cpu = KTR_CPU; if (!CPU_ISSET(cpu, &ktr_cpumask)) return; #if defined(KTR_VERBOSE) || defined(KTR_ALQ) td = curthread; if (td->td_pflags & TDP_INKTR) return; td->td_pflags |= TDP_INKTR; #endif #ifdef KTR_ALQ if (ktr_alq_enabled) { if (td->td_critnest == 0 && (td->td_flags & TDF_IDLETD) == 0 && td != ald_thread) { if (ktr_alq_max && ktr_alq_cnt > ktr_alq_max) goto done; if ((ale = alq_get(ktr_alq, ALQ_NOWAIT)) == NULL) { ktr_alq_failed++; goto done; } ktr_alq_cnt++; entry = (struct ktr_entry *)ale->ae_data; } else { goto done; } } else #endif { do { saveindex = ktr_idx; newindex = (saveindex + 1) % ktr_entries; } while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0); entry = &ktr_buf[saveindex]; } entry->ktr_timestamp = KTR_TIME; entry->ktr_cpu = cpu; entry->ktr_thread = curthread; if (file != NULL) while (strncmp(file, "../", 3) == 0) file += 3; entry->ktr_file = file; entry->ktr_line = line; #ifdef KTR_VERBOSE if (ktr_verbose) { #ifdef SMP printf("cpu%d ", cpu); #endif if (ktr_verbose > 1) { printf("%s.%d\t", entry->ktr_file, entry->ktr_line); } printf(format, arg1, arg2, arg3, arg4, arg5, arg6); printf("\n"); } #endif entry->ktr_desc = format; entry->ktr_parms[0] = arg1; entry->ktr_parms[1] = arg2; entry->ktr_parms[2] = arg3; entry->ktr_parms[3] = arg4; entry->ktr_parms[4] = arg5; entry->ktr_parms[5] = arg6; #ifdef KTR_ALQ if (ktr_alq_enabled && ale) alq_post(ktr_alq, ale); done: #endif #if defined(KTR_VERBOSE) || defined(KTR_ALQ) td->td_pflags &= ~TDP_INKTR; #endif } #ifdef DDB struct tstate { int cur; int first; }; static struct tstate tstate; static int db_ktr_verbose; static int db_mach_vtrace(void); DB_SHOW_COMMAND(ktr, db_ktr_all) { tstate.cur = (ktr_idx - 1) % ktr_entries; tstate.first = -1; db_ktr_verbose = 0; db_ktr_verbose |= (strchr(modif, 'v') != NULL) ? 2 : 0; db_ktr_verbose |= (strchr(modif, 'V') != NULL) ? 1 : 0; /* just timestap please */ if (strchr(modif, 'a') != NULL) { db_disable_pager(); while (cncheckc() != -1) if (db_mach_vtrace() == 0) break; } else { while (!db_pager_quit) if (db_mach_vtrace() == 0) break; } } static int db_mach_vtrace(void) { struct ktr_entry *kp; if (tstate.cur == tstate.first || ktr_buf == NULL) { db_printf("--- End of trace buffer ---\n"); return (0); } kp = &ktr_buf[tstate.cur]; /* Skip over unused entries. */ if (kp->ktr_desc == NULL) { db_printf("--- End of trace buffer ---\n"); return (0); } db_printf("%d (%p", tstate.cur, kp->ktr_thread); #ifdef SMP db_printf(":cpu%d", kp->ktr_cpu); #endif db_printf(")"); if (db_ktr_verbose >= 1) { db_printf(" %10.10lld", (long long)kp->ktr_timestamp); } if (db_ktr_verbose >= 2) { db_printf(" %s.%d", kp->ktr_file, kp->ktr_line); } db_printf(": "); db_printf(kp->ktr_desc, kp->ktr_parms[0], kp->ktr_parms[1], kp->ktr_parms[2], kp->ktr_parms[3], kp->ktr_parms[4], kp->ktr_parms[5]); db_printf("\n"); if (tstate.first == -1) tstate.first = tstate.cur; if (--tstate.cur < 0) tstate.cur = ktr_entries - 1; return (1); } #endif /* DDB */ Index: user/attilio/vmc-playground/sys/kern/kern_malloc.c =================================================================== --- user/attilio/vmc-playground/sys/kern/kern_malloc.c (revision 246333) +++ user/attilio/vmc-playground/sys/kern/kern_malloc.c (revision 246334) @@ -1,1096 +1,1085 @@ /*- * Copyright (c) 1987, 1991, 1993 * The Regents of the University of California. * Copyright (c) 2005-2009 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 */ /* * Kernel malloc(9) implementation -- general purpose kernel memory allocator * based on memory types. Back end is implemented using the UMA(9) zone * allocator. A set of fixed-size buckets are used for smaller allocations, * and a special UMA allocation interface is used for larger allocations. * Callers declare memory types, and statistics are maintained independently * for each memory type. Statistics are maintained per-CPU for performance * reasons. See malloc(9) and comments in malloc.h for a detailed * description. */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_kdtrace.h" #include "opt_vm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG_MEMGUARD #include #endif #ifdef DEBUG_REDZONE #include #endif #if defined(INVARIANTS) && defined(__i386__) #include #endif #include #ifdef KDTRACE_HOOKS #include dtrace_malloc_probe_func_t dtrace_malloc_probe; #endif /* * When realloc() is called, if the new size is sufficiently smaller than * the old size, realloc() will allocate a new, smaller block to avoid * wasting memory. 'Sufficiently smaller' is defined as: newsize <= * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. */ #ifndef REALLOC_FRACTION #define REALLOC_FRACTION 1 /* new block if <= half the size */ #endif /* * Centrally define some common malloc types. */ MALLOC_DEFINE(M_CACHE, "cache", "Various Dynamically allocated caches"); MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers"); MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options"); MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery"); static void kmeminit(void *); SYSINIT(kmem, SI_SUB_KMEM, SI_ORDER_FIRST, kmeminit, NULL); static MALLOC_DEFINE(M_FREE, "free", "should be on free list"); static struct malloc_type *kmemstatistics; static vm_offset_t kmembase; static vm_offset_t kmemlimit; static int kmemcount; #define KMEM_ZSHIFT 4 #define KMEM_ZBASE 16 #define KMEM_ZMASK (KMEM_ZBASE - 1) #define KMEM_ZMAX PAGE_SIZE #define KMEM_ZSIZE (KMEM_ZMAX >> KMEM_ZSHIFT) static uint8_t kmemsize[KMEM_ZSIZE + 1]; #ifndef MALLOC_DEBUG_MAXZONES #define MALLOC_DEBUG_MAXZONES 1 #endif static int numzones = MALLOC_DEBUG_MAXZONES; /* * Small malloc(9) memory allocations are allocated from a set of UMA buckets * of various sizes. * * XXX: The comment here used to read "These won't be powers of two for * long." It's possible that a significant amount of wasted memory could be * recovered by tuning the sizes of these buckets. */ struct { int kz_size; char *kz_name; uma_zone_t kz_zone[MALLOC_DEBUG_MAXZONES]; } kmemzones[] = { {16, "16", }, {32, "32", }, {64, "64", }, {128, "128", }, {256, "256", }, {512, "512", }, {1024, "1024", }, {2048, "2048", }, {4096, "4096", }, #if PAGE_SIZE > 4096 {8192, "8192", }, #if PAGE_SIZE > 8192 {16384, "16384", }, #if PAGE_SIZE > 16384 {32768, "32768", }, #if PAGE_SIZE > 32768 {65536, "65536", }, #if PAGE_SIZE > 65536 #error "Unsupported PAGE_SIZE" #endif /* 65536 */ #endif /* 32768 */ #endif /* 16384 */ #endif /* 8192 */ #endif /* 4096 */ {0, NULL}, }; /* * Zone to allocate malloc type descriptions from. For ABI reasons, memory * types are described by a data structure passed by the declaring code, but * the malloc(9) implementation has its own data structure describing the * type and statistics. This permits the malloc(9)-internal data structures * to be modified without breaking binary-compiled kernel modules that * declare malloc types. */ static uma_zone_t mt_zone; -static vm_offset_t vm_min_kernel_address = VM_MIN_KERNEL_ADDRESS; -SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, - &vm_min_kernel_address, 0, "Min kernel address"); - -#ifndef __sparc64__ -static vm_offset_t vm_max_kernel_address = VM_MAX_KERNEL_ADDRESS; -#endif -SYSCTL_ULONG(_vm, OID_AUTO, max_kernel_address, CTLFLAG_RD, - &vm_max_kernel_address, 0, "Max kernel address"); - u_long vm_kmem_size; SYSCTL_ULONG(_vm, OID_AUTO, kmem_size, CTLFLAG_RDTUN, &vm_kmem_size, 0, "Size of kernel memory"); static u_long vm_kmem_size_min; SYSCTL_ULONG(_vm, OID_AUTO, kmem_size_min, CTLFLAG_RDTUN, &vm_kmem_size_min, 0, "Minimum size of kernel memory"); static u_long vm_kmem_size_max; SYSCTL_ULONG(_vm, OID_AUTO, kmem_size_max, CTLFLAG_RDTUN, &vm_kmem_size_max, 0, "Maximum size of kernel memory"); static u_int vm_kmem_size_scale; SYSCTL_UINT(_vm, OID_AUTO, kmem_size_scale, CTLFLAG_RDTUN, &vm_kmem_size_scale, 0, "Scale factor for kernel memory size"); static int sysctl_kmem_map_size(SYSCTL_HANDLER_ARGS); SYSCTL_PROC(_vm, OID_AUTO, kmem_map_size, CTLFLAG_RD | CTLTYPE_ULONG | CTLFLAG_MPSAFE, NULL, 0, sysctl_kmem_map_size, "LU", "Current kmem_map allocation size"); static int sysctl_kmem_map_free(SYSCTL_HANDLER_ARGS); SYSCTL_PROC(_vm, OID_AUTO, kmem_map_free, CTLFLAG_RD | CTLTYPE_ULONG | CTLFLAG_MPSAFE, NULL, 0, sysctl_kmem_map_free, "LU", "Largest contiguous free range in kmem_map"); /* * The malloc_mtx protects the kmemstatistics linked list. */ struct mtx malloc_mtx; #ifdef MALLOC_PROFILE uint64_t krequests[KMEM_ZSIZE + 1]; static int sysctl_kern_mprof(SYSCTL_HANDLER_ARGS); #endif static int sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS); /* * time_uptime of the last malloc(9) failure (induced or real). */ static time_t t_malloc_fail; #if defined(MALLOC_MAKE_FAILURES) || (MALLOC_DEBUG_MAXZONES > 1) static SYSCTL_NODE(_debug, OID_AUTO, malloc, CTLFLAG_RD, 0, "Kernel malloc debugging options"); #endif /* * malloc(9) fault injection -- cause malloc failures every (n) mallocs when * the caller specifies M_NOWAIT. If set to 0, no failures are caused. */ #ifdef MALLOC_MAKE_FAILURES static int malloc_failure_rate; static int malloc_nowait_count; static int malloc_failure_count; SYSCTL_INT(_debug_malloc, OID_AUTO, failure_rate, CTLFLAG_RW, &malloc_failure_rate, 0, "Every (n) mallocs with M_NOWAIT will fail"); TUNABLE_INT("debug.malloc.failure_rate", &malloc_failure_rate); SYSCTL_INT(_debug_malloc, OID_AUTO, failure_count, CTLFLAG_RD, &malloc_failure_count, 0, "Number of imposed M_NOWAIT malloc failures"); #endif static int sysctl_kmem_map_size(SYSCTL_HANDLER_ARGS) { u_long size; size = kmem_map->size; return (sysctl_handle_long(oidp, &size, 0, req)); } static int sysctl_kmem_map_free(SYSCTL_HANDLER_ARGS) { u_long size; vm_map_lock_read(kmem_map); size = kmem_map->root != NULL ? kmem_map->root->max_free : kmem_map->max_offset - kmem_map->min_offset; vm_map_unlock_read(kmem_map); return (sysctl_handle_long(oidp, &size, 0, req)); } /* * malloc(9) uma zone separation -- sub-page buffer overruns in one * malloc type will affect only a subset of other malloc types. */ #if MALLOC_DEBUG_MAXZONES > 1 static void tunable_set_numzones(void) { TUNABLE_INT_FETCH("debug.malloc.numzones", &numzones); /* Sanity check the number of malloc uma zones. */ if (numzones <= 0) numzones = 1; if (numzones > MALLOC_DEBUG_MAXZONES) numzones = MALLOC_DEBUG_MAXZONES; } SYSINIT(numzones, SI_SUB_TUNABLES, SI_ORDER_ANY, tunable_set_numzones, NULL); SYSCTL_INT(_debug_malloc, OID_AUTO, numzones, CTLFLAG_RDTUN, &numzones, 0, "Number of malloc uma subzones"); /* * Any number that changes regularly is an okay choice for the * offset. Build numbers are pretty good of you have them. */ static u_int zone_offset = __FreeBSD_version; TUNABLE_INT("debug.malloc.zone_offset", &zone_offset); SYSCTL_UINT(_debug_malloc, OID_AUTO, zone_offset, CTLFLAG_RDTUN, &zone_offset, 0, "Separate malloc types by examining the " "Nth character in the malloc type short description."); static u_int mtp_get_subzone(const char *desc) { size_t len; u_int val; if (desc == NULL || (len = strlen(desc)) == 0) return (0); val = desc[zone_offset % len]; return (val % numzones); } #elif MALLOC_DEBUG_MAXZONES == 0 #error "MALLOC_DEBUG_MAXZONES must be positive." #else static inline u_int mtp_get_subzone(const char *desc) { return (0); } #endif /* MALLOC_DEBUG_MAXZONES > 1 */ int malloc_last_fail(void) { return (time_uptime - t_malloc_fail); } /* * An allocation has succeeded -- update malloc type statistics for the * amount of bucket size. Occurs within a critical section so that the * thread isn't preempted and doesn't migrate while updating per-PCU * statistics. */ static void malloc_type_zone_allocated(struct malloc_type *mtp, unsigned long size, int zindx) { struct malloc_type_internal *mtip; struct malloc_type_stats *mtsp; critical_enter(); mtip = mtp->ks_handle; mtsp = &mtip->mti_stats[curcpu]; if (size > 0) { mtsp->mts_memalloced += size; mtsp->mts_numallocs++; } if (zindx != -1) mtsp->mts_size |= 1 << zindx; #ifdef KDTRACE_HOOKS if (dtrace_malloc_probe != NULL) { uint32_t probe_id = mtip->mti_probes[DTMALLOC_PROBE_MALLOC]; if (probe_id != 0) (dtrace_malloc_probe)(probe_id, (uintptr_t) mtp, (uintptr_t) mtip, (uintptr_t) mtsp, size, zindx); } #endif critical_exit(); } void malloc_type_allocated(struct malloc_type *mtp, unsigned long size) { if (size > 0) malloc_type_zone_allocated(mtp, size, -1); } /* * A free operation has occurred -- update malloc type statistics for the * amount of the bucket size. Occurs within a critical section so that the * thread isn't preempted and doesn't migrate while updating per-CPU * statistics. */ void malloc_type_freed(struct malloc_type *mtp, unsigned long size) { struct malloc_type_internal *mtip; struct malloc_type_stats *mtsp; critical_enter(); mtip = mtp->ks_handle; mtsp = &mtip->mti_stats[curcpu]; mtsp->mts_memfreed += size; mtsp->mts_numfrees++; #ifdef KDTRACE_HOOKS if (dtrace_malloc_probe != NULL) { uint32_t probe_id = mtip->mti_probes[DTMALLOC_PROBE_FREE]; if (probe_id != 0) (dtrace_malloc_probe)(probe_id, (uintptr_t) mtp, (uintptr_t) mtip, (uintptr_t) mtsp, size, 0); } #endif critical_exit(); } /* * contigmalloc: * * Allocate a block of physically contiguous memory. * * If M_NOWAIT is set, this routine will not block and return NULL if * the allocation fails. */ void * contigmalloc(unsigned long size, struct malloc_type *type, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) { void *ret; ret = (void *)kmem_alloc_contig(kernel_map, size, flags, low, high, alignment, boundary, VM_MEMATTR_DEFAULT); if (ret != NULL) malloc_type_allocated(type, round_page(size)); return (ret); } /* * contigfree: * * Free a block of memory allocated by contigmalloc. * * This routine may not block. */ void contigfree(void *addr, unsigned long size, struct malloc_type *type) { kmem_free(kernel_map, (vm_offset_t)addr, size); malloc_type_freed(type, round_page(size)); } /* * malloc: * * Allocate a block of memory. * * If M_NOWAIT is set, this routine will not block and return NULL if * the allocation fails. */ void * malloc(unsigned long size, struct malloc_type *mtp, int flags) { int indx; struct malloc_type_internal *mtip; caddr_t va; uma_zone_t zone; #if defined(DIAGNOSTIC) || defined(DEBUG_REDZONE) unsigned long osize = size; #endif #ifdef INVARIANTS KASSERT(mtp->ks_magic == M_MAGIC, ("malloc: bad malloc type magic")); /* * Check that exactly one of M_WAITOK or M_NOWAIT is specified. */ indx = flags & (M_WAITOK | M_NOWAIT); if (indx != M_NOWAIT && indx != M_WAITOK) { static struct timeval lasterr; static int curerr, once; if (once == 0 && ppsratecheck(&lasterr, &curerr, 1)) { printf("Bad malloc flags: %x\n", indx); kdb_backtrace(); flags |= M_WAITOK; once++; } } #endif #ifdef MALLOC_MAKE_FAILURES if ((flags & M_NOWAIT) && (malloc_failure_rate != 0)) { atomic_add_int(&malloc_nowait_count, 1); if ((malloc_nowait_count % malloc_failure_rate) == 0) { atomic_add_int(&malloc_failure_count, 1); t_malloc_fail = time_uptime; return (NULL); } } #endif if (flags & M_WAITOK) KASSERT(curthread->td_intr_nesting_level == 0, ("malloc(M_WAITOK) in interrupt context")); #ifdef DEBUG_MEMGUARD if (memguard_cmp_mtp(mtp, size)) { va = memguard_alloc(size, flags); if (va != NULL) return (va); /* This is unfortunate but should not be fatal. */ } #endif #ifdef DEBUG_REDZONE size = redzone_size_ntor(size); #endif if (size <= KMEM_ZMAX) { mtip = mtp->ks_handle; if (size & KMEM_ZMASK) size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; indx = kmemsize[size >> KMEM_ZSHIFT]; KASSERT(mtip->mti_zone < numzones, ("mti_zone %u out of range %d", mtip->mti_zone, numzones)); zone = kmemzones[indx].kz_zone[mtip->mti_zone]; #ifdef MALLOC_PROFILE krequests[size >> KMEM_ZSHIFT]++; #endif va = uma_zalloc(zone, flags); if (va != NULL) size = zone->uz_size; malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); } else { size = roundup(size, PAGE_SIZE); zone = NULL; va = uma_large_malloc(size, flags); malloc_type_allocated(mtp, va == NULL ? 0 : size); } if (flags & M_WAITOK) KASSERT(va != NULL, ("malloc(M_WAITOK) returned NULL")); else if (va == NULL) t_malloc_fail = time_uptime; #ifdef DIAGNOSTIC if (va != NULL && !(flags & M_ZERO)) { memset(va, 0x70, osize); } #endif #ifdef DEBUG_REDZONE if (va != NULL) va = redzone_setup(va, osize); #endif return ((void *) va); } /* * free: * * Free a block of memory allocated by malloc. * * This routine may not block. */ void free(void *addr, struct malloc_type *mtp) { uma_slab_t slab; u_long size; KASSERT(mtp->ks_magic == M_MAGIC, ("free: bad malloc type magic")); /* free(NULL, ...) does nothing */ if (addr == NULL) return; #ifdef DEBUG_MEMGUARD if (is_memguard_addr(addr)) { memguard_free(addr); return; } #endif #ifdef DEBUG_REDZONE redzone_check(addr); addr = redzone_addr_ntor(addr); #endif slab = vtoslab((vm_offset_t)addr & (~UMA_SLAB_MASK)); if (slab == NULL) panic("free: address %p(%p) has not been allocated.\n", addr, (void *)((u_long)addr & (~UMA_SLAB_MASK))); - if (!(slab->us_flags & UMA_SLAB_MALLOC)) { #ifdef INVARIANTS struct malloc_type **mtpp = addr; #endif size = slab->us_keg->uk_size; #ifdef INVARIANTS /* * Cache a pointer to the malloc_type that most recently freed * this memory here. This way we know who is most likely to * have stepped on it later. * * This code assumes that size is a multiple of 8 bytes for * 64 bit machines */ mtpp = (struct malloc_type **) ((unsigned long)mtpp & ~UMA_ALIGN_PTR); mtpp += (size - sizeof(struct malloc_type *)) / sizeof(struct malloc_type *); *mtpp = mtp; #endif uma_zfree_arg(LIST_FIRST(&slab->us_keg->uk_zones), addr, slab); } else { size = slab->us_size; uma_large_free(slab); } malloc_type_freed(mtp, size); } /* * realloc: change the size of a memory block */ void * realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags) { uma_slab_t slab; unsigned long alloc; void *newaddr; KASSERT(mtp->ks_magic == M_MAGIC, ("realloc: bad malloc type magic")); /* realloc(NULL, ...) is equivalent to malloc(...) */ if (addr == NULL) return (malloc(size, mtp, flags)); /* * XXX: Should report free of old memory and alloc of new memory to * per-CPU stats. */ #ifdef DEBUG_MEMGUARD if (is_memguard_addr(addr)) return (memguard_realloc(addr, size, mtp, flags)); #endif #ifdef DEBUG_REDZONE slab = NULL; alloc = redzone_get_size(addr); #else slab = vtoslab((vm_offset_t)addr & ~(UMA_SLAB_MASK)); /* Sanity check */ KASSERT(slab != NULL, ("realloc: address %p out of range", (void *)addr)); /* Get the size of the original block */ if (!(slab->us_flags & UMA_SLAB_MALLOC)) alloc = slab->us_keg->uk_size; else alloc = slab->us_size; /* Reuse the original block if appropriate */ if (size <= alloc && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) return (addr); #endif /* !DEBUG_REDZONE */ /* Allocate a new, bigger (or smaller) block */ if ((newaddr = malloc(size, mtp, flags)) == NULL) return (NULL); /* Copy over original contents */ bcopy(addr, newaddr, min(size, alloc)); free(addr, mtp); return (newaddr); } /* * reallocf: same as realloc() but free memory on failure. */ void * reallocf(void *addr, unsigned long size, struct malloc_type *mtp, int flags) { void *mem; if ((mem = realloc(addr, size, mtp, flags)) == NULL) free(addr, mtp); return (mem); } /* * Initialize the kernel memory allocator */ /* ARGSUSED*/ static void kmeminit(void *dummy) { uint8_t indx; u_long mem_size, tmp; int i; mtx_init(&malloc_mtx, "malloc", NULL, MTX_DEF); /* * Try to auto-tune the kernel memory size, so that it is * more applicable for a wider range of machine sizes. The * VM_KMEM_SIZE_MAX is dependent on the maximum KVA space * available. * * Note that the kmem_map is also used by the zone allocator, * so make sure that there is enough space. */ vm_kmem_size = VM_KMEM_SIZE + nmbclusters * PAGE_SIZE; mem_size = cnt.v_page_count; #if defined(VM_KMEM_SIZE_SCALE) vm_kmem_size_scale = VM_KMEM_SIZE_SCALE; #endif TUNABLE_INT_FETCH("vm.kmem_size_scale", &vm_kmem_size_scale); if (vm_kmem_size_scale > 0 && (mem_size / vm_kmem_size_scale) > (vm_kmem_size / PAGE_SIZE)) vm_kmem_size = (mem_size / vm_kmem_size_scale) * PAGE_SIZE; #if defined(VM_KMEM_SIZE_MIN) vm_kmem_size_min = VM_KMEM_SIZE_MIN; #endif TUNABLE_ULONG_FETCH("vm.kmem_size_min", &vm_kmem_size_min); if (vm_kmem_size_min > 0 && vm_kmem_size < vm_kmem_size_min) { vm_kmem_size = vm_kmem_size_min; } #if defined(VM_KMEM_SIZE_MAX) vm_kmem_size_max = VM_KMEM_SIZE_MAX; #endif TUNABLE_ULONG_FETCH("vm.kmem_size_max", &vm_kmem_size_max); if (vm_kmem_size_max > 0 && vm_kmem_size >= vm_kmem_size_max) vm_kmem_size = vm_kmem_size_max; /* Allow final override from the kernel environment */ TUNABLE_ULONG_FETCH("vm.kmem_size", &vm_kmem_size); /* * Limit kmem virtual size to twice the physical memory. * This allows for kmem map sparseness, but limits the size * to something sane. Be careful to not overflow the 32bit * ints while doing the check or the adjustment. */ if (vm_kmem_size / 2 / PAGE_SIZE > mem_size) vm_kmem_size = 2 * mem_size * PAGE_SIZE; #ifdef DEBUG_MEMGUARD tmp = memguard_fudge(vm_kmem_size, kernel_map); #else tmp = vm_kmem_size; #endif kmem_map = kmem_suballoc(kernel_map, &kmembase, &kmemlimit, tmp, TRUE); kmem_map->system_map = 1; #ifdef DEBUG_MEMGUARD /* * Initialize MemGuard if support compiled in. MemGuard is a * replacement allocator used for detecting tamper-after-free * scenarios as they occur. It is only used for debugging. */ memguard_init(kmem_map); #endif uma_startup2(); mt_zone = uma_zcreate("mt_zone", sizeof(struct malloc_type_internal), #ifdef INVARIANTS mtrash_ctor, mtrash_dtor, mtrash_init, mtrash_fini, #else NULL, NULL, NULL, NULL, #endif UMA_ALIGN_PTR, UMA_ZONE_MALLOC); for (i = 0, indx = 0; kmemzones[indx].kz_size != 0; indx++) { int size = kmemzones[indx].kz_size; char *name = kmemzones[indx].kz_name; int subzone; for (subzone = 0; subzone < numzones; subzone++) { kmemzones[indx].kz_zone[subzone] = uma_zcreate(name, size, #ifdef INVARIANTS mtrash_ctor, mtrash_dtor, mtrash_init, mtrash_fini, #else NULL, NULL, NULL, NULL, #endif UMA_ALIGN_PTR, UMA_ZONE_MALLOC); } for (;i <= size; i+= KMEM_ZBASE) kmemsize[i >> KMEM_ZSHIFT] = indx; } } void malloc_init(void *data) { struct malloc_type_internal *mtip; struct malloc_type *mtp; KASSERT(cnt.v_page_count != 0, ("malloc_register before vm_init")); mtp = data; if (mtp->ks_magic != M_MAGIC) panic("malloc_init: bad malloc type magic"); mtip = uma_zalloc(mt_zone, M_WAITOK | M_ZERO); mtp->ks_handle = mtip; mtip->mti_zone = mtp_get_subzone(mtp->ks_shortdesc); mtx_lock(&malloc_mtx); mtp->ks_next = kmemstatistics; kmemstatistics = mtp; kmemcount++; mtx_unlock(&malloc_mtx); } void malloc_uninit(void *data) { struct malloc_type_internal *mtip; struct malloc_type_stats *mtsp; struct malloc_type *mtp, *temp; uma_slab_t slab; long temp_allocs, temp_bytes; int i; mtp = data; KASSERT(mtp->ks_magic == M_MAGIC, ("malloc_uninit: bad malloc type magic")); KASSERT(mtp->ks_handle != NULL, ("malloc_deregister: cookie NULL")); mtx_lock(&malloc_mtx); mtip = mtp->ks_handle; mtp->ks_handle = NULL; if (mtp != kmemstatistics) { for (temp = kmemstatistics; temp != NULL; temp = temp->ks_next) { if (temp->ks_next == mtp) { temp->ks_next = mtp->ks_next; break; } } KASSERT(temp, ("malloc_uninit: type '%s' not found", mtp->ks_shortdesc)); } else kmemstatistics = mtp->ks_next; kmemcount--; mtx_unlock(&malloc_mtx); /* * Look for memory leaks. */ temp_allocs = temp_bytes = 0; for (i = 0; i < MAXCPU; i++) { mtsp = &mtip->mti_stats[i]; temp_allocs += mtsp->mts_numallocs; temp_allocs -= mtsp->mts_numfrees; temp_bytes += mtsp->mts_memalloced; temp_bytes -= mtsp->mts_memfreed; } if (temp_allocs > 0 || temp_bytes > 0) { printf("Warning: memory type %s leaked memory on destroy " "(%ld allocations, %ld bytes leaked).\n", mtp->ks_shortdesc, temp_allocs, temp_bytes); } slab = vtoslab((vm_offset_t) mtip & (~UMA_SLAB_MASK)); uma_zfree_arg(mt_zone, mtip, slab); } struct malloc_type * malloc_desc2type(const char *desc) { struct malloc_type *mtp; mtx_assert(&malloc_mtx, MA_OWNED); for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) { if (strcmp(mtp->ks_shortdesc, desc) == 0) return (mtp); } return (NULL); } static int sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS) { struct malloc_type_stream_header mtsh; struct malloc_type_internal *mtip; struct malloc_type_header mth; struct malloc_type *mtp; int error, i; struct sbuf sbuf; error = sysctl_wire_old_buffer(req, 0); if (error != 0) return (error); sbuf_new_for_sysctl(&sbuf, NULL, 128, req); mtx_lock(&malloc_mtx); /* * Insert stream header. */ bzero(&mtsh, sizeof(mtsh)); mtsh.mtsh_version = MALLOC_TYPE_STREAM_VERSION; mtsh.mtsh_maxcpus = MAXCPU; mtsh.mtsh_count = kmemcount; (void)sbuf_bcat(&sbuf, &mtsh, sizeof(mtsh)); /* * Insert alternating sequence of type headers and type statistics. */ for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) { mtip = (struct malloc_type_internal *)mtp->ks_handle; /* * Insert type header. */ bzero(&mth, sizeof(mth)); strlcpy(mth.mth_name, mtp->ks_shortdesc, MALLOC_MAX_NAME); (void)sbuf_bcat(&sbuf, &mth, sizeof(mth)); /* * Insert type statistics for each CPU. */ for (i = 0; i < MAXCPU; i++) { (void)sbuf_bcat(&sbuf, &mtip->mti_stats[i], sizeof(mtip->mti_stats[i])); } } mtx_unlock(&malloc_mtx); error = sbuf_finish(&sbuf); sbuf_delete(&sbuf); return (error); } SYSCTL_PROC(_kern, OID_AUTO, malloc_stats, CTLFLAG_RD|CTLTYPE_STRUCT, 0, 0, sysctl_kern_malloc_stats, "s,malloc_type_ustats", "Return malloc types"); SYSCTL_INT(_kern, OID_AUTO, malloc_count, CTLFLAG_RD, &kmemcount, 0, "Count of kernel malloc types"); void malloc_type_list(malloc_type_list_func_t *func, void *arg) { struct malloc_type *mtp, **bufmtp; int count, i; size_t buflen; mtx_lock(&malloc_mtx); restart: mtx_assert(&malloc_mtx, MA_OWNED); count = kmemcount; mtx_unlock(&malloc_mtx); buflen = sizeof(struct malloc_type *) * count; bufmtp = malloc(buflen, M_TEMP, M_WAITOK); mtx_lock(&malloc_mtx); if (count < kmemcount) { free(bufmtp, M_TEMP); goto restart; } for (mtp = kmemstatistics, i = 0; mtp != NULL; mtp = mtp->ks_next, i++) bufmtp[i] = mtp; mtx_unlock(&malloc_mtx); for (i = 0; i < count; i++) (func)(bufmtp[i], arg); free(bufmtp, M_TEMP); } #ifdef DDB DB_SHOW_COMMAND(malloc, db_show_malloc) { struct malloc_type_internal *mtip; struct malloc_type *mtp; uint64_t allocs, frees; uint64_t alloced, freed; int i; db_printf("%18s %12s %12s %12s\n", "Type", "InUse", "MemUse", "Requests"); for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) { mtip = (struct malloc_type_internal *)mtp->ks_handle; allocs = 0; frees = 0; alloced = 0; freed = 0; for (i = 0; i < MAXCPU; i++) { allocs += mtip->mti_stats[i].mts_numallocs; frees += mtip->mti_stats[i].mts_numfrees; alloced += mtip->mti_stats[i].mts_memalloced; freed += mtip->mti_stats[i].mts_memfreed; } db_printf("%18s %12ju %12juK %12ju\n", mtp->ks_shortdesc, allocs - frees, (alloced - freed + 1023) / 1024, allocs); if (db_pager_quit) break; } } #if MALLOC_DEBUG_MAXZONES > 1 DB_SHOW_COMMAND(multizone_matches, db_show_multizone_matches) { struct malloc_type_internal *mtip; struct malloc_type *mtp; u_int subzone; if (!have_addr) { db_printf("Usage: show multizone_matches \n"); return; } mtp = (void *)addr; if (mtp->ks_magic != M_MAGIC) { db_printf("Magic %lx does not match expected %x\n", mtp->ks_magic, M_MAGIC); return; } mtip = mtp->ks_handle; subzone = mtip->mti_zone; for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) { mtip = mtp->ks_handle; if (mtip->mti_zone != subzone) continue; db_printf("%s\n", mtp->ks_shortdesc); if (db_pager_quit) break; } } #endif /* MALLOC_DEBUG_MAXZONES > 1 */ #endif /* DDB */ #ifdef MALLOC_PROFILE static int sysctl_kern_mprof(SYSCTL_HANDLER_ARGS) { struct sbuf sbuf; uint64_t count; uint64_t waste; uint64_t mem; int error; int rsize; int size; int i; waste = 0; mem = 0; error = sysctl_wire_old_buffer(req, 0); if (error != 0) return (error); sbuf_new_for_sysctl(&sbuf, NULL, 128, req); sbuf_printf(&sbuf, "\n Size Requests Real Size\n"); for (i = 0; i < KMEM_ZSIZE; i++) { size = i << KMEM_ZSHIFT; rsize = kmemzones[kmemsize[i]].kz_size; count = (long long unsigned)krequests[i]; sbuf_printf(&sbuf, "%6d%28llu%11d\n", size, (unsigned long long)count, rsize); if ((rsize * count) > (size * count)) waste += (rsize * count) - (size * count); mem += (rsize * count); } sbuf_printf(&sbuf, "\nTotal memory used:\t%30llu\nTotal Memory wasted:\t%30llu\n", (unsigned long long)mem, (unsigned long long)waste); error = sbuf_finish(&sbuf); sbuf_delete(&sbuf); return (error); } SYSCTL_OID(_kern, OID_AUTO, mprof, CTLTYPE_STRING|CTLFLAG_RD, NULL, 0, sysctl_kern_mprof, "A", "Malloc Profiling"); #endif /* MALLOC_PROFILE */ Index: user/attilio/vmc-playground/sys/netgraph/ng_ether.c =================================================================== --- user/attilio/vmc-playground/sys/netgraph/ng_ether.c (revision 246333) +++ user/attilio/vmc-playground/sys/netgraph/ng_ether.c (revision 246334) @@ -1,873 +1,879 @@ /* * ng_ether.c */ /*- * Copyright (c) 1996-2000 Whistle Communications, Inc. * All rights reserved. * * Subject to the following obligations and disclaimer of warranty, use and * redistribution of this software, in source or object code forms, with or * without modifications are expressly permitted by Whistle Communications; * provided, however, that: * 1. Any and all reproductions of the source or object code must include the * copyright notice above and the following disclaimer of warranties; and * 2. No rights are granted, in any manner or form, to use Whistle * Communications, Inc. trademarks, including the mark "WHISTLE * COMMUNICATIONS" on advertising, endorsements, or otherwise except as * such appears in the above copyright notice or in the software. * * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Authors: Archie Cobbs * Julian Elischer * * $FreeBSD$ */ /* * ng_ether(4) netgraph node type */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_VERSION(ng_ether, 1); #define IFP2NG(ifp) (IFP2AC((ifp))->ac_netgraph) /* Per-node private data */ struct private { struct ifnet *ifp; /* associated interface */ hook_p upper; /* upper hook connection */ hook_p lower; /* lower hook connection */ hook_p orphan; /* orphan hook connection */ u_char autoSrcAddr; /* always overwrite source address */ u_char promisc; /* promiscuous mode enabled */ u_long hwassist; /* hardware checksum capabilities */ u_int flags; /* flags e.g. really die */ }; typedef struct private *priv_p; /* Hook pointers used by if_ethersubr.c to callback to netgraph */ extern void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp); extern void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m); extern int (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp); extern void (*ng_ether_attach_p)(struct ifnet *ifp); extern void (*ng_ether_detach_p)(struct ifnet *ifp); extern void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); /* Functional hooks called from if_ethersubr.c */ static void ng_ether_input(struct ifnet *ifp, struct mbuf **mp); static void ng_ether_input_orphan(struct ifnet *ifp, struct mbuf *m); static int ng_ether_output(struct ifnet *ifp, struct mbuf **mp); static void ng_ether_attach(struct ifnet *ifp); static void ng_ether_detach(struct ifnet *ifp); static void ng_ether_link_state(struct ifnet *ifp, int state); /* Other functions */ static int ng_ether_rcv_lower(hook_p node, item_p item); static int ng_ether_rcv_upper(hook_p node, item_p item); /* Netgraph node methods */ static ng_constructor_t ng_ether_constructor; static ng_rcvmsg_t ng_ether_rcvmsg; static ng_shutdown_t ng_ether_shutdown; static ng_newhook_t ng_ether_newhook; static ng_rcvdata_t ng_ether_rcvdata; static ng_disconnect_t ng_ether_disconnect; static int ng_ether_mod_event(module_t mod, int event, void *data); static eventhandler_tag ng_ether_ifnet_arrival_cookie; /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_ether_cmdlist[] = { { NGM_ETHER_COOKIE, NGM_ETHER_GET_IFNAME, "getifname", NULL, &ng_parse_string_type }, { NGM_ETHER_COOKIE, NGM_ETHER_GET_IFINDEX, "getifindex", NULL, &ng_parse_int32_type }, { NGM_ETHER_COOKIE, NGM_ETHER_GET_ENADDR, "getenaddr", NULL, &ng_parse_enaddr_type }, { NGM_ETHER_COOKIE, NGM_ETHER_SET_ENADDR, "setenaddr", &ng_parse_enaddr_type, NULL }, { NGM_ETHER_COOKIE, NGM_ETHER_GET_PROMISC, "getpromisc", NULL, &ng_parse_int32_type }, { NGM_ETHER_COOKIE, NGM_ETHER_SET_PROMISC, "setpromisc", &ng_parse_int32_type, NULL }, { NGM_ETHER_COOKIE, NGM_ETHER_GET_AUTOSRC, "getautosrc", NULL, &ng_parse_int32_type }, { NGM_ETHER_COOKIE, NGM_ETHER_SET_AUTOSRC, "setautosrc", &ng_parse_int32_type, NULL }, { NGM_ETHER_COOKIE, NGM_ETHER_ADD_MULTI, "addmulti", &ng_parse_enaddr_type, NULL }, { NGM_ETHER_COOKIE, NGM_ETHER_DEL_MULTI, "delmulti", &ng_parse_enaddr_type, NULL }, { NGM_ETHER_COOKIE, NGM_ETHER_DETACH, "detach", NULL, NULL }, { 0 } }; static struct ng_type ng_ether_typestruct = { .version = NG_ABI_VERSION, .name = NG_ETHER_NODE_TYPE, .mod_event = ng_ether_mod_event, .constructor = ng_ether_constructor, .rcvmsg = ng_ether_rcvmsg, .shutdown = ng_ether_shutdown, .newhook = ng_ether_newhook, .rcvdata = ng_ether_rcvdata, .disconnect = ng_ether_disconnect, .cmdlist = ng_ether_cmdlist, }; NETGRAPH_INIT(ether, &ng_ether_typestruct); /****************************************************************** UTILITY FUNCTIONS ******************************************************************/ static void ng_ether_sanitize_ifname(const char *ifname, char *name) { int i; for (i = 0; i < IFNAMSIZ; i++) { if (ifname[i] == '.' || ifname[i] == ':') name[i] = '_'; else name[i] = ifname[i]; if (name[i] == '\0') break; } } /****************************************************************** ETHERNET FUNCTION HOOKS ******************************************************************/ /* * Handle a packet that has come in on an interface. We get to * look at it here before any upper layer protocols do. */ static void ng_ether_input(struct ifnet *ifp, struct mbuf **mp) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); int error; /* If "lower" hook not connected, let packet continue */ if (priv->lower == NULL) return; NG_SEND_DATA_ONLY(error, priv->lower, *mp); /* sets *mp = NULL */ } /* * Handle a packet that has come in on an interface, and which * does not match any of our known protocols (an ``orphan''). */ static void ng_ether_input_orphan(struct ifnet *ifp, struct mbuf *m) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); int error; /* If "orphan" hook not connected, discard packet */ if (priv->orphan == NULL) { m_freem(m); return; } NG_SEND_DATA_ONLY(error, priv->orphan, m); } /* * Handle a packet that is going out on an interface. * The Ethernet header is already attached to the mbuf. */ static int ng_ether_output(struct ifnet *ifp, struct mbuf **mp) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); int error = 0; /* If "upper" hook not connected, let packet continue */ if (priv->upper == NULL) return (0); /* Send it out "upper" hook */ NG_OUTBOUND_THREAD_REF(); NG_SEND_DATA_ONLY(error, priv->upper, *mp); NG_OUTBOUND_THREAD_UNREF(); return (error); } /* * A new Ethernet interface has been attached. * Create a new node for it, etc. */ static void ng_ether_attach(struct ifnet *ifp) { char name[IFNAMSIZ]; priv_p priv; node_p node; /* * Do not create / attach an ether node to this ifnet if * a netgraph node with the same name already exists. * This should prevent ether nodes to become attached to * eiface nodes, which may be problematic due to naming * clashes. */ if ((node = ng_name2noderef(NULL, ifp->if_xname)) != NULL) { NG_NODE_UNREF(node); return; } /* Create node */ KASSERT(!IFP2NG(ifp), ("%s: node already exists?", __func__)); if (ng_make_node_common(&ng_ether_typestruct, &node) != 0) { log(LOG_ERR, "%s: can't %s for %s\n", __func__, "create node", ifp->if_xname); return; } /* Allocate private data */ priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); if (priv == NULL) { log(LOG_ERR, "%s: can't %s for %s\n", __func__, "allocate memory", ifp->if_xname); NG_NODE_UNREF(node); return; } NG_NODE_SET_PRIVATE(node, priv); priv->ifp = ifp; IFP2NG(ifp) = node; priv->hwassist = ifp->if_hwassist; /* Try to give the node the same name as the interface */ ng_ether_sanitize_ifname(ifp->if_xname, name); if (ng_name_node(node, name) != 0) log(LOG_WARNING, "%s: can't name node %s\n", __func__, name); } /* * An Ethernet interface is being detached. * REALLY Destroy its node. */ static void ng_ether_detach(struct ifnet *ifp) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); taskqueue_drain(taskqueue_swi, &ifp->if_linktask); NG_NODE_REALLY_DIE(node); /* Force real removal of node */ /* * We can't assume the ifnet is still around when we run shutdown * So zap it now. XXX We HOPE that anything running at this time * handles it (as it should in the non netgraph case). */ IFP2NG(ifp) = NULL; priv->ifp = NULL; /* XXX race if interrupted an output packet */ ng_rmnode_self(node); /* remove all netgraph parts */ } /* * Notify graph about link event. * if_link_state_change() has already checked that the state has changed. */ static void ng_ether_link_state(struct ifnet *ifp, int state) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg; int cmd, dummy_error = 0; if (state == LINK_STATE_UP) cmd = NGM_LINK_IS_UP; else if (state == LINK_STATE_DOWN) cmd = NGM_LINK_IS_DOWN; else return; if (priv->lower != NULL) { NG_MKMESSAGE(msg, NGM_FLOW_COOKIE, cmd, 0, M_NOWAIT); if (msg != NULL) NG_SEND_MSG_HOOK(dummy_error, node, msg, priv->lower, 0); } if (priv->orphan != NULL) { NG_MKMESSAGE(msg, NGM_FLOW_COOKIE, cmd, 0, M_NOWAIT); if (msg != NULL) NG_SEND_MSG_HOOK(dummy_error, node, msg, priv->orphan, 0); } } /* * Interface arrival notification handler. * The notification is produced in two cases: * o a new interface arrives * o an existing interface got renamed * Currently the first case is handled by ng_ether_attach via special * hook ng_ether_attach_p. */ static void ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp) { char name[IFNAMSIZ]; - node_p node = IFP2NG(ifp); + node_p node; + /* Only ethernet interfaces are of interest. */ + if (ifp->if_type != IFT_ETHER + && ifp->if_type != IFT_L2VLAN) + return; + /* * Just return if it's a new interface without an ng_ether companion. */ + node = IFP2NG(ifp); if (node == NULL) return; /* Try to give the node the same name as the new interface name */ ng_ether_sanitize_ifname(ifp->if_xname, name); if (ng_name_node(node, name) != 0) log(LOG_WARNING, "%s: can't re-name node %s\n", __func__, name); } /****************************************************************** NETGRAPH NODE METHODS ******************************************************************/ /* * It is not possible or allowable to create a node of this type. * Nodes get created when the interface is attached (or, when * this node type's KLD is loaded). */ static int ng_ether_constructor(node_p node) { return (EINVAL); } /* * Check for attaching a new hook. */ static int ng_ether_newhook(node_p node, hook_p hook, const char *name) { const priv_p priv = NG_NODE_PRIVATE(node); hook_p *hookptr; /* Divert hook is an alias for lower */ if (strcmp(name, NG_ETHER_HOOK_DIVERT) == 0) name = NG_ETHER_HOOK_LOWER; /* Which hook? */ if (strcmp(name, NG_ETHER_HOOK_UPPER) == 0) { hookptr = &priv->upper; NG_HOOK_SET_RCVDATA(hook, ng_ether_rcv_upper); NG_HOOK_SET_TO_INBOUND(hook); } else if (strcmp(name, NG_ETHER_HOOK_LOWER) == 0) { hookptr = &priv->lower; NG_HOOK_SET_RCVDATA(hook, ng_ether_rcv_lower); } else if (strcmp(name, NG_ETHER_HOOK_ORPHAN) == 0) { hookptr = &priv->orphan; NG_HOOK_SET_RCVDATA(hook, ng_ether_rcv_lower); } else return (EINVAL); /* Check if already connected (shouldn't be, but doesn't hurt) */ if (*hookptr != NULL) return (EISCONN); /* Disable hardware checksums while 'upper' hook is connected */ if (hookptr == &priv->upper) priv->ifp->if_hwassist = 0; NG_HOOK_HI_STACK(hook); /* OK */ *hookptr = hook; return (0); } /* * Receive an incoming control message. */ static int ng_ether_rcvmsg(node_p node, item_p item, hook_p lasthook) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *resp = NULL; int error = 0; struct ng_mesg *msg; NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_ETHER_COOKIE: switch (msg->header.cmd) { case NGM_ETHER_GET_IFNAME: NG_MKRESPONSE(resp, msg, IFNAMSIZ, M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } strlcpy(resp->data, priv->ifp->if_xname, IFNAMSIZ); break; case NGM_ETHER_GET_IFINDEX: NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } *((u_int32_t *)resp->data) = priv->ifp->if_index; break; case NGM_ETHER_GET_ENADDR: NG_MKRESPONSE(resp, msg, ETHER_ADDR_LEN, M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } bcopy(IF_LLADDR(priv->ifp), resp->data, ETHER_ADDR_LEN); break; case NGM_ETHER_SET_ENADDR: { if (msg->header.arglen != ETHER_ADDR_LEN) { error = EINVAL; break; } error = if_setlladdr(priv->ifp, (u_char *)msg->data, ETHER_ADDR_LEN); EVENTHANDLER_INVOKE(iflladdr_event, priv->ifp); break; } case NGM_ETHER_GET_PROMISC: NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } *((u_int32_t *)resp->data) = priv->promisc; break; case NGM_ETHER_SET_PROMISC: { u_char want; if (msg->header.arglen != sizeof(u_int32_t)) { error = EINVAL; break; } want = !!*((u_int32_t *)msg->data); if (want ^ priv->promisc) { if ((error = ifpromisc(priv->ifp, want)) != 0) break; priv->promisc = want; } break; } case NGM_ETHER_GET_AUTOSRC: NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT); if (resp == NULL) { error = ENOMEM; break; } *((u_int32_t *)resp->data) = priv->autoSrcAddr; break; case NGM_ETHER_SET_AUTOSRC: if (msg->header.arglen != sizeof(u_int32_t)) { error = EINVAL; break; } priv->autoSrcAddr = !!*((u_int32_t *)msg->data); break; case NGM_ETHER_ADD_MULTI: { struct sockaddr_dl sa_dl; struct ifmultiaddr *ifma; if (msg->header.arglen != ETHER_ADDR_LEN) { error = EINVAL; break; } bzero(&sa_dl, sizeof(struct sockaddr_dl)); sa_dl.sdl_len = sizeof(struct sockaddr_dl); sa_dl.sdl_family = AF_LINK; sa_dl.sdl_alen = ETHER_ADDR_LEN; bcopy((void *)msg->data, LLADDR(&sa_dl), ETHER_ADDR_LEN); /* * Netgraph is only permitted to join groups once * via the if_addmulti() KPI, because it cannot hold * struct ifmultiaddr * between calls. It may also * lose a race while we check if the membership * already exists. */ if_maddr_rlock(priv->ifp); ifma = if_findmulti(priv->ifp, (struct sockaddr *)&sa_dl); if_maddr_runlock(priv->ifp); if (ifma != NULL) { error = EADDRINUSE; } else { error = if_addmulti(priv->ifp, (struct sockaddr *)&sa_dl, &ifma); } break; } case NGM_ETHER_DEL_MULTI: { struct sockaddr_dl sa_dl; if (msg->header.arglen != ETHER_ADDR_LEN) { error = EINVAL; break; } bzero(&sa_dl, sizeof(struct sockaddr_dl)); sa_dl.sdl_len = sizeof(struct sockaddr_dl); sa_dl.sdl_family = AF_LINK; sa_dl.sdl_alen = ETHER_ADDR_LEN; bcopy((void *)msg->data, LLADDR(&sa_dl), ETHER_ADDR_LEN); error = if_delmulti(priv->ifp, (struct sockaddr *)&sa_dl); break; } case NGM_ETHER_DETACH: ng_ether_detach(priv->ifp); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); return (error); } /* * Receive data on a hook. * Since we use per-hook recveive methods this should never be called. */ static int ng_ether_rcvdata(hook_p hook, item_p item) { NG_FREE_ITEM(item); panic("%s: weird hook", __func__); } /* * Handle an mbuf received on the "lower" or "orphan" hook. */ static int ng_ether_rcv_lower(hook_p hook, item_p item) { struct mbuf *m; const node_p node = NG_HOOK_NODE(hook); const priv_p priv = NG_NODE_PRIVATE(node); struct ifnet *const ifp = priv->ifp; NGI_GET_M(item, m); NG_FREE_ITEM(item); /* Check whether interface is ready for packets */ if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) { NG_FREE_M(m); return (ENETDOWN); } /* Make sure header is fully pulled up */ if (m->m_pkthdr.len < sizeof(struct ether_header)) { NG_FREE_M(m); return (EINVAL); } if (m->m_len < sizeof(struct ether_header) && (m = m_pullup(m, sizeof(struct ether_header))) == NULL) return (ENOBUFS); /* Drop in the MAC address if desired */ if (priv->autoSrcAddr) { /* Make the mbuf writable if it's not already */ if (!M_WRITABLE(m) && (m = m_pullup(m, sizeof(struct ether_header))) == NULL) return (ENOBUFS); /* Overwrite source MAC address */ bcopy(IF_LLADDR(ifp), mtod(m, struct ether_header *)->ether_shost, ETHER_ADDR_LEN); } /* Send it on its way */ return ether_output_frame(ifp, m); } /* * Handle an mbuf received on the "upper" hook. */ static int ng_ether_rcv_upper(hook_p hook, item_p item) { struct mbuf *m; const node_p node = NG_HOOK_NODE(hook); const priv_p priv = NG_NODE_PRIVATE(node); struct ifnet *ifp = priv->ifp; NGI_GET_M(item, m); NG_FREE_ITEM(item); /* Check length and pull off header */ if (m->m_pkthdr.len < sizeof(struct ether_header)) { NG_FREE_M(m); return (EINVAL); } if (m->m_len < sizeof(struct ether_header) && (m = m_pullup(m, sizeof(struct ether_header))) == NULL) return (ENOBUFS); m->m_pkthdr.rcvif = ifp; /* Pass the packet to the bridge, it may come back to us */ if (ifp->if_bridge) { BRIDGE_INPUT(ifp, m); if (m == NULL) return (0); } /* Route packet back in */ ether_demux(ifp, m); return (0); } /* * Shutdown node. This resets the node but does not remove it * unless the REALLY_DIE flag is set. */ static int ng_ether_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); if (node->nd_flags & NGF_REALLY_DIE) { /* * WE came here because the ethernet card is being unloaded, * so stop being persistant. * Actually undo all the things we did on creation. * Assume the ifp has already been freed. */ NG_NODE_SET_PRIVATE(node, NULL); free(priv, M_NETGRAPH); NG_NODE_UNREF(node); /* free node itself */ return (0); } if (priv->promisc) { /* disable promiscuous mode */ (void)ifpromisc(priv->ifp, 0); priv->promisc = 0; } NG_NODE_REVIVE(node); /* Signal ng_rmnode we are persisant */ return (0); } /* * Hook disconnection. */ static int ng_ether_disconnect(hook_p hook) { const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); if (hook == priv->upper) { priv->upper = NULL; if (priv->ifp != NULL) /* restore h/w csum */ priv->ifp->if_hwassist = priv->hwassist; } else if (hook == priv->lower) priv->lower = NULL; else if (hook == priv->orphan) priv->orphan = NULL; else panic("%s: weird hook", __func__); if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) ng_rmnode_self(NG_HOOK_NODE(hook)); /* reset node */ return (0); } /****************************************************************** INITIALIZATION ******************************************************************/ /* * Handle loading and unloading for this node type. */ static int ng_ether_mod_event(module_t mod, int event, void *data) { int error = 0; switch (event) { case MOD_LOAD: /* Register function hooks */ if (ng_ether_attach_p != NULL) { error = EEXIST; break; } ng_ether_attach_p = ng_ether_attach; ng_ether_detach_p = ng_ether_detach; ng_ether_output_p = ng_ether_output; ng_ether_input_p = ng_ether_input; ng_ether_input_orphan_p = ng_ether_input_orphan; ng_ether_link_state_p = ng_ether_link_state; ng_ether_ifnet_arrival_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event, ng_ether_ifnet_arrival_event, NULL, EVENTHANDLER_PRI_ANY); break; case MOD_UNLOAD: /* * Note that the base code won't try to unload us until * all nodes have been removed, and that can't happen * until all Ethernet interfaces are removed. In any * case, we know there are no nodes left if the action * is MOD_UNLOAD, so there's no need to detach any nodes. */ EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ng_ether_ifnet_arrival_cookie); /* Unregister function hooks */ ng_ether_attach_p = NULL; ng_ether_detach_p = NULL; ng_ether_output_p = NULL; ng_ether_input_p = NULL; ng_ether_input_orphan_p = NULL; ng_ether_link_state_p = NULL; break; default: error = EOPNOTSUPP; break; } return (error); } static void vnet_ng_ether_init(const void *unused) { struct ifnet *ifp; /* If module load was rejected, don't attach to vnets. */ if (ng_ether_attach_p != ng_ether_attach) return; /* Create nodes for any already-existing Ethernet interfaces. */ IFNET_RLOCK(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) ng_ether_attach(ifp); } IFNET_RUNLOCK(); } VNET_SYSINIT(vnet_ng_ether_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_ng_ether_init, NULL); Index: user/attilio/vmc-playground/sys/ufs/ufs/ufs_lookup.c =================================================================== --- user/attilio/vmc-playground/sys/ufs/ufs/ufs_lookup.c (revision 246333) +++ user/attilio/vmc-playground/sys/ufs/ufs/ufs_lookup.c (revision 246334) @@ -1,1476 +1,1475 @@ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_ufs.h" #include "opt_quota.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef UFS_DIRHASH #include #endif #include #include #ifdef DIAGNOSTIC static int dirchk = 1; #else static int dirchk = 0; #endif SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, ""); /* true if old FS format...*/ #define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) #ifdef QUOTA static int ufs_lookup_upgrade_lock(struct vnode *vp) { int error; ASSERT_VOP_LOCKED(vp, __FUNCTION__); if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) return (0); error = 0; /* * Upgrade vnode lock, since getinoquota() * requires exclusive lock to modify inode. */ vhold(vp); vn_lock(vp, LK_UPGRADE | LK_RETRY); VI_LOCK(vp); if (vp->v_iflag & VI_DOOMED) error = ENOENT; vdropl(vp); return (error); } #endif static int ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred, struct thread *td) { int error; #ifdef UFS_ACL /* * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt * * 3.16.2.1. ACE4_DELETE vs. ACE4_DELETE_CHILD */ /* * XXX: Is this check required? */ error = VOP_ACCESS(vdp, VEXEC, cred, td); if (error) return (error); error = VOP_ACCESSX(tdp, VDELETE, cred, td); if (error == 0) return (0); error = VOP_ACCESSX(vdp, VDELETE_CHILD, cred, td); if (error == 0) return (0); error = VOP_ACCESSX(vdp, VEXPLICIT_DENY | VDELETE_CHILD, cred, td); if (error) return (error); #endif /* !UFS_ACL */ /* * Standard Unix access control - delete access requires VWRITE. */ error = VOP_ACCESS(vdp, VWRITE, cred, td); if (error) return (error); /* * If directory is "sticky", then user must own * the directory, or the file in it, else she * may not delete it (unless she's root). This * implements append-only directories. */ if ((VTOI(vdp)->i_mode & ISVTX) && VOP_ACCESS(vdp, VADMIN, cred, td) && VOP_ACCESS(tdp, VADMIN, cred, td)) return (EPERM); return (0); } /* * Convert a component of a pathname into a pointer to a locked inode. * This is a very central and rather complicated routine. * If the filesystem is not maintained in a strict tree hierarchy, * this can result in a deadlock situation (see comments in code below). * * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending * on whether the name is to be looked up, created, renamed, or deleted. * When CREATE, RENAME, or DELETE is specified, information usable in * creating, renaming, or deleting a directory entry may be calculated. * If flag has LOCKPARENT or'ed into it and the target of the pathname * exists, lookup returns both the target and its parent directory locked. * When creating or renaming and LOCKPARENT is specified, the target may * not be ".". When deleting and LOCKPARENT is specified, the target may * be "."., but the caller must check to ensure it does an vrele and vput * instead of two vputs. * * This routine is actually used as VOP_CACHEDLOOKUP method, and the * filesystem employs the generic vfs_cache_lookup() as VOP_LOOKUP * method. * * vfs_cache_lookup() performs the following for us: * check that it is a directory * check accessibility of directory * check for modification attempts on read-only mounts * if name found in cache * if at end of path and deleting or creating * drop it * else * return name. * return VOP_CACHEDLOOKUP() * * Overall outline of ufs_lookup: * * search for name in directory, to found or notfound * notfound: * if creating, return locked directory, leaving info on available slots * else return error * found: * if at end of path and deleting, return information to allow delete * if at end of path and rewriting (RENAME and LOCKPARENT), lock target * inode and return info to allow rewrite * if not at end, add name to cache; if at end and neither creating * nor deleting, add name to cache */ int ufs_lookup(ap) struct vop_cachedlookup_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; } */ *ap; { return (ufs_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); } int ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, ino_t *dd_ino) { struct inode *dp; /* inode for directory being searched */ struct buf *bp; /* a buffer of directory entries */ struct direct *ep; /* the current directory entry */ int entryoffsetinblock; /* offset of ep in bp's buffer */ enum {NONE, COMPACT, FOUND} slotstatus; doff_t slotoffset; /* offset of area with free space */ doff_t i_diroff; /* cached i_diroff value. */ doff_t i_offset; /* cached i_offset value. */ int slotsize; /* size of area at slotoffset */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ doff_t prevoff; /* prev entry dp->i_offset */ struct vnode *pdp; /* saved dp during symlink work */ struct vnode *tdp; /* returned by VFS_VGET */ doff_t enduseful; /* pointer past last used dir slot */ u_long bmask; /* block offset mask */ int namlen, error; struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; ino_t ino, ino1; int ltype; if (vpp != NULL) *vpp = NULL; dp = VTOI(vdp); if (dp->i_effnlink == 0) return (ENOENT); /* * Create a vm object if vmiodirenable is enabled. * Alternatively we could call vnode_create_vobject * in VFS_VGET but we could end up creating objects * that are never used. */ vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread); bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; #ifdef QUOTA if ((nameiop == DELETE || nameiop == RENAME) && (flags & ISLASTCN)) { error = ufs_lookup_upgrade_lock(vdp); if (error != 0) return (error); } #endif restart: bp = NULL; slotoffset = -1; /* * We now have a segment name to search for, and a directory to search. * * Suppress search for slots unless creating * file and at end of pathname, in which case * we watch for a place to put the new file in * case it doesn't already exist. */ ino = 0; i_diroff = dp->i_diroff; slotstatus = FOUND; slotfreespace = slotsize = slotneeded = 0; if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN)) { slotstatus = NONE; slotneeded = DIRECTSIZ(cnp->cn_namelen); } #ifdef UFS_DIRHASH /* * Use dirhash for fast operations on large directories. The logic * to determine whether to hash the directory is contained within * ufsdirhash_build(); a zero return means that it decided to hash * this directory and it successfully built up the hash table. */ if (ufsdirhash_build(dp) == 0) { /* Look for a free slot if needed. */ enduseful = dp->i_size; if (slotstatus != FOUND) { slotoffset = ufsdirhash_findfree(dp, slotneeded, &slotsize); if (slotoffset >= 0) { slotstatus = COMPACT; enduseful = ufsdirhash_enduseful(dp); if (enduseful < 0) enduseful = dp->i_size; } } /* Look up the component. */ numdirpasses = 1; entryoffsetinblock = 0; /* silence compiler warning */ switch (ufsdirhash_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen, &i_offset, &bp, nameiop == DELETE ? &prevoff : NULL)) { case 0: ep = (struct direct *)((char *)bp->b_data + (i_offset & bmask)); goto foundentry; case ENOENT: i_offset = roundup2(dp->i_size, DIRBLKSIZ); goto notfound; default: /* Something failed; just do a linear search. */ break; } } #endif /* UFS_DIRHASH */ /* * If there is cached information on a previous search of * this directory, pick up where we last left off. * We cache only lookups as these are the most common * and have the greatest payoff. Caching CREATE has little * benefit as it usually must search the entire directory * to determine that the entry does not exist. Caching the * location of the last DELETE or RENAME has not reduced * profiling time and hence has been removed in the interest * of simplicity. */ if (nameiop != LOOKUP || i_diroff == 0 || i_diroff >= dp->i_size) { entryoffsetinblock = 0; i_offset = 0; numdirpasses = 1; } else { i_offset = i_diroff; if ((entryoffsetinblock = i_offset & bmask) && (error = UFS_BLKATOFF(vdp, (off_t)i_offset, NULL, &bp))) return (error); numdirpasses = 2; nchstats.ncs_2passes++; } prevoff = i_offset; endsearch = roundup2(dp->i_size, DIRBLKSIZ); enduseful = 0; searchloop: while (i_offset < endsearch) { /* * If necessary, get the next directory block. */ if ((i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); error = UFS_BLKATOFF(vdp, (off_t)i_offset, NULL, &bp); if (error) return (error); entryoffsetinblock = 0; } /* * If still looking for a slot, and at a DIRBLKSIZE * boundary, have to start looking for free space again. */ if (slotstatus == NONE && (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) { slotoffset = -1; slotfreespace = 0; } /* * Get pointer to next entry. * Full validation checks are slow, so we only check * enough to insure forward progress through the * directory. Complete checks can be run by patching * "dirchk" to be true. */ ep = (struct direct *)((char *)bp->b_data + entryoffsetinblock); if (ep->d_reclen == 0 || ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || (dirchk && ufs_dirbadentry(vdp, ep, entryoffsetinblock))) { int i; ufs_dirbad(dp, i_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); i_offset += i; entryoffsetinblock += i; continue; } /* * If an appropriate sized slot has not yet been found, * check to see if one is available. Also accumulate space * in the current block so that we can determine if * compaction is viable. */ if (slotstatus != FOUND) { int size = ep->d_reclen; if (ep->d_ino != 0) size -= DIRSIZ(OFSFMT(vdp), ep); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; slotoffset = i_offset; slotsize = ep->d_reclen; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) slotoffset = i_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; slotsize = i_offset + ep->d_reclen - slotoffset; } } } } /* * Check for a name match. */ if (ep->d_ino) { # if (BYTE_ORDER == LITTLE_ENDIAN) if (OFSFMT(vdp)) namlen = ep->d_type; else namlen = ep->d_namlen; # else namlen = ep->d_namlen; # endif if (namlen == cnp->cn_namelen && (cnp->cn_nameptr[0] == ep->d_name[0]) && !bcmp(cnp->cn_nameptr, ep->d_name, (unsigned)namlen)) { #ifdef UFS_DIRHASH foundentry: #endif /* * Save directory entry's inode number and * reclen in ndp->ni_ufs area, and release * directory buffer. */ if (vdp->v_mount->mnt_maxsymlinklen > 0 && ep->d_type == DT_WHT) { slotstatus = FOUND; slotoffset = i_offset; slotsize = ep->d_reclen; enduseful = dp->i_size; cnp->cn_flags |= ISWHITEOUT; numdirpasses--; goto notfound; } ino = ep->d_ino; goto found; } } prevoff = i_offset; i_offset += ep->d_reclen; entryoffsetinblock += ep->d_reclen; if (ep->d_ino) enduseful = i_offset; } notfound: /* * If we started in the middle of the directory and failed * to find our target, we must check the beginning as well. */ if (numdirpasses == 2) { numdirpasses--; i_offset = 0; endsearch = i_diroff; goto searchloop; } if (bp != NULL) brelse(bp); /* * If creating, and at end of pathname and current * directory has not been removed, then can consider * allowing file to be created. */ if ((nameiop == CREATE || nameiop == RENAME || (nameiop == DELETE && (cnp->cn_flags & DOWHITEOUT) && (cnp->cn_flags & ISWHITEOUT))) && (flags & ISLASTCN) && dp->i_effnlink != 0) { /* * Access for write is interpreted as allowing * creation of files in the directory. * * XXX: Fix the comment above. */ if (flags & WILLBEDIR) error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); else error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); if (error) return (error); /* * Return an indication of where the new directory * entry should be put. If we didn't find a slot, * then set dp->i_count to 0 indicating * that the new slot belongs at the end of the * directory. If we found a slot, then the new entry * can be put in the range from dp->i_offset to * dp->i_offset + dp->i_count. */ if (slotstatus == NONE) { dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ); dp->i_count = 0; enduseful = dp->i_offset; } else if (nameiop == DELETE) { dp->i_offset = slotoffset; if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; } else { dp->i_offset = slotoffset; dp->i_count = slotsize; if (enduseful < slotoffset + slotsize) enduseful = slotoffset + slotsize; } dp->i_endoff = roundup2(enduseful, DIRBLKSIZ); /* * We return with the directory locked, so that * the parameters we set up above will still be * valid if we actually decide to do a direnter(). * We return ni_vp == NULL to indicate that the entry * does not currently exist; we leave a pointer to * the (locked) directory inode in ndp->ni_dvp. * The pathname buffer is saved so that the name * can be obtained later. * * NB - if the directory is unlocked, then this * information cannot be used. */ cnp->cn_flags |= SAVENAME; return (EJUSTRETURN); } /* * Insert name into cache (as non-existent) if appropriate. */ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) cache_enter(vdp, NULL, cnp); return (ENOENT); found: if (dd_ino != NULL) *dd_ino = ino; if (numdirpasses == 2) nchstats.ncs_pass2++; /* * Check that directory length properly reflects presence * of this entry. */ if (i_offset + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) { ufs_dirbad(dp, i_offset, "i_size too small"); dp->i_size = i_offset + DIRSIZ(OFSFMT(vdp), ep); DIP_SET(dp, i_size, dp->i_size); dp->i_flag |= IN_CHANGE | IN_UPDATE; } brelse(bp); /* * Found component in pathname. * If the final component of path name, save information * in the cache as to where the entry was found. */ if ((flags & ISLASTCN) && nameiop == LOOKUP) dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1); /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. */ if (nameiop == DELETE && (flags & ISLASTCN)) { if (flags & LOCKPARENT) ASSERT_VOP_ELOCKED(vdp, __FUNCTION__); /* * Return pointer to current entry in dp->i_offset, * and distance past previous entry (if there * is a previous entry in this block) in dp->i_count. * Save directory inode pointer in ndp->ni_dvp for dirremove(). * * Technically we shouldn't be setting these in the * WANTPARENT case (first lookup in rename()), but any * lookups that will result in directory changes will * overwrite these. */ dp->i_offset = i_offset; if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; if (dd_ino != NULL) return (0); if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread); if (error) { vput(tdp); return (error); } if (dp->i_number == ino) { VREF(vdp); *vpp = vdp; vput(tdp); return (0); } *vpp = tdp; return (0); } /* * If rewriting (RENAME), return the inode and the * information required to rewrite the present directory * Must get inode of directory entry to verify it's a * regular file, or empty directory. */ if (nameiop == RENAME && (flags & ISLASTCN)) { if (flags & WILLBEDIR) error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); else error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); if (error) return (error); /* * Careful about locking second inode. * This can only occur if the target is ".". */ dp->i_offset = i_offset; if (dp->i_number == ino) return (EISDIR); if (dd_ino != NULL) return (0); if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread); if (error) { vput(tdp); return (error); } #ifdef SunOS_doesnt_do_that /* * The only purpose of this check is to return the correct * error. Assume that we want to rename directory "a" * to a file "b", and that we have no ACL_WRITE_DATA on * a containing directory, but we _do_ have ACL_APPEND_DATA. * In that case, the VOP_ACCESS check above will return 0, * and the operation will fail with ENOTDIR instead * of EACCESS. */ if (tdp->v_type == VDIR) error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); else error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); if (error) { vput(tdp); return (error); } #endif *vpp = tdp; cnp->cn_flags |= SAVENAME; return (0); } if (dd_ino != NULL) return (0); /* * Step through the translation in the name. We do not `vput' the * directory because we may need it again if a symbolic link * is relative to the current directory. Instead we save it * unlocked as "pdp". We must get the target inode before unlocking * the directory to insure that the inode will not be removed * before we get it. We prevent deadlock by always fetching * inodes from the root, moving down the directory tree. Thus * when following backward pointers ".." we must unlock the * parent directory before getting the requested directory. * There is a potential race condition here if both the current * and parent directories are removed before the VFS_VGET for the * inode associated with ".." returns. We hope that this occurs * infrequently since we cannot avoid this race condition without * implementing a sophisticated deadlock detection algorithm. * Note also that this simple deadlock detection scheme will not * work if the filesystem has any hard links other than ".." * that point backwards in the directory structure. */ pdp = vdp; if (flags & ISDOTDOT) { error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp); if (error) return (error); /* * Recheck that ".." entry in the vdp directory points * to the inode we looked up before vdp lock was * dropped. */ error = ufs_lookup_ino(pdp, NULL, cnp, &ino1); if (error) { vput(tdp); return (error); } if (ino1 != ino) { vput(tdp); goto restart; } *vpp = tdp; } else if (dp->i_number == ino) { VREF(vdp); /* we want ourself, ie "." */ /* * When we lookup "." we still can be asked to lock it * differently. */ ltype = cnp->cn_lkflags & LK_TYPE_MASK; if (ltype != VOP_ISLOCKED(vdp)) { if (ltype == LK_EXCLUSIVE) vn_lock(vdp, LK_UPGRADE | LK_RETRY); else /* if (ltype == LK_SHARED) */ vn_lock(vdp, LK_DOWNGRADE | LK_RETRY); /* * Relock for the "." case may left us with * reclaimed vnode. */ if (vdp->v_iflag & VI_DOOMED) { vrele(vdp); return (ENOENT); } } *vpp = vdp; } else { error = VFS_VGET(pdp->v_mount, ino, cnp->cn_lkflags, &tdp); if (error) return (error); *vpp = tdp; } /* * Insert name into cache if appropriate. */ if (cnp->cn_flags & MAKEENTRY) cache_enter(vdp, *vpp, cnp); return (0); } void ufs_dirbad(ip, offset, how) struct inode *ip; doff_t offset; char *how; { struct mount *mp; mp = ITOV(ip)->v_mount; if ((mp->mnt_flag & MNT_RDONLY) == 0) panic("ufs_dirbad: %s: bad dir ino %ju at offset %ld: %s", mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, (long)offset, how); else (void)printf("%s: bad dir ino %ju at offset %ld: %s\n", mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, (long)offset, how); } /* * Do consistency checking on a directory entry: * record length must be multiple of 4 * entry must fit in rest of its DIRBLKSIZ block * record must be large enough to contain entry * name is not longer than MAXNAMLEN * name must be as long as advertised, and null terminated */ int ufs_dirbadentry(dp, ep, entryoffsetinblock) struct vnode *dp; struct direct *ep; int entryoffsetinblock; { int i, namlen; # if (BYTE_ORDER == LITTLE_ENDIAN) if (OFSFMT(dp)) namlen = ep->d_type; else namlen = ep->d_namlen; # else namlen = ep->d_namlen; # endif if ((ep->d_reclen & 0x3) != 0 || ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || ep->d_reclen < DIRSIZ(OFSFMT(dp), ep) || namlen > MAXNAMLEN) { /*return (1); */ printf("First bad\n"); goto bad; } if (ep->d_ino == 0) return (0); for (i = 0; i < namlen; i++) if (ep->d_name[i] == '\0') { /*return (1); */ printf("Second bad\n"); goto bad; } if (ep->d_name[i]) goto bad; return (0); bad: return (1); } /* * Construct a new directory entry after a call to namei, using the * parameters that it left in the componentname argument cnp. The * argument ip is the inode to which the new directory entry will refer. */ void ufs_makedirentry(ip, cnp, newdirp) struct inode *ip; struct componentname *cnp; struct direct *newdirp; { #ifdef INVARIANTS if ((cnp->cn_flags & SAVENAME) == 0) panic("ufs_makedirentry: missing name"); #endif newdirp->d_ino = ip->i_number; newdirp->d_namlen = cnp->cn_namelen; bcopy(cnp->cn_nameptr, newdirp->d_name, (unsigned)cnp->cn_namelen + 1); if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0) newdirp->d_type = IFTODT(ip->i_mode); else { newdirp->d_type = 0; # if (BYTE_ORDER == LITTLE_ENDIAN) { u_char tmp = newdirp->d_namlen; newdirp->d_namlen = newdirp->d_type; newdirp->d_type = tmp; } # endif } } /* * Write a directory entry after a call to namei, using the parameters * that it left in nameidata. The argument dirp is the new directory * entry contents. Dvp is a pointer to the directory to be written, * which was left locked by namei. Remaining parameters (dp->i_offset, * dp->i_count) indicate how the space for the new entry is to be obtained. * Non-null bp indicates that a directory is being created (for the * soft dependency code). */ int ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename) struct vnode *dvp; struct vnode *tvp; struct direct *dirp; struct componentname *cnp; struct buf *newdirbp; int isrename; { struct ucred *cr; struct thread *td; int newentrysize; struct inode *dp; struct buf *bp; u_int dsize; struct direct *ep, *nep; int error, ret, blkoff, loc, spacefree, flags, namlen; char *dirbuf; td = curthread; /* XXX */ cr = td->td_ucred; dp = VTOI(dvp); newentrysize = DIRSIZ(OFSFMT(dvp), dirp); if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no * space in the directory. Here, dp->i_offset will * be on a directory block boundary and we will write the * new entry into a fresh block. */ if (dp->i_offset & (DIRBLKSIZ - 1)) panic("ufs_direnter: newblk"); flags = BA_CLRBUF; if (!DOINGSOFTDEP(dvp) && !DOINGASYNC(dvp)) flags |= IO_SYNC; #ifdef QUOTA if ((error = getinoquota(dp)) != 0) { if (DOINGSOFTDEP(dvp) && newdirbp != NULL) bdwrite(newdirbp); return (error); } #endif if ((error = UFS_BALLOC(dvp, (off_t)dp->i_offset, DIRBLKSIZ, cr, flags, &bp)) != 0) { if (DOINGSOFTDEP(dvp) && newdirbp != NULL) bdwrite(newdirbp); return (error); } dp->i_size = dp->i_offset + DIRBLKSIZ; DIP_SET(dp, i_size, dp->i_size); dp->i_flag |= IN_CHANGE | IN_UPDATE; vnode_pager_setsize(dvp, (u_long)dp->i_size); dirp->d_reclen = DIRBLKSIZ; blkoff = dp->i_offset & (VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1); bcopy((caddr_t)dirp, (caddr_t)bp->b_data + blkoff,newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) { ufsdirhash_newblk(dp, dp->i_offset); ufsdirhash_add(dp, dirp, dp->i_offset); ufsdirhash_checkblock(dp, (char *)bp->b_data + blkoff, dp->i_offset); } #endif if (DOINGSOFTDEP(dvp)) { /* * Ensure that the entire newly allocated block is a * valid directory so that future growth within the * block does not have to ensure that the block is * written before the inode. */ blkoff += DIRBLKSIZ; while (blkoff < bp->b_bcount) { ((struct direct *) (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ; blkoff += DIRBLKSIZ; } if (softdep_setup_directory_add(bp, dp, dp->i_offset, dirp->d_ino, newdirbp, 1)) dp->i_flag |= IN_NEEDSYNC; if (newdirbp) bdwrite(newdirbp); bdwrite(bp); if ((dp->i_flag & IN_NEEDSYNC) == 0) return (UFS_UPDATE(dvp, 0)); /* * We have just allocated a directory block in an * indirect block. We must prevent holes in the * directory created if directory entries are * written out of order. To accomplish this we * fsync when we extend a directory into indirects. * During rename it's not safe to drop the tvp lock * so sync must be delayed until it is. * * This synchronous step could be removed if fsck and * the kernel were taught to fill in sparse * directories rather than panic. */ if (isrename) return (0); if (tvp != NULL) VOP_UNLOCK(tvp, 0); (void) VOP_FSYNC(dvp, MNT_WAIT, td); if (tvp != NULL) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); return (error); } if (DOINGASYNC(dvp)) { bdwrite(bp); return (UFS_UPDATE(dvp, 0)); } error = bwrite(bp); ret = UFS_UPDATE(dvp, 1); if (error == 0) return (ret); return (error); } /* * If dp->i_count is non-zero, then namei found space for the new * entry in the range dp->i_offset to dp->i_offset + dp->i_count * in the directory. To use this space, we may have to compact * the entries located there, by copying them together towards the * beginning of the block, leaving the free space in one usable * chunk at the end. */ /* * Increase size of directory if entry eats into new space. * This should never push the size past a new multiple of * DIRBLKSIZE. * * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. */ if (dp->i_offset + dp->i_count > dp->i_size) { dp->i_size = dp->i_offset + dp->i_count; DIP_SET(dp, i_size, dp->i_size); } /* * Get the block containing the space for the new directory entry. */ error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp); if (error) { if (DOINGSOFTDEP(dvp) && newdirbp != NULL) bdwrite(newdirbp); return (error); } /* * Find space for the new entry. In the simple case, the entry at * offset base will have the space. If it does not, then namei * arranged that compacting the region dp->i_offset to * dp->i_offset + dp->i_count would yield the space. */ ep = (struct direct *)dirbuf; dsize = ep->d_ino ? DIRSIZ(OFSFMT(dvp), ep) : 0; spacefree = ep->d_reclen - dsize; for (loc = ep->d_reclen; loc < dp->i_count; ) { nep = (struct direct *)(dirbuf + loc); /* Trim the existing slot (NB: dsize may be zero). */ ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); /* Read nep->d_reclen now as the bcopy() may clobber it. */ loc += nep->d_reclen; if (nep->d_ino == 0) { /* * A mid-block unused entry. Such entries are * never created by the kernel, but fsck_ffs * can create them (and it doesn't fix them). * * Add up the free space, and initialise the * relocated entry since we don't bcopy it. */ spacefree += nep->d_reclen; ep->d_ino = 0; dsize = 0; continue; } dsize = DIRSIZ(OFSFMT(dvp), nep); spacefree += nep->d_reclen - dsize; #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_move(dp, nep, dp->i_offset + ((char *)nep - dirbuf), dp->i_offset + ((char *)ep - dirbuf)); #endif if (DOINGSOFTDEP(dvp)) softdep_change_directoryentry_offset(bp, dp, dirbuf, (caddr_t)nep, (caddr_t)ep, dsize); else bcopy((caddr_t)nep, (caddr_t)ep, dsize); } /* * Here, `ep' points to a directory entry containing `dsize' in-use * bytes followed by `spacefree' unused bytes. If ep->d_ino == 0, * then the entry is completely unused (dsize == 0). The value * of ep->d_reclen is always indeterminate. * * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ # if (BYTE_ORDER == LITTLE_ENDIAN) if (OFSFMT(dvp)) namlen = ep->d_type; else namlen = ep->d_namlen; # else namlen = ep->d_namlen; # endif if (ep->d_ino == 0 || (ep->d_ino == WINO && namlen == dirp->d_namlen && bcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) { if (spacefree + dsize < newentrysize) panic("ufs_direnter: compact1"); dirp->d_reclen = spacefree + dsize; } else { if (spacefree < newentrysize) panic("ufs_direnter: compact2"); dirp->d_reclen = spacefree; ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); } #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL && (ep->d_ino == 0 || dirp->d_reclen == spacefree)) ufsdirhash_add(dp, dirp, dp->i_offset + ((char *)ep - dirbuf)); #endif bcopy((caddr_t)dirp, (caddr_t)ep, (u_int)newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_checkblock(dp, dirbuf - (dp->i_offset & (DIRBLKSIZ - 1)), dp->i_offset & ~(DIRBLKSIZ - 1)); #endif if (DOINGSOFTDEP(dvp)) { (void) softdep_setup_directory_add(bp, dp, dp->i_offset + (caddr_t)ep - dirbuf, dirp->d_ino, newdirbp, 0); if (newdirbp != NULL) bdwrite(newdirbp); bdwrite(bp); } else { if (DOINGASYNC(dvp)) { bdwrite(bp); error = 0; } else { error = bwrite(bp); } } dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * If all went well, and the directory can be shortened, proceed * with the truncation. Note that we have to unlock the inode for * the entry that we just entered, as the truncation may need to * lock other inodes which can lead to deadlock if we also hold a * lock on the newly entered node. */ if (isrename == 0 && error == 0 && dp->i_endoff && dp->i_endoff < dp->i_size) { if (tvp != NULL) VOP_UNLOCK(tvp, 0); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_dirtrunc(dp, dp->i_endoff); #endif (void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_NORMAL | IO_SYNC, cr); if (tvp != NULL) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); } return (error); } /* * Remove a directory entry after a call to namei, using * the parameters which it left in nameidata. The entry * dp->i_offset contains the offset into the directory of the * entry to be eliminated. The dp->i_count field contains the * size of the previous record in the directory. If this * is 0, the first entry is being deleted, so we need only * zero the inode number to mark the entry as free. If the * entry is not the first in the directory, we must reclaim * the space of the now empty record by adding the record size * to the size of the previous entry. */ int ufs_dirremove(dvp, ip, flags, isrmdir) struct vnode *dvp; struct inode *ip; int flags; int isrmdir; { struct inode *dp; struct direct *ep, *rep; struct buf *bp; int error; dp = VTOI(dvp); /* * Adjust the link count early so softdep can block if necessary. */ if (ip) { ip->i_effnlink--; if (DOINGSOFTDEP(dvp)) { softdep_setup_unlink(dp, ip); } else { ip->i_nlink--; DIP_SET(ip, i_nlink, ip->i_nlink); ip->i_flag |= IN_CHANGE; } } if (flags & DOWHITEOUT) { /* * Whiteout entry: set d_ino to WINO. */ if ((error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) return (error); ep->d_ino = WINO; ep->d_type = DT_WHT; goto out; } if ((error = UFS_BLKATOFF(dvp, (off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0) return (error); /* Set 'rep' to the entry being removed. */ if (dp->i_count == 0) rep = ep; else rep = (struct direct *)((char *)ep + ep->d_reclen); #ifdef UFS_DIRHASH /* * Remove the dirhash entry. This is complicated by the fact * that `ep' is the previous entry when dp->i_count != 0. */ if (dp->i_dirhash != NULL) ufsdirhash_remove(dp, rep, dp->i_offset); #endif if (ip && rep->d_ino != ip->i_number) panic("ufs_dirremove: ip %ju does not match dirent ino %ju\n", (uintmax_t)ip->i_number, (uintmax_t)rep->d_ino); if (dp->i_count == 0) { /* * First entry in block: set d_ino to zero. */ ep->d_ino = 0; } else { /* * Collapse new free space into previous entry. */ ep->d_reclen += rep->d_reclen; } #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_checkblock(dp, (char *)ep - ((dp->i_offset - dp->i_count) & (DIRBLKSIZ - 1)), dp->i_offset & ~(DIRBLKSIZ - 1)); #endif out: error = 0; if (DOINGSOFTDEP(dvp)) { if (ip) softdep_setup_remove(bp, dp, ip, isrmdir); if (softdep_slowdown(dvp)) error = bwrite(bp); else bdwrite(bp); } else { if (flags & DOWHITEOUT) error = bwrite(bp); else if (DOINGASYNC(dvp) && dp->i_count != 0) bdwrite(bp); else error = bwrite(bp); } dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * If the last named reference to a snapshot goes away, * drop its snapshot reference so that it will be reclaimed * when last open reference goes away. */ if (ip != 0 && (ip->i_flags & SF_SNAPSHOT) != 0 && ip->i_effnlink == 0) UFS_SNAPGONE(ip); return (error); } /* * Rewrite an existing directory entry to point at the inode * supplied. The parameters describing the directory entry are * set up by a call to namei. */ int ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir) struct inode *dp, *oip; ino_t newinum; int newtype; int isrmdir; { struct buf *bp; struct direct *ep; struct vnode *vdp = ITOV(dp); int error; /* * Drop the link before we lock the buf so softdep can block if * necessary. */ oip->i_effnlink--; if (DOINGSOFTDEP(vdp)) { softdep_setup_unlink(dp, oip); } else { oip->i_nlink--; DIP_SET(oip, i_nlink, oip->i_nlink); oip->i_flag |= IN_CHANGE; } error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp); if (error) return (error); if (ep->d_namlen == 2 && ep->d_name[1] == '.' && ep->d_name[0] == '.' && ep->d_ino != oip->i_number) { brelse(bp); return (EIDRM); } ep->d_ino = newinum; if (!OFSFMT(vdp)) ep->d_type = newtype; if (DOINGSOFTDEP(vdp)) { softdep_setup_directory_change(bp, dp, oip, newinum, isrmdir); bdwrite(bp); } else { if (DOINGASYNC(vdp)) { bdwrite(bp); error = 0; } else { error = bwrite(bp); } } dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * If the last named reference to a snapshot goes away, * drop its snapshot reference so that it will be reclaimed * when last open reference goes away. */ if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_effnlink == 0) UFS_SNAPGONE(oip); return (error); } /* * Check if a directory is empty or not. * Inode supplied must be locked. * * Using a struct dirtemplate here is not precisely * what we want, but better than using a struct direct. * * NB: does not handle corrupted directories. */ int ufs_dirempty(ip, parentino, cred) struct inode *ip; ino_t parentino; struct ucred *cred; { doff_t off; struct dirtemplate dbuf; struct direct *dp = (struct direct *)&dbuf; int error, namlen; ssize_t count; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) for (off = 0; off < ip->i_size; off += dp->d_reclen) { error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, &count, (struct thread *)0); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. */ if (error || count != 0) return (0); /* avoid infinite loops */ if (dp->d_reclen == 0) return (0); /* skip empty entries */ if (dp->d_ino == 0 || dp->d_ino == WINO) continue; /* accept only "." and ".." */ # if (BYTE_ORDER == LITTLE_ENDIAN) if (OFSFMT(ITOV(ip))) namlen = dp->d_type; else namlen = dp->d_namlen; # else namlen = dp->d_namlen; # endif if (namlen > 2) return (0); if (dp->d_name[0] != '.') return (0); /* * At this point namlen must be 1 or 2. * 1 implies ".", 2 implies ".." if second * char is also "." */ if (namlen == 1 && dp->d_ino == ip->i_number) continue; if (dp->d_name[1] == '.' && dp->d_ino == parentino) continue; return (0); } return (1); } static int ufs_dir_dd_ino(struct vnode *vp, struct ucred *cred, ino_t *dd_ino) { struct dirtemplate dirbuf; int error, namlen; if (vp->v_type != VDIR) return (ENOTDIR); error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL, NULL); if (error != 0) return (error); #if (BYTE_ORDER == LITTLE_ENDIAN) if (OFSFMT(vp)) namlen = dirbuf.dotdot_type; else namlen = dirbuf.dotdot_namlen; #else namlen = dirbuf.dotdot_namlen; #endif if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') return (ENOTDIR); *dd_ino = dirbuf.dotdot_ino; return (0); } /* * Check if source directory is in the path of the target directory. */ int ufs_checkpath(ino_t source_ino, ino_t parent_ino, struct inode *target, struct ucred *cred, ino_t *wait_ino) { struct mount *mp; struct vnode *tvp, *vp, *vp1; int error; ino_t dd_ino; vp = tvp = ITOV(target); mp = vp->v_mount; *wait_ino = 0; if (target->i_number == source_ino) return (EEXIST); if (target->i_number == parent_ino) return (0); if (target->i_number == ROOTINO) return (0); - error = 0; for (;;) { error = ufs_dir_dd_ino(vp, cred, &dd_ino); if (error != 0) break; if (dd_ino == source_ino) { error = EINVAL; break; } if (dd_ino == ROOTINO) break; if (dd_ino == parent_ino) break; error = VFS_VGET(mp, dd_ino, LK_SHARED | LK_NOWAIT, &vp1); if (error != 0) { *wait_ino = dd_ino; break; } /* Recheck that ".." still points to vp1 after relock of vp */ error = ufs_dir_dd_ino(vp, cred, &dd_ino); if (error != 0) { vput(vp1); break; } /* Redo the check of ".." if directory was reparented */ if (dd_ino != VTOI(vp1)->i_number) { vput(vp1); continue; } if (vp != tvp) vput(vp); vp = vp1; } if (error == ENOTDIR) panic("checkpath: .. not a directory\n"); if (vp != tvp) vput(vp); return (error); } Index: user/attilio/vmc-playground/sys/vm/vm_kern.c =================================================================== --- user/attilio/vmc-playground/sys/vm/vm_kern.c (revision 246333) +++ user/attilio/vmc-playground/sys/vm/vm_kern.c (revision 246334) @@ -1,706 +1,717 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)vm_kern.c 8.3 (Berkeley) 1/12/94 * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Authors: Avadis Tevanian, Jr., Michael Wayne Young * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * Kernel memory management. */ #include __FBSDID("$FreeBSD$"); #include #include #include /* for ticks and hz */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include vm_map_t kernel_map=0; vm_map_t kmem_map=0; vm_map_t exec_map=0; vm_map_t pipe_map; vm_map_t buffer_map=0; const void *zero_region; CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0); +SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, + NULL, VM_MIN_KERNEL_ADDRESS, "Min kernel address"); + +SYSCTL_ULONG(_vm, OID_AUTO, max_kernel_address, CTLFLAG_RD, +#ifdef __sparc64__ + &vm_max_kernel_address, 0, +#else + NULL, VM_MAX_KERNEL_ADDRESS, +#endif + "Max kernel address"); + /* * kmem_alloc_nofault: * * Allocate a virtual address range with no underlying object and * no initial mapping to physical memory. Any mapping from this * range to physical memory must be explicitly created prior to * its use, typically with pmap_qenter(). Any attempt to create * a mapping on demand through vm_fault() will result in a panic. */ vm_offset_t kmem_alloc_nofault(map, size) vm_map_t map; vm_size_t size; { vm_offset_t addr; int result; size = round_page(size); addr = vm_map_min(map); result = vm_map_find(map, NULL, 0, &addr, size, VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT); if (result != KERN_SUCCESS) { return (0); } return (addr); } /* * kmem_alloc_nofault_space: * * Allocate a virtual address range with no underlying object and * no initial mapping to physical memory within the specified * address space. Any mapping from this range to physical memory * must be explicitly created prior to its use, typically with * pmap_qenter(). Any attempt to create a mapping on demand * through vm_fault() will result in a panic. */ vm_offset_t kmem_alloc_nofault_space(map, size, find_space) vm_map_t map; vm_size_t size; int find_space; { vm_offset_t addr; int result; size = round_page(size); addr = vm_map_min(map); result = vm_map_find(map, NULL, 0, &addr, size, find_space, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT); if (result != KERN_SUCCESS) { return (0); } return (addr); } /* * Allocate wired-down memory in the kernel's address map * or a submap. */ vm_offset_t kmem_alloc(map, size) vm_map_t map; vm_size_t size; { vm_offset_t addr; vm_offset_t offset; size = round_page(size); /* * Use the kernel object for wired-down kernel pages. Assume that no * region of the kernel object is referenced more than once. */ /* * Locate sufficient space in the map. This will give us the final * virtual address for the new memory, and thus will tell us the * offset within the kernel map. */ vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr)) { vm_map_unlock(map); return (0); } offset = addr - VM_MIN_KERNEL_ADDRESS; vm_object_reference(kernel_object); vm_map_insert(map, kernel_object, offset, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); vm_map_unlock(map); /* * And finally, mark the data as non-pageable. */ (void) vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES); return (addr); } /* * Allocates a region from the kernel address map and physical pages * within the specified address range to the kernel object. Creates a * wired mapping from this region to these pages, and returns the * region's starting virtual address. The allocated pages are not * necessarily physically contiguous. If M_ZERO is specified through the * given flags, then the pages are zeroed before they are mapped. */ vm_offset_t kmem_alloc_attr(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr) { vm_object_t object = kernel_object; vm_offset_t addr; vm_ooffset_t end_offset, offset; vm_page_t m; int pflags, tries; size = round_page(size); vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr)) { vm_map_unlock(map); return (0); } offset = addr - VM_MIN_KERNEL_ADDRESS; vm_object_reference(object); vm_map_insert(map, object, offset, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); pflags = malloc2vm_flags(flags) | VM_ALLOC_NOBUSY; VM_OBJECT_LOCK(object); end_offset = offset + size; for (; offset < end_offset; offset += PAGE_SIZE) { tries = 0; retry: m = vm_page_alloc_contig(object, OFF_TO_IDX(offset), pflags, 1, low, high, PAGE_SIZE, 0, memattr); if (m == NULL) { VM_OBJECT_UNLOCK(object); if (tries < ((flags & M_NOWAIT) != 0 ? 1 : 3)) { vm_map_unlock(map); vm_pageout_grow_cache(tries, low, high); vm_map_lock(map); VM_OBJECT_LOCK(object); tries++; goto retry; } /* * Since the pages that were allocated by any previous * iterations of this loop are not busy, they can be * freed by vm_object_page_remove(), which is called * by vm_map_delete(). */ vm_map_delete(map, addr, addr + size); vm_map_unlock(map); return (0); } if ((flags & M_ZERO) && (m->flags & PG_ZERO) == 0) pmap_zero_page(m); m->valid = VM_PAGE_BITS_ALL; } VM_OBJECT_UNLOCK(object); vm_map_unlock(map); vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES); return (addr); } /* * Allocates a region from the kernel address map and physically * contiguous pages within the specified address range to the kernel * object. Creates a wired mapping from this region to these pages, and * returns the region's starting virtual address. If M_ZERO is specified * through the given flags, then the pages are zeroed before they are * mapped. */ vm_offset_t kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr) { vm_object_t object = kernel_object; vm_offset_t addr; vm_ooffset_t offset; vm_page_t end_m, m; int pflags, tries; size = round_page(size); vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr)) { vm_map_unlock(map); return (0); } offset = addr - VM_MIN_KERNEL_ADDRESS; vm_object_reference(object); vm_map_insert(map, object, offset, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); pflags = malloc2vm_flags(flags) | VM_ALLOC_NOBUSY; VM_OBJECT_LOCK(object); tries = 0; retry: m = vm_page_alloc_contig(object, OFF_TO_IDX(offset), pflags, atop(size), low, high, alignment, boundary, memattr); if (m == NULL) { VM_OBJECT_UNLOCK(object); if (tries < ((flags & M_NOWAIT) != 0 ? 1 : 3)) { vm_map_unlock(map); vm_pageout_grow_cache(tries, low, high); vm_map_lock(map); VM_OBJECT_LOCK(object); tries++; goto retry; } vm_map_delete(map, addr, addr + size); vm_map_unlock(map); return (0); } end_m = m + atop(size); for (; m < end_m; m++) { if ((flags & M_ZERO) && (m->flags & PG_ZERO) == 0) pmap_zero_page(m); m->valid = VM_PAGE_BITS_ALL; } VM_OBJECT_UNLOCK(object); vm_map_unlock(map); vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES); return (addr); } /* * kmem_free: * * Release a region of kernel virtual memory allocated * with kmem_alloc, and return the physical pages * associated with that region. * * This routine may not block on kernel maps. */ void kmem_free(map, addr, size) vm_map_t map; vm_offset_t addr; vm_size_t size; { (void) vm_map_remove(map, trunc_page(addr), round_page(addr + size)); } /* * kmem_suballoc: * * Allocates a map to manage a subrange * of the kernel virtual address space. * * Arguments are as follows: * * parent Map to take range from * min, max Returned endpoints of map * size Size of range to find * superpage_align Request that min is superpage aligned */ vm_map_t kmem_suballoc(vm_map_t parent, vm_offset_t *min, vm_offset_t *max, vm_size_t size, boolean_t superpage_align) { int ret; vm_map_t result; size = round_page(size); *min = vm_map_min(parent); ret = vm_map_find(parent, NULL, 0, min, size, superpage_align ? VMFS_ALIGNED_SPACE : VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL, MAP_ACC_NO_CHARGE); if (ret != KERN_SUCCESS) panic("kmem_suballoc: bad status return of %d", ret); *max = *min + size; result = vm_map_create(vm_map_pmap(parent), *min, *max); if (result == NULL) panic("kmem_suballoc: cannot create submap"); if (vm_map_submap(parent, *min, *max, result) != KERN_SUCCESS) panic("kmem_suballoc: unable to change range to submap"); return (result); } /* * kmem_malloc: * * Allocate wired-down memory in the kernel's address map for the higher * level kernel memory allocator (kern/kern_malloc.c). We cannot use * kmem_alloc() because we may need to allocate memory at interrupt * level where we cannot block (canwait == FALSE). * * This routine has its own private kernel submap (kmem_map) and object * (kmem_object). This, combined with the fact that only malloc uses * this routine, ensures that we will never block in map or object waits. * * We don't worry about expanding the map (adding entries) since entries * for wired maps are statically allocated. * * `map' is ONLY allowed to be kmem_map or one of the mbuf submaps to * which we never free. */ vm_offset_t kmem_malloc(map, size, flags) vm_map_t map; vm_size_t size; int flags; { vm_offset_t addr; int i, rv; size = round_page(size); addr = vm_map_min(map); /* * Locate sufficient space in the map. This will give us the final * virtual address for the new memory, and thus will tell us the * offset within the kernel map. */ vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr)) { vm_map_unlock(map); if ((flags & M_NOWAIT) == 0) { for (i = 0; i < 8; i++) { EVENTHANDLER_INVOKE(vm_lowmem, 0); uma_reclaim(); vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr) == 0) { break; } vm_map_unlock(map); tsleep(&i, 0, "nokva", (hz / 4) * (i + 1)); } if (i == 8) { panic("kmem_malloc(%ld): kmem_map too small: %ld total allocated", (long)size, (long)map->size); } } else { return (0); } } rv = kmem_back(map, addr, size, flags); vm_map_unlock(map); return (rv == KERN_SUCCESS ? addr : 0); } /* * kmem_back: * * Allocate physical pages for the specified virtual address range. */ int kmem_back(vm_map_t map, vm_offset_t addr, vm_size_t size, int flags) { vm_offset_t offset, i; vm_map_entry_t entry; vm_page_t m; int pflags; boolean_t found; KASSERT(vm_map_locked(map), ("kmem_back: map %p is not locked", map)); offset = addr - VM_MIN_KERNEL_ADDRESS; vm_object_reference(kmem_object); vm_map_insert(map, kmem_object, offset, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); /* * Assert: vm_map_insert() will never be able to extend the * previous entry so vm_map_lookup_entry() will find a new * entry exactly corresponding to this address range and it * will have wired_count == 0. */ found = vm_map_lookup_entry(map, addr, &entry); KASSERT(found && entry->start == addr && entry->end == addr + size && entry->wired_count == 0 && (entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0, ("kmem_back: entry not found or misaligned")); pflags = malloc2vm_flags(flags) | VM_ALLOC_WIRED; VM_OBJECT_LOCK(kmem_object); for (i = 0; i < size; i += PAGE_SIZE) { retry: m = vm_page_alloc(kmem_object, OFF_TO_IDX(offset + i), pflags); /* * Ran out of space, free everything up and return. Don't need * to lock page queues here as we know that the pages we got * aren't on any queues. */ if (m == NULL) { if ((flags & M_NOWAIT) == 0) { VM_OBJECT_UNLOCK(kmem_object); entry->eflags |= MAP_ENTRY_IN_TRANSITION; vm_map_unlock(map); VM_WAIT; vm_map_lock(map); KASSERT( (entry->eflags & (MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_NEEDS_WAKEUP)) == MAP_ENTRY_IN_TRANSITION, ("kmem_back: volatile entry")); entry->eflags &= ~MAP_ENTRY_IN_TRANSITION; VM_OBJECT_LOCK(kmem_object); goto retry; } /* * Free the pages before removing the map entry. * They are already marked busy. Calling * vm_map_delete before the pages has been freed or * unbusied will cause a deadlock. */ while (i != 0) { i -= PAGE_SIZE; m = vm_page_lookup(kmem_object, OFF_TO_IDX(offset + i)); vm_page_unwire(m, 0); vm_page_free(m); } VM_OBJECT_UNLOCK(kmem_object); vm_map_delete(map, addr, addr + size); return (KERN_NO_SPACE); } if (flags & M_ZERO && (m->flags & PG_ZERO) == 0) pmap_zero_page(m); m->valid = VM_PAGE_BITS_ALL; KASSERT((m->oflags & VPO_UNMANAGED) != 0, ("kmem_malloc: page %p is managed", m)); } VM_OBJECT_UNLOCK(kmem_object); /* * Mark map entry as non-pageable. Repeat the assert. */ KASSERT(entry->start == addr && entry->end == addr + size && entry->wired_count == 0, ("kmem_back: entry not found or misaligned after allocation")); entry->wired_count = 1; /* * At this point, the kmem_object must be unlocked because * vm_map_simplify_entry() calls vm_object_deallocate(), which * locks the kmem_object. */ vm_map_simplify_entry(map, entry); /* * Loop thru pages, entering them in the pmap. */ VM_OBJECT_LOCK(kmem_object); for (i = 0; i < size; i += PAGE_SIZE) { m = vm_page_lookup(kmem_object, OFF_TO_IDX(offset + i)); /* * Because this is kernel_pmap, this call will not block. */ pmap_enter(kernel_pmap, addr + i, VM_PROT_ALL, m, VM_PROT_ALL, TRUE); vm_page_wakeup(m); } VM_OBJECT_UNLOCK(kmem_object); return (KERN_SUCCESS); } /* * kmem_alloc_wait: * * Allocates pageable memory from a sub-map of the kernel. If the submap * has no room, the caller sleeps waiting for more memory in the submap. * * This routine may block. */ vm_offset_t kmem_alloc_wait(map, size) vm_map_t map; vm_size_t size; { vm_offset_t addr; size = round_page(size); if (!swap_reserve(size)) return (0); for (;;) { /* * To make this work for more than one map, use the map's lock * to lock out sleepers/wakers. */ vm_map_lock(map); if (vm_map_findspace(map, vm_map_min(map), size, &addr) == 0) break; /* no space now; see if we can ever get space */ if (vm_map_max(map) - vm_map_min(map) < size) { vm_map_unlock(map); swap_release(size); return (0); } map->needs_wakeup = TRUE; vm_map_unlock_and_wait(map, 0); } vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, MAP_ACC_CHARGED); vm_map_unlock(map); return (addr); } /* * kmem_free_wakeup: * * Returns memory to a submap of the kernel, and wakes up any processes * waiting for memory in that map. */ void kmem_free_wakeup(map, addr, size) vm_map_t map; vm_offset_t addr; vm_size_t size; { vm_map_lock(map); (void) vm_map_delete(map, trunc_page(addr), round_page(addr + size)); if (map->needs_wakeup) { map->needs_wakeup = FALSE; vm_map_wakeup(map); } vm_map_unlock(map); } static void kmem_init_zero_region(void) { vm_offset_t addr, i; vm_page_t m; int error; /* * Map a single physical page of zeros to a larger virtual range. * This requires less looping in places that want large amounts of * zeros, while not using much more physical resources. */ addr = kmem_alloc_nofault(kernel_map, ZERO_REGION_SIZE); m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO); if ((m->flags & PG_ZERO) == 0) pmap_zero_page(m); for (i = 0; i < ZERO_REGION_SIZE; i += PAGE_SIZE) pmap_qenter(addr + i, &m, 1); error = vm_map_protect(kernel_map, addr, addr + ZERO_REGION_SIZE, VM_PROT_READ, TRUE); KASSERT(error == 0, ("error=%d", error)); zero_region = (const void *)addr; } /* * kmem_init: * * Create the kernel map; insert a mapping covering kernel text, * data, bss, and all space allocated thus far (`boostrap' data). The * new map will thus map the range between VM_MIN_KERNEL_ADDRESS and * `start' as allocated, and the range between `start' and `end' as free. */ void kmem_init(start, end) vm_offset_t start, end; { vm_map_t m; m = vm_map_create(kernel_pmap, VM_MIN_KERNEL_ADDRESS, end); m->system_map = 1; vm_map_lock(m); /* N.B.: cannot use kgdb to debug, starting with this assignment ... */ kernel_map = m; (void) vm_map_insert(m, NULL, (vm_ooffset_t) 0, #ifdef __amd64__ KERNBASE, #else VM_MIN_KERNEL_ADDRESS, #endif start, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT); /* ... and ending with the completion of the above `insert' */ vm_map_unlock(m); kmem_init_zero_region(); } #ifdef DIAGNOSTIC /* * Allow userspace to directly trigger the VM drain routine for testing * purposes. */ static int debug_vm_lowmem(SYSCTL_HANDLER_ARGS) { int error, i; i = 0; error = sysctl_handle_int(oidp, &i, 0, req); if (error) return (error); if (i) EVENTHANDLER_INVOKE(vm_lowmem, 0); return (0); } SYSCTL_PROC(_debug, OID_AUTO, vm_lowmem, CTLTYPE_INT | CTLFLAG_RW, 0, 0, debug_vm_lowmem, "I", "set to trigger vm_lowmem event"); #endif Index: user/attilio/vmc-playground/sys =================================================================== --- user/attilio/vmc-playground/sys (revision 246333) +++ user/attilio/vmc-playground/sys (revision 246334) Property changes on: user/attilio/vmc-playground/sys ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /head/sys:r246295-246332 Merged /user/attilio/vmcontention/sys:r246320-246333 Index: user/attilio/vmc-playground/usr.bin/bmake/Makefile.config =================================================================== --- user/attilio/vmc-playground/usr.bin/bmake/Makefile.config (nonexistent) +++ user/attilio/vmc-playground/usr.bin/bmake/Makefile.config (revision 246334) @@ -0,0 +1,21 @@ +# This is a generated file, do NOT edit! +# See contrib/bmake/bsd.after-import.mk +# +# $FreeBSD$ + +SRCTOP?= ${.CURDIR:H:H} + +# things set by configure + +prefix= /usr +srcdir= ${SRCTOP}/contrib/bmake +CC?= gcc +DEFAULT_SYS_PATH= .../share/mk:/usr/share/mk + +CPPFLAGS+= +CFLAGS+= ${CPPFLAGS} -DHAVE_CONFIG_H +LDFLAGS= +LIBOBJS= ${LIBOBJDIR}stresep$U.o +LDADD= +USE_META= yes +FILEMON_H= /usr/include/dev/filemon/filemon.h Property changes on: user/attilio/vmc-playground/usr.bin/bmake/Makefile.config ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/attilio/vmc-playground/usr.bin/bmake/unit-tests/Makefile =================================================================== --- user/attilio/vmc-playground/usr.bin/bmake/unit-tests/Makefile (revision 246333) +++ user/attilio/vmc-playground/usr.bin/bmake/unit-tests/Makefile (revision 246334) @@ -1,105 +1,107 @@ # This is a generated file, do NOT edit! # See contrib/bmake/bsd.after-import.mk # # $FreeBSD$ SRCTOP?= ${.CURDIR:H:H:H} # $Id: Makefile.in,v 1.40 2012/12/28 21:28:19 sjg Exp $ # # $NetBSD: Makefile,v 1.35 2012/11/09 19:08:28 sjg Exp $ # # Unit tests for make(1) # The main targets are: # # all: run all the tests # test: run 'all', capture output and compare to expected results # accept: move generated output to expected results # # Adding a test case. # Each feature should get its own set of tests in its own suitably # named makefile which should be added to SUBFILES to hook it in. # srcdir= ${SRCTOP}/contrib/bmake/unit-tests .MAIN: all UNIT_TESTS:= ${srcdir} # Simple sub-makefiles - we run them as a black box # keep the list sorted. SUBFILES= \ comment \ cond1 \ error \ export \ export-all \ doterror \ dotwait \ forloop \ forsubst \ hash \ misc \ moderrs \ modmatch \ modmisc \ modorder \ modts \ modword \ order \ phony-end \ posix \ qequals \ sysv \ ternary \ unexport \ unexport-env \ varcmd all: ${SUBFILES} flags.doterror= flags.order=-j1 # the tests are actually done with sub-makes. .PHONY: ${SUBFILES} .PRECIOUS: ${SUBFILES} ${SUBFILES}: -@${.MAKE} ${flags.$@:U-k} -f ${UNIT_TESTS}/$@ clean: rm -f *.out *.fail *.core .sinclude TEST_MAKE?= ${.MAKE} TOOL_SED?= sed TOOL_TR?= tr TOOL_DIFF?= diff DIFF_FLAGS?= -u +.if defined(.PARSEDIR) # ensure consistent results from sort(1) LC_ALL= C LANG= C .export LANG LC_ALL +.endif # The driver. # We always pretend .MAKE was called 'make' # and strip ${.CURDIR}/ from the output # and replace anything after 'stopped in' with unit-tests # so the results can be compared. test: @echo "${TEST_MAKE} -f ${MAKEFILE} > ${.TARGET}.out 2>&1" @cd ${.OBJDIR} && ${TEST_MAKE} -f ${MAKEFILE} 2>&1 | \ ${TOOL_TR} -d '\015' | \ ${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}:,make:,' \ -e '/stopped/s, /.*, unit-tests,' \ -e 's,${.CURDIR:C/\./\\\./g}/,,g' \ -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' > ${.TARGET}.out || { \ tail ${.TARGET}.out; mv ${.TARGET}.out ${.TARGET}.fail; exit 1; } ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/${.TARGET}.exp ${.TARGET}.out accept: mv test.out ${srcdir}/test.exp Index: user/attilio/vmc-playground/usr.bin/join/join.c =================================================================== --- user/attilio/vmc-playground/usr.bin/join/join.c (revision 246333) +++ user/attilio/vmc-playground/usr.bin/join/join.c (revision 246334) @@ -1,665 +1,665 @@ /*- * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Steve Hayman of the Computer Science Department, Indiana University, * Michiro Hikida and David Goodenough. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1991, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)join.c 8.6 (Berkeley) 5/4/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include /* * There's a structure per input file which encapsulates the state of the * file. We repeatedly read lines from each file until we've read in all * the consecutive lines from the file with a common join field. Then we * compare the set of lines with an equivalent set from the other file. */ typedef struct { char *line; /* line */ u_long linealloc; /* line allocated count */ char **fields; /* line field(s) */ u_long fieldcnt; /* line field(s) count */ u_long fieldalloc; /* line field(s) allocated count */ } LINE; typedef struct { FILE *fp; /* file descriptor */ u_long joinf; /* join field (-1, -2, -j) */ int unpair; /* output unpairable lines (-a) */ u_long number; /* 1 for file 1, 2 for file 2 */ LINE *set; /* set of lines with same field */ int pushbool; /* if pushback is set */ u_long pushback; /* line on the stack */ u_long setcnt; /* set count */ u_long setalloc; /* set allocated count */ } INPUT; static INPUT input1 = { NULL, 0, 0, 1, NULL, 0, 0, 0, 0 }, input2 = { NULL, 0, 0, 2, NULL, 0, 0, 0, 0 }; typedef struct { u_long filenum; /* file number */ u_long fieldno; /* field number */ } OLIST; static OLIST *olist; /* output field list */ static u_long olistcnt; /* output field list count */ static u_long olistalloc; /* output field allocated count */ static int joinout = 1; /* show lines with matched join fields (-v) */ static int needsep; /* need separator character */ static int spans = 1; /* span multiple delimiters (-t) */ static char *empty; /* empty field replacement string (-e) */ static wchar_t default_tabchar[] = L" \t"; static wchar_t *tabchar = default_tabchar; /* delimiter characters (-t) */ static int cmp(LINE *, u_long, LINE *, u_long); static void fieldarg(char *); static void joinlines(INPUT *, INPUT *); static int mbscoll(const char *, const char *); static char *mbssep(char **, const wchar_t *); static void obsolete(char **); static void outfield(LINE *, u_long, int); static void outoneline(INPUT *, LINE *); static void outtwoline(INPUT *, LINE *, INPUT *, LINE *); static void slurp(INPUT *); static wchar_t *towcs(const char *); static void usage(void); int main(int argc, char *argv[]) { INPUT *F1, *F2; int aflag, ch, cval, vflag; char *end; setlocale(LC_ALL, ""); F1 = &input1; F2 = &input2; aflag = vflag = 0; obsolete(argv); while ((ch = getopt(argc, argv, "\01a:e:j:1:2:o:t:v:")) != -1) { switch (ch) { case '\01': /* See comment in obsolete(). */ aflag = 1; F1->unpair = F2->unpair = 1; break; case '1': if ((F1->joinf = strtol(optarg, &end, 10)) < 1) errx(1, "-1 option field number less than 1"); if (*end) errx(1, "illegal field number -- %s", optarg); --F1->joinf; break; case '2': if ((F2->joinf = strtol(optarg, &end, 10)) < 1) errx(1, "-2 option field number less than 1"); if (*end) errx(1, "illegal field number -- %s", optarg); --F2->joinf; break; case 'a': aflag = 1; switch(strtol(optarg, &end, 10)) { case 1: F1->unpair = 1; break; case 2: F2->unpair = 1; break; default: errx(1, "-a option file number not 1 or 2"); break; } if (*end) errx(1, "illegal file number -- %s", optarg); break; case 'e': empty = optarg; break; case 'j': if ((F1->joinf = F2->joinf = strtol(optarg, &end, 10)) < 1) errx(1, "-j option field number less than 1"); if (*end) errx(1, "illegal field number -- %s", optarg); --F1->joinf; --F2->joinf; break; case 'o': fieldarg(optarg); break; case 't': spans = 0; if (mbrtowc(&tabchar[0], optarg, MB_LEN_MAX, NULL) != strlen(optarg)) errx(1, "illegal tab character specification"); tabchar[1] = L'\0'; break; case 'v': vflag = 1; joinout = 0; switch (strtol(optarg, &end, 10)) { case 1: F1->unpair = 1; break; case 2: F2->unpair = 1; break; default: errx(1, "-v option file number not 1 or 2"); break; } if (*end) errx(1, "illegal file number -- %s", optarg); break; case '?': default: usage(); } } argc -= optind; argv += optind; if (aflag && vflag) errx(1, "the -a and -v options are mutually exclusive"); if (argc != 2) usage(); /* Open the files; "-" means stdin. */ if (!strcmp(*argv, "-")) F1->fp = stdin; else if ((F1->fp = fopen(*argv, "r")) == NULL) err(1, "%s", *argv); ++argv; if (!strcmp(*argv, "-")) F2->fp = stdin; else if ((F2->fp = fopen(*argv, "r")) == NULL) err(1, "%s", *argv); if (F1->fp == stdin && F2->fp == stdin) errx(1, "only one input file may be stdin"); slurp(F1); slurp(F2); while (F1->setcnt && F2->setcnt) { cval = cmp(F1->set, F1->joinf, F2->set, F2->joinf); if (cval == 0) { /* Oh joy, oh rapture, oh beauty divine! */ if (joinout) joinlines(F1, F2); slurp(F1); slurp(F2); } else if (cval < 0) { /* File 1 takes the lead... */ if (F1->unpair) joinlines(F1, NULL); slurp(F1); } else { /* File 2 takes the lead... */ if (F2->unpair) joinlines(F2, NULL); slurp(F2); } } /* * Now that one of the files is used up, optionally output any * remaining lines from the other file. */ if (F1->unpair) while (F1->setcnt) { joinlines(F1, NULL); slurp(F1); } if (F2->unpair) while (F2->setcnt) { joinlines(F2, NULL); slurp(F2); } exit(0); } static void slurp(INPUT *F) { LINE *lp, *lastlp, tmp; size_t len; int cnt; char *bp, *fieldp; /* * Read all of the lines from an input file that have the same * join field. */ F->setcnt = 0; for (lastlp = NULL;; ++F->setcnt) { /* * If we're out of space to hold line structures, allocate * more. Initialize the structure so that we know that this * is new space. */ if (F->setcnt == F->setalloc) { cnt = F->setalloc; F->setalloc += 50; if ((F->set = realloc(F->set, F->setalloc * sizeof(LINE))) == NULL) err(1, NULL); memset(F->set + cnt, 0, 50 * sizeof(LINE)); /* re-set lastlp in case it moved */ if (lastlp != NULL) lastlp = &F->set[F->setcnt - 1]; } /* * Get any pushed back line, else get the next line. Allocate * space as necessary. If taking the line from the stack swap * the two structures so that we don't lose space allocated to * either structure. This could be avoided by doing another * level of indirection, but it's probably okay as is. */ lp = &F->set[F->setcnt]; if (F->setcnt) lastlp = &F->set[F->setcnt - 1]; if (F->pushbool) { tmp = F->set[F->setcnt]; F->set[F->setcnt] = F->set[F->pushback]; F->set[F->pushback] = tmp; F->pushbool = 0; continue; } if ((bp = fgetln(F->fp, &len)) == NULL) return; if (lp->linealloc <= len + 1) { lp->linealloc += MAX(100, len + 1 - lp->linealloc); if ((lp->line = realloc(lp->line, lp->linealloc)) == NULL) err(1, NULL); } memmove(lp->line, bp, len); /* Replace trailing newline, if it exists. */ if (bp[len - 1] == '\n') lp->line[len - 1] = '\0'; else lp->line[len] = '\0'; bp = lp->line; /* Split the line into fields, allocate space as necessary. */ lp->fieldcnt = 0; while ((fieldp = mbssep(&bp, tabchar)) != NULL) { if (spans && *fieldp == '\0') continue; if (lp->fieldcnt == lp->fieldalloc) { lp->fieldalloc += 50; if ((lp->fields = realloc(lp->fields, lp->fieldalloc * sizeof(char *))) == NULL) err(1, NULL); } lp->fields[lp->fieldcnt++] = fieldp; } /* See if the join field value has changed. */ if (lastlp != NULL && cmp(lp, F->joinf, lastlp, F->joinf)) { F->pushbool = 1; F->pushback = F->setcnt; break; } } } static char * mbssep(char **stringp, const wchar_t *delim) { char *s, *tok; const wchar_t *spanp; wchar_t c, sc; size_t n; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { n = mbrtowc(&c, s, MB_LEN_MAX, NULL); if (n == (size_t)-1 || n == (size_t)-2) errc(1, EILSEQ, NULL); /* XXX */ s += n; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-n] = '\0'; *stringp = s; return (tok); } } while (sc != 0); } } static int cmp(LINE *lp1, u_long fieldno1, LINE *lp2, u_long fieldno2) { if (lp1->fieldcnt <= fieldno1) return (lp2->fieldcnt <= fieldno2 ? 0 : 1); if (lp2->fieldcnt <= fieldno2) return (-1); return (mbscoll(lp1->fields[fieldno1], lp2->fields[fieldno2])); } static int mbscoll(const char *s1, const char *s2) { wchar_t *w1, *w2; int ret; if (MB_CUR_MAX == 1) return (strcoll(s1, s2)); if ((w1 = towcs(s1)) == NULL || (w2 = towcs(s2)) == NULL) err(1, NULL); /* XXX */ ret = wcscoll(w1, w2); free(w1); free(w2); return (ret); } static wchar_t * towcs(const char *s) { wchar_t *wcs; size_t n; if ((n = mbsrtowcs(NULL, &s, 0, NULL)) == (size_t)-1) return (NULL); if ((wcs = malloc((n + 1) * sizeof(*wcs))) == NULL) return (NULL); mbsrtowcs(wcs, &s, n + 1, NULL); return (wcs); } static void joinlines(INPUT *F1, INPUT *F2) { u_long cnt1, cnt2; /* * Output the results of a join comparison. The output may be from * either file 1 or file 2 (in which case the first argument is the * file from which to output) or from both. */ if (F2 == NULL) { for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1) outoneline(F1, &F1->set[cnt1]); return; } for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1) for (cnt2 = 0; cnt2 < F2->setcnt; ++cnt2) outtwoline(F1, &F1->set[cnt1], F2, &F2->set[cnt2]); } static void outoneline(INPUT *F, LINE *lp) { u_long cnt; /* * Output a single line from one of the files, according to the * join rules. This happens when we are writing unmatched single * lines. Output empty fields in the right places. */ if (olist) for (cnt = 0; cnt < olistcnt; ++cnt) { if (olist[cnt].filenum == (unsigned)F->number) outfield(lp, olist[cnt].fieldno, 0); else if (olist[cnt].filenum == 0) outfield(lp, F->joinf, 0); else outfield(lp, 0, 1); } else for (cnt = 0; cnt < lp->fieldcnt; ++cnt) outfield(lp, cnt, 0); (void)printf("\n"); if (ferror(stdout)) err(1, "stdout"); needsep = 0; } static void outtwoline(INPUT *F1, LINE *lp1, INPUT *F2, LINE *lp2) { u_long cnt; /* Output a pair of lines according to the join list (if any). */ if (olist) for (cnt = 0; cnt < olistcnt; ++cnt) if (olist[cnt].filenum == 0) { if (lp1->fieldcnt >= F1->joinf) outfield(lp1, F1->joinf, 0); else outfield(lp2, F2->joinf, 0); } else if (olist[cnt].filenum == 1) outfield(lp1, olist[cnt].fieldno, 0); else /* if (olist[cnt].filenum == 2) */ outfield(lp2, olist[cnt].fieldno, 0); else { /* * Output the join field, then the remaining fields from F1 * and F2. */ outfield(lp1, F1->joinf, 0); for (cnt = 0; cnt < lp1->fieldcnt; ++cnt) if (F1->joinf != cnt) outfield(lp1, cnt, 0); for (cnt = 0; cnt < lp2->fieldcnt; ++cnt) if (F2->joinf != cnt) outfield(lp2, cnt, 0); } (void)printf("\n"); if (ferror(stdout)) err(1, "stdout"); needsep = 0; } static void outfield(LINE *lp, u_long fieldno, int out_empty) { if (needsep++) - (void)printf("%lc", *tabchar); + (void)printf("%lc", (wint_t)*tabchar); if (!ferror(stdout)) { if (lp->fieldcnt <= fieldno || out_empty) { if (empty != NULL) (void)printf("%s", empty); } else { if (*lp->fields[fieldno] == '\0') return; (void)printf("%s", lp->fields[fieldno]); } } if (ferror(stdout)) err(1, "stdout"); } /* * Convert an output list argument "2.1, 1.3, 2.4" into an array of output * fields. */ static void fieldarg(char *option) { u_long fieldno, filenum; char *end, *token; while ((token = strsep(&option, ", \t")) != NULL) { if (*token == '\0') continue; if (token[0] == '0') filenum = fieldno = 0; else if ((token[0] == '1' || token[0] == '2') && token[1] == '.') { filenum = token[0] - '0'; fieldno = strtol(token + 2, &end, 10); if (*end) errx(1, "malformed -o option field"); if (fieldno == 0) errx(1, "field numbers are 1 based"); --fieldno; } else errx(1, "malformed -o option field"); if (olistcnt == olistalloc) { olistalloc += 50; if ((olist = realloc(olist, olistalloc * sizeof(OLIST))) == NULL) err(1, NULL); } olist[olistcnt].filenum = filenum; olist[olistcnt].fieldno = fieldno; ++olistcnt; } } static void obsolete(char **argv) { size_t len; char **p, *ap, *t; while ((ap = *++argv) != NULL) { /* Return if "--". */ if (ap[0] == '-' && ap[1] == '-') return; /* skip if not an option */ if (ap[0] != '-') continue; switch (ap[1]) { case 'a': /* * The original join allowed "-a", which meant the * same as -a1 plus -a2. POSIX 1003.2, Draft 11.2 * only specifies this as "-a 1" and "a -2", so we * have to use another option flag, one that is * unlikely to ever be used or accidentally entered * on the command line. (Well, we could reallocate * the argv array, but that hardly seems worthwhile.) */ if (ap[2] == '\0' && (argv[1] == NULL || (strcmp(argv[1], "1") != 0 && strcmp(argv[1], "2") != 0))) { ap[1] = '\01'; warnx("-a option used without an argument; " "reverting to historical behavior"); } break; case 'j': /* * The original join allowed "-j[12] arg" and "-j arg". * Convert the former to "-[12] arg". Don't convert * the latter since getopt(3) can handle it. */ switch(ap[2]) { case '1': if (ap[3] != '\0') goto jbad; ap[1] = '1'; ap[2] = '\0'; break; case '2': if (ap[3] != '\0') goto jbad; ap[1] = '2'; ap[2] = '\0'; break; case '\0': break; default: jbad: errx(1, "illegal option -- %s", ap); usage(); } break; case 'o': /* * The original join allowed "-o arg arg". * Convert to "-o arg -o arg". */ if (ap[2] != '\0') break; for (p = argv + 2; *p; ++p) { if (p[0][0] == '0' || ((p[0][0] != '1' && p[0][0] != '2') || p[0][1] != '.')) break; len = strlen(*p); if (len - 2 != strspn(*p + 2, "0123456789")) break; if ((t = malloc(len + 3)) == NULL) err(1, NULL); t[0] = '-'; t[1] = 'o'; memmove(t + 2, *p, len + 1); *p = t; } argv = p - 1; break; } } } static void usage(void) { (void)fprintf(stderr, "%s %s\n%s\n", "usage: join [-a fileno | -v fileno ] [-e string] [-1 field]", "[-2 field]", " [-o list] [-t char] file1 file2"); exit(1); } Index: user/attilio/vmc-playground/usr.sbin/crunch/crunchide/exec_elf32.c =================================================================== --- user/attilio/vmc-playground/usr.sbin/crunch/crunchide/exec_elf32.c (revision 246333) +++ user/attilio/vmc-playground/usr.sbin/crunch/crunchide/exec_elf32.c (revision 246334) @@ -1,397 +1,497 @@ /* * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint #if 0 __RCSID("$NetBSD: exec_elf32.c,v 1.6 1999/09/20 04:12:16 christos Exp $"); #endif #endif __FBSDID("$FreeBSD$"); #ifndef ELFSIZE #define ELFSIZE 32 #endif #include #include #include #include +#include #include #include #include #include #include "extern.h" #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \ (defined(NLIST_ELF64) && (ELFSIZE == 64)) #define __ELF_WORD_SIZE ELFSIZE #if (ELFSIZE == 32) #include #define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) #define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) #define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) #define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) #elif (ELFSIZE == 64) #include #define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x)) #define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x)) /* elf64 Elf64_Word are 32 bits */ #define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) #define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) #endif #include #define CONCAT(x,y) __CONCAT(x,y) #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) #define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) #define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) #define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) -struct listelem { - struct listelem *next; - void *mem; - off_t file; - size_t size; +struct shlayout { + Elf_Shdr *shdr; + void *bufp; }; static ssize_t xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn) { ssize_t rv; if (lseek(fd, off, SEEK_SET) != off) { perror(fn); return -1; } if ((size_t)(rv = read(fd, buf, size)) != size) { fprintf(stderr, "%s: read error: %s\n", fn, rv == -1 ? strerror(errno) : "short read"); return -1; } return size; } static ssize_t xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn) { ssize_t rv; if (lseek(fd, off, SEEK_SET) != off) { perror(fn); return -1; } if ((size_t)(rv = write(fd, buf, size)) != size) { fprintf(stderr, "%s: write error: %s\n", fn, rv == -1 ? strerror(errno) : "short write"); return -1; } return size; } static void * xmalloc(size_t size, const char *fn, const char *use) { void *rv; rv = malloc(size); if (rv == NULL) fprintf(stderr, "%s: out of memory (allocating for %s)\n", fn, use); return (rv); } static void * xrealloc(void *ptr, size_t size, const char *fn, const char *use) { void *rv; rv = realloc(ptr, size); if (rv == NULL) { free(ptr); fprintf(stderr, "%s: out of memory (reallocating for %s)\n", fn, use); } return (rv); } int ELFNAMEEND(check)(int fd, const char *fn) { Elf_Ehdr eh; struct stat sb; unsigned char data; /* * Check the header to maek sure it's an ELF file (of the * appropriate size). */ if (fstat(fd, &sb) == -1) return 0; if (sb.st_size < (off_t)(sizeof eh)) return 0; if (read(fd, &eh, sizeof eh) != sizeof eh) return 0; if (IS_ELF(eh) == 0) return 0; data = eh.e_ident[EI_DATA]; switch (xe16toh(eh.e_machine)) { case EM_386: break; case EM_ALPHA: break; #ifndef EM_ARM #define EM_ARM 40 #endif case EM_ARM: break; #ifndef EM_MIPS #define EM_MIPS 8 #endif #ifndef EM_MIPS_RS4_BE /* same as EM_MIPS_RS3_LE */ #define EM_MIPS_RS4_BE 10 #endif case EM_MIPS: break; case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE: break; #ifndef EM_IA_64 #define EM_IA_64 50 #endif case EM_IA_64: break; #ifndef EM_PPC #define EM_PPC 20 #endif case EM_PPC: break; #ifndef EM_PPC64 #define EM_PPC64 21 #endif case EM_PPC64: break; #ifndef EM_SPARCV9 #define EM_SPARCV9 43 #endif case EM_SPARCV9: break; #ifndef EM_X86_64 #define EM_X86_64 62 #endif case EM_X86_64: break; /* ELFDEFNNAME(MACHDEP_ID_CASES) */ default: return 0; } return 1; } /* * This function 'hides' (some of) ELF executable file's symbols. * It hides them by renaming them to "_$$hide$$ ". * Symbols in the global keep list, or which are marked as being undefined, * are left alone. * * An old version of this code shuffled various tables around, turning * global symbols to be hidden into local symbols. That lost on the * mips, because CALL16 relocs must reference global symbols, and, if * those symbols were being hidden, they were no longer global. * * The new renaming behaviour doesn't take global symbols out of the * namespace. However, it's ... unlikely that there will ever be * any collisions in practice because of the new method. */ int ELFNAMEEND(hide)(int fd, const char *fn) { Elf_Ehdr ehdr; - Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr; + struct shlayout *layoutp = NULL; + Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr, *shstrtabshdr; + Elf_Shdr shdrshdr; Elf_Sym *symtabp = NULL; - char *strtabp = NULL; - Elf_Size nsyms, ewi; + char *shstrtabp = NULL, *strtabp = NULL; + Elf_Size nsyms, ewi; + Elf_Off off; ssize_t shdrsize; - int rv, i, weird; - size_t nstrtab_size, nstrtab_nextoff, fn_size; + int rv, i, weird, l, m, r, strtabidx; + size_t nstrtab_size, nstrtab_nextoff, fn_size, size; char *nstrtabp = NULL; unsigned char data; - Elf_Off maxoff, stroff; const char *weirdreason = NULL; + void *buf; + Elf_Half shnum; rv = 0; if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr) goto bad; data = ehdr.e_ident[EI_DATA]; + shnum = xe16toh(ehdr.e_shnum); - shdrsize = xe16toh(ehdr.e_shnum) * xe16toh(ehdr.e_shentsize); + shdrsize = shnum * xe16toh(ehdr.e_shentsize); if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL) goto bad; if (xreadatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != shdrsize) goto bad; - symtabshdr = strtabshdr = NULL; + symtabshdr = strtabshdr = shstrtabshdr = NULL; weird = 0; - maxoff = stroff = 0; - for (i = 0; i < xe16toh(ehdr.e_shnum); i++) { - if (xewtoh(shdrp[i].sh_offset) > maxoff) - maxoff = xewtoh(shdrp[i].sh_offset); + for (i = 0; i < shnum; i++) { switch (xe32toh(shdrp[i].sh_type)) { case SHT_SYMTAB: - if (symtabshdr != NULL) + if (symtabshdr != NULL) { weird = 1; + weirdreason = "multiple symbol tables"; + } symtabshdr = &shdrp[i]; strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)]; - - /* Check whether the string table is the last section */ - stroff = xewtoh(shdrp[xe32toh(shdrp[i].sh_link)].sh_offset); - if (!weird && xe32toh(shdrp[i].sh_link) != (xe16toh(ehdr.e_shnum) - 1)) { - weird = 1; - weirdreason = "string table not last section"; - } break; + case SHT_STRTAB: + if (i == xe16toh(ehdr.e_shstrndx)) + shstrtabshdr = &shdrp[i]; + break; } } - if (! weirdreason) - weirdreason = "unsupported"; if (symtabshdr == NULL) goto out; - if (strtabshdr == NULL) + if (strtabshdr == NULL) { weird = 1; - if (!weird && stroff != maxoff) { + weirdreason = "string table does not exist"; + } + if (shstrtabshdr == NULL) { weird = 1; - weirdreason = "string table section not last in file"; - } + weirdreason = "section header string table does not exist"; + } + if (weirdreason == NULL) + weirdreason = "unsupported"; if (weird) { fprintf(stderr, "%s: weird executable (%s)\n", fn, weirdreason); goto bad; } /* + * sort section layout table by offset + */ + layoutp = xmalloc((shnum + 1) * sizeof(struct shlayout), + fn, "layout table"); + if (layoutp == NULL) + goto bad; + + /* add a pseudo entry to represent the section header table */ + shdrshdr.sh_offset = ehdr.e_shoff; + shdrshdr.sh_size = htoxew(shdrsize); + shdrshdr.sh_addralign = htoxew(ELFSIZE / 8); + layoutp[shnum].shdr = &shdrshdr; + + /* insert and sort normal section headers */ + for (i = shnum; i-- != 0;) { + l = i + 1; + r = shnum; + while (l <= r) { + m = ( l + r) / 2; + if (xewtoh(shdrp[i].sh_offset) > + xewtoh(layoutp[m].shdr->sh_offset)) + l = m + 1; + else + r = m - 1; + } + + if (r != i) { + memmove(&layoutp[i], &layoutp[i + 1], + sizeof(struct shlayout) * (r - i)); + } + + layoutp[r].shdr = &shdrp[i]; + layoutp[r].bufp = NULL; + } + ++shnum; + + /* * load up everything we need */ - /* symbol table */ - if ((symtabp = xmalloc(xewtoh(symtabshdr->sh_size), fn, "symbol table")) - == NULL) + /* load section string table for debug use */ + if ((shstrtabp = xmalloc(xewtoh(shstrtabshdr->sh_size), fn, + "section string table")) == NULL) goto bad; - if ((size_t)xreadatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset), - xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size)) + if ((size_t)xreadatoff(fd, shstrtabp, xewtoh(shstrtabshdr->sh_offset), + xewtoh(shstrtabshdr->sh_size), fn) != xewtoh(shstrtabshdr->sh_size)) goto bad; - /* string table */ - if ((strtabp = xmalloc(xewtoh(strtabshdr->sh_size), fn, "string table")) - == NULL) - goto bad; - if ((size_t)xreadatoff(fd, strtabp, xewtoh(strtabshdr->sh_offset), - xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size)) - goto bad; + /* we need symtab, strtab, and everything behind strtab */ + strtabidx = INT_MAX; + for (i = 0; i < shnum; i++) { + if (layoutp[i].shdr == &shdrshdr) { + /* not load section header again */ + layoutp[i].bufp = shdrp; + continue; + } + if (layoutp[i].shdr == shstrtabshdr) { + /* not load section string table again */ + layoutp[i].bufp = shstrtabp; + continue; + } + if (layoutp[i].shdr == strtabshdr) + strtabidx = i; + if (layoutp[i].shdr == symtabshdr || i >= strtabidx) { + off = xewtoh(layoutp[i].shdr->sh_offset); + size = xewtoh(layoutp[i].shdr->sh_size); + layoutp[i].bufp = xmalloc(size, fn, + shstrtabp + xewtoh(layoutp[i].shdr->sh_name)); + if (layoutp[i].bufp == NULL) + goto bad; + if ((size_t)xreadatoff(fd, layoutp[i].bufp, off, size, fn) != + size) + goto bad; + + /* set symbol table and string table */ + if (layoutp[i].shdr == symtabshdr) + symtabp = layoutp[i].bufp; + else if (layoutp[i].shdr == strtabshdr) + strtabp = layoutp[i].bufp; + } + } + nstrtab_size = 256; nstrtabp = xmalloc(nstrtab_size, fn, "new string table"); if (nstrtabp == NULL) goto bad; nstrtab_nextoff = 0; fn_size = strlen(fn); /* Prepare data structures for symbol movement. */ nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize); /* move symbols, making them local */ for (ewi = 0; ewi < nsyms; ewi++) { Elf_Sym *sp = &symtabp[ewi]; const char *symname = strtabp + xe32toh(sp->st_name); size_t newent_len; /* * make sure there's size for the next entry, even if it's * as large as it can be. * * "_$$hide$$ " -> * 9 + 3 + sizes of fn and sym name */ while ((nstrtab_size - nstrtab_nextoff) < strlen(symname) + fn_size + 12) { nstrtab_size *= 2; nstrtabp = xrealloc(nstrtabp, nstrtab_size, fn, "new string table"); if (nstrtabp == NULL) goto bad; } sp->st_name = htowew(nstrtab_nextoff); /* if it's a keeper or is undefined, don't rename it. */ if (in_keep_list(symname) || (xe16toh(sp->st_shndx) == SHN_UNDEF)) { newent_len = sprintf(nstrtabp + nstrtab_nextoff, "%s", symname) + 1; } else { newent_len = sprintf(nstrtabp + nstrtab_nextoff, "_$$hide$$ %s %s", fn, symname) + 1; } nstrtab_nextoff += newent_len; } strtabshdr->sh_size = htoxew(nstrtab_nextoff); /* - * write new tables to the file + * update section header table in ascending order of offset */ - if (xwriteatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != - shdrsize) - goto bad; - if ((size_t)xwriteatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset), - xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size)) - goto bad; - /* write new symbol table strings */ - if ((size_t)xwriteatoff(fd, nstrtabp, xewtoh(strtabshdr->sh_offset), - xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size)) - goto bad; + for (i = strtabidx + 1; i < shnum; i++) { + Elf_Off off, align; + off = xewtoh(layoutp[i - 1].shdr->sh_offset) + + xewtoh(layoutp[i - 1].shdr->sh_size); + align = xewtoh(layoutp[i].shdr->sh_addralign); + off = (off + (align - 1)) & ~(align - 1); + layoutp[i].shdr->sh_offset = htoxew(off); + } + /* + * write data to the file in descending order of offset + */ + for (i = shnum; i-- != 0;) { + if (layoutp[i].shdr == strtabshdr) { + /* new string table */ + buf = nstrtabp; + } else + buf = layoutp[i].bufp; + + if (layoutp[i].shdr == &shdrshdr || + layoutp[i].shdr == symtabshdr || i >= strtabidx) { + if (buf == NULL) + goto bad; + + /* + * update the offset of section header table in elf + * header if needed. + */ + if (layoutp[i].shdr == &shdrshdr && + ehdr.e_shoff != shdrshdr.sh_offset) { + ehdr.e_shoff = shdrshdr.sh_offset; + off = (ELFSIZE == 32) ? 32 : 44; + size = sizeof(Elf_Off); + if ((size_t)xwriteatoff(fd, &ehdr.e_shoff, off, size, + fn) != size) + goto bad; + } + + off = xewtoh(layoutp[i].shdr->sh_offset); + size = xewtoh(layoutp[i].shdr->sh_size); + if ((size_t)xwriteatoff(fd, buf, off, size, fn) != size) + goto bad; + } + } + out: - if (shdrp != NULL) - free(shdrp); - if (symtabp != NULL) - free(symtabp); - if (strtabp != NULL) - free(strtabp); - if (nstrtabp != NULL) - free(nstrtabp); + if (layoutp != NULL) { + for (i = 0; i < shnum; i++) { + if (layoutp[i].bufp != NULL) + free(layoutp[i].bufp); + } + free(layoutp); + } + free(nstrtabp); return (rv); bad: rv = 1; goto out; } #endif /* include this size of ELF */ Index: user/attilio/vmc-playground =================================================================== --- user/attilio/vmc-playground (revision 246333) +++ user/attilio/vmc-playground (revision 246334) Property changes on: user/attilio/vmc-playground ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /user/attilio/vmcontention:r246320-246333 Merged /head:r246295-246332