void print_stack(struct object_heap* oh) { struct Interpreter* i = oh->cached.interpreter; word_t size = i->stackPointer; word_t j; for (j=0; j < size; j++) { fprintf(stderr, "stack[%" PRIdPTR "] = ", j); print_detail(oh, i->stack->elements[j]); } }
static int handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi, GElf_Addr pc, struct stuff *stuff) { int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame); if (result != 0) { error (0, 0, "dwarf_addrframe (%s): %s", which, dwfl_errmsg (-1)); return 1; } Dwarf_Addr start = pc; Dwarf_Addr end = pc; bool signalp; int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp); if (ra_regno >= 0) { start += stuff->bias; end += stuff->bias; } printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n", which, pc, start, end); if (ra_regno < 0) printf ("\treturn address register unavailable (%s)\n", dwarf_errmsg (0)); else printf ("\treturn address in reg%u%s\n", ra_regno, signalp ? " (signal frame)" : ""); Dwarf_Op *cfa_ops; size_t cfa_nops; result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops); printf ("\tCFA "); print_detail (result, cfa_ops, cfa_nops, stuff->bias); (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc), &print_register, stuff); return 0; }
static int print_register (void *arg, int regno, const char *setname, const char *prefix, const char *regname, int bits __attribute__ ((unused)), int type __attribute__ ((unused))) { struct stuff *stuff = arg; printf ("\t%s reg%u (%s%s): ", setname, regno, prefix, regname); Dwarf_Op ops_mem[2]; Dwarf_Op *ops; size_t nops; int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops); print_detail (result, ops, nops, stuff->bias); return DWARF_CB_OK; }
void print_backtrace(struct object_heap* oh) { word_t depth = 0, detail_depth = -1 /*raise this to print verbose args in stack longer*/; struct Interpreter* i = oh->cached.interpreter; struct Closure* closure = (struct Closure*)i->method; word_t codePointer = i->codePointer; word_t fp = i->framePointer; word_t sp = i->stackPointer; word_t codeSize = i->codeSize; word_t resultStackPointer = object_to_smallint(i->stack->elements[fp - FRAME_OFFSET_RESULT_STACK_POINTER]); struct LexicalContext* lc = (struct LexicalContext*)i->stack->elements[fp - FRAME_OFFSET_LEXICAL_CONTEXT];; fprintf(stderr, "printing backtrace from fp=%" PRIdPTR ", sp=%" PRIdPTR "\n", fp, i->stackPointer); do { word_t j; struct Object** vars; word_t input_count = object_to_smallint(closure->method->inputVariables); word_t local_count = object_to_smallint(closure->method->localVariables); vars = (closure->method->heapAllocate == oh->cached.true_object)? (&lc->variables[0]) : (&i->stack->elements[fp]); fprintf(stderr, "------------------------------\n"); fprintf(stderr, "FP: %" PRIdPTR "\n", fp); fprintf(stderr, "SP: %" PRIdPTR "\n", sp); fprintf(stderr, "IP: %" PRIdPTR "/%" PRIdPTR "\n", codePointer, codeSize); fprintf(stderr, "result: %" PRIdPTR "\n", resultStackPointer); fprintf(stderr, "code: %p\n", closure->method->code); fprintf(stderr, "selector #"); print_byte_array((struct Object*)(closure->method->selector)); fprintf(stderr, "\n"); fprintf(stderr, "regs: %" PRIdPTR "\n", object_to_smallint(closure->method->registerCount)); fprintf(stderr, "heap alloc: %s\n", (closure->method->heapAllocate == oh->cached.true_object)? "true" : "false"); for (j = 0; j < input_count; j++) { fprintf(stderr, "arg[%" PRIdPTR "] (%p) = ", j, (void*)vars[j]); if (depth > detail_depth) { print_type(oh, vars[j]); } else { print_detail(oh, vars[j]); } } if (closure->method->heapAllocate == oh->cached.true_object) { for (j = 0; j < local_count; j++) { fprintf(stderr, "var[%" PRIdPTR "] (%p)= ", j, (void*)lc->variables[j]); if (depth > detail_depth) { print_type(oh, lc->variables[j]); } else { print_detail(oh, lc->variables[j]); } } } else { for (j = input_count; j < input_count + local_count; j++) { fprintf(stderr, "var[%" PRIdPTR "] (%p) = ", j - input_count, (void*)vars[j]); if (depth > detail_depth) { print_type(oh, vars[j]); } else { print_detail(oh, vars[j]); } } } /*order matters here*/ codePointer = object_to_smallint(i->stack->elements[fp - FRAME_OFFSET_CODE_POINTER]); fp = object_to_smallint(i->stack->elements[fp - FRAME_OFFSET_PREVIOUS_FRAME_POINTER]); if (fp < FUNCTION_FRAME_SIZE) break; sp = object_to_smallint(i->stack->elements[fp - FRAME_OFFSET_BEFORE_CALL_STACK_POINTER]); resultStackPointer = object_to_smallint(i->stack->elements[fp - FRAME_OFFSET_RESULT_STACK_POINTER]); closure = (struct Closure*)i->stack->elements[fp - FRAME_OFFSET_METHOD]; lc = (struct LexicalContext*)i->stack->elements[fp - FRAME_OFFSET_LEXICAL_CONTEXT]; codeSize = array_size(closure->method->code); depth++; } while (fp >= FUNCTION_FRAME_SIZE); }
/* * This is the main dispatch function * */ struct MethodDefinition* method_dispatch_on(struct object_heap* oh, struct Symbol* name, struct Object* arguments[], word_t arity, struct Object* resendMethod) { struct MethodDefinition *dispatch, *bestDef; struct Object* slotLocation; word_t bestRank, depth, delegationCount, resendRank, restricted, i; #ifdef PRINT_DEBUG_DISPATCH fprintf(stderr, "dispatch to: '"); print_symbol(name); fprintf(stderr, "' (arity: %" PRIdPTR ")\n", arity); for (i = 0; i < arity; i++) { fprintf(stderr, "arguments[%" PRIdPTR "] (%p) = ", i, (void*)arguments[i]); print_type(oh, arguments[i]); } /* fprintf(stderr, "resend: "); print_object(resendMethod);*/ #endif dispatch = NULL; slotLocation = NULL; #ifndef SLATE_DISABLE_METHOD_CACHE if (resendMethod == NULL && arity <= METHOD_CACHE_ARITY) { dispatch = method_check_cache(oh, name, arguments, arity); if (dispatch != NULL) return dispatch; } #endif oh->current_dispatch_id++; bestRank = 0; bestDef = NULL; resendRank = ((resendMethod == NULL) ? WORDT_MAX : 0); for (i = 0; i < arity; i++) { struct Object *obj; struct Map* map; struct Object* arg = arguments[i]; delegationCount = 0; depth = 0; restricted = WORDT_MAX; /*pointer in delegate_stack (with sp of delegateCount) to where we don't trace further*/ do { /* Set up obj to be a pointer to the object, or SmallInteger if it's a direct SmallInt. */ if (object_is_smallint(arg)) { obj = get_special(oh, SPECIAL_OOP_SMALL_INT_PROTO); } else { obj = arg; } /* Identify the map, and update its dispatchID and reset the visited mask if it hasn't been visited during this call already. */ map = obj->map; if (map->dispatchID != oh->current_dispatch_id) { map->dispatchID = oh->current_dispatch_id; map->visitedPositions = 0; } /* we haven't been here before */ if ((map->visitedPositions & (1 << i)) == 0) { struct RoleEntry* role; /* If the map marks an obj-meta transition and the top of the stack is not the original argument, then mark the restriction point at the top of the delegation stack. */ if (((word_t)map->flags & MAP_FLAG_RESTRICT_DELEGATION) && (arg != arguments[i])) { restricted = delegationCount; } map->visitedPositions |= (1 << i); role = role_table_entry_for_name(oh, map->roleTable, name); while (role != NULL) { if ((object_to_smallint(role->rolePositions) & (1 << i)) != 0) { struct MethodDefinition* def = role->methodDefinition; /* If the method hasn't been visited this time, mark it so and clear the other dispatch marks.*/ if (def->dispatchID != oh->current_dispatch_id) { def->dispatchID = oh->current_dispatch_id; def->foundPositions = 0; def->dispatchRank = 0; } /*If the method hasn't been found at this position...*/ if ((def->foundPositions & (1 << i)) == 0) { /*fix*/ def->dispatchRank |= ((31 - depth) << ((5 - i) * 5)); def->foundPositions |= (1 << i); #ifdef PRINT_DEBUG_FOUND_ROLE fprintf(stderr, "found role index %" PRIdPTR " <%p> for '%s' foundPos: %" PRIuPTR "x dispatchPos: %" PRIuPTR "x\n", i, (void*) role, ((struct Symbol*)(role->name))->elements, def->foundPositions, def->dispatchPositions); #endif if (def->method == resendMethod) { struct RoleEntry* rescan = role_table_entry_for_name(oh, map->roleTable, name); resendRank = def->dispatchRank; while (rescan != role) { struct MethodDefinition* redef = rescan->methodDefinition; if (redef->foundPositions == redef->dispatchPositions && (dispatch == NULL || redef->dispatchRank <= resendRank)) { dispatch = redef; slotLocation = obj; if (redef->dispatchRank > bestRank) { bestRank = redef->dispatchRank; bestDef = redef; } } if (rescan->nextRole == oh->cached.nil) { rescan = NULL; } else { rescan = &map->roleTable->roles[object_to_smallint(rescan->nextRole)]; } } } else /*not a resend*/ { if (def->foundPositions == def->dispatchPositions && (dispatch == NULL || def->dispatchRank > dispatch->dispatchRank) && def->dispatchRank <= resendRank) { dispatch = def; slotLocation = obj; if (def->dispatchRank > bestRank) { bestRank = def->dispatchRank; bestDef = def; } } } if (def->dispatchRank >= bestRank && def != bestDef) { bestRank = def->dispatchRank; bestDef = NULL; } } } role = ((role->nextRole == oh->cached.nil) ? NULL : &map->roleTable->roles[object_to_smallint(role->nextRole)]); } /*while role != NULL*/ if (depth > 31) { /*fix wordsize*/ assert(0); } if (dispatch != NULL && bestDef == dispatch) { if (dispatch->slotAccessor != oh->cached.nil) { arguments[0] = slotLocation; /*do we need to try to do a heap_store_into?*/ #ifdef PRINT_DEBUG_DISPATCH_SLOT_CHANGES fprintf(stderr, "arguments[0] changed to slot location: \n"); print_detail(oh, arguments[0]); #endif } if (resendMethod == 0 && arity <= METHOD_CACHE_ARITY) method_save_cache(oh, dispatch, name, arguments, arity); return dispatch; } depth++; /* We add the delegates to the list when we didn't just finish checking a restricted object*/ if (delegationCount <= restricted && array_size(map->delegates) > 0) { struct OopArray* delegates = map->delegates; word_t offset = object_array_offset((struct Object*)delegates); word_t limit = object_total_size((struct Object*)delegates); for (; offset != limit; offset += sizeof(word_t)) { struct Object* delegate = object_slot_value_at_offset((struct Object*)delegates, offset); if (delegate != oh->cached.nil) { oh->delegation_stack[delegationCount++] = delegate; } } } } /*end haven't been here before*/ delegationCount--; if (delegationCount < restricted) restricted = WORDT_MAX; /*everything is unrestricted now*/ if (delegationCount < 0 || delegationCount >= DELEGATION_STACK_SIZE) break; arg = oh->delegation_stack[delegationCount]; } while (1); } if (dispatch != NULL && dispatch->slotAccessor != oh->cached.nil) { /*check heap store into?*/ arguments[0] = slotLocation; #ifdef PRINT_DEBUG_DISPATCH_SLOT_CHANGES fprintf(stderr, "arguments[0] changed to slot location: \n"); print_detail(oh, arguments[0]); #endif } #ifndef SLATE_DISABLE_METHOD_CACHE if (dispatch != NULL && resendMethod == 0 && arity < METHOD_CACHE_ARITY) { method_save_cache(oh, dispatch, name, arguments, arity); } #endif return dispatch; }
static void detail(char *toks[], int t, struct config *conf, int row, int col) { int x=0; char msg[1024]=""; const char *tmp=NULL; if(toks[0]) { snprintf(msg, sizeof(msg), "Client: %s", toks[0]); print_line(msg, x++, col); } if(toks[1]) { switch(*(toks[1])) { case STATUS_IDLE: { print_line("Status: idle", x++, col); show_all_backups(toks, t, &x, col); return; } case STATUS_SERVER_CRASHED: { print_line("Status: server crashed", x++, col); show_all_backups(toks, t, &x, col); return; } case STATUS_CLIENT_CRASHED: { print_line("Status: client crashed", x++, col); show_all_backups(toks, t, &x, col); return; } case STATUS_RUNNING: { if(toks[2]) { char msg[64]=""; if(t<3) return; snprintf(msg, sizeof(msg), "Status: running (%s)", running_status_to_text( *(toks[2]))); print_line(msg, x++, col); } break; } } } print_line("", x++, col); table_header(&x, col); if(t>4) print_detail("Files", toks[4], &x, col, 0); if(t>5) print_detail("Encrypted files", toks[5], &x, col, 0); if(t>6) print_detail("Meta data", toks[6], &x, col, 0); if(t>7) print_detail("Encrypted meta data", toks[7], &x, col, 0); if(t>8) print_detail("Directories", toks[8], &x, col, 0); if(t>9) print_detail("Soft links", toks[9], &x, col, 0); if(t>10) print_detail("Hard links", toks[10], &x, col, 0); if(t>11) print_detail("Special files", toks[11], &x, col, 0); if(t>12) { print_detail("Total", toks[12], &x, col, 1); } print_line("", x++, col); if(t>14) print_detail2("Warnings", toks[14], "", &x, col); if(t>15) { tmp=bytes_to_human_str(toks[15]); print_detail2("Bytes expected", toks[15], tmp, &x, col); } if(t>16) { tmp=bytes_to_human_str(toks[16]); print_detail2("Bytes in backup", toks[16], tmp, &x, col); } if(t>17) { tmp=bytes_to_human_str(toks[17]); print_detail2("Bytes received", toks[17], tmp, &x, col); } if(t>18) { tmp=bytes_to_human_str(toks[18]); print_detail2("Bytes sent", toks[18], tmp, &x, col); } if(t>19) { long start=0; time_t now=0; time_t diff=0; now=time(NULL); start=atol(toks[19]); diff=now-start; print_detail2("Start time", getdatestr(start), " ", &x, col); print_detail2("Time taken", time_taken(diff), " ", &x, col); if(diff>0) { unsigned long long bytesleft=0; unsigned long long byteswant=0; unsigned long long bytesgot=0; float bytespersec=0; byteswant=strtoull(toks[15], NULL, 10); bytesgot=strtoull(toks[16], NULL, 10); bytespersec=(float)(bytesgot/diff); bytesleft=byteswant-bytesgot; if(bytespersec>0) { time_t timeleft=0; timeleft=(time_t)(bytesleft/bytespersec); print_detail2("Time left", time_taken(timeleft), " ", &x, col); } } } if(t>20 && toks[20]) { #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { printw("\n%s\n", toks[20]); return; } #else printf("\n%s\n", toks[20]); #endif } }