📄 target.c
字号:
Result is zero if the pushed target ended up on top of the stack, nonzero if at least one target is on top of it. Rather than allow an empty stack, we always have the dummy target at the bottom stratum, so we can call the function vectors without checking them. */intpush_target (t) struct target_ops *t;{ struct target_ops *st, *prev; for (prev = 0, st = current_target; st; prev = st, st = st->to_next) { if ((int)(t->to_stratum) >= (int)(st->to_stratum)) break; } while (t->to_stratum == st->to_stratum) { /* There's already something on this stratum. Close it off. */ (st->to_close) (0); if (prev) prev->to_next = st->to_next; /* Unchain old target_ops */ else current_target = st->to_next; /* Unchain first on list */ st = st->to_next; } /* We have removed all targets in our stratum, now add ourself. */ t->to_next = st; if (prev) prev->to_next = t; else current_target = t; cleanup_target (current_target); return prev != 0;}/* Remove a target_ops vector from the stack, wherever it may be. Return how many times it was removed (0 or 1 unless bug). */intunpush_target (t) struct target_ops *t;{ struct target_ops *u, *v; int result = 0; for (u = current_target, v = 0; u; v = u, u = u->to_next) if (u == t) { if (v == 0) pop_target(); /* unchain top copy */ else { (t->to_close)(0); /* Let it clean up */ v->to_next = t->to_next; /* unchain middle copy */ } result++; } return result;}voidpop_target (){ (current_target->to_close)(0); /* Let it clean up */ current_target = current_target->to_next; if (!current_target) /* At bottom, push dummy. */ push_target (&dummy_target);}#define MIN(A, B) (((A) <= (B)) ? (A) : (B))/* target_read_string -- read a null terminated string from MEMADDR in target. The read may also be terminated early by getting an error from target_xfer_ memory. LEN is the size of the buffer pointed to by MYADDR. Note that a terminating null will only be written if there is sufficient room. The return value is is the number of bytes (including the null) actually transferred.*/inttarget_read_string (memaddr, myaddr, len) CORE_ADDR memaddr; char *myaddr; int len;{ int tlen, origlen, offset, i; char buf[4]; origlen = len; while (len > 0) { tlen = MIN (len, 4 - (memaddr & 3)); offset = memaddr & 3; if (target_xfer_memory (memaddr & ~3, buf, 4, 0)) return origlen - len; for (i = 0; i < tlen; i++) { *myaddr++ = buf[i + offset]; if (buf[i + offset] == '\000') return (origlen - len) + i + 1; } memaddr += tlen; len -= tlen; } return origlen;}/* Move memory to or from the targets. Iterate until all of it has been moved, if necessary. The top target gets priority; anything it doesn't want, is offered to the next one down, etc. Note the business with curlen: if an early target says "no, but I have a boundary overlapping this xfer" then we shorten what we offer to the subsequent targets so the early guy will get a chance at the tail before the subsequent ones do. Result is 0 or errno value. */inttarget_read_memory (memaddr, myaddr, len) CORE_ADDR memaddr; char *myaddr; int len;{ return target_xfer_memory (memaddr, myaddr, len, 0);}inttarget_write_memory (memaddr, myaddr, len) CORE_ADDR memaddr; char *myaddr; int len;{ return target_xfer_memory (memaddr, myaddr, len, 1);} inttarget_xfer_memory (memaddr, myaddr, len, write) CORE_ADDR memaddr; char *myaddr; int len; int write;{ int curlen; int res; struct target_ops *t; /* The quick case is that the top target does it all. */ res = current_target->to_xfer_memory (memaddr, myaddr, len, write, current_target); if (res == len) return 0; if (res > 0) goto bump; /* If res <= 0 then we call it again in the loop. Ah well. */ for (; len > 0;) { curlen = len; /* Want to do it all */ for (t = current_target; t; t = t->to_has_all_memory? 0: t->to_next) { res = t->to_xfer_memory(memaddr, myaddr, curlen, write, t); if (res > 0) break; /* Handled all or part of xfer */ if (res == 0) continue; /* Handled none */ curlen = -res; /* Could handle once we get past res bytes */ } if (res <= 0) { /* If this address is for nonexistent memory, read zeros if reading, or do nothing if writing. Return error. */ if (!write) memset (myaddr, 0, len); if (errno == 0) return EIO; else return errno; }bump: memaddr += res; myaddr += res; len -= res; } return 0; /* We managed to cover it all somehow. */}/* ARGSUSED */static voidtarget_info (args, from_tty) char *args; int from_tty;{ struct target_ops *t; int has_all_mem = 0; if (symfile_objfile != NULL) printf ("Symbols from \"%s\".\n", symfile_objfile->name);#ifdef FILES_INFO_HOOK if (FILES_INFO_HOOK ()) return;#endif for (t = current_target; t; t = t->to_next) { if ((int)(t->to_stratum) <= (int)dummy_stratum) continue; if (has_all_mem) printf("\tWhile running this, gdb does not access memory from...\n"); printf("%s:\n", t->to_longname); (t->to_files_info)(t); has_all_mem = t->to_has_all_memory; }}/* This is to be called by the open routine before it does anything. */voidtarget_preopen (from_tty) int from_tty;{ dont_repeat(); if (target_has_execution) { if (query ("A program is being debugged already. Kill it? ")) target_kill (); else error ("Program not killed."); }}/* Look through the list of possible targets for a target that can execute a run or attach command without any other data. This is used to locate the default process stratum. Result is always valid (error() is called for errors). */static struct target_ops *find_default_run_target (do_mesg) char *do_mesg;{ struct target_ops **t; struct target_ops *runable; int count; count = 0; for (t = target_structs; t < target_structs + target_struct_size; ++t) { if (target_can_run(*t)) { runable = *t; ++count; } } if (count != 1) error ("Don't know how to %s. Try \"help target\".", do_mesg); return runable;}voidfind_default_attach (args, from_tty) char *args; int from_tty;{ struct target_ops *t; t = find_default_run_target("attach"); (t->to_attach) (args, from_tty); return;}voidfind_default_create_inferior (exec_file, allargs, env) char *exec_file; char *allargs; char **env;{ struct target_ops *t; t = find_default_run_target("run"); (t->to_create_inferior) (exec_file, allargs, env); return;}static intreturn_zero (){ return 0;}struct target_ops *find_core_target (){ struct target_ops **t; struct target_ops *runable; int count; count = 0; for (t = target_structs; t < target_structs + target_struct_size; ++t) { if ((*t)->to_stratum == core_stratum) { runable = *t; ++count; } } return(count == 1 ? runable : NULL);} static char targ_desc[] = "Names of targets and files being debugged.\n\Shows the entire stack of targets currently in use (including the exec-file,\n\core-file, and process, if any), as well as the symbol file name.";void_initialize_targets (){ current_target = &dummy_target; cleanup_target (current_target); add_info ("target", target_info, targ_desc); add_info ("files", target_info, targ_desc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -