Exemplo n.º 1
0
void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters)
{
    Object object = initStackPointers(pExceptionRegisters);
    advanceStackPointerToValueBeforeException(&object);
    initFloatingPointFlag(&object);

    do
    {
        setStackSentinel();
        CrashCatcher_DumpStart();
        dumpSignature(&object);
        dumpFlags(&object);
        dumpR0toR3(&object);
        dumpR4toR11(&object);
        dumpR12(&object);
        dumpSP(&object);
        dumpLR_PC_PSR(&object);
        dumpExceptionPSR(&object);
        if (object.flags & CRASH_CATCHER_FLAGS_FLOATING_POINT)
            dumpFloatingPointRegisters(&object);
        dumpMemoryRegions(CrashCatcher_GetMemoryRegions());
        if (!isARMv6MDevice())
            dumpFaultStatusRegisters();
        checkStackSentinelForStackOverflow();
    }
    while (CrashCatcher_DumpEnd() == CRASH_CATCHER_TRY_AGAIN);
}
Exemplo n.º 2
0
static void
errMsg(args *argv, uint8_t *message, ...)
{
	va_list plist;

	va_start(plist, message);
	vsprintf(workSpace(argv), message, plist);
	va_end(plist);
	dumpFlags(argv) |= J9TPF_ERRMSG_IN_WKSPC;
	return;
}
Exemplo n.º 3
0
/**
 * \internal Build the z/TPF ELF-format core dump from the JDB built by CCCPSE.
 *
 * First figure out the absolute file path (starts with a '/' and
 * ends with a file suffix) we are to write the dump to, then ensure we
 * have enough room left over in the Java dump buffer left for us by 
 * CCCPSE. If we do not, return an error. Otherwise, section the buffer
 * space off, building in order:
 *    - The ELF64 header
 *    - The ELF64 Program Header section
 *    - The ELF64 NOTE section
 *      
 * Finally, write all the above to the indicated filename, and follow it
 * with a copy of storage contents from the Java dump buffer, which is
 * laid out in ascending address order, with the ELF64_Phdrs created to
 * match the dump buffer. Expect a final file size measured in tens
 * of megabytes.
 *
 * As a matter of protocol, set the first 8 bytes of the Java Dump
 * Buffer (struct ijavdbf) to zeros so CCCPSE knows it's okay to 
 * write over its contents once we're done working with it.
 *
 * The arg block is used for the bi-directional passing of data. Those of its
 * members which are pointers (most of them, in fact) are used mainly for 
 * output or at least have an output role. The fields of <arg> which are
 * required are shown as input parameters below. The fields of <arg> which
 * are used for output are detailed as return values.
 *
 * Since the pthread_create() calls limits us to one pointer to type void as the
 * function's input, and the function is required to return a void pointer, this
 * function will take the address of the <arg> block as the input parameter, and
 * will return a pointer to type char which represents the file name which now
 * contains the full path name of the ELF-format core dump file. There are also 
 * fields in <arg> that will be updated as described below.
 *
 * \param[in][out]     arg   pointer to a user-created datatype 'args', declared
 *                           in header file j9osdump_helpers.h
 * \param[in]        arg->OSFilename        Pointer to scratch storage for a path +
 *                                        file name string. It will be presumed 
 *                                        to be at least PATH_MAX+1 in size.
 * \param[in]        arg->wkspcSize        32-bit quantity representing the size in
 *                                        bytes of the wkSpace field, following.
 * \param[in]        arg->wkSpace        64-bit pointer to scratch workspace for
 *                                        use by this function. It is recommended
 *                                        to make it equal to PATH_MAX, since file &
 *                                        path names will be built in this space.
 * \param[in][out]    arg->flags            Indicators as to what is present and what
 *                                        is not.
 * \param[in]        arg->sii            Pointer to scratch storage to be used 
 *                                        forever more as a siginfo_t block
 * \param[in]        arg->uct            Pointer to scratch storage to be used 
 *                                        forever more as a ucontext_t block
 * \param[in]        arg->sct            Pointer to scratch storage to be used 
 *                                        forever more as a sigcontext block
 * \param[in]        arg->portLibrary    Pointer to an initialized OMRPortLibrary
 *                                        block. If there isn't one at call time,
 *                                        leave this value NULL and set flag
 *                                        J9ZTPF_NO_PORT_LIBRARY
 * \param[in]        arg->dibPtr            Address of the DIB attached to the faulting
 *                                        UOW at post-interrupt time.
 * 
 * \returns    Pointer to a hz-terminated string representing the absolute path
 *               name at which the core dump file was written.
 *            
 * \returns    arg->sii                   Filled in.
 * \returns    arg->uct                   Filled in.
 * \returns    arg->sct                   Filled in.
 * \returns    arg->rc                   Final return code. Zero if successful
 *                                       (core file built), non-zero if not.
 * \returns    arg->OSFilename           Same as the function return value.
 */
void *
ztpfBuildCoreFile(void *argv_block)
{
#define  MOUNT_TFS    4  /* TPF Filesystem equate from imount.h */

	args *arg = (args *) argv_block;
	uint8_t *buffer, *endBuffer;
	DBFHDR *dbfptr; /* Ptr to JDB's index header                */
	DIB *dibPtr = dibAddr(arg); /* Ptr to the Dump I'chg Block    */
	Elf64_Ehdr *ehdrp; /* Pointer to Elf64 file header                */
	Elf64_Phdr *phdrp; /* Pointer to Elf64_Phdr block                */
	Elf64_Nhdr *narea; /* Pointer to the ELF NOTE data                */
	char pathName[PATH_MAX]; /* Working buffer for core.* fname.*/
	char *ofn = dumpFilename(arg); /* Output dump file path    */
	uint32_t ofd; /* File descriptor for output dump            */
	uintptr_t rc; /* Working return code d.o.                    */
	uintptr_t wPtr; /* Working byte-sized pointer d.o.            */
	uint64_t phCount; /* Counter of Elf64_Phdrs required            */
	uint8_t *imageBuffer; /* Start of the JDB's ICB            */
	uint64_t imageBufferSize; /* Size of data in the ICB            */
	uint64_t octetsToWrite = 0UL; /* Count of bytes to write        */
	uint64_t octetsWritten = 0UL; /* Count of bytes written        */
	uint64_t spcAvailable;

	/*
	 *    If there is a Java dump buffer belonging to this process, then
	 *    convert its contents into an Elf64 core dump file; otherwise
	 *    return failure.
	 */
	if (!(dibPtr->dibjdb)) { /* No dump buffer? Not possible.*/
		dumpFlags(arg) |= J9TPF_NO_JAVA_DUMPBUFFER;
		returnCode (arg) = -1; /* Set error flags & bad RC ...    */
		return NULL; /* 'Bye.                        */
	}
	dbfptr = dibPtr->dibjdb; /* Pick up the dump buffer ptr    */
	if (0L == dbfptr->ijavcnt) { /* Did CCCPSE write us one?        */
		returnCode (arg) = -1; /* Nope. JDB is locked...        */
		dumpFlags(arg) |= J9TPF_JDUMPBUFFER_LOCKED;
		return NULL; /* See ya next time.            */
	}
	/*
	 *     Calculate the start, end, and net length of the output buffer we'll
	 *     use for the ELF-dictated start of the file content. The start address
	 *     should, as a matter of good practice, start on a paragraph boundary.
	 */
	buffer = (uint8_t *) (dbfptr->ijavbfp); /* Get buffer start as uint8_t ptr    */
	buffer = (uint8_t *) NEXT_PARA(buffer); /* Start it on next paragraph    */
	/*    boundary.                    */
	endBuffer = buffer + dbfptr->ijavbfl; /* Get bytes left in buffer        */
	spcAvailable = endBuffer - buffer; /* Get corrected count of bytes    */

	phCount = dbfptr->ijavcnt;

	int numJavaPgms = sizeof(javaPgmsToDump) / 5;
	octetsToWrite = sizeof(Elf64_Ehdr)
			+ ((phCount + 1 + numJavaPgms) * sizeof(Elf64_Phdr)) +
			NOTE_TABLE_SIZE;
	/*
	 *     Uh oh. Not enough free space remaining in the dump buffer. Now
	 *     we've gotta go to the heap and see if there's enough there. Not
	 *     much hope; but we have to try it.
	 */
	if (octetsToWrite > spcAvailable) { /* Check for available memory,    */
		buffer = malloc64(octetsToWrite); /*  anywhere. We're desperate.    */
		if (!buffer) { /* If we can't buffer our I/Os,    */
			returnCode (arg) = -1; /*  we are done. Indicate error */
			errMsg(arg, "Cannot buffer dump file, out of memory");
			dumpFlags(arg) |= J9TPF_OUT_OF_BUFFERSPACE;
			KEY0();
			dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
			UNKEY();
			return NULL; /* See ya 'round.                */
		}
	}
	/*
	 *    We're ready to write the file. First, we need a full path + filename
	 *    to represent the "OS filename" we're going to write. Get that path
	 *    from the final file name passed in the <tt>args</tt> block, then
	 *    follow that with "core.%X.%d" with the TOD in the second node and
	 *    the PID number in the third. In this way, we can identify the OS
	 *    filename later.
	 *
	 *    Next, we'll try to open it in CREATE+WRITE_ONLY mode. If it fails,
	 *    halt; else write away!
	 */
	splitPathName(ofn, pathName);
	/*
	 *    The "OS filename" will look like ${path}/core.${TOD_in_hex}.${pid}
	 */
	sprintf(workSpace(arg), "core.%lX.%d", dibPtr->dstckf,
			dumpSiginfo(arg)->si_pid);
	{
		int pathLen = strlen(pathName);
		char ebcdicPath[pathLen + 1];
		a2e_len(pathName, ebcdicPath, strlen(pathName));
		int fsystype = pathconf(ebcdicPath, _TPF_PC_FS_TYPE);
		if (fsystype == MOUNT_TFS) {
			errMsg(arg, "Cannot use the tfs for java dumps: path used='%s'\n",
					pathName);
			returnCode (arg) = -1;
			KEY0();
			dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
			UNKEY();
			return NULL;
			//dir_path_name is within the TFS
		}
	}
	strcat(pathName, workSpace(arg));
	ofd = open(pathName, O_WRONLY | O_CREAT | O_EXCL);

	if (-1 == ofd) {
		errMsg(arg, "Cannot open() filename %s: %s\n", strerror(errno));
		returnCode (arg) = -1;
		KEY0();
		dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
		UNKEY();
		return NULL;
	}
	/*
	 *    The file is named and opened. Now we have to go build its ELF-dictated
	 *    parts. Set up pointers to the start of each sub-section, and then go
	 *    build them. When that's complete, write the file in two parts: first,
	 *    the ELF-dictated start, and then follow that with the data in the
	 *    ICB.
	 */
	wPtr = (uintptr_t) buffer; /*    Calc section addresses with single    */
	                           /*     byte arithmetic                    */
	ehdrp = (Elf64_Ehdr *) wPtr; /*    Elf64_Ehdr pointer                    */
	phdrp = (Elf64_Phdr *) (ehdrp + 1); /*    Elf64_Phdr pointer                    */
	buildELFHeader(ehdrp);
	uint64_t numBytes = 0;
	uint64_t pCount = buildELFPheaderBlk(phdrp, dbfptr, phCount, &numBytes);
	KEY0(); /* Get into SPK 0, then write the        */
	ehdrp->e_phnum = pCount; /*  absolutely final Phdr count and     */
	ehdrp->e_phoff = 0x40; /*    offset of its table into place in    */
	UNKEY(); /*  the Ehdr, then get back to SPK 1.    */
	wPtr = (uintptr_t) phdrp; /* Calculate the end address        */
	wPtr += ((phCount + 1 + numJavaPgms) * sizeof(Elf64_Phdr)); /*    of the Elf64_Phdr section        */
	narea = (Elf64_Nhdr *) wPtr; /* Calculate the address of NOTE sec,    */
	buildELFNoteArea(narea, dibPtr); /*    and go write it there.                */
	/*
	 *    Write the ELF-dictated portion of the file first.
	 */
	octetsWritten = writeDumpFile(ofd, buffer, octetsToWrite);
	if (-1 == octetsWritten) {
		errMsg(arg, "Error writing dump file %s: %s", ofn, strerror(errno));
		dumpFlags(arg) |= J9TPF_FILE_SYSTEM_ERROR;
		KEY0();
		dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
		UNKEY();
		return NULL;
	}
	/*
	 *    Finish the output with the ICB portion of the Java Dump Buffer
	 */
	imageBuffer = (uint8_t *) cinfc_fast(CINFC_CMMJDB);
	octetsWritten = writeDumpFile(ofd, imageBuffer, numBytes);
	if (-1 == octetsWritten) {
		errMsg(arg, "Error writing dump file %s: %s", ofn, strerror(errno));
		dumpFlags(arg) |= J9TPF_FILE_SYSTEM_ERROR;
		KEY0();
		dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
		UNKEY();
		return NULL;
	}
	int i = 0;
	for (i = 0; i < numJavaPgms; i++) {
		struct pat * pgmpat = progc(javaPgmsToDump[i], PROGC_PBI);
		struct ifetch *pgmbase = pgmpat->patgca;
		if (pgmbase != NULL) {
			int offset = pgmbase->_iftch_txt_off + pgmbase->_iftch_txt_size
					+ 0x1000;
			char * text = ((char*) pgmbase) + offset;
			uint64_t size = pgmpat->patpsize - offset;
			octetsWritten = writeDumpFile(ofd, text, size);
			if (-1 == octetsWritten) {
				errMsg(arg, "Error writing dump file %s: %s", ofn,
						strerror(errno));
				dumpFlags(arg) |= J9TPF_FILE_SYSTEM_ERROR;
				KEY0();
				dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
				UNKEY();
				return NULL;
			}
		}
	}
	/*
	 *    That's all folks. Close the file and return the so-called "OS Filename"
	 *    to the caller as if the OS had written it.
	 */
	rc = close(ofd); /* Only try to close() the file once    */
	if (-1 == rc) {
		errMsg(arg, "I/O error attempting to close %s:%s\n", ofn,
				strerror(errno));
		KEY0();
		dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
		UNKEY();
		return NULL;
	}
	/*
	 * Make sure we have a recognizable IPC permission on the OS filename,
	 *  then make sure the JDB buffer is unlocked in case CPSE needs it again.
	 */
	rc = chmod(workSpace(arg), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
	KEY0();
	dbfptr->ijavcnt = 0L; /* Unlock the JDB so CCCPSE can reuse it*/
	UNKEY();
	/*
	 * Return the filename to the caller. Remember that the buffer containing
	 * it is non-JVM-managed heap space and should be free()d back to it to
	 * avoid a mem leak.
	 */
	strcpy(dumpFilename(arg), ofn); /* Store it in the args block so the */
	return (void *) ofn; /*  caller always has it, and goback.*/
}