setcor() { fcor = datmap.ufd = getfile(corfil,2); if (kernel && fcor != -1 && INKERNEL(filhdr.a_entry)) { struct stat stb; kcore = 1; fstat(fcor, &stb); datmap.b1 = 0; datmap.e1 = -1; if (kernel == 0 && (stb.st_mode & S_IFREG)) datmap.b1 = 0x80000000; lookup("_Sysmap"); sbr = cursym->n_value; lookup("_Syssize"); slr = cursym->n_value; printf("sbr %x slr %x\n", sbr, slr); lookup("_masterpaddr"); physrw(fcor, KVTOPH(cursym->n_value), &masterpcbb, 1); masterpcbb = (masterpcbb&PG_PFNUM)*NBPG; getpcb(); findstackframe(); return; } if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) || !INUDOT(u.u_pcb.pcb_ksp) || !INSTACK(u.u_pcb.pcb_usp)) { datmap.e1 = MAXFILE; return; } signo = u.u_arg[0]; sigcode = u.u_code; filhdr.a_text = ctob(u.u_tsize); filhdr.a_data = ctob(u.u_dsize); stksiz = ctob(u.u_ssize); switch (filhdr.a_magic) { case OMAGIC: datmap.b1 = 0; datmap.e1 = filhdr.a_text+filhdr.a_data; datmap.f2 = ctob(UPAGES) + datmap.e1; break; case NMAGIC: case ZMAGIC: datmap.b1 = round(filhdr.a_text, PAGSIZ); datmap.e1 = datmap.b1 + filhdr.a_data; datmap.f2 = ctob(UPAGES) + filhdr.a_data; break; } datbas = datmap.b1; datmap.f1 = ctob(UPAGES); datmap.b2 = MAXSTOR - stksiz; datmap.e2 = MAXSTOR; }
static void internal_pthread_backtrace(pthread_t thread, void** buffer, size_t max, size_t* depth, size_t skip) { *depth = 0; //! Get information about the stack (pos & size). uint8_t* stackbot; size_t stack_size; //! in bytes size_t guard_size; //! in bytes #if defined(__FreeBSD__) pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_get_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #elif defined(__APPLE__) stackbot = (uint8_t*)pthread_get_stackaddr_np(thread); stack_size = pthread_get_stacksize_np(thread); guard_size = 0; //FIXME anyway to get that? #else pthread_attr_t attr; pthread_getattr_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #endif stack_size -= guard_size; //! The thread is is still running!!! //! So make a buffer copy of the stack, else it gets changed while we reading from it! std::vector<uint8_t> sbuffer(stack_size); uint8_t* stack_buffer = &sbuffer[0]; memcpy(stack_buffer, stackbot, stack_size); //! It is impossible to get the current frame (the current function pos) on the stack //! for other pthreads, so we need to find it ourself. The beneath method is very naive //! and just searchs for the starting address that gives us the longest stackdepth. unsigned longest_stack = 0; unsigned longest_offset = 0; int check_area = MAX(0, stack_size - 1024*sizeof(uintptr_t)); check_area *= 0.8f; //! only check ~20% from the top of the stack for (int offset = stack_size - sizeof(uintptr_t); offset >= check_area; offset -= sizeof(uintptr_t)) { unsigned stack_depth = 0; uint8_t* frame = stack_buffer + offset; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); uint8_t* last_frame = frame; while (INSTACK(frame) && (frame > last_frame)) { last_frame = frame; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); stack_depth++; } if (stack_depth > longest_stack) { longest_stack = stack_depth; longest_offset = offset; } } //! Now get the list of function addresses from the stack. uint8_t* frame = stack_buffer + longest_offset; if(!INSTACK(frame)) return; while (skip--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); if(!INSTACK(next)) return; frame = next; } while (max--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); buffer[*depth] = (void*)*((uintptr_t*)frame + FP_OFFSET); (*depth)++; if(!INSTACK(next)) return; frame = next; } }