mcinspect: vtop (in progress)
Change-Id: I09f487e96edc7c4f59c97e6fb6dde28baf84c1e5
This commit is contained in:
committed by
Masamichi Takagi
parent
91146acfe5
commit
5224551782
@ -29,6 +29,7 @@ if (NOT LIBDWARF)
|
|||||||
else()
|
else()
|
||||||
target_link_libraries(mcinspect ${LIBDWARF})
|
target_link_libraries(mcinspect ${LIBDWARF})
|
||||||
endif()
|
endif()
|
||||||
|
target_link_libraries(mcinspect ${LIBBFD})
|
||||||
|
|
||||||
add_executable(eclair eclair.c arch/${ARCH}/arch-eclair.c)
|
add_executable(eclair eclair.c arch/${ARCH}/arch-eclair.c)
|
||||||
target_link_libraries(eclair ${LIBBFD})
|
target_link_libraries(eclair ${LIBBFD})
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include <libdwarf/libdwarf.h>
|
#include <libdwarf/libdwarf.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <bfd.h>
|
||||||
|
|
||||||
void usage(char **argv)
|
void usage(char **argv)
|
||||||
{
|
{
|
||||||
@ -32,22 +33,88 @@ void usage(char **argv)
|
|||||||
printf(" --help Display this help message.\n");
|
printf(" --help Display this help message.\n");
|
||||||
printf(" --kernel PATH Path to kernel image.\n");
|
printf(" --kernel PATH Path to kernel image.\n");
|
||||||
printf(" --ps List processes running on LWK.\n");
|
printf(" --ps List processes running on LWK.\n");
|
||||||
printf(" -v, --vtop [ADDR] Display page table corresponding to ADDR\n");
|
printf(" --vtop Dump page tables.\n");
|
||||||
printf(" or dump all page tables.\n");
|
printf(" -v, --va ADDR Dump page tables for ADDR only.\n");
|
||||||
|
printf(" -p, --pid PID Use process PID for vtop.\n");
|
||||||
printf(" --debug Enable debug mode.\n");
|
printf(" --debug Enable debug mode.\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Example: \n");
|
printf("Examples: \n");
|
||||||
printf(" %s --kernel=smp-x86/kernel/mckernel.img --ps\n", basename(argv[0]));
|
printf(" %s --kernel=smp-x86/kernel/mckernel.img --ps\n", basename(argv[0]));
|
||||||
|
printf(" %s --kernel=smp-x86/kernel/mckernel.img --vtop --pid 100 --va 0x3fffff800000\n",
|
||||||
|
basename(argv[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int debug;
|
int debug;
|
||||||
int mcfd;
|
int mcfd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BFD based symbol table
|
||||||
|
*/
|
||||||
|
bfd *symbfd = NULL;
|
||||||
|
asymbol **symtab = NULL;
|
||||||
|
ssize_t nsyms;
|
||||||
|
#define NOSYMBOL (-1UL)
|
||||||
|
|
||||||
|
unsigned long int lookup_bfd_symbol(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nsyms; ++i) {
|
||||||
|
if (!strcmp(symtab[i]->name, name)) {
|
||||||
|
return (symtab[i]->section->vma + symtab[i]->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOSYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_bfd_symbols(char *fname) {
|
||||||
|
ssize_t needs;
|
||||||
|
bfd_boolean ok;
|
||||||
|
|
||||||
|
symbfd = bfd_openr(fname, NULL);
|
||||||
|
|
||||||
|
if (!symbfd) {
|
||||||
|
bfd_perror("bfd_openr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = bfd_check_format(symbfd, bfd_object);
|
||||||
|
if (!ok) {
|
||||||
|
bfd_perror("bfd_check_format");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
needs = bfd_get_symtab_upper_bound(symbfd);
|
||||||
|
if (needs < 0) {
|
||||||
|
bfd_perror("bfd_get_symtab_upper_bound");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!needs) {
|
||||||
|
printf("no symbols\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
symtab = malloc(needs);
|
||||||
|
if (!symtab) {
|
||||||
|
perror("malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsyms = bfd_canonicalize_symtab(symbfd, symtab);
|
||||||
|
if (nsyms < 0) {
|
||||||
|
bfd_perror("bfd_canonicalize_symtab");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Walk DWARF tree and call func with arg for each Die
|
* Walk DWARF tree and call func with arg for each Die
|
||||||
*/
|
*/
|
||||||
static int dwarf_walk_tree(Dwarf_Debug dbg,
|
int dwarf_walk_tree(Dwarf_Debug dbg,
|
||||||
int (*func)(Dwarf_Debug dbg, Dwarf_Die die, void *arg), void *arg)
|
int (*func)(Dwarf_Debug dbg, Dwarf_Die die, void *arg), void *arg)
|
||||||
{
|
{
|
||||||
Dwarf_Bool is_info;
|
Dwarf_Bool is_info;
|
||||||
@ -191,7 +258,7 @@ static int dwarf_walk_tree(Dwarf_Debug dbg,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dwarf_get_size(Dwarf_Debug dbg,
|
int dwarf_get_size(Dwarf_Debug dbg,
|
||||||
Dwarf_Die die,
|
Dwarf_Die die,
|
||||||
unsigned long *psize,
|
unsigned long *psize,
|
||||||
Dwarf_Error *perr)
|
Dwarf_Error *perr)
|
||||||
@ -345,7 +412,7 @@ out:
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
static int dwarf_get_offset(Dwarf_Debug dbg,
|
int dwarf_get_offset(Dwarf_Debug dbg,
|
||||||
Dwarf_Die die,
|
Dwarf_Die die,
|
||||||
unsigned long *poffset,
|
unsigned long *poffset,
|
||||||
Dwarf_Error *perr)
|
Dwarf_Error *perr)
|
||||||
@ -560,7 +627,7 @@ out:
|
|||||||
/*
|
/*
|
||||||
* Find the address of a global variable.
|
* Find the address of a global variable.
|
||||||
*/
|
*/
|
||||||
static int dwarf_get_address(Dwarf_Debug dbg,
|
int dwarf_get_address(Dwarf_Debug dbg,
|
||||||
Dwarf_Die die,
|
Dwarf_Die die,
|
||||||
unsigned long *paddr,
|
unsigned long *paddr,
|
||||||
Dwarf_Error *perr)
|
Dwarf_Error *perr)
|
||||||
@ -611,6 +678,7 @@ static int dwarf_get_address(Dwarf_Debug dbg,
|
|||||||
if (attr_i != DW_AT_location) {
|
if (attr_i != DW_AT_location) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
printf("%s: DW_AT_location\n", __func__);
|
||||||
|
|
||||||
rc = dwarf_whatform(attr, &form, perr);
|
rc = dwarf_whatform(attr, &form, perr);
|
||||||
if (rc != DW_DLV_OK) {
|
if (rc != DW_DLV_OK) {
|
||||||
@ -779,8 +847,11 @@ int dwarf_global_var_addr(Dwarf_Debug dbg, Dwarf_Die die, void *arg)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("%s: inspecting %s\n", __func__, name);
|
||||||
|
|
||||||
rc = dwarf_get_address(dbg, die, &addr, &err);
|
rc = dwarf_get_address(dbg, die, &addr, &err);
|
||||||
if (rc == DW_DLV_NO_ENTRY) {
|
if (rc == DW_DLV_NO_ENTRY) {
|
||||||
|
printf("%s: inspecting %s -> DW_DLV_NO_ENTRY for addr?\n", __func__, name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
else if (rc != DW_DLV_OK) {
|
else if (rc != DW_DLV_OK) {
|
||||||
@ -812,12 +883,15 @@ out:
|
|||||||
.variable = #__variable__, \
|
.variable = #__variable__, \
|
||||||
.addrp = &addr, \
|
.addrp = &addr, \
|
||||||
}; \
|
}; \
|
||||||
|
addr = lookup_bfd_symbol(gva.variable); \
|
||||||
|
if (addr == NOSYMBOL) { \
|
||||||
rc = dwarf_walk_tree(dbg, dwarf_global_var_addr, &gva); \
|
rc = dwarf_walk_tree(dbg, dwarf_global_var_addr, &gva); \
|
||||||
if (rc != DW_DLV_OK) { \
|
if (rc != DW_DLV_OK) { \
|
||||||
fprintf(stderr, "%s: error: finding addr of %s\n", \
|
fprintf(stderr, "%s: error: finding addr of %s\n", \
|
||||||
__func__, gva.variable); \
|
__func__, gva.variable); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
} \
|
} \
|
||||||
|
} \
|
||||||
addr; \
|
addr; \
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -831,7 +905,7 @@ struct ihk_os_read_kaddr_desc {
|
|||||||
void *ubuf;
|
void *ubuf;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ihk_read_kernel(unsigned long addr,
|
void ihk_read_kernel(unsigned long addr,
|
||||||
unsigned long len, void *buf)
|
unsigned long len, void *buf)
|
||||||
{
|
{
|
||||||
struct ihk_os_read_kaddr_desc desc;
|
struct ihk_os_read_kaddr_desc desc;
|
||||||
@ -850,6 +924,14 @@ static void ihk_read_kernel(unsigned long addr,
|
|||||||
#define ihk_read_val(addr, pval) \
|
#define ihk_read_val(addr, pval) \
|
||||||
ihk_read_kernel(addr, sizeof(*pval), (void *)pval)
|
ihk_read_kernel(addr, sizeof(*pval), (void *)pval)
|
||||||
|
|
||||||
|
#define get_pointer_symbol_val(__variable__, pval) \
|
||||||
|
({ \
|
||||||
|
unsigned long addr; \
|
||||||
|
addr = DWARF_GET_VARIABLE_ADDRESS(__variable__); \
|
||||||
|
ihk_read_kernel(addr, sizeof(*pval), (void *)pval); \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#define PS_RUNNING 0x1
|
#define PS_RUNNING 0x1
|
||||||
#define PS_INTERRUPTIBLE 0x2
|
#define PS_INTERRUPTIBLE 0x2
|
||||||
#define PS_UNINTERRUPTIBLE 0x4
|
#define PS_UNINTERRUPTIBLE 0x4
|
||||||
@ -857,6 +939,9 @@ static void ihk_read_kernel(unsigned long addr,
|
|||||||
#define PS_EXITED 0x10
|
#define PS_EXITED 0x10
|
||||||
#define PS_STOPPED 0x20
|
#define PS_STOPPED 0x20
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
int nr_cpus;
|
int nr_cpus;
|
||||||
unsigned long clv;
|
unsigned long clv;
|
||||||
unsigned long clv_size;
|
unsigned long clv_size;
|
||||||
@ -868,10 +953,44 @@ unsigned long thread_sched_list_offset;
|
|||||||
unsigned long thread_proc_offset;
|
unsigned long thread_proc_offset;
|
||||||
unsigned long thread_status_offset;
|
unsigned long thread_status_offset;
|
||||||
unsigned long process_pid_offset;
|
unsigned long process_pid_offset;
|
||||||
|
unsigned long process_vm_offset;
|
||||||
unsigned long process_saved_cmdline_offset;
|
unsigned long process_saved_cmdline_offset;
|
||||||
unsigned long process_saved_cmdline_len_offset;
|
unsigned long process_saved_cmdline_len_offset;
|
||||||
|
unsigned long vm_address_space_offset;
|
||||||
|
unsigned long address_space_page_table_offset;
|
||||||
|
|
||||||
static void print_thread(int cpu,
|
void init_globals(Dwarf_Debug dbg)
|
||||||
|
{
|
||||||
|
unsigned long num_processors_addr;
|
||||||
|
|
||||||
|
num_processors_addr = DWARF_GET_VARIABLE_ADDRESS(mck_num_processors);
|
||||||
|
ihk_read_val(num_processors_addr, &num_processors_addr);
|
||||||
|
ihk_read_val(num_processors_addr, &nr_cpus);
|
||||||
|
ihk_read_val(DWARF_GET_VARIABLE_ADDRESS(clv), &clv);
|
||||||
|
clv_size = DWARF_GET_SIZE(cpu_local_var);
|
||||||
|
|
||||||
|
clv_runq_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, runq);
|
||||||
|
clv_idle_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, idle);
|
||||||
|
clv_current_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, current);
|
||||||
|
thread_tid_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, tid);
|
||||||
|
thread_proc_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, proc);
|
||||||
|
thread_status_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, status);
|
||||||
|
thread_sched_list_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(thread, sched_list);
|
||||||
|
process_pid_offset = DWARF_GET_OFFSET_IN_STRUCT(process, pid);
|
||||||
|
process_saved_cmdline_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(process, saved_cmdline);
|
||||||
|
process_saved_cmdline_len_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(process, saved_cmdline_len);
|
||||||
|
process_vm_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(process, vm);
|
||||||
|
vm_address_space_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(process_vm, address_space);
|
||||||
|
address_space_page_table_offset =
|
||||||
|
DWARF_GET_OFFSET_IN_STRUCT(address_space, page_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_thread(int cpu,
|
||||||
unsigned long thread,
|
unsigned long thread,
|
||||||
unsigned long idle,
|
unsigned long idle,
|
||||||
int active)
|
int active)
|
||||||
@ -925,31 +1044,9 @@ static void print_thread(int cpu,
|
|||||||
free(cmd_line);
|
free(cmd_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mcps(Dwarf_Debug dbg)
|
||||||
static int mcps(Dwarf_Debug dbg)
|
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
unsigned long num_processors_addr;
|
|
||||||
|
|
||||||
num_processors_addr = DWARF_GET_VARIABLE_ADDRESS(mck_num_processors);
|
|
||||||
ihk_read_val(num_processors_addr, &num_processors_addr);
|
|
||||||
ihk_read_val(num_processors_addr, &nr_cpus);
|
|
||||||
ihk_read_val(DWARF_GET_VARIABLE_ADDRESS(clv), &clv);
|
|
||||||
clv_size = DWARF_GET_SIZE(cpu_local_var);
|
|
||||||
|
|
||||||
clv_runq_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, runq);
|
|
||||||
clv_idle_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, idle);
|
|
||||||
clv_current_offset = DWARF_GET_OFFSET_IN_STRUCT(cpu_local_var, current);
|
|
||||||
thread_tid_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, tid);
|
|
||||||
thread_proc_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, proc);
|
|
||||||
thread_status_offset = DWARF_GET_OFFSET_IN_STRUCT(thread, status);
|
|
||||||
thread_sched_list_offset =
|
|
||||||
DWARF_GET_OFFSET_IN_STRUCT(thread, sched_list);
|
|
||||||
process_pid_offset = DWARF_GET_OFFSET_IN_STRUCT(process, pid);
|
|
||||||
process_saved_cmdline_offset =
|
|
||||||
DWARF_GET_OFFSET_IN_STRUCT(process, saved_cmdline);
|
|
||||||
process_saved_cmdline_len_offset =
|
|
||||||
DWARF_GET_OFFSET_IN_STRUCT(process, saved_cmdline_len);
|
|
||||||
|
|
||||||
printf("%3s %s%6s %6s %18s %2s %s\n",
|
printf("%3s %s%6s %6s %18s %2s %s\n",
|
||||||
"CPU", " ", "TID", "PID", "Thread", "ST", "exe");
|
"CPU", " ", "TID", "PID", "Thread", "ST", "exe");
|
||||||
@ -991,12 +1088,107 @@ static int mcps(Dwarf_Debug dbg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_proc(Dwarf_Debug dbg, int pid, unsigned long *rproc)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
/* Iterate CPUs */
|
||||||
|
for (cpu = 0; cpu < nr_cpus; ++cpu) {
|
||||||
|
unsigned long per_cpu;
|
||||||
|
unsigned long runq;
|
||||||
|
unsigned long thread;
|
||||||
|
unsigned long thread_sched_list;
|
||||||
|
int ipid;
|
||||||
|
|
||||||
|
per_cpu = clv + (clv_size * cpu);
|
||||||
|
runq = per_cpu + clv_runq_offset;
|
||||||
|
ihk_read_val(per_cpu + clv_runq_offset, &thread_sched_list);
|
||||||
|
|
||||||
|
/* Iterate threads */
|
||||||
|
for (; thread_sched_list != runq;
|
||||||
|
ihk_read_val(thread_sched_list, &thread_sched_list)) {
|
||||||
|
unsigned long proc;
|
||||||
|
|
||||||
|
thread = thread_sched_list - thread_sched_list_offset;
|
||||||
|
|
||||||
|
ihk_read_val(thread + thread_proc_offset, &proc);
|
||||||
|
ihk_read_val(proc + process_pid_offset, &ipid);
|
||||||
|
|
||||||
|
if (pid == ipid) {
|
||||||
|
*rproc = proc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void do_pte_walk_single(Dwarf_Debug dbg,
|
||||||
|
unsigned long pt, int level, unsigned long va)
|
||||||
|
{
|
||||||
|
unsigned long pte;
|
||||||
|
int idx = va >> ptl_shift(level);
|
||||||
|
|
||||||
|
ihk_read_val(pt + idx * sizeof(pte), &pte);
|
||||||
|
if (pte_is_type_page(pte, level)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level > 1) {
|
||||||
|
pt =
|
||||||
|
do_pte_walk_single();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int print_pte_single(Dwarf_Debug dbg,
|
||||||
|
unsigned long pt, unsigned long va)
|
||||||
|
{
|
||||||
|
int level = PGTABLE_LEVELS;
|
||||||
|
printf("VA: 0x%lx -> \n", va);
|
||||||
|
do_pte_walk_single(dbg, pt, PGTABLE_LEVELS, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int mcvtop(Dwarf_Debug dbg, int pid, unsigned long vtop_addr)
|
||||||
|
{
|
||||||
|
unsigned long proc = 0;
|
||||||
|
unsigned long init_pt;
|
||||||
|
unsigned long vm, ap, pt = 0;
|
||||||
|
|
||||||
|
if (pid != 0) {
|
||||||
|
if (find_proc(dbg, pid, &proc) < 0) {
|
||||||
|
fprintf(stderr, "%s: error: finding PID %d\n",
|
||||||
|
__func__, pid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_pointer_symbol_val(swapper_page_table, &init_pt);
|
||||||
|
printf("%s: init_pt: 0x%lx\n", __func__, init_pt);
|
||||||
|
|
||||||
|
if (proc) {
|
||||||
|
ihk_read_val(proc + process_vm_offset, &vm);
|
||||||
|
ihk_read_val(vm + vm_address_space_offset, &ap);
|
||||||
|
ihk_read_val(ap + address_space_page_table_offset, &pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int help;
|
int help;
|
||||||
int ps;
|
int ps;
|
||||||
int vtop;
|
int vtop;
|
||||||
|
int pid;
|
||||||
unsigned long vtop_addr;
|
unsigned long vtop_addr;
|
||||||
|
|
||||||
static struct option mcinspect_options[] = {
|
struct option mcinspect_options[] = {
|
||||||
{
|
{
|
||||||
.name = "kernel",
|
.name = "kernel",
|
||||||
.has_arg = required_argument,
|
.has_arg = required_argument,
|
||||||
@ -1015,17 +1207,29 @@ static struct option mcinspect_options[] = {
|
|||||||
.flag = &help,
|
.flag = &help,
|
||||||
.val = 1,
|
.val = 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "debug",
|
||||||
|
.has_arg = no_argument,
|
||||||
|
.flag = &debug,
|
||||||
|
.val = 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "vtop",
|
.name = "vtop",
|
||||||
|
.has_arg = no_argument,
|
||||||
|
.flag = &vtop,
|
||||||
|
.val = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "va",
|
||||||
.has_arg = required_argument,
|
.has_arg = required_argument,
|
||||||
.flag = NULL,
|
.flag = NULL,
|
||||||
.val = 'v',
|
.val = 'v',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "debug",
|
.name = "pid",
|
||||||
.has_arg = no_argument,
|
.has_arg = required_argument,
|
||||||
.flag = &debug,
|
.flag = NULL,
|
||||||
.val = 1,
|
.val = 'p',
|
||||||
},
|
},
|
||||||
/* end */
|
/* end */
|
||||||
{ NULL, 0, NULL, 0, },
|
{ NULL, 0, NULL, 0, },
|
||||||
@ -1048,9 +1252,10 @@ int main(int argc, char **argv)
|
|||||||
help = 0;
|
help = 0;
|
||||||
ps = 0;
|
ps = 0;
|
||||||
vtop = 0;
|
vtop = 0;
|
||||||
vtop_addr = -1;
|
vtop_addr = -1UL;
|
||||||
|
pid = 0;
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "+k:v:",
|
while ((opt = getopt_long(argc, argv, "+k:v:p:",
|
||||||
mcinspect_options, NULL)) != -1) {
|
mcinspect_options, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'k':
|
case 'k':
|
||||||
@ -1058,7 +1263,17 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
vtop_addr = strtoul(optarg, 0, 0);
|
vtop_addr = strtoul(optarg, 0, 16);
|
||||||
|
if (vtop_addr == 0 ||
|
||||||
|
errno == EINVAL || errno == ERANGE) {
|
||||||
|
fprintf(stderr, "error: invalid VA? (expected format: 0xXXXX)\n\n");
|
||||||
|
usage(argv);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
pid = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1075,10 +1290,16 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ps && !vtop) {
|
if (!ps && !vtop) {
|
||||||
|
printf("PID: %d\n", pid);
|
||||||
usage(argv);
|
usage(argv);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (init_bfd_symbols(kernel_path) < 0) {
|
||||||
|
fprintf(stderr, "error: accessing ELF image %s\n", kernel_path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
mcfd = open("/dev/mcos0", O_RDONLY);
|
mcfd = open("/dev/mcos0", O_RDONLY);
|
||||||
if (mcfd < 0) {
|
if (mcfd < 0) {
|
||||||
fprintf(stderr, "error: opening IHK OS device file\n");
|
fprintf(stderr, "error: opening IHK OS device file\n");
|
||||||
@ -1097,12 +1318,13 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_globals(dbg);
|
||||||
|
|
||||||
if (ps)
|
if (ps)
|
||||||
mcps(dbg);
|
mcps(dbg);
|
||||||
|
|
||||||
if (vtop) {
|
if (vtop) {
|
||||||
fprintf(stderr, "error: not implemented\n");
|
mcvtop(dbg, pid, vtop_addr);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dwarf_finish(dbg, &error);
|
dwarf_finish(dbg, &error);
|
||||||
|
|||||||
Reference in New Issue
Block a user