From: Don Slutz <dslutz@verizon.com> Add more functionality to xenctx. Change from v2 to v3: Added patches #1, #2, #5, and #16. #1: Move all usgae cleanup into it''s own patch/ #2: Move xenctx.xc_handle out of patch v2#9 #5: Redo to stack dump output size adjustments into commanle line options. #16: Declare this I maintain xenctx, and drop George Dunlap. Unchanged (other then thier number) #3, #8, and #9 Mostly from Jan Beulich: #4: * Dropped extra change about i < 10. * Move add to usage to the end. #6, #7, #10: * Add command line option to control this. * More info in commit message. #11: * Reworked option handling to allow multiple actions to work. * Add check for NO_TRANSLATION where needed. * Support -b and -l. #12: * Do this patch after -m patch. * Reworked option handling to allow multiple actions to work. * Add check for NO_TRANSLATION where needed. * More info in commit message. #13: * new name is kernel_addr(). * Use kernel_start if set. * Remove other changes. #14: * Extract just the symbol printing code from "xenctx: Dump registers via hvm info if available" #15: * Extract just the vcpu printing code from "xenctx: xenctx: Add optional fCPU" v1 patch #11 "xenctx: Dump registers via hvm info if available" has been defered to the "merge xenctx and xen_hvmctx" patch set. v1 patch #12 "xenctx: Add optional fCPU" has been dropped. Change from v1 to v2: title was: xenctx: Add an option to output more registers. Processed review comments. Jan Beulich: Split 1 change into 12. Switch to enum for is_kernel_text(), renamed to is_kernel_addr(). Renamed vars like memAddr to mem_addr. Ian Campbell: More on is_kernel_text(). Don Slutz (16): xenctx: clean up usage output xenctx: Correct check for xc_interface_open failing (prevents SIGSEGV) xenctx: Clean up stack trace when hypercall_page not in symbol table xenctx: Add -2 (--two-pages) option to switch stack size to 8KiB xenctx: Add command line options -b and -l xenctx: Add command line option -D (--decode-as-ascii) xenctx: Add command line option -t (--tag-stack-dump) xenctx: Change print_symbol to do the space before. xenctx: More info on failed to map page. xenctx: Add command line option -T (--tag-call-trace) xenctx: Add -m <maddr> option to dump memory at maddr. xenctx: Add -d <daddr> option to dump memory at daddr as a stack. xenctx: change is_kernel_text() into kernel_addr(). xenctx: Add convert of more registers to symbols xenctx: Add output of vcpu value and state for --all-vcpus MAINTAINERS: Add XENCTX maintainer MAINTAINERS | 6 + tools/xentrace/xenctx.c | 500 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 415 insertions(+), 91 deletions(-) -- 1.8.4
From: Don Slutz <dslutz@verizon.com> Fix usage formatting to be all the same. Fix usage display of default --kernel-start for 64 bit. Signed-off-by: Don Slutz <dslutz@verizon.com> --- tools/xentrace/xenctx.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 060e480..4490d82 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -812,15 +812,16 @@ static void usage(void) printf("options:\n"); printf(" -f, --frame-pointers\n"); - printf(" assume the kernel was compiled with\n"); - printf(" frame pointers.\n"); + printf(" assume the kernel was compiled with\n"); + printf(" frame pointers.\n"); printf(" -s SYMTAB, --symbol-table=SYMTAB\n"); - printf(" read symbol table from SYMTAB.\n"); - printf(" -S --stack-trace print a complete stack trace.\n"); - printf(" -k, --kernel-start\n"); - printf(" set user/kernel split. (default 0xc0000000)\n"); - printf(" -a --all display more registers\n"); - printf(" -C --all-vcpus print info for all vcpus\n"); + printf(" read symbol table from SYMTAB.\n"); + printf(" -S, --stack-trace print a complete stack trace.\n"); + printf(" -k kaddr, --kernel-start=kaddr\n"); + printf(" set user/kernel split. (default 0x"FMT_32B_WORD")\n", + kernel_start); + printf(" -a, --all display more registers\n"); + printf(" -C, --all-vcpus print info for all vcpus\n"); } int main(int argc, char **argv) -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 02/16] xenctx: Correct check for xc_interface_open failing (prevents SIGSEGV)
From: Don Slutz <dslutz@verizon.com> Signed-off-by: Don Slutz <dslutz@verizon.com> --- tools/xentrace/xenctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 4490d82..3d18bf7 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -892,7 +892,7 @@ int main(int argc, char **argv) read_symbol_table(symbol_table); xenctx.xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */ - if (xenctx.xc_handle < 0) { + if (!xenctx.xc_handle) { perror("xc_interface_open"); exit(-1); } -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 03/16] xenctx: Clean up stack trace when hypercall_page not in symbol table
From: Don Slutz <Don@CloudSwitch.com> Before: Call Trace: [<ffffffff8006b2b0>] default_idle+0x29 <-- [<ffffffff80048d19>] cpu_idle+0x95 [<ffffffff803e7801>] start_kernel+0x220 [<0000000000000000>] startup_64+0x80000000 [<ffffffff803e722f>] x86_64_start_kernel+0x22f [<0000000000000000>] startup_64+0x80000000 [<0000000000000000>] startup_64+0x80000000 [<0000000000000000>] startup_64+0x80000000 [<0000000000000000>] startup_64+0x80000000 After: Call Trace: [<ffffffff8006b2b0>] default_idle+0x29 <-- [<ffffffff80048d19>] cpu_idle+0x95 [<ffffffff803e7801>] start_kernel+0x220 [<ffffffff803e722f>] x86_64_start_kernel+0x22f Signed-off-by: Don Slutz <Don@CloudSwitch.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/xentrace/xenctx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 3d18bf7..841078d 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -83,8 +83,9 @@ static int is_kernel_text(guest_word_t addr) if (addr >= kernel_stext && addr <= kernel_etext) return 1; - if (addr >= kernel_hypercallpage && - addr <= kernel_hypercallpage + 4096) + if (kernel_hypercallpage && + (addr >= kernel_hypercallpage && + addr <= kernel_hypercallpage + 4096)) return 1; if (addr >= kernel_sinittext && addr <= kernel_einittext) -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 04/16] xenctx: Add -2 (--two-pages) option to switch stack size to 8KiB
From: Don Slutz <Don@CloudSwitch.com> Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Dropped extra change about i < 10. * Move add to usage to the end. tools/xentrace/xenctx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 841078d..038536b 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -35,6 +35,7 @@ static struct xenctx { int frame_ptrs; int stack_trace; int disp_all; + int two_pages; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -650,6 +651,8 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE) & ~((guest_word_t) XC_PAGE_SIZE - 1)); + if (xenctx.two_pages) + stack_limit += XC_PAGE_SIZE; printf("\n"); printf("Stack:\n"); for (i=1; i<5 && stack < stack_limit; i++) { @@ -823,18 +826,20 @@ static void usage(void) kernel_start); printf(" -a, --all display more registers\n"); printf(" -C, --all-vcpus print info for all vcpus\n"); + printf(" -2, --two-pages assume the kernel was compiled with 8KiB stacks.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC"; + static const char *sopts = "fs:hak:SC2"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, {"frame-pointers", 0, NULL, ''f''}, {"kernel-start", 1, NULL, ''k''}, + {"two-pages", 0, NULL, ''2''}, {"all", 0, NULL, ''a''}, {"all-vcpus", 0, NULL, ''C''}, {"help", 0, NULL, ''h''}, @@ -858,6 +863,9 @@ int main(int argc, char **argv) case ''a'': xenctx.disp_all = 1; break; + case ''2'': + xenctx.two_pages = 1; + break; case ''C'': xenctx.all_vcpus = 1; break; -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 05/16] xenctx: Add command line options -b and -l
From: Don Slutz <dslutz@verizon.com> -b <bytes>, --bytes-per-line <bytes> change the number of bytes per line output for Stack. note: rounded to native size (4 or 8 bytes). -l <lines>, --lines <lines> change the number of lines output for Stack. Signed-off-by: Don Slutz <dslutz@verizon.com> --- tools/xentrace/xenctx.c | 62 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 038536b..62ba94c 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -36,6 +36,8 @@ static struct xenctx { int stack_trace; int disp_all; int two_pages; + int bytes_per_line; + int lines; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -62,6 +64,8 @@ typedef uint64_t guest_word_t; #define FMT_64B_WORD "%016lx" #endif +#define MAX_BYTES_PER_LINE 128 + struct symbol { guest_word_t address; char *name; @@ -649,25 +653,30 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) guest_word_t *p; int i; + if (width) + xenctx.bytes_per_line = ((xenctx.bytes_per_line + width - 1) / width) * width; stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE) & ~((guest_word_t) XC_PAGE_SIZE - 1)); if (xenctx.two_pages) stack_limit += XC_PAGE_SIZE; printf("\n"); - printf("Stack:\n"); - for (i=1; i<5 && stack < stack_limit; i++) { - while(stack < stack_limit && stack < stack_pointer(ctx) + i*32) { - p = map_page(ctx, vcpu, stack); - if (!p) - return -1; - word = read_stack_word(p, width); - printf(" "); - print_stack_word(word, width); - stack += width; + if (xenctx.lines) { + printf("Stack:\n"); + for (i = 1; i < xenctx.lines + 1 && stack < stack_limit; i++) { + while(stack < stack_limit && + stack < stack_pointer(ctx) + i * xenctx.bytes_per_line) { + p = map_page(ctx, vcpu, stack); + if (!p) + return -1; + word = read_stack_word(p, width); + printf(" "); + print_stack_word(word, width); + stack += width; + } + printf("\n"); } printf("\n"); } - printf("\n"); if(xenctx.stack_trace) printf("Stack Trace:\n"); @@ -827,19 +836,26 @@ static void usage(void) printf(" -a, --all display more registers\n"); printf(" -C, --all-vcpus print info for all vcpus\n"); printf(" -2, --two-pages assume the kernel was compiled with 8KiB stacks.\n"); + printf(" -b <bytes>, --bytes-per-line <bytes>\n"); + printf(" change the number of bytes per line output for Stack.\n"); + printf(" note: rounded to native size (4 or 8 bytes).\n"); + printf(" -l <lines>, --lines <lines>\n"); + printf(" change the number of lines output for Stack.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC2"; + static const char *sopts = "fs:hak:SC2b:l:"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, {"frame-pointers", 0, NULL, ''f''}, {"kernel-start", 1, NULL, ''k''}, {"two-pages", 0, NULL, ''2''}, + {"bytes-per-line", 1, NULL, ''b''}, + {"lines", 1, NULL, ''l''}, {"all", 0, NULL, ''a''}, {"all-vcpus", 0, NULL, ''C''}, {"help", 0, NULL, ''h''}, @@ -849,6 +865,9 @@ int main(int argc, char **argv) int vcpu = 0; + xenctx.bytes_per_line = 32; + xenctx.lines = 5; + while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch(ch) { case ''f'': @@ -866,6 +885,25 @@ int main(int argc, char **argv) case ''2'': xenctx.two_pages = 1; break; + case ''b'': + xenctx.bytes_per_line = strtol(optarg, NULL, 0); + if (xenctx.bytes_per_line < 4 || + xenctx.bytes_per_line > MAX_BYTES_PER_LINE) { + fprintf(stderr, + "%s: Unsupported value for --bytes-per-line. Needs to be 4 <= <bytes> <= %d\n", + argv[0], MAX_BYTES_PER_LINE); + exit(-1); + } + break; + case ''l'': + xenctx.lines = strtol(optarg, NULL, 0); + if (xenctx.lines < 0) { + fprintf(stderr, + "%s: Unsupported value for --lines. Needs to be >= 0\n", + argv[0]); + exit(-1); + } + break; case ''C'': xenctx.all_vcpus = 1; break; -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 06/16] xenctx: Add command line option -D (--decode-as-ascii)
From: Don Slutz <Don@CloudSwitch.com> If specified, output ascii version of stack also. Here is an example: Stack: ffffffff80048d19 0000000000200800 ffffffff803e7801 0000000000086800 .......... ......x>......h...... 0000000000000000 ffffffff80430720 ffffffff803e722f 80008e000010019c ........ .C...../r>............. 00000000ffffffff 0000000000000000 0000000000000000 0000000000200000 .......................... ..... 0000000000000000 0000000000000000 ................ Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Add command line option to control this. * More info in commit message. tools/xentrace/xenctx.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 62ba94c..9aae658 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -38,6 +38,7 @@ static struct xenctx { int two_pages; int bytes_per_line; int lines; + int decode_as_ascii; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -651,6 +652,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) guest_word_t frame; guest_word_t word; guest_word_t *p; + guest_word_t ascii[MAX_BYTES_PER_LINE/4]; int i; if (width) @@ -663,16 +665,38 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) if (xenctx.lines) { printf("Stack:\n"); for (i = 1; i < xenctx.lines + 1 && stack < stack_limit; i++) { + int j = 0; + int k; + while(stack < stack_limit && stack < stack_pointer(ctx) + i * xenctx.bytes_per_line) { p = map_page(ctx, vcpu, stack); if (!p) return -1; word = read_stack_word(p, width); + if (xenctx.decode_as_ascii) + ascii[j++] = word; printf(" "); print_stack_word(word, width); stack += width; } + printf(" "); + if (xenctx.decode_as_ascii) { + for (k = j; k < xenctx.bytes_per_line/width; k++) + printf(" %*s", width*2, ""); + for (k = 0; k < j; k++) { + int l; + unsigned char *bytep = (unsigned char*)&ascii[k]; + + for (l = 0; l < width; l++) { + if (isprint(*bytep)) + printf("%c", *bytep); + else + printf("."); + bytep++; + } + } + } printf("\n"); } printf("\n"); @@ -841,19 +865,22 @@ static void usage(void) printf(" note: rounded to native size (4 or 8 bytes).\n"); printf(" -l <lines>, --lines <lines>\n"); printf(" change the number of lines output for Stack.\n"); + printf(" -D, --decode-as-ascii\n"); + printf(" add a decode of Stack dump as ascii.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC2b:l:"; + static const char *sopts = "fs:hak:SC2b:l:D"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, {"frame-pointers", 0, NULL, ''f''}, {"kernel-start", 1, NULL, ''k''}, {"two-pages", 0, NULL, ''2''}, + {"decode-as-ascii", 0, NULL, ''D''}, {"bytes-per-line", 1, NULL, ''b''}, {"lines", 1, NULL, ''l''}, {"all", 0, NULL, ''a''}, @@ -885,6 +912,9 @@ int main(int argc, char **argv) case ''2'': xenctx.two_pages = 1; break; + case ''D'': + xenctx.decode_as_ascii = 1; + break; case ''b'': xenctx.bytes_per_line = strtol(optarg, NULL, 0); if (xenctx.bytes_per_line < 4 || -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 07/16] xenctx: Add command line option -t (--tag-stack-dump)
From: Don Slutz <Don@CloudSwitch.com> If specified, add stack address to dump. Here is an example: Stack: ffffffff803ddf90: ffffffff80048d19 0000000000200800 ffffffff803e7801 0000000000086800 ffffffff803ddfb0: 0000000000000000 ffffffff80430720 ffffffff803e722f 80008e000010019c ffffffff803ddfd0: 00000000ffffffff 0000000000000000 0000000000000000 0000000000200000 ffffffff803ddff0: 0000000000000000 0000000000000000 Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Add command line option to control this. * More info in commit message. tools/xentrace/xenctx.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 9aae658..a88c347 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -39,6 +39,7 @@ static struct xenctx { int bytes_per_line; int lines; int decode_as_ascii; + int tag_stack_dump; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -668,6 +669,10 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) int j = 0; int k; + if (xenctx.tag_stack_dump) { + print_stack_word(stack, width); + printf(":"); + } while(stack < stack_limit && stack < stack_pointer(ctx) + i * xenctx.bytes_per_line) { p = map_page(ctx, vcpu, stack); @@ -867,13 +872,15 @@ static void usage(void) printf(" change the number of lines output for Stack.\n"); printf(" -D, --decode-as-ascii\n"); printf(" add a decode of Stack dump as ascii.\n"); + printf(" -t, --tag-stack-dump\n"); + printf(" add address on each line of Stack dump.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC2b:l:D"; + static const char *sopts = "fs:hak:SC2b:l:Dt"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, @@ -881,6 +888,7 @@ int main(int argc, char **argv) {"kernel-start", 1, NULL, ''k''}, {"two-pages", 0, NULL, ''2''}, {"decode-as-ascii", 0, NULL, ''D''}, + {"tag-stack-dump", 0, NULL, ''t''}, {"bytes-per-line", 1, NULL, ''b''}, {"lines", 1, NULL, ''l''}, {"all", 0, NULL, ''a''}, @@ -915,6 +923,9 @@ int main(int argc, char **argv) case ''D'': xenctx.decode_as_ascii = 1; break; + case ''t'': + xenctx.tag_stack_dump = 1; + break; case ''b'': xenctx.bytes_per_line = strtol(optarg, NULL, 0); if (xenctx.bytes_per_line < 4 || -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 08/16] xenctx: Change print_symbol to do the space before.
From: Don Slutz <Don@CloudSwitch.com> This stops the output of an extra space at the end of the line. Signed-off-by: Don Slutz <Don@CloudSwitch.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/xentrace/xenctx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index a88c347..c0d7bf6 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -164,9 +164,9 @@ static void print_symbol(guest_word_t addr) return; if (addr==s->address) - printf("%s ", s->name); + printf(" %s", s->name); else - printf("%s+%#x ", s->name, (unsigned int)(addr - s->address)); + printf(" %s+%#x", s->name, (unsigned int)(addr - s->address)); } static void read_symbol_table(const char *symtab) @@ -293,7 +293,7 @@ static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx) { struct cpu_user_regs_x86_32 *regs = &ctx->user_regs; - printf("cs:eip: %04x:%08x ", regs->cs, regs->eip); + printf("cs:eip: %04x:%08x", regs->cs, regs->eip); print_symbol(regs->eip); print_flags(regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp); @@ -322,7 +322,7 @@ static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx) { struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; - printf("cs:eip: %04x:%08x ", regs->cs, (uint32_t)regs->eip); + printf("cs:eip: %04x:%08x", regs->cs, (uint32_t)regs->eip); print_symbol((uint32_t)regs->eip); print_flags((uint32_t)regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp); @@ -351,7 +351,7 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx) { struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; - printf("rip: %016"PRIx64" ", regs->rip); + printf("rip: %016"PRIx64, regs->rip); print_symbol(regs->rip); print_flags(regs->rflags); printf("rsp: %016"PRIx64"\n", regs->rsp); @@ -449,7 +449,7 @@ static void print_ctx_32(vcpu_guest_context_t *ctx) { vcpu_guest_core_regs_t *regs = &ctx->user_regs; - printf("PC: %08"PRIx32" ", regs->pc32); + printf("PC: %08"PRIx32, regs->pc32); print_symbol(regs->pc32); printf("\n"); printf("CPSR: %08"PRIx32"\n", regs->cpsr); @@ -501,7 +501,7 @@ static void print_ctx_64(vcpu_guest_context_t *ctx) { vcpu_guest_core_regs_t *regs = &ctx->user_regs; - printf("PC: %016"PRIx64" ", regs->pc64); + printf("PC: %016"PRIx64, regs->pc64); print_symbol(regs->pc64); printf("\n"); @@ -713,7 +713,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) printf("Call Trace:\n"); printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); print_stack_word(instr_pointer(ctx), width); - printf(">] "); + printf(">]"); print_symbol(instr_pointer(ctx)); printf(" <--\n"); @@ -753,7 +753,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) word = read_stack_word(p, width); printf("%c [<", xenctx.stack_trace ? ''|'' : '' ''); print_stack_word(word, width); - printf(">] "); + printf(">]"); print_symbol(word); printf("\n"); stack += width; @@ -769,7 +769,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) if (is_kernel_text(word)) { printf(" [<"); print_stack_word(word, width); - printf(">] "); + printf(">]"); print_symbol(word); printf("\n"); } else if (xenctx.stack_trace) { -- 1.8.4
From: Don Slutz <Don@CloudSwitch.com> Also output an extra new line since we may be in the middle of output. Signed-off-by: Don Slutz <Don@CloudSwitch.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/xentrace/xenctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index c0d7bf6..018e2fe 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -599,7 +599,7 @@ static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt mapped = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, XC_PAGE_SIZE, PROT_READ, mfn); if (mapped == NULL) { - fprintf(stderr, "failed to map page.\n"); + fprintf(stderr, "\nfailed to map page for "FMT_32B_WORD".\n", virt); return NULL; } -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 10/16] xenctx: Add command line option -T (--tag-call-trace)
From: Don Slutz <Don@CloudSwitch.com> If specified, add stack addr to call trace. Here is an example: Call Trace: [<ffffffff8006b2b0>] default_idle+0x29 <-- ffffffff803ddf90: [<ffffffff80048d19>] cpu_idle+0x95 ffffffff803ddfa0: [<ffffffff803e7801>] start_kernel+0x220 ffffffff803ddfc0: [<ffffffff803e722f>] x86_64_start_kernel+0x22f and Stack Trace: * [<ffffffff8006b2b0>] default_idle+0x29 <-- ffffffff803ddf90: [<ffffffff80048d19>] cpu_idle+0x95 ffffffff803ddf98: 0000000000200800 ffffffff803ddfa0: [<ffffffff803e7801>] start_kernel+0x220 ffffffff803ddfa8: 0000000000086800 ffffffff803ddfb0: 0000000000000000 ffffffff803ddfb8: ffffffff80430720 ffffffff803ddfc0: [<ffffffff803e722f>] x86_64_start_kernel+0x22f ffffffff803ddfc8: 80008e000010019c ffffffff803ddfd0: 00000000ffffffff ffffffff803ddfd8: 0000000000000000 ffffffff803ddfe0: 0000000000000000 ffffffff803ddfe8: 0000000000200000 ffffffff803ddff0: 0000000000000000 ffffffff803ddff8: 0000000000000000 Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Add command line option to control this. * More info in commit message. tools/xentrace/xenctx.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 018e2fe..40e72f4 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -40,6 +40,7 @@ static struct xenctx { int lines; int decode_as_ascii; int tag_stack_dump; + int tag_call_trace; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -711,6 +712,8 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) printf("Stack Trace:\n"); else printf("Call Trace:\n"); + if (xenctx.tag_call_trace) + printf(" %*s", width*2, ""); printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); print_stack_word(instr_pointer(ctx), width); printf(">]"); @@ -726,9 +729,14 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) p = map_page(ctx, vcpu, stack); if (!p) return -1; - printf("| "); + if (xenctx.tag_call_trace) { + print_stack_word(stack, width); + printf(": | "); + } else { + printf("| "); + } print_stack_word(read_stack_word(p, width), width); - printf(" \n"); + printf("\n"); stack += width; } } else { @@ -740,7 +748,12 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) return -1; frame = read_stack_word(p, width); if (xenctx.stack_trace) { - printf("|-- "); + if (xenctx.tag_call_trace) { + print_stack_word(stack, width); + printf(": |-- "); + } else { + printf("|-- "); + } print_stack_word(read_stack_word(p, width), width); printf("\n"); } @@ -751,7 +764,12 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) if (!p) return -1; word = read_stack_word(p, width); - printf("%c [<", xenctx.stack_trace ? ''|'' : '' ''); + if (xenctx.tag_call_trace) { + print_stack_word(stack, width); + printf(": %c [<", xenctx.stack_trace ? ''|'' : '' ''); + } else { + printf("%c [<", xenctx.stack_trace ? ''|'' : '' ''); + } print_stack_word(word, width); printf(">]"); print_symbol(word); @@ -767,13 +785,23 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) return -1; word = read_stack_word(p, width); if (is_kernel_text(word)) { - printf(" [<"); + if (xenctx.tag_call_trace) { + print_stack_word(stack, width); + printf(": [<"); + } else { + printf(" [<"); + } print_stack_word(word, width); printf(">]"); print_symbol(word); printf("\n"); } else if (xenctx.stack_trace) { - printf(" "); + if (xenctx.tag_call_trace) { + print_stack_word(stack, width); + printf(": "); + } else { + printf(" "); + } print_stack_word(word, width); printf("\n"); } @@ -874,13 +902,15 @@ static void usage(void) printf(" add a decode of Stack dump as ascii.\n"); printf(" -t, --tag-stack-dump\n"); printf(" add address on each line of Stack dump.\n"); + printf(" -T, --tag-call-trace\n"); + printf(" add address on each line of Call trace.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC2b:l:Dt"; + static const char *sopts = "fs:hak:SC2b:l:DtT"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, @@ -889,6 +919,7 @@ int main(int argc, char **argv) {"two-pages", 0, NULL, ''2''}, {"decode-as-ascii", 0, NULL, ''D''}, {"tag-stack-dump", 0, NULL, ''t''}, + {"tag-call-trace", 0, NULL, ''T''}, {"bytes-per-line", 1, NULL, ''b''}, {"lines", 1, NULL, ''l''}, {"all", 0, NULL, ''a''}, @@ -926,6 +957,9 @@ int main(int argc, char **argv) case ''t'': xenctx.tag_stack_dump = 1; break; + case ''T'': + xenctx.tag_call_trace = 1; + break; case ''b'': xenctx.bytes_per_line = strtol(optarg, NULL, 0); if (xenctx.bytes_per_line < 4 || -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 11/16] xenctx: Add -m <maddr> option to dump memory at maddr.
From: Don Slutz <Don@CloudSwitch.com> Currently not supported on ARM. New routine read_mem_word() will correctly read a word that crosses a page boundary. It will not fault if the 2nd page can not be mapped. Here is an example: Memory (address ffffffff803ddf90): ffffffff80048d19 0000000000200800 ffffffff803e7801 0000000000086800 0000000000000000 ffffffff80430720 ffffffff803e722f 80008e000010019c 00000000ffffffff 0000000000000000 0000000000000000 0000000000200000 0000000000000000 0000000000000000 0000000000000000 00cf9b000000ffff 00af9b000000ffff 00cf93000000ffff 00cffb000000ffff 00cff3000000ffff Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Reworked option handling to allow multiple actions to work. * Add check for NO_TRANSLATION where needed. * Support -b and -l. tools/xentrace/xenctx.c | 157 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 139 insertions(+), 18 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 40e72f4..98202f8 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -29,23 +29,6 @@ #include <xen/foreign/x86_64.h> #include <xen/hvm/save.h> -static struct xenctx { - xc_interface *xc_handle; - int domid; - int frame_ptrs; - int stack_trace; - int disp_all; - int two_pages; - int bytes_per_line; - int lines; - int decode_as_ascii; - int tag_stack_dump; - int tag_call_trace; - int all_vcpus; - int self_paused; - xc_dominfo_t dominfo; -} xenctx; - #if defined (__i386__) || defined (__x86_64__) typedef unsigned long long guest_word_t; #define FMT_32B_WORD "%08llx" @@ -69,6 +52,27 @@ typedef uint64_t guest_word_t; #define MAX_BYTES_PER_LINE 128 +static struct xenctx { + xc_interface *xc_handle; + int domid; + int frame_ptrs; + int stack_trace; + int disp_all; + int two_pages; + int bytes_per_line; + int lines; + int decode_as_ascii; + int tag_stack_dump; + int tag_call_trace; + int all_vcpus; +#ifndef NO_TRANSLATION + guest_word_t mem_addr; + int do_memory; +#endif + int self_paused; + xc_dominfo_t dominfo; +} xenctx; + struct symbol { guest_word_t address; char *name; @@ -616,6 +620,34 @@ static guest_word_t read_stack_word(guest_word_t *src, int width) return word; } +#ifndef NO_TRANSLATION +static guest_word_t read_mem_word(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt, int width) +{ + if ((virt & 7) == 0) { + guest_word_t *p = map_page(ctx, vcpu, virt); + + if (p) + return read_stack_word(p, width); + else + return -1; + } else { + guest_word_t word = -1; + char *src, *dst; + int i; + + dst = (char*)&word; + for(i = 0; i < width; i++) { + src = map_page(ctx, vcpu, virt + i); + if (src) + *dst++ = *src; + else + return word; + } + return word; + } +} +#endif + static void print_stack_word(guest_word_t word, int width) { if (width == 4) @@ -624,6 +656,61 @@ static void print_stack_word(guest_word_t word, int width) printf(FMT_64B_WORD, word); } +#ifndef NO_TRANSLATION +static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest_word_t mem_addr) +{ + guest_word_t instr; + guest_word_t instr_start; + guest_word_t word; + guest_word_t ascii[MAX_BYTES_PER_LINE/4]; + int i; + + instr_start = mem_addr; + instr = mem_addr; + printf("Memory (address "); + print_stack_word(instr, width); + printf("):\n"); + for (i = 1; i < xenctx.lines + 1; i++) { + int j = 0; + int k; + + if (xenctx.tag_stack_dump) { + print_stack_word(instr, width); + printf(":"); + } + while(instr < instr_start + i * xenctx.bytes_per_line) { + void *p = map_page(ctx, vcpu, instr); + if (!p) + return; + word = read_mem_word(ctx, vcpu, instr, width); + if (xenctx.decode_as_ascii) + ascii[j++] = word; + printf(" "); + print_stack_word(word, width); + instr += width; + } + printf(" "); + if (xenctx.decode_as_ascii) { + for (k = j; k < xenctx.bytes_per_line/width; k++) + printf(" %*s", width*2, ""); + for (k = 0; k < j; k++) { + int l; + unsigned char *bytep = (unsigned char*)&ascii[k]; + + for (l = 0; l < width; l++) { + if ((*bytep < 127) && (*bytep >= 32)) + printf("%c", *bytep); + else + printf("."); + bytep++; + } + } + } + printf("\n"); + } +} +#endif + static int print_code(vcpu_guest_context_any_t *ctx, int vcpu) { guest_word_t instr; @@ -851,6 +938,12 @@ static void dump_ctx(int vcpu) } #endif +#ifndef NO_TRANSLATION + if (xenctx.do_memory) { + print_mem(&ctx, vcpu, guest_word_size, xenctx.mem_addr); + return; + } +#endif print_ctx(&ctx); #ifndef NO_TRANSLATION if (print_code(&ctx, vcpu)) @@ -904,13 +997,21 @@ static void usage(void) printf(" add address on each line of Stack dump.\n"); printf(" -T, --tag-call-trace\n"); printf(" add address on each line of Call trace.\n"); +#ifndef NO_TRANSLATION + printf(" -m maddr, --memory=maddr\n"); + printf(" dump memory at maddr.\n"); +#endif } int main(int argc, char **argv) { int ch; int ret; +#ifndef NO_TRANSLATION + static const char *sopts = "fs:hak:SC2b:l:DtTm:"; +#else static const char *sopts = "fs:hak:SC2b:l:DtT"; +#endif static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, @@ -920,6 +1021,9 @@ int main(int argc, char **argv) {"decode-as-ascii", 0, NULL, ''D''}, {"tag-stack-dump", 0, NULL, ''t''}, {"tag-call-trace", 0, NULL, ''T''}, +#ifndef NO_TRANSLATION + {"memory", 1, NULL, ''m''}, +#endif {"bytes-per-line", 1, NULL, ''b''}, {"lines", 1, NULL, ''l''}, {"all", 0, NULL, ''a''}, @@ -930,6 +1034,7 @@ int main(int argc, char **argv) const char *symbol_table = NULL; int vcpu = 0; + int do_default = 1; xenctx.bytes_per_line = 32; xenctx.lines = 5; @@ -981,10 +1086,18 @@ int main(int argc, char **argv) break; case ''C'': xenctx.all_vcpus = 1; + do_default = 0; break; case ''k'': kernel_start = strtoull(optarg, NULL, 0); break; +#ifndef NO_TRANSLATION + case ''m'': + xenctx.mem_addr = strtoull(optarg, NULL, 0); + xenctx.do_memory = 1; + do_default = 0; + break; +#endif case ''h'': usage(); exit(-1); @@ -1034,9 +1147,17 @@ int main(int argc, char **argv) xenctx.self_paused = 1; } +#ifndef NO_TRANSLATION + if (xenctx.do_memory) { + dump_ctx(vcpu); + if (xenctx.all_vcpus) + printf("\n"); + } + xenctx.do_memory = 0; +#endif if (xenctx.all_vcpus) dump_all_vcpus(); - else + if (do_default) dump_ctx(vcpu); if (xenctx.self_paused) { -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 12/16] xenctx: Add -d <daddr> option to dump memory at daddr as a stack.
From: Don Slutz <Don@CloudSwitch.com> Also switch from read_stack_word to read_mem_word since the provided address may not be aligned. Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * Do this patch after -m patch. * Reworked option handling to allow multiple actions to work. * Add check for NO_TRANSLATION where needed. * More info in commit message. tools/xentrace/xenctx.c | 72 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 98202f8..ee3dcb9 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -67,7 +67,9 @@ static struct xenctx { int all_vcpus; #ifndef NO_TRANSLATION guest_word_t mem_addr; + guest_word_t stk_addr; int do_memory; + int do_stack; #endif int self_paused; xc_dominfo_t dominfo; @@ -728,15 +730,13 @@ static int print_code(vcpu_guest_context_any_t *ctx, int vcpu) else printf("%02x ", *c); } - printf("\n"); - - printf("\n"); + printf("\n\n\n"); return 0; } -static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) +static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest_word_t stk_addr_start) { - guest_word_t stack = stack_pointer(ctx); + guest_word_t stack = stk_addr_start; guest_word_t stack_limit; guest_word_t frame; guest_word_t word; @@ -746,11 +746,10 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) if (width) xenctx.bytes_per_line = ((xenctx.bytes_per_line + width - 1) / width) * width; - stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE) + stack_limit = ((stack + XC_PAGE_SIZE) & ~((guest_word_t) XC_PAGE_SIZE - 1)); if (xenctx.two_pages) stack_limit += XC_PAGE_SIZE; - printf("\n"); if (xenctx.lines) { printf("Stack:\n"); for (i = 1; i < xenctx.lines + 1 && stack < stack_limit; i++) { @@ -762,11 +761,11 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) printf(":"); } while(stack < stack_limit && - stack < stack_pointer(ctx) + i * xenctx.bytes_per_line) { + stack < stk_addr_start + i * xenctx.bytes_per_line) { p = map_page(ctx, vcpu, stack); if (!p) return -1; - word = read_stack_word(p, width); + word = read_mem_word(ctx, vcpu, stack, width); if (xenctx.decode_as_ascii) ascii[j++] = word; printf(" "); @@ -799,14 +798,16 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) printf("Stack Trace:\n"); else printf("Call Trace:\n"); - if (xenctx.tag_call_trace) - printf(" %*s", width*2, ""); - printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); - print_stack_word(instr_pointer(ctx), width); - printf(">]"); - - print_symbol(instr_pointer(ctx)); - printf(" <--\n"); + if (!xenctx.do_stack) { + if (xenctx.tag_call_trace) + printf(" %*s", width*2, ""); + printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); + print_stack_word(instr_pointer(ctx), width); + printf(">]"); + + print_symbol(instr_pointer(ctx)); + printf(" <--\n"); + } if (xenctx.frame_ptrs) { stack = stack_pointer(ctx); frame = frame_pointer(ctx); @@ -865,12 +866,12 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) } } } else { - stack = stack_pointer(ctx); + stack = stk_addr_start; while(stack < stack_limit) { p = map_page(ctx, vcpu, stack); if (!p) return -1; - word = read_stack_word(p, width); + word = read_mem_word(ctx, vcpu, stack, width); if (is_kernel_text(word)) { if (xenctx.tag_call_trace) { print_stack_word(stack, width); @@ -943,13 +944,17 @@ static void dump_ctx(int vcpu) print_mem(&ctx, vcpu, guest_word_size, xenctx.mem_addr); return; } + if (xenctx.do_stack) { + print_stack(&ctx, vcpu, guest_word_size, xenctx.stk_addr); + return; + } #endif print_ctx(&ctx); #ifndef NO_TRANSLATION if (print_code(&ctx, vcpu)) return; if (is_kernel_text(instr_pointer(&ctx))) - if (print_stack(&ctx, vcpu, guest_word_size)) + if (print_stack(&ctx, vcpu, guest_word_size, stack_pointer(&ctx))) return; #endif } @@ -1000,6 +1005,8 @@ static void usage(void) #ifndef NO_TRANSLATION printf(" -m maddr, --memory=maddr\n"); printf(" dump memory at maddr.\n"); + printf(" -d daddr, --dump-as-stack=daddr\n"); + printf(" dump memory as a stack at daddr.\n"); #endif } @@ -1008,7 +1015,7 @@ int main(int argc, char **argv) int ch; int ret; #ifndef NO_TRANSLATION - static const char *sopts = "fs:hak:SC2b:l:DtTm:"; + static const char *sopts = "fs:hak:SC2b:l:DtTm:d:"; #else static const char *sopts = "fs:hak:SC2b:l:DtT"; #endif @@ -1023,6 +1030,7 @@ int main(int argc, char **argv) {"tag-call-trace", 0, NULL, ''T''}, #ifndef NO_TRANSLATION {"memory", 1, NULL, ''m''}, + {"dump-as-stack", 1, NULL, ''d''}, #endif {"bytes-per-line", 1, NULL, ''b''}, {"lines", 1, NULL, ''l''}, @@ -1097,6 +1105,11 @@ int main(int argc, char **argv) xenctx.do_memory = 1; do_default = 0; break; + case ''d'': + xenctx.stk_addr = strtoull(optarg, NULL, 0); + xenctx.do_stack = 1; + do_default = 0; + break; #endif case ''h'': usage(); @@ -1114,6 +1127,15 @@ int main(int argc, char **argv) exit(-1); } +#ifndef NO_TRANSLATION + if (xenctx.frame_ptrs && xenctx.do_stack) { + fprintf(stderr, + "%s both --frame-pointers and --dump-as-stack is not supported\n", + argv[0]); + exit(-1); + } +#endif + xenctx.domid = atoi(argv[0]); if (xenctx.domid==0) { fprintf(stderr, "cannot trace dom0\n"); @@ -1150,10 +1172,16 @@ int main(int argc, char **argv) #ifndef NO_TRANSLATION if (xenctx.do_memory) { dump_ctx(vcpu); - if (xenctx.all_vcpus) + if (xenctx.do_stack || xenctx.all_vcpus) printf("\n"); } xenctx.do_memory = 0; + if (xenctx.do_stack) { + dump_ctx(vcpu); + if (xenctx.all_vcpus) + printf("\n"); + } + xenctx.do_stack = 0; #endif if (xenctx.all_vcpus) dump_all_vcpus(); -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 13/16] xenctx: change is_kernel_text() into kernel_addr().
From: Don Slutz <Don@CloudSwitch.com> A new enum has been added to allow the caller to determine if this kernel address is a text or data address. This is currenlty not used, but will be in the next patch. Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- Changed since v2: * new name is kernel_addr(). * Use kernel_start if set. * Remove other changes. tools/xentrace/xenctx.c | 67 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index ee3dcb9..23f2199 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -29,6 +29,15 @@ #include <xen/foreign/x86_64.h> #include <xen/hvm/save.h> +/* Note: the order of these matter. + * NOT_KERNEL_ADDR must be < both KERNEL_DATA_ADDR and KERNEL_TEXT_ADDR. + * KERNEL_DATA_ADDR must be < KERNEL_TEXT_ADDR. */ +typedef enum type_of_addr_ { + NOT_KERNEL_ADDR, + KERNEL_DATA_ADDR, + KERNEL_TEXT_ADDR, +} type_of_addr; + #if defined (__i386__) || defined (__x86_64__) typedef unsigned long long guest_word_t; #define FMT_32B_WORD "%08llx" @@ -71,6 +80,7 @@ static struct xenctx { int do_memory; int do_stack; #endif + int kernel_start_set; int self_paused; xc_dominfo_t dominfo; } xenctx; @@ -82,6 +92,7 @@ struct symbol { } *symbol_table = NULL; guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage; +guest_word_t kernel_text, kernel_end; #if defined (__i386__) unsigned long long kernel_start = 0xc0000000; @@ -89,22 +100,35 @@ unsigned long long kernel_start = 0xc0000000; unsigned long long kernel_start = 0xffffffff80000000UL; #endif -static int is_kernel_text(guest_word_t addr) +static type_of_addr kernel_addr(guest_word_t addr) { - if (symbol_table == NULL) - return (addr > kernel_start); + if (symbol_table == NULL) { + if (addr > kernel_start) + return KERNEL_TEXT_ADDR; + else + return NOT_KERNEL_ADDR; + } if (addr >= kernel_stext && addr <= kernel_etext) - return 1; + return KERNEL_TEXT_ADDR; if (kernel_hypercallpage && (addr >= kernel_hypercallpage && addr <= kernel_hypercallpage + 4096)) - return 1; + return KERNEL_TEXT_ADDR; if (addr >= kernel_sinittext && addr <= kernel_einittext) - return 1; - return 0; + return KERNEL_TEXT_ADDR; + if (xenctx.kernel_start_set) { + if (addr >= kernel_start && + addr <= kernel_end) + return KERNEL_DATA_ADDR; + } else { + if (addr >= kernel_text && + addr <= kernel_end) + return KERNEL_DATA_ADDR; + } + return NOT_KERNEL_ADDR; } #if 0 @@ -158,11 +182,11 @@ static struct symbol *lookup_symbol(guest_word_t address) return s->next && s->next->address <= address ? s->next : s; } -static void print_symbol(guest_word_t addr) +static void print_symbol(guest_word_t addr, type_of_addr type) { struct symbol *s; - if (!is_kernel_text(addr)) + if (kernel_addr(addr) < type) return; s = lookup_symbol(addr); @@ -230,6 +254,10 @@ static void read_symbol_table(const char *symtab) kernel_stext = symbol->address; else if (strcmp(symbol->name, "_etext") == 0) kernel_etext = symbol->address; + else if (strcmp(symbol->name, "_text") == 0) + kernel_text = symbol->address; + else if (strcmp(symbol->name, "_end") == 0) + kernel_end = symbol->address; else if (strcmp(symbol->name, "_sinittext") == 0) kernel_sinittext = symbol->address; else if (strcmp(symbol->name, "_einittext") == 0) @@ -301,7 +329,7 @@ static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx) struct cpu_user_regs_x86_32 *regs = &ctx->user_regs; printf("cs:eip: %04x:%08x", regs->cs, regs->eip); - print_symbol(regs->eip); + print_symbol(regs->eip, KERNEL_TEXT_ADDR); print_flags(regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp); @@ -330,7 +358,7 @@ static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx) struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; printf("cs:eip: %04x:%08x", regs->cs, (uint32_t)regs->eip); - print_symbol((uint32_t)regs->eip); + print_symbol((uint32_t)regs->eip, KERNEL_TEXT_ADDR); print_flags((uint32_t)regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp); @@ -359,7 +387,7 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx) struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; printf("rip: %016"PRIx64, regs->rip); - print_symbol(regs->rip); + print_symbol(regs->rip, KERNEL_TEXT_ADDR); print_flags(regs->rflags); printf("rsp: %016"PRIx64"\n", regs->rsp); @@ -457,7 +485,7 @@ static void print_ctx_32(vcpu_guest_context_t *ctx) vcpu_guest_core_regs_t *regs = &ctx->user_regs; printf("PC: %08"PRIx32, regs->pc32); - print_symbol(regs->pc32); + print_symbol(regs->pc32, KERNEL_TEXT_ADDR); printf("\n"); printf("CPSR: %08"PRIx32"\n", regs->cpsr); printf("USR: SP:%08"PRIx32" LR:%08"PRIx32"\n", @@ -509,7 +537,7 @@ static void print_ctx_64(vcpu_guest_context_t *ctx) vcpu_guest_core_regs_t *regs = &ctx->user_regs; printf("PC: %016"PRIx64, regs->pc64); - print_symbol(regs->pc64); + print_symbol(regs->pc64, KERNEL_TEXT_ADDR); printf("\n"); printf("LR: %016"PRIx64"zn", regs->x30); @@ -805,7 +833,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest print_stack_word(instr_pointer(ctx), width); printf(">]"); - print_symbol(instr_pointer(ctx)); + print_symbol(instr_pointer(ctx), KERNEL_TEXT_ADDR); printf(" <--\n"); } if (xenctx.frame_ptrs) { @@ -860,7 +888,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest } print_stack_word(word, width); printf(">]"); - print_symbol(word); + print_symbol(word, KERNEL_TEXT_ADDR); printf("\n"); stack += width; } @@ -872,7 +900,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest if (!p) return -1; word = read_mem_word(ctx, vcpu, stack, width); - if (is_kernel_text(word)) { + if (kernel_addr(word) >= KERNEL_TEXT_ADDR) { if (xenctx.tag_call_trace) { print_stack_word(stack, width); printf(": [<"); @@ -881,7 +909,7 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, guest } print_stack_word(word, width); printf(">]"); - print_symbol(word); + print_symbol(word, KERNEL_TEXT_ADDR); printf("\n"); } else if (xenctx.stack_trace) { if (xenctx.tag_call_trace) { @@ -953,7 +981,7 @@ static void dump_ctx(int vcpu) #ifndef NO_TRANSLATION if (print_code(&ctx, vcpu)) return; - if (is_kernel_text(instr_pointer(&ctx))) + if (kernel_addr(instr_pointer(&ctx)) >= KERNEL_TEXT_ADDR) if (print_stack(&ctx, vcpu, guest_word_size, stack_pointer(&ctx))) return; #endif @@ -1098,6 +1126,7 @@ int main(int argc, char **argv) break; case ''k'': kernel_start = strtoull(optarg, NULL, 0); + xenctx.kernel_start_set = 1; break; #ifndef NO_TRANSLATION case ''m'': -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 14/16] xenctx: Add convert of more registers to symbols
From: Don Slutz <dslutz@verizon.com> For example can change: gs: 0000 @ ffffffff803ac000/0000000000000000 to gs: 0000 @ ffffffff803ac000/0000000000000000 boot_cpu_pda/ Signed-off-by: Don Slutz <dslutz@verizon.com> --- Changed since v2: * Extract just the symbol printing code from "xenctx: Dump registers via hvm info if available" tools/xentrace/xenctx.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 23f2199..d0398da 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -317,10 +317,14 @@ static void print_special(void *regs, const char *name, unsigned int mask, int w printf("\n"); for (i = 0; mask; mask >>= 1, ++i) if (mask & 1) { - if (width == 4) - printf("%s%u: %08"PRIx32"\n", name, i, ((uint32_t *) regs)[i]); - else - printf("%s%u: %08"PRIx64"\n", name, i, ((uint64_t *) regs)[i]); + if (width == 4) { + printf("%s%u: %08"PRIx32, name, i, ((uint32_t *) regs)[i]); + print_symbol(((uint32_t *) regs)[i], KERNEL_DATA_ADDR); + } else { + printf("%s%u: %016"PRIx64, name, i, ((uint64_t *) regs)[i]); + print_symbol(((uint64_t *) regs)[i], KERNEL_DATA_ADDR); + } + printf("\n"); } } @@ -416,9 +420,17 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx) printf(" ds: %04x\t", regs->ds); printf(" es: %04x\n", regs->es); - printf(" fs: %04x @ %016"PRIx64"\n", regs->fs, ctx->fs_base); - printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64"\n", regs->gs, + printf(" fs: %04x @ %016"PRIx64, regs->fs, ctx->fs_base); + print_symbol(ctx->fs_base, KERNEL_DATA_ADDR); + printf("\n"); + printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64, regs->gs, ctx->gs_base_kernel, ctx->gs_base_user); + if (symbol_table) { + print_symbol(ctx->gs_base_kernel, KERNEL_DATA_ADDR); + printf("/"); + print_symbol(ctx->gs_base_user, KERNEL_DATA_ADDR); + } + printf("\n"); if (xenctx.disp_all) { print_special(ctx->ctrlreg, "cr", 0x1d, 8); -- 1.8.4
Don Slutz
2013-Nov-11 18:15 UTC
[PATCH v3 15/16] xenctx: Add output of vcpu value and state for --all-vcpus
From: Don Slutz <dslutz@verizon.com> This makes it easier to know which vcpu the registers belong to and when not all vcpus are online, which vcpu it is. Signed-off-by: Don Slutz <dslutz@verizon.com> --- Changed since v2: * Extract just the vcpu printing code from "xenctx: xenctx: Add optional fCPU" tools/xentrace/xenctx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index d0398da..8d96e9f 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -1007,8 +1007,13 @@ static void dump_all_vcpus(void) { if ( xc_vcpu_getinfo(xenctx.xc_handle, xenctx.domid, vcpu, &vinfo) ) continue; - if ( vinfo.online ) + if ( vinfo.online ) { + printf("vcpu=%d online\n", vcpu); dump_ctx(vcpu); + printf("\n"); + } else { + printf("vcpu=%d offline\n\n", vcpu); + } } } -- 1.8.4
From: Don Slutz <dslutz@verizon.com> Signed-off-by: Don Slutz <dslutz@verizon.com> --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 843f9e3..b21e1cd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -312,11 +312,17 @@ M: Tim Deegan <tim@xen.org> S: Supported F: xen/arch/x86/mm/ +XENCTX +M: Don Slutz <dslutz@verizon.com> +S: Supported +F: tools/xentrace/xenctx + XENTRACE M: George Dunlap <george.dunlap@eu.citrix.com> S: Supported F: tools/xentrace/ F: xen/common/trace.c +X: tools/xentrace/xenctx XSM/FLASK M: Daniel De Graaf <dgdegra@tycho.nsa.gov> -- 1.8.4
Jan Beulich
2013-Nov-12 15:31 UTC
Re: [PATCH v3 04/16] xenctx: Add -2 (--two-pages) option to switch stack size to 8KiB
>>> On 11.11.13 at 19:15, Don Slutz <dslutz@verizon.com> wrote: > @@ -823,18 +826,20 @@ static void usage(void) > kernel_start); > printf(" -a, --all display more registers\n"); > printf(" -C, --all-vcpus print info for all vcpus\n"); > + printf(" -2, --two-pages assume the kernel was compiled with 8KiB stacks.\n");I think it was IanC who had pointed out on the previous version that this would benefit from making fully flexible (i.e. also allowing larger stack sizes). Jan
Don Slutz
2013-Nov-13 17:19 UTC
Re: [PATCH v3 04/16] xenctx: Add -2 (--two-pages) option to switch stack size to 8KiB
On 11/12/13 10:31, Jan Beulich wrote:>>>> On 11.11.13 at 19:15, Don Slutz <dslutz@verizon.com> wrote: >> @@ -823,18 +826,20 @@ static void usage(void) >> kernel_start); >> printf(" -a, --all display more registers\n"); >> printf(" -C, --all-vcpus print info for all vcpus\n"); >> + printf(" -2, --two-pages assume the kernel was compiled with 8KiB stacks.\n"); > I think it was IanC who had pointed out on the previous version > that this would benefit from making fully flexible (i.e. also > allowing larger stack sizes). > > Jan >Here is a fully flexible version: From 81f8af696816c02d13a6b29f6bb6ae8c4d99250d Mon Sep 17 00:00:00 2001 From: Don Slutz <Don@CloudSwitch.com> Date: Mon, 2 Jul 2012 18:48:52 -0400 Subject: [PATCH] xenctx: Add -m (--multiple_pages) option to output larger stack Important: This is the stack size to display not the configured stack size. Using pictures (for a 3 page configured system): +------------------+ | | | | | | | | | | +------------------+ | | | | | | | | | | +------------------+ | | | | | | SP --> | | | | +------------------+ Display using "-m 1" since the used stack pages is 1. +------------------+ | | | | | | | | | | +------------------+ | | SP --> | | | | | | | | +------------------+ | | | | | | | | | | +------------------+ Display using "-m 2" since the used stack pages is 1. +------------------+ | | | | | | | | SP --> | | +------------------+ | | | | | | | | | | +------------------+ | | | | | | | | | | +------------------+ Display using "-m 3" since the used stack pages is 1. Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- tools/xentrace/xenctx.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 841078d..2be5b08 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -35,6 +35,7 @@ static struct xenctx { int frame_ptrs; int stack_trace; int disp_all; + int multiple_pages; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -650,6 +651,8 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE) & ~((guest_word_t) XC_PAGE_SIZE - 1)); + if (xenctx.multiple_pages > 1) + stack_limit += (xenctx.multiple_pages - 1) * XC_PAGE_SIZE; printf("\n"); printf("Stack:\n"); for (i=1; i<5 && stack < stack_limit; i++) { @@ -823,18 +826,21 @@ static void usage(void) kernel_start); printf(" -a, --all display more registers\n"); printf(" -C, --all-vcpus print info for all vcpus\n"); + printf(" -m PAGES, --multiple-pages=PAGES\n"); + printf(" assume the kernel was compiled with PAGES (default 1) of stacks.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC"; + static const char *sopts = "fs:hak:SCm:"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, {"frame-pointers", 0, NULL, ''f''}, {"kernel-start", 1, NULL, ''k''}, + {"multiple-pages", 0, NULL, ''m''}, {"all", 0, NULL, ''a''}, {"all-vcpus", 0, NULL, ''C''}, {"help", 0, NULL, ''h''}, @@ -858,6 +864,9 @@ int main(int argc, char **argv) case ''a'': xenctx.disp_all = 1; break; + case ''m'': + xenctx.multiple_pages = strtol(optarg, NULL, 0); + break; case ''C'': xenctx.all_vcpus = 1; break; -- 1.7.11.7
On 11/11/13 13:15, Don Slutz wrote:> From: Don Slutz <dslutz@verizon.com> > > Fix usage formatting to be all the same. > > Fix usage display of default --kernel-start for 64 bit. > > Signed-off-by: Don Slutz <dslutz@verizon.com> > --- > tools/xentrace/xenctx.c | 17 +++++++++-------- > 1 file changed, 9 insertions(+), 8 deletions(-) > > diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c > index 060e480..4490d82 100644 > --- a/tools/xentrace/xenctx.c > +++ b/tools/xentrace/xenctx.c > @@ -812,15 +812,16 @@ static void usage(void) > > printf("options:\n"); > printf(" -f, --frame-pointers\n"); > - printf(" assume the kernel was compiled with\n"); > - printf(" frame pointers.\n"); > + printf(" assume the kernel was compiled with\n"); > + printf(" frame pointers.\n"); > printf(" -s SYMTAB, --symbol-table=SYMTAB\n"); > - printf(" read symbol table from SYMTAB.\n"); > - printf(" -S --stack-trace print a complete stack trace.\n"); > - printf(" -k, --kernel-start\n"); > - printf(" set user/kernel split. (default 0xc0000000)\n"); > - printf(" -a --all display more registers\n"); > - printf(" -C --all-vcpus print info for all vcpus\n"); > + printf(" read symbol table from SYMTAB.\n"); > + printf(" -S, --stack-trace print a complete stack trace.\n"); > + printf(" -k kaddr, --kernel-start=kaddr\n");When redoing patch #4 I noticed that kaddr was not added as KADDR. Also I started using <maddr> not MADDR. Which is the preferred way? -Don Slutz> + printf(" set user/kernel split. (default 0x"FMT_32B_WORD")\n", > + kernel_start); > + printf(" -a, --all display more registers\n"); > + printf(" -C, --all-vcpus print info for all vcpus\n"); > } > > int main(int argc, char **argv)
Don Slutz
2013-Nov-14 12:04 UTC
Re: [PATCH v3 02/16] xenctx: Correct check for xc_interface_open failing (prevents SIGSEGV)
I missed seeing: http://lists.xen.org/archives/html/xen-devel/2013-10/msg02343.html Which this is a duplicate of. Will drop in v4. -Don Slutz On 11/11/13 13:15, Don Slutz wrote:> From: Don Slutz <dslutz@verizon.com> > > Signed-off-by: Don Slutz <dslutz@verizon.com> > --- > tools/xentrace/xenctx.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c > index 4490d82..3d18bf7 100644 > --- a/tools/xentrace/xenctx.c > +++ b/tools/xentrace/xenctx.c > @@ -892,7 +892,7 @@ int main(int argc, char **argv) > read_symbol_table(symbol_table); > > xenctx.xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */ > - if (xenctx.xc_handle < 0) { > + if (!xenctx.xc_handle) { > perror("xc_interface_open"); > exit(-1); > }