The "dis" command offers a well known "-r" option, which allows
the user to display all instructions from the start of the routine
up to and including the designated address. Currently there is no option to
go in the opposite direction.
This patch introduces the "-f" (forward) option. As the option suggests, it
is to be used to displays all instructions from the given text address to
the end of the routine. The given address may be expressed by value, symbol
or expression. For example:
crash> dis -f do_fork+430
0xffffffff8013804b <do_fork+430>: callq 0xffffffff80143aac <ptrace_notify>
0xffffffff80138050 <do_fork+435>: jmp 0xffffffff8013805d <do_fork+448>
0xffffffff80138052 <do_fork+437>: mov %r13d,%edi
0xffffffff80138055 <do_fork+440>: mov %rbx,%r13
0xffffffff80138058 <do_fork+443>: callq 0xffffffff80149060 <free_pidmap>
0xffffffff8013805d <do_fork+448>: mov %r13,%rax
0xffffffff80138060 <do_fork+451>: add $0x38,%rsp
0xffffffff80138064 <do_fork+455>: pop %rbx
0xffffffff80138065 <do_fork+456>: pop %rbp
0xffffffff80138066 <do_fork+457>: pop %r12
0xffffffff80138068 <do_fork+459>: pop %r13
0xffffffff8013806a <do_fork+461>: pop %r14
0xffffffff8013806c <do_fork+463>: pop %r15
0xffffffff8013806e <do_fork+465>: retq
0xffffffff8013806f <do_fork+466>: nop
Signed-off-by: Aaron Tomlin <atomlin(a)redhat.com>
---
help.c | 2 ++
kernel.c | 44 ++++++++++++++++++++++++++++----------------
2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/help.c b/help.c
index 2848ead..6f3965b 100644
--- a/help.c
+++ b/help.c
@@ -6152,6 +6152,8 @@ char *help_dis[] = {
" a text address that may be expressed by value, symbol or expression:\n",
" -r (reverse) displays all instructions from the start of the ",
" routine up to and including the designated address.",
+" -f (forward) displays all instructions from the given address ",
+" to the end of the routine.",
" -l displays source code line number data in addition to the ",
" disassembly output.",
" -u address is a user virtual address in the current context;",
diff --git a/kernel.c b/kernel.c
index 846cf71..77ca271 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1427,11 +1427,11 @@ void
cmd_dis(void)
{
int c;
- int do_load_module_filter, do_machdep_filter, reverse;
+ int do_load_module_filter, do_machdep_filter, reverse, forward;
int unfiltered, user_mode, count_entered, bug_bytes_entered;
unsigned int radix;
ulong curaddr;
- ulong revtarget;
+ ulong target;
ulong count;
ulong offset;
struct syment *sp;
@@ -1453,17 +1453,18 @@ cmd_dis(void)
return;
}
- reverse = count_entered = bug_bytes_entered = FALSE;
+ reverse = forward = count_entered = bug_bytes_entered = FALSE;
sp = NULL;
unfiltered = user_mode = do_machdep_filter = do_load_module_filter = 0;
radix = 0;
+ target = 0;
req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
req->buf = GETBUF(BUFSIZE);
req->flags |= GNU_FROM_TTY_OFF|GNU_RETURN_ON_ERROR;
req->count = 1;
- while ((c = getopt(argcnt, args, "dxhulrUb:B:")) != EOF) {
+ while ((c = getopt(argcnt, args, "dxhulrfUb:B:")) != EOF) {
switch(c)
{
case 'd':
@@ -1493,6 +1494,10 @@ cmd_dis(void)
reverse = TRUE;
break;
+ case 'f':
+ forward = TRUE;
+ break;
+
case 'l':
if (NO_LINE_NUMBERS())
error(INFO, "line numbers are not available\n");
@@ -1559,9 +1564,10 @@ cmd_dis(void)
}
if (args[++optind]) {
- if (reverse) {
+ if (reverse || forward) {
error(INFO,
- "count argument ignored with -r option\n");
+ "count argument ignored with -%s option\n",
+ reverse ? "r" : "f");
} else {
req->count = stol(args[optind],
FAULT_ON_ERROR, NULL);
@@ -1592,7 +1598,7 @@ cmd_dis(void)
req->command = GNU_RESOLVE_TEXT_ADDR;
gdb_interface(req);
req->flags &= ~GNU_COMMAND_FAILED;
- if (reverse || req->flags & GNU_FUNCTION_ONLY) {
+ if (reverse || forward || req->flags & GNU_FUNCTION_ONLY) {
if (sp) {
savename = sp->name;
if ((sp = next_symbol(NULL, sp)))
@@ -1610,12 +1616,11 @@ cmd_dis(void)
}
}
- if (reverse) {
- revtarget = req->addr;
- if ((sp = value_search(revtarget, NULL)) == NULL)
- error(FATAL, "cannot resolve address: %lx\n", revtarget);
+ if (reverse || forward) {
+ target = req->addr;
+ if ((sp = value_search(target, NULL)) == NULL)
+ error(FATAL, "cannot resolve address: %lx\n", target);
- sprintf(buf1, "0x%lx", revtarget);
req->addr = sp->value;
} else
count = 0;
@@ -1627,12 +1632,12 @@ cmd_dis(void)
if (reverse)
sprintf(buf5, "x/%ldi 0x%lx",
- (revtarget - req->addr) ? revtarget - req->addr : 1,
+ (target - req->addr) ? target - req->addr : 1,
req->addr);
else
sprintf(buf5, "x/%ldi 0x%lx",
count_entered && req->count ? req->count :
- req->flags & GNU_FUNCTION_ONLY ?
+ forward || req->flags & GNU_FUNCTION_ONLY ?
req->addr2 - req->addr : 1,
req->addr);
gdb_pass_through(buf5, NULL, GNU_RETURN_ON_ERROR);
@@ -1655,8 +1660,15 @@ cmd_dis(void)
extract_hex(buf2, &curaddr, ':', TRUE);
+ if (forward) {
+ if (curaddr != target)
+ continue;
+ else
+ forward = FALSE;
+ }
+
if (!reverse)
- if ((req->flags & GNU_FUNCTION_ONLY) &&
+ if (!count_entered &&
(curaddr >= req->addr2))
break;
@@ -1677,7 +1689,7 @@ cmd_dis(void)
print_verbatim(pc->saved_fp, buf2);
if (reverse) {
- if (STRNEQ(buf2, buf1)) {
+ if (curaddr == target) {
if (LASTCHAR(clean_line(buf2)) != ':')
break;
--
2.4.3