enum sym_get_lval symbol_picker_interactive(const char* name, const struct sgv_data* sgv, struct dbg_lvalue* rtn) { char buffer[512]; unsigned i; if (!dbg_interactiveP) { dbg_printf("More than one symbol named %s, picking the first one\n", name); *rtn = sgv->syms[0].lvalue; return sglv_found; } dbg_printf("Many symbols with name '%s', " "choose the one you want (<cr> to abort):\n", name); for (i = 0; i < sgv->num; i++) { if (sgv->num - sgv->num_thunks > 1 && (sgv->syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) continue; dbg_printf("[%d]: ", i + 1); if (sgv->syms[i].flags & SYMFLAG_LOCAL) { dbg_printf("%s %sof %s\n", sgv->syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", sgv->syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", name); } else if (sgv->syms[i].flags & SYMFLAG_THUNK) { print_address(&sgv->syms[i].lvalue.addr, TRUE); /* FIXME: should display where the thunks points to */ dbg_printf(" thunk %s\n", name); } else { print_address(&sgv->syms[i].lvalue.addr, TRUE); dbg_printf("\n"); } } do { i = 0; if (input_read_line("=> ", buffer, sizeof(buffer))) { if (buffer[0] == '\0') return sglv_aborted; i = atoi(buffer); if (i < 1 || i > sgv->num) dbg_printf("Invalid choice %d\n", i); } else return sglv_aborted; } while (i < 1 || i > sgv->num); /* The array is 0-based, but the choices are 1..n, * so we have to subtract one before returning. */ *rtn = sgv->syms[i - 1].lvalue; return sglv_found; }
static int source_display(const char* sourcefile, int start, int end) { char* addr; int i; struct open_file_list* ol; int nlines; const char* basename = NULL; char* pnt; int rtn; struct search_list* sl; HANDLE hMap; DWORD status; char tmppath[PATH_MAX]; /* * First see whether we have the file open already. If so, then * use that, otherwise we have to try and open it. */ ol = source_search_open_file(sourcefile); if (ol == NULL) { /* * Try again, stripping the path from the opened file. */ basename = strrchr(sourcefile, '\\'); if (!basename) basename = strrchr(sourcefile, '/'); if (!basename) basename = sourcefile; else basename++; ol = source_search_open_file(basename); } if (ol == NULL) { /* * Crapola. We need to try and open the file. */ status = GetFileAttributes(sourcefile); if (status != INVALID_FILE_ATTRIBUTES) { strcpy(tmppath, sourcefile); } else if ((status = GetFileAttributes(basename)) != INVALID_FILE_ATTRIBUTES) { strcpy(tmppath, basename); } else { for (sl = source_list_head; sl; sl = sl->next) { strcpy(tmppath, sl->path); if (tmppath[strlen(tmppath) - 1] != '/' && tmppath[strlen(tmppath) - 1] != '\\') { strcat(tmppath, "/"); } /* * Now append the base file name. */ strcat(tmppath, basename); status = GetFileAttributes(tmppath); if (status != INVALID_FILE_ATTRIBUTES) break; } if (sl == NULL) { if (dbg_interactiveP) { char zbuf[256]; /* * Still couldn't find it. Ask user for path to add. */ snprintf(zbuf, sizeof(zbuf), "Enter path to file '%s': ", sourcefile); input_read_line(zbuf, tmppath, sizeof(tmppath)); if (tmppath[strlen(tmppath) - 1] != '/') { strcat(tmppath, "/"); } /* * Now append the base file name. */ strcat(tmppath, basename); status = GetFileAttributes(tmppath); } else { status = INVALID_FILE_ATTRIBUTES; strcpy(tmppath, sourcefile); } if (status == INVALID_FILE_ATTRIBUTES) { /* * OK, I guess the user doesn't really want to see it * after all. */ ol = HeapAlloc(GetProcessHeap(), 0, sizeof(*ol)); ol->path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(sourcefile) + 1), sourcefile); ol->real_path = NULL; ol->next = source_ofiles; ol->nlines = 0; ol->linelist = NULL; source_ofiles = ol; dbg_printf("Unable to open file '%s'\n", tmppath); return FALSE; } } } /* * Create header for file. */ ol = HeapAlloc(GetProcessHeap(), 0, sizeof(*ol)); ol->path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(sourcefile) + 1), sourcefile); ol->real_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(tmppath) + 1), tmppath); ol->next = source_ofiles; ol->nlines = 0; ol->linelist = NULL; ol->size = 0; source_ofiles = ol; addr = source_map_file(tmppath, &hMap, &ol->size); if (addr == (char*)-1) return FALSE; /* * Now build up the line number mapping table. */ ol->nlines = 1; pnt = addr; while (pnt < addr + ol->size) { if (*pnt++ == '\n') ol->nlines++; } ol->nlines++; ol->linelist = HeapAlloc(GetProcessHeap(), 0, ol->nlines * sizeof(unsigned int)); nlines = 0; pnt = addr; ol->linelist[nlines++] = 0; while (pnt < addr + ol->size) { if (*pnt++ == '\n') ol->linelist[nlines++] = pnt - addr; } ol->linelist[nlines++] = pnt - addr; } else { addr = source_map_file(ol->real_path, &hMap, NULL); if (addr == (char*)-1) return FALSE; } /* * All we need to do is to display the source lines here. */ rtn = FALSE; for (i = start - 1; i <= end - 1; i++) { char buffer[1024]; if (i < 0 || i >= ol->nlines - 1) continue; rtn = TRUE; memset(&buffer, 0, sizeof(buffer)); if (ol->linelist[i+1] != ol->linelist[i]) { memcpy(&buffer, addr + ol->linelist[i], (ol->linelist[i+1] - ol->linelist[i]) - 1); } dbg_printf("%d\t%s\n", i + 1, buffer); } source_unmap_file(addr, hMap); return rtn; }
/*********************************************************************** * symbol_get_lvalue * * Get the address of a named symbol. * Return values: * sglv_found: if the symbol is found * sglv_unknown: if the symbol isn't found * sglv_aborted: some error occurred (likely, many symbols of same name exist, * and user didn't pick one of them) */ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* rtn, BOOL bp_disp) { struct sgv_data sgv; int i; char buffer[512]; DWORD opt; IMAGEHLP_STACK_FRAME ihsf; if (strlen(name) + 4 > sizeof(buffer)) { WINE_WARN("Too long symbol (%s)\n", name); return sglv_unknown; } sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = DBG_IVAR(AlwaysShowThunks); if (strchr(name, '!')) { strcpy(buffer, name); } else { buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); } /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); if (!sgv.num) { const char* ptr = strchr(name, '!'); if ((ptr && ptr[1] != '_') || (!ptr && *name != '_')) { if (ptr) { int offset = ptr - name; memcpy(buffer, name, offset + 1); buffer[offset + 1] = '_'; strcpy(&buffer[offset + 2], ptr + 1); } else { buffer[0] = '*'; buffer[1] = '!'; buffer[2] = '_'; strcpy(&buffer[3], name); } SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); } } SymSetOptions(opt); /* now grab local symbols */ if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV) { sgv.frame_offset = ihsf.FrameOffset; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } if (!sgv.num) { dbg_printf("No symbols found for %s\n", name); return sglv_unknown; } /* recompute potential offsets for functions (linenumber, skip prolog) */ for (i = 0; i < sgv.num; i++) { if (sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL|SYMFLAG_LOCAL|SYMFLAG_THUNK)) continue; if (lineno == -1) { struct dbg_type type; ULONG64 addr; type.module = sgv.syms[i].lvalue.type.module; type.id = sgv.syms[i].sym_info; if (bp_disp && symbol_get_debug_start(&type, &addr)) sgv.syms[i].lvalue.addr.Offset = addr; } else { DWORD disp; IMAGEHLP_LINE il; BOOL found = FALSE; il.SizeOfStruct = sizeof(il); SymGetLineFromAddr(dbg_curr_process->handle, (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr), &disp, &il); do { if (lineno == il.LineNumber) { sgv.syms[i].lvalue.addr.Offset = il.Address; found = TRUE; break; } } while (SymGetLineNext(dbg_curr_process->handle, &il)); if (!found) WINE_FIXME("No line (%d) found for %s (setting to symbol start)\n", lineno, name); } } i = 0; if (dbg_interactiveP) { if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) { dbg_printf("Many symbols with name '%s', " "choose the one you want (<cr> to abort):\n", name); for (i = 0; i < sgv.num; i++) { if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) continue; dbg_printf("[%d]: ", i + 1); if (sgv.syms[i].flags & SYMFLAG_LOCAL) { dbg_printf("%s %sof %s\n", sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", name); } else if (sgv.syms[i].flags & SYMFLAG_THUNK) { print_address(&sgv.syms[i].lvalue.addr, TRUE); /* FIXME: should display where the thunks points to */ dbg_printf(" thunk %s\n", name); } else { print_address(&sgv.syms[i].lvalue.addr, TRUE); dbg_printf("\n"); } } do { i = 0; if (input_read_line("=> ", buffer, sizeof(buffer))) { if (buffer[0] == '\0') return sglv_aborted; i = atoi(buffer); if (i < 1 || i > sgv.num) dbg_printf("Invalid choice %d\n", i); } else return sglv_aborted; } while (i < 1 || i > sgv.num); /* The array is 0-based, but the choices are 1..n, * so we have to subtract one before returning. */ i--; } } else { /* FIXME: could display the list of non-picked up symbols */ if (sgv.num > 1) dbg_printf("More than one symbol named %s, picking the first one\n", name); } *rtn = sgv.syms[i].lvalue; return sglv_found; }
int shell_key_event(Shell *shell, KBD_Event *ev) { static const char *left = "\033[D"; static const char *right = "\033[C"; static const char *up = "\033[A"; static const char *down = "\033[B"; static const char *pgup = "\033[5~"; static const char *pgdown = "\033[6~"; static const char *home = "\033OH"; static const char *end = "\033OF"; static const char *insert = "\033[2~"; static const char *del = "\033[3~"; int key = ev->symbol; int code = ev->unicode; int modifier = ev->modifier; int state = ev->state; if (state != KBD_EVENT_STATE_PRESSED) return (0); if (modifier & KBD_MOD_CTRL) { switch (key) { case KBD_KEY_d: /* logout shell */ break; } } else { switch (key) { case KBD_KEY_LEFT: vt102_puts(shell->vt102, left, 3); break; case KBD_KEY_RIGHT: vt102_puts(shell->vt102, right, 3); break; case KBD_KEY_UP: vt102_puts(shell->vt102, up, 3); break; case KBD_KEY_DOWN: vt102_puts(shell->vt102, down, 3); break; case KBD_KEY_PAGEUP: vt102_puts(shell->vt102, pgup, 4); break; case KBD_KEY_PAGEDOWN: vt102_puts(shell->vt102, pgdown, 4); break; case KBD_KEY_HOME: vt102_puts(shell->vt102, home, 3); break; case KBD_KEY_END: vt102_puts(shell->vt102, end, 3); break; case KBD_KEY_INSERT: vt102_puts(shell->vt102, insert, 4); break; case KBD_KEY_DELETE: vt102_puts(shell->vt102, del, 4); break; default: if ((key <= KBD_KEY_DELETE) && (key > KBD_KEY_FIRST)) { vt102_puts(shell->vt102, (char *)&code, 1); } break; } } input_key_event(shell->input, ev); if (key == KBD_KEY_RETURN) { input_read_line(shell->input, &shell->cmd); vt102_putc(shell->vt102, CR); vt102_putc(shell->vt102, LF); } return (1); }