static void dbg_init_arch_data(void) { uint32_t dbgdidr; dbgdidr = dbg_read(DBGDIDR); dbg.arch = BMVAL(dbgdidr, 16, 19); dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1; dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1; dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1; }
static inline void dbg_save_state(int cpu) { int i, j; i = cpu * MAX_DBG_REGS; switch (dbg.arch) { case ARM_DEBUG_ARCH_V8: dbg_write(OSLOCK_MAGIC, DBGOSLAR); isb(); dbg.state[i++] = dbg_read(DBGDSCRext); for (j = 0; j < dbg.nr_bp; j++) i = dbg_read_arch32_bxr(dbg.state, i, j); for (j = 0; j < dbg.nr_wp; j++) i = dbg_read_arch32_wxr(dbg.state, i, j); dbg.state[i++] = dbg_read(DBGDCCINT); dbg.state[i++] = dbg_read(DBGCLAIMCLR); dbg.state[i++] = dbg_read(DBGOSECCR); dbg.state[i++] = dbg_read(DBGDTRRXext); dbg.state[i++] = dbg_read(DBGDTRTXext); isb(); dbg_write(0x1, DBGOSDLR); isb(); break; default: pr_err_ratelimited("unsupported dbg arch %d in %s\n", dbg.arch, __func__); } }
/* * dbg_read_stack(client, level) * * Reads a DWORD from the stack of the client "client". The * DWORD will be located at ESP - (level * sizeof(uint32_t)). * */ uint32_t dbg_read_stack(sid_t client, int level) { uint32_t l__buf; uintptr_t l__adr; /* Get its ESP */ uintptr_t l__esp = dbg_get_esp(client); if (*tls_errno) return 0; l__adr = l__esp - (level * sizeof(uint32_t)); if (dbg_read(client, l__adr, &l__buf, sizeof(uint32_t))) { dbg_isprintf("Can't read datas from the stack of 0x%X on level 0x%X at ESP 0x%X + 0x%X = 0x%X, because of %i.\n", client, level, l__esp, level * sizeof(uint32_t), l__adr, *tls_errno); return 0; } return l__buf; }
static int dbg_read_arch32_wxr(uint32_t *state, int i, int j) { switch (j) { case 0: state[i++] = dbg_read(DBGWVR0); state[i++] = dbg_read(DBGWCR0); break; case 1: state[i++] = dbg_read(DBGWVR1); state[i++] = dbg_read(DBGWCR1); break; case 2: state[i++] = dbg_read(DBGWVR2); state[i++] = dbg_read(DBGWCR2); break; case 3: state[i++] = dbg_read(DBGWVR3); state[i++] = dbg_read(DBGWCR3); break; case 4: state[i++] = dbg_read(DBGWVR4); state[i++] = dbg_read(DBGWCR4); break; case 5: state[i++] = dbg_read(DBGWVR5); state[i++] = dbg_read(DBGWCR5); break; case 6: state[i++] = dbg_read(DBGWVR6); state[i++] = dbg_read(DBGWCR6); break; case 7: state[i++] = dbg_read(DBGWVR7); state[i++] = dbg_read(DBGWCR7); break; case 8: state[i++] = dbg_read(DBGWVR8); state[i++] = dbg_read(DBGWCR8); break; case 9: state[i++] = dbg_read(DBGWVR9); state[i++] = dbg_read(DBGWCR9); break; case 10: state[i++] = dbg_read(DBGWVR10); state[i++] = dbg_read(DBGWCR10); break; case 11: state[i++] = dbg_read(DBGWVR11); state[i++] = dbg_read(DBGWCR11); break; case 12: state[i++] = dbg_read(DBGWVR12); state[i++] = dbg_read(DBGWCR12); break; case 13: state[i++] = dbg_read(DBGWVR13); state[i++] = dbg_read(DBGWCR13); break; case 14: state[i++] = dbg_read(DBGWVR14); state[i++] = dbg_read(DBGWCR14); break; case 15: state[i++] = dbg_read(DBGWVR15); state[i++] = dbg_read(DBGWCR15); break; default: pr_err_ratelimited("idx %d out of bounds in %s\n", j, __func__); } return i; }
/* * dbg_prepare_sh_read(name, sz, &numb) * * Prepares the read procedure for the command "name" for reading data in * junks of "sz". The number of bytes to read will be stored to the buffer, * where "numb" points to. * * Return value: * == NULL if failed * != NULL pointer to the read datas (number of blocks => numb) * */ static void* dbg_prepare_sh_read(const utf8_t *name, size_t sz, unsigned *numb) { dbg_shell_t *l__shell = *dbg_tls_shellptr; int l__infopar = -1; sid_t l__sid; unsigned l__num; uintptr_t l__adr; uint32_t *l__buf = NULL; /* Right count of parameters? */ if (l__shell->n_pars < 2) { dbg_iprintf(l__shell->terminal, "Missing parameters. Try \"help %s\" for more informations.\n", name); return NULL; } /* Was a SID defined? */ l__sid = dbg_get_sidpar(name, SIDTYPE_THREAD); if (l__sid == SID_INVALID) return NULL; /* SID completion */ if (l__sid < 0xFFFF) l__sid += 0x1000000; /* Was a size defined? */ l__infopar = dbg_test_par(0, "-n"); if (l__infopar > -1) { /* The next parameter should contain our size parameter */ if (l__shell->n_pars < (unsigned)l__infopar) { dbg_iprintf(l__shell->terminal, "Missing size parameter. Try \"help %s\" for more informations.\n", name); return NULL; } /* Get the number of DWORDs */ if (dbglib_atoul(l__shell->pars[l__infopar + 1], &l__num, 10)) { dbg_iprintf(l__shell->terminal, "Can't convert parameter - \"%s\".\n", l__shell->pars[l__infopar + 1]); return NULL; } } else { /* No number. Just one DWORD. */ l__num = 1; } /* Get the destination address */ if (dbglib_atoul(l__shell->pars[1], &l__adr, 16)) { dbg_iprintf(l__shell->terminal, "Illegal address - \"%s\".\n", l__shell->pars[1]); return NULL; } /* Allocate the memory buffer */ l__buf = mem_alloc(l__num * sz); if (l__buf == NULL) { dbg_iprintf(l__shell->terminal, "Can't allocate memory for read buffer, because of %i.\n", *tls_errno); *tls_errno = 0; return NULL; } /* Try to read it */ if (dbg_read(l__sid, l__adr, l__buf, l__num * sz)) { dbg_iprintf(l__shell->terminal, "Can't read %i bytes from 0x%X at 0x%X (message on system terminal).\n", l__num * sizeof(uint8_t), l__sid, l__adr, *tls_errno); *tls_errno = 0; return NULL; } dbg_iprintf(l__shell->terminal, "Reading %i bytes from 0x%X at 0x%X:\n", l__num * sz, l__sid, l__adr); *numb = l__num; return l__buf; }