Index: head/Makefile.inc1 =================================================================== --- head/Makefile.inc1 (revision 291405) +++ head/Makefile.inc1 (revision 291406) @@ -1,2369 +1,2370 @@ # # $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 # -DWITHOUT_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_ITOOLS="list of tools" to add additional tools to the ITOOLS 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:${SHELL}) # WORLD_FLAGS= additional flags to pass to make(1) during buildworld # KERNEL_FLAGS= additional flags to pass to make(1) during buildkernel # SUBDIR_OVERRIDE="list of dirs" to build rather than everything. # All libraries and includes, and some build tools will still build. # # 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: svn/svnup) # # Standard targets (not defined here) are documented in the makefiles in # /usr/share/mk. These include: # obj depend all install clean cleandepend cleanobj .if !defined(TARGET) || !defined(TARGET_ARCH) .error "Both TARGET and TARGET_ARCH must be defined." .endif # Cross toolchain changes must be in effect before bsd.compiler.mk # so that gets the right CC, and pass CROSS_TOOLCHAIN to submakes. .if defined(CROSS_TOOLCHAIN) LOCALBASE?= /usr/local .include "${LOCALBASE}/share/toolchains/${CROSS_TOOLCHAIN}.mk" CROSSENV+=CROSS_TOOLCHAIN="${CROSS_TOOLCHAIN}" .endif .include # don't depend on src.opts.mk doing it .include "share/mk/src.opts.mk" # We must do lib/ and libexec/ before bin/ in case of a mid-install error to # keep the users system reasonably usable. For static->dynamic root upgrades, # we don't want to install a dynamic binary without rtld and the needed # libraries. More commonly, for dynamic root, we don't want to install a # binary that requires a newer library version that hasn't been installed yet. # This ordering is not a guarantee though. The only guarantee of a working # system here would require fine-grained ordering of all components based # on their dependencies. SRCDIR?= ${.CURDIR} .if !empty(SUBDIR_OVERRIDE) SUBDIR= ${SUBDIR_OVERRIDE} .else SUBDIR= lib libexec .if make(install*) # Ensure libraries are installed before progressing. SUBDIR+=.WAIT .endif SUBDIR+=bin .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_TESTS} != "no" SUBDIR+= tests .endif .if ${MK_OFED} != "no" SUBDIR+=contrib/ofed .endif # Local directories are last, since it is nice to at least get the base # system rebuilt before you do them. .for _DIR in ${LOCAL_DIRS} .if exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} .endif .endfor # Add LOCAL_LIB_DIRS, but only if they will not be picked up as a SUBDIR # of a LOCAL_DIRS directory. This allows LOCAL_DIRS=foo and # LOCAL_LIB_DIRS=foo/lib to behave as expected. .for _DIR in ${LOCAL_DIRS:M*/} ${LOCAL_DIRS:N*/:S|$|/|} _REDUNDENT_LIB_DIRS+= ${LOCAL_LIB_DIRS:M${_DIR}*} .endfor .for _DIR in ${LOCAL_LIB_DIRS} .if empty(_REDUNDENT_LIB_DIRS:M${_DIR}) && exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} .else .warning ${_DIR} not added to SUBDIR list. See UPDATING 20141121. .endif .endfor # We must do etc/ last as it hooks into building the man whatis file # by calling 'makedb' in share/man. This is only relevant for # install/distribute so they build the whatis file after every manpage is # installed. .if make(install*) SUBDIR+=.WAIT .endif SUBDIR+=etc .endif # !empty(SUBDIR_OVERRIDE) .if defined(NOCLEAN) .warning NOCLEAN option is deprecated. Use NO_CLEAN instead. NO_CLEAN= ${NOCLEAN} .endif .if defined(NO_CLEANDIR) CLEANDIR= clean cleandepend .else CLEANDIR= cleandir .endif LOCAL_TOOL_DIRS?= BUILDENV_SHELL?=${SHELL} SVN?= /usr/local/bin/svn SVNFLAGS?= -r HEAD 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 .export OSRELDATE .endif # Set VERSION for CTFMERGE to use via the default CTFFLAGS=-L VERSION. .if !defined(VERSION) REVISION!= ${MAKE} -C ${SRCDIR}/release -V REVISION BRANCH!= ${MAKE} -C ${SRCDIR}/release -V BRANCH SRCRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \ ${SRCDIR}/sys/sys/param.h VERSION= FreeBSD ${REVISION}-${BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDATE} .export VERSION .endif KNOWN_ARCHES?= aarch64/arm64 amd64 arm armeb/arm armv6/arm armv6hf/arm i386 i386/pc98 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 BPATH= ${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/bin XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin 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. These are generally # APIs that tools from one of those three stages need to # build that aren't present on the host. # 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. Some programs are listed during # this phase because they build binaries to generate # files needed to build these programs. This stage also # builds the 'build-tools' target rather than 'all'. # 3. cross-tools stage [XMAKE] # This stage is responsible for creating any tools that # are needed for building the system. A cross-compiler is one # of them. This differs from build tools in two ways: # 1. the 'all' target is built rather than 'build-tools' # 2. these tools are installed into TMPPATH for stage 4. # 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 .if defined(TARGET_CFLAGS) CROSSENV+= ${TARGET_CFLAGS} .endif # bootstrap-tools stage BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${BPATH}:${PATH} \ WORLDTMP=${WORLDTMP} \ MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" # need to keep this in sync with targets/pseudo/bootstrap-tools/Makefile BSARGS= DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ MK_HTML=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no MK_TESTS=no \ MK_INCLUDES=yes BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ ${BSARGS} # 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 MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no MK_TESTS=no # cross-tools stage XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ MK_GDB=no MK_TESTS=no # kernel-tools stage KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${BPATH}:${PATH} \ WORLDTMP=${WORLDTMP} KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \ ${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ MK_HTML=no -DNO_LINT MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no # world stage WMAKEENV= ${CROSSENV} \ _LDSCRIPTROOT= \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} # make hierarchy HMAKE= PATH=${TMPPATH} ${MAKE} LOCAL_MTREE=${LOCAL_MTREE:Q} .if defined(NO_ROOT) HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT .endif .if defined(CROSS_TOOLCHAIN_PREFIX) CROSS_COMPILER_PREFIX?=${CROSS_TOOLCHAIN_PREFIX} CROSS_BINUTILS_PREFIX?=${CROSS_TOOLCHAIN_PREFIX} .endif # If we do not have a bootstrap binutils (because the in-tree one does not # support the target architecture), provide a default cross-binutils prefix. # This allows aarch64 builds, for example, to automatically use the # aarch64-binutils port or package. .if !make(showconfig) .if !empty(BROKEN_OPTIONS:MBINUTILS_BOOTSTRAP) && \ !defined(CROSS_BINUTILS_PREFIX) CROSS_BINUTILS_PREFIX=/usr/local/${TARGET_ARCH}-freebsd/bin/ .if !exists(${CROSS_BINUTILS_PREFIX}) .error In-tree binutils does not support the ${TARGET_ARCH} architecture. Install the ${TARGET_ARCH}-binutils port or package or set CROSS_BINUTILS_PREFIX. .endif .endif .endif XCOMPILERS= CC CXX CPP .for COMPILER in ${XCOMPILERS} .if defined(CROSS_COMPILER_PREFIX) X${COMPILER}?= ${CROSS_COMPILER_PREFIX}${${COMPILER}} .else X${COMPILER}?= ${${COMPILER}} .endif .endfor XBINUTILS= AS AR LD NM OBJCOPY OBJDUMP RANLIB SIZE STRINGS .for BINUTIL in ${XBINUTILS} .if defined(CROSS_BINUTILS_PREFIX) && \ exists(${CROSS_BINUTILS_PREFIX}${${BINUTIL}}) X${BINUTIL}?= ${CROSS_BINUTILS_PREFIX}${${BINUTIL}} .else X${BINUTIL}?= ${${BINUTIL}} .endif .endfor CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCFLAGS} ${XCXXFLAGS}" \ DEPFLAGS="${DEPFLAGS}" \ CPP="${XCPP} ${XCFLAGS}" \ AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \ OBJDUMP=${XOBJDUMP} OBJCOPY="${XOBJCOPY}" \ RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \ SIZE="${XSIZE}" .if ${XCC:N${CCACHE_BIN}:M/*} .if defined(CROSS_BINUTILS_PREFIX) # In the case of xdev-build tools, CROSS_BINUTILS_PREFIX won't be a # directory, but the compiler will look in the right place for it's # tools so we don't need to tell it where to look. .if exists(${CROSS_BINUTILS_PREFIX}) BFLAGS+= -B${CROSS_BINUTILS_PREFIX} .endif .else BFLAGS+= -B${WORLDTMP}/usr/bin .endif .if ${TARGET} == "arm" .if ${TARGET_ARCH:M*hf*} != "" TARGET_ABI= gnueabihf .else TARGET_ABI= gnueabi .endif .endif .if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc XCFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib XCXXFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 -std=gnu++11 -L${WORLDTMP}/../lib/libc++ # XXX: DEPFLAGS is a workaround for not properly passing CXXFLAGS to sub-makes # due to CXX="${XCXX} ${XCXXFLAGS}". bsd.dep.mk does use CXXFLAGS when # building C++ files so this can come out if passing CXXFLAGS down is fixed. DEPFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 .else TARGET_ABI?= unknown TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0 XCFLAGS+= -target ${TARGET_TRIPLE} .endif XCFLAGS+= --sysroot=${WORLDTMP} ${BFLAGS} XCXXFLAGS+= --sysroot=${WORLDTMP} ${BFLAGS} .else .if defined(CROSS_BINUTILS_PREFIX) && exists(${CROSS_BINUTILS_PREFIX}) BFLAGS+= -B${CROSS_BINUTILS_PREFIX} XCFLAGS+= ${BFLAGS} XCXXFLAGS+= ${BFLAGS} .endif .endif # ${XCC:M/*} WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP} .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64" # 32 bit world LIB32_OBJTREE= ${OBJTREE}${.CURDIR}/world32 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="${XAS} --32" \ LD="${XLD} -m elf_i386_fbsd -Y P,${LIB32TMP}/usr/lib32" \ OBJCOPY="${XOBJCOPY}" .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="${XLD} -m elf32ppc_fbsd" \ OBJCOPY="${XOBJCOPY}" .endif LIB32FLAGS= -m32 ${LIB32CPUFLAGS} -DCOMPAT_32BIT \ -isystem ${LIB32TMP}/usr/include/ \ -L${LIB32TMP}/usr/lib32 \ -B${LIB32TMP}/usr/lib32 .if ${XCC:N${CCACHE_BIN}:M/*} LIB32FLAGS+= --sysroot=${WORLDTMP} .endif # Yes, the flags are redundant. LIB32WMAKEENV+= MAKEOBJDIRPREFIX=${LIB32_OBJTREE} \ _LDSCRIPTROOT=${LIB32TMP} \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} \ LIBDIR=/usr/lib32 \ SHLIBDIR=/usr/lib32 \ DTRACE="${DTRACE} -32" LIB32WMAKEFLAGS+= CC="${XCC} ${LIB32FLAGS}" \ CXX="${XCXX} ${LIB32FLAGS}" \ DESTDIR=${LIB32TMP} \ -DCOMPAT_32BIT \ -DLIBRARIES_ONLY \ -DNO_CPU_CFLAGS \ MK_CTF=no \ -DNO_LINT \ MK_TESTS=no LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \ MK_MAN=no MK_HTML=no LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} \ MK_TOOLCHAIN=no ${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 _INSTALL_DDIR= ${DESTDIR}/${DISTDIR} INSTALL_DDIR= ${_INSTALL_DDIR:S://:/:g:C:/$::} .if defined(NO_ROOT) METALOG?= ${DESTDIR}/${DISTDIR}/METALOG IMAKE+= -DNO_ROOT METALOG=${METALOG} INSTALLFLAGS+= -U -M ${METALOG} -D ${INSTALL_DDIR} MTREEFLAGS+= -W .endif .if defined(DB_FROM_SRC) || defined(NO_ROOT) IMAKE_INSTALL= INSTALL="install ${INSTALLFLAGS}" IMAKE_MTREE= MTREE_CMD="mtree ${MTREEFLAGS}" .endif # kernel stage KMAKEENV= ${WMAKEENV} KMAKE= ${KMAKEENV} ${MAKE} ${.MAKEFLAGS} ${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: .PHONY .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_DEBUG_FILES} != "no" # We could instead disable debug files for these build stages mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${WORLDTMP}/legacy/usr/lib >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${WORLDTMP}/usr/lib >/dev/null .endif .if ${MK_LIB32} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${WORLDTMP}/usr >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${WORLDTMP}/legacy/usr/lib/debug/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${WORLDTMP}/usr/lib/debug/usr >/dev/null .endif .endif .if ${MK_TESTS} != "no" mkdir -p ${WORLDTMP}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${WORLDTMP}${TESTSBASE} >/dev/null .if ${MK_DEBUG_FILES} != "no" mkdir -p ${WORLDTMP}/usr/lib/debug/${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${WORLDTMP}/usr/lib/debug/${TESTSBASE} >/dev/null .endif .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} .if defined(LIB32TMP) ${_+_}cd ${.CURDIR}; ${LIB32WMAKE} -f Makefile.inc1 ${CLEANDIR} .endif .endif _obj: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.2: rebuilding the object tree" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} 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 ${_+_}cd ${.CURDIR}; ${XMAKE} kernel-tools _includes: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.1: building includes" @echo "--------------------------------------------------------------" # Special handling for SUBDIR_OVERRIDE in buildworld as they most likely need # headers from default SUBDIR. Do SUBDIR_OVERRIDE includes last. ${_+_}cd ${.CURDIR}; ${WMAKE} SUBDIR_OVERRIDE= SHARED=symlinks \ buildincludes ${_+_}cd ${.CURDIR}; ${WMAKE} SUBDIR_OVERRIDE= SHARED=symlinks \ installincludes .if !empty(SUBDIR_OVERRIDE) && make(buildworld) ${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks buildincludes ${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks installincludes .endif _libraries: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.2: building libraries" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; \ ${WMAKE} -DNO_FSCHG MK_HTML=no -DNO_LINT MK_MAN=no \ MK_PROFILE=no MK_TESTS=no MK_TESTS_SUPPORT=${MK_TESTS} libraries _depend: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.3: make dependencies" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} depend everything: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.4: building everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-all .if defined(LIB32TMP) build32: .PHONY @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 mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${LIB32TMP}/usr >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${LIB32TMP}/usr/lib >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${LIB32TMP}/usr/lib/debug/usr >/dev/null .endif 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=${LIB32_OBJTREE} ${MAKE} SSP_CFLAGS= DESTDIR= \ DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ build-tools .endfor ${_+_}cd ${.CURDIR}; \ ${LIB32WMAKE} -f Makefile.inc1 -DNO_FSCHG libraries .for _t in obj depend all ${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} \ -DNO_FSCHG DIRPRFX=libexec/rtld-elf/ ${_t} ${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} \ DIRPRFX=usr.bin/ldd ${_t} .endfor distribute32 install32: .MAKE .PHONY ${_+_}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= WMAKE_TGTS+= _worldtmp _legacy .if empty(SUBDIR_OVERRIDE) WMAKE_TGTS+= _bootstrap-tools .endif WMAKE_TGTS+= _cleanobj _obj _build-tools _cross-tools WMAKE_TGTS+= _includes _libraries _depend everything .if defined(LIB32TMP) && ${MK_LIB32} != "no" && empty(SUBDIR_OVERRIDE) 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: .PHONY @echo ${WMAKEENV:Q} ${.MAKE.EXPORTED:@v@$v=\"${$v}\"@} .if ${.TARGETS:Mbuildenv} .if ${.MAKEFLAGS:M-j} .error The buildenv target is incompatible with -j .endif .endif BUILDENV_DIR?= ${.CURDIR} buildenv: .PHONY @echo Entering world for ${TARGET_ARCH}:${TARGET} .if ${BUILDENV_SHELL:M*zsh*} @echo For ZSH you must run: export CPUTYPE=${TARGET_CPUTYPE} .endif @cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${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: _installcheck_world _installcheck_kernel _installcheck_world: _installcheck_kernel: # # 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_world: __installcheck_DESTDIR _installcheck_kernel: __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 .if ${MK_UNBOUND} != "no" CHECK_UIDS+= unbound CHECK_GIDS+= unbound .endif _installcheck_world: __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_ZONEINFO} != "no" _zoneinfo= zic tzsetup .endif ITOOLS= [ awk cap_mkdb cat chflags chmod chown cmp cp \ date echo egrep find grep id install ${_install-info} \ ln make mkdir mtree mv pwd_mkdb \ rm sed services_mkdb sh strip sysctl test true uname wc ${_zoneinfo} \ ${LOCAL_ITOOLS} # Needed for share/man .if ${MK_MAN} != "no" ITOOLS+=makewhatis .endif # # 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 defined(LIB32TMP) && ${MK_LIB32} != "no" EXTRA_DISTRIBUTIONS+= lib32 .endif .if ${MK_TESTS} != "no" EXTRA_DISTRIBUTIONS+= tests .endif DEBUG_DISTRIBUTIONS= .if ${MK_DEBUG_FILES} != "no" DEBUG_DISTRIBUTIONS+= base ${EXTRA_DISTRIBUTIONS:S,doc,,:S,tests,,} .endif MTREE_MAGIC?= mtree 2.0 distributeworld installworld: _installcheck_world 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 ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib >/dev/null .endif .if ${MK_LIB32} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib/debug/usr >/dev/null .endif .endif .if ${MK_TESTS} != "no" && ${dist} == "tests" -mkdir -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib/debug/${TESTSBASE} >/dev/null .endif .endif .if defined(NO_ROOT) ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \ sed -e 's#^\./#./${dist}/#' >> ${METALOG} ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \ sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG} ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \ sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG} .if ${MK_LIB32} != "no" ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.lib32.dist | \ sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG} .endif .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:Q} 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} -mindepth 1 -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 .for dist in ${DEBUG_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}/usr/lib/debug | sort -u ${METALOG} - | \ awk 'BEGIN { print "#${MTREE_MAGIC}" } !/ type=/ { file = $$1 } / type=/ { if ($$1 == file) { sub(/^\.\/${dist}\//, "./"); print } }' > \ ${DESTDIR}/${DISTDIR}/${dist}.debug.meta .endfor .endif .endif packageworld: .for dist in base ${EXTRA_DISTRIBUTIONS} .if defined(NO_ROOT) ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvf - --exclude usr/lib/debug \ @${DESTDIR}/${DISTDIR}/${dist}.meta | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/${dist}.txz .else ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvf - --exclude usr/lib/debug . | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/${dist}.txz .endif .endfor .for dist in ${DEBUG_DISTRIBUTIONS} . if defined(NO_ROOT) ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvf - @${DESTDIR}/${DISTDIR}/${dist}.debug.meta | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/${dist}-dbg.txz . else ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvLf - usr/lib/debug | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/${dist}-dbg.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: .MAKE .PHONY @echo "--------------------------------------------------------------" @echo ">>> Making hierarchy" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 \ LOCAL_MTREE=${LOCAL_MTREE:Q} 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: .MAKE .PHONY @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: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} distribution: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} ${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \ METALOG=${METALOG} installconfig # # 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 ${TARGET_ARCH} == "powerpc64" KERNCONF?= GENERIC64 .else KERNCONF?= GENERIC .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 ${WMAKE_TGTS:N_worldtmp:Nbuild32} ${.ALLTARGETS:M_*:N_worldtmp}: .MAKE .PHONY # # buildkernel # # Builds all kernels defined by BUILDKERNELS. # buildkernel: .MAKE .PHONY .if empty(BUILDKERNELS) @echo "ERROR: Missing kernel configuration file(s) (${KERNCONF})."; \ false .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} \ -I '${KERNCONFDIR}' '${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 ${.CURDIR}; ${KTMAKE} kernel-tools .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_kernel .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//} .if ${BUILDKERNELS:[#]} > 1 .for _kernel in ${BUILDKERNELS:[2..-1]} @echo "--------------------------------------------------------------" @echo ">>> Installing kernel ${_kernel}" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; \ ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} ${IMAKE_INSTALL} KERNEL=${INSTKERNNAME}.${_kernel} ${.TARGET:S/kernel//} .endfor .endif distributekernel distributekernel.debug: .if empty(INSTALLKERNEL) @echo "ERROR: No kernel \"${KERNCONF}\" to install."; \ false .endif mkdir -p ${DESTDIR}/${DISTDIR} .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${DESTDIR}/${DISTDIR}/kernel.premeta .endif cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \ ${IMAKEENV} ${IMAKE_INSTALL:S/METALOG/kernel.premeta/} \ ${IMAKE_MTREE} PATH=${TMPPATH} ${MAKE} KERNEL=${INSTKERNNAME} \ DESTDIR=${INSTALL_DDIR}/kernel \ ${.TARGET:S/distributekernel/install/} .if defined(NO_ROOT) sed -e 's|^./kernel|.|' ${DESTDIR}/${DISTDIR}/kernel.premeta > \ ${DESTDIR}/${DISTDIR}/kernel.meta .endif .if ${BUILDKERNELS:[#]} > 1 .for _kernel in ${BUILDKERNELS:[2..-1]} .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.premeta .endif cd ${KRNLOBJDIR}/${_kernel}; \ ${IMAKEENV} ${IMAKE_INSTALL:S/METALOG/kernel.${_kernel}.premeta/} \ ${IMAKE_MTREE} PATH=${TMPPATH} ${MAKE} \ KERNEL=${INSTKERNNAME}.${_kernel} \ DESTDIR=${INSTALL_DDIR}/kernel.${_kernel} \ ${.TARGET:S/distributekernel/install/} .if defined(NO_ROOT) sed -e 's|^./kernel|.|' \ ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.premeta > \ ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.meta .endif .endfor .endif packagekernel: .if defined(NO_ROOT) cd ${DESTDIR}/${DISTDIR}/kernel; \ tar cvf - @${DESTDIR}/${DISTDIR}/kernel.meta | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/kernel.txz .if ${BUILDKERNELS:[#]} > 1 .for _kernel in ${BUILDKERNELS:[2..-1]} cd ${DESTDIR}/${DISTDIR}/kernel.${_kernel}; \ tar cvf - @${DESTDIR}/${DISTDIR}/kernel.${_kernel}.meta | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.txz .endfor .endif .else cd ${DESTDIR}/${DISTDIR}/kernel; \ tar cvf - . | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/kernel.txz .if ${BUILDKERNELS:[#]} > 1 .for _kernel in ${BUILDKERNELS:[2..-1]} cd ${DESTDIR}/${DISTDIR}/kernel.${_kernel}; \ tar cvf - . | \ ${XZ_CMD} > ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.txz .endfor .endif .endif # # doxygen # # Build the API documentation with doxygen # doxygen: .PHONY @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 svn/svnup to update to the # latest copy. # update: .if (defined(CVS_UPDATE) || defined(SUP_UPDATE)) && !defined(SVN_UPDATE) @echo "--------------------------------------------------------------" @echo "CVS_UPDATE and SUP_UPDATE are no longer supported." @echo "Please see: https://wiki.freebsd.org/CvsIsDeprecated" @echo "--------------------------------------------------------------" @exit 1 .endif .if defined(SVN_UPDATE) @echo "--------------------------------------------------------------" @echo ">>> Updating ${.CURDIR} using Subversion" @echo "--------------------------------------------------------------" @(cd ${.CURDIR} && ${SVN} update ${SVNFLAGS}) .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. This is a # minimal set of tools and shims necessary to compensate for older systems # which don't have the APIs required by the targets built in bootstrap-tools, # build-tools or cross-tools. # # ELF Tool Chain libraries are needed for ELF tools and dtrace tools. .if ${BOOTSTRAPPING} < 1100006 _elftoolchain_libs= lib/libelf lib/libdwarf .endif legacy: .if ${BOOTSTRAPPING} < 800107 && ${BOOTSTRAPPING} != 0 @echo "ERROR: Source upgrades from versions prior to 8.0 are not supported."; \ false .endif .for _tool in tools/build ${_elftoolchain_libs} ${_+_}@${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. These are binaries that # are built to build other binaries in the system. However, the focus of these # binaries is usually quite narrow. Bootstrap tools use the host's compiler and # libraries, augmented by -legacy. # _bt= _bootstrap-tools .if ${MK_GAMES} != "no" _strfile= usr.bin/fortune/strfile .endif .if ${MK_GCC} != "no" && ${MK_CXX} != "no" _gperf= gnu/usr.bin/gperf .endif .if ${MK_GROFF} != "no" _groff= gnu/usr.bin/groff \ usr.bin/soelim .endif .if ${MK_VT} != "no" _vtfontcvt= usr.bin/vtfontcvt .endif .if ${BOOTSTRAPPING} < 900002 _sed= usr.bin/sed .endif .if ${BOOTSTRAPPING} < 1000002 _libopenbsd= lib/libopenbsd _m4= usr.bin/m4 ${_bt}-usr.bin/m4: ${_bt}-lib/libopenbsd .endif .if ${BOOTSTRAPPING} < 1000026 _nmtree= lib/libnetbsd \ usr.sbin/nmtree ${_bt}-usr.sbin/nmtree: ${_bt}-lib/libnetbsd .endif .if ${BOOTSTRAPPING} < 1000027 _cat= bin/cat .endif .if ${BOOTSTRAPPING} < 1000033 _lex= usr.bin/lex ${_bt}-usr.bin/lex: ${_bt}-usr.bin/m4 .endif # r277259 crunchide: Correct 64-bit section header offset # r281674 crunchide: always include both 32- and 64-bit ELF support # r285986 crunchen: use STRIPBIN rather than STRIP .if ${BOOTSTRAPPING} < 1100078 _crunch= usr.sbin/crunch .endif .if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 _awk= usr.bin/awk .endif _yacc= lib/liby \ usr.bin/yacc ${_bt}-usr.bin/yacc: ${_bt}-lib/liby .if ${MK_BSNMP} != "no" _gensnmptree= usr.sbin/bsnmpd/gensnmptree .endif # We need to build tblgen when we're building clang either as # the bootstrap compiler, or as the part of the normal build. .if ${MK_CLANG_BOOTSTRAP} != "no" || ${MK_CLANG} != "no" _clang_tblgen= \ lib/clang/libllvmsupport \ lib/clang/libllvmtablegen \ usr.bin/clang/tblgen \ usr.bin/clang/clang-tblgen ${_bt}-usr.bin/clang/clang-tblgen: ${_bt}-lib/clang/libllvmtablegen ${_bt}-lib/clang/libllvmsupport ${_bt}-usr.bin/clang/tblgen: ${_bt}-lib/clang/libllvmtablegen ${_bt}-lib/clang/libllvmsupport .endif # Default to building the GPL DTC, but build the BSDL 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 \ usr.bin/compile_et .ORDER: ${_kerberos5_bootstrap_tools:C/^/${_bt}-/g} .endif .if ${MK_MANDOCDB} != "no" _libopenbsd?= lib/libopenbsd _makewhatis= lib/libsqlite3 \ usr.bin/mandoc ${_bt}-usr.bin/mandoc: ${_bt}-lib/libopenbsd ${_bt}-lib/libsqlite3 .else _makewhatis=usr.bin/makewhatis .endif bootstrap-tools: .PHONY # 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. .for _tool in \ ${_clang_tblgen} \ ${_kerberos5_bootstrap_tools} \ ${_strfile} \ ${_gperf} \ ${_groff} \ ${_dtc} \ ${_awk} \ ${_cat} \ usr.bin/lorder \ ${_libopenbsd} \ ${_makewhatis} \ usr.bin/rpcgen \ ${_sed} \ ${_yacc} \ ${_m4} \ ${_lex} \ usr.bin/xinstall \ ${_gensnmptree} \ usr.sbin/config \ ${_crunch} \ ${_nmtree} \ ${_vtfontcvt} \ usr.bin/localedef ${_bt}-${_tool}: .PHONY .MAKE ${_+_}@${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 bootstrap-tools: ${_bt}-${_tool} .endfor # # build-tools: Build special purpose build tools # .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 includes programs that have build-tools targets _rescue=rescue/rescue .endif .for _tool in \ bin/csh \ bin/sh \ ${LOCAL_TOOL_DIRS} \ lib/ncurses/ncurses \ lib/ncurses/ncursesw \ ${_rescue} \ ${_share} \ usr.bin/awk \ lib/libmagic \ usr.bin/mkesdb_static \ usr.bin/mkcsmapper_static \ usr.bin/vi/catalog build-tools_${_tool}: .PHONY ${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ build-tools build-tools: build-tools_${_tool} .endfor .for _tool in \ ${_gcc_tools} build-tools_${_tool}: .PHONY ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ depend && \ ${MAKE} DIRPRFX=${_tool}/ all build-tools: build-tools_${_tool} .endfor # # kernel-tools: Build kernel-building tools # kernel-tools: mkdir -p ${MAKEOBJDIRPREFIX}/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${MAKEOBJDIRPREFIX}/usr >/dev/null # # cross-tools: All the tools needed to build the rest of the system after # we get done with the earlier stages. It is the last set of tools needed # to begin building the target binaries. # .if ${TARGET_ARCH} != ${MACHINE_ARCH} .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386" _btxld= usr.sbin/btxld .endif .endif # Rebuild ctfconvert and ctfmerge to avoid difficult-to-diagnose failures # resulting from missing bug fixes or ELF Toolchain updates. .if ${MK_CDDL} != "no" _dtrace_tools= cddl/lib/libctf cddl/usr.bin/ctfconvert \ cddl/usr.bin/ctfmerge .endif # If we're given an XAS, don't build binutils. .if ${XAS:M/*} == "" .if ${MK_BINUTILS_BOOTSTRAP} != "no" _binutils= gnu/usr.bin/binutils .endif .if ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no" _elftctools= lib/libelftc \ usr.bin/elfcopy \ usr.bin/nm \ usr.bin/size \ usr.bin/strings # These are not required by the build, but can be useful for developers who # cross-build on a FreeBSD 10 host: _elftctools+= usr.bin/addr2line .endif .elif ${TARGET_ARCH} != ${MACHINE_ARCH} && ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no" # If cross-building with an external binutils we still need to build strip for # the target (for at least crunchide). _elftctools= lib/libelftc \ usr.bin/elfcopy .endif # If an full path to an external cross compiler is given, don't build # a cross compiler. .if ${XCC:N${CCACHE_BIN}:M/*} == "" && ${MK_CROSS_COMPILER} != "no" .if ${MK_CLANG_BOOTSTRAP} != "no" _clang= usr.bin/clang _clang_libs= lib/clang .endif .if ${MK_GCC_BOOTSTRAP} != "no" _cc= gnu/usr.bin/cc .endif .endif .if ${MK_USB} != "no" _usb_tools= sys/boot/usb/tools .endif cross-tools: .MAKE .PHONY .for _tool in \ ${_clang_libs} \ ${_clang} \ ${_binutils} \ ${_elftctools} \ ${_dtrace_tools} \ ${_cc} \ ${_btxld} \ ${_crunchide} \ ${_usb_tools} ${_+_}@${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 NXBDESTDIR= ${OBJTREE}/nxb-bin NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${PATH}:${OBJTREE}/gperf_for_gcc/usr/bin NXBMAKE= ${NXBENV} ${MAKE} \ TBLGEN=${NXBDESTDIR}/usr/bin/tblgen \ CLANG_TBLGEN=${NXBDESTDIR}/usr/bin/clang-tblgen \ MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} \ MK_GDB=no MK_TESTS=no \ SSP_CFLAGS= \ MK_HTML=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no # native-xtools is the current target for qemu-user cross builds of ports # via poudriere and the imgact_binmisc kernel module. # For non-clang enabled targets that are still using the in tree gcc # we must build a gperf binary for one instance of its Makefiles. On # clang-enabled systems, the gperf binary is obsolete. native-xtools: .PHONY .if ${MK_GCC_BOOTSTRAP} != "no" mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin ${_+_}@${ECHODIR} "===> ${_gperf} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_gperf} && \ ${NXBMAKE} DIRPRFX=${_gperf}/ obj && \ ${NXBMAKE} DIRPRFX=${_gperf}/ depend && \ ${NXBMAKE} DIRPRFX=${_gperf}/ all && \ ${NXBMAKE} DIRPRFX=${_gperf}/ DESTDIR=${OBJTREE}/gperf_for_gcc install .endif mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${NXBDESTDIR}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${NXBDESTDIR}/usr/include >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${NXBDESTDIR}/usr/lib >/dev/null .endif .for _tool in \ bin/cat \ bin/chmod \ bin/cp \ bin/csh \ bin/echo \ bin/expr \ bin/hostname \ bin/ln \ bin/ls \ bin/mkdir \ bin/mv \ bin/ps \ bin/realpath \ bin/rm \ bin/rmdir \ bin/sh \ bin/sleep \ ${_clang_tblgen} \ usr.bin/ar \ ${_binutils} \ ${_elftctools} \ ${_cc} \ ${_gcc_tools} \ ${_clang_libs} \ ${_clang} \ sbin/md5 \ sbin/sysctl \ gnu/usr.bin/diff \ usr.bin/awk \ usr.bin/basename \ usr.bin/bmake \ usr.bin/bzip2 \ usr.bin/cmp \ usr.bin/dirname \ usr.bin/env \ usr.bin/fetch \ usr.bin/find \ usr.bin/grep \ usr.bin/gzip \ usr.bin/id \ usr.bin/lex \ usr.bin/lorder \ usr.bin/mktemp \ usr.bin/mt \ usr.bin/patch \ usr.bin/sed \ usr.bin/sort \ usr.bin/tar \ usr.bin/touch \ usr.bin/tr \ usr.bin/true \ usr.bin/uniq \ usr.bin/unzip \ usr.bin/xargs \ usr.bin/xinstall \ usr.bin/xz \ usr.bin/yacc \ usr.sbin/chown ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${NXBMAKE} DIRPRFX=${_tool}/ obj && \ ${NXBMAKE} DIRPRFX=${_tool}/ depend && \ ${NXBMAKE} DIRPRFX=${_tool}/ all && \ ${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${NXBDESTDIR} install .endfor # # hierarchy - ensure that all the needed directories are present # hierarchy hier: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc && ${HMAKE} distrib-dirs # # 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: .MAKE .PHONY ${_+_}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 _startup_libs+= lib/csu _startup_libs+= gnu/lib/libgcc _startup_libs+= lib/libcompiler_rt _startup_libs+= lib/libc _startup_libs+= lib/libc_nonshared .if ${MK_LIBCPLUSPLUS} != "no" _startup_libs+= lib/libcxxrt .endif gnu/lib/libgcc__L: lib/libc__L gnu/lib/libgcc__L: lib/libc_nonshared__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} \ ${_libsqlite3} \ ${_kerberos5_lib_libheimipcc} \ ${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \ ${_kerberos5_lib_libroken} \ ${_kerberos5_lib_libwind} \ lib/libbz2 ${_libcom_err} lib/libcrypt \ lib/libelf lib/libexpat \ lib/libfigpar \ ${_lib_libgssapi} \ lib/libkiconv lib/libkvm lib/liblzma lib/libmd lib/libnv \ ${_lib_libcapsicum} \ lib/ncurses/ncurses lib/ncurses/ncursesw \ lib/libopie lib/libpam ${_lib_libthr} \ ${_lib_libradius} lib/libsbuf lib/libtacplus \ lib/libgeom \ ${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \ ${_cddl_lib_libuutil} \ ${_cddl_lib_libavl} \ ${_cddl_lib_libzfs_core} \ ${_cddl_lib_libctf} \ lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \ ${_secure_lib_libcrypto} ${_lib_libldns} \ ${_secure_lib_libssh} ${_secure_lib_libssl} \ gnu/lib/libdialog .if ${MK_GNUCXX} != "no" _prebuild_libs+= gnu/lib/libstdc++ gnu/lib/libsupc++ gnu/lib/libstdc++__L: lib/msun__L gnu/lib/libsupc++__L: gnu/lib/libstdc++__L .endif .if ${MK_LIBCPLUSPLUS} != "no" _prebuild_libs+= lib/libc++ .endif lib/libgeom__L: lib/libexpat__L +lib/libkvm__L: lib/libelf__L .if ${MK_LIBTHR} != "no" _lib_libthr= lib/libthr .endif .if ${MK_RADIUS_SUPPORT} != "no" _lib_libradius= lib/libradius .endif .if ${MK_OFED} != "no" _ofed_lib= contrib/ofed/usr.lib/ .endif .if ${MK_CASPER} != "no" _lib_libcapsicum=lib/libcapsicum .endif lib/libcapsicum__L: lib/libnv__L lib/libpjdlog__L: lib/libutil__L lib/liblzma__L: lib/libthr__L _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_libavl= cddl/lib/libavl _cddl_lib_libuutil= cddl/lib/libuutil _cddl_lib_libzfs_core= cddl/lib/libzfs_core _cddl_lib_libctf= cddl/lib/libctf _cddl_lib= cddl/lib cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L cddl/lib/libzfs__L: lib/libgeom__L cddl/lib/libctf__L: lib/libz__L .endif # cddl/lib/libdtrace requires lib/libproc and lib/librtld_db; it's only built # on select architectures though (see cddl/lib/Makefile) .if ${MACHINE_CPUARCH} != "sparc64" _prebuild_libs+= lib/libproc lib/librtld_db .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_LDNS} != "no" _lib_libldns= lib/libldns lib/libldns__L: secure/lib/libcrypto__L .endif .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_LDNS} != "no" secure/lib/libssh__L: lib/libldns__L .endif .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 lib/libsqlite3__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 .endif lib/libsqlite3__L: lib/libthr__L .if ${MK_GSSAPI} != "no" _lib_libgssapi= lib/libgssapi .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 _libsqlite3= lib/libsqlite3 _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 lib/libproc__L: \ ${_cddl_lib_libctf:D${_cddl_lib_libctf}__L} lib/libelf__L lib/librtld_db__L lib/libutil__L .if ${MK_CXX} != "no" .if ${MK_LIBCPLUSPLUS} != "no" lib/libproc__L: lib/libcxxrt__L .else # This implies MK_GNUCXX != "no"; see lib/libproc lib/libproc__L: gnu/lib/libsupc++__L .endif .endif gnu/lib/libdialog__L: lib/msun__L lib/ncurses/ncursesw__L .for _lib in ${_prereq_libs} ${_lib}__PL: .PHONY .MAKE .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib} && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \ ${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \ DIRPRFX=${_lib}/ all && \ ${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \ DIRPRFX=${_lib}/ install .endif .endfor .for _lib in ${_startup_libs} ${_prebuild_libs:Nlib/libpam} ${_generic_libs} ${_lib}__L: .PHONY .MAKE .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib} && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all && \ ${MAKE} MK_TESTS=no 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 .MAKE ${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \ cd ${.CURDIR}/lib/libpam && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ depend && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \ -D_NO_LIBPAM_SO_YET all && \ ${MAKE} MK_TESTS=no 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/} # Enable SUBDIR_PARALLEL when not calling 'make all', unless called as # 'par-all'. This is because it is unlikely that running 'make all' from # the top-level, especially with a SUBDIR_OVERRIDE or LOCAL_DIRS set, # will have a reliable build if SUBDIRs are built in parallel. This is # safe for the world stage of buildworld though since it has already # built libraries in a proper order and installed includes into WORLDTMP. # Special handling is done for SUBDIR ordering for 'install*' to avoid # trashing a system if it crashes mid-install. par-all: all .PHONY .if !make(all) SUBDIR_PARALLEL= .endif .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; \ cd ${.CURDIR}; \ ${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; \ for ext in debug symbols; do \ if ! [ -e "${DESTDIR}/$${file}" ] && [ -f \ "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ rm ${RM_I} "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" \ <&3; \ fi; \ done; \ 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" @cd ${.CURDIR}; \ ${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; \ for ext in debug symbols; do \ if [ -f "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ echo "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}"; \ fi; \ done; \ 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; \ cd ${.CURDIR}; \ ${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; \ for ext in debug symbols; do \ if ! [ -e "${DESTDIR}/$${file}" ] && [ -f \ "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ rm ${RM_I} "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" \ <&3; \ fi; \ done; \ done @echo ">>> Old libraries removed" check-old-libs: @echo ">>> Checking for old libraries" @cd ${.CURDIR}; \ ${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; \ for ext in debug symbols; do \ if [ -f "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ echo "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}"; \ fi; \ done; \ done delete-old-dirs: @echo ">>> Removing old directories" @cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_DIRS | xargs -n1 | sort -r | \ 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" @cd ${.CURDIR}; \ ${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 ${.CURDIR}/sys/conf/kern.opts.mk -V dummy -dg1; \ ${MAKE} -n -f ${.CURDIR}/share/mk/src.opts.mk -V dummy -dg1) 2>&1 | grep ^MK_ | sort -u .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: @PATH=${TMPPATH} MACHINE=${TARGET} \ ${.CURDIR}/sys/tools/fdt/make_dtb.sh ${.CURDIR}/sys \ "${FDT_DTS_FILE}" ${DTBOUTPUTPATH} ############### # cleanworld # In the following, the first 'rm' in a series will usually remove all # files and directories. If it does not, then there are probably some # files with file flags set, so this unsets them and tries the 'rm' a # second time. There are situations where this target will be cleaning # some directories via more than one method, but that duplication is # needed to correctly handle all the possible situations. Removing all # files without file flags set in the first 'rm' instance saves time, # because 'chflags' will need to operate on fewer files afterwards. # # It is expected that BW_CANONICALOBJDIR == the CANONICALOBJDIR as would be # created by bsd.obj.mk, except that we don't want to .include that file # in this makefile. # BW_CANONICALOBJDIR:=${OBJTREE}${.CURDIR} cleanworld: .PHONY .if exists(${BW_CANONICALOBJDIR}/) -rm -rf ${BW_CANONICALOBJDIR}/* -chflags -R 0 ${BW_CANONICALOBJDIR} rm -rf ${BW_CANONICALOBJDIR}/* .endif .if ${.CURDIR} == ${.OBJDIR} || ${.CURDIR}/obj == ${.OBJDIR} # To be safe in this case, fall back to a 'make cleandir' ${_+_}@cd ${.CURDIR}; ${MAKE} cleandir .endif .if defined(TARGET) && defined(TARGET_ARCH) .if ${TARGET} == ${MACHINE} && ${TARGET_ARCH} == ${MACHINE_ARCH} XDEV_CPUTYPE?=${CPUTYPE} .else XDEV_CPUTYPE?=${TARGET_CPUTYPE} .endif NOFUN=-DNO_FSCHG MK_HTML=no -DNO_LINT \ MK_MAN=no MK_NLS=no MK_PROFILE=no \ MK_KERBEROS=no MK_RESCUE=no MK_TESTS=no MK_WARNS=no \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ CPUTYPE=${XDEV_CPUTYPE} XDDIR=${TARGET_ARCH}-freebsd XDTP?=/usr/${XDDIR} .if ${XDTP:N/*} .error XDTP variable should be an absolute path .endif CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \ INSTALL="sh ${.CURDIR}/tools/install.sh" CDENV= ${CDBENV} \ TOOLS_PREFIX=${XDTP} CD2CFLAGS=-isystem ${XDDESTDIR}/usr/include -L${XDDESTDIR}/usr/lib \ --sysroot=${XDDESTDIR}/ -B${XDDESTDIR}/usr/libexec \ -B${XDDESTDIR}/usr/bin -B${XDDESTDIR}/usr/lib CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" CXX="${CXX} ${CD2CFLAGS}" \ CPP="${CPP} ${CD2CFLAGS}" \ MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} CDTMP= ${MAKEOBJDIRPREFIX}/${XDDIR}/${.CURDIR}/tmp CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${NOFUN} CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} ${MAKE} ${NOFUN} XDDESTDIR=${DESTDIR}/${XDTP} .if !defined(OSREL) OSREL!= uname -r | sed -e 's/[-(].*//' .endif .ORDER: xdev-build xdev-install xdev-links xdev: xdev-build xdev-install .ORDER: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools xdev-build: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools _xb-worldtmp: .PHONY mkdir -p ${CDTMP}/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${CDTMP}/usr >/dev/null _xb-bootstrap-tools: .PHONY .for _tool in \ ${_clang_tblgen} \ ${_gperf} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${CDMAKE} DIRPRFX=${_tool}/ obj && \ ${CDMAKE} DIRPRFX=${_tool}/ depend && \ ${CDMAKE} DIRPRFX=${_tool}/ all && \ ${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install .endfor _xb-build-tools: .PHONY ${_+_}@cd ${.CURDIR}; \ ${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools _xb-cross-tools: .PHONY .for _tool in \ ${_binutils} \ ${_elftctools} \ usr.bin/ar \ ${_clang_libs} \ ${_clang} \ ${_cc} ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool} && \ ${CDMAKE} DIRPRFX=${_tool}/ obj && \ ${CDMAKE} DIRPRFX=${_tool}/ depend && \ ${CDMAKE} DIRPRFX=${_tool}/ all .endfor _xi-mtree: .PHONY ${_+_}@${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 .if ${MK_LIB32} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib32.dist \ -p ${XDDESTDIR}/usr >/dev/null .endif .if ${MK_TESTS} != "no" mkdir -p ${XDDESTDIR}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${XDDESTDIR}${TESTSBASE} >/dev/null .endif .ORDER: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-cross-tools: .PHONY @echo "_xi-cross-tools" .for _tool in \ ${_binutils} \ ${_elftctools} \ usr.bin/ar \ ${_clang_libs} \ ${_clang} \ ${_cc} ${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \ cd ${.CURDIR}/${_tool}; \ ${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR} .endfor _xi-includes: .PHONY ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 buildincludes \ DESTDIR=${XDDESTDIR} ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 installincludes \ DESTDIR=${XDDESTDIR} _xi-libraries: .PHONY ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 libraries \ DESTDIR=${XDDESTDIR} xdev-links: .PHONY ${_+_}cd ${XDDESTDIR}/usr/bin; \ mkdir -p ../../../../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-build xdev-install xdev-links: @echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${.TARGET}\" target" .endif Index: head/gnu/usr.bin/gdb/kgdb/Makefile =================================================================== --- head/gnu/usr.bin/gdb/kgdb/Makefile (revision 291405) +++ head/gnu/usr.bin/gdb/kgdb/Makefile (revision 291406) @@ -1,19 +1,15 @@ # $FreeBSD$ PROG= kgdb${GDB_SUFFIX} SRCS= main.c kld.c kthr.c trgt.c trgt_${TARGET_CPUARCH}.c WARNS?= 2 BULIBS= ${OBJ_BU}/libbfd/libbfd.a ${OBJ_BU}/libopcodes/libopcodes.a \ ${OBJ_BU}/libiberty/libiberty.a GDBLIBS= ${OBJ_GDB}/libgdb/libgdb.a DPADD= ${GDBLIBS} ${BULIBS} ${LIBKVM} -LDADD= ${GDBLIBS} ${BULIBS} -lkvm${GDB_SUFFIX} +LDADD= ${GDBLIBS} ${BULIBS} -lkvm LIBADD+= m readline ncursesw gnuregex - -.if defined(GDB_CROSS_DEBUGGER) -CFLAGS+= -Wl,-export-dynamic -.endif .include Index: head/gnu/usr.bin/gdb/kgdb/main.c =================================================================== --- head/gnu/usr.bin/gdb/kgdb/main.c (revision 291405) +++ head/gnu/usr.bin/gdb/kgdb/main.c (revision 291406) @@ -1,502 +1,481 @@ /* * Copyright (c) 2004 Marcel Moolenaar * 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 #include #include -#ifdef CROSS_DEBUGGER -#include -#endif #include #include #include #include /* libgdb stuff. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern frame_unwind_sniffer_ftype *kgdb_sniffer_kluge; #include "kgdb.h" static int dumpnr; static int quiet; static int verbose; static char crashdir[PATH_MAX]; static char *kernel; static char *remote; static char *vmcore; static struct ui_file *parse_gdberr; static void (*kgdb_new_objfile_chain)(struct objfile * objfile); - -#ifdef CROSS_DEBUGGER -ps_err_e -ps_pglobal_lookup(struct ps_prochandle *ph, const char *obj, const char *name, - psaddr_t *sym_addr) -{ - struct minimal_symbol *ms; - CORE_ADDR addr; - - ms = lookup_minimal_symbol (name, NULL, NULL); - if (ms == NULL) - return PS_NOSYM; - - addr = SYMBOL_VALUE_ADDRESS (ms); - store_typed_address(sym_addr, builtin_type_void_data_ptr, addr); - return PS_OK; -} -#endif static void usage(void) { fprintf(stderr, "usage: %s [-afqvw] [-b rate] [-d crashdir] [-c core | -n dumpnr | -r device]\n" "\t[kernel [core]]\n", getprogname()); exit(1); } static void kernel_from_dumpnr(int nr) { char path[PATH_MAX]; FILE *info; char *s; struct stat st; int l; /* * If there's a kernel image right here in the crash directory, then * use it. The kernel image is either called kernel. or is in a * subdirectory kernel. and called kernel. The latter allows us * to collect the modules in the same place. */ snprintf(path, sizeof(path), "%s/kernel.%d", crashdir, nr); if (stat(path, &st) == 0) { if (S_ISREG(st.st_mode)) { kernel = strdup(path); return; } if (S_ISDIR(st.st_mode)) { snprintf(path, sizeof(path), "%s/kernel.%d/kernel", crashdir, nr); if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { kernel = strdup(path); return; } } } /* * No kernel image here. Parse the dump header. The kernel object * directory can be found there and we probably have the kernel * image still in it. The object directory may also have a kernel * with debugging info (called kernel.debug). If we have a debug * kernel, use it. */ snprintf(path, sizeof(path), "%s/info.%d", crashdir, nr); info = fopen(path, "r"); if (info == NULL) { warn("%s", path); return; } while (fgets(path, sizeof(path), info) != NULL) { l = strlen(path); if (l > 0 && path[l - 1] == '\n') path[--l] = '\0'; if (strncmp(path, " ", 4) == 0) { s = strchr(path, ':'); s = (s == NULL) ? path + 4 : s + 1; l = snprintf(path, sizeof(path), "%s/kernel.debug", s); if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { path[l - 6] = '\0'; if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) break; } kernel = strdup(path); break; } } fclose(info); } static void kgdb_new_objfile(struct objfile *objfile) { static int once = 1; kld_new_objfile(objfile); kgdb_trgt_new_objfile(objfile); if (kgdb_new_objfile_chain != NULL) kgdb_new_objfile_chain(objfile); if (once && objfile != NULL && objfile == symfile_objfile) { /* * The initial kernel has just been loaded. Start the * remote target if we have one. */ once = 0; if (remote != NULL) push_remote_target (remote, 0); } } /* * Parse an expression and return its value. If 'quiet' is true, then * any error messages from the parser are masked. */ CORE_ADDR kgdb_parse_1(const char *exp, int quiet) { struct ui_file *old_stderr; struct cleanup *old_chain; struct expression *expr; struct value *val; char *s; CORE_ADDR n; old_stderr = gdb_stderr; if (quiet) gdb_stderr = parse_gdberr; n = 0; s = xstrdup(exp); old_chain = make_cleanup(xfree, s); if (gdb_parse_exp_1(&s, NULL, 0, &expr) && *s == '\0') { make_cleanup(free_current_contents, &expr); if (gdb_evaluate_expression(expr, &val)) n = value_as_address(val); } do_cleanups(old_chain); gdb_stderr = old_stderr; return (n); } #define MSGBUF_SEQ_TO_POS(size, seq) ((seq) % (size)) void kgdb_dmesg(void) { CORE_ADDR bufp; int size, rseq, wseq; char c; /* * Display the unread portion of the message buffer. This gives the * user a some initial data to work from. */ if (quiet) return; bufp = kgdb_parse("msgbufp->msg_ptr"); size = (int)kgdb_parse("msgbufp->msg_size"); if (bufp == 0 || size == 0) return; rseq = (int)kgdb_parse("msgbufp->msg_rseq"); wseq = (int)kgdb_parse("msgbufp->msg_wseq"); rseq = MSGBUF_SEQ_TO_POS(size, rseq); wseq = MSGBUF_SEQ_TO_POS(size, wseq); if (rseq == wseq) return; printf("\nUnread portion of the kernel message buffer:\n"); while (rseq < wseq) { read_memory(bufp + rseq, &c, 1); putchar(c); rseq++; if (rseq == size) rseq = 0; } if (c != '\n') putchar('\n'); putchar('\n'); } static void kgdb_init(char *argv0 __unused) { parse_gdberr = mem_fileopen(); set_prompt("(kgdb) "); initialize_kgdb_target(); initialize_kld_target(); kgdb_new_objfile_chain = target_new_objfile_hook; target_new_objfile_hook = kgdb_new_objfile; } /* * Remote targets can support any number of syntaxes and we want to * support them all with one addition: we support specifying a device * node for a serial device without the "/dev/" prefix. * * What we do is to stat(2) the existing remote target first. If that * fails, we try it with "/dev/" prepended. If that succeeds we use * the resulting path, otherwise we use the original target. If * either stat(2) succeeds make sure the file is either a character * device or a FIFO. */ static void verify_remote(void) { char path[PATH_MAX]; struct stat st; if (stat(remote, &st) != 0) { snprintf(path, sizeof(path), "/dev/%s", remote); if (stat(path, &st) != 0) return; free(remote); remote = strdup(path); } if (!S_ISCHR(st.st_mode) && !S_ISFIFO(st.st_mode)) errx(1, "%s: not a special file, FIFO or socket", remote); } static void add_arg(struct captured_main_args *args, char *arg) { args->argc++; args->argv = reallocf(args->argv, (args->argc + 1) * sizeof(char *)); if (args->argv == NULL) err(1, "Out of memory building argument list"); args->argv[args->argc] = arg; } int main(int argc, char *argv[]) { char path[PATH_MAX]; struct stat st; struct captured_main_args args; char *s; int a, ch; dumpnr = -1; strlcpy(crashdir, "/var/crash", sizeof(crashdir)); s = getenv("KGDB_CRASH_DIR"); if (s != NULL) strlcpy(crashdir, s, sizeof(crashdir)); /* Convert long options into short options. */ for (a = 1; a < argc; a++) { s = argv[a]; if (s[0] == '-') { s++; /* Long options take either 1 or 2 dashes. */ if (s[0] == '-') s++; if (strcmp(s, "quiet") == 0) argv[a] = "-q"; else if (strcmp(s, "fullname") == 0) argv[a] = "-f"; } } quiet = 0; memset (&args, 0, sizeof args); args.use_windows = 0; args.interpreter_p = INTERP_CONSOLE; args.argv = malloc(sizeof(char *)); args.argv[0] = argv[0]; while ((ch = getopt(argc, argv, "ab:c:d:fn:qr:vw")) != -1) { switch (ch) { case 'a': annotation_level++; break; case 'b': { int i; char *p; i = strtol(optarg, &p, 0); if (*p != '\0' || p == optarg) warnx("warning: could not set baud rate to `%s'.\n", optarg); else baud_rate = i; break; } case 'c': /* use given core file. */ if (vmcore != NULL) { warnx("option %c: can only be specified once", optopt); usage(); /* NOTREACHED */ } vmcore = strdup(optarg); break; case 'd': /* lookup dumps in given directory. */ strlcpy(crashdir, optarg, sizeof(crashdir)); break; case 'f': annotation_level = 1; break; case 'n': /* use dump with given number. */ dumpnr = strtol(optarg, &s, 0); if (dumpnr < 0 || *s != '\0') { warnx("option %c: invalid kernel dump number", optopt); usage(); /* NOTREACHED */ } break; case 'q': quiet = 1; add_arg(&args, "-q"); break; case 'r': /* use given device for remote session. */ if (remote != NULL) { warnx("option %c: can only be specified once", optopt); usage(); /* NOTREACHED */ } remote = strdup(optarg); break; case 'v': /* increase verbosity. */ verbose++; break; case 'w': /* core file is writeable. */ add_arg(&args, "--write"); break; case '?': default: usage(); } } if (((vmcore != NULL) ? 1 : 0) + ((dumpnr >= 0) ? 1 : 0) + ((remote != NULL) ? 1 : 0) > 1) { warnx("options -c, -n and -r are mutually exclusive"); usage(); /* NOTREACHED */ } if (verbose > 1) warnx("using %s as the crash directory", crashdir); if (argc > optind) kernel = strdup(argv[optind++]); if (argc > optind && (dumpnr >= 0 || remote != NULL)) { warnx("options -n and -r do not take a core file. Ignored"); optind = argc; } if (dumpnr >= 0) { snprintf(path, sizeof(path), "%s/vmcore.%d", crashdir, dumpnr); if (stat(path, &st) == -1) err(1, "%s", path); if (!S_ISREG(st.st_mode)) errx(1, "%s: not a regular file", path); vmcore = strdup(path); } else if (remote != NULL) { verify_remote(); } else if (argc > optind) { if (vmcore == NULL) vmcore = strdup(argv[optind++]); if (argc > optind) warnx("multiple core files specified. Ignored"); } else if (vmcore == NULL && kernel == NULL) { vmcore = strdup(_PATH_MEM); kernel = strdup(getbootfile()); } if (verbose) { if (vmcore != NULL) warnx("core file: %s", vmcore); if (remote != NULL) warnx("device file: %s", remote); if (kernel != NULL) warnx("kernel image: %s", kernel); } /* A remote target requires an explicit kernel argument. */ if (remote != NULL && kernel == NULL) { warnx("remote debugging requires a kernel"); usage(); /* NOTREACHED */ } /* If we don't have a kernel image yet, try to find one. */ if (kernel == NULL) { if (dumpnr >= 0) kernel_from_dumpnr(dumpnr); if (kernel == NULL) errx(1, "couldn't find a suitable kernel image"); if (verbose) warnx("kernel image: %s", kernel); } add_arg(&args, kernel); if (vmcore != NULL) add_arg(&args, vmcore); /* The libgdb code uses optind too. Reset it... */ optind = 0; /* Terminate argv list. */ add_arg(&args, NULL); init_ui_hook = kgdb_init; kgdb_sniffer_kluge = kgdb_trgt_trapframe_sniffer; return (gdb_main(&args)); } Index: head/gnu/usr.bin/gdb/kgdb/trgt.c =================================================================== --- head/gnu/usr.bin/gdb/kgdb/trgt.c (revision 291405) +++ head/gnu/usr.bin/gdb/kgdb/trgt.c (revision 291406) @@ -1,383 +1,396 @@ /* * Copyright (c) 2004 Marcel Moolenaar * 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 #include #include #include #include #include #include #include #include #include #include #include "kgdb.h" #ifdef CROSS_DEBUGGER /* * We suppress the call to add_target() of core_ops in corelow.c because if * there are multiple core_stratum targets, the find_core_target() function * won't know which one to return and returns none. We need it to return * our target. We only have to do that when we're building a cross-debugger * because fbsd-threads.c is part of a native debugger and it too defines * coreops_suppress_target with 1 as the initializer. */ int coreops_suppress_target = 1; #endif static CORE_ADDR stoppcbs; static void kgdb_core_cleanup(void *); static char *vmcore; static struct target_ops kgdb_trgt_ops; kvm_t *kvm; static char kvm_err[_POSIX2_LINE_MAX]; #define KERNOFF (kgdb_kernbase ()) #define PINKERNEL(x) ((x) >= KERNOFF) +static int +kgdb_resolve_symbol(const char *name, kvaddr_t *kva) +{ + struct minimal_symbol *ms; + + ms = lookup_minimal_symbol (name, NULL, NULL); + if (ms == NULL) + return (1); + + *kva = SYMBOL_VALUE_ADDRESS (ms); + return (0);; +} + static CORE_ADDR kgdb_kernbase (void) { static CORE_ADDR kernbase; struct minimal_symbol *sym; if (kernbase == 0) { sym = lookup_minimal_symbol ("kernbase", NULL, NULL); if (sym == NULL) { kernbase = KERNBASE; } else { kernbase = SYMBOL_VALUE_ADDRESS (sym); } } return kernbase; } static void kgdb_trgt_open(char *filename, int from_tty) { struct cleanup *old_chain; struct thread_info *ti; struct kthr *kt; kvm_t *nkvm; char *temp; int ontop; target_preopen (from_tty); if (!filename) error ("No vmcore file specified."); if (!exec_bfd) error ("Can't open a vmcore without a kernel"); filename = tilde_expand (filename); if (filename[0] != '/') { temp = concat (current_directory, "/", filename, NULL); xfree(filename); filename = temp; } old_chain = make_cleanup (xfree, filename); - nkvm = kvm_openfiles(bfd_get_filename(exec_bfd), filename, NULL, - write_files ? O_RDWR : O_RDONLY, kvm_err); + nkvm = kvm_open2(bfd_get_filename(exec_bfd), filename, + write_files ? O_RDWR : O_RDONLY, kvm_err, kgdb_resolve_symbol); if (nkvm == NULL) error ("Failed to open vmcore: %s", kvm_err); /* Don't free the filename now and close any previous vmcore. */ discard_cleanups(old_chain); unpush_target(&kgdb_trgt_ops); kvm = nkvm; vmcore = filename; old_chain = make_cleanup(kgdb_core_cleanup, NULL); ontop = !push_target (&kgdb_trgt_ops); discard_cleanups (old_chain); kgdb_dmesg(); init_thread_list(); kt = kgdb_thr_init(); while (kt != NULL) { ti = add_thread(pid_to_ptid(kt->tid)); kt = kgdb_thr_next(kt); } if (curkthr != 0) inferior_ptid = pid_to_ptid(curkthr->tid); if (ontop) { /* XXX: fetch registers? */ kld_init(); flush_cached_frames(); select_frame (get_current_frame()); print_stack_frame(get_selected_frame(), frame_relative_level(get_selected_frame()), 1); } else warning( "you won't be able to access this vmcore until you terminate\n\ your %s; do ``info files''", target_longname); } static void kgdb_trgt_close(int quitting) { if (kvm != NULL) { inferior_ptid = null_ptid; CLEAR_SOLIB(); if (kvm_close(kvm) != 0) warning("cannot close \"%s\": %s", vmcore, kvm_geterr(kvm)); kvm = NULL; xfree(vmcore); vmcore = NULL; if (kgdb_trgt_ops.to_sections) { xfree(kgdb_trgt_ops.to_sections); kgdb_trgt_ops.to_sections = NULL; kgdb_trgt_ops.to_sections_end = NULL; } } } static void kgdb_core_cleanup(void *arg) { kgdb_trgt_close(0); } static void kgdb_trgt_detach(char *args, int from_tty) { if (args) error ("Too many arguments"); unpush_target(&kgdb_trgt_ops); reinit_frame_cache(); if (from_tty) printf_filtered("No vmcore file now.\n"); } static char * kgdb_trgt_extra_thread_info(struct thread_info *ti) { return (kgdb_thr_extra_thread_info(ptid_get_pid(ti->ptid))); } static void kgdb_trgt_files_info(struct target_ops *target) { printf_filtered ("\t`%s', ", vmcore); wrap_here (" "); printf_filtered ("file type %s.\n", "FreeBSD kernel vmcore"); } static void kgdb_trgt_find_new_threads(void) { struct target_ops *tb; if (kvm != NULL) return; tb = find_target_beneath(&kgdb_trgt_ops); if (tb->to_find_new_threads != NULL) tb->to_find_new_threads(); } static char * kgdb_trgt_pid_to_str(ptid_t ptid) { static char buf[33]; snprintf(buf, sizeof(buf), "Thread %d", ptid_get_pid(ptid)); return (buf); } static int kgdb_trgt_thread_alive(ptid_t ptid) { return (kgdb_thr_lookup_tid(ptid_get_pid(ptid)) != NULL); } static int kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write, struct mem_attrib *attrib, struct target_ops *target) { struct target_ops *tb; if (kvm != NULL) { if (len == 0) return (0); if (!write) - return (kvm_read(kvm, memaddr, myaddr, len)); + return (kvm_read2(kvm, memaddr, myaddr, len)); else return (kvm_write(kvm, memaddr, myaddr, len)); } tb = find_target_beneath(target); return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb)); } static int kgdb_trgt_ignore_breakpoints(CORE_ADDR addr, char *contents) { return 0; } static void kgdb_switch_to_thread(int tid) { char buf[16]; int thread_id; thread_id = pid_to_thread_id(pid_to_ptid(tid)); if (thread_id == 0) error ("invalid tid"); snprintf(buf, sizeof(buf), "%d", thread_id); gdb_thread_select(uiout, buf); } static void kgdb_set_proc_cmd (char *arg, int from_tty) { CORE_ADDR addr; struct kthr *thr; if (!arg) error_no_arg ("proc address for the new context"); if (kvm == NULL) error ("only supported for core file target"); addr = (CORE_ADDR) parse_and_eval_address (arg); if (!PINKERNEL (addr)) { thr = kgdb_thr_lookup_pid((int)addr); if (thr == NULL) error ("invalid pid"); } else { thr = kgdb_thr_lookup_paddr(addr); if (thr == NULL) error("invalid proc address"); } kgdb_switch_to_thread(thr->tid); } static void kgdb_set_tid_cmd (char *arg, int from_tty) { CORE_ADDR addr; struct kthr *thr; if (!arg) error_no_arg ("TID or thread address for the new context"); addr = (CORE_ADDR) parse_and_eval_address (arg); if (kvm != NULL && PINKERNEL (addr)) { thr = kgdb_thr_lookup_taddr(addr); if (thr == NULL) error("invalid thread address"); addr = thr->tid; } kgdb_switch_to_thread(addr); } int fbsdcoreops_suppress_target = 1; void initialize_kgdb_target(void) { kgdb_trgt_ops.to_magic = OPS_MAGIC; kgdb_trgt_ops.to_shortname = "kernel"; kgdb_trgt_ops.to_longname = "kernel core dump file"; kgdb_trgt_ops.to_doc = "Use a vmcore file as a target. Specify the filename of the vmcore file."; kgdb_trgt_ops.to_stratum = core_stratum; kgdb_trgt_ops.to_has_memory = 1; kgdb_trgt_ops.to_has_registers = 1; kgdb_trgt_ops.to_has_stack = 1; kgdb_trgt_ops.to_open = kgdb_trgt_open; kgdb_trgt_ops.to_close = kgdb_trgt_close; kgdb_trgt_ops.to_attach = find_default_attach; kgdb_trgt_ops.to_detach = kgdb_trgt_detach; kgdb_trgt_ops.to_extra_thread_info = kgdb_trgt_extra_thread_info; kgdb_trgt_ops.to_fetch_registers = kgdb_trgt_fetch_registers; kgdb_trgt_ops.to_files_info = kgdb_trgt_files_info; kgdb_trgt_ops.to_find_new_threads = kgdb_trgt_find_new_threads; kgdb_trgt_ops.to_pid_to_str = kgdb_trgt_pid_to_str; kgdb_trgt_ops.to_store_registers = kgdb_trgt_store_registers; kgdb_trgt_ops.to_thread_alive = kgdb_trgt_thread_alive; kgdb_trgt_ops.to_xfer_memory = kgdb_trgt_xfer_memory; kgdb_trgt_ops.to_insert_breakpoint = kgdb_trgt_ignore_breakpoints; kgdb_trgt_ops.to_remove_breakpoint = kgdb_trgt_ignore_breakpoints; add_target(&kgdb_trgt_ops); add_com ("proc", class_obscure, kgdb_set_proc_cmd, "Set current process context"); add_com ("tid", class_obscure, kgdb_set_tid_cmd, "Set current thread context"); } CORE_ADDR kgdb_trgt_stop_pcb(u_int cpuid, u_int pcbsz) { static int once = 0; if (stoppcbs == 0 && !once) { once = 1; stoppcbs = kgdb_lookup("stoppcbs"); } if (stoppcbs == 0) return 0; return (stoppcbs + pcbsz * cpuid); } Index: head/lib/libkvm/kvm_aarch64.c =================================================================== --- head/lib/libkvm/kvm_aarch64.c (revision 291405) +++ head/lib/libkvm/kvm_aarch64.c (nonexistent) @@ -1,105 +0,0 @@ -/*- - * Copyright (C) 2006 Bruce M. Simpson. - * Copyright (c) 2015 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Andrew Turner under - * sponsorship from the FreeBSD Foundation. - * - * 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 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. - */ - -/* - * arm64 (AArch64) machine dependent routines for kvm. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "kvm_private.h" - -/* minidump must be the first item! */ -struct vmstate { - int minidump; /* 1 = minidump mode */ - void *mmapbase; - size_t mmapsize; -}; - -void -_kvm_freevtop(kvm_t *kd) -{ - - if (kd->vmst != 0) { - if (kd->vmst->minidump) - return (_kvm_minidump_freevtop(kd)); - if (kd->vmst->mmapbase != NULL) - munmap(kd->vmst->mmapbase, kd->vmst->mmapsize); - free(kd->vmst); - kd->vmst = NULL; - } -} - -int -_kvm_initvtop(kvm_t *kd) -{ - char minihdr[8]; - - if (!kd->rawdump) { - if (pread(kd->pmfd, &minihdr, 8, 0) == 8) { - if (memcmp(&minihdr, "minidump", 8) == 0) - return (_kvm_minidump_initvtop(kd)); - } else { - _kvm_err(kd, kd->program, "cannot read header"); - return (-1); - } - } - - _kvm_err(kd, 0, "_kvm_initvtop: Unsupported image type"); - return (-1); -} - -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) -{ - - if (kd->vmst->minidump) - return _kvm_minidump_kvatop(kd, va, pa); - - - _kvm_err(kd, 0, "_kvm_kvatop: Unsupported image type"); - return (0); -} Property changes on: head/lib/libkvm/kvm_aarch64.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/lib/libkvm/kvm_mips.c =================================================================== --- head/lib/libkvm/kvm_mips.c (revision 291405) +++ head/lib/libkvm/kvm_mips.c (nonexistent) @@ -1,116 +0,0 @@ -/*- - * Copyright (C) 2006 Bruce M. Simpson. - * 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 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. - */ - -/* - * MIPS machine dependent routines for kvm. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "kvm_private.h" - -/* minidump must be the first item! */ -struct vmstate { - int minidump; /* 1 = minidump mode */ - void *mmapbase; - size_t mmapsize; -}; - -void -_kvm_freevtop(kvm_t *kd) -{ - if (kd->vmst != 0) { - if (kd->vmst->minidump) - return (_kvm_minidump_freevtop(kd)); - if (kd->vmst->mmapbase != NULL) - munmap(kd->vmst->mmapbase, kd->vmst->mmapsize); - free(kd->vmst); - kd->vmst = NULL; - } -} - -int -_kvm_initvtop(kvm_t *kd) -{ - char minihdr[8]; - - if (!kd->rawdump) { - if (pread(kd->pmfd, &minihdr, 8, 0) == 8) { - if (memcmp(&minihdr, "minidump", 8) == 0) - return (_kvm_minidump_initvtop(kd)); - } else { - _kvm_err(kd, kd->program, "cannot read header"); - return (-1); - } - } - - _kvm_err(kd, 0, "_kvm_initvtop: Unsupported image type"); - return (-1); -} - -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) -{ - - if (kd->vmst->minidump) - return _kvm_minidump_kvatop(kd, va, pa); - - - _kvm_err(kd, 0, "_kvm_kvatop: Unsupported image type"); - return (0); -} - -/* - * Machine-dependent initialization for ALL open kvm descriptors, - * not just those for a kernel crash dump. Some architectures - * have to deal with these NOT being constants! (i.e. m68k) - */ -#ifdef FBSD_NOT_YET -int -_kvm_mdopen(kvm_t *kd __unused) -{ - - return (0); -} -#endif Property changes on: head/lib/libkvm/kvm_mips.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/lib/libkvm/Makefile =================================================================== --- head/lib/libkvm/Makefile (revision 291405) +++ head/lib/libkvm/Makefile (revision 291406) @@ -1,50 +1,38 @@ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ -.if defined(TARGET_ARCH) && !defined(COMPAT_32BIT) -KVM_XARCH=${TARGET_ARCH} -KVM_XCPUARCH=${KVM_XARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc64/powerpc/} -.else -KVM_XARCH=${MACHINE_ARCH} -KVM_XCPUARCH=${MACHINE_CPUARCH} -.endif - -.if ${KVM_XARCH} != ${MACHINE_ARCH} -LIB= kvm-${KVM_XARCH} -CFLAGS+=-DCROSS_LIBKVM -.else LIB= kvm -.endif SHLIBDIR?= /lib SHLIB_MAJOR= 6 CFLAGS+=-DLIBC_SCCS -I${.CURDIR} -.if exists(${.CURDIR}/kvm_${KVM_XARCH}.c) -KVM_ARCH=${KVM_XARCH} -.else -KVM_ARCH=${KVM_XCPUARCH} -.endif - WARNS?= 3 -SRCS= kvm.c kvm_${KVM_ARCH}.c kvm_cptime.c kvm_file.c kvm_getloadavg.c \ - kvm_getswapinfo.c kvm_pcpu.c kvm_proc.c kvm_vnet.c -.if exists(${.CURDIR}/kvm_minidump_${KVM_ARCH}.c) -SRCS+= kvm_minidump_${KVM_ARCH}.c -.endif +SRCS= kvm.c kvm_cptime.c kvm_file.c kvm_getloadavg.c \ + kvm_getswapinfo.c kvm_pcpu.c kvm_proc.c kvm_vnet.c \ + kvm_minidump_aarch64.c \ + kvm_amd64.c kvm_minidump_amd64.c \ + kvm_arm.c kvm_minidump_arm.c \ + kvm_i386.c kvm_minidump_i386.c \ + kvm_minidump_mips.c \ + kvm_powerpc.c kvm_powerpc64.c \ + kvm_sparc64.c INCS= kvm.h +LIBADD= elf + MAN= kvm.3 kvm_getcptime.3 kvm_geterr.3 kvm_getfiles.3 kvm_getloadavg.3 \ - kvm_getpcpu.3 kvm_getprocs.3 kvm_getswapinfo.3 kvm_nlist.3 kvm_open.3 \ - kvm_read.3 + kvm_getpcpu.3 kvm_getprocs.3 kvm_getswapinfo.3 kvm_native.3 \ + kvm_nlist.3 kvm_open.3 kvm_read.3 MLINKS+=kvm_getpcpu.3 kvm_getmaxcpu.3 \ kvm_getpcpu.3 kvm_dpcpu_setcpu.3 \ kvm_getpcpu.3 kvm_read_zpcpu.3 \ kvm_getpcpu.3 kvm_counter_u64_fetch.3 MLINKS+=kvm_getprocs.3 kvm_getargv.3 kvm_getprocs.3 kvm_getenvv.3 -MLINKS+=kvm_open.3 kvm_close.3 kvm_open.3 kvm_openfiles.3 -MLINKS+=kvm_read.3 kvm_write.3 +MLINKS+=kvm_nlist.3 kvm_nlist2.3 +MLINKS+=kvm_open.3 kvm_close.3 kvm_open.3 kvm_open2.3 kvm_open.3 kvm_openfiles.3 +MLINKS+=kvm_read.3 kvm_read2.3 kvm_read.3 kvm_write.3 .include Index: head/lib/libkvm/Makefile.depend =================================================================== --- head/lib/libkvm/Makefile.depend (revision 291405) +++ head/lib/libkvm/Makefile.depend (revision 291406) @@ -1,18 +1,19 @@ # $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ + lib/libelf \ .include .if ${DEP_RELDIR} == ${_DEP_RELDIR} # local dependencies - needed for -jN in clean tree .endif Index: head/lib/libkvm/kvm.3 =================================================================== --- head/lib/libkvm/kvm.3 (revision 291405) +++ head/lib/libkvm/kvm.3 (revision 291406) @@ -1,120 +1,162 @@ .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software developed by the Computer Systems .\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract .\" BG 91-66 and contributed to Berkeley. .\" .\" 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. .\" .\" @(#)kvm.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd April 25, 2010 +.Dd November 27, 2015 .Dt KVM 3 .Os .Sh NAME .Nm kvm .Nd kernel memory interface .Sh LIBRARY .Lb libkvm .Sh DESCRIPTION The .Nm library provides a uniform interface for accessing kernel virtual memory images, including live systems and crash dumps. Access to live systems is via .Xr sysctl 3 for some functions, and .Xr mem 4 and .Xr kmem 4 for other functions, while crash dumps can be examined via the core file generated by .Xr savecore 8 . The interface behaves similarly in both cases. Memory can be read and written, kernel symbol addresses can be looked up efficiently, and information about user processes can be gathered. .Pp The .Fn kvm_open function is first called to obtain a descriptor for all subsequent calls. .Sh COMPATIBILITY The kvm interface was first introduced in SunOS. A considerable number of programs have been developed that use this interface, making backward compatibility highly desirable. In most respects, the Sun kvm interface is consistent and clean. Accordingly, the generic portion of the interface (i.e., .Fn kvm_open , .Fn kvm_close , .Fn kvm_read , .Fn kvm_write , and .Fn kvm_nlist ) has been incorporated into the .Bx interface. Indeed, many kvm applications (i.e., debuggers and statistical monitors) use only this subset of the interface. .Pp The process interface was not kept. This is not a portability issue since any code that manipulates processes is inherently machine dependent. .Pp Finally, the Sun kvm error reporting semantics are poorly defined. The library can be configured either to print errors to .Dv stderr automatically, or to print no error messages at all. In the latter case, the nature of the error cannot be determined. To overcome this, the .Bx interface includes a routine, .Xr kvm_geterr 3 , to return (not print out) the error message corresponding to the most recent error condition on the given descriptor. +.Sh CROSS DEBUGGING +The +.Nm +library supports inspection of crash dumps from non-native kernels. +Only a limited subset of the kvm interface is supported for these dumps. +To inspect a crash dump of a non-native kernel, +the caller must provide a +.Fa resolver +function when opening a descriptor via +.Fn kvm_open2 . +In addition, +the kvm interface defines an integer type +.Pq Vt kvaddr_t +that is large enough to hold all valid addresses of all supported +architectures. +The interface also defines a new namelist structure type +.Pq Vt "struct kvm_nlist" +for use with +.Fn kvm_nlist2 . +To avoid address truncation issues, +the caller should use +.Fn kvm_nlist2 +and +.Fn kvm_read2 +in place of +.Fn kvm_nlist +and +.Fn kvm_read , +respectively. +Finally, only a limited subset of operations are supported for non-native +crash dumps: +.Fn kvm_close , +.Fn kvm_geterr +.Fn kvm_open2 , +.Fn kvm_native , +.Fn kvm_nlist2 , +and +.Fn kvm_read2 . .Sh SEE ALSO .Xr kvm_close 3 , .Xr kvm_getargv 3 , .Xr kvm_getenvv 3 , .Xr kvm_geterr 3 , .Xr kvm_getfiles 3 , .Xr kvm_getloadavg 3 , .Xr kvm_getprocs 3 , .Xr kvm_getswapinfo 3 , +.Xr kvm_native 3 , .Xr kvm_nlist 3 , +.Xr kvm_nlist2 3 , .Xr kvm_open 3 , +.Xr kvm_open2 3 , .Xr kvm_openfiles 3 , .Xr kvm_read 3 , +.Xr kvm_read2 3 , .Xr kvm_write 3 , .Xr sysctl 3 , .Xr kmem 4 , .Xr mem 4 Index: head/lib/libkvm/kvm.c =================================================================== --- head/lib/libkvm/kvm.c (revision 291405) +++ head/lib/libkvm/kvm.c (revision 291406) @@ -1,618 +1,897 @@ /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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. */ #include __FBSDID("$FreeBSD$"); #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; #endif #endif /* LIBC_SCCS and not lint */ #include +#include #define _WANT_VNET #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 "kvm_private.h" -#ifndef CROSS_LIBKVM +SET_DECLARE(kvm_arch, struct kvm_arch); /* from src/lib/libc/gen/nlist.c */ int __fdnlist(int, struct nlist *); -#define kvm_fdnlist __fdnlist - -#else - -#include - static int -kvm_fdnlist(int fd, struct nlist *list) +kvm_fdnlist(kvm_t *kd, struct kvm_nlist *list) { - psaddr_t addr; - ps_err_e pserr; - int nfail; + kvaddr_t addr; + int error, nfail; + if (kd->resolve_symbol == NULL) { + struct nlist *nl; + int count, i; + + for (count = 0; list[count].n_name != NULL && + list[count].n_name[0] != '\0'; count++) + ; + nl = calloc(count + 1, sizeof(*nl)); + for (i = 0; i < count; i++) + nl[i].n_name = list[i].n_name; + nfail = __fdnlist(kd->nlfd, nl); + for (i = 0; i < count; i++) { + list[i].n_type = nl[i].n_type; + list[i].n_value = nl[i].n_value; + } + free(nl); + return (nfail); + } + nfail = 0; while (list->n_name != NULL && list->n_name[0] != '\0') { - list->n_other = 0; - list->n_desc = 0; - pserr = ps_pglobal_lookup(NULL, NULL, list->n_name, &addr); - if (pserr != PS_OK) { + error = kd->resolve_symbol(list->n_name, &addr); + if (error != 0) { nfail++; list->n_value = 0; list->n_type = 0; } else { list->n_value = addr; list->n_type = N_DATA | N_EXT; } list++; } return (nfail); } -#endif /* CROSS_LIBKVM */ - char * kvm_geterr(kvm_t *kd) { return (kd->errbuf); } #include /* * Report an error using printf style arguments. "program" is kd->program * on hard errors, and 0 on soft errors, so that under sun error emulation, * only hard errors are printed out (otherwise, programs like gdb will * generate tons of error messages when trying to access bogus pointers). */ void _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (program != NULL) { (void)fprintf(stderr, "%s: ", program); (void)vfprintf(stderr, fmt, ap); (void)fputc('\n', stderr); } else (void)vsnprintf(kd->errbuf, sizeof(kd->errbuf), fmt, ap); va_end(ap); } void _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) { va_list ap; int n; va_start(ap, fmt); if (program != NULL) { (void)fprintf(stderr, "%s: ", program); (void)vfprintf(stderr, fmt, ap); (void)fprintf(stderr, ": %s\n", strerror(errno)); } else { char *cp = kd->errbuf; (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap); n = strlen(cp); (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", strerror(errno)); } va_end(ap); } void * _kvm_malloc(kvm_t *kd, size_t n) { void *p; if ((p = calloc(n, sizeof(char))) == NULL) _kvm_err(kd, kd->program, "can't allocate %zu bytes: %s", n, strerror(errno)); return (p); } +static int +_kvm_read_kernel_ehdr(kvm_t *kd) +{ + Elf *elf; + + if (elf_version(EV_CURRENT) == EV_NONE) { + _kvm_err(kd, kd->program, "Unsupported libelf"); + return (-1); + } + elf = elf_begin(kd->nlfd, ELF_C_READ, NULL); + if (elf == NULL) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + return (-1); + } + if (elf_kind(elf) != ELF_K_ELF) { + _kvm_err(kd, kd->program, "kernel is not an ELF file"); + return (-1); + } + if (gelf_getehdr(elf, &kd->nlehdr) == NULL) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + elf_end(elf); + return (-1); + } + elf_end(elf); + + switch (kd->nlehdr.e_ident[EI_DATA]) { + case ELFDATA2LSB: + case ELFDATA2MSB: + return (0); + default: + _kvm_err(kd, kd->program, + "unsupported ELF data encoding for kernel"); + return (-1); + } +} + +int +_kvm_probe_elf_kernel(kvm_t *kd, int class, int machine) +{ + + return (kd->nlehdr.e_ident[EI_CLASS] == class && + kd->nlehdr.e_type == ET_EXEC && + kd->nlehdr.e_machine == machine); +} + +int +_kvm_is_minidump(kvm_t *kd) +{ + char minihdr[8]; + + if (kd->rawdump) + return (0); + if (pread(kd->pmfd, &minihdr, 8, 0) == 8 && + memcmp(&minihdr, "minidump", 8) == 0) + return (1); + return (0); +} + +/* + * The powerpc backend has a hack to strip a leading kerneldump + * header from the core before treating it as an ELF header. + * + * We can add that here if we can get a change to libelf to support + * an inital offset into the file. Alternatively we could patch + * savecore to extract cores from a regular file instead. + */ +int +_kvm_read_core_phdrs(kvm_t *kd, size_t *phnump, GElf_Phdr **phdrp) +{ + GElf_Ehdr ehdr; + GElf_Phdr *phdr; + Elf *elf; + size_t i, phnum; + + elf = elf_begin(kd->pmfd, ELF_C_READ, NULL); + if (elf == NULL) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + return (-1); + } + if (elf_kind(elf) != ELF_K_ELF) { + _kvm_err(kd, kd->program, "invalid core"); + goto bad; + } + if (gelf_getclass(elf) != kd->nlehdr.e_ident[EI_CLASS]) { + _kvm_err(kd, kd->program, "invalid core"); + goto bad; + } + if (gelf_getehdr(elf, &ehdr) == NULL) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + goto bad; + } + if (ehdr.e_type != ET_CORE) { + _kvm_err(kd, kd->program, "invalid core"); + goto bad; + } + if (ehdr.e_machine != kd->nlehdr.e_machine) { + _kvm_err(kd, kd->program, "invalid core"); + goto bad; + } + + if (elf_getphdrnum(elf, &phnum) == -1) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + goto bad; + } + + phdr = calloc(phnum, sizeof(*phdr)); + if (phdr == NULL) { + _kvm_err(kd, kd->program, "failed to allocate phdrs"); + goto bad; + } + + for (i = 0; i < phnum; i++) { + if (gelf_getphdr(elf, i, &phdr[i]) == NULL) { + _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); + goto bad; + } + } + elf_end(elf); + *phnump = phnum; + *phdrp = phdr; + return (0); + +bad: + elf_end(elf); + return (-1); +} + +static void +_kvm_hpt_insert(struct hpt *hpt, uint64_t pa, off_t off) +{ + struct hpte *hpte; + uint32_t fnv = FNV1_32_INIT; + + fnv = fnv_32_buf(&pa, sizeof(pa), fnv); + fnv &= (HPT_SIZE - 1); + hpte = malloc(sizeof(*hpte)); + hpte->pa = pa; + hpte->off = off; + hpte->next = hpt->hpt_head[fnv]; + hpt->hpt_head[fnv] = hpte; +} + +void +_kvm_hpt_init(kvm_t *kd, struct hpt *hpt, void *base, size_t len, off_t off, + int page_size, int word_size) +{ + uint64_t bits, idx, pa; + uint64_t *base64; + uint32_t *base32; + + base64 = base; + base32 = base; + for (idx = 0; idx < len / word_size; idx++) { + if (word_size == sizeof(uint64_t)) + bits = _kvm64toh(kd, base64[idx]); + else + bits = _kvm32toh(kd, base32[idx]); + pa = idx * word_size * NBBY * page_size; + for (; bits != 0; bits >>= 1, pa += page_size) { + if ((bits & 1) == 0) + continue; + _kvm_hpt_insert(hpt, pa, off); + off += page_size; + } + } +} + +off_t +_kvm_hpt_find(struct hpt *hpt, uint64_t pa) +{ + struct hpte *hpte; + uint32_t fnv = FNV1_32_INIT; + + fnv = fnv_32_buf(&pa, sizeof(pa), fnv); + fnv &= (HPT_SIZE - 1); + for (hpte = hpt->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { + if (pa == hpte->pa) + return (hpte->off); + } + return (-1); +} + +void +_kvm_hpt_free(struct hpt *hpt) +{ + struct hpte *hpte, *next; + int i; + + for (i = 0; i < HPT_SIZE; i++) { + for (hpte = hpt->hpt_head[i]; hpte != NULL; hpte = next) { + next = hpte->next; + free(hpte); + } + } +} + static kvm_t * _kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout) { + struct kvm_arch **parch; struct stat st; kd->vmfd = -1; kd->pmfd = -1; kd->nlfd = -1; kd->vmst = 0; kd->procbase = 0; kd->argspc = 0; kd->argv = 0; if (uf == 0) uf = getbootfile(); else if (strlen(uf) >= MAXPATHLEN) { _kvm_err(kd, kd->program, "exec file name too long"); goto failed; } if (flag & ~O_RDWR) { _kvm_err(kd, kd->program, "bad flags arg"); goto failed; } if (mf == 0) mf = _PATH_MEM; if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 0)) < 0) { _kvm_syserr(kd, kd->program, "%s", mf); goto failed; } if (fstat(kd->pmfd, &st) < 0) { _kvm_syserr(kd, kd->program, "%s", mf); goto failed; } if (S_ISREG(st.st_mode) && st.st_size <= 0) { errno = EINVAL; _kvm_syserr(kd, kd->program, "empty file"); goto failed; } if (S_ISCHR(st.st_mode)) { /* * If this is a character special device, then check that * it's /dev/mem. If so, open kmem too. (Maybe we should * make it work for either /dev/mem or /dev/kmem -- in either * case you're working with a live kernel.) */ if (strcmp(mf, _PATH_DEVNULL) == 0) { kd->vmfd = open(_PATH_DEVNULL, O_RDONLY | O_CLOEXEC); return (kd); } else if (strcmp(mf, _PATH_MEM) == 0) { if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC)) < 0) { _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); goto failed; } return (kd); } } /* * This is a crash dump. - * Initialize the virtual address translation machinery, - * but first setup the namelist fd. + * Open the namelist fd and determine the architecture. */ if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) { _kvm_syserr(kd, kd->program, "%s", uf); goto failed; } + if (_kvm_read_kernel_ehdr(kd) < 0) + goto failed; if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0) kd->rawdump = 1; - if (_kvm_initvtop(kd) < 0) + SET_FOREACH(parch, kvm_arch) { + if ((*parch)->ka_probe(kd)) { + kd->arch = *parch; + break; + } + } + if (kd->arch == NULL) { + _kvm_err(kd, kd->program, "unsupported architecture"); goto failed; + } + + /* + * Non-native kernels require a symbol resolver. + */ + if (!kd->arch->ka_native(kd) && kd->resolve_symbol == NULL) { + _kvm_err(kd, kd->program, + "non-native kernel requires a symbol resolver"); + goto failed; + } + + /* + * Initialize the virtual address translation machinery. + */ + if (kd->arch->ka_initvtop(kd) < 0) + goto failed; return (kd); failed: /* * Copy out the error if doing sane error semantics. */ if (errout != 0) strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); (void)kvm_close(kd); return (0); } kvm_t * kvm_openfiles(const char *uf, const char *mf, const char *sf __unused, int flag, char *errout) { kvm_t *kd; if ((kd = calloc(1, sizeof(*kd))) == NULL) { (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); return (0); } - kd->program = 0; return (_kvm_open(kd, uf, mf, flag, errout)); } kvm_t * kvm_open(const char *uf, const char *mf, const char *sf __unused, int flag, const char *errstr) { kvm_t *kd; if ((kd = calloc(1, sizeof(*kd))) == NULL) { if (errstr != NULL) (void)fprintf(stderr, "%s: %s\n", errstr, strerror(errno)); return (0); } kd->program = errstr; return (_kvm_open(kd, uf, mf, flag, NULL)); } +kvm_t * +kvm_open2(const char *uf, const char *mf, int flag, char *errout, + int (*resolver)(const char *, kvaddr_t *)) +{ + kvm_t *kd; + + if ((kd = calloc(1, sizeof(*kd))) == NULL) { + (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); + return (0); + } + kd->resolve_symbol = resolver; + return (_kvm_open(kd, uf, mf, flag, errout)); +} + int kvm_close(kvm_t *kd) { int error = 0; + if (kd->vmst != NULL) + kd->arch->ka_freevtop(kd); if (kd->pmfd >= 0) error |= close(kd->pmfd); if (kd->vmfd >= 0) error |= close(kd->vmfd); if (kd->nlfd >= 0) error |= close(kd->nlfd); - if (kd->vmst) - _kvm_freevtop(kd); if (kd->procbase != 0) free((void *)kd->procbase); if (kd->argbuf != 0) free((void *) kd->argbuf); if (kd->argspc != 0) free((void *) kd->argspc); if (kd->argv != 0) free((void *)kd->argv); free((void *)kd); return (0); } /* * Walk the list of unresolved symbols, generate a new list and prefix the * symbol names, try again, and merge back what we could resolve. */ static int -kvm_fdnlist_prefix(kvm_t *kd, struct nlist *nl, int missing, const char *prefix, - uintptr_t (*validate_fn)(kvm_t *, uintptr_t)) +kvm_fdnlist_prefix(kvm_t *kd, struct kvm_nlist *nl, int missing, + const char *prefix, kvaddr_t (*validate_fn)(kvm_t *, kvaddr_t)) { - struct nlist *n, *np, *p; + struct kvm_nlist *n, *np, *p; char *cp, *ce; const char *ccp; size_t len; int slen, unresolved; /* * Calculate the space we need to malloc for nlist and names. * We are going to store the name twice for later lookups: once * with the prefix and once the unmodified name delmited by \0. */ len = 0; unresolved = 0; for (p = nl; p->n_name && p->n_name[0]; ++p) { if (p->n_type != N_UNDF) continue; - len += sizeof(struct nlist) + strlen(prefix) + + len += sizeof(struct kvm_nlist) + strlen(prefix) + 2 * (strlen(p->n_name) + 1); unresolved++; } if (unresolved == 0) return (unresolved); /* Add space for the terminating nlist entry. */ - len += sizeof(struct nlist); + len += sizeof(struct kvm_nlist); unresolved++; /* Alloc one chunk for (nlist, [names]) and setup pointers. */ n = np = malloc(len); bzero(n, len); if (n == NULL) return (missing); cp = ce = (char *)np; - cp += unresolved * sizeof(struct nlist); + cp += unresolved * sizeof(struct kvm_nlist); ce += len; /* Generate shortened nlist with special prefix. */ unresolved = 0; for (p = nl; p->n_name && p->n_name[0]; ++p) { if (p->n_type != N_UNDF) continue; - bcopy(p, np, sizeof(struct nlist)); + *np = *p; /* Save the new\0orig. name so we can later match it again. */ slen = snprintf(cp, ce - cp, "%s%s%c%s", prefix, (prefix[0] != '\0' && p->n_name[0] == '_') ? (p->n_name + 1) : p->n_name, '\0', p->n_name); if (slen < 0 || slen >= ce - cp) continue; np->n_name = cp; cp += slen + 1; np++; unresolved++; } /* Do lookup on the reduced list. */ np = n; - unresolved = kvm_fdnlist(kd->nlfd, np); + unresolved = kvm_fdnlist(kd, np); /* Check if we could resolve further symbols and update the list. */ if (unresolved >= 0 && unresolved < missing) { /* Find the first freshly resolved entry. */ for (; np->n_name && np->n_name[0]; np++) if (np->n_type != N_UNDF) break; /* * The lists are both in the same order, * so we can walk them in parallel. */ for (p = nl; np->n_name && np->n_name[0] && p->n_name && p->n_name[0]; ++p) { if (p->n_type != N_UNDF) continue; /* Skip expanded name and compare to orig. one. */ ccp = np->n_name + strlen(np->n_name) + 1; if (strcmp(ccp, p->n_name) != 0) continue; /* Update nlist with new, translated results. */ p->n_type = np->n_type; - p->n_other = np->n_other; - p->n_desc = np->n_desc; if (validate_fn) p->n_value = (*validate_fn)(kd, np->n_value); else p->n_value = np->n_value; missing--; /* Find next freshly resolved entry. */ for (np++; np->n_name && np->n_name[0]; np++) if (np->n_type != N_UNDF) break; } } /* We could assert missing = unresolved here. */ free(n); return (unresolved); } int -_kvm_nlist(kvm_t *kd, struct nlist *nl, int initialize) +_kvm_nlist(kvm_t *kd, struct kvm_nlist *nl, int initialize) { - struct nlist *p; + struct kvm_nlist *p; int nvalid; struct kld_sym_lookup lookup; int error; const char *prefix = ""; char symname[1024]; /* XXX-BZ symbol name length limit? */ int tried_vnet, tried_dpcpu; /* * If we can't use the kld symbol lookup, revert to the * slow library call. */ if (!ISALIVE(kd)) { - error = kvm_fdnlist(kd->nlfd, nl); + error = kvm_fdnlist(kd, nl); if (error <= 0) /* Hard error or success. */ return (error); if (_kvm_vnet_initialized(kd, initialize)) error = kvm_fdnlist_prefix(kd, nl, error, VNET_SYMPREFIX, _kvm_vnet_validaddr); if (error > 0 && _kvm_dpcpu_initialized(kd, initialize)) error = kvm_fdnlist_prefix(kd, nl, error, DPCPU_SYMPREFIX, _kvm_dpcpu_validaddr); return (error); } /* * We can use the kld lookup syscall. Go through each nlist entry * and look it up with a kldsym(2) syscall. */ nvalid = 0; tried_vnet = 0; tried_dpcpu = 0; again: for (p = nl; p->n_name && p->n_name[0]; ++p) { if (p->n_type != N_UNDF) continue; lookup.version = sizeof(lookup); lookup.symvalue = 0; lookup.symsize = 0; error = snprintf(symname, sizeof(symname), "%s%s", prefix, (prefix[0] != '\0' && p->n_name[0] == '_') ? (p->n_name + 1) : p->n_name); if (error < 0 || error >= (int)sizeof(symname)) continue; lookup.symname = symname; if (lookup.symname[0] == '_') lookup.symname++; if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { p->n_type = N_TEXT; - p->n_other = 0; - p->n_desc = 0; if (_kvm_vnet_initialized(kd, initialize) && strcmp(prefix, VNET_SYMPREFIX) == 0) p->n_value = _kvm_vnet_validaddr(kd, lookup.symvalue); else if (_kvm_dpcpu_initialized(kd, initialize) && strcmp(prefix, DPCPU_SYMPREFIX) == 0) p->n_value = _kvm_dpcpu_validaddr(kd, lookup.symvalue); else p->n_value = lookup.symvalue; ++nvalid; /* lookup.symsize */ } } /* * Check the number of entries that weren't found. If they exist, * try again with a prefix for virtualized or DPCPU symbol names. */ error = ((p - nl) - nvalid); if (error && _kvm_vnet_initialized(kd, initialize) && !tried_vnet) { tried_vnet = 1; prefix = VNET_SYMPREFIX; goto again; } if (error && _kvm_dpcpu_initialized(kd, initialize) && !tried_dpcpu) { tried_dpcpu = 1; prefix = DPCPU_SYMPREFIX; goto again; } /* * Return the number of entries that weren't found. If they exist, * also fill internal error buffer. */ error = ((p - nl) - nvalid); if (error) _kvm_syserr(kd, kd->program, "kvm_nlist"); return (error); } int -kvm_nlist(kvm_t *kd, struct nlist *nl) +kvm_nlist2(kvm_t *kd, struct kvm_nlist *nl) { /* * If called via the public interface, permit intialization of * further virtualized modules on demand. */ return (_kvm_nlist(kd, nl, 1)); } +int +kvm_nlist(kvm_t *kd, struct nlist *nl) +{ + struct kvm_nlist *kl; + int count, i, nfail; + + /* + * Avoid reporting truncated addresses by failing for non-native + * cores. + */ + if (!kvm_native(kd)) { + _kvm_err(kd, kd->program, "kvm_nlist of non-native vmcore"); + return (-1); + } + + for (count = 0; nl[count].n_name != NULL && nl[count].n_name[0] != '\0'; + count++) + ; + if (count == 0) + return (0); + kl = calloc(count + 1, sizeof(*kl)); + for (i = 0; i < count; i++) + kl[i].n_name = nl[i].n_name; + nfail = kvm_nlist2(kd, kl); + for (i = 0; i < count; i++) { + nl[i].n_type = kl[i].n_type; + nl[i].n_other = 0; + nl[i].n_desc = 0; + nl[i].n_value = kl[i].n_value; + } + return (nfail); +} + ssize_t kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len) { + + return (kvm_read2(kd, kva, buf, len)); +} + +ssize_t +kvm_read2(kvm_t *kd, kvaddr_t kva, void *buf, size_t len) +{ int cc; ssize_t cr; off_t pa; char *cp; if (ISALIVE(kd)) { /* * We're using /dev/kmem. Just read straight from the * device and let the active kernel do the address translation. */ errno = 0; if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { - _kvm_err(kd, 0, "invalid address (%lx)", kva); + _kvm_err(kd, 0, "invalid address (0x%jx)", + (uintmax_t)kva); return (-1); } cr = read(kd->vmfd, buf, len); if (cr < 0) { _kvm_syserr(kd, 0, "kvm_read"); return (-1); } else if (cr < (ssize_t)len) _kvm_err(kd, kd->program, "short read"); return (cr); } cp = buf; while (len > 0) { - cc = _kvm_kvatop(kd, kva, &pa); + cc = kd->arch->ka_kvatop(kd, kva, &pa); if (cc == 0) return (-1); if (cc > (ssize_t)len) cc = len; errno = 0; if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) { _kvm_syserr(kd, 0, _PATH_MEM); break; } cr = read(kd->pmfd, cp, cc); if (cr < 0) { _kvm_syserr(kd, kd->program, "kvm_read"); break; } /* - * If kvm_kvatop returns a bogus value or our core file is + * If ka_kvatop returns a bogus value or our core file is * truncated, we might wind up seeking beyond the end of the * core file in which case the read will return 0 (EOF). */ if (cr == 0) break; cp += cr; kva += cr; len -= cr; } return (cp - (char *)buf); } ssize_t kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) { int cc; if (ISALIVE(kd)) { /* * Just like kvm_read, only we write. */ errno = 0; if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { _kvm_err(kd, 0, "invalid address (%lx)", kva); return (-1); } cc = write(kd->vmfd, buf, len); if (cc < 0) { _kvm_syserr(kd, 0, "kvm_write"); return (-1); } else if ((size_t)cc < len) _kvm_err(kd, kd->program, "short write"); return (cc); } else { _kvm_err(kd, kd->program, "kvm_write not implemented for dead kernels"); return (-1); } /* NOTREACHED */ +} + +int +kvm_native(kvm_t *kd) +{ + + if (ISALIVE(kd)) + return (1); + return (kd->arch->ka_native(kd)); } Index: head/lib/libkvm/kvm.h =================================================================== --- head/lib/libkvm/kvm.h (revision 291405) +++ head/lib/libkvm/kvm.h (revision 291406) @@ -1,96 +1,110 @@ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. 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. * * @(#)kvm.h 8.1 (Berkeley) 6/2/93 * $FreeBSD$ */ #ifndef _KVM_H_ #define _KVM_H_ #include #include #include /* Default version symbol. */ #define VRS_SYM "_version" #define VRS_KEY "VERSION" #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #define _SSIZE_T_DECLARED #endif +typedef uint64_t kvaddr_t; /* An address in a target image. */ + +struct kvm_nlist { + const char *n_name; + unsigned char n_type; + kvaddr_t n_value; +}; + typedef struct __kvm kvm_t; struct kinfo_proc; struct proc; struct kvm_swap { char ksw_devname[32]; int ksw_used; int ksw_total; int ksw_flags; int ksw_reserved1; int ksw_reserved2; }; #define SWIF_DEV_PREFIX 0x0002 __BEGIN_DECLS int kvm_close(kvm_t *); int kvm_dpcpu_setcpu(kvm_t *, unsigned int); char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int); int kvm_getcptime(kvm_t *, long *); char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int); char *kvm_geterr(kvm_t *); char *kvm_getfiles(kvm_t *, int, int, int *); int kvm_getloadavg(kvm_t *, double [], int); int kvm_getmaxcpu(kvm_t *); int kvm_getncpus(kvm_t *); void *kvm_getpcpu(kvm_t *, int); uint64_t kvm_counter_u64_fetch(kvm_t *, u_long); struct kinfo_proc * kvm_getprocs(kvm_t *, int, int, int *); int kvm_getswapinfo(kvm_t *, struct kvm_swap *, int, int); +int kvm_native(kvm_t *); int kvm_nlist(kvm_t *, struct nlist *); +int kvm_nlist2(kvm_t *, struct kvm_nlist *); kvm_t *kvm_open (const char *, const char *, const char *, int, const char *); kvm_t *kvm_openfiles (const char *, const char *, const char *, int, char *); +kvm_t *kvm_open2 + (const char *, const char *, int, char *, + int (*)(const char *, kvaddr_t *)); ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t); ssize_t kvm_read_zpcpu(kvm_t *, unsigned long, void *, size_t, int); +ssize_t kvm_read2(kvm_t *, kvaddr_t, void *, size_t); ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t); __END_DECLS #endif /* !_KVM_H_ */ Index: head/lib/libkvm/kvm_aarch64.h =================================================================== --- head/lib/libkvm/kvm_aarch64.h (nonexistent) +++ head/lib/libkvm/kvm_aarch64.h (revision 291406) @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_AARCH64_H__ +#define __KVM_AARCH64_H__ + +#ifdef __aarch64__ +#include +#endif + +typedef uint64_t aarch64_physaddr_t; +typedef uint64_t aarch64_pte_t; + +#define AARCH64_PAGE_SHIFT 12 +#define AARCH64_PAGE_SIZE (1 << AARCH64_PAGE_SHIFT) +#define AARCH64_PAGE_MASK (AARCH64_PAGE_SIZE - 1) + +#define AARCH64_ATTR_MASK 0xfff0000000000fff + +#define AARCH64_ATTR_DESCR_MASK 3 + +#define AARCH64_L3_SHIFT 12 +#define AARCH64_L3_PAGE 0x3 + +#ifdef __aarch64__ +_Static_assert(PAGE_SHIFT == AARCH64_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == AARCH64_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == AARCH64_PAGE_MASK, "PAGE_MASK mismatch"); +_Static_assert(ATTR_MASK == AARCH64_ATTR_MASK, "ATTR_MASK mismatch"); +_Static_assert(ATTR_DESCR_MASK == AARCH64_ATTR_DESCR_MASK, + "ATTR_DESCR_MASK mismatch"); +_Static_assert(L3_SHIFT == AARCH64_L3_SHIFT, "L3_SHIFT mismatch"); +_Static_assert(L3_PAGE == AARCH64_L3_PAGE, "L3_PAGE mismatch"); +#endif + +#endif /* !__KVM_AARCH64_H__ */ Property changes on: head/lib/libkvm/kvm_aarch64.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_amd64.c =================================================================== --- head/lib/libkvm/kvm_amd64.c (revision 291405) +++ head/lib/libkvm/kvm_amd64.c (revision 291406) @@ -1,356 +1,332 @@ /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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. */ #include __FBSDID("$FreeBSD$"); #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* LIBC_SCCS and not lint */ /* * AMD64 machine dependent routines for kvm. Hopefully, the forthcoming * vm code will one day obsolete this module. */ #include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include -#include -#include - -#include - #include #include "kvm_private.h" +#include "kvm_amd64.h" -#ifndef btop -#define btop(x) (amd64_btop(x)) -#define ptob(x) (amd64_ptob(x)) -#endif - -/* minidump must be the first item! */ struct vmstate { - int minidump; /* 1 = minidump mode */ - void *mmapbase; - size_t mmapsize; - pml4_entry_t *PML4; + size_t phnum; + GElf_Phdr *phdr; + amd64_pml4e_t *PML4; }; /* - * Map the ELF headers into the process' address space. We do this in two - * steps: first the ELF header itself and using that information the whole - * set of headers. - */ -static int -_kvm_maphdrs(kvm_t *kd, size_t sz) -{ - struct vmstate *vm = kd->vmst; - - /* munmap() previous mmap(). */ - if (vm->mmapbase != NULL) { - munmap(vm->mmapbase, vm->mmapsize); - vm->mmapbase = NULL; - } - - vm->mmapsize = sz; - vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); - if (vm->mmapbase == MAP_FAILED) { - _kvm_err(kd, kd->program, "cannot mmap corefile"); - return (-1); - } - return (0); -} - -/* * Translate a physical memory address to a file-offset in the crash-dump. */ static size_t _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs) { - Elf_Ehdr *e = kd->vmst->mmapbase; - Elf_Phdr *p; - int n; + struct vmstate *vm = kd->vmst; + GElf_Phdr *p; + size_t n; if (kd->rawdump) { *ofs = pa; - return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); + return (AMD64_PAGE_SIZE - (pa & AMD64_PAGE_MASK)); } - p = (Elf_Phdr*)((char*)e + e->e_phoff); - n = e->e_phnum; + p = vm->phdr; + n = vm->phnum; while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) p++, n--; if (n == 0) return (0); *ofs = (pa - p->p_paddr) + p->p_offset; - return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); + return (AMD64_PAGE_SIZE - (pa & AMD64_PAGE_MASK)); } -void -_kvm_freevtop(kvm_t *kd) +static void +_amd64_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (kd->vmst->minidump) - return (_kvm_minidump_freevtop(kd)); - if (vm->mmapbase != NULL) - munmap(vm->mmapbase, vm->mmapsize); if (vm->PML4) free(vm->PML4); + free(vm->phdr); free(vm); kd->vmst = NULL; } -int -_kvm_initvtop(kvm_t *kd) +static int +_amd64_probe(kvm_t *kd) { - struct nlist nl[2]; - u_long pa; - u_long kernbase; - pml4_entry_t *PML4; - Elf_Ehdr *ehdr; - size_t hdrsz; - char minihdr[8]; - if (!kd->rawdump && pread(kd->pmfd, &minihdr, 8, 0) == 8) - if (memcmp(&minihdr, "minidump", 8) == 0) - return (_kvm_minidump_initvtop(kd)); + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_X86_64) && + !_kvm_is_minidump(kd)); +} +static int +_amd64_initvtop(kvm_t *kd) +{ + struct kvm_nlist nl[2]; + amd64_physaddr_t pa; + kvaddr_t kernbase; + amd64_pml4e_t *PML4; + kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); if (kd->vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst->PML4 = 0; if (kd->rawdump == 0) { - if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1) + if (_kvm_read_core_phdrs(kd, &kd->vmst->phnum, + &kd->vmst->phdr) == -1) return (-1); - - ehdr = kd->vmst->mmapbase; - hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; - if (_kvm_maphdrs(kd, hdrsz) == -1) - return (-1); } nl[0].n_name = "kernbase"; nl[1].n_name = 0; - if (kvm_nlist(kd, nl) != 0) { + if (kvm_nlist2(kd, nl) != 0) { _kvm_err(kd, kd->program, "bad namelist - no kernbase"); return (-1); } kernbase = nl[0].n_value; nl[0].n_name = "KPML4phys"; nl[1].n_name = 0; - if (kvm_nlist(kd, nl) != 0) { + if (kvm_nlist2(kd, nl) != 0) { _kvm_err(kd, kd->program, "bad namelist - no KPML4phys"); return (-1); } - if (kvm_read(kd, (nl[0].n_value - kernbase), &pa, sizeof(pa)) != + if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, sizeof(pa)) != sizeof(pa)) { _kvm_err(kd, kd->program, "cannot read KPML4phys"); return (-1); } - PML4 = _kvm_malloc(kd, PAGE_SIZE); - if (kvm_read(kd, pa, PML4, PAGE_SIZE) != PAGE_SIZE) { + pa = le64toh(pa); + PML4 = _kvm_malloc(kd, AMD64_PAGE_SIZE); + if (kvm_read2(kd, pa, PML4, AMD64_PAGE_SIZE) != AMD64_PAGE_SIZE) { _kvm_err(kd, kd->program, "cannot read KPML4phys"); return (-1); } kd->vmst->PML4 = PML4; return (0); } static int -_kvm_vatop(kvm_t *kd, u_long va, off_t *pa) +_amd64_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - u_long offset; - u_long pdpe_pa; - u_long pde_pa; - u_long pte_pa; - pml4_entry_t pml4e; - pdp_entry_t pdpe; - pd_entry_t pde; - pt_entry_t pte; - u_long pml4eindex; - u_long pdpeindex; - u_long pdeindex; - u_long pteindex; - u_long a; + amd64_physaddr_t offset; + amd64_physaddr_t pdpe_pa; + amd64_physaddr_t pde_pa; + amd64_physaddr_t pte_pa; + amd64_pml4e_t pml4e; + amd64_pdpe_t pdpe; + amd64_pde_t pde; + amd64_pte_t pte; + kvaddr_t pml4eindex; + kvaddr_t pdpeindex; + kvaddr_t pdeindex; + kvaddr_t pteindex; + amd64_physaddr_t a; off_t ofs; size_t s; vm = kd->vmst; - offset = va & (PAGE_SIZE - 1); + offset = va & AMD64_PAGE_MASK; /* * If we are initializing (kernel page table descriptor pointer * not yet set) then return pa == va to avoid infinite recursion. */ if (vm->PML4 == 0) { s = _kvm_pa2off(kd, va, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop: bootstrap data not in dump"); + "_amd64_vatop: bootstrap data not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); } - pml4eindex = (va >> PML4SHIFT) & (NPML4EPG - 1); - pml4e = vm->PML4[pml4eindex]; - if (((u_long)pml4e & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pml4e not valid"); + pml4eindex = (va >> AMD64_PML4SHIFT) & (AMD64_NPML4EPG - 1); + pml4e = le64toh(vm->PML4[pml4eindex]); + if ((pml4e & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, "_amd64_vatop: pml4e not valid"); goto invalid; } - pdpeindex = (va >> PDPSHIFT) & (NPDPEPG-1); - pdpe_pa = ((u_long)pml4e & PG_FRAME) + - (pdpeindex * sizeof(pdp_entry_t)); + pdpeindex = (va >> AMD64_PDPSHIFT) & (AMD64_NPDPEPG - 1); + pdpe_pa = (pml4e & AMD64_PG_FRAME) + (pdpeindex * sizeof(amd64_pdpe_t)); s = _kvm_pa2off(kd, pdpe_pa, &ofs); - if (s < sizeof pdpe) { - _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found"); + if (s < sizeof(pdpe)) { + _kvm_err(kd, kd->program, "_amd64_vatop: pdpe_pa not found"); goto invalid; } - if (lseek(kd->pmfd, ofs, 0) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek pdpe_pa"); + if (pread(kd->pmfd, &pdpe, sizeof(pdpe), ofs) != sizeof(pdpe)) { + _kvm_syserr(kd, kd->program, "_amd64_vatop: read pdpe"); goto invalid; } - if (read(kd->pmfd, &pdpe, sizeof pdpe) != sizeof pdpe) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: read pdpe"); + pdpe = le64toh(pdpe); + if ((pdpe & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, "_amd64_vatop: pdpe not valid"); goto invalid; } - if (((u_long)pdpe & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pdpe not valid"); - goto invalid; + + if (pdpe & AMD64_PG_PS) { + /* + * No next-level page table; pdpe describes one 1GB page. + */ + a = (pde & AMD64_PG_1GB_FRAME) + (va & AMD64_PDPMASK); + s = _kvm_pa2off(kd, a, pa); + if (s == 0) { + _kvm_err(kd, kd->program, + "_amd64_vatop: 1GB page address not in dump"); + goto invalid; + } else + return (AMD64_NBPDP - (va & AMD64_PDPMASK)); } - pdeindex = (va >> PDRSHIFT) & (NPDEPG-1); - pde_pa = ((u_long)pdpe & PG_FRAME) + (pdeindex * sizeof(pd_entry_t)); + pdeindex = (va >> AMD64_PDRSHIFT) & (AMD64_NPDEPG - 1); + pde_pa = (pdpe & AMD64_PG_FRAME) + (pdeindex * sizeof(amd64_pde_t)); s = _kvm_pa2off(kd, pde_pa, &ofs); - if (s < sizeof pde) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: pde_pa not found"); + if (s < sizeof(pde)) { + _kvm_syserr(kd, kd->program, "_amd64_vatop: pde_pa not found"); goto invalid; } - if (lseek(kd->pmfd, ofs, 0) == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: lseek pde_pa"); + if (pread(kd->pmfd, &pde, sizeof(pde), ofs) != sizeof(pde)) { + _kvm_syserr(kd, kd->program, "_amd64_vatop: read pde"); goto invalid; } - if (read(kd->pmfd, &pde, sizeof pde) != sizeof pde) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: read pde"); + pde = le64toh(pde); + if ((pde & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, "_amd64_vatop: pde not valid"); goto invalid; } - if (((u_long)pde & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); - goto invalid; - } - if ((u_long)pde & PG_PS) { - /* - * No final-level page table; ptd describes one 2MB page. - */ -#define PAGE2M_MASK (NBPDR - 1) -#define PG_FRAME2M (~PAGE2M_MASK) - a = ((u_long)pde & PG_FRAME2M) + (va & PAGE2M_MASK); + if (pde & AMD64_PG_PS) { + /* + * No final-level page table; pde describes one 2MB page. + */ + a = (pde & AMD64_PG_PS_FRAME) + (va & AMD64_PDRMASK); s = _kvm_pa2off(kd, a, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop: 2MB page address not in dump"); + "_amd64_vatop: 2MB page address not in dump"); goto invalid; } else - return (NBPDR - (va & PAGE2M_MASK)); + return (AMD64_NBPDR - (va & AMD64_PDRMASK)); } - pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); - pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t)); + pteindex = (va >> AMD64_PAGE_SHIFT) & (AMD64_NPTEPG - 1); + pte_pa = (pde & AMD64_PG_FRAME) + (pteindex * sizeof(amd64_pte_t)); s = _kvm_pa2off(kd, pte_pa, &ofs); - if (s < sizeof pte) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte_pa not found"); + if (s < sizeof(pte)) { + _kvm_err(kd, kd->program, "_amd64_vatop: pte_pa not found"); goto invalid; } - if (lseek(kd->pmfd, ofs, 0) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); + if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { + _kvm_syserr(kd, kd->program, "_amd64_vatop: read"); goto invalid; } - if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); + if ((pte & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, "_amd64_vatop: pte not valid"); goto invalid; } - if (((u_long)pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); - goto invalid; - } - a = ((u_long)pte & PG_FRAME) + offset; + a = (pte & AMD64_PG_FRAME) + offset; s = _kvm_pa2off(kd, a, pa); if (s == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: address not in dump"); + _kvm_err(kd, kd->program, "_amd64_vatop: address not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_amd64_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { - if (kd->vmst->minidump) - return (_kvm_minidump_kvatop(kd, va, pa)); if (ISALIVE(kd)) { _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); return (0); } - return (_kvm_vatop(kd, va, pa)); + return (_amd64_vatop(kd, va, pa)); } + +int +_amd64_native(kvm_t *kd) +{ + +#ifdef __amd64__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_amd64 = { + .ka_probe = _amd64_probe, + .ka_initvtop = _amd64_initvtop, + .ka_freevtop = _amd64_freevtop, + .ka_kvatop = _amd64_kvatop, + .ka_native = _amd64_native, +}; + +KVM_ARCH(kvm_amd64); Index: head/lib/libkvm/kvm_amd64.h =================================================================== --- head/lib/libkvm/kvm_amd64.h (nonexistent) +++ head/lib/libkvm/kvm_amd64.h (revision 291406) @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_AMD64_H__ +#define __KVM_AMD64_H__ + +#ifdef __amd64__ +#include +#include +#endif + +typedef uint64_t amd64_physaddr_t; +typedef uint64_t amd64_pte_t; +typedef uint64_t amd64_pde_t; +typedef uint64_t amd64_pdpe_t; +typedef uint64_t amd64_pml4e_t; + +#define AMD64_NPTEPG (AMD64_PAGE_SIZE / sizeof(amd64_pte_t)) +#define AMD64_PAGE_SHIFT 12 +#define AMD64_PAGE_SIZE (1 << AMD64_PAGE_SHIFT) +#define AMD64_PAGE_MASK (AMD64_PAGE_SIZE - 1) +#define AMD64_NPDEPG (AMD64_PAGE_SIZE / sizeof(amd64_pde_t)) +#define AMD64_PDRSHIFT 21 +#define AMD64_NBPDR (1 << AMD64_PDRSHIFT) +#define AMD64_PDRMASK (AMD64_NBPDR - 1) +#define AMD64_NPDPEPG (AMD64_PAGE_SIZE / sizeof(amd64_pdpe_t)) +#define AMD64_PDPSHIFT 30 +#define AMD64_NBPDP (1 << AMD64_PDPSHIFT) +#define AMD64_PDPMASK (AMD64_NBPDP - 1) +#define AMD64_NPML4EPG (AMD64_PAGE_SIZE / sizeof(amd64_pml4e_t)) +#define AMD64_PML4SHIFT 39 + +#define AMD64_PG_V 0x001 +#define AMD64_PG_PS 0x080 +#define AMD64_PG_FRAME (0x000ffffffffff000) +#define AMD64_PG_PS_FRAME (0x000fffffffe00000) +#define AMD64_PG_1GB_FRAME (0x000fffffc0000000) + +#ifdef __amd64__ +_Static_assert(NPTEPG == AMD64_NPTEPG, "NPTEPG mismatch"); +_Static_assert(PAGE_SHIFT == AMD64_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == AMD64_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == AMD64_PAGE_MASK, "PAGE_MASK mismatch"); +_Static_assert(NPDEPG == AMD64_NPDEPG, "NPDEPG mismatch"); +_Static_assert(PDRSHIFT == AMD64_PDRSHIFT, "PDRSHIFT mismatch"); +_Static_assert(NBPDR == AMD64_NBPDR, "NBPDR mismatch"); +_Static_assert(PDRMASK == AMD64_PDRMASK, "PDRMASK mismatch"); +_Static_assert(NPDPEPG == AMD64_NPDPEPG, "NPDPEPG mismatch"); +_Static_assert(PDPSHIFT == AMD64_PDPSHIFT, "PDPSHIFT mismatch"); +_Static_assert(NBPDP == AMD64_NBPDP, "NBPDP mismatch"); +_Static_assert(PDPMASK == AMD64_PDPMASK, "PDPMASK mismatch"); +_Static_assert(NPML4EPG == AMD64_NPML4EPG, "NPML4EPG mismatch"); +_Static_assert(PML4SHIFT == AMD64_PML4SHIFT, "PML4SHIFT mismatch"); + +_Static_assert(PG_V == AMD64_PG_V, "PG_V mismatch"); +_Static_assert(PG_PS == AMD64_PG_PS, "PG_PS mismatch"); +_Static_assert(PG_FRAME == AMD64_PG_FRAME, "PG_FRAME mismatch"); +_Static_assert(PG_PS_FRAME == AMD64_PG_PS_FRAME, "PG_PS_FRAME mismatch"); +#endif + +int _amd64_native(kvm_t *); + +#endif /* !__KVM_AMD64_H__ */ Property changes on: head/lib/libkvm/kvm_amd64.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_arm.c =================================================================== --- head/lib/libkvm/kvm_arm.c (revision 291405) +++ head/lib/libkvm/kvm_arm.c (revision 291406) @@ -1,286 +1,270 @@ /*- * Copyright (c) 2005 Olivier Houchard * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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 TOOLS GMBH ``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 TOOLS GMBH 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. */ /* * ARM machine dependent routines for kvm. */ #include __FBSDID("$FreeBSD$"); #include -#include -#include - -#ifndef CROSS_LIBKVM -#include -#include -#include -#include -#else -#include "../../sys/arm/include/pte.h" -#include "../../sys/arm/include/vmparam.h" -#endif - -#include -#include +#include #include +#include +#include #include -#include #include +#ifdef __arm__ +#include +#endif + #include "kvm_private.h" +#include "kvm_arm.h" -/* minidump must be the first item! */ struct vmstate { - int minidump; /* 1 = minidump mode */ - pd_entry_t *l1pt; - void *mmapbase; - size_t mmapsize; + arm_pd_entry_t *l1pt; + size_t phnum; + GElf_Phdr *phdr; }; -static int -_kvm_maphdrs(kvm_t *kd, size_t sz) -{ - struct vmstate *vm = kd->vmst; - - /* munmap() previous mmap(). */ - if (vm->mmapbase != NULL) { - munmap(vm->mmapbase, vm->mmapsize); - vm->mmapbase = NULL; - } - - vm->mmapsize = sz; - vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); - if (vm->mmapbase == MAP_FAILED) { - _kvm_err(kd, kd->program, "cannot mmap corefile"); - return (-1); - } - - return (0); -} - /* * Translate a physical memory address to a file-offset in the crash-dump. */ static size_t _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs, size_t pgsz) { - Elf32_Ehdr *e = kd->vmst->mmapbase; - Elf32_Phdr *p = (Elf32_Phdr*)((char*)e + e->e_phoff); - int n = e->e_phnum; + struct vmstate *vm = kd->vmst; + GElf_Phdr *p; + size_t n; + p = vm->phdr; + n = vm->phnum; while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) p++, n--; if (n == 0) return (0); *ofs = (pa - p->p_paddr) + p->p_offset; if (pgsz == 0) return (p->p_memsz - (pa - p->p_paddr)); return (pgsz - ((size_t)pa & (pgsz - 1))); } -void -_kvm_freevtop(kvm_t *kd) +static void +_arm_freevtop(kvm_t *kd) { - if (kd->vmst != 0) { - if (kd->vmst->minidump) - return (_kvm_minidump_freevtop(kd)); - if (kd->vmst->mmapbase != NULL) - munmap(kd->vmst->mmapbase, kd->vmst->mmapsize); - free(kd->vmst); - kd->vmst = NULL; - } + struct vmstate *vm = kd->vmst; + + free(vm->phdr); + free(vm); + kd->vmst = NULL; } -int -_kvm_initvtop(kvm_t *kd) +static int +_arm_probe(kvm_t *kd) { + + return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_ARM) && + !_kvm_is_minidump(kd)); +} + +static int +_arm_initvtop(kvm_t *kd) +{ struct vmstate *vm; - struct nlist nl[2]; - u_long kernbase, physaddr, pa; - pd_entry_t *l1pt; - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdr; - size_t hdrsz; - char minihdr[8]; - int found, i; + struct kvm_nlist nl[2]; + kvaddr_t kernbase; + arm_physaddr_t physaddr, pa; + arm_pd_entry_t *l1pt; + size_t i; + int found; - if (!kd->rawdump) { - if (pread(kd->pmfd, &minihdr, 8, 0) == 8) { - if (memcmp(&minihdr, "minidump", 8) == 0) - return (_kvm_minidump_initvtop(kd)); - } else { - _kvm_err(kd, kd->program, "cannot read header"); - return (-1); - } + if (kd->rawdump) { + _kvm_err(kd, kd->program, "raw dumps not supported on arm"); + return (-1); } vm = _kvm_malloc(kd, sizeof(*vm)); if (vm == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vm; vm->l1pt = NULL; - if (_kvm_maphdrs(kd, sizeof(Elf32_Ehdr)) == -1) + + if (_kvm_read_core_phdrs(kd, &vm->phnum, &vm->phdr) == -1) return (-1); - ehdr = kd->vmst->mmapbase; - hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; - if (_kvm_maphdrs(kd, hdrsz) == -1) - return (-1); - phdr = (Elf32_Phdr *)((uint8_t *)ehdr + ehdr->e_phoff); found = 0; - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_DUMP_DELTA) { - kernbase = phdr[i].p_vaddr; - physaddr = phdr[i].p_paddr; + for (i = 0; i < vm->phnum; i++) { + if (vm->phdr[i].p_type == PT_DUMP_DELTA) { + kernbase = vm->phdr[i].p_vaddr; + physaddr = vm->phdr[i].p_paddr; found = 1; break; } } nl[1].n_name = NULL; if (!found) { nl[0].n_name = "kernbase"; - if (kvm_nlist(kd, nl) != 0) + if (kvm_nlist2(kd, nl) != 0) { +#ifdef __arm__ kernbase = KERNBASE; - else +#else + _kvm_err(kd, kd->program, "cannot resolve kernbase"); + return (-1); +#endif + } else kernbase = nl[0].n_value; nl[0].n_name = "physaddr"; - if (kvm_nlist(kd, nl) != 0) { + if (kvm_nlist2(kd, nl) != 0) { _kvm_err(kd, kd->program, "couldn't get phys addr"); return (-1); } physaddr = nl[0].n_value; } nl[0].n_name = "kernel_l1pa"; - if (kvm_nlist(kd, nl) != 0) { + if (kvm_nlist2(kd, nl) != 0) { _kvm_err(kd, kd->program, "bad namelist"); return (-1); } - if (kvm_read(kd, (nl[0].n_value - kernbase + physaddr), &pa, + if (kvm_read2(kd, (nl[0].n_value - kernbase + physaddr), &pa, sizeof(pa)) != sizeof(pa)) { _kvm_err(kd, kd->program, "cannot read kernel_l1pa"); return (-1); } - l1pt = _kvm_malloc(kd, L1_TABLE_SIZE); - if (kvm_read(kd, pa, l1pt, L1_TABLE_SIZE) != L1_TABLE_SIZE) { + l1pt = _kvm_malloc(kd, ARM_L1_TABLE_SIZE); + if (kvm_read2(kd, pa, l1pt, ARM_L1_TABLE_SIZE) != ARM_L1_TABLE_SIZE) { _kvm_err(kd, kd->program, "cannot read l1pt"); free(l1pt); return (-1); } vm->l1pt = l1pt; return 0; } /* from arm/pmap.c */ -#define L1_IDX(va) (((vm_offset_t)(va)) >> L1_S_SHIFT) -/* from arm/pmap.h */ -#define L1_TYPE_INV 0x00 /* Invalid (fault) */ -#define L1_TYPE_C 0x01 /* Coarse L2 */ -#define L1_TYPE_S 0x02 /* Section */ -#define L1_TYPE_F 0x03 /* Fine L2 */ -#define L1_TYPE_MASK 0x03 /* mask of type bits */ +#define ARM_L1_IDX(va) ((va) >> ARM_L1_S_SHIFT) -#define l1pte_section_p(pde) (((pde) & L1_TYPE_MASK) == L1_TYPE_S) +#define l1pte_section_p(pde) (((pde) & ARM_L1_TYPE_MASK) == ARM_L1_TYPE_S) #define l1pte_valid(pde) ((pde) != 0) #define l2pte_valid(pte) ((pte) != 0) -#define l2pte_index(v) (((v) & L2_ADDR_BITS) >> L2_S_SHIFT) +#define l2pte_index(v) (((v) & ARM_L2_ADDR_BITS) >> ARM_L2_S_SHIFT) -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_arm_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm = kd->vmst; - pd_entry_t pd; - pt_entry_t pte; - off_t pte_pa; + arm_pd_entry_t pd; + arm_pt_entry_t pte; + arm_physaddr_t pte_pa; + off_t pte_off; - if (kd->vmst->minidump) - return (_kvm_minidump_kvatop(kd, va, pa)); - if (vm->l1pt == NULL) - return (_kvm_pa2off(kd, va, pa, PAGE_SIZE)); - pd = vm->l1pt[L1_IDX(va)]; + return (_kvm_pa2off(kd, va, pa, ARM_PAGE_SIZE)); + pd = _kvm32toh(kd, vm->l1pt[ARM_L1_IDX(va)]); if (!l1pte_valid(pd)) goto invalid; if (l1pte_section_p(pd)) { /* 1MB section mapping. */ - *pa = ((u_long)pd & L1_S_ADDR_MASK) + (va & L1_S_OFFSET); - return (_kvm_pa2off(kd, *pa, pa, L1_S_SIZE)); + *pa = (pd & ARM_L1_S_ADDR_MASK) + (va & ARM_L1_S_OFFSET); + return (_kvm_pa2off(kd, *pa, pa, ARM_L1_S_SIZE)); } - pte_pa = (pd & L1_ADDR_MASK) + l2pte_index(va) * sizeof(pte); - _kvm_pa2off(kd, pte_pa, &pte_pa, L1_S_SIZE); - if (lseek(kd->pmfd, pte_pa, 0) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_kvatop: lseek"); + pte_pa = (pd & ARM_L1_C_ADDR_MASK) + l2pte_index(va) * sizeof(pte); + _kvm_pa2off(kd, pte_pa, &pte_off, ARM_L1_S_SIZE); + if (pread(kd->pmfd, &pte, sizeof(pte), pte_off) != sizeof(pte)) { + _kvm_syserr(kd, kd->program, "_arm_kvatop: pread"); goto invalid; } - if (read(kd->pmfd, &pte, sizeof(pte)) != sizeof (pte)) { - _kvm_syserr(kd, kd->program, "_kvm_kvatop: read"); - goto invalid; - } + pte = _kvm32toh(kd, pte); if (!l2pte_valid(pte)) { goto invalid; } - if ((pte & L2_TYPE_MASK) == L2_TYPE_L) { - *pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET); - return (_kvm_pa2off(kd, *pa, pa, L2_L_SIZE)); + if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_L) { + *pa = (pte & ARM_L2_L_FRAME) | (va & ARM_L2_L_OFFSET); + return (_kvm_pa2off(kd, *pa, pa, ARM_L2_L_SIZE)); } - *pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); - return (_kvm_pa2off(kd, *pa, pa, PAGE_SIZE)); + *pa = (pte & ARM_L2_S_FRAME) | (va & ARM_L2_S_OFFSET); + return (_kvm_pa2off(kd, *pa, pa, ARM_PAGE_SIZE)); invalid: - _kvm_err(kd, 0, "Invalid address (%lx)", va); + _kvm_err(kd, 0, "Invalid address (%jx)", (uintmax_t)va); return 0; } /* * Machine-dependent initialization for ALL open kvm descriptors, * not just those for a kernel crash dump. Some architectures * have to deal with these NOT being constants! (i.e. m68k) */ #ifdef FBSD_NOT_YET int _kvm_mdopen(kvm_t *kd) { kd->usrstack = USRSTACK; kd->min_uva = VM_MIN_ADDRESS; kd->max_uva = VM_MAXUSER_ADDRESS; return (0); } #endif + +int +_arm_native(kvm_t *kd) +{ + +#ifdef __arm__ +#if _BYTE_ORDER == _LITTLE_ENDIAN + return (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB); +#else + return (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB); +#endif +#else + return (0); +#endif +} + +struct kvm_arch kvm_arm = { + .ka_probe = _arm_probe, + .ka_initvtop = _arm_initvtop, + .ka_freevtop = _arm_freevtop, + .ka_kvatop = _arm_kvatop, + .ka_native = _arm_native, +}; + +KVM_ARCH(kvm_arm); Index: head/lib/libkvm/kvm_arm.h =================================================================== --- head/lib/libkvm/kvm_arm.h (nonexistent) +++ head/lib/libkvm/kvm_arm.h (revision 291406) @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_ARM_H__ +#define __KVM_ARM_H__ + +#ifdef __arm__ +#include +#endif + +typedef uint32_t arm_physaddr_t; +typedef uint32_t arm_pd_entry_t; +typedef uint32_t arm_pt_entry_t; + +#define ARM_PAGE_SHIFT 12 +#define ARM_PAGE_SIZE (1 << ARM_PAGE_SHIFT) /* Page size */ +#define ARM_PAGE_MASK (ARM_PAGE_SIZE - 1) + +#define ARM_L1_TABLE_SIZE 0x4000 /* 16K */ + +#define ARM_L1_S_SIZE 0x00100000 /* 1M */ +#define ARM_L1_S_OFFSET (ARM_L1_S_SIZE - 1) +#define ARM_L1_S_FRAME (~ARM_L1_S_OFFSET) +#define ARM_L1_S_SHIFT 20 + +#define ARM_L2_L_SIZE 0x00010000 /* 64K */ +#define ARM_L2_L_OFFSET (ARM_L2_L_SIZE - 1) +#define ARM_L2_L_FRAME (~ARM_L2_L_OFFSET) +#define ARM_L2_L_SHIFT 16 + +#define ARM_L2_S_SIZE 0x00001000 /* 4K */ +#define ARM_L2_S_OFFSET (ARM_L2_S_SIZE - 1) +#define ARM_L2_S_FRAME (~ARM_L2_S_OFFSET) +#define ARM_L2_S_SHIFT 12 + +#define ARM_L1_TYPE_INV 0x00 /* Invalid (fault) */ +#define ARM_L1_TYPE_C 0x01 /* Coarse L2 */ +#define ARM_L1_TYPE_S 0x02 /* Section */ +#define ARM_L1_TYPE_MASK 0x03 /* Mask of type bits */ + +#define ARM_L1_S_ADDR_MASK 0xfff00000 /* phys address of section */ +#define ARM_L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */ + +#define ARM_L2_TYPE_INV 0x00 /* Invalid (fault) */ +#define ARM_L2_TYPE_L 0x01 /* Large Page - 64k - not used yet*/ +#define ARM_L2_TYPE_S 0x02 /* Small Page - 4 */ +#define ARM_L2_TYPE_MASK 0x03 + +#define ARM_L2_ADDR_BITS 0x000ff000 /* L2 PTE address bits */ + +#ifdef __arm__ +_Static_assert(PAGE_SHIFT == ARM_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == ARM_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == ARM_PAGE_MASK, "PAGE_MASK mismatch"); +_Static_assert(L1_TABLE_SIZE == ARM_L1_TABLE_SIZE, "L1_TABLE_SIZE mismatch"); +_Static_assert(L1_S_SIZE == ARM_L1_S_SIZE, "L1_S_SIZE mismatch"); +_Static_assert(L1_S_OFFSET == ARM_L1_S_OFFSET, "L1_S_OFFSET mismatch"); +_Static_assert(L1_S_FRAME == ARM_L1_S_FRAME, "L1_S_FRAME mismatch"); +_Static_assert(L1_S_SHIFT == ARM_L1_S_SHIFT, "L1_S_SHIFT mismatch"); +_Static_assert(L2_L_SIZE == ARM_L2_L_SIZE, "L2_L_SIZE mismatch"); +_Static_assert(L2_L_OFFSET == ARM_L2_L_OFFSET, "L2_L_OFFSET mismatch"); +_Static_assert(L2_L_FRAME == ARM_L2_L_FRAME, "L2_L_FRAME mismatch"); +_Static_assert(L2_L_SHIFT == ARM_L2_L_SHIFT, "L2_L_SHIFT mismatch"); +_Static_assert(L2_S_SIZE == ARM_L2_S_SIZE, "L2_S_SIZE mismatch"); +_Static_assert(L2_S_OFFSET == ARM_L2_S_OFFSET, "L2_S_OFFSET mismatch"); +_Static_assert(L2_S_FRAME == ARM_L2_S_FRAME, "L2_S_FRAME mismatch"); +_Static_assert(L2_S_SHIFT == ARM_L2_S_SHIFT, "L2_S_SHIFT mismatch"); +_Static_assert(L1_TYPE_INV == ARM_L1_TYPE_INV, "L1_TYPE_INV mismatch"); +_Static_assert(L1_TYPE_C == ARM_L1_TYPE_C, "L1_TYPE_C mismatch"); +_Static_assert(L1_TYPE_S == ARM_L1_TYPE_S, "L1_TYPE_S mismatch"); +_Static_assert(L1_TYPE_MASK == ARM_L1_TYPE_MASK, "L1_TYPE_MASK mismatch"); +_Static_assert(L1_S_ADDR_MASK == ARM_L1_S_ADDR_MASK, "L1_S_ADDR_MASK mismatch"); +_Static_assert(L1_C_ADDR_MASK == ARM_L1_C_ADDR_MASK, "L1_C_ADDR_MASK mismatch"); +_Static_assert(L2_TYPE_INV == ARM_L2_TYPE_INV, "L2_TYPE_INV mismatch"); +_Static_assert(L2_TYPE_L == ARM_L2_TYPE_L, "L2_TYPE_L mismatch"); +_Static_assert(L2_TYPE_S == ARM_L2_TYPE_S, "L2_TYPE_S mismatch"); +_Static_assert(L2_TYPE_MASK == ARM_L2_TYPE_MASK, "L2_TYPE_MASK mismatch"); +_Static_assert(L2_ADDR_BITS == ARM_L2_ADDR_BITS, "L2_ADDR_BITS mismatch"); +#endif + +int _arm_native(kvm_t *); + +#endif /* !__KVM_ARM_H__ */ Property changes on: head/lib/libkvm/kvm_arm.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_cptime.c =================================================================== --- head/lib/libkvm/kvm_cptime.c (revision 291405) +++ head/lib/libkvm/kvm_cptime.c (revision 291406) @@ -1,134 +1,140 @@ /*- * Copyright (c) 2008 Yahoo!, Inc. * All rights reserved. * Written by: John Baldwin * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "kvm_private.h" static struct nlist kvm_cp_time_nl[] = { { .n_name = "_cp_time" }, /* (deprecated) */ { .n_name = NULL }, }; #define NL_CP_TIME 0 static int kvm_cp_time_cached; static int _kvm_cp_time_init(kvm_t *kd) { if (kvm_nlist(kd, kvm_cp_time_nl) < 0) return (-1); kvm_cp_time_cached = 1; return (0); } static int getsysctl(kvm_t *kd, const char *name, void *buf, size_t len) { size_t nlen; nlen = len; if (sysctlbyname(name, buf, &nlen, NULL, 0) < 0) { _kvm_err(kd, kd->program, "cannot read sysctl %s:%s", name, strerror(errno)); return (-1); } if (nlen != len) { _kvm_err(kd, kd->program, "sysctl %s has unexpected size", name); return (-1); } return (0); } int kvm_getcptime(kvm_t *kd, long *cp_time) { struct pcpu *pc; int i, j, maxcpu; if (kd == NULL) { kvm_cp_time_cached = 0; return (0); } if (ISALIVE(kd)) return (getsysctl(kd, "kern.cp_time", cp_time, sizeof(long) * CPUSTATES)); + if (!kd->arch->ka_native(kd)) { + _kvm_err(kd, kd->program, + "cannot read cp_time from non-native core"); + return (-1); + } + if (kvm_cp_time_cached == 0) { if (_kvm_cp_time_init(kd) < 0) return (-1); } /* If this kernel has a "cp_time[]" symbol, then just read that. */ if (kvm_cp_time_nl[NL_CP_TIME].n_value != 0) { if (kvm_read(kd, kvm_cp_time_nl[NL_CP_TIME].n_value, cp_time, sizeof(long) * CPUSTATES) != sizeof(long) * CPUSTATES) { _kvm_err(kd, kd->program, "cannot read cp_time array"); return (-1); } return (0); } /* * If we don't have that symbol, then we have to simulate * "cp_time[]" by adding up the individual times for each CPU. */ maxcpu = kvm_getmaxcpu(kd); if (maxcpu < 0) return (-1); for (i = 0; i < CPUSTATES; i++) cp_time[i] = 0; for (i = 0; i < maxcpu; i++) { pc = kvm_getpcpu(kd, i); if (pc == NULL) continue; if (pc == (void *)-1) return (-1); for (j = 0; j < CPUSTATES; j++) cp_time[j] += pc->pc_cp_time[j]; free(pc); } return (0); } Index: head/lib/libkvm/kvm_getloadavg.c =================================================================== --- head/lib/libkvm/kvm_getloadavg.c (revision 291405) +++ head/lib/libkvm/kvm_getloadavg.c (revision 291406) @@ -1,99 +1,105 @@ /*- * Copyright (c) 1993 * The Regents of the University of California. 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. */ #include __FBSDID("$FreeBSD$"); #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)kvm_getloadavg.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include "kvm_private.h" static struct nlist nl[] = { { .n_name = "_averunnable" }, #define X_AVERUNNABLE 0 { .n_name = "_fscale" }, #define X_FSCALE 1 { .n_name = "" }, }; /* * kvm_getloadavg() -- Get system load averages, from live or dead kernels. * * Put `nelem' samples into `loadavg' array. * Return number of samples retrieved, or -1 on error. */ int kvm_getloadavg(kvm_t *kd, double loadavg[], int nelem) { struct loadavg loadinfo; struct nlist *p; int fscale, i; if (ISALIVE(kd)) return (getloadavg(loadavg, nelem)); + if (!kd->arch->ka_native(kd)) { + _kvm_err(kd, kd->program, + "cannot read loadavg from non-native core"); + return (-1); + } + if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p); _kvm_err(kd, kd->program, "%s: no such symbol", p->n_name); return (-1); } #define KREAD(kd, addr, obj) \ (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) if (KREAD(kd, nl[X_AVERUNNABLE].n_value, &loadinfo)) { _kvm_err(kd, kd->program, "can't read averunnable"); return (-1); } /* * Old kernels have fscale separately; if not found assume * running new format. */ if (!KREAD(kd, nl[X_FSCALE].n_value, &fscale)) loadinfo.fscale = fscale; nelem = MIN(nelem, (int)(sizeof(loadinfo.ldavg) / sizeof(fixpt_t))); for (i = 0; i < nelem; i++) loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale; return (nelem); } Index: head/lib/libkvm/kvm_getswapinfo.c =================================================================== --- head/lib/libkvm/kvm_getswapinfo.c (revision 291405) +++ head/lib/libkvm/kvm_getswapinfo.c (revision 291406) @@ -1,261 +1,267 @@ /* * Copyright (c) 1999, Matthew Dillon. All Rights Reserved. * Copyright (c) 2001, Thomas Moestl. 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 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 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kvm_private.h" static struct nlist kvm_swap_nl[] = { { .n_name = "_swtailq" }, /* list of swap devices and sizes */ { .n_name = "_dmmax" }, /* maximum size of a swap block */ { .n_name = NULL } }; #define NL_SWTAILQ 0 #define NL_DMMAX 1 static int kvm_swap_nl_cached = 0; static int unswdev; /* number of found swap dev's */ static int dmmax; static int kvm_getswapinfo_kvm(kvm_t *, struct kvm_swap *, int, int); static int kvm_getswapinfo_sysctl(kvm_t *, struct kvm_swap *, int, int); static int nlist_init(kvm_t *); static int getsysctl(kvm_t *, const char *, void *, size_t); #define KREAD(kd, addr, obj) \ (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) #define KGET(idx, var) \ KGET2(kvm_swap_nl[(idx)].n_value, var, kvm_swap_nl[(idx)].n_name) #define KGET2(addr, var, msg) \ if (KREAD(kd, (u_long)(addr), (var))) { \ _kvm_err(kd, kd->program, "cannot read %s", msg); \ return (-1); \ } #define GETSWDEVNAME(dev, str, flags) \ if (dev == NODEV) { \ strlcpy(str, "[NFS swap]", sizeof(str)); \ } else { \ snprintf( \ str, sizeof(str),"%s%s", \ ((flags & SWIF_DEV_PREFIX) ? _PATH_DEV : ""), \ devname(dev, S_IFCHR) \ ); \ } int kvm_getswapinfo(kvm_t *kd, struct kvm_swap *swap_ary, int swap_max, int flags) { /* * clear cache */ if (kd == NULL) { kvm_swap_nl_cached = 0; return(0); } if (ISALIVE(kd)) { return kvm_getswapinfo_sysctl(kd, swap_ary, swap_max, flags); } else { return kvm_getswapinfo_kvm(kd, swap_ary, swap_max, flags); } } int kvm_getswapinfo_kvm(kvm_t *kd, struct kvm_swap *swap_ary, int swap_max, int flags) { int i, ttl; TAILQ_HEAD(, swdevt) swtailq; struct swdevt *sp, swinfo; struct kvm_swap tot; + if (!kd->arch->ka_native(kd)) { + _kvm_err(kd, kd->program, + "cannot read swapinfo from non-native core"); + return (-1); + } + if (!nlist_init(kd)) return (-1); bzero(&tot, sizeof(tot)); KGET(NL_SWTAILQ, &swtailq); sp = TAILQ_FIRST(&swtailq); for (i = 0; sp != NULL; i++) { KGET2(sp, &swinfo, "swinfo"); ttl = swinfo.sw_nblks - dmmax; if (i < swap_max - 1) { bzero(&swap_ary[i], sizeof(swap_ary[i])); swap_ary[i].ksw_total = ttl; swap_ary[i].ksw_used = swinfo.sw_used; swap_ary[i].ksw_flags = swinfo.sw_flags; GETSWDEVNAME(swinfo.sw_dev, swap_ary[i].ksw_devname, flags); } tot.ksw_total += ttl; tot.ksw_used += swinfo.sw_used; sp = TAILQ_NEXT(&swinfo, sw_list); } if (i >= swap_max) i = swap_max - 1; if (i >= 0) swap_ary[i] = tot; return(i); } #define GETSYSCTL(kd, name, var) \ getsysctl(kd, name, &(var), sizeof(var)) /* The maximum MIB length for vm.swap_info and an additional device number */ #define SWI_MAXMIB 3 int kvm_getswapinfo_sysctl(kvm_t *kd, struct kvm_swap *swap_ary, int swap_max, int flags) { int ti, ttl; size_t mibi, len; int soid[SWI_MAXMIB]; struct xswdev xsd; struct kvm_swap tot; if (!GETSYSCTL(kd, "vm.dmmax", dmmax)) return -1; mibi = SWI_MAXMIB - 1; if (sysctlnametomib("vm.swap_info", soid, &mibi) == -1) { _kvm_err(kd, kd->program, "sysctlnametomib failed: %s", strerror(errno)); return -1; } bzero(&tot, sizeof(tot)); for (unswdev = 0;; unswdev++) { soid[mibi] = unswdev; len = sizeof(xsd); if (sysctl(soid, mibi + 1, &xsd, &len, NULL, 0) == -1) { if (errno == ENOENT) break; _kvm_err(kd, kd->program, "cannot read sysctl: %s.", strerror(errno)); return -1; } if (len != sizeof(xsd)) { _kvm_err(kd, kd->program, "struct xswdev has unexpected " "size; kernel and libkvm out of sync?"); return -1; } if (xsd.xsw_version != XSWDEV_VERSION) { _kvm_err(kd, kd->program, "struct xswdev version " "mismatch; kernel and libkvm out of sync?"); return -1; } ttl = xsd.xsw_nblks - dmmax; if (unswdev < swap_max - 1) { bzero(&swap_ary[unswdev], sizeof(swap_ary[unswdev])); swap_ary[unswdev].ksw_total = ttl; swap_ary[unswdev].ksw_used = xsd.xsw_used; swap_ary[unswdev].ksw_flags = xsd.xsw_flags; GETSWDEVNAME(xsd.xsw_dev, swap_ary[unswdev].ksw_devname, flags); } tot.ksw_total += ttl; tot.ksw_used += xsd.xsw_used; } ti = unswdev; if (ti >= swap_max) ti = swap_max - 1; if (ti >= 0) swap_ary[ti] = tot; return(ti); } static int nlist_init(kvm_t *kd) { if (kvm_swap_nl_cached) return (1); if (kvm_nlist(kd, kvm_swap_nl) < 0) return (0); /* Required entries */ if (kvm_swap_nl[NL_SWTAILQ].n_value == 0) { _kvm_err(kd, kd->program, "unable to find swtailq"); return (0); } if (kvm_swap_nl[NL_DMMAX].n_value == 0) { _kvm_err(kd, kd->program, "unable to find dmmax"); return (0); } /* Get globals, type of swap */ KGET(NL_DMMAX, &dmmax); kvm_swap_nl_cached = 1; return (1); } static int getsysctl(kvm_t *kd, const char *name, void *ptr, size_t len) { size_t nlen = len; if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { _kvm_err(kd, kd->program, "cannot read sysctl %s:%s", name, strerror(errno)); return (0); } if (nlen != len) { _kvm_err(kd, kd->program, "sysctl %s has unexpected size", name); return (0); } return (1); } Index: head/lib/libkvm/kvm_i386.c =================================================================== --- head/lib/libkvm/kvm_i386.c (revision 291405) +++ head/lib/libkvm/kvm_i386.c (revision 291406) @@ -1,452 +1,422 @@ /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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. */ #include __FBSDID("$FreeBSD$"); #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* LIBC_SCCS and not lint */ /* * i386 machine dependent routines for kvm. Hopefully, the forthcoming * vm code will one day obsolete this module. */ #include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include -#include -#include +#ifdef __i386__ +#include /* For KERNBASE. */ +#endif -#include - #include #include "kvm_private.h" +#include "kvm_i386.h" -#ifndef btop -#define btop(x) (i386_btop(x)) -#define ptob(x) (i386_ptob(x)) -#endif - -#define PG_FRAME_PAE (~((uint64_t)PAGE_MASK)) -#define PDRSHIFT_PAE 21 -#define NPTEPG_PAE (PAGE_SIZE/sizeof(uint64_t)) -#define NBPDR_PAE (1<vmst; - - /* munmap() previous mmap(). */ - if (vm->mmapbase != NULL) { - munmap(vm->mmapbase, vm->mmapsize); - vm->mmapbase = NULL; - } - - vm->mmapsize = sz; - vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); - if (vm->mmapbase == MAP_FAILED) { - _kvm_err(kd, kd->program, "cannot mmap corefile"); - return (-1); - } - return (0); -} - -/* * Translate a physical memory address to a file-offset in the crash-dump. */ static size_t _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs) { - Elf_Ehdr *e = kd->vmst->mmapbase; - Elf_Phdr *p; - int n; + struct vmstate *vm = kd->vmst; + GElf_Phdr *p; + size_t n; if (kd->rawdump) { *ofs = pa; - return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); + return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); } - p = (Elf_Phdr*)((char*)e + e->e_phoff); - n = e->e_phnum; + p = vm->phdr; + n = vm->phnum; while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) p++, n--; if (n == 0) return (0); *ofs = (pa - p->p_paddr) + p->p_offset; - return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); + return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); } -void -_kvm_freevtop(kvm_t *kd) +static void +_i386_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (kd->vmst->minidump) - return (_kvm_minidump_freevtop(kd)); - if (vm->mmapbase != NULL) - munmap(vm->mmapbase, vm->mmapsize); if (vm->PTD) free(vm->PTD); + free(vm->phdr); free(vm); kd->vmst = NULL; } -int -_kvm_initvtop(kvm_t *kd) +static int +_i386_probe(kvm_t *kd) { - struct nlist nl[2]; - u_long pa; - u_long kernbase; + + return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_386) && + !_kvm_is_minidump(kd)); +} + +static int +_i386_initvtop(kvm_t *kd) +{ + struct kvm_nlist nl[2]; + i386_physaddr_t pa; + kvaddr_t kernbase; char *PTD; - Elf_Ehdr *ehdr; - size_t hdrsz; int i; - char minihdr[8]; - if (!kd->rawdump && pread(kd->pmfd, &minihdr, 8, 0) == 8) - if (memcmp(&minihdr, "minidump", 8) == 0) - return (_kvm_minidump_initvtop(kd)); - - kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); - if (kd->vmst == 0) { + kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(struct vmstate)); + if (kd->vmst == NULL) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst->PTD = 0; if (kd->rawdump == 0) { - if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1) + if (_kvm_read_core_phdrs(kd, &kd->vmst->phnum, + &kd->vmst->phdr) == -1) return (-1); - - ehdr = kd->vmst->mmapbase; - hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; - if (_kvm_maphdrs(kd, hdrsz) == -1) - return (-1); } nl[0].n_name = "kernbase"; nl[1].n_name = 0; - if (kvm_nlist(kd, nl) != 0) + if (kvm_nlist2(kd, nl) != 0) { +#ifdef __i386__ kernbase = KERNBASE; /* for old kernels */ - else +#else + _kvm_err(kd, kd->program, "cannot resolve kernbase"); + return (-1); +#endif + } else kernbase = nl[0].n_value; nl[0].n_name = "IdlePDPT"; nl[1].n_name = 0; - if (kvm_nlist(kd, nl) == 0) { - uint64_t pa64; + if (kvm_nlist2(kd, nl) == 0) { + i386_physaddr_pae_t pa64; - if (kvm_read(kd, (nl[0].n_value - kernbase), &pa, + if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, sizeof(pa)) != sizeof(pa)) { _kvm_err(kd, kd->program, "cannot read IdlePDPT"); return (-1); } - PTD = _kvm_malloc(kd, 4 * PAGE_SIZE); + pa = le32toh(pa); + PTD = _kvm_malloc(kd, 4 * I386_PAGE_SIZE); for (i = 0; i < 4; i++) { - if (kvm_read(kd, pa + (i * sizeof(pa64)), &pa64, + if (kvm_read2(kd, pa + (i * sizeof(pa64)), &pa64, sizeof(pa64)) != sizeof(pa64)) { _kvm_err(kd, kd->program, "Cannot read PDPT"); free(PTD); return (-1); } - if (kvm_read(kd, pa64 & PG_FRAME_PAE, - PTD + (i * PAGE_SIZE), PAGE_SIZE) != (PAGE_SIZE)) { + pa64 = le64toh(pa64); + if (kvm_read2(kd, pa64 & I386_PG_FRAME_PAE, + PTD + (i * I386_PAGE_SIZE), I386_PAGE_SIZE) != + I386_PAGE_SIZE) { _kvm_err(kd, kd->program, "cannot read PDPT"); free(PTD); return (-1); } } kd->vmst->PTD = PTD; kd->vmst->pae = 1; } else { nl[0].n_name = "IdlePTD"; nl[1].n_name = 0; - if (kvm_nlist(kd, nl) != 0) { + if (kvm_nlist2(kd, nl) != 0) { _kvm_err(kd, kd->program, "bad namelist"); return (-1); } - if (kvm_read(kd, (nl[0].n_value - kernbase), &pa, + if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, sizeof(pa)) != sizeof(pa)) { _kvm_err(kd, kd->program, "cannot read IdlePTD"); return (-1); } - PTD = _kvm_malloc(kd, PAGE_SIZE); - if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { + pa = le32toh(pa); + PTD = _kvm_malloc(kd, I386_PAGE_SIZE); + if (kvm_read2(kd, pa, PTD, I386_PAGE_SIZE) != I386_PAGE_SIZE) { _kvm_err(kd, kd->program, "cannot read PTD"); return (-1); } kd->vmst->PTD = PTD; kd->vmst->pae = 0; } return (0); } static int -_kvm_vatop(kvm_t *kd, u_long va, off_t *pa) +_i386_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - u_long offset; - u_long pte_pa; - u_long pde_pa; - pd_entry_t pde; - pt_entry_t pte; - u_long pdeindex; - u_long pteindex; + i386_physaddr_t offset; + i386_physaddr_t pte_pa; + i386_pde_t pde; + i386_pte_t pte; + kvaddr_t pdeindex; + kvaddr_t pteindex; size_t s; - u_long a; + i386_physaddr_t a; off_t ofs; - uint32_t *PTD; + i386_pde_t *PTD; vm = kd->vmst; - PTD = (uint32_t *)vm->PTD; - offset = va & (PAGE_SIZE - 1); + PTD = (i386_pde_t *)vm->PTD; + offset = va & I386_PAGE_MASK; /* * If we are initializing (kernel page table descriptor pointer * not yet set) then return pa == va to avoid infinite recursion. */ if (PTD == 0) { s = _kvm_pa2off(kd, va, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop: bootstrap data not in dump"); + "_i386_vatop: bootstrap data not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); } - pdeindex = va >> PDRSHIFT; - pde = PTD[pdeindex]; - if (((u_long)pde & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); + pdeindex = va >> I386_PDRSHIFT; + pde = le32toh(PTD[pdeindex]); + if ((pde & I386_PG_V) == 0) { + _kvm_err(kd, kd->program, "_i386_vatop: pde not valid"); goto invalid; } - if ((u_long)pde & PG_PS) { - /* - * No second-level page table; ptd describes one 4MB page. - * (We assume that the kernel wouldn't set PG_PS without enabling - * it cr0). - */ -#define PAGE4M_MASK (NBPDR - 1) -#define PG_FRAME4M (~PAGE4M_MASK) - pde_pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); - s = _kvm_pa2off(kd, pde_pa, &ofs); + if (pde & I386_PG_PS) { + /* + * No second-level page table; ptd describes one 4MB + * page. (We assume that the kernel wouldn't set + * PG_PS without enabling it cr0). + */ + offset = va & I386_PAGE_PS_MASK; + a = (pde & I386_PG_PS_FRAME) + offset; + s = _kvm_pa2off(kd, a, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop: 4MB page address not in dump"); + "_i386_vatop: 4MB page address not in dump"); goto invalid; } - *pa = ofs; - return (NBPDR - (va & PAGE4M_MASK)); + return (I386_NBPDR - offset); } - pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); - pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pde)); + pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG - 1); + pte_pa = (pde & I386_PG_FRAME) + (pteindex * sizeof(pte)); s = _kvm_pa2off(kd, pte_pa, &ofs); - if (s < sizeof pte) { - _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found"); + if (s < sizeof(pte)) { + _kvm_err(kd, kd->program, "_i386_vatop: pte_pa not found"); goto invalid; } /* XXX This has to be a physical address read, kvm_read is virtual */ - if (lseek(kd->pmfd, ofs, 0) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); + if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { + _kvm_syserr(kd, kd->program, "_i386_vatop: pread"); goto invalid; } - if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { - _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); - goto invalid; - } - if (((u_long)pte & PG_V) == 0) { + pte = le32toh(pte); + if ((pte & I386_PG_V) == 0) { _kvm_err(kd, kd->program, "_kvm_kvatop: pte not valid"); goto invalid; } - a = ((u_long)pte & PG_FRAME) + offset; - s =_kvm_pa2off(kd, a, pa); + a = (pte & I386_PG_FRAME) + offset; + s = _kvm_pa2off(kd, a, pa); if (s == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: address not in dump"); + _kvm_err(kd, kd->program, "_i386_vatop: address not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } static int -_kvm_vatop_pae(kvm_t *kd, u_long va, off_t *pa) +_i386_vatop_pae(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - uint64_t offset; - uint64_t pte_pa; - uint64_t pde_pa; - uint64_t pde; - uint64_t pte; - u_long pdeindex; - u_long pteindex; + i386_physaddr_pae_t offset; + i386_physaddr_pae_t pte_pa; + i386_pde_pae_t pde; + i386_pte_pae_t pte; + kvaddr_t pdeindex; + kvaddr_t pteindex; size_t s; - uint64_t a; + i386_physaddr_pae_t a; off_t ofs; - uint64_t *PTD; + i386_pde_pae_t *PTD; vm = kd->vmst; - PTD = (uint64_t *)vm->PTD; - offset = va & (PAGE_SIZE - 1); + PTD = (i386_pde_pae_t *)vm->PTD; + offset = va & I386_PAGE_MASK; /* * If we are initializing (kernel page table descriptor pointer * not yet set) then return pa == va to avoid infinite recursion. */ if (PTD == 0) { s = _kvm_pa2off(kd, va, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop_pae: bootstrap data not in dump"); + "_i386_vatop_pae: bootstrap data not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); } - pdeindex = va >> PDRSHIFT_PAE; - pde = PTD[pdeindex]; - if (((u_long)pde & PG_V) == 0) { + pdeindex = va >> I386_PDRSHIFT_PAE; + pde = le64toh(PTD[pdeindex]); + if ((pde & I386_PG_V) == 0) { _kvm_err(kd, kd->program, "_kvm_kvatop_pae: pde not valid"); goto invalid; } - if ((u_long)pde & PG_PS) { - /* - * No second-level page table; ptd describes one 2MB page. - * (We assume that the kernel wouldn't set PG_PS without enabling - * it cr0). - */ -#define PAGE2M_MASK (NBPDR_PAE - 1) -#define PG_FRAME2M (~PAGE2M_MASK) - pde_pa = ((u_long)pde & PG_FRAME2M) + (va & PAGE2M_MASK); - s = _kvm_pa2off(kd, pde_pa, &ofs); + if (pde & I386_PG_PS) { + /* + * No second-level page table; ptd describes one 2MB + * page. (We assume that the kernel wouldn't set + * PG_PS without enabling it cr0). + */ + offset = va & I386_PAGE_PS_MASK_PAE; + a = (pde & I386_PG_PS_FRAME_PAE) + offset; + s = _kvm_pa2off(kd, a, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop: 2MB page address not in dump"); + "_i386_vatop: 2MB page address not in dump"); goto invalid; } - *pa = ofs; - return (NBPDR_PAE - (va & PAGE2M_MASK)); + return (I386_NBPDR_PAE - offset); } - pteindex = (va >> PAGE_SHIFT) & (NPTEPG_PAE-1); - pte_pa = ((uint64_t)pde & PG_FRAME_PAE) + (pteindex * sizeof(pde)); + pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG_PAE - 1); + pte_pa = (pde & I386_PG_FRAME_PAE) + (pteindex * sizeof(pde)); s = _kvm_pa2off(kd, pte_pa, &ofs); - if (s < sizeof pte) { - _kvm_err(kd, kd->program, "_kvm_vatop_pae: pdpe_pa not found"); + if (s < sizeof(pte)) { + _kvm_err(kd, kd->program, "_i386_vatop_pae: pdpe_pa not found"); goto invalid; } /* XXX This has to be a physical address read, kvm_read is virtual */ - if (lseek(kd->pmfd, ofs, 0) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_vatop_pae: lseek"); + if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { + _kvm_syserr(kd, kd->program, "_i386_vatop_pae: read"); goto invalid; } - if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { - _kvm_syserr(kd, kd->program, "_kvm_vatop_pae: read"); + pte = le64toh(pte); + if ((pte & I386_PG_V) == 0) { + _kvm_err(kd, kd->program, "_i386_vatop_pae: pte not valid"); goto invalid; } - if (((uint64_t)pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop_pae: pte not valid"); - goto invalid; - } - a = ((uint64_t)pte & PG_FRAME_PAE) + offset; - s =_kvm_pa2off(kd, a, pa); + a = (pte & I386_PG_FRAME_PAE) + offset; + s = _kvm_pa2off(kd, a, pa); if (s == 0) { _kvm_err(kd, kd->program, - "_kvm_vatop_pae: address not in dump"); + "_i386_vatop_pae: address not in dump"); goto invalid; } else - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_i386_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { - if (kd->vmst->minidump) - return (_kvm_minidump_kvatop(kd, va, pa)); if (ISALIVE(kd)) { _kvm_err(kd, 0, "vatop called in live kernel!"); return (0); } if (kd->vmst->pae) - return (_kvm_vatop_pae(kd, va, pa)); + return (_i386_vatop_pae(kd, va, pa)); else - return (_kvm_vatop(kd, va, pa)); + return (_i386_vatop(kd, va, pa)); } + +int +_i386_native(kvm_t *kd) +{ + +#ifdef __i386__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_i386 = { + .ka_probe = _i386_probe, + .ka_initvtop = _i386_initvtop, + .ka_freevtop = _i386_freevtop, + .ka_kvatop = _i386_kvatop, + .ka_native = _i386_native, +}; + +KVM_ARCH(kvm_i386); Index: head/lib/libkvm/kvm_i386.h =================================================================== --- head/lib/libkvm/kvm_i386.h (nonexistent) +++ head/lib/libkvm/kvm_i386.h (revision 291406) @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_I386_H__ +#define __KVM_I386_H__ + +#ifdef __i386__ +#include +#include +#endif + +typedef uint32_t i386_physaddr_t; +typedef uint32_t i386_pte_t; +typedef uint32_t i386_pde_t; +typedef uint64_t i386_physaddr_pae_t; +typedef uint64_t i386_pte_pae_t; +typedef uint64_t i386_pde_pae_t; + +#define I386_PAGE_SHIFT 12 +#define I386_PAGE_SIZE (1 << I386_PAGE_SHIFT) +#define I386_PAGE_MASK (I386_PAGE_SIZE - 1) +#define I386_NPTEPG (I386_PAGE_SIZE / sizeof(i386_pte_t)) +#define I386_PDRSHIFT 22 +#define I386_NBPDR (1 << I386_PDRSHIFT) +#define I386_PAGE_PS_MASK (I386_NBPDR - 1) +#define I386_NPTEPG_PAE (I386_PAGE_SIZE / sizeof(i386_pte_pae_t)) +#define I386_PDRSHIFT_PAE 21 +#define I386_NBPDR_PAE (1 << I386_PDRSHIFT_PAE) +#define I386_PAGE_PS_MASK_PAE (I386_NBPDR_PAE - 1) + +#define I386_PG_V 0x001 +#define I386_PG_PS 0x080 +#define I386_PG_FRAME_PAE (0x000ffffffffff000ull) +#define I386_PG_PS_FRAME_PAE (0x000fffffffe00000ull) +#define I386_PG_FRAME (0xfffff000) +#define I386_PG_PS_FRAME (0xffc00000) + +#ifdef __i386__ +_Static_assert(PAGE_SHIFT == I386_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == I386_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == I386_PAGE_MASK, "PAGE_MASK mismatch"); +_Static_assert(NPTEPG == I386_NPTEPG, "NPTEPG mismatch"); +_Static_assert(PDRSHIFT == I386_PDRSHIFT, "PDRSHIFT mismatch"); +_Static_assert(NBPDR == I386_NBPDR, "NBPDR mismatch"); + +_Static_assert(PG_V == I386_PG_V, "PG_V mismatch"); +_Static_assert(PG_PS == I386_PG_PS, "PG_PS mismatch"); +_Static_assert(PG_FRAME == I386_PG_FRAME, "PG_FRAME mismatch"); +_Static_assert(PG_PS_FRAME == I386_PG_PS_FRAME, "PG_PS_FRAME mismatch"); +#endif + +int _i386_native(kvm_t *); + +#endif /* !__KVM_I386_H__ */ Property changes on: head/lib/libkvm/kvm_i386.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_minidump_aarch64.c =================================================================== --- head/lib/libkvm/kvm_minidump_aarch64.c (revision 291405) +++ head/lib/libkvm/kvm_minidump_aarch64.c (revision 291406) @@ -1,269 +1,253 @@ /*- * Copyright (c) 2006 Peter Wemm * * 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 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. * * From: FreeBSD: src/lib/libkvm/kvm_minidump_amd64.c r261799 */ #include __FBSDID("$FreeBSD$"); /* * ARM64 (AArch64) machine dependent routines for kvm and minidumps. */ #include -#include -#include -#include -#include -#include +#include #include #include #include -#include #include -#include -#include +#include "../../sys/arm64/include/minidump.h" -#include -#include -#include -#include - #include -#include #include "kvm_private.h" +#include "kvm_aarch64.h" -struct hpte { - struct hpte *next; - vm_paddr_t pa; - int64_t off; -}; +#define aarch64_round_page(x) roundup2((kvaddr_t)(x), AARCH64_PAGE_SIZE) -#define HPT_SIZE 1024 - -/* minidump must be the first item! */ struct vmstate { - int minidump; /* 1 = minidump mode */ struct minidumphdr hdr; - void *hpt_head[HPT_SIZE]; - uint64_t *bitmap; + struct hpt hpt; uint64_t *page_map; }; -static void -hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - hpte = malloc(sizeof(*hpte)); - hpte->pa = pa; - hpte->off = off; - hpte->next = kd->vmst->hpt_head[fnv]; - kd->vmst->hpt_head[fnv] = hpte; -} - -static int64_t -hpt_find(kvm_t *kd, vm_paddr_t pa) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { - if (pa == hpte->pa) - return (hpte->off); - } - return (-1); -} - static int -inithash(kvm_t *kd, uint64_t *base, int len, off_t off) +_aarch64_minidump_probe(kvm_t *kd) { - uint64_t idx; - uint64_t bit, bits; - vm_paddr_t pa; - for (idx = 0; idx < len / sizeof(*base); idx++) { - bits = base[idx]; - while (bits) { - bit = ffsl(bits) - 1; - bits &= ~(1ul << bit); - pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; - hpt_insert(kd, pa, off); - off += PAGE_SIZE; - } - } - return (off); + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_AARCH64) && + _kvm_is_minidump(kd)); } -void -_kvm_minidump_freevtop(kvm_t *kd) +static void +_aarch64_minidump_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - free(vm->bitmap); + _kvm_hpt_free(&vm->hpt); free(vm->page_map); free(vm); kd->vmst = NULL; } -int -_kvm_minidump_initvtop(kvm_t *kd) +static int +_aarch64_minidump_initvtop(kvm_t *kd) { struct vmstate *vmst; + uint64_t *bitmap; off_t off; vmst = _kvm_malloc(kd, sizeof(*vmst)); if (vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vmst; - vmst->minidump = 1; if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) { _kvm_err(kd, kd->program, "cannot read dump header"); return (-1); } if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { _kvm_err(kd, kd->program, "not a minidump for this platform"); return (-1); } - if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) { + vmst->hdr.version = le32toh(vmst->hdr.version); + if (vmst->hdr.version != MINIDUMP_VERSION) { _kvm_err(kd, kd->program, "wrong minidump version. " "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); return (-1); } + vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); + vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); + vmst->hdr.pmapsize = le32toh(vmst->hdr.pmapsize); + vmst->hdr.kernbase = le64toh(vmst->hdr.kernbase); + vmst->hdr.dmapphys = le64toh(vmst->hdr.dmapphys); + vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase); + vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend); /* Skip header and msgbuf */ - off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize); + off = AARCH64_PAGE_SIZE + aarch64_round_page(vmst->hdr.msgbufsize); - vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); - if (vmst->bitmap == NULL) { + bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); + if (bitmap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for bitmap", vmst->hdr.bitmapsize); return (-1); } - if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) != - vmst->hdr.bitmapsize) { + if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) != + (ssize_t)vmst->hdr.bitmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap", vmst->hdr.bitmapsize); + free(bitmap); return (-1); } - off += round_page(vmst->hdr.bitmapsize); + off += aarch64_round_page(vmst->hdr.bitmapsize); vmst->page_map = _kvm_malloc(kd, vmst->hdr.pmapsize); if (vmst->page_map == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for page_map", vmst->hdr.pmapsize); + free(bitmap); return (-1); } /* This is the end of the dump, savecore may have truncated it. */ + /* + * XXX: This doesn't make sense. The pmap is not at the end, + * and if it is truncated we don't have any actual data (it's + * all stored after the bitmap and pmap. -- jhb + */ if (pread(kd->pmfd, vmst->page_map, vmst->hdr.pmapsize, off) < - PAGE_SIZE) { + AARCH64_PAGE_SIZE) { _kvm_err(kd, kd->program, "cannot read %d bytes for page_map", vmst->hdr.pmapsize); + free(bitmap); + return (-1); } off += vmst->hdr.pmapsize; /* build physical address hash table for sparse pages */ - inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off); + _kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off, + AARCH64_PAGE_SIZE, sizeof(*bitmap)); + free(bitmap); return (0); } static int -_kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) +_aarch64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - u_long offset; - pt_entry_t l3; - u_long l3_index; - u_long a; + aarch64_physaddr_t offset; + aarch64_pte_t l3; + kvaddr_t l3_index; + aarch64_physaddr_t a; off_t ofs; vm = kd->vmst; - offset = va & PAGE_MASK; + offset = va & AARCH64_PAGE_MASK; if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) { - a = (va - vm->hdr.dmapbase + vm->hdr.dmapphys) & ~PAGE_MASK; - ofs = hpt_find(kd, a); + a = (va - vm->hdr.dmapbase + vm->hdr.dmapphys) & + ~AARCH64_PAGE_MASK; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: " - "direct map address 0x%lx not in minidump", va); + _kvm_err(kd, kd->program, "_aarch64_minidump_vatop: " + "direct map address 0x%jx not in minidump", + (uintmax_t)va); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AARCH64_PAGE_SIZE - offset); } else if (va >= vm->hdr.kernbase) { - l3_index = (va - vm->hdr.kernbase) >> L3_SHIFT; + l3_index = (va - vm->hdr.kernbase) >> AARCH64_L3_SHIFT; if (l3_index >= vm->hdr.pmapsize / sizeof(*vm->page_map)) goto invalid; - l3 = vm->page_map[l3_index]; - if ((l3 & ATTR_DESCR_MASK) != L3_PAGE) { - _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); + l3 = le64toh(vm->page_map[l3_index]); + if ((l3 & AARCH64_ATTR_DESCR_MASK) != AARCH64_L3_PAGE) { + _kvm_err(kd, kd->program, + "_aarch64_minidump_vatop: pde not valid"); goto invalid; } - a = l3 & ~ATTR_MASK; - ofs = hpt_find(kd, a); + a = l3 & ~AARCH64_ATTR_MASK; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: " - "physical address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, "_aarch64_minidump_vatop: " + "physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AARCH64_PAGE_SIZE - offset); } else { _kvm_err(kd, kd->program, - "_kvm_vatop: virtual address 0x%lx not minidumped", va); + "_aarch64_minidump_vatop: virtual address 0x%jx not minidumped", + (uintmax_t)va); goto invalid; } invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } -int -_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_aarch64_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { if (ISALIVE(kd)) { - _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); + _kvm_err(kd, 0, + "_aarch64_minidump_kvatop called in live kernel!"); return (0); } - return (_kvm_minidump_vatop(kd, va, pa)); + return (_aarch64_minidump_vatop(kd, va, pa)); } + +static int +_aarch64_native(kvm_t *kd) +{ + +#ifdef __aarch64__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_aarch64_minidump = { + .ka_probe = _aarch64_minidump_probe, + .ka_initvtop = _aarch64_minidump_initvtop, + .ka_freevtop = _aarch64_minidump_freevtop, + .ka_kvatop = _aarch64_minidump_kvatop, + .ka_native = _aarch64_native, +}; + +KVM_ARCH(kvm_aarch64_minidump); Index: head/lib/libkvm/kvm_minidump_amd64.c =================================================================== --- head/lib/libkvm/kvm_minidump_amd64.c (revision 291405) +++ head/lib/libkvm/kvm_minidump_amd64.c (revision 291406) @@ -1,336 +1,321 @@ /*- * Copyright (c) 2006 Peter Wemm * * 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 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. */ #include __FBSDID("$FreeBSD$"); /* * AMD64 machine dependent routines for kvm and minidumps. */ #include -#include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include -#include -#include +#include "../../sys/amd64/include/minidump.h" -#include -#include -#include - #include #include "kvm_private.h" +#include "kvm_amd64.h" -struct hpte { - struct hpte *next; - vm_paddr_t pa; - int64_t off; -}; +#define amd64_round_page(x) roundup2((kvaddr_t)(x), AMD64_PAGE_SIZE) -#define HPT_SIZE 1024 - -/* minidump must be the first item! */ struct vmstate { - int minidump; /* 1 = minidump mode */ struct minidumphdr hdr; - void *hpt_head[HPT_SIZE]; - uint64_t *bitmap; - uint64_t *page_map; + struct hpt hpt; + amd64_pte_t *page_map; }; -static void -hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - hpte = malloc(sizeof(*hpte)); - hpte->pa = pa; - hpte->off = off; - hpte->next = kd->vmst->hpt_head[fnv]; - kd->vmst->hpt_head[fnv] = hpte; -} - -static int64_t -hpt_find(kvm_t *kd, vm_paddr_t pa) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { - if (pa == hpte->pa) - return (hpte->off); - } - return (-1); -} - static int -inithash(kvm_t *kd, uint64_t *base, int len, off_t off) +_amd64_minidump_probe(kvm_t *kd) { - uint64_t idx; - uint64_t bit, bits; - vm_paddr_t pa; - for (idx = 0; idx < len / sizeof(*base); idx++) { - bits = base[idx]; - while (bits) { - bit = bsfq(bits); - bits &= ~(1ul << bit); - pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; - hpt_insert(kd, pa, off); - off += PAGE_SIZE; - } - } - return (off); + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_X86_64) && + _kvm_is_minidump(kd)); } -void -_kvm_minidump_freevtop(kvm_t *kd) +static void +_amd64_minidump_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm->bitmap) - free(vm->bitmap); + _kvm_hpt_free(&vm->hpt); if (vm->page_map) free(vm->page_map); free(vm); kd->vmst = NULL; } -int -_kvm_minidump_initvtop(kvm_t *kd) +static int +_amd64_minidump_initvtop(kvm_t *kd) { struct vmstate *vmst; + uint64_t *bitmap; off_t off; vmst = _kvm_malloc(kd, sizeof(*vmst)); if (vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vmst; - vmst->minidump = 1; if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) { _kvm_err(kd, kd->program, "cannot read dump header"); return (-1); } if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { _kvm_err(kd, kd->program, "not a minidump for this platform"); return (-1); } /* * NB: amd64 minidump header is binary compatible between version 1 * and version 2; this may not be the case for the future versions. */ + vmst->hdr.version = le32toh(vmst->hdr.version); if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) { _kvm_err(kd, kd->program, "wrong minidump version. expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); return (-1); } + vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); + vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); + vmst->hdr.pmapsize = le32toh(vmst->hdr.pmapsize); + vmst->hdr.kernbase = le64toh(vmst->hdr.kernbase); + vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase); + vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend); /* Skip header and msgbuf */ - off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize); + off = AMD64_PAGE_SIZE + amd64_round_page(vmst->hdr.msgbufsize); - vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); - if (vmst->bitmap == NULL) { + bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); + if (bitmap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for bitmap", vmst->hdr.bitmapsize); return (-1); } - if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) != - vmst->hdr.bitmapsize) { + if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) != + (ssize_t)vmst->hdr.bitmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap", vmst->hdr.bitmapsize); + free(bitmap); return (-1); } - off += round_page(vmst->hdr.bitmapsize); + off += amd64_round_page(vmst->hdr.bitmapsize); vmst->page_map = _kvm_malloc(kd, vmst->hdr.pmapsize); if (vmst->page_map == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for page_map", vmst->hdr.pmapsize); + free(bitmap); return (-1); } if (pread(kd->pmfd, vmst->page_map, vmst->hdr.pmapsize, off) != - vmst->hdr.pmapsize) { + (ssize_t)vmst->hdr.pmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page_map", vmst->hdr.pmapsize); + free(bitmap); return (-1); } off += vmst->hdr.pmapsize; /* build physical address hash table for sparse pages */ - inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off); + _kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off, + AMD64_PAGE_SIZE, sizeof(*bitmap)); + free(bitmap); return (0); } static int -_kvm_minidump_vatop_v1(kvm_t *kd, u_long va, off_t *pa) +_amd64_minidump_vatop_v1(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - u_long offset; - pt_entry_t pte; - u_long pteindex; - u_long a; + amd64_physaddr_t offset; + amd64_pte_t pte; + kvaddr_t pteindex; + amd64_physaddr_t a; off_t ofs; vm = kd->vmst; - offset = va & (PAGE_SIZE - 1); + offset = va & AMD64_PAGE_MASK; if (va >= vm->hdr.kernbase) { - pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; + pteindex = (va - vm->hdr.kernbase) >> AMD64_PAGE_SHIFT; if (pteindex >= vm->hdr.pmapsize / sizeof(*vm->page_map)) goto invalid; - pte = vm->page_map[pteindex]; - if (((u_long)pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + pte = le64toh(vm->page_map[pteindex]); + if ((pte & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop_v1: pte not valid"); goto invalid; } - a = pte & PG_FRAME; - ofs = hpt_find(kd, a); + a = pte & AMD64_PG_FRAME; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop_v1: physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); } else if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) { - a = (va - vm->hdr.dmapbase) & ~PAGE_MASK; - ofs = hpt_find(kd, a); + a = (va - vm->hdr.dmapbase) & ~AMD64_PAGE_MASK; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: direct map address 0x%lx not in minidump", va); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop_v1: direct map address 0x%jx not in minidump", + (uintmax_t)va); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); } else { - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop_v1: virtual address 0x%jx not minidumped", + (uintmax_t)va); goto invalid; } invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } static int -_kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) +_amd64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) { - pt_entry_t pt[NPTEPG]; + amd64_pte_t pt[AMD64_NPTEPG]; struct vmstate *vm; - u_long offset; - pd_entry_t pde; - pd_entry_t pte; - u_long pteindex; - u_long pdeindex; - u_long a; + amd64_physaddr_t offset; + amd64_pde_t pde; + amd64_pte_t pte; + kvaddr_t pteindex; + kvaddr_t pdeindex; + amd64_physaddr_t a; off_t ofs; vm = kd->vmst; - offset = va & PAGE_MASK; + offset = va & AMD64_PAGE_MASK; if (va >= vm->hdr.kernbase) { - pdeindex = (va - vm->hdr.kernbase) >> PDRSHIFT; + pdeindex = (va - vm->hdr.kernbase) >> AMD64_PDRSHIFT; if (pdeindex >= vm->hdr.pmapsize / sizeof(*vm->page_map)) goto invalid; - pde = vm->page_map[pdeindex]; - if (((u_long)pde & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); + pde = le64toh(vm->page_map[pdeindex]); + if ((pde & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: pde not valid"); goto invalid; } - if ((pde & PG_PS) == 0) { - a = pde & PG_FRAME; - ofs = hpt_find(kd, a); + if ((pde & AMD64_PG_PS) == 0) { + a = pde & AMD64_PG_FRAME; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: pt physical address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: pt physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } - if (pread(kd->pmfd, &pt, PAGE_SIZE, ofs) != PAGE_SIZE) { - _kvm_err(kd, kd->program, "cannot read %d bytes for pt", PAGE_SIZE); + /* TODO: Just read the single PTE */ + if (pread(kd->pmfd, &pt, AMD64_PAGE_SIZE, ofs) != + AMD64_PAGE_SIZE) { + _kvm_err(kd, kd->program, + "cannot read %d bytes for page table", + AMD64_PAGE_SIZE); return (-1); } - pteindex = (va >> PAGE_SHIFT) & ((1ul << NPTEPGSHIFT) - 1); - pte = pt[pteindex]; - if (((u_long)pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + pteindex = (va >> AMD64_PAGE_SHIFT) & + (AMD64_NPTEPG - 1); + pte = le64toh(pt[pteindex]); + if ((pte & AMD64_PG_V) == 0) { + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: pte not valid"); goto invalid; } - a = pte & PG_FRAME; + a = pte & AMD64_PG_FRAME; } else { - a = pde & PG_PS_FRAME; - a += (va & PDRMASK) ^ offset; + a = pde & AMD64_PG_PS_FRAME; + a += (va & AMD64_PDRMASK) ^ offset; } - ofs = hpt_find(kd, a); + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); } else if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) { - a = (va - vm->hdr.dmapbase) & ~PAGE_MASK; - ofs = hpt_find(kd, a); + a = (va - vm->hdr.dmapbase) & ~AMD64_PAGE_MASK; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: direct map address 0x%lx not in minidump", va); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: direct map address 0x%jx not in minidump", + (uintmax_t)va); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (AMD64_PAGE_SIZE - offset); } else { - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); + _kvm_err(kd, kd->program, + "_amd64_minidump_vatop: virtual address 0x%jx not minidumped", + (uintmax_t)va); goto invalid; } invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } -int -_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_amd64_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { if (ISALIVE(kd)) { - _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); + _kvm_err(kd, 0, + "_amd64_minidump_kvatop called in live kernel!"); return (0); } if (((struct vmstate *)kd->vmst)->hdr.version == 1) - return (_kvm_minidump_vatop_v1(kd, va, pa)); + return (_amd64_minidump_vatop_v1(kd, va, pa)); else - return (_kvm_minidump_vatop(kd, va, pa)); + return (_amd64_minidump_vatop(kd, va, pa)); } + +struct kvm_arch kvm_amd64_minidump = { + .ka_probe = _amd64_minidump_probe, + .ka_initvtop = _amd64_minidump_initvtop, + .ka_freevtop = _amd64_minidump_freevtop, + .ka_kvatop = _amd64_minidump_kvatop, + .ka_native = _amd64_native, +}; + +KVM_ARCH(kvm_amd64_minidump); Index: head/lib/libkvm/kvm_minidump_arm.c =================================================================== --- head/lib/libkvm/kvm_minidump_arm.c (revision 291405) +++ head/lib/libkvm/kvm_minidump_arm.c (revision 291406) @@ -1,268 +1,224 @@ /*- * Copyright (c) 2008 Semihalf, Grzegorz Bernacki * Copyright (c) 2006 Peter Wemm * * 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 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. * * From: FreeBSD: src/lib/libkvm/kvm_minidump_i386.c,v 1.2 2006/06/05 08:51:14 */ #include __FBSDID("$FreeBSD$"); /* * ARM machine dependent routines for kvm and minidumps. */ +#include #include -#ifndef CROSS_LIBKVM -#include -#endif -#include -#include -#include -#include +#include +#include +#include #include #include #include -#include -#include -#ifndef CROSS_LIBKVM -#include -#include - -#include -#include -#include -#else -#include "../../sys/arm/include/pte.h" -#include "../../sys/arm/include/vmparam.h" #include "../../sys/arm/include/minidump.h" -#endif -#include - #include "kvm_private.h" +#include "kvm_arm.h" -struct hpte { - struct hpte *next; - uint64_t pa; - int64_t off; -}; +#define arm_round_page(x) roundup2((kvaddr_t)(x), ARM_PAGE_SIZE) -#define HPT_SIZE 1024 - -/* minidump must be the first field */ struct vmstate { - int minidump; /* 1 = minidump mode */ struct minidumphdr hdr; - void *hpt_head[HPT_SIZE]; - uint32_t *bitmap; + struct hpt hpt; void *ptemap; + unsigned char ei_data; }; -static void -hpt_insert(kvm_t *kd, uint64_t pa, int64_t off) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - hpte = malloc(sizeof(*hpte)); - hpte->pa = pa; - hpte->off = off; - hpte->next = kd->vmst->hpt_head[fnv]; - kd->vmst->hpt_head[fnv] = hpte; -} - -static int64_t -hpt_find(kvm_t *kd, uint64_t pa) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) - if (pa == hpte->pa) - return (hpte->off); - - return (-1); -} - static int -inithash(kvm_t *kd, uint32_t *base, int len, off_t off) +_arm_minidump_probe(kvm_t *kd) { - uint64_t idx, pa; - uint32_t bit, bits; - for (idx = 0; idx < len / sizeof(*base); idx++) { - bits = base[idx]; - while (bits) { - bit = ffs(bits) - 1; - bits &= ~(1ul << bit); - pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; - hpt_insert(kd, pa, off); - off += PAGE_SIZE; - } - } - return (off); + return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_ARM) && + _kvm_is_minidump(kd)); } -void -_kvm_minidump_freevtop(kvm_t *kd) +static void +_arm_minidump_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm->bitmap) - free(vm->bitmap); + _kvm_hpt_free(&vm->hpt); if (vm->ptemap) free(vm->ptemap); free(vm); kd->vmst = NULL; } -int -_kvm_minidump_initvtop(kvm_t *kd) +static int +_arm_minidump_initvtop(kvm_t *kd) { struct vmstate *vmst; + uint32_t *bitmap; off_t off; vmst = _kvm_malloc(kd, sizeof(*vmst)); if (vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vmst; - vmst->minidump = 1; if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) { _kvm_err(kd, kd->program, "cannot read dump header"); return (-1); } if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { _kvm_err(kd, kd->program, "not a minidump for this platform"); return (-1); } + vmst->hdr.version = _kvm32toh(kd, vmst->hdr.version); if (vmst->hdr.version != MINIDUMP_VERSION) { _kvm_err(kd, kd->program, "wrong minidump version. " "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); return (-1); } + vmst->hdr.msgbufsize = _kvm32toh(kd, vmst->hdr.msgbufsize); + vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize); + vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize); + vmst->hdr.kernbase = _kvm32toh(kd, vmst->hdr.kernbase); /* Skip header and msgbuf */ - off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize); + off = ARM_PAGE_SIZE + arm_round_page(vmst->hdr.msgbufsize); - vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); - if (vmst->bitmap == NULL) { + bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); + if (bitmap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for " "bitmap", vmst->hdr.bitmapsize); return (-1); } - if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) != + if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) != (ssize_t)vmst->hdr.bitmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap", vmst->hdr.bitmapsize); + free(bitmap); return (-1); } - off += round_page(vmst->hdr.bitmapsize); + off += arm_round_page(vmst->hdr.bitmapsize); vmst->ptemap = _kvm_malloc(kd, vmst->hdr.ptesize); if (vmst->ptemap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for " "ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } if (pread(kd->pmfd, vmst->ptemap, vmst->hdr.ptesize, off) != (ssize_t)vmst->hdr.ptesize) { _kvm_err(kd, kd->program, "cannot read %d bytes for ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } off += vmst->hdr.ptesize; /* Build physical address hash table for sparse pages */ - inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off); + _kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off, + ARM_PAGE_SIZE, sizeof(*bitmap)); + free(bitmap); return (0); } -int -_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_arm_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - pt_entry_t pte; - u_long offset, pteindex, a; + arm_pt_entry_t pte; + arm_physaddr_t offset, a; + kvaddr_t pteindex; off_t ofs; - uint32_t *ptemap; + arm_pt_entry_t *ptemap; if (ISALIVE(kd)) { - _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); + _kvm_err(kd, 0, "_arm_minidump_kvatop called in live kernel!"); return (0); } vm = kd->vmst; ptemap = vm->ptemap; if (va >= vm->hdr.kernbase) { - pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; - pte = ptemap[pteindex]; + pteindex = (va - vm->hdr.kernbase) >> ARM_PAGE_SHIFT; + pte = _kvm32toh(kd, ptemap[pteindex]); if (!pte) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + _kvm_err(kd, kd->program, + "_arm_minidump_kvatop: pte not valid"); goto invalid; } - if ((pte & L2_TYPE_MASK) == L2_TYPE_L) { - offset = va & L2_L_OFFSET; - a = pte & L2_L_FRAME; - } else if ((pte & L2_TYPE_MASK) == L2_TYPE_S) { - offset = va & L2_S_OFFSET; - a = pte & L2_S_FRAME; + if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_L) { + offset = va & ARM_L2_L_OFFSET; + a = pte & ARM_L2_L_FRAME; + } else if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_S) { + offset = va & ARM_L2_S_OFFSET; + a = pte & ARM_L2_S_FRAME; } else goto invalid; - ofs = hpt_find(kd, a); + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical " - "address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, "_arm_minidump_kvatop: " + "physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (ARM_PAGE_SIZE - offset); } else - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx " - "not minidumped", va); + _kvm_err(kd, kd->program, "_arm_minidump_kvatop: virtual " + "address 0x%jx not minidumped", (uintmax_t)va); invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } + +struct kvm_arch kvm_arm_minidump = { + .ka_probe = _arm_minidump_probe, + .ka_initvtop = _arm_minidump_initvtop, + .ka_freevtop = _arm_minidump_freevtop, + .ka_kvatop = _arm_minidump_kvatop, + .ka_native = _arm_native, +}; + +KVM_ARCH(kvm_arm_minidump); Index: head/lib/libkvm/kvm_minidump_i386.c =================================================================== --- head/lib/libkvm/kvm_minidump_i386.c (revision 291405) +++ head/lib/libkvm/kvm_minidump_i386.c (revision 291406) @@ -1,291 +1,260 @@ /*- * Copyright (c) 2006 Peter Wemm * * 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 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. */ #include __FBSDID("$FreeBSD$"); /* - * AMD64 machine dependent routines for kvm and minidumps. + * i386 machine dependent routines for kvm and minidumps. */ #include -#include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include -#include -#include +#include "../../sys/i386/include/minidump.h" -#include -#include -#include - #include #include "kvm_private.h" +#include "kvm_i386.h" -#define PG_FRAME_PAE (~((uint64_t)PAGE_MASK)) +#define i386_round_page(x) roundup2((kvaddr_t)(x), I386_PAGE_SIZE) -struct hpte { - struct hpte *next; - uint64_t pa; - int64_t off; -}; - -#define HPT_SIZE 1024 - -/* minidump must be the first item! */ struct vmstate { - int minidump; /* 1 = minidump mode */ struct minidumphdr hdr; - void *hpt_head[HPT_SIZE]; - uint32_t *bitmap; + struct hpt hpt; void *ptemap; }; -static void -hpt_insert(kvm_t *kd, uint64_t pa, int64_t off) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - hpte = malloc(sizeof(*hpte)); - hpte->pa = pa; - hpte->off = off; - hpte->next = kd->vmst->hpt_head[fnv]; - kd->vmst->hpt_head[fnv] = hpte; -} - -static int64_t -hpt_find(kvm_t *kd, uint64_t pa) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { - if (pa == hpte->pa) - return (hpte->off); - } - return (-1); -} - static int -inithash(kvm_t *kd, uint32_t *base, int len, off_t off) +_i386_minidump_probe(kvm_t *kd) { - uint64_t idx; - uint32_t bit, bits; - uint64_t pa; - for (idx = 0; idx < len / sizeof(*base); idx++) { - bits = base[idx]; - while (bits) { - bit = bsfl(bits); - bits &= ~(1ul << bit); - pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; - hpt_insert(kd, pa, off); - off += PAGE_SIZE; - } - } - return (off); + return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_386) && + _kvm_is_minidump(kd)); } -void -_kvm_minidump_freevtop(kvm_t *kd) +static void +_i386_minidump_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm->bitmap) - free(vm->bitmap); + _kvm_hpt_free(&vm->hpt); if (vm->ptemap) free(vm->ptemap); free(vm); kd->vmst = NULL; } -int -_kvm_minidump_initvtop(kvm_t *kd) +static int +_i386_minidump_initvtop(kvm_t *kd) { struct vmstate *vmst; + uint32_t *bitmap; off_t off; vmst = _kvm_malloc(kd, sizeof(*vmst)); if (vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vmst; - vmst->minidump = 1; if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) { _kvm_err(kd, kd->program, "cannot read dump header"); return (-1); } if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { _kvm_err(kd, kd->program, "not a minidump for this platform"); return (-1); } + vmst->hdr.version = le32toh(vmst->hdr.version); if (vmst->hdr.version != MINIDUMP_VERSION) { _kvm_err(kd, kd->program, "wrong minidump version. expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); return (-1); } + vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); + vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); + vmst->hdr.ptesize = le32toh(vmst->hdr.ptesize); + vmst->hdr.kernbase = le32toh(vmst->hdr.kernbase); + vmst->hdr.paemode = le32toh(vmst->hdr.paemode); /* Skip header and msgbuf */ - off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize); + off = I386_PAGE_SIZE + i386_round_page(vmst->hdr.msgbufsize); - vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); - if (vmst->bitmap == NULL) { + bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); + if (bitmap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for bitmap", vmst->hdr.bitmapsize); return (-1); } - if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) != + if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) != (ssize_t)vmst->hdr.bitmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap", vmst->hdr.bitmapsize); + free(bitmap); return (-1); } - off += round_page(vmst->hdr.bitmapsize); + off += i386_round_page(vmst->hdr.bitmapsize); vmst->ptemap = _kvm_malloc(kd, vmst->hdr.ptesize); if (vmst->ptemap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } if (pread(kd->pmfd, vmst->ptemap, vmst->hdr.ptesize, off) != (ssize_t)vmst->hdr.ptesize) { _kvm_err(kd, kd->program, "cannot read %d bytes for ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } off += vmst->hdr.ptesize; /* build physical address hash table for sparse pages */ - inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off); + _kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off, + I386_PAGE_SIZE, sizeof(*bitmap)); + free(bitmap); return (0); } static int -_kvm_minidump_vatop_pae(kvm_t *kd, u_long va, off_t *pa) +_i386_minidump_vatop_pae(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - uint64_t offset; - uint64_t pte; - u_long pteindex; - uint64_t a; + i386_physaddr_pae_t offset; + i386_pte_pae_t pte; + kvaddr_t pteindex; + i386_physaddr_pae_t a; off_t ofs; - uint64_t *ptemap; + i386_pte_pae_t *ptemap; vm = kd->vmst; ptemap = vm->ptemap; - offset = va & (PAGE_SIZE - 1); + offset = va & I386_PAGE_MASK; if (va >= vm->hdr.kernbase) { - pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; - pte = ptemap[pteindex]; - if ((pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + pteindex = (va - vm->hdr.kernbase) >> I386_PAGE_SHIFT; + pte = le64toh(ptemap[pteindex]); + if ((pte & I386_PG_V) == 0) { + _kvm_err(kd, kd->program, + "_i386_minidump_vatop_pae: pte not valid"); goto invalid; } - a = pte & PG_FRAME_PAE; - ofs = hpt_find(kd, a); + a = pte & I386_PG_FRAME_PAE; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%llx not in minidump", a); + _kvm_err(kd, kd->program, + "_i386_minidump_vatop_pae: physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); } else { - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); + _kvm_err(kd, kd->program, + "_i386_minidump_vatop_pae: virtual address 0x%jx not minidumped", + (uintmax_t)va); goto invalid; } invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } static int -_kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) +_i386_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - u_long offset; - pt_entry_t pte; - u_long pteindex; - u_long a; + i386_physaddr_t offset; + i386_pte_t pte; + kvaddr_t pteindex; + i386_physaddr_t a; off_t ofs; - uint32_t *ptemap; + i386_pte_t *ptemap; vm = kd->vmst; ptemap = vm->ptemap; - offset = va & (PAGE_SIZE - 1); + offset = va & I386_PAGE_MASK; if (va >= vm->hdr.kernbase) { - pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; - pte = ptemap[pteindex]; - if ((pte & PG_V) == 0) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + pteindex = (va - vm->hdr.kernbase) >> I386_PAGE_SHIFT; + pte = le32toh(ptemap[pteindex]); + if ((pte & I386_PG_V) == 0) { + _kvm_err(kd, kd->program, + "_i386_minidump_vatop: pte not valid"); goto invalid; } - a = pte & PG_FRAME; - ofs = hpt_find(kd, a); + a = pte & I386_PG_FRAME; + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, + "_i386_minidump_vatop: physical address 0x%jx not in minidump", + (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (I386_PAGE_SIZE - offset); } else { - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); + _kvm_err(kd, kd->program, + "_i386_minidump_vatop: virtual address 0x%jx not minidumped", + (uintmax_t)va); goto invalid; } invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } -int -_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_i386_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { if (ISALIVE(kd)) { - _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); + _kvm_err(kd, 0, "_i386_minidump_kvatop called in live kernel!"); return (0); } if (kd->vmst->hdr.paemode) - return (_kvm_minidump_vatop_pae(kd, va, pa)); + return (_i386_minidump_vatop_pae(kd, va, pa)); else - return (_kvm_minidump_vatop(kd, va, pa)); + return (_i386_minidump_vatop(kd, va, pa)); } + +struct kvm_arch kvm_i386_minidump = { + .ka_probe = _i386_minidump_probe, + .ka_initvtop = _i386_minidump_initvtop, + .ka_freevtop = _i386_minidump_freevtop, + .ka_kvatop = _i386_minidump_kvatop, + .ka_native = _i386_native, +}; + +KVM_ARCH(kvm_i386_minidump); Index: head/lib/libkvm/kvm_minidump_mips.c =================================================================== --- head/lib/libkvm/kvm_minidump_mips.c (revision 291405) +++ head/lib/libkvm/kvm_minidump_mips.c (revision 291406) @@ -1,273 +1,295 @@ /*- * Copyright (c) 2010 Oleksandr Tymoshenko * Copyright (c) 2008 Semihalf, Grzegorz Bernacki * Copyright (c) 2006 Peter Wemm * * 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 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. * * From: FreeBSD: src/lib/libkvm/kvm_minidump_arm.c r214223 */ #include __FBSDID("$FreeBSD$"); /* * MIPS machine dependent routines for kvm and minidumps. */ #include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include -#include -#include -#include -#include +#include "../../sys/mips/include/cpuregs.h" +#include "../../sys/mips/include/minidump.h" -#include -#include -#include - -#include - #include "kvm_private.h" +#include "kvm_mips.h" -struct hpte { - struct hpte *next; - uint64_t pa; - int64_t off; -}; +#define mips_round_page(x) roundup2((kvaddr_t)(x), MIPS_PAGE_SIZE) -#define HPT_SIZE 1024 - -/* minidump must be the first field */ struct vmstate { - int minidump; /* 1 = minidump mode */ struct minidumphdr hdr; - void *hpt_head[HPT_SIZE]; - uint32_t *bitmap; + struct hpt hpt; void *ptemap; + int pte_size; }; -static void -hpt_insert(kvm_t *kd, uint64_t pa, int64_t off) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - hpte = malloc(sizeof(*hpte)); - hpte->pa = pa; - hpte->off = off; - hpte->next = kd->vmst->hpt_head[fnv]; - kd->vmst->hpt_head[fnv] = hpte; -} - -static int64_t -hpt_find(kvm_t *kd, uint64_t pa) -{ - struct hpte *hpte; - uint32_t fnv = FNV1_32_INIT; - - fnv = fnv_32_buf(&pa, sizeof(pa), fnv); - fnv &= (HPT_SIZE - 1); - for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) - if (pa == hpte->pa) - return (hpte->off); - - return (-1); -} - static int -inithash(kvm_t *kd, uint32_t *base, int len, off_t off) +_mips_minidump_probe(kvm_t *kd) { - uint64_t idx, pa; - uint32_t bit, bits; - for (idx = 0; idx < len / sizeof(*base); idx++) { - bits = base[idx]; - while (bits) { - bit = ffs(bits) - 1; - bits &= ~(1ul << bit); - pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; - hpt_insert(kd, pa, off); - off += PAGE_SIZE; - } - } - - return (off); + if (kd->nlehdr.e_ident[EI_CLASS] != ELFCLASS32 && + kd->nlehdr.e_ident[EI_CLASS] != ELFCLASS64) + return (0); + if (kd->nlehdr.e_machine != EM_MIPS) + return (0); + return (_kvm_is_minidump(kd)); } -void -_kvm_minidump_freevtop(kvm_t *kd) +static void +_mips_minidump_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm->bitmap) - free(vm->bitmap); + _kvm_hpt_free(&vm->hpt); if (vm->ptemap) free(vm->ptemap); free(vm); kd->vmst = NULL; } -int -_kvm_minidump_initvtop(kvm_t *kd) +static int +_mips_minidump_initvtop(kvm_t *kd) { struct vmstate *vmst; + uint32_t *bitmap; off_t off; vmst = _kvm_malloc(kd, sizeof(*vmst)); if (vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vmst; - vmst->minidump = 1; - off = lseek(kd->pmfd, 0, SEEK_CUR); + if (kd->nlehdr.e_ident[EI_CLASS] == ELFCLASS64 || + kd->nlehdr.e_flags & EF_MIPS_ABI2) + vmst->pte_size = 64; + else + vmst->pte_size = 32; + if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) { _kvm_err(kd, kd->program, "cannot read dump header"); return (-1); } if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { _kvm_err(kd, kd->program, "not a minidump for this platform"); return (-1); } + vmst->hdr.version = _kvm32toh(kd, vmst->hdr.version); if (vmst->hdr.version != MINIDUMP_VERSION) { _kvm_err(kd, kd->program, "wrong minidump version. " "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version); return (-1); } + vmst->hdr.msgbufsize = _kvm32toh(kd, vmst->hdr.msgbufsize); + vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize); + vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize); + vmst->hdr.kernbase = _kvm64toh(kd, vmst->hdr.kernbase); + vmst->hdr.dmapbase = _kvm64toh(kd, vmst->hdr.dmapbase); + vmst->hdr.dmapend = _kvm64toh(kd, vmst->hdr.dmapend); /* Skip header and msgbuf */ - off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize); + off = MIPS_PAGE_SIZE + mips_round_page(vmst->hdr.msgbufsize); - vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); - if (vmst->bitmap == NULL) { + bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize); + if (bitmap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for " "bitmap", vmst->hdr.bitmapsize); return (-1); } - if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) != + if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) != (ssize_t)vmst->hdr.bitmapsize) { _kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap", vmst->hdr.bitmapsize); + free(bitmap); return (-1); } - off += round_page(vmst->hdr.bitmapsize); + off += mips_round_page(vmst->hdr.bitmapsize); vmst->ptemap = _kvm_malloc(kd, vmst->hdr.ptesize); if (vmst->ptemap == NULL) { _kvm_err(kd, kd->program, "cannot allocate %d bytes for " "ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } if (pread(kd->pmfd, vmst->ptemap, vmst->hdr.ptesize, off) != (ssize_t)vmst->hdr.ptesize) { _kvm_err(kd, kd->program, "cannot read %d bytes for ptemap", vmst->hdr.ptesize); + free(bitmap); return (-1); } off += vmst->hdr.ptesize; /* Build physical address hash table for sparse pages */ - inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off); + _kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off, + MIPS_PAGE_SIZE, sizeof(*bitmap)); + free(bitmap); return (0); } -int -_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_mips_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { struct vmstate *vm; - pt_entry_t pte; - u_long offset, pteindex, a; + uint64_t pte; + mips_physaddr_t offset, a; + kvaddr_t pteindex; off_t ofs; - pt_entry_t *ptemap; + uint32_t *ptemap32; + uint64_t *ptemap64; if (ISALIVE(kd)) { - _kvm_err(kd, 0, "kvm_kvatop called in live kernel!"); + _kvm_err(kd, 0, "_mips_minidump_kvatop called in live kernel!"); return (0); } - offset = va & PAGE_MASK; + offset = va & MIPS_PAGE_MASK; /* Operate with page-aligned address */ - va &= ~PAGE_MASK; + va &= ~MIPS_PAGE_MASK; vm = kd->vmst; - ptemap = vm->ptemap; + ptemap32 = vm->ptemap; + ptemap64 = vm->ptemap; -#if defined(__mips_n64) - if (va >= MIPS_XKPHYS_START && va < MIPS_XKPHYS_END) - a = (MIPS_XKPHYS_TO_PHYS(va)); - else -#endif - if (va >= (u_long)MIPS_KSEG0_START && va < (u_long)MIPS_KSEG0_END) - a = (MIPS_KSEG0_TO_PHYS(va)); - else if (va >= (u_long)MIPS_KSEG1_START && va < (u_long)MIPS_KSEG1_END) - a = (MIPS_KSEG1_TO_PHYS(va)); - else if (va >= vm->hdr.kernbase) { - pteindex = (va - vm->hdr.kernbase) >> PAGE_SHIFT; - pte = ptemap[pteindex]; + if (kd->nlehdr.e_ident[EI_CLASS] == ELFCLASS64) { + if (va >= MIPS_XKPHYS_START && va < MIPS_XKPHYS_END) { + a = va & MIPS_XKPHYS_PHYS_MASK; + goto found; + } + if (va >= MIPS64_KSEG0_START && va < MIPS64_KSEG0_END) { + a = va & MIPS_KSEG0_PHYS_MASK; + goto found; + } + if (va >= MIPS64_KSEG1_START && va < MIPS64_KSEG1_END) { + a = va & MIPS_KSEG0_PHYS_MASK; + goto found; + } + } else { + if (va >= MIPS32_KSEG0_START && va < MIPS32_KSEG0_END) { + a = va & MIPS_KSEG0_PHYS_MASK; + goto found; + } + if (va >= MIPS32_KSEG1_START && va < MIPS32_KSEG1_END) { + a = va & MIPS_KSEG0_PHYS_MASK; + goto found; + } + } + if (va >= vm->hdr.kernbase) { + pteindex = (va - vm->hdr.kernbase) >> MIPS_PAGE_SHIFT; + if (vm->pte_size == 64) { + pte = _kvm64toh(kd, ptemap64[pteindex]); + a = MIPS64_PTE_TO_PA(pte); + } else { + pte = _kvm32toh(kd, ptemap32[pteindex]); + a = MIPS32_PTE_TO_PA(pte); + } if (!pte) { - _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid"); + _kvm_err(kd, kd->program, "_mips_minidump_kvatop: pte " + "not valid"); goto invalid; } - - a = TLBLO_PTE_TO_PA(pte); - } else { - _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx " - "not minidumped", va); + _kvm_err(kd, kd->program, "_mips_minidump_kvatop: virtual " + "address 0x%jx not minidumped", (uintmax_t)va); return (0); } - ofs = hpt_find(kd, a); +found: + ofs = _kvm_hpt_find(&vm->hpt, a); if (ofs == -1) { - _kvm_err(kd, kd->program, "_kvm_vatop: physical " - "address 0x%lx not in minidump", a); + _kvm_err(kd, kd->program, "_mips_minidump_kvatop: physical " + "address 0x%jx not in minidump", (uintmax_t)a); goto invalid; } *pa = ofs + offset; - return (PAGE_SIZE - offset); + return (MIPS_PAGE_SIZE - offset); invalid: - _kvm_err(kd, 0, "invalid address (0x%lx)", va); + _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); return (0); } + +static int +_mips_native(kvm_t *kd) +{ + +#ifdef __mips__ +#ifdef __mips_n64 + if (kd->nlehdr.e_ident[EI_CLASS] != ELFCLASS64) + return (0); +#else + if (kd->nlehdr.e_ident[EI_CLASS] != ELFCLASS32) + return (0); +#ifdef __mips_n32 + if (!(kd->nlehdr.e_flags & EF_MIPS_ABI2)) + return (0); +#else + if (kd->nlehdr.e_flags & EF_MIPS_ABI2) + return (0); +#endif +#endif +#if _BYTE_ORDER == _LITTLE_ENDIAN + return (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB); +#else + return (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB); +#endif +#else + return (0); +#endif +} + +struct kvm_arch kvm_mips_minidump = { + .ka_probe = _mips_minidump_probe, + .ka_initvtop = _mips_minidump_initvtop, + .ka_freevtop = _mips_minidump_freevtop, + .ka_kvatop = _mips_minidump_kvatop, + .ka_native = _mips_native, +}; + +KVM_ARCH(kvm_mips_minidump); Index: head/lib/libkvm/kvm_mips.h =================================================================== --- head/lib/libkvm/kvm_mips.h (nonexistent) +++ head/lib/libkvm/kvm_mips.h (revision 291406) @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_MIPS_H__ +#define __KVM_MIPS_H__ + +#ifdef __mips__ +#include +#endif + +typedef uint64_t mips_physaddr_t; + +#define MIPS_PAGE_SHIFT 12 +#define MIPS_PAGE_SIZE (1 << MIPS_PAGE_SHIFT) +#define MIPS_PAGE_MASK (MIPS_PAGE_SIZE - 1) + +#define MIPS32_KSEG0_START 0x80000000 +#define MIPS32_KSEG0_END 0x9fffffff +#define MIPS32_KSEG1_START 0xa0000000 +#define MIPS32_KSEG1_END 0xbfffffff +#define MIPS64_KSEG0_START 0xffffffff80000000 +#define MIPS64_KSEG0_END 0xffffffff9fffffff +#define MIPS64_KSEG1_START 0xffffffffa0000000 +#define MIPS64_KSEG1_END 0xffffffffbfffffff + +#define MIPS32_PFN_MASK (0x1FFFFFC0) +#define MIPS64_PFN_MASK 0x3FFFFFFC0 +#define MIPS_PFN_SHIFT (6) + +#define MIPS_PFN_TO_PA(pfn) (((pfn) >> MIPS_PFN_SHIFT) << MIPS_PAGE_SHIFT) +#define MIPS32_PTE_TO_PFN(pte) ((pte) & MIPS32_PFN_MASK) +#define MIPS32_PTE_TO_PA(pte) (MIPS_PFN_TO_PA(MIPS32_PTE_TO_PFN((pte)))) +#define MIPS64_PTE_TO_PFN(pte) ((pte) & MIPS64_PFN_MASK) +#define MIPS64_PTE_TO_PA(pte) (MIPS_PFN_TO_PA(MIPS64_PTE_TO_PFN((pte)))) + +#ifdef __mips__ +_Static_assert(PAGE_SHIFT == MIPS_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == MIPS_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == MIPS_PAGE_MASK, "PAGE_MASK mismatch"); +#ifdef __mips_n64 +_Static_assert((uint64_t)MIPS_KSEG0_START == MIPS64_KSEG0_START, + "MIPS_KSEG0_START mismatch"); +_Static_assert((uint64_t)MIPS_KSEG0_END == MIPS64_KSEG0_END, + "MIPS_KSEG0_END mismatch"); +_Static_assert((uint64_t)MIPS_KSEG1_START == MIPS64_KSEG1_START, + "MIPS_KSEG1_START mismatch"); +_Static_assert((uint64_t)MIPS_KSEG1_END == MIPS64_KSEG1_END, + "MIPS_KSEG1_END mismatch"); +#else +_Static_assert((uint32_t)MIPS_KSEG0_START == MIPS32_KSEG0_START, + "MIPS_KSEG0_START mismatch"); +_Static_assert((uint32_t)MIPS_KSEG0_END == MIPS32_KSEG0_END, + "MIPS_KSEG0_END mismatch"); +_Static_assert((uint32_t)MIPS_KSEG1_START == MIPS32_KSEG1_START, + "MIPS_KSEG1_START mismatch"); +_Static_assert((uint32_t)MIPS_KSEG1_END == MIPS32_KSEG1_END, + "MIPS_KSEG1_END mismatch"); +#endif +#if defined(__mips_n64) || defined(__mips_n32) +_Static_assert(TLBLO_PFN_MASK == MIPS64_PFN_MASK, "TLBLO_PFN_MASK mismatch"); +#else +_Static_assert(TLBLO_PFN_MASK == MIPS32_PFN_MASK, "TLBLO_PFN_MASK mismatch"); +#endif +_Static_assert(TLBLO_PFN_SHIFT == MIPS_PFN_SHIFT, "TLBLO_PFN_SHIFT mismatch"); +_Static_assert(TLB_PAGE_SHIFT == MIPS_PAGE_SHIFT, "TLB_PAGE_SHIFT mismatch"); +#endif + +#endif /* !__KVM_MIPS_H__ */ Property changes on: head/lib/libkvm/kvm_mips.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_native.3 =================================================================== --- head/lib/libkvm/kvm_native.3 (nonexistent) +++ head/lib/libkvm/kvm_native.3 (revision 291406) @@ -0,0 +1,62 @@ +.\" +.\" Copyright (c) 2015 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. +.\" +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd November 27, 2015 +.Dt kvm_native 3 +.Os +.Sh NAME +.Nm kvm_native +.Nd is a kvm descriptor opened on a native kernel image +.Sh LIBRARY +.Lb libkvm +.Sh SYNOPSIS +.In kvm.h +.Ft int +.Fn kvm_native "kvm_t *kd" +.Sh DESCRIPTION +The +.Nm kvm +library provides an interface for accessing kernel virtual memory images +for both native kernel images +.Pq where the ABI of the kernel executable matches the host system +and non-native kernel images. +The +.Fn kvm_native +function returns a non-zero value if the kvm descriptor +.Fa kd +is attached to a native kernel image; +otherwise it returns zero. +.Sh RETURN VALUES +The +.Fn kvm_native +function returns a non-zero value if the kvm descriptor +.Fa kd +is attached to a native kernel image; +otherwise it returns zero. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_open2 3 Property changes on: head/lib/libkvm/kvm_native.3 ___________________________________________________________________ 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: head/lib/libkvm/kvm_nlist.3 =================================================================== --- head/lib/libkvm/kvm_nlist.3 (revision 291405) +++ head/lib/libkvm/kvm_nlist.3 (revision 291406) @@ -1,85 +1,118 @@ .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software developed by the Computer Systems .\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract .\" BG 91-66 and contributed to Berkeley. .\" .\" 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. .\" .\" @(#)kvm_nlist.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd November 27, 2015 .Dt KVM_NLIST 3 .Os .Sh NAME -.Nm kvm_nlist +.Nm kvm_nlist , +.Nm kvm_nlist2 .Nd retrieve symbol table names from a kernel image .Sh LIBRARY .Lb libkvm .Sh SYNOPSIS .In kvm.h .In nlist.h .Ft int .Fn kvm_nlist "kvm_t *kd" "struct nlist *nl" +.Ft int +.Fn kvm_nlist2 "kvm_t *kd" "struct kvm_nlist *nl" .Sh DESCRIPTION The .Fn kvm_nlist function retrieves the symbol table entries indicated by the name list argument .Fa \&nl . This argument points to an array of nlist structures, terminated by -an entry whose n_name field is +an entry whose +.Fa n_name +field is .Dv NULL (see .Xr nlist 3 ) . -Each symbol is looked up using the n_name field, and if found, the -corresponding n_type and n_value fields are filled in. +Each symbol is looked up using the +.Fa n_name +field, and if found, the +corresponding +.Fa n_type +and +.Fa n_value +fields are filled in. These fields are set to 0 if the symbol is not found. .Pp The .Xr kldsym 2 -system call is used to locate the symbol. +system call is used to locate symbols in live kernels. This is a less than perfect emulation of the nlist values but has the advantage of being aware of kernel modules and is reasonably fast. +.Pp +The +.Fn kvm_nlist2 +function retrieves the symbol table entries indicated by the name list argument +.Fa nl . +This argument points to an array of +.Vt "struct kvm_nlist" +structures, +terminated by an entry whose +.Fa n_name +field is +.Dv NULL +These structures are similar to the nlist structures used by +.Fn kvm_nlist +except that the +.Fa n_value +field uses a different type +.Pq Vt kvaddr_t +to avoid truncation when examining non-native kernel images. .Sh RETURN VALUES The .Fn kvm_nlist -function returns the number of invalid entries found. +and +.Fn kvm_nlist2 +functions return the number of invalid entries found. If the kernel symbol table was unreadable, -1 is returned. .Sh SEE ALSO .Xr kldsym 2 , .Xr kvm 3 , .Xr kvm_close 3 , .Xr kvm_getargv 3 , .Xr kvm_getenvv 3 , .Xr kvm_geterr 3 , .Xr kvm_getprocs 3 , +.Xr kvm_native 3 , .Xr kvm_open 3 , .Xr kvm_openfiles 3 , .Xr kvm_read 3 , .Xr kvm_write 3 Index: head/lib/libkvm/kvm_open.3 =================================================================== --- head/lib/libkvm/kvm_open.3 (revision 291405) +++ head/lib/libkvm/kvm_open.3 (revision 291406) @@ -1,205 +1,252 @@ .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software developed by the Computer Systems .\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract .\" BG 91-66 and contributed to Berkeley. .\" .\" 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. .\" .\" @(#)kvm_open.3 8.3 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd January 29, 2004 +.Dd November 27, 2015 .Dt KVM_OPEN 3 .Os .Sh NAME .Nm kvm_open , +.Nm kvm_open2 , .Nm kvm_openfiles , .Nm kvm_close .Nd initialize kernel virtual memory access .Sh LIBRARY .Lb libkvm .Sh SYNOPSIS .In fcntl.h .In kvm.h .Ft kvm_t * .Fn kvm_open "const char *execfile" "const char *corefile" "const char *swapfile" "int flags" "const char *errstr" .Ft kvm_t * +.Fo kvm_open2 +.Fa "const char *execfile" +.Fa "const char *corefile" +.Fa "int flags" +.Fa "char *errbuf" +.Fa "int (*resolver)(const char *name, kvaddr_t *addr)" +.Fc +.Ft kvm_t * .Fn kvm_openfiles "const char *execfile" "const char *corefile" "const char *swapfile" "int flags" "char *errbuf" .Ft int .Fn kvm_close "kvm_t *kd" .Sh DESCRIPTION The functions -.Fn kvm_open +.Fn kvm_open , +.Fn kvm_open2 , and .Fn kvm_openfiles return a descriptor used to access kernel virtual memory via the .Xr kvm 3 library routines. Both active kernels and crash dumps are accessible through this interface. .Pp The .Fa execfile argument is the executable image of the kernel being examined. This file must contain a symbol table. If this argument is .Dv NULL , the currently running system is assumed, as determined from .Xr getbootfile 3 . .Pp The .Fa corefile argument is the kernel memory device file. It can be either .Pa /dev/mem or a crash dump core generated by .Xr savecore 8 . If .Fa corefile is .Dv NULL , the default indicated by .Dv _PATH_MEM from .In paths.h is used. It can also be set to a special value .Pa /dev/null by utilities like .Xr ps 1 that do not directly access kernel memory. .Pp The .Fa swapfile argument is currently unused. .Pp The .Fa flags argument indicates read/write access as in .Xr open 2 and applies only to the core file. Only .Dv O_RDONLY , .Dv O_WRONLY , and .Dv O_RDWR are permitted. .Pp -There are two open routines which differ only with respect to -the error mechanism. +The +.Nm kvm +library provides two different error reporting mechanisms. One provides backward compatibility with the SunOS kvm library, while the other provides an improved error reporting framework. +The mechanism used by a descriptor is determined by the function used to +open the descriptor. .Pp The .Fn kvm_open function is the Sun kvm compatible open call. Here, the .Fa errstr argument indicates how errors should be handled. If it is .Dv NULL , no errors are reported and the application cannot know the specific nature of the failed kvm call. If it is not .Dv NULL , errors are printed to .Dv stderr with .Fa errstr prepended to the message, as in .Xr perror 3 . Normally, the name of the program is used here. The string is assumed to persist at least until the corresponding .Fn kvm_close call. .Pp The +.Fn kvm_open2 +and .Fn kvm_openfiles -function provides +functions provide .Bx style error reporting. Here, error messages are not printed out by the library. Instead, the application obtains the error message corresponding to the most recent kvm library call using .Fn kvm_geterr (see .Xr kvm_geterr 3 ) . The results are undefined if the most recent kvm call did not produce an error. Since .Fn kvm_geterr requires a kvm descriptor, but the open routines return .Dv NULL on failure, .Fn kvm_geterr cannot be used to get the error message if open fails. Thus, +.Fn kvm_open2 +and .Fn kvm_openfiles will place any error message in the .Fa errbuf argument. This buffer should be _POSIX2_LINE_MAX characters large (from ). +.Pp +The +.Fa resolver +argument points to a function used by the +.Nm kvm +library to map symbol names to kernel virtual addresses. +When the +.Fa resolver +function is called, +.Fa name +specifies the requested symbol name. +If the function is able to resolve the name to an address, +the address should be set in +.Fa *addr +and the function should return zero. +If the function is not able to resolve the name to an address, +it should return a non-zero value. +When opening a native kernel image, +.Fa resolver +may be set to +.Dv NULL +to use an internal function to resolve symbol names. +Non-native kernel images +.Pq such as when cross-debugging a crash dump +require a valid +.Fa resolver . .Sh RETURN VALUES The -.Fn kvm_open +.Fn kvm_open , +.Fn kvm_open2 , and .Fn kvm_openfiles -functions both return a descriptor to be used +functions return a descriptor to be used in all subsequent kvm library calls. The library is fully re-entrant. On failure, .Dv NULL is returned, in which case +.Fn kvm_open2 +and .Fn kvm_openfiles -writes the error message into +write the error message into .Fa errbuf . .Pp The .Fn kvm_close function returns 0 on success and -1 on failure. .Sh SEE ALSO .Xr open 2 , .Xr kvm 3 , .Xr kvm_getargv 3 , .Xr kvm_getenvv 3 , .Xr kvm_geterr 3 , .Xr kvm_getprocs 3 , +.Xr kvm_native 3 , .Xr kvm_nlist 3 , .Xr kvm_read 3 , .Xr kvm_write 3 , .Xr kmem 4 , .Xr mem 4 .Sh BUGS -There should not be two open calls. +There should not be three open calls. The ill-defined error semantics of the Sun library and the desire to have a backward-compatible library for .Bx left little choice. Index: head/lib/libkvm/kvm_pcpu.c =================================================================== --- head/lib/libkvm/kvm_pcpu.c (revision 291405) +++ head/lib/libkvm/kvm_pcpu.c (revision 291406) @@ -1,346 +1,354 @@ /*- * Copyright (c) 2013 Gleb Smirnoff * Copyright (c) 2010 Juniper Networks, Inc. * Copyright (c) 2009 Robert N. M. Watson * Copyright (c) 2009 Bjoern A. Zeeb * Copyright (c) 2008 Yahoo!, Inc. * All rights reserved. * * Written by: John Baldwin * * This software was developed by Robert N. M. Watson under contract * to Juniper Networks, 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. * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "kvm_private.h" static struct nlist kvm_pcpu_nl[] = { { .n_name = "_cpuid_to_pcpu" }, { .n_name = "_mp_maxcpus" }, { .n_name = "_mp_ncpus" }, { .n_name = NULL }, }; #define NL_CPUID_TO_PCPU 0 #define NL_MP_MAXCPUS 1 #define NL_MP_NCPUS 2 /* * Kernel per-CPU data state. We cache this stuff on the first * access. * * XXXRW: Possibly, this (and kvmpcpu_nl) should be per-kvm_t, in case the * consumer has multiple handles in flight to differently configured * kernels/crashdumps. */ static void **pcpu_data; static int maxcpu; static int mp_ncpus; static int _kvm_pcpu_init(kvm_t *kd) { size_t len; int max; void *data; if (kvm_nlist(kd, kvm_pcpu_nl) < 0) return (-1); if (kvm_pcpu_nl[NL_CPUID_TO_PCPU].n_value == 0) { _kvm_err(kd, kd->program, "unable to find cpuid_to_pcpu"); return (-1); } if (kvm_pcpu_nl[NL_MP_MAXCPUS].n_value == 0) { _kvm_err(kd, kd->program, "unable to find mp_maxcpus"); return (-1); } if (kvm_read(kd, kvm_pcpu_nl[NL_MP_MAXCPUS].n_value, &max, sizeof(max)) != sizeof(max)) { _kvm_err(kd, kd->program, "cannot read mp_maxcpus"); return (-1); } if (kvm_pcpu_nl[NL_MP_NCPUS].n_value == 0) { _kvm_err(kd, kd->program, "unable to find mp_ncpus"); return (-1); } if (kvm_read(kd, kvm_pcpu_nl[NL_MP_NCPUS].n_value, &mp_ncpus, sizeof(mp_ncpus)) != sizeof(mp_ncpus)) { _kvm_err(kd, kd->program, "cannot read mp_ncpus"); return (-1); } len = max * sizeof(void *); data = malloc(len); if (data == NULL) { _kvm_err(kd, kd->program, "out of memory"); return (-1); } if (kvm_read(kd, kvm_pcpu_nl[NL_CPUID_TO_PCPU].n_value, data, len) != (ssize_t)len) { _kvm_err(kd, kd->program, "cannot read cpuid_to_pcpu array"); free(data); return (-1); } pcpu_data = data; maxcpu = max; return (0); } static void _kvm_pcpu_clear(void) { maxcpu = 0; free(pcpu_data); pcpu_data = NULL; } void * kvm_getpcpu(kvm_t *kd, int cpu) { char *buf; if (kd == NULL) { _kvm_pcpu_clear(); return (NULL); } if (maxcpu == 0) if (_kvm_pcpu_init(kd) < 0) return ((void *)-1); if (cpu >= maxcpu || pcpu_data[cpu] == NULL) return (NULL); buf = malloc(sizeof(struct pcpu)); if (buf == NULL) { _kvm_err(kd, kd->program, "out of memory"); return ((void *)-1); } if (kvm_read(kd, (uintptr_t)pcpu_data[cpu], buf, sizeof(struct pcpu)) != sizeof(struct pcpu)) { _kvm_err(kd, kd->program, "unable to read per-CPU data"); free(buf); return ((void *)-1); } return (buf); } int kvm_getmaxcpu(kvm_t *kd) { if (kd == NULL) { _kvm_pcpu_clear(); return (0); } if (maxcpu == 0) if (_kvm_pcpu_init(kd) < 0) return (-1); return (maxcpu); } int kvm_getncpus(kvm_t *kd) { if (mp_ncpus == 0) if (_kvm_pcpu_init(kd) < 0) return (-1); return (mp_ncpus); } static int _kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu, int report_error) { if (!kd->dpcpu_initialized) { if (report_error) _kvm_err(kd, kd->program, "%s: not initialized", __func__); return (-1); } if (cpu >= kd->dpcpu_maxcpus) { if (report_error) _kvm_err(kd, kd->program, "%s: CPU %u too big", __func__, cpu); return (-1); } if (kd->dpcpu_off[cpu] == 0) { if (report_error) _kvm_err(kd, kd->program, "%s: CPU %u not found", __func__, cpu); return (-1); } kd->dpcpu_curcpu = cpu; kd->dpcpu_curoff = kd->dpcpu_off[cpu]; return (0); } /* * Set up libkvm to handle dynamic per-CPU memory. */ static int _kvm_dpcpu_init(kvm_t *kd) { - struct nlist nl[] = { + struct kvm_nlist nl[] = { #define NLIST_START_SET_PCPU 0 { .n_name = "___start_" DPCPU_SETNAME }, #define NLIST_STOP_SET_PCPU 1 { .n_name = "___stop_" DPCPU_SETNAME }, #define NLIST_DPCPU_OFF 2 { .n_name = "_dpcpu_off" }, #define NLIST_MP_MAXCPUS 3 { .n_name = "_mp_maxcpus" }, { .n_name = NULL }, }; uintptr_t *dpcpu_off_buf; size_t len; u_int dpcpu_maxcpus; /* + * XXX: This only works for native kernels for now. + */ + if (!kvm_native(kd)) + return (-1); + + /* * Locate and cache locations of important symbols using the internal * version of _kvm_nlist, turning off initialization to avoid * recursion in case of unresolveable symbols. */ if (_kvm_nlist(kd, nl, 0) != 0) return (-1); if (kvm_read(kd, nl[NLIST_MP_MAXCPUS].n_value, &dpcpu_maxcpus, sizeof(dpcpu_maxcpus)) != sizeof(dpcpu_maxcpus)) return (-1); len = dpcpu_maxcpus * sizeof(*dpcpu_off_buf); dpcpu_off_buf = malloc(len); if (dpcpu_off_buf == NULL) return (-1); if (kvm_read(kd, nl[NLIST_DPCPU_OFF].n_value, dpcpu_off_buf, len) != (ssize_t)len) { free(dpcpu_off_buf); return (-1); } kd->dpcpu_start = nl[NLIST_START_SET_PCPU].n_value; kd->dpcpu_stop = nl[NLIST_STOP_SET_PCPU].n_value; kd->dpcpu_maxcpus = dpcpu_maxcpus; kd->dpcpu_off = dpcpu_off_buf; kd->dpcpu_initialized = 1; (void)_kvm_dpcpu_setcpu(kd, 0, 0); return (0); } /* * Check whether the dpcpu module has been initialized sucessfully or not, * initialize it if permitted. */ int _kvm_dpcpu_initialized(kvm_t *kd, int intialize) { if (kd->dpcpu_initialized || !intialize) return (kd->dpcpu_initialized); (void)_kvm_dpcpu_init(kd); return (kd->dpcpu_initialized); } /* * Check whether the value is within the dpcpu symbol range and only if so * adjust the offset relative to the current offset. */ -uintptr_t -_kvm_dpcpu_validaddr(kvm_t *kd, uintptr_t value) +kvaddr_t +_kvm_dpcpu_validaddr(kvm_t *kd, kvaddr_t value) { if (value == 0) return (value); if (!kd->dpcpu_initialized) return (value); if (value < kd->dpcpu_start || value >= kd->dpcpu_stop) return (value); return (kd->dpcpu_curoff + value); } int kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu) { int ret; if (!kd->dpcpu_initialized) { ret = _kvm_dpcpu_init(kd); if (ret != 0) { _kvm_err(kd, kd->program, "%s: init failed", __func__); return (ret); } } return (_kvm_dpcpu_setcpu(kd, cpu, 1)); } /* * Obtain a per-CPU copy for given cpu from UMA_ZONE_PCPU allocation. */ ssize_t kvm_read_zpcpu(kvm_t *kd, u_long base, void *buf, size_t size, int cpu) { + if (!kvm_native(kd)) + return (-1); return (kvm_read(kd, (uintptr_t)(base + sizeof(struct pcpu) * cpu), buf, size)); } /* * Fetch value of a counter(9). */ uint64_t kvm_counter_u64_fetch(kvm_t *kd, u_long base) { uint64_t r, c; if (mp_ncpus == 0) if (_kvm_pcpu_init(kd) < 0) return (0); r = 0; for (int i = 0; i < mp_ncpus; i++) { if (kvm_read_zpcpu(kd, base, &c, sizeof(c), i) != sizeof(c)) return (0); r += c; } return (r); } Index: head/lib/libkvm/kvm_powerpc.c =================================================================== --- head/lib/libkvm/kvm_powerpc.c (revision 291405) +++ head/lib/libkvm/kvm_powerpc.c (revision 291406) @@ -1,219 +1,235 @@ /*- * Copyright (c) 2008, Juniper Networks, Inc. * 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 ``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 #include "kvm_private.h" struct vmstate { void *map; size_t mapsz; size_t dmphdrsz; Elf32_Ehdr *eh; Elf32_Phdr *ph; }; static int valid_elf_header(Elf32_Ehdr *eh) { if (!IS_ELF(*eh)) return (0); if (eh->e_ident[EI_CLASS] != ELFCLASS32) return (0); if (eh->e_ident[EI_DATA] != ELFDATA2MSB) return (0); if (eh->e_ident[EI_VERSION] != EV_CURRENT) return (0); if (eh->e_ident[EI_OSABI] != ELFOSABI_STANDALONE) return (0); if (be16toh(eh->e_type) != ET_CORE) return (0); if (be16toh(eh->e_machine) != EM_PPC) return (0); /* Can't think of anything else to check... */ return (1); } static size_t dump_header_size(struct kerneldumpheader *dh) { if (strcmp(dh->magic, KERNELDUMPMAGIC) != 0) return (0); if (strcmp(dh->architecture, "powerpc") != 0) return (0); /* That should do it... */ return (sizeof(*dh)); } /* * Map the ELF headers into the process' address space. We do this in two * steps: first the ELF header itself and using that information the whole * set of headers. */ static int powerpc_maphdrs(kvm_t *kd) { struct vmstate *vm; size_t mapsz; vm = kd->vmst; - vm->mapsz = PAGE_SIZE; + vm->mapsz = sizeof(*vm->eh) + sizeof(struct kerneldumpheader); vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); if (vm->map == MAP_FAILED) { _kvm_err(kd, kd->program, "cannot map corefile"); return (-1); } vm->dmphdrsz = 0; vm->eh = vm->map; if (!valid_elf_header(vm->eh)) { /* * Hmmm, no ELF header. Maybe we still have a dump header. * This is normal when the core file wasn't created by * savecore(8), but instead was dumped over TFTP. We can * easily skip the dump header... */ vm->dmphdrsz = dump_header_size(vm->map); if (vm->dmphdrsz == 0) goto inval; vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); if (!valid_elf_header(vm->eh)) goto inval; } mapsz = be16toh(vm->eh->e_phentsize) * be16toh(vm->eh->e_phnum) + be32toh(vm->eh->e_phoff); munmap(vm->map, vm->mapsz); /* Map all headers. */ vm->mapsz = vm->dmphdrsz + mapsz; vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); if (vm->map == MAP_FAILED) { - _kvm_err(kd, kd->program, "cannot map corefle headers"); + _kvm_err(kd, kd->program, "cannot map corefile headers"); return (-1); } vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); vm->ph = (void *)((uintptr_t)vm->eh + be32toh(vm->eh->e_phoff)); return (0); inval: - munmap(vm->map, vm->mapsz); - vm->map = MAP_FAILED; _kvm_err(kd, kd->program, "invalid corefile"); return (-1); } /* * Determine the offset within the corefile corresponding the virtual * address. Return the number of contiguous bytes in the corefile or * 0 when the virtual address is invalid. */ static size_t -powerpc_va2off(kvm_t *kd, u_long va, off_t *ofs) +powerpc_va2off(kvm_t *kd, kvaddr_t va, off_t *ofs) { struct vmstate *vm = kd->vmst; Elf32_Phdr *ph; int nph; ph = vm->ph; nph = be16toh(vm->eh->e_phnum); while (nph && (va < be32toh(ph->p_vaddr) || va >= be32toh(ph->p_vaddr) + be32toh(ph->p_memsz))) { nph--; ph = (void *)((uintptr_t)ph + be16toh(vm->eh->e_phentsize)); } if (nph == 0) return (0); /* Segment found. Return file offset and range. */ *ofs = vm->dmphdrsz + be32toh(ph->p_offset) + (va - be32toh(ph->p_vaddr)); return (be32toh(ph->p_memsz) - (va - be32toh(ph->p_vaddr))); } -void -_kvm_freevtop(kvm_t *kd) +static void +_powerpc_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm == NULL) - return; - - if (vm->eh != MAP_FAILED) { + if (vm->eh != MAP_FAILED) munmap(vm->eh, vm->mapsz); - vm->eh = MAP_FAILED; - } free(vm); kd->vmst = NULL; } -int -_kvm_initvtop(kvm_t *kd) +static int +_powerpc_probe(kvm_t *kd) { + return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_PPC) && + kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB); +} + +static int +_powerpc_initvtop(kvm_t *kd) +{ + kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); - if (kd->vmst == NULL) { - _kvm_err(kd, kd->program, "out of virtual memory"); + if (kd->vmst == NULL) return (-1); - } - if (powerpc_maphdrs(kd) == -1) { - free(kd->vmst); - kd->vmst = NULL; + + if (powerpc_maphdrs(kd) == -1) return (-1); - } + return (0); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *ofs) +static int +_powerpc_kvatop(kvm_t *kd, kvaddr_t va, off_t *ofs) { struct vmstate *vm; vm = kd->vmst; - if (vm->ph->p_paddr == ~0U) + if (be32toh(vm->ph->p_paddr) == 0xffffffff) return ((int)powerpc_va2off(kd, va, ofs)); _kvm_err(kd, kd->program, "Raw corefile not supported"); return (0); } + +static int +_powerpc_native(kvm_t *kd) +{ + +#if defined(__powerpc__) && !defined(__powerpc64__) + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_powerpc = { + .ka_probe = _powerpc_probe, + .ka_initvtop = _powerpc_initvtop, + .ka_freevtop = _powerpc_freevtop, + .ka_kvatop = _powerpc_kvatop, + .ka_native = _powerpc_native, +}; + +KVM_ARCH(kvm_powerpc); Index: head/lib/libkvm/kvm_powerpc64.c =================================================================== --- head/lib/libkvm/kvm_powerpc64.c (revision 291405) +++ head/lib/libkvm/kvm_powerpc64.c (revision 291406) @@ -1,219 +1,236 @@ /*- * Copyright (c) 2008, Juniper Networks, Inc. * 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 ``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 #include "kvm_private.h" struct vmstate { void *map; size_t mapsz; size_t dmphdrsz; Elf64_Ehdr *eh; Elf64_Phdr *ph; }; static int valid_elf_header(Elf64_Ehdr *eh) { if (!IS_ELF(*eh)) return (0); if (eh->e_ident[EI_CLASS] != ELFCLASS64) return (0); if (eh->e_ident[EI_DATA] != ELFDATA2MSB) return (0); if (eh->e_ident[EI_VERSION] != EV_CURRENT) return (0); if (eh->e_ident[EI_OSABI] != ELFOSABI_STANDALONE) return (0); if (be16toh(eh->e_type) != ET_CORE) return (0); if (be16toh(eh->e_machine) != EM_PPC64) return (0); /* Can't think of anything else to check... */ return (1); } static size_t dump_header_size(struct kerneldumpheader *dh) { if (strcmp(dh->magic, KERNELDUMPMAGIC) != 0) return (0); if (strcmp(dh->architecture, "powerpc64") != 0) return (0); /* That should do it... */ return (sizeof(*dh)); } /* * Map the ELF headers into the process' address space. We do this in two * steps: first the ELF header itself and using that information the whole * set of headers. */ static int powerpc_maphdrs(kvm_t *kd) { struct vmstate *vm; size_t mapsz; vm = kd->vmst; - vm->mapsz = PAGE_SIZE; + vm->mapsz = sizeof(*vm->eh) + sizeof(struct kerneldumpheader); vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); if (vm->map == MAP_FAILED) { _kvm_err(kd, kd->program, "cannot map corefile"); return (-1); } vm->dmphdrsz = 0; vm->eh = vm->map; if (!valid_elf_header(vm->eh)) { /* * Hmmm, no ELF header. Maybe we still have a dump header. * This is normal when the core file wasn't created by * savecore(8), but instead was dumped over TFTP. We can * easily skip the dump header... */ vm->dmphdrsz = dump_header_size(vm->map); if (vm->dmphdrsz == 0) goto inval; vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); if (!valid_elf_header(vm->eh)) goto inval; } mapsz = be16toh(vm->eh->e_phentsize) * be16toh(vm->eh->e_phnum) + be64toh(vm->eh->e_phoff); munmap(vm->map, vm->mapsz); /* Map all headers. */ vm->mapsz = vm->dmphdrsz + mapsz; vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); if (vm->map == MAP_FAILED) { - _kvm_err(kd, kd->program, "cannot map corefle headers"); + _kvm_err(kd, kd->program, "cannot map corefile headers"); return (-1); } vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); - vm->ph = (void *)((uintptr_t)vm->eh + be64toh(vm->eh->e_phoff)); + vm->ph = (void *)((uintptr_t)vm->eh + + (uintptr_t)be64toh(vm->eh->e_phoff)); return (0); inval: - munmap(vm->map, vm->mapsz); - vm->map = MAP_FAILED; _kvm_err(kd, kd->program, "invalid corefile"); return (-1); } /* * Determine the offset within the corefile corresponding the virtual * address. Return the number of contiguous bytes in the corefile or * 0 when the virtual address is invalid. */ static size_t -powerpc64_va2off(kvm_t *kd, u_long va, off_t *ofs) +powerpc64_va2off(kvm_t *kd, kvaddr_t va, off_t *ofs) { struct vmstate *vm = kd->vmst; Elf64_Phdr *ph; int nph; ph = vm->ph; nph = be16toh(vm->eh->e_phnum); while (nph && (va < be64toh(ph->p_vaddr) || va >= be64toh(ph->p_vaddr) + be64toh(ph->p_memsz))) { nph--; ph = (void *)((uintptr_t)ph + be16toh(vm->eh->e_phentsize)); } if (nph == 0) return (0); /* Segment found. Return file offset and range. */ *ofs = vm->dmphdrsz + be64toh(ph->p_offset) + (va - be64toh(ph->p_vaddr)); return (be64toh(ph->p_memsz) - (va - be64toh(ph->p_vaddr))); } -void -_kvm_freevtop(kvm_t *kd) +static void +_powerpc64_freevtop(kvm_t *kd) { struct vmstate *vm = kd->vmst; - if (vm == NULL) - return; - - if (vm->eh != MAP_FAILED) { + if (vm->eh != MAP_FAILED) munmap(vm->eh, vm->mapsz); - vm->eh = MAP_FAILED; - } free(vm); kd->vmst = NULL; } -int -_kvm_initvtop(kvm_t *kd) +static int +_powerpc64_probe(kvm_t *kd) { + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_PPC64) && + kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB); +} + +static int +_powerpc64_initvtop(kvm_t *kd) +{ + kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); - if (kd->vmst == NULL) { - _kvm_err(kd, kd->program, "out of virtual memory"); + if (kd->vmst == NULL) return (-1); - } - if (powerpc_maphdrs(kd) == -1) { - free(kd->vmst); - kd->vmst = NULL; + + if (powerpc_maphdrs(kd) == -1) return (-1); - } + return (0); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *ofs) +static int +_powerpc64_kvatop(kvm_t *kd, kvaddr_t va, off_t *ofs) { struct vmstate *vm; vm = kd->vmst; - if (vm->ph->p_paddr == ~0UL) + if (be64toh(vm->ph->p_paddr) == 0xffffffffffffffff) return ((int)powerpc64_va2off(kd, va, ofs)); _kvm_err(kd, kd->program, "Raw corefile not supported"); return (0); } + +static int +_powerpc64_native(kvm_t *kd) +{ + +#ifdef __powerpc64__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_powerpc64 = { + .ka_probe = _powerpc64_probe, + .ka_initvtop = _powerpc64_initvtop, + .ka_freevtop = _powerpc64_freevtop, + .ka_kvatop = _powerpc64_kvatop, + .ka_native = _powerpc64_native, +}; + +KVM_ARCH(kvm_powerpc64); Index: head/lib/libkvm/kvm_private.h =================================================================== --- head/lib/libkvm/kvm_private.h (revision 291405) +++ head/lib/libkvm/kvm_private.h (revision 291406) @@ -1,112 +1,159 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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. * * @(#)kvm_private.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ +#include +#include +#include + +struct kvm_arch { + int (*ka_probe)(kvm_t *); + int (*ka_initvtop)(kvm_t *); + void (*ka_freevtop)(kvm_t *); + int (*ka_kvatop)(kvm_t *, kvaddr_t, off_t *); + int (*ka_native)(kvm_t *); +}; + +#define KVM_ARCH(ka) DATA_SET(kvm_arch, ka) + struct __kvm { + struct kvm_arch *arch; /* * a string to be prepended to error messages * provided for compatibility with sun's interface * if this value is null, errors are saved in errbuf[] */ const char *program; char *errp; /* XXX this can probably go away */ char errbuf[_POSIX2_LINE_MAX]; #define ISALIVE(kd) ((kd)->vmfd >= 0) int pmfd; /* physical memory file (or crashdump) */ int vmfd; /* virtual memory file (-1 if crashdump) */ - int unused; /* was: swap file (e.g., /dev/drum) */ int nlfd; /* namelist file (e.g., /kernel) */ + GElf_Ehdr nlehdr; /* ELF file header for namelist file */ + int (*resolve_symbol)(const char *, kvaddr_t *); struct kinfo_proc *procbase; char *argspc; /* (dynamic) storage for argv strings */ int arglen; /* length of the above */ char **argv; /* (dynamic) storage for argv pointers */ int argc; /* length of above (not actual # present) */ char *argbuf; /* (dynamic) temporary storage */ /* * Kernel virtual address translation state. This only gets filled * in for dead kernels; otherwise, the running kernel (i.e. kmem) * will do the translations for us. It could be big, so we * only allocate it if necessary. */ struct vmstate *vmst; int rawdump; /* raw dump format */ int vnet_initialized; /* vnet fields set up */ - uintptr_t vnet_start; /* start of kernel's vnet region */ - uintptr_t vnet_stop; /* stop of kernel's vnet region */ - uintptr_t vnet_current; /* vnet we're working with */ - uintptr_t vnet_base; /* vnet base of current vnet */ + kvaddr_t vnet_start; /* start of kernel's vnet region */ + kvaddr_t vnet_stop; /* stop of kernel's vnet region */ + kvaddr_t vnet_current; /* vnet we're working with */ + kvaddr_t vnet_base; /* vnet base of current vnet */ /* * Dynamic per-CPU kernel memory. We translate symbols, on-demand, * to the data associated with dpcpu_curcpu, set with * kvm_dpcpu_setcpu(). */ int dpcpu_initialized; /* dpcpu fields set up */ - uintptr_t dpcpu_start; /* start of kernel's dpcpu region */ - uintptr_t dpcpu_stop; /* stop of kernel's dpcpu region */ + kvaddr_t dpcpu_start; /* start of kernel's dpcpu region */ + kvaddr_t dpcpu_stop; /* stop of kernel's dpcpu region */ u_int dpcpu_maxcpus; /* size of base array */ uintptr_t *dpcpu_off; /* base array, indexed by CPU ID */ u_int dpcpu_curcpu; /* CPU we're currently working with */ - uintptr_t dpcpu_curoff; /* dpcpu base of current CPU */ + kvaddr_t dpcpu_curoff; /* dpcpu base of current CPU */ }; /* + * Page table hash used by minidump backends to map physical addresses + * to file offsets. + */ +struct hpte { + struct hpte *next; + uint64_t pa; + off_t off; +}; + +#define HPT_SIZE 1024 + +struct hpt { + struct hpte *hpt_head[HPT_SIZE]; +}; + +/* * Functions used internally by kvm, but across kvm modules. */ +static inline uint32_t +_kvm32toh(kvm_t *kd, uint32_t val) +{ + + if (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return (le32toh(val)); + else + return (be32toh(val)); +} + +static inline uint64_t +_kvm64toh(kvm_t *kd, uint64_t val) +{ + + if (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB) + return (le64toh(val)); + else + return (be64toh(val)); +} + void _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) __printflike(3, 4); void _kvm_freeprocs(kvm_t *kd); -void _kvm_freevtop(kvm_t *); -int _kvm_initvtop(kvm_t *); -int _kvm_kvatop(kvm_t *, u_long, off_t *); void *_kvm_malloc(kvm_t *kd, size_t); -int _kvm_nlist(kvm_t *, struct nlist *, int); +int _kvm_nlist(kvm_t *, struct kvm_nlist *, int); void *_kvm_realloc(kvm_t *kd, void *, size_t); void _kvm_syserr (kvm_t *kd, const char *program, const char *fmt, ...) __printflike(3, 4); -int _kvm_uvatop(kvm_t *, const struct proc *, u_long, u_long *); int _kvm_vnet_selectpid(kvm_t *, pid_t); int _kvm_vnet_initialized(kvm_t *, int); -uintptr_t _kvm_vnet_validaddr(kvm_t *, uintptr_t); +kvaddr_t _kvm_vnet_validaddr(kvm_t *, kvaddr_t); int _kvm_dpcpu_initialized(kvm_t *, int); -uintptr_t _kvm_dpcpu_validaddr(kvm_t *, uintptr_t); - -#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \ - defined(__i386__) || defined(__mips__) -void _kvm_minidump_freevtop(kvm_t *); -int _kvm_minidump_initvtop(kvm_t *); -int _kvm_minidump_kvatop(kvm_t *, u_long, off_t *); -#endif +kvaddr_t _kvm_dpcpu_validaddr(kvm_t *, kvaddr_t); +int _kvm_probe_elf_kernel(kvm_t *, int, int); +int _kvm_is_minidump(kvm_t *); +int _kvm_read_core_phdrs(kvm_t *, size_t *, GElf_Phdr **); +void _kvm_hpt_init(kvm_t *, struct hpt *, void *, size_t, off_t, int, int); +off_t _kvm_hpt_find(struct hpt *, uint64_t); +void _kvm_hpt_free(struct hpt *); Index: head/lib/libkvm/kvm_proc.c =================================================================== --- head/lib/libkvm/kvm_proc.c (revision 291405) +++ head/lib/libkvm/kvm_proc.c (revision 291406) @@ -1,734 +1,740 @@ /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93"; #endif /* LIBC_SCCS and not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * Proc traversal interface for kvm. ps and w are (probably) the exclusive * users of this code, so we've factored it out into a separate module. * Thus, we keep this grunge out of the other kvm applications (i.e., * most other applications are interested only in open/close/read/nlist). */ #include #define _WANT_UCRED /* make ucred.h give us 'struct ucred' */ #include #include #include #include #include #include #include #include #define _WANT_PRISON /* make jail.h give us 'struct prison' */ #include #include #include #include #include #include #include #include #define _WANT_KW_EXITCODE #include #include #include #include #include #include #include #include #include #include #include "kvm_private.h" #define KREAD(kd, addr, obj) \ (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) static int ticks; static int hz; static uint64_t cpu_tick_frequency; /* * From sys/kern/kern_tc.c. Depends on cpu_tick_frequency, which is * read/initialized before this function is ever called. */ static uint64_t cputick2usec(uint64_t tick) { if (cpu_tick_frequency == 0) return (0); if (tick > 18446744073709551) /* floor(2^64 / 1000) */ return (tick / (cpu_tick_frequency / 1000000)); else if (tick > 18446744073709) /* floor(2^64 / 1000000) */ return ((tick * 1000) / (cpu_tick_frequency / 1000)); else return ((tick * 1000000) / cpu_tick_frequency); } /* * Read proc's from memory file into buffer bp, which has space to hold * at most maxcnt procs. */ static int kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p, struct kinfo_proc *bp, int maxcnt) { int cnt = 0; struct kinfo_proc kinfo_proc, *kp; struct pgrp pgrp; struct session sess; struct cdev t_cdev; struct tty tty; struct vmspace vmspace; struct sigacts sigacts; #if 0 struct pstats pstats; #endif struct ucred ucred; struct prison pr; struct thread mtd; struct proc proc; struct proc pproc; struct sysentvec sysent; char svname[KI_EMULNAMELEN]; kp = &kinfo_proc; kp->ki_structsize = sizeof(kinfo_proc); /* * Loop on the processes. this is completely broken because we need to be * able to loop on the threads and merge the ones that are the same process some how. */ for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) { memset(kp, 0, sizeof *kp); if (KREAD(kd, (u_long)p, &proc)) { _kvm_err(kd, kd->program, "can't read proc at %p", p); return (-1); } if (proc.p_state == PRS_NEW) continue; if (proc.p_state != PRS_ZOMBIE) { if (KREAD(kd, (u_long)TAILQ_FIRST(&proc.p_threads), &mtd)) { _kvm_err(kd, kd->program, "can't read thread at %p", TAILQ_FIRST(&proc.p_threads)); return (-1); } } if (KREAD(kd, (u_long)proc.p_ucred, &ucred) == 0) { kp->ki_ruid = ucred.cr_ruid; kp->ki_svuid = ucred.cr_svuid; kp->ki_rgid = ucred.cr_rgid; kp->ki_svgid = ucred.cr_svgid; kp->ki_cr_flags = ucred.cr_flags; if (ucred.cr_ngroups > KI_NGROUPS) { kp->ki_ngroups = KI_NGROUPS; kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW; } else kp->ki_ngroups = ucred.cr_ngroups; kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups, kp->ki_ngroups * sizeof(gid_t)); kp->ki_uid = ucred.cr_uid; if (ucred.cr_prison != NULL) { if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) { _kvm_err(kd, kd->program, "can't read prison at %p", ucred.cr_prison); return (-1); } kp->ki_jid = pr.pr_id; } } switch(what & ~KERN_PROC_INC_THREAD) { case KERN_PROC_GID: if (kp->ki_groups[0] != (gid_t)arg) continue; break; case KERN_PROC_PID: if (proc.p_pid != (pid_t)arg) continue; break; case KERN_PROC_RGID: if (kp->ki_rgid != (gid_t)arg) continue; break; case KERN_PROC_UID: if (kp->ki_uid != (uid_t)arg) continue; break; case KERN_PROC_RUID: if (kp->ki_ruid != (uid_t)arg) continue; break; } /* * We're going to add another proc to the set. If this * will overflow the buffer, assume the reason is because * nprocs (or the proc list) is corrupt and declare an error. */ if (cnt >= maxcnt) { _kvm_err(kd, kd->program, "nprocs corrupt"); return (-1); } /* * gather kinfo_proc */ kp->ki_paddr = p; kp->ki_addr = 0; /* XXX uarea */ /* kp->ki_kstack = proc.p_thread.td_kstack; XXXKSE */ kp->ki_args = proc.p_args; kp->ki_tracep = proc.p_tracevp; kp->ki_textvp = proc.p_textvp; kp->ki_fd = proc.p_fd; kp->ki_vmspace = proc.p_vmspace; if (proc.p_sigacts != NULL) { if (KREAD(kd, (u_long)proc.p_sigacts, &sigacts)) { _kvm_err(kd, kd->program, "can't read sigacts at %p", proc.p_sigacts); return (-1); } kp->ki_sigignore = sigacts.ps_sigignore; kp->ki_sigcatch = sigacts.ps_sigcatch; } #if 0 if ((proc.p_flag & P_INMEM) && proc.p_stats != NULL) { if (KREAD(kd, (u_long)proc.p_stats, &pstats)) { _kvm_err(kd, kd->program, "can't read stats at %x", proc.p_stats); return (-1); } kp->ki_start = pstats.p_start; /* * XXX: The times here are probably zero and need * to be calculated from the raw data in p_rux and * p_crux. */ kp->ki_rusage = pstats.p_ru; kp->ki_childstime = pstats.p_cru.ru_stime; kp->ki_childutime = pstats.p_cru.ru_utime; /* Some callers want child-times in a single value */ timeradd(&kp->ki_childstime, &kp->ki_childutime, &kp->ki_childtime); } #endif if (proc.p_oppid) kp->ki_ppid = proc.p_oppid; else if (proc.p_pptr) { if (KREAD(kd, (u_long)proc.p_pptr, &pproc)) { _kvm_err(kd, kd->program, "can't read pproc at %p", proc.p_pptr); return (-1); } kp->ki_ppid = pproc.p_pid; } else kp->ki_ppid = 0; if (proc.p_pgrp == NULL) goto nopgrp; if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) { _kvm_err(kd, kd->program, "can't read pgrp at %p", proc.p_pgrp); return (-1); } kp->ki_pgid = pgrp.pg_id; kp->ki_jobc = pgrp.pg_jobc; if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) { _kvm_err(kd, kd->program, "can't read session at %p", pgrp.pg_session); return (-1); } kp->ki_sid = sess.s_sid; (void)memcpy(kp->ki_login, sess.s_login, sizeof(kp->ki_login)); kp->ki_kiflag = sess.s_ttyvp ? KI_CTTY : 0; if (sess.s_leader == p) kp->ki_kiflag |= KI_SLEADER; if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) { if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) { _kvm_err(kd, kd->program, "can't read tty at %p", sess.s_ttyp); return (-1); } if (tty.t_dev != NULL) { if (KREAD(kd, (u_long)tty.t_dev, &t_cdev)) { _kvm_err(kd, kd->program, "can't read cdev at %p", tty.t_dev); return (-1); } #if 0 kp->ki_tdev = t_cdev.si_udev; #else kp->ki_tdev = NODEV; #endif } if (tty.t_pgrp != NULL) { if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) { _kvm_err(kd, kd->program, "can't read tpgrp at %p", tty.t_pgrp); return (-1); } kp->ki_tpgid = pgrp.pg_id; } else kp->ki_tpgid = -1; if (tty.t_session != NULL) { if (KREAD(kd, (u_long)tty.t_session, &sess)) { _kvm_err(kd, kd->program, "can't read session at %p", tty.t_session); return (-1); } kp->ki_tsid = sess.s_sid; } } else { nopgrp: kp->ki_tdev = NODEV; } if ((proc.p_state != PRS_ZOMBIE) && mtd.td_wmesg) (void)kvm_read(kd, (u_long)mtd.td_wmesg, kp->ki_wmesg, WMESGLEN); (void)kvm_read(kd, (u_long)proc.p_vmspace, (char *)&vmspace, sizeof(vmspace)); kp->ki_size = vmspace.vm_map.size; /* * Approximate the kernel's method of calculating * this field. */ #define pmap_resident_count(pm) ((pm)->pm_stats.resident_count) kp->ki_rssize = pmap_resident_count(&vmspace.vm_pmap); kp->ki_swrss = vmspace.vm_swrss; kp->ki_tsize = vmspace.vm_tsize; kp->ki_dsize = vmspace.vm_dsize; kp->ki_ssize = vmspace.vm_ssize; switch (what & ~KERN_PROC_INC_THREAD) { case KERN_PROC_PGRP: if (kp->ki_pgid != (pid_t)arg) continue; break; case KERN_PROC_SESSION: if (kp->ki_sid != (pid_t)arg) continue; break; case KERN_PROC_TTY: if ((proc.p_flag & P_CONTROLT) == 0 || kp->ki_tdev != (dev_t)arg) continue; break; } if (proc.p_comm[0] != 0) strlcpy(kp->ki_comm, proc.p_comm, MAXCOMLEN); (void)kvm_read(kd, (u_long)proc.p_sysent, (char *)&sysent, sizeof(sysent)); (void)kvm_read(kd, (u_long)sysent.sv_name, (char *)&svname, sizeof(svname)); if (svname[0] != 0) strlcpy(kp->ki_emul, svname, KI_EMULNAMELEN); if ((proc.p_state != PRS_ZOMBIE) && (mtd.td_blocked != 0)) { kp->ki_kiflag |= KI_LOCKBLOCK; if (mtd.td_lockname) (void)kvm_read(kd, (u_long)mtd.td_lockname, kp->ki_lockname, LOCKNAMELEN); kp->ki_lockname[LOCKNAMELEN] = 0; } kp->ki_runtime = cputick2usec(proc.p_rux.rux_runtime); kp->ki_pid = proc.p_pid; kp->ki_siglist = proc.p_siglist; SIGSETOR(kp->ki_siglist, mtd.td_siglist); kp->ki_sigmask = mtd.td_sigmask; kp->ki_xstat = KW_EXITCODE(proc.p_xexit, proc.p_xsig); kp->ki_acflag = proc.p_acflag; kp->ki_lock = proc.p_lock; if (proc.p_state != PRS_ZOMBIE) { kp->ki_swtime = (ticks - proc.p_swtick) / hz; kp->ki_flag = proc.p_flag; kp->ki_sflag = 0; kp->ki_nice = proc.p_nice; kp->ki_traceflag = proc.p_traceflag; if (proc.p_state == PRS_NORMAL) { if (TD_ON_RUNQ(&mtd) || TD_CAN_RUN(&mtd) || TD_IS_RUNNING(&mtd)) { kp->ki_stat = SRUN; } else if (mtd.td_state == TDS_INHIBITED) { if (P_SHOULDSTOP(&proc)) { kp->ki_stat = SSTOP; } else if ( TD_IS_SLEEPING(&mtd)) { kp->ki_stat = SSLEEP; } else if (TD_ON_LOCK(&mtd)) { kp->ki_stat = SLOCK; } else { kp->ki_stat = SWAIT; } } } else { kp->ki_stat = SIDL; } /* Stuff from the thread */ kp->ki_pri.pri_level = mtd.td_priority; kp->ki_pri.pri_native = mtd.td_base_pri; kp->ki_lastcpu = mtd.td_lastcpu; kp->ki_wchan = mtd.td_wchan; if (mtd.td_name[0] != 0) strlcpy(kp->ki_tdname, mtd.td_name, MAXCOMLEN); kp->ki_oncpu = mtd.td_oncpu; if (mtd.td_name[0] != '\0') strlcpy(kp->ki_tdname, mtd.td_name, sizeof(kp->ki_tdname)); kp->ki_pctcpu = 0; kp->ki_rqindex = 0; /* * Note: legacy fields; wraps at NO_CPU_OLD or the * old max CPU value as appropriate */ if (mtd.td_lastcpu == NOCPU) kp->ki_lastcpu_old = NOCPU_OLD; else if (mtd.td_lastcpu > MAXCPU_OLD) kp->ki_lastcpu_old = MAXCPU_OLD; else kp->ki_lastcpu_old = mtd.td_lastcpu; if (mtd.td_oncpu == NOCPU) kp->ki_oncpu_old = NOCPU_OLD; else if (mtd.td_oncpu > MAXCPU_OLD) kp->ki_oncpu_old = MAXCPU_OLD; else kp->ki_oncpu_old = mtd.td_oncpu; } else { kp->ki_stat = SZOMB; } bcopy(&kinfo_proc, bp, sizeof(kinfo_proc)); ++bp; ++cnt; } return (cnt); } /* * Build proc info array by reading in proc list from a crash dump. * Return number of procs read. maxcnt is the max we will read. */ static int kvm_deadprocs(kvm_t *kd, int what, int arg, u_long a_allproc, u_long a_zombproc, int maxcnt) { struct kinfo_proc *bp = kd->procbase; int acnt, zcnt; struct proc *p; if (KREAD(kd, a_allproc, &p)) { _kvm_err(kd, kd->program, "cannot read allproc"); return (-1); } acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt); if (acnt < 0) return (acnt); if (KREAD(kd, a_zombproc, &p)) { _kvm_err(kd, kd->program, "cannot read zombproc"); return (-1); } zcnt = kvm_proclist(kd, what, arg, p, bp + acnt, maxcnt - acnt); if (zcnt < 0) zcnt = 0; return (acnt + zcnt); } struct kinfo_proc * kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt) { int mib[4], st, nprocs; size_t size, osize; int temp_op; if (kd->procbase != 0) { free((void *)kd->procbase); /* * Clear this pointer in case this call fails. Otherwise, * kvm_close() will free it again. */ kd->procbase = 0; } if (ISALIVE(kd)) { size = 0; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = op; mib[3] = arg; temp_op = op & ~KERN_PROC_INC_THREAD; st = sysctl(mib, temp_op == KERN_PROC_ALL || temp_op == KERN_PROC_PROC ? 3 : 4, NULL, &size, NULL, 0); if (st == -1) { _kvm_syserr(kd, kd->program, "kvm_getprocs"); return (0); } /* * We can't continue with a size of 0 because we pass * it to realloc() (via _kvm_realloc()), and passing 0 * to realloc() results in undefined behavior. */ if (size == 0) { /* * XXX: We should probably return an invalid, * but non-NULL, pointer here so any client * program trying to dereference it will * crash. However, _kvm_freeprocs() calls * free() on kd->procbase if it isn't NULL, * and free()'ing a junk pointer isn't good. * Then again, _kvm_freeprocs() isn't used * anywhere . . . */ kd->procbase = _kvm_malloc(kd, 1); goto liveout; } do { size += size / 10; kd->procbase = (struct kinfo_proc *) _kvm_realloc(kd, kd->procbase, size); if (kd->procbase == 0) return (0); osize = size; st = sysctl(mib, temp_op == KERN_PROC_ALL || temp_op == KERN_PROC_PROC ? 3 : 4, kd->procbase, &size, NULL, 0); } while (st == -1 && errno == ENOMEM && size == osize); if (st == -1) { _kvm_syserr(kd, kd->program, "kvm_getprocs"); return (0); } /* * We have to check the size again because sysctl() * may "round up" oldlenp if oldp is NULL; hence it * might've told us that there was data to get when * there really isn't any. */ if (size > 0 && kd->procbase->ki_structsize != sizeof(struct kinfo_proc)) { _kvm_err(kd, kd->program, "kinfo_proc size mismatch (expected %zu, got %d)", sizeof(struct kinfo_proc), kd->procbase->ki_structsize); return (0); } liveout: nprocs = size == 0 ? 0 : size / kd->procbase->ki_structsize; } else { struct nlist nl[7], *p; nl[0].n_name = "_nprocs"; nl[1].n_name = "_allproc"; nl[2].n_name = "_zombproc"; nl[3].n_name = "_ticks"; nl[4].n_name = "_hz"; nl[5].n_name = "_cpu_tick_frequency"; nl[6].n_name = 0; + if (!kd->arch->ka_native(kd)) { + _kvm_err(kd, kd->program, + "cannot read procs from non-native core"); + return (0); + } + if (kvm_nlist(kd, nl) != 0) { for (p = nl; p->n_type != 0; ++p) ; _kvm_err(kd, kd->program, "%s: no such symbol", p->n_name); return (0); } if (KREAD(kd, nl[0].n_value, &nprocs)) { _kvm_err(kd, kd->program, "can't read nprocs"); return (0); } if (KREAD(kd, nl[3].n_value, &ticks)) { _kvm_err(kd, kd->program, "can't read ticks"); return (0); } if (KREAD(kd, nl[4].n_value, &hz)) { _kvm_err(kd, kd->program, "can't read hz"); return (0); } if (KREAD(kd, nl[5].n_value, &cpu_tick_frequency)) { _kvm_err(kd, kd->program, "can't read cpu_tick_frequency"); return (0); } size = nprocs * sizeof(struct kinfo_proc); kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); if (kd->procbase == 0) return (0); nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value, nl[2].n_value, nprocs); if (nprocs <= 0) { _kvm_freeprocs(kd); nprocs = 0; } #ifdef notdef else { size = nprocs * sizeof(struct kinfo_proc); kd->procbase = realloc(kd->procbase, size); } #endif } *cnt = nprocs; return (kd->procbase); } void _kvm_freeprocs(kvm_t *kd) { if (kd->procbase) { free(kd->procbase); kd->procbase = 0; } } void * _kvm_realloc(kvm_t *kd, void *p, size_t n) { void *np = (void *)realloc(p, n); if (np == 0) { free(p); _kvm_err(kd, kd->program, "out of memory"); } return (np); } /* * Get the command args or environment. */ static char ** kvm_argv(kvm_t *kd, const struct kinfo_proc *kp, int env, int nchr) { int oid[4]; int i; size_t bufsz; static int buflen; static char *buf, *p; static char **bufp; static int argc; if (!ISALIVE(kd)) { _kvm_err(kd, kd->program, "cannot read user space from dead kernel"); return (0); } if (nchr == 0 || nchr > ARG_MAX) nchr = ARG_MAX; if (buflen == 0) { buf = malloc(nchr); if (buf == NULL) { _kvm_err(kd, kd->program, "cannot allocate memory"); return (0); } buflen = nchr; argc = 32; bufp = malloc(sizeof(char *) * argc); } else if (nchr > buflen) { p = realloc(buf, nchr); if (p != NULL) { buf = p; buflen = nchr; } } oid[0] = CTL_KERN; oid[1] = KERN_PROC; oid[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS; oid[3] = kp->ki_pid; bufsz = buflen; if (sysctl(oid, 4, buf, &bufsz, 0, 0) == -1) { /* * If the supplied buf is too short to hold the requested * value the sysctl returns with ENOMEM. The buf is filled * with the truncated value and the returned bufsz is equal * to the requested len. */ if (errno != ENOMEM || bufsz != (size_t)buflen) return (0); buf[bufsz - 1] = '\0'; errno = 0; } else if (bufsz == 0) { return (0); } i = 0; p = buf; do { bufp[i++] = p; p += strlen(p) + 1; if (i >= argc) { argc += argc; bufp = realloc(bufp, sizeof(char *) * argc); } } while (p < buf + bufsz); bufp[i++] = 0; return (bufp); } char ** kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) { return (kvm_argv(kd, kp, 0, nchr)); } char ** kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr) { return (kvm_argv(kd, kp, 1, nchr)); } Index: head/lib/libkvm/kvm_read.3 =================================================================== --- head/lib/libkvm/kvm_read.3 (revision 291405) +++ head/lib/libkvm/kvm_read.3 (revision 291406) @@ -1,92 +1,106 @@ .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software developed by the Computer Systems .\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract .\" BG 91-66 and contributed to Berkeley. .\" .\" 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. .\" .\" @(#)kvm_read.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd November 27, 2015 .Dt KVM_READ 3 .Os .Sh NAME .Nm kvm_read , +.Nm kvm_read2 , .Nm kvm_write .Nd read or write kernel virtual memory .Sh LIBRARY .Lb libkvm .Sh SYNOPSIS .In kvm.h .Ft ssize_t .Fn kvm_read "kvm_t *kd" "unsigned long addr" "void *buf" "size_t nbytes" .Ft ssize_t +.Fn kvm_read2 "kvm_t *kd" "kvaddr_t addr" "void *buf" "size_t nbytes" +.Ft ssize_t .Fn kvm_write "kvm_t *kd" "unsigned long addr" "const void *buf" "size_t nbytes" .Sh DESCRIPTION The -.Fn kvm_read +.Fn kvm_read , +.Fn kvm_read2 , and .Fn kvm_write functions are used to read and write kernel virtual memory (or a crash dump file). See .Fn kvm_open 3 -or -.Fn kvm_openfiles 3 for information regarding opening kernel virtual memory and crash dumps. .Pp The .Fn kvm_read -function transfers +and +.Fn kvm_read2 +functions transfer .Fa nbytes bytes of data from the kernel space address .Fa addr to .Fa buf . Conversely, .Fn kvm_write transfers data from .Fa buf to .Fa addr . Unlike their SunOS counterparts, these functions cannot be used to read or write process address spaces. +.Pp +The +.Fn kvm_read2 +function uses a different type +.Pq Vt kvaddr_t +for the +.Fa addr +argument to allow use of addresses larger than +.Dv ULONG_MAX +when examining non-native kernel images. .Sh RETURN VALUES Upon success, the number of bytes actually transferred is returned. Otherwise, -1 is returned. .Sh SEE ALSO .Xr kvm 3 , .Xr kvm_close 3 , .Xr kvm_getargv 3 , .Xr kvm_getenvv 3 , .Xr kvm_geterr 3 , .Xr kvm_getprocs 3 , .Xr kvm_nlist 3 , .Xr kvm_open 3 , .Xr kvm_openfiles 3 Index: head/lib/libkvm/kvm_sparc64.c =================================================================== --- head/lib/libkvm/kvm_sparc64.c (revision 291405) +++ head/lib/libkvm/kvm_sparc64.c (revision 291406) @@ -1,221 +1,244 @@ /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software developed by the Computer Systems * Engineering group at Lawrence Berkeley Laboratory under DARPA contract * BG 91-66 and contributed to Berkeley. * * 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: FreeBSD: src/lib/libkvm/kvm_i386.c,v 1.15 2001/10/10 17:48:43 */ #include __FBSDID("$FreeBSD$"); #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; #endif #endif /* LIBC_SCCS and not lint */ /* * sparc64 machine dependent routines for kvm. */ #include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include "../../sys/sparc64/include/kerneldump.h" -#include -#include -#include -#include - -#include - #include "kvm_private.h" +#include "kvm_sparc64.h" -#ifndef btop -#define btop(x) (sparc64_btop(x)) -#define ptob(x) (sparc64_ptob(x)) -#endif - struct vmstate { off_t vm_tsb_off; - vm_size_t vm_tsb_mask; + uint64_t vm_tsb_mask; int vm_nregions; struct sparc64_dump_reg *vm_regions; }; -void -_kvm_freevtop(kvm_t *kd) +static int +_sparc64_probe(kvm_t *kd) { - if (kd->vmst != 0) { - free(kd->vmst->vm_regions); - free(kd->vmst); - } + + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_SPARCV9)); } +static void +_sparc64_freevtop(kvm_t *kd) +{ + + free(kd->vmst->vm_regions); + free(kd->vmst); + kd->vmst = NULL; +} + static int -_kvm_read_phys(kvm_t *kd, off_t pos, void *buf, size_t size) +_sparc64_read_phys(kvm_t *kd, off_t pos, void *buf, size_t size) { /* XXX This has to be a raw file read, kvm_read is virtual. */ - if (lseek(kd->pmfd, pos, SEEK_SET) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_read_phys: lseek"); + if (pread(kd->pmfd, buf, size, pos) != (ssize_t)size) { + _kvm_syserr(kd, kd->program, "_sparc64_read_phys: pread"); return (0); } - if (read(kd->pmfd, buf, size) != (ssize_t)size) { - _kvm_syserr(kd, kd->program, "_kvm_read_phys: read"); - return (0); - } return (1); } static int -_kvm_reg_cmp(const void *a, const void *b) +_sparc64_reg_cmp(const void *a, const void *b) { const struct sparc64_dump_reg *ra, *rb; ra = a; rb = b; if (ra->dr_pa < rb->dr_pa) return (-1); else if (ra->dr_pa >= rb->dr_pa + rb->dr_size) return (1); else return (0); } #define KVM_OFF_NOTFOUND 0 static off_t -_kvm_find_off(struct vmstate *vm, vm_offset_t pa, vm_size_t size) +_sparc64_find_off(struct vmstate *vm, uint64_t pa, uint64_t size) { struct sparc64_dump_reg *reg, key; vm_offset_t o; key.dr_pa = pa; reg = bsearch(&key, vm->vm_regions, vm->vm_nregions, - sizeof(*vm->vm_regions), _kvm_reg_cmp); + sizeof(*vm->vm_regions), _sparc64_reg_cmp); if (reg == NULL) return (KVM_OFF_NOTFOUND); o = pa - reg->dr_pa; if (o + size > reg->dr_size) return (KVM_OFF_NOTFOUND); return (reg->dr_offs + o); } -int -_kvm_initvtop(kvm_t *kd) +static int +_sparc64_initvtop(kvm_t *kd) { struct sparc64_dump_hdr hdr; struct sparc64_dump_reg *regs; struct vmstate *vm; size_t regsz; - vm_offset_t pa; + uint64_t pa; + int i; vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); if (vm == NULL) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } kd->vmst = vm; - if (!_kvm_read_phys(kd, 0, &hdr, sizeof(hdr))) + if (!_sparc64_read_phys(kd, 0, &hdr, sizeof(hdr))) goto fail_vm; + hdr.dh_hdr_size = be64toh(hdr.dh_hdr_size); + hdr.dh_tsb_pa = be64toh(hdr.dh_tsb_pa); + hdr.dh_tsb_size = be64toh(hdr.dh_tsb_size); + hdr.dh_tsb_mask = be64toh(hdr.dh_tsb_mask); + hdr.dh_nregions = be32toh(hdr.dh_nregions); pa = hdr.dh_tsb_pa; regsz = hdr.dh_nregions * sizeof(*regs); regs = _kvm_malloc(kd, regsz); if (regs == NULL) { _kvm_err(kd, kd->program, "cannot allocate regions"); goto fail_vm; } - if (!_kvm_read_phys(kd, sizeof(hdr), regs, regsz)) + if (!_sparc64_read_phys(kd, sizeof(hdr), regs, regsz)) goto fail_regs; - qsort(regs, hdr.dh_nregions, sizeof(*regs), _kvm_reg_cmp); + for (i = 0; i < hdr.dh_nregions; i++) { + regs[i].dr_pa = be64toh(regs[i].dr_pa); + regs[i].dr_size = be64toh(regs[i].dr_size); + regs[i].dr_offs = be64toh(regs[i].dr_offs); + } + qsort(regs, hdr.dh_nregions, sizeof(*regs), _sparc64_reg_cmp); vm->vm_tsb_mask = hdr.dh_tsb_mask; vm->vm_regions = regs; vm->vm_nregions = hdr.dh_nregions; - vm->vm_tsb_off = _kvm_find_off(vm, hdr.dh_tsb_pa, hdr.dh_tsb_size); + vm->vm_tsb_off = _sparc64_find_off(vm, hdr.dh_tsb_pa, hdr.dh_tsb_size); if (vm->vm_tsb_off == KVM_OFF_NOTFOUND) { _kvm_err(kd, kd->program, "tsb not found in dump"); goto fail_regs; } return (0); fail_regs: free(regs); fail_vm: free(vm); return (-1); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_sparc64_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { - struct tte tte; + struct sparc64_tte tte; off_t tte_off; - u_long vpn; + kvaddr_t vpn; off_t pa_off; - u_long pg_off; + kvaddr_t pg_off; int rest; - pg_off = va & PAGE_MASK; - if (va >= VM_MIN_DIRECT_ADDRESS) - pa_off = TLB_DIRECT_TO_PHYS(va) & ~PAGE_MASK; + pg_off = va & SPARC64_PAGE_MASK; + if (va >= SPARC64_MIN_DIRECT_ADDRESS) + pa_off = SPARC64_DIRECT_TO_PHYS(va) & ~SPARC64_PAGE_MASK; else { - vpn = btop(va); + vpn = va >> SPARC64_PAGE_SHIFT; tte_off = kd->vmst->vm_tsb_off + - ((vpn & kd->vmst->vm_tsb_mask) << TTE_SHIFT); - if (!_kvm_read_phys(kd, tte_off, &tte, sizeof(tte))) + ((vpn & kd->vmst->vm_tsb_mask) << SPARC64_TTE_SHIFT); + if (!_sparc64_read_phys(kd, tte_off, &tte, sizeof(tte))) goto invalid; - if (!tte_match(&tte, va)) + tte.tte_vpn = be64toh(tte.tte_vpn); + tte.tte_data = be64toh(tte.tte_data); + if (!sparc64_tte_match(&tte, va)) goto invalid; - pa_off = TTE_GET_PA(&tte); + pa_off = SPARC64_TTE_GET_PA(&tte); } - rest = PAGE_SIZE - pg_off; - pa_off = _kvm_find_off(kd->vmst, pa_off, rest); + rest = SPARC64_PAGE_SIZE - pg_off; + pa_off = _sparc64_find_off(kd->vmst, pa_off, rest); if (pa_off == KVM_OFF_NOTFOUND) goto invalid; *pa = pa_off + pg_off; return (rest); invalid: - _kvm_err(kd, 0, "invalid address (%lx)", va); + _kvm_err(kd, 0, "invalid address (%jx)", (uintmax_t)va); return (0); } + +static int +_sparc64_native(kvm_t *kd) +{ + +#ifdef __sparc64__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_sparc64 = { + .ka_probe = _sparc64_probe, + .ka_initvtop = _sparc64_initvtop, + .ka_freevtop = _sparc64_freevtop, + .ka_kvatop = _sparc64_kvatop, + .ka_native = _sparc64_native, +}; + +KVM_ARCH(kvm_sparc64); Index: head/lib/libkvm/kvm_sparc64.h =================================================================== --- head/lib/libkvm/kvm_sparc64.h (nonexistent) +++ head/lib/libkvm/kvm_sparc64.h (revision 291406) @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2015 John H. 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. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef __KVM_SPARC64_H__ +#define __KVM_SPARC64_H__ + +#ifdef __sparc64__ +#include +#include +#include +#include +#include +#endif + +#define SPARC64_PAGE_SHIFT 13 +#define SPARC64_PAGE_SIZE (1 << SPARC64_PAGE_SHIFT) +#define SPARC64_PAGE_MASK (SPARC64_PAGE_SIZE - 1) + +#define SPARC64_MIN_DIRECT_ADDRESS (0xfffff80000000000) + +#define SPARC64_DIRECT_ADDRESS_BITS (43) +#define SPARC64_DIRECT_ADDRESS_MASK \ + (((uint64_t)1 << SPARC64_DIRECT_ADDRESS_BITS) - 1) + +#define SPARC64_DIRECT_TO_PHYS(va) ((va) & SPARC64_DIRECT_ADDRESS_MASK) + +#define SPARC64_TTE_SHIFT (5) + +#define SPARC64_TD_SIZE_SHIFT (61) +#define SPARC64_TD_PA_SHIFT (13) + +#define SPARC64_TD_SIZE_BITS (2) +#define SPARC64_TD_PA_CH_BITS (30) /* US-III{,i,+}, US-IV{,+}, SPARC64 V */ +#define SPARC64_TD_PA_BITS SPARC64_TD_PA_CH_BITS + +#define SPARC64_TD_SIZE_MASK (((uint64_t)1 << SPARC64_TD_SIZE_BITS) - 1) +#define SPARC64_TD_PA_MASK (((uint64_t)1 << SPARC64_TD_PA_BITS) - 1) + +#define SPARC64_TD_V ((uint64_t)1 << 63) + +#define SPARC64_TV_SIZE_BITS (SPARC64_TD_SIZE_BITS) +#define SPARC64_TV_VPN(va, sz) \ + ((((va) >> SPARC64_TTE_PAGE_SHIFT(sz)) << SPARC64_TV_SIZE_BITS) | sz) + +#define SPARC64_TTE_SIZE_SPREAD (3) +#define SPARC64_TTE_PAGE_SHIFT(sz) \ + (SPARC64_PAGE_SHIFT + ((sz) * SPARC64_TTE_SIZE_SPREAD)) + +#define SPARC64_TTE_GET_SIZE(tp) \ + (((tp)->tte_data >> SPARC64_TD_SIZE_SHIFT) & SPARC64_TD_SIZE_MASK) + +#define SPARC64_TTE_GET_PA(tp) \ + ((tp)->tte_data & (SPARC64_TD_PA_MASK << SPARC64_TD_PA_SHIFT)) + +struct sparc64_tte { + uint64_t tte_vpn; + uint64_t tte_data; +}; + +static __inline int +sparc64_tte_match(struct sparc64_tte *tp, kvaddr_t va) +{ + + return (((tp->tte_data & SPARC64_TD_V) != 0) && + (tp->tte_vpn == SPARC64_TV_VPN(va, SPARC64_TTE_GET_SIZE(tp)))); +} + +#ifdef __sparc64__ +_Static_assert(PAGE_SHIFT == SPARC64_PAGE_SHIFT, "PAGE_SHIFT mismatch"); +_Static_assert(PAGE_SIZE == SPARC64_PAGE_SIZE, "PAGE_SIZE mismatch"); +_Static_assert(PAGE_MASK == SPARC64_PAGE_MASK, "PAGE_MASK mismatch"); +_Static_assert(VM_MIN_DIRECT_ADDRESS == SPARC64_MIN_DIRECT_ADDRESS, + "VM_MIN_DIRECT_ADDRESS mismatch"); +_Static_assert(TLB_DIRECT_ADDRESS_BITS == SPARC64_DIRECT_ADDRESS_BITS, + "TLB_DIRECT_ADDRESS_BITS mismatch"); +_Static_assert(TLB_DIRECT_ADDRESS_MASK == SPARC64_DIRECT_ADDRESS_MASK, + "TLB_DIRECT_ADDRESS_MASK mismatch"); +_Static_assert(TTE_SHIFT == SPARC64_TTE_SHIFT, "TTE_SHIFT mismatch"); +_Static_assert(TD_SIZE_SHIFT == SPARC64_TD_SIZE_SHIFT, + "TD_SIZE_SHIFT mismatch"); +_Static_assert(TD_PA_SHIFT == SPARC64_TD_PA_SHIFT, + "TD_PA_SHIFT mismatch"); +_Static_assert(TD_SIZE_BITS == SPARC64_TD_SIZE_BITS, "TD_SIZE_BITS mismatch"); +_Static_assert(TD_PA_BITS == SPARC64_TD_PA_BITS, "TD_PA_BITS mismatch"); +_Static_assert(TD_SIZE_MASK == SPARC64_TD_SIZE_MASK, "TD_SIZE_MASK mismatch"); +_Static_assert(TD_PA_MASK == SPARC64_TD_PA_MASK, "TD_PA_MASK mismatch"); +_Static_assert(TD_V == SPARC64_TD_V, "TD_V mismatch"); +_Static_assert(TV_SIZE_BITS == SPARC64_TV_SIZE_BITS, "TV_SIZE_BITS mismatch"); +_Static_assert(TTE_SIZE_SPREAD == SPARC64_TTE_SIZE_SPREAD, + "TTE_SIZE_SPREAD mismatch"); +#endif + +#endif /* !__KVM_SPARC64_H__ */ Property changes on: head/lib/libkvm/kvm_sparc64.h ___________________________________________________________________ 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: head/lib/libkvm/kvm_vnet.c =================================================================== --- head/lib/libkvm/kvm_vnet.c (revision 291405) +++ head/lib/libkvm/kvm_vnet.c (revision 291406) @@ -1,239 +1,244 @@ /*- * Copyright (c) 2009 Robert N. M. Watson * Copyright (c) 2009 Bjoern A. Zeeb * 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 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. */ #include __FBSDID("$FreeBSD$"); #include #define _WANT_PRISON #define _WANT_UCRED #define _WANT_VNET #include #include #include #include #include #include #include -#include #include #include #include #include #include "kvm_private.h" /* * Set up libkvm to handle virtual network stack symbols by selecting a * starting pid. */ int _kvm_vnet_selectpid(kvm_t *kd, pid_t pid) { struct proc proc; struct ucred cred; struct prison prison; struct vnet vnet; - struct nlist nl[] = { + struct kvm_nlist nl[] = { /* * Note: kvm_nlist strips the first '_' so add an extra one * here to __{start,stop}_set_vnet. */ #define NLIST_START_VNET 0 { .n_name = "___start_" VNET_SETNAME }, #define NLIST_STOP_VNET 1 { .n_name = "___stop_" VNET_SETNAME }, #define NLIST_VNET_HEAD 2 { .n_name = "vnet_head" }, #define NLIST_ALLPROC 3 { .n_name = "allproc" }, #define NLIST_DUMPTID 4 { .n_name = "dumptid" }, #define NLIST_PROC0 5 { .n_name = "proc0" }, { .n_name = NULL }, }; uintptr_t procp, credp; #define VMCORE_VNET_OF_PROC0 #ifndef VMCORE_VNET_OF_PROC0 struct thread td; uintptr_t tdp; #endif lwpid_t dumptid; /* + * XXX: This only works for native kernels for now. + */ + if (!kvm_native(kd)) + return (-1); + + /* * Locate and cache locations of important symbols * using the internal version of _kvm_nlist, turning * off initialization to avoid recursion in case of * unresolveable symbols. */ if (_kvm_nlist(kd, nl, 0) != 0) { /* * XXX-BZ: ___start_/___stop_VNET_SETNAME may fail. * For now do not report an error here as we are called * internally and in `void context' until we merge the * functionality to optionally activate this into programs. * By that time we can properly fail and let the callers * handle the error. */ /* _kvm_err(kd, kd->program, "%s: no namelist", __func__); */ return (-1); } /* * Auto-detect if this is a crashdump by reading dumptid. */ dumptid = 0; if (nl[NLIST_DUMPTID].n_value) { if (kvm_read(kd, nl[NLIST_DUMPTID].n_value, &dumptid, sizeof(dumptid)) != sizeof(dumptid)) { _kvm_err(kd, kd->program, "%s: dumptid", __func__); return (-1); } } /* * First, find the process for this pid. If we are working on a * dump, either locate the thread dumptid is refering to or proc0. * Based on either, take the address of the ucred. */ credp = 0; procp = nl[NLIST_ALLPROC].n_value; #ifdef VMCORE_VNET_OF_PROC0 if (dumptid > 0) { procp = nl[NLIST_PROC0].n_value; pid = 0; } #endif while (procp != 0) { if (kvm_read(kd, procp, &proc, sizeof(proc)) != sizeof(proc)) { _kvm_err(kd, kd->program, "%s: proc", __func__); return (-1); } #ifndef VMCORE_VNET_OF_PROC0 if (dumptid > 0) { tdp = (uintptr_t)TAILQ_FIRST(&proc.p_threads); while (tdp != 0) { if (kvm_read(kd, tdp, &td, sizeof(td)) != sizeof(td)) { _kvm_err(kd, kd->program, "%s: thread", __func__); return (-1); } if (td.td_tid == dumptid) { credp = (uintptr_t)td.td_ucred; break; } tdp = (uintptr_t)TAILQ_NEXT(&td, td_plist); } } else #endif if (proc.p_pid == pid) credp = (uintptr_t)proc.p_ucred; if (credp != 0) break; procp = (uintptr_t)LIST_NEXT(&proc, p_list); } if (credp == 0) { _kvm_err(kd, kd->program, "%s: pid/tid not found", __func__); return (-1); } if (kvm_read(kd, (uintptr_t)credp, &cred, sizeof(cred)) != sizeof(cred)) { _kvm_err(kd, kd->program, "%s: cred", __func__); return (-1); } if (cred.cr_prison == NULL) { _kvm_err(kd, kd->program, "%s: no jail", __func__); return (-1); } if (kvm_read(kd, (uintptr_t)cred.cr_prison, &prison, sizeof(prison)) != sizeof(prison)) { _kvm_err(kd, kd->program, "%s: prison", __func__); return (-1); } if (prison.pr_vnet == NULL) { _kvm_err(kd, kd->program, "%s: no vnet", __func__); return (-1); } if (kvm_read(kd, (uintptr_t)prison.pr_vnet, &vnet, sizeof(vnet)) != sizeof(vnet)) { _kvm_err(kd, kd->program, "%s: vnet", __func__); return (-1); } if (vnet.vnet_magic_n != VNET_MAGIC_N) { _kvm_err(kd, kd->program, "%s: invalid vnet magic#", __func__); return (-1); } kd->vnet_initialized = 1; kd->vnet_start = nl[NLIST_START_VNET].n_value; kd->vnet_stop = nl[NLIST_STOP_VNET].n_value; kd->vnet_current = (uintptr_t)prison.pr_vnet; kd->vnet_base = vnet.vnet_data_base; return (0); } /* * Check whether the vnet module has been initialized sucessfully - * or not, intialize it if permitted. + * or not, initialize it if permitted. */ int _kvm_vnet_initialized(kvm_t *kd, int intialize) { if (kd->vnet_initialized || !intialize) return (kd->vnet_initialized); (void) _kvm_vnet_selectpid(kd, getpid()); return (kd->vnet_initialized); } /* * Check whether the value is within the vnet symbol range and * only if so adjust the offset relative to the current base. */ -uintptr_t -_kvm_vnet_validaddr(kvm_t *kd, uintptr_t value) +kvaddr_t +_kvm_vnet_validaddr(kvm_t *kd, kvaddr_t value) { if (value == 0) return (value); if (!kd->vnet_initialized) return (value); if (value < kd->vnet_start || value >= kd->vnet_stop) return (value); return (kd->vnet_base + value); } Index: head/rescue/rescue/Makefile =================================================================== --- head/rescue/rescue/Makefile (revision 291405) +++ head/rescue/rescue/Makefile (revision 291406) @@ -1,230 +1,230 @@ #$FreeBSD$ # @(#)Makefile 8.1 (Berkeley) 6/2/93 .include MAN= MK_SSP= no PROG= rescue BINDIR?=/rescue # Shell scripts need #! line to be edited from /bin/sh to /rescue/sh SCRIPTS= nextboot_FIXED SCRIPTSNAME_nextboot_FIXED= nextboot nextboot_FIXED: ../../sbin/reboot/nextboot.sh sed '1s/\/bin\//\/rescue\//' ${.ALLSRC} > ${.TARGET} CLEANFILES+= nextboot_FIXED SCRIPTS+= dhclient_FIXED SCRIPTSNAME_dhclient_FIXED= dhclient-script dhclient_FIXED: ../../sbin/dhclient/dhclient-script sed '1s/\/bin\//\/rescue\//' ${.ALLSRC} > ${.TARGET} CLEANFILES+= dhclient_FIXED # The help which used to be here is now in mk/bsd.crunchgen.mk # Define Makefile variable RESCUE CRUNCH_BUILDOPTS+= -DRESCUE # Define compile-time RESCUE symbol when compiling components CRUNCH_BUILDOPTS+= CRUNCH_CFLAGS=-DRESCUE # An experiment that failed: try overriding bsd.lib.mk and bsd.prog.mk # rather than incorporating rescue-specific logic into standard files. #MAKEFLAGS= -m ${.CURDIR} ${.MAKEFLAGS} # Hackery: 'librescue' exists merely as a tool for appropriately # recompiling specific library entries. We _know_ they're needed, and # regular archive searching creates ugly library ordering problems. # Easiest fix: tell the linker to include them into the executable # first, so they are guaranteed to override the regular lib entries. # Note that if 'librescue' hasn't been compiled, we'll just get the # regular lib entries from libc and friends. CRUNCH_LIBS+= ${.OBJDIR}/../librescue/*.o ################################################################### # Programs from stock /bin # # WARNING: Changing this list may require adjusting # /usr/include/paths.h as well! You were warned! # CRUNCH_SRCDIRS+= bin CRUNCH_PROGS_bin= cat chflags chio chmod cp date dd df echo \ ed expr getfacl hostname kenv kill ln ls mkdir mv \ pkill ps pwd realpath rm rmdir setfacl sh sleep stty \ sync test -CRUNCH_LIBS+= -lcrypt -ledit -ljail -lkvm -ll -ltermcapw -lutil -lxo +CRUNCH_LIBS+= -lcrypt -ledit -ljail -lkvm -lelf -ll -ltermcapw -lutil -lxo CRUNCH_BUILDTOOLS+= bin/sh # Additional options for specific programs CRUNCH_ALIAS_test= [ CRUNCH_ALIAS_sh= -sh # The -sh alias shouldn't appear in /rescue as a hard link CRUNCH_SUPPRESS_LINK_-sh= 1 CRUNCH_ALIAS_ln= link CRUNCH_ALIAS_rm= unlink CRUNCH_ALIAS_ed= red CRUNCH_ALIAS_pkill= pgrep .if ${MK_RCMDS} != "no" CRUNCH_PROGS_bin+= rcp .endif .if ${MK_TCSH} != "no" CRUNCH_PROGS_bin+= csh CRUNCH_ALIAS_csh= -csh tcsh -tcsh CRUNCH_BUILDTOOLS+= bin/csh CRUNCH_SUPPRESS_LINK_-csh= 1 CRUNCH_SUPPRESS_LINK_-tcsh= 1 .endif ################################################################### # Programs from standard /sbin # # WARNING: Changing this list may require adjusting # /usr/include/paths.h as well! You were warned! # # Note that mdmfs have their own private 'pathnames.h' # headers in addition to the standard 'paths.h' header. # CRUNCH_SRCDIRS+= sbin CRUNCH_PROGS_sbin= badsect \ camcontrol ccdconfig clri devfs dmesg dump \ dumpfs dumpon fsck fsck_ffs fsck_msdosfs fsdb \ fsirand gbde geom ifconfig init \ kldconfig kldload kldstat kldunload ldconfig \ md5 mdconfig mdmfs mknod mount mount_cd9660 \ mount_msdosfs mount_nfs mount_nullfs \ mount_udf mount_unionfs newfs \ newfs_msdos nos-tun ping reboot \ restore rcorder route routed rtquery rtsol savecore \ spppcontrol swapon sysctl tunefs umount .if ${MK_ATM} != "no" CRUNCH_PROGS_sbin+= atmconfig .endif .if ${MK_INET6_SUPPORT} != "no" CRUNCH_PROGS_sbin+= ping6 .endif .if ${MK_IPFILTER} != "no" CRUNCH_PROGS_sbin+= ipf .endif .if ${MK_ZFS} != "no" CRUNCH_PROGS_sbin+= zfs CRUNCH_PROGS_sbin+= zpool CRUNCH_PROGS_usr.sbin+= zdb .endif # crunchgen does not like C++ programs; this should be fixed someday # CRUNCH_PROGS+= devd CRUNCH_LIBS+= -lalias -lcam -lncursesw -ldevstat -lipsec -llzma .if ${MK_ZFS} != "no" CRUNCH_LIBS+= -lavl -lzpool -lzfs_core -lzfs -lnvpair -lpthread -luutil -lumem .else # liblzma needs pthread CRUNCH_LIBS+= -lpthread .endif CRUNCH_LIBS+= -lgeom -lbsdxml -lkiconv .if ${MK_OPENSSL} == "no" CRUNCH_LIBS+= -lmd .endif CRUNCH_LIBS+= -lmt -lsbuf -lufs -lz .if ${MACHINE_CPUARCH} == "i386" CRUNCH_PROGS_sbin+= bsdlabel sconfig fdisk CRUNCH_ALIAS_bsdlabel= disklabel #CRUNCH_PROGS+= mount_smbfs #CRUNCH_LIBS+= -lsmb .endif .if ${MACHINE} == "pc98" CRUNCH_SRCDIR_fdisk= $(.CURDIR)/../../sbin/fdisk_pc98 .endif .if ${MACHINE_CPUARCH} == "sparc64" CRUNCH_PROGS_sbin+= bsdlabel sunlabel .endif .if ${MACHINE_CPUARCH} == "amd64" CRUNCH_PROGS_sbin+= bsdlabel fdisk CRUNCH_ALIAS_bsdlabel= disklabel .endif CRUNCH_SRCDIR_atm= $(.CURDIR)/../../sbin/atm/atm CRUNCH_SRCDIR_atmconfig= $(.CURDIR)/../../sbin/atm/atmconfig CRUNCH_SRCDIR_fore_dnld= $(.CURDIR)/../../sbin/atm/fore_dnld CRUNCH_SRCDIR_ilmid= $(.CURDIR)/../../sbin/atm/ilmid CRUNCH_SRCDIR_rtquery= $(.CURDIR)/../../sbin/routed/rtquery CRUNCH_SRCDIR_ipf= $(.CURDIR)/../../sbin/ipf/ipf .if ${MK_ZFS} != "no" CRUNCH_SRCDIR_zfs= ${.CURDIR}/../../cddl/sbin/zfs CRUNCH_SRCDIR_zpool= ${.CURDIR}/../../cddl/sbin/zpool CRUNCH_SRCDIR_zdb= ${.CURDIR}/../../cddl/usr.sbin/zdb .endif CRUNCH_ALIAS_reboot= fastboot halt fasthalt CRUNCH_ALIAS_restore= rrestore CRUNCH_ALIAS_dump= rdump CRUNCH_ALIAS_fsck_ffs= fsck_4.2bsd fsck_ufs CRUNCH_ALIAS_geom= glabel gpart # dhclient has historically been troublesome... CRUNCH_PROGS_sbin+= dhclient CRUNCH_BUILDOPTS_dhclient= -DRELEASE_CRUNCH -Dlint ################################################################## # Programs from stock /usr/bin # CRUNCH_SRCDIRS+= usr.bin CRUNCH_PROGS_usr.bin= head mt nc sed tail tee CRUNCH_PROGS_usr.bin+= gzip CRUNCH_ALIAS_gzip= gunzip gzcat zcat CRUNCH_PROGS_usr.bin+= bzip2 CRUNCH_ALIAS_bzip2= bunzip2 bzcat CRUNCH_LIBS+= -lbz2 CRUNCH_PROGS_usr.bin+= less CRUNCH_ALIAS_less= more CRUNCH_PROGS_usr.bin+= xz CRUNCH_ALIAS_xz= unxz lzma unlzma xzcat lzcat CRUNCH_PROGS_usr.bin+= tar CRUNCH_LIBS+= -larchive .if ${MK_OPENSSL} != "no" CRUNCH_LIBS+= -lcrypto .endif CRUNCH_LIBS+= -lmd .if ${MK_VI} != "no" CRUNCH_PROGS_usr.bin+= vi CRUNCH_ALIAS_vi= ex .endif CRUNCH_PROGS_usr.bin+= id CRUNCH_ALIAS_id= groups whoami ################################################################## # Programs from stock /usr/sbin # CRUNCH_SRCDIRS+= usr.sbin CRUNCH_PROGS_usr.sbin+= chroot CRUNCH_PROGS_usr.sbin+= chown CRUNCH_ALIAS_chown= chgrp ################################################################## CRUNCH_LIBS+= -lm .if ${MK_ISCSI} != "no" CRUNCH_PROGS_usr.bin+= iscsictl CRUNCH_PROGS_usr.sbin+= iscsid .endif .include .include Index: head/share/mk/src.libnames.mk =================================================================== --- head/share/mk/src.libnames.mk (revision 291405) +++ head/share/mk/src.libnames.mk (revision 291406) @@ -1,431 +1,432 @@ # $FreeBSD$ # # The include file define library names suitable # for INTERNALLIB and PRIVATELIB definition .if !target(____) .error src.libnames.mk cannot be included directly. .endif .if !target(____) ____: .include _PRIVATELIBS= \ atf_c \ atf_cxx \ bsdstat \ event \ heimipcc \ heimipcs \ ldns \ sqlite3 \ ssh \ ucl \ unbound _INTERNALLIBS= \ amu \ bsnmptools \ cron \ elftc \ fifolog \ ipf \ lpr \ netbsd \ ntp \ ntpevent \ openbsd \ opts \ parse \ readline \ sl \ sm \ smdb \ smutil \ telnet \ vers _LIBRARIES= \ ${_PRIVATELIBS} \ ${_INTERNALLIBS} \ alias \ archive \ asn1 \ auditd \ avl \ begemot \ bluetooth \ bsdxml \ bsm \ bsnmp \ bz2 \ c \ c_pic \ calendar \ cam \ capsicum \ casper \ com_err \ compiler_rt \ crypt \ crypto \ ctf \ cuse \ cxxrt \ devctl \ devinfo \ devstat \ dialog \ dpv \ dtrace \ dwarf \ edit \ elf \ execinfo \ fetch \ figpar \ geom \ gnuregex \ gpio \ gssapi \ gssapi_krb5 \ hdb \ heimbase \ heimntlm \ heimsqlite \ hx509 \ ipsec \ jail \ kadm5clnt \ kadm5srv \ kafs5 \ kdc \ kiconv \ krb5 \ kvm \ l \ lzma \ m \ magic \ md \ memstat \ mp \ mt \ nandfs \ ncurses \ ncursesw \ netgraph \ ngatm \ nv \ opie \ pam \ panel \ panelw \ pcap \ pcsclite \ pjdlog \ pmc \ proc \ procstat \ pthread \ radius \ readline \ roken \ rpcsec_gss \ rpcsvc \ rt \ rtld_db \ sbuf \ sdp \ sm \ smb \ ssl \ ssp_nonshared \ stdthreads \ supcplusplus \ tacplus \ termcapw \ ufs \ ugidfw \ ulog \ usb \ usbhid \ util \ vmmapi \ wind \ wrap \ xo \ y \ ypclnt \ z _DP_archive= z bz2 lzma bsdxml .if ${MK_OPENSSL} != "no" _DP_archive+= crypto .else _DP_archive+= md .endif _DP_ssl= crypto _DP_ssh= crypto crypt .if ${MK_LDNS} != "no" _DP_ssh+= ldns z .endif _DP_edit= ncursesw .if ${MK_OPENSSL} != "no" _DP_bsnmp= crypto .endif _DP_geom= bsdxml sbuf _DP_cam= sbuf _DP_casper= capsicum nv pjdlog _DP_capsicum= nv +_DP_kvm= elf _DP_pjdlog= util _DP_opie= md _DP_usb= pthread _DP_unbound= pthread _DP_rt= pthread .if ${MK_OPENSSL} == "no" _DP_radius= md .else _DP_radius= crypto .endif _DP_procstat= kvm util elf .if ${MK_CXX} == "yes" .if ${MK_LIBCPLUSPLUS} != "no" _DP_proc= cxxrt .else _DP_proc= supcplusplus .endif .endif .if ${MK_CDDL} != "no" _DP_proc+= ctf .endif _DP_mp= crypto _DP_memstat= kvm _DP_magic= z _DP_mt= bsdxml _DP_ldns= crypto .if ${MK_OPENSSL} != "no" _DP_fetch= ssl crypto .else _DP_fetch= md .endif _DP_execinfo= elf _DP_dwarf= elf _DP_dpv= dialog figpar util _DP_dialog= ncursesw m _DP_cuse= pthread _DP_atf_cxx= atf_c _DP_devstat= kvm _DP_pam= radius tacplus opie md util .if ${MK_KERBEROS} != "no" _DP_pam+= krb5 .endif .if ${MK_OPENSSH} != "no" _DP_pam+= ssh .endif .if ${MK_NIS} != "no" _DP_pam+= ypclnt .endif _DP_krb5+= asn1 com_err crypt crypto hx509 roken wind heimbase heimipcc \ pthread _DP_gssapi_krb5+= gssapi krb5 crypto roken asn1 com_err _DP_lzma= pthread _DP_ucl= m _DP_vmmapi= util _DP_ctf= z _DP_proc= rtld_db util _DP_dtrace= rtld_db pthread _DP_xo= util # Define spacial cases LDADD_supcplusplus= -lsupc++ LIBATF_C= ${DESTDIR}${LIBDIR}/libprivateatf-c.a LIBATF_CXX= ${DESTDIR}${LIBDIR}/libprivateatf-c++.a LDADD_atf_c= -lprivateatf-c LDADD_atf_cxx= -lprivateatf-c++ .for _l in ${_PRIVATELIBS} LIB${_l:tu}?= ${DESTDIR}${LIBDIR}/libprivate${_l}.a .endfor .for _l in ${_LIBRARIES} .if ${_INTERNALLIBS:M${_l}} LDADD_${_l}_L+= -L${LIB${_l:tu}DIR} .endif DPADD_${_l}?= ${LIB${_l:tu}} .if ${_PRIVATELIBS:M${_l}} LDADD_${_l}?= -lprivate${_l} .else LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l} .endif .if defined(_DP_${_l}) && defined(NO_SHARED) && (${NO_SHARED} != "no" && ${NO_SHARED} != "NO") .for _d in ${_DP_${_l}} DPADD_${_l}+= ${DPADD_${_d}} LDADD_${_l}+= ${LDADD_${_d}} .endfor .endif .endfor DPADD_atf_cxx+= ${DPADD_atf_c} LDADD_atf_cxx+= ${LDADD_atf_c} DPADD_sqlite3+= ${DPADD_pthread} LDADD_sqlite3+= ${LDADD_pthread} DPADD_fifolog+= ${DPADD_z} LDADD_fifolog+= ${LDADD_z} DPADD_ipf+= ${DPADD_kvm} LDADD_ipf+= ${LDADD_kvm} DPADD_mt+= ${DPADD_sbuf} LDADD_mt+= ${LDADD_sbuf} DPADD_dtrace+= ${DPADD_ctf} ${DPADD_elf} ${DPADD_proc} LDADD_dtrace+= ${LDADD_ctf} ${LDADD_elf} ${LDADD_proc} # The following depends on libraries which are using pthread DPADD_hdb+= ${DPADD_pthread} LDADD_hdb+= ${LDADD_pthread} DPADD_kadm5srv+= ${DPADD_pthread} LDADD_kadm5srv+= ${LDADD_pthread} DPADD_krb5+= ${DPADD_pthread} LDADD_krb5+= ${LDADD_pthread} DPADD_gssapi_krb5+= ${DPADD_pthread} LDADD_gssapi_krb5+= ${LDADD_pthread} .for _l in ${LIBADD} DPADD+= ${DPADD_${_l}:Umissing-dpadd_${_l}} LDADD+= ${LDADD_${_l}} .endfor .if defined(DPADD) && ${DPADD:Mmissing-dpadd_*} .error Missing ${DPADD:Mmissing-dpadd_*:S/missing-dpadd_//:S/^/DPADD_/} variable add "${DPADD:Mmissing-dpadd_*:S/missing-dpadd_//}" to _LIBRARIES, _INTERNALLIBS, or _PRIVATELIBS and define "${DPADD:Mmissing-dpadd_*:S/missing-dpadd_//:S/^/LIB/:tu}". .endif LIBELFTCDIR= ${OBJTOP}/lib/libelftc LIBELFTC?= ${LIBELFTCDIR}/libelftc.a LIBREADLINEDIR= ${OBJTOP}/gnu/lib/libreadline/readline LIBREADLINE?= ${LIBREADLINEDIR}/libreadline.a LIBOPENBSDDIR= ${OBJTOP}/lib/libopenbsd LIBOPENBSD?= ${LIBOPENBSDDIR}/libopenbsd.a LIBSMDIR= ${OBJTOP}/lib/libsm LIBSM?= ${LIBSMDIR}/libsm.a LIBSMDBDIR= ${OBJTOP}/lib/libsmdb LIBSMDB?= ${LIBSMDBDIR}/libsmdb.a LIBSMUTILDIR= ${OBJTOP}/lib/libsmutil LIBSMUTIL?= ${LIBSMDBDIR}/libsmutil.a LIBNETBSDDIR?= ${OBJTOP}/lib/libnetbsd LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd.a LIBVERSDIR?= ${OBJTOP}/kerberos5/lib/libvers LIBVERS?= ${LIBVERSDIR}/libvers.a LIBSLDIR= ${OBJTOP}/kerberos5/lib/libsl LIBSL?= ${LIBSLDIR}/libsl.a LIBIPFDIR= ${OBJTOP}/sbin/ipf/libipf LIBIPF?= ${LIBIPFDIR}/libipf.a LIBTELNETDIR= ${OBJTOP}/lib/libtelnet LIBTELNET?= ${LIBTELNETDIR}/libtelnet.a LIBCRONDIR= ${OBJTOP}/usr.sbin/cron/lib LIBCRON?= ${LIBCRONDIR}/libcron.a LIBNTPDIR= ${OBJTOP}/usr.sbin/ntp/libntp LIBNTP?= ${LIBNTPDIR}/libntp.a LIBNTPEVENTDIR= ${OBJTOP}/usr.sbin/ntp/libntpevent LIBNTPEVENT?= ${LIBNTPEVENTDIR}/libntpevent.a LIBOPTSDIR= ${OBJTOP}/usr.sbin/ntp/libopts LIBOTPS?= ${LIBOPTSDIR}/libopts.a LIBPARSEDIR= ${OBJTOP}/usr.sbin/ntp/libparse LIBPARSE?= ${LIBPARSEDIR}/libparse.a LIBLPRDIR= ${OBJTOP}/usr.sbin/lpr/common_source LIBLPR?= ${LIBOPTSDIR}/liblpr.a LIBFIFOLOGDIR= ${OBJTOP}/usr.sbin/fifolog/lib LIBFIFOLOG?= ${LIBOPTSDIR}/libfifolog.a LIBBSNMPTOOLSDIR= ${OBJTOP}/usr.sbin/bsnmpd/tools/libbsnmptools LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools.a LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu LIBAMU?= ${LIBAMUDIR}/libamu/libamu.a # Define a directory for each library. This is useful for adding -L in when # not using a --sysroot or for meta mode bootstrapping when there is no # Makefile.depend. These are sorted by directory. LIBAVLDIR= ${OBJTOP}/cddl/lib/libavl LIBCTFDIR= ${OBJTOP}/cddl/lib/libctf LIBDTRACEDIR= ${OBJTOP}/cddl/lib/libdtrace LIBNVPAIRDIR= ${OBJTOP}/cddl/lib/libnvpair LIBUMEMDIR= ${OBJTOP}/cddl/lib/libumem LIBUUTILDIR= ${OBJTOP}/cddl/lib/libuutil LIBZFSDIR= ${OBJTOP}/cddl/lib/libzfs LIBZFS_COREDIR= ${OBJTOP}/cddl/lib/libzfs_core LIBZPOOLDIR= ${OBJTOP}/cddl/lib/libzpool LIBDIALOGDIR= ${OBJTOP}/gnu/lib/libdialog LIBGCOVDIR= ${OBJTOP}/gnu/lib/libgcov LIBGOMPDIR= ${OBJTOP}/gnu/lib/libgomp LIBGNUREGEXDIR= ${OBJTOP}/gnu/lib/libregex LIBSSPDIR= ${OBJTOP}/gnu/lib/libssp LIBSSP_NONSHAREDDIR= ${OBJTOP}/gnu/lib/libssp/libssp_nonshared LIBSUPCPLUSPLUSDIR= ${OBJTOP}/gnu/lib/libsupc++ LIBASN1DIR= ${OBJTOP}/kerberos5/lib/libasn1 LIBGSSAPI_KRB5DIR= ${OBJTOP}/kerberos5/lib/libgssapi_krb5 LIBGSSAPI_NTLMDIR= ${OBJTOP}/kerberos5/lib/libgssapi_ntlm LIBGSSAPI_SPNEGODIR= ${OBJTOP}/kerberos5/lib/libgssapi_spnego LIBHDBDIR= ${OBJTOP}/kerberos5/lib/libhdb LIBHEIMBASEDIR= ${OBJTOP}/kerberos5/lib/libheimbase LIBHEIMIPCCDIR= ${OBJTOP}/kerberos5/lib/libheimipcc LIBHEIMIPCSDIR= ${OBJTOP}/kerberos5/lib/libheimipcs LIBHEIMNTLMDIR= ${OBJTOP}/kerberos5/lib/libheimntlm LIBHX509DIR= ${OBJTOP}/kerberos5/lib/libhx509 LIBKADM5CLNTDIR= ${OBJTOP}/kerberos5/lib/libkadm5clnt LIBKADM5SRVDIR= ${OBJTOP}/kerberos5/lib/libkadm5srv LIBKAFS5DIR= ${OBJTOP}/kerberos5/lib/libkafs5 LIBKDCDIR= ${OBJTOP}/kerberos5/lib/libkdc LIBKRB5DIR= ${OBJTOP}/kerberos5/lib/libkrb5 LIBROKENDIR= ${OBJTOP}/kerberos5/lib/libroken LIBWINDDIR= ${OBJTOP}/kerberos5/lib/libwind LIBALIASDIR= ${OBJTOP}/lib/libalias/libalias LIBBLOCKSRUNTIMEDIR= ${OBJTOP}/lib/libblocksruntime LIBBSNMPDIR= ${OBJTOP}/lib/libbsnmp/libbsnmp LIBBSDXMLDIR= ${OBJTOP}/lib/libexpat LIBKVMDIR= ${OBJTOP}/lib/libkvm LIBPTHREADDIR= ${OBJTOP}/lib/libthr LIBMDIR= ${OBJTOP}/lib/msun LIBFORMDIR= ${OBJTOP}/lib/ncurses/form LIBFORMLIBWDIR= ${OBJTOP}/lib/ncurses/formw LIBMENUDIR= ${OBJTOP}/lib/ncurses/menu LIBMENULIBWDIR= ${OBJTOP}/lib/ncurses/menuw LIBTERMCAPDIR= ${OBJTOP}/lib/ncurses/ncurses LIBTERMCAPWDIR= ${OBJTOP}/lib/ncurses/ncursesw LIBPANELDIR= ${OBJTOP}/lib/ncurses/panel LIBPANELWDIR= ${OBJTOP}/lib/ncurses/panelw LIBCRYPTODIR= ${OBJTOP}/secure/lib/libcrypto LIBSSHDIR= ${OBJTOP}/secure/lib/libssh LIBSSLDIR= ${OBJTOP}/secure/lib/libssl LIBTEKENDIR= ${OBJTOP}/sys/teken/libteken LIBEGACYDIR= ${OBJTOP}/tools/build LIBLNDIR= ${OBJTOP}/usr.bin/lex/lib # Default other library directories to lib/libNAME. .for lib in ${_LIBRARIES} LIB${lib:tu}DIR?= ${OBJTOP}/lib/lib${lib} .endfor .endif # !target(____) Index: head/sys/sparc64/include/kerneldump.h =================================================================== --- head/sys/sparc64/include/kerneldump.h (revision 291405) +++ head/sys/sparc64/include/kerneldump.h (revision 291406) @@ -1,51 +1,52 @@ /*- * Copyright (c) 2002 by Thomas Moestl . * 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 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. * * $FreeBSD$ */ #ifndef _MACHINE_KERNELDUMP_H_ #define _MACHINE_KERNELDUMP_H_ struct sparc64_dump_reg { - vm_paddr_t dr_pa; - vm_offset_t dr_size; - vm_offset_t dr_offs; + uint64_t dr_pa; + uint64_t dr_size; + uint64_t dr_offs; }; /* * Kernel dump format for sparc64. This does not use ELF because it is of no * avail (only libkvm knows how to translate addresses properly anyway) and * would require some ugly hacks. */ struct sparc64_dump_hdr { - vm_offset_t dh_hdr_size; - vm_paddr_t dh_tsb_pa; - vm_size_t dh_tsb_size; - vm_size_t dh_tsb_mask; - int dh_nregions; + uint64_t dh_hdr_size; + uint64_t dh_tsb_pa; + uint64_t dh_tsb_size; + uint64_t dh_tsb_mask; + int32_t dh_nregions; + int32_t dh_pad; struct sparc64_dump_reg dh_regions[]; }; #endif /* _MACHINE_KERNELDUMP_H_ */