tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount, int32 skipFrames, bool kernelOnly) { #if ENABLE_TRACING // page_fault_exception() doesn't allow us to gracefully handle a bad // address in the stack trace, if interrupts are disabled, so we always // restrict the stack traces to the kernel only in this case. A bad address // in the kernel stack trace would still cause a panic(), but this is // probably even desired. if (!are_interrupts_enabled()) kernelOnly = true; tracing_stack_trace* stackTrace = (tracing_stack_trace*)alloc_tracing_buffer( sizeof(tracing_stack_trace) + maxCount * sizeof(addr_t)); if (stackTrace != NULL) { stackTrace->depth = arch_debug_get_stack_trace( stackTrace->return_addresses, maxCount, 0, skipFrames + 1, STACK_TRACE_KERNEL | (kernelOnly ? 0 : STACK_TRACE_USER)); } return stackTrace; #else return NULL; #endif }
char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize, bool user) { if (source == NULL || maxSize == 0) return NULL; if (user && !IS_USER_ADDRESS(source)) return NULL; // limit maxSize to the actual source string len if (user) { ssize_t size = user_strlcpy(NULL, source, 0); // there's no user_strnlen() if (size < 0) return 0; maxSize = min_c(maxSize, (size_t)size + 1); } else maxSize = strnlen(source, maxSize - 1) + 1; char* buffer = (char*)alloc_tracing_buffer(maxSize); if (buffer == NULL) return NULL; if (user) { if (user_strlcpy(buffer, source, maxSize) < B_OK) return NULL; } else strlcpy(buffer, source, maxSize); return buffer; }
PollTraceEntry(pollfd* fds, int count, bool resultEvents) : fEntries(NULL), fCount(0) { if (fds != NULL && count > 0) { for (int i = 0; i < count; i++) { if (resultEvents ? fds[i].revents : fds[i].events) fCount++; } } if (fCount == 0) return; fEntries = (FDEntry*)alloc_tracing_buffer(fCount * sizeof(FDEntry)); if (fEntries != NULL) { for (int i = 0; i < fCount; fds++) { uint16 events = resultEvents ? fds->revents : fds->events; if (events != 0) { fEntries[i].fd = fds->fd; fEntries[i].events = events; i++; } } } }
SelectTraceEntry(int count, fd_set* readSet, fd_set* writeSet, fd_set* errorSet) : fReadSet(NULL), fWriteSet(NULL), fErrorSet(NULL), fCount(count) { int sets = (readSet != NULL ? 1 : 0) + (writeSet != NULL ? 1 : 0) + (errorSet != NULL ? 1 : 0); if (sets > 0 && count > 0) { uint32 bytes = _howmany(count, NFDBITS) * sizeof(fd_mask); uint8* allocated = (uint8*)alloc_tracing_buffer(bytes * sets); if (allocated != NULL) { if (readSet != NULL) { fReadSet = (fd_set*)allocated; memcpy(fReadSet, readSet, bytes); allocated += bytes; } if (writeSet != NULL) { fWriteSet = (fd_set*)allocated; memcpy(fWriteSet, writeSet, bytes); allocated += bytes; } if (errorSet != NULL) { fErrorSet = (fd_set*)allocated; memcpy(fErrorSet, errorSet, bytes); } } } }
uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user) { if (user && !IS_USER_ADDRESS(source)) return NULL; uint8* buffer = alloc_tracing_buffer(size); if (buffer == NULL) return NULL; if (user) { if (user_memcpy(buffer, source, size) != B_OK) return NULL; } else memcpy(buffer, source, size); return buffer; }