[Pdbg] [PATCH 8/8] pdbg: Use new command parsing

rashmica rashmicy at gmail.com
Thu Jun 28 11:55:33 AEST 2018


On 20/06/18 15:34, Alistair Popple wrote:
> This switches all commands except the htm command to use the new command/option
> parsing code. For the moment we leave the usage help and generic targeting flag
> processing alone, but future changes should allow this to also use the common
> parsing code.
>
> Signed-off-by: Alistair Popple <alistair at popple.id.au>
> ---
>  Makefile.am  |   1 +
>  src/cfam.c   |  55 ++++++--------------
>  src/cfam.h   |  18 -------
>  src/main.c   | 125 ++++++++++++++++++++++++++++-----------------
>  src/mem.c    | 124 ++++++++------------------------------------
>  src/mem.h    |  20 --------
>  src/reg.c    | 164 +++++++++++++++--------------------------------------------
>  src/reg.h    |  20 --------
>  src/ring.c   |  32 ++----------
>  src/ring.h   |  17 -------
>  src/scom.c   |  54 +++++---------------
>  src/scom.h   |  18 -------
>  src/thread.c |  87 ++++++++++++++++++++++---------
>  src/thread.h |  23 ---------
>  14 files changed, 237 insertions(+), 521 deletions(-)
>  delete mode 100644 src/cfam.h
>  delete mode 100644 src/mem.h
>  delete mode 100644 src/reg.h
>  delete mode 100644 src/ring.h
>  delete mode 100644 src/scom.h
>  delete mode 100644 src/thread.h
>
> diff --git a/Makefile.am b/Makefile.am
> index 23f2080..4e0dce2 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -39,6 +39,7 @@ pdbg_SOURCES = \
>  	src/ring.c \
>  	src/htm.c \
>  	src/progress.c \
> +	src/parsers.c \
>  	src/optcmd.c \
>  	src/options_ at ARCH@.c
>  
> diff --git a/src/cfam.c b/src/cfam.c
> index 269123e..6dab388 100644
> --- a/src/cfam.c
> +++ b/src/cfam.c
> @@ -20,8 +20,9 @@
>  #include <inttypes.h>
>  
>  #include "main.h"
> +#include "optcmd.h"
>  
> -static int getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused)
> +static int _getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused)
>  {
>  	uint32_t value;
>  
> @@ -33,7 +34,15 @@ static int getcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, u
>  	return 1;
>  }
>  
> -static int putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data)
> +static int getcfam(uint32_t addr)
> +{
> +	uint64_t addr64 = addr;
> +
> +	return for_each_target("fsi", _getcfam, &addr64, NULL);
> +}
> +OPTCMD_DEFINE_CMD_WITH_ARGS(getcfam, getcfam, (ADDRESS32));
> +
> +static int _putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data)
>  {
>  	if (fsi_write(target, *addr, *data))
>  		return 0;
> @@ -41,44 +50,10 @@ static int putcfam(struct pdbg_target *target, uint32_t index, uint64_t *addr, u
>  	return 1;
>  }
>  
> -int handle_cfams(int optind, int argc, char *argv[])
> +static int putcfam(uint32_t addr, uint32_t data)
>  {
> -	uint64_t addr;
> -	char *endptr;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires an address\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	addr = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse address '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> +	uint64_t addr64 = addr, data64 = data;
>  
> -	if (strcmp(argv[optind], "putcfam") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 2 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		data = strtoull(argv[optind + 2], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> -
> -		return for_each_target("fsi", putcfam, &addr, &data);
> -	}
> -
> -	return for_each_target("fsi", getcfam, &addr, NULL);
> +	return for_each_target("fsi", _putcfam, &addr64, &data64);
>  }
> -
> -
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putcfam, putcfam, (ADDRESS32, DATA32));
> diff --git a/src/cfam.h b/src/cfam.h
> deleted file mode 100644
> index 997ed3d..0000000
> --- a/src/cfam.h
> +++ /dev/null
> @@ -1,18 +0,0 @@
> -/* Copyright 2017 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - * 	http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -#include <inttypes.h>
> -
> -int handle_cfams(int optind, int argc, char *argv[]);
> diff --git a/src/main.c b/src/main.c
> index cf9a3b2..1cfaca7 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -34,14 +34,9 @@
>  #include <target.h>
>  
>  #include "main.h"
> -#include "cfam.h"
> -#include "scom.h"
> -#include "reg.h"
> -#include "ring.h"
> -#include "mem.h"
> -#include "thread.h"
>  #include "htm.h"
>  #include "options.h"
> +#include "optcmd.h"
>  
>  #define PR_ERROR(x, args...) \
>  	pdbg_log(PDBG_ERROR, x, ##args)
> @@ -77,44 +72,64 @@ static int **processorsel[MAX_PROCESSORS];
>  static int *chipsel[MAX_PROCESSORS][MAX_CHIPS];
>  static int threadsel[MAX_PROCESSORS][MAX_CHIPS][MAX_THREADS];
>  
> -static int handle_probe(int optind, int argc, char *argv[]);
> -static int handle_release(int optind, int argc, char *argv[]);
> +static int probe(void);
> +static int release(void);
> +
> +/* TODO: We are repeating ourselves here. A little bit more macro magic could
> + * easily fix this but I was hesitant to introduce too much magic all at
> + * once. */
> +extern struct optcmd_cmd
> +	optcmd_getscom, optcmd_putscom,	optcmd_getcfam, optcmd_putcfam,
> +	optcmd_getgpr, optcmd_putgpr, optcmd_getspr, optcmd_putspr,
> +	optcmd_getnia, optcmd_putnia, optcmd_getmsr, optcmd_putmsr,
> +	optcmd_getring, optcmd_start, optcmd_stop, optcmd_step,
> +	optcmd_threadstatus, optcmd_sreset, optcmd_regs, optcmd_probe,
> +	optcmd_getmem, optcmd_putmem;
> +
> +static struct optcmd_cmd *cmds[] = {
> +	&optcmd_getscom, &optcmd_putscom, &optcmd_getcfam, &optcmd_putcfam,
> +	&optcmd_getgpr, &optcmd_putgpr, &optcmd_getspr, &optcmd_putspr,
> +	&optcmd_getnia, &optcmd_putnia, &optcmd_getmsr, &optcmd_putmsr,
> +	&optcmd_getring, &optcmd_start, &optcmd_stop, &optcmd_step,
> +	&optcmd_threadstatus, &optcmd_sreset, &optcmd_regs, &optcmd_probe,
> +	&optcmd_getmem, &optcmd_putmem,
> +};

I think you're missing optcmd_release from these declarations?


>  
> +/* Purely for printing usage text. We could integrate printing argument and flag
> + * help into optcmd if desired. */
>  struct action {
>  	const char *name;
>  	const char *args;
>  	const char *desc;
> -	int (*fn)(int, int, char **);
>  };
>  
>  static struct action actions[] = {
> -	{ "getgpr",  "<gpr>", "Read General Purpose Register (GPR)", &handle_gpr },
> -	{ "putgpr",  "<gpr> <value>", "Write General Purpose Register (GPR)", &handle_gpr },
> -	{ "getnia",  "", "Get Next Instruction Address (NIA)", &handle_nia },
> -	{ "putnia",  "<value>", "Write Next Instrution Address (NIA)", &handle_nia },
> -	{ "getspr",  "<spr>", "Get Special Purpose Register (SPR)", &handle_spr },
> -	{ "putspr",  "<spr> <value>", "Write Special Purpose Register (SPR)", &handle_spr },
> -	{ "getmsr",  "", "Get Machine State Register (MSR)", &handle_msr },
> -	{ "putmsr",  "<value>", "Write Machine State Register (MSR)", &handle_msr },
> -	{ "getring", "<addr> <len>", "Read a ring. Length must be correct", &handle_getring },
> -	{ "start",   "", "Start thread", &thread_start },
> -	{ "step",    "<count>", "Set a thread <count> instructions", &thread_step },
> -	{ "stop",    "", "Stop thread", &thread_stop },
> -	{ "htm", "core|nest start|stop|status|reset|dump|trace|analyse", "Hardware Trace Macro", &run_htm },
> -	{ "release", "", "Should be called after pdbg work is finished, to release special wakeups and other resources.", &handle_release},
> -	{ "probe", "", "", &handle_probe },
> -	{ "getcfam", "<address>", "Read system cfam", &handle_cfams },
> -	{ "putcfam", "<address> <value> [<mask>]", "Write system cfam", &handle_cfams },
> -	{ "getscom", "<address>", "Read system scom", &handle_scoms },
> -	{ "putscom", "<address> <value> [<mask>]", "Write system scom", &handle_scoms },
> -	{ "getmem",  "<address> <count>", "Read system memory", &handle_mem },
> -	{ "putmem",  "<address>", "Write to system memory", &handle_mem },
> -	{ "threadstatus", "", "Print the status of a thread", &thread_status_print },
> -	{ "sreset",  "", "Reset", &thread_sreset },
> -	{ "regs",  "", "State", &thread_state },
> +	{ "getgpr",  "<gpr>", "Read General Purpose Register (GPR)" },
> +	{ "putgpr",  "<gpr> <value>", "Write General Purpose Register (GPR)" },
> +	{ "getnia",  "", "Get Next Instruction Address (NIA)" },
> +	{ "putnia",  "<value>", "Write Next Instrution Address (NIA)" },
> +	{ "getspr",  "<spr>", "Get Special Purpose Register (SPR)" },
> +	{ "putspr",  "<spr> <value>", "Write Special Purpose Register (SPR)" },
> +	{ "getmsr",  "", "Get Machine State Register (MSR)" },
> +	{ "putmsr",  "<value>", "Write Machine State Register (MSR)" },
> +	{ "getring", "<addr> <len>", "Read a ring. Length must be correct" },
> +	{ "start",   "", "Start thread" },
> +	{ "step",    "<count>", "Set a thread <count> instructions" },
> +	{ "stop",    "", "Stop thread" },
> +	{ "htm", "core|nest start|stop|status|reset|dump|trace|analyse", "Hardware Trace Macro" },
> +	{ "release", "", "Should be called after pdbg work is finished" },
> +	{ "probe", "", "" },
> +	{ "getcfam", "<address>", "Read system cfam" },
> +	{ "putcfam", "<address> <value> [<mask>]", "Write system cfam" },
> +	{ "getscom", "<address>", "Read system scom" },
> +	{ "putscom", "<address> <value> [<mask>]", "Write system scom" },
> +	{ "getmem",  "<address> <count>", "Read system memory" },
> +	{ "putmem",  "<address>", "Write to system memory" },
> +	{ "threadstatus", "", "Print the status of a thread" },
> +	{ "sreset",  "", "Reset" },
> +	{ "regs",  "", "State" },
>  };
>  
> -
>  static void print_usage(char *pname)
>  {
>  	int i;
> @@ -600,7 +615,7 @@ static void release_target(struct pdbg_target *target)
>  	pdbg_target_release(target);
>  }
>  
> -static void do_release(void)
> +static int release(void)
>  {
>  	struct pdbg_target_class *target_class;
>  
> @@ -610,7 +625,10 @@ static void do_release(void)
>  		pdbg_for_each_class_target(target_class->name, target)
>  			release_target(target);
>  	}
> +
> +	return 0;
>  }
> +OPTCMD_DEFINE_CMD(release, release);
>  
>  void print_target(struct pdbg_target *target, int level)
>  {
> @@ -652,7 +670,7 @@ void print_target(struct pdbg_target *target, int level)
>  	}
>  }
>  
> -static int handle_probe(int optind, int argc, char *argv[])
> +static int probe(void)
>  {
>  	struct pdbg_target *target;
>  
> @@ -664,25 +682,21 @@ static int handle_probe(int optind, int argc, char *argv[])
>  
>  	return 1;
>  }
> +OPTCMD_DEFINE_CMD(probe, probe);
>  
>  /*
>   * Release handler.
>   */
>  static void atexit_release(void)
>  {
> -	do_release();
> -}
> -
> -static int handle_release(int optind, int argc, char *argv[])
> -{
> -	do_release();
> -
> -	return 1;
> +	release();
>  }
>  
>  int main(int argc, char *argv[])
>  {
>  	int i, rc = 0;
> +	void **args, **flags;
> +	optcmd_cmd_t *cmd;
>  
>  	backend = default_backend();
>  	device_node = default_target(backend);
> @@ -714,13 +728,28 @@ int main(int argc, char *argv[])
>  
>  	atexit(atexit_release);
>  
> -	for (i = 0; i < ARRAY_SIZE(actions); i++) {
> -		if (strcmp(argv[optind], actions[i].name) == 0) {
> -			rc = actions[i].fn(optind, argc, argv);
> -			goto found_action;
> +	for (i = 0; i < ARRAY_SIZE(cmds); i++) {
> +		if (!strcmp(argv[optind], cmds[i]->cmd)) {
> +			/* Found our command */
> +			cmd = optcmd_parse(cmds[i], (const char **) &argv[optind + 1],
> +					   argc - (optind + 1), &args, &flags);
> +			if (cmd) {
> +				rc = cmd(args, flags);
> +				goto found_action;
> +			} else {
> +				/* Error parsing arguments so exit return directly */
> +				return 1;
> +			}
>  		}
>  	}
>  
> +	/* Process subcommands. Currently only 'htm'.
> +	 * TODO: Move htm command parsing to optcmd once htm clean-up is complete */
> +	if (!strcmp(argv[optind], "htm")) {
> +		run_htm(optind, argc, argv);
> +		goto found_action;
> +	}
> +
>  	PR_ERROR("Unsupported command: %s\n", argv[optind]);
>  	return 1;
>  
> diff --git a/src/mem.c b/src/mem.c
> index e0327d1..29fd21e 100644
> --- a/src/mem.c
> +++ b/src/mem.c
> @@ -20,21 +20,34 @@
>  #include <string.h>
>  #include <unistd.h>
>  #include <assert.h>
> +#include <stdbool.h>
>  
>  #include <libpdbg.h>
>  
>  #include "main.h"
>  #include "progress.h"
> +#include "optcmd.h"
> +#include "parsers.h"
>  
>  #define PR_ERROR(x, args...) \
>  	pdbg_log(PDBG_ERROR, x, ##args)
>  
>  #define PUTMEM_BUF_SIZE 1024
> -static int getmem(uint64_t addr, uint64_t size, bool ci)
> +
> +struct mem_flags {
> +	bool ci;
> +};
> +
> +#define MEM_CI_FLAG ("--ci", ci, parse_flag_noarg, false)
> +
> +static int getmem(uint64_t addr, uint64_t size, struct mem_flags flags)
>  {
>  	struct pdbg_target *target;
>  	uint8_t *buf;
>  	int rc = 0;
> +
> +	printf("getmem ci %d\n", flags.ci);
> +
>  	buf = malloc(size);
>  	assert(buf);
>  	pdbg_for_each_class_target("adu", target) {
> @@ -43,7 +56,7 @@ static int getmem(uint64_t addr, uint64_t size, bool ci)
>  
>  		pdbg_set_progress_tick(progress_tick);
>  		progress_init();
> -		if (!__adu_getmem(target, addr, buf, size, ci)) {
> +		if (!__adu_getmem(target, addr, buf, size, flags.ci)) {
>  			if (write(STDOUT_FILENO, buf, size) < 0)
>  				PR_ERROR("Unable to write stdout.\n");
>  			else
> @@ -58,7 +71,10 @@ static int getmem(uint64_t addr, uint64_t size, bool ci)
>  	return rc;
>  
>  }
> -static int putmem(uint64_t addr, bool ci)
> +OPTCMD_DEFINE_CMD_WITH_FLAGS(getmem, getmem, (ADDRESS, DATA),
> +			     mem_flags, (MEM_CI_FLAG));
> +
> +static int putmem(uint64_t addr, struct mem_flags flags)
>  {
>  	uint8_t *buf;
>  	int read_size, rc = 0;
> @@ -76,7 +92,7 @@ static int putmem(uint64_t addr, bool ci)
>  	progress_init();
>  	do {
>  		read_size = read(STDIN_FILENO, buf, PUTMEM_BUF_SIZE);
> -		if (__adu_putmem(adu_target, addr, buf, read_size, ci)) {
> +		if (__adu_putmem(adu_target, addr, buf, read_size, flags.ci)) {
>  			rc = 0;
>  			printf("Unable to write memory.\n");
>  			break;
> @@ -89,101 +105,5 @@ static int putmem(uint64_t addr, bool ci)
>  	free(buf);
>  	return rc;
>  }
> -
> -static bool is_real_address(struct thread_regs *regs, uint64_t addr)
> -{
> -	return true;
> -	if ((addr & 0xf000000000000000ULL) == 0xc000000000000000ULL)
> -		return true;
> -	return false;
> -}
> -
> -static int load8(struct pdbg_target *target, uint64_t addr, uint64_t *value)
> -{
> -	if (adu_getmem(target, addr, (uint8_t *)value, 8)) {
> -		PR_ERROR("Unable to read memory address=%016" PRIx64 ".\n", addr);
> -		return 0;
> -	}
> -
> -	return 1;
> -}
> -
> -int dump_stack(struct thread_regs *regs)
> -{
> -	struct pdbg_target *target;
> -	uint64_t sp = regs->gprs[1];
> -	uint64_t pc;
> -
> -	pdbg_for_each_class_target("adu", target) {
> -		if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED)
> -			continue;
> -		break;
> -	}
> -
> -	printf("STACK:\n");
> -	if (!target)
> -		PR_ERROR("Unable to read memory (no ADU found)\n");
> -
> -	if (sp && is_real_address(regs, sp)) {
> -		if (!load8(target, sp, &sp))
> -			return 1;
> -		while (sp && is_real_address(regs, sp)) {
> -			if (!load8(target, sp + 16, &pc))
> -				return 1;
> -
> -			printf(" 0x%016" PRIx64 " 0x%16" PRIx64 "\n", sp, pc);
> -
> -			if (!load8(target, sp, &sp))
> -				return 1;
> -		}
> -	}
> -
> -	return 0;
> -}
> -
> -int handle_mem(int optind, int argc, char *argv[])
> -{
> -	uint64_t addr;
> -	char *endptr;
> -	bool ci = false;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires an address\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -
> -	if (strcmp(argv[optind +1], "-ci") == 0) {
> -		/* Set cache-inhibited flag */
> -		ci = true;
> -	}
> -
> -	addr = strtoull(argv[optind + 1 + ci], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse address '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1 + ci]);
> -		return -1;
> -	}
> -
> -	if (strcmp(argv[optind], "getmem") == 0) {
> -		uint64_t size;
> -
> -		if (optind + 2 + ci >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		size = strtoull(argv[optind + 2 + ci], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1 + ci]);
> -			return -1;
> -		}
> -
> -		return getmem(addr, size, ci);
> -	}
> -
> -	return putmem(addr, ci);
> -}
> +OPTCMD_DEFINE_CMD_WITH_FLAGS(putmem, putmem, (ADDRESS),
> +			     mem_flags, (MEM_CI_FLAG));
> diff --git a/src/mem.h b/src/mem.h
> deleted file mode 100644
> index 42bdc04..0000000
> --- a/src/mem.h
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -/* Copyright 2017 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - * 	http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -#include <inttypes.h>
> -#include <libpdbg.h>
> -
> -int dump_stack(struct thread_regs *regs);
> -int handle_mem(int optind, int argc, char *argv[]);
> diff --git a/src/reg.c b/src/reg.c
> index 21bec13..aa77a8a 100644
> --- a/src/reg.c
> +++ b/src/reg.c
> @@ -22,6 +22,7 @@
>  #include <libpdbg.h>
>  
>  #include "main.h"
> +#include "optcmd.h"
>  
>  #define REG_MEM -3
>  #define REG_MSR -2
> @@ -91,143 +92,58 @@ static int getprocreg(struct pdbg_target *target, uint32_t index, uint64_t *reg,
>  	return !rc;
>  }
>  
> -int handle_gpr(int optind, int argc, char *argv[])
> +static int getgpr(int gpr)
>  {
> -	char *endptr;
> -	uint64_t gpr;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires a GPR\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	gpr = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse GPR '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> -
> -	if (gpr > 31) {
> -		printf("A GPR must be between zero and 31 inclusive\n");
> -		return -1;
> -	}
> -
> -	if (strcmp(argv[optind], "putgpr") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 2 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		data = strtoull(argv[optind + 2], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> -
> -		return for_each_target("thread", putprocreg, &gpr, &data);
> -	}
> -
> -	return for_each_target("thread", getprocreg, &gpr, NULL);
> +	uint64_t reg = gpr;
> +	return for_each_target("thread", getprocreg, &reg, NULL);
>  }
> +OPTCMD_DEFINE_CMD_WITH_ARGS(getgpr, getgpr, (GPR));
>  
> -int handle_nia(int optind, int argc, char *argv[])
> +static int putgpr(int gpr, uint64_t data)
>  {
> -	uint64_t reg = REG_NIA;
> -	char *endptr;
> -
> -	if (strcmp(argv[optind], "putnia") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 1 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		data = strtoull(argv[optind + 1], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> -
> -		return for_each_target("thread", putprocreg, &reg, &data);
> -	}
> +	uint64_t reg = gpr;
> +	return for_each_target("thread", putprocreg, &reg, &data);
> +}
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putgpr, putgpr, (GPR, DATA));
>  
> +static int getnia(void)
> +{
> +	uint64_t reg = REG_NIA;
>  	return for_each_target("thread", getprocreg, &reg, NULL);
>  }
> +OPTCMD_DEFINE_CMD(getnia, getnia);
>  
> -int handle_spr(int optind, int argc, char *argv[])
> +static int putnia(uint64_t nia)
>  {
> -	char *endptr;
> -	uint64_t spr;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires a GPR\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	spr = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse GPR '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> -
> -	spr += REG_R31;
> -
> -	if (strcmp(argv[optind], "putspr") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 2 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		data = strtoull(argv[optind + 2], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> -
> -		return for_each_target("thread", putprocreg, &spr, &data);
> -	}
> -
> -	return for_each_target("thread", getprocreg, &spr, NULL);
> +	uint64_t reg = REG_NIA;
> +	return for_each_target("thread", getprocreg, &reg, &nia);
>  }
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putnia, putnia, (DATA));
>  
> -int handle_msr(int optind, int argc, char *argv[])
> +static int getspr(int spr)
>  {
> -	uint64_t msr = REG_MSR;
> -	char *endptr;
> -
> -	if (strcmp(argv[optind], "putmsr") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 1 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> +	uint64_t reg = spr + REG_R31;
> +	return for_each_target("thread", getprocreg, &reg, NULL);
> +}
> +OPTCMD_DEFINE_CMD_WITH_ARGS(getspr, getspr, (SPR));
>  
> -		errno = 0;
> -		data = strtoull(argv[optind + 1], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> +static int putspr(int spr, uint64_t data)
> +{
> +	uint64_t reg = spr + REG_R31;
> +	return for_each_target("thread", putprocreg, &reg, &data);
> +}
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putspr, putspr, (SPR, DATA));
>  
> -		return for_each_target("thread", putprocreg, &msr, &data);
> -	}
> +static int getmsr(void)
> +{
> +	uint64_t reg = REG_MSR;
> +	return for_each_target("thread", getprocreg, &reg, NULL);
> +}
> +OPTCMD_DEFINE_CMD(getmsr, getmsr);
>  
> -	return for_each_target("thread", getprocreg, &msr, NULL);
> +static int putmsr(uint64_t data)
> +{
> +	uint64_t reg = REG_MSR;
> +	return for_each_target("thread", putprocreg, &reg, &data);
>  }
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putmsr, putmsr, (DATA));
> diff --git a/src/reg.h b/src/reg.h
> deleted file mode 100644
> index ad41d9d..0000000
> --- a/src/reg.h
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -/* Copyright 2017 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - * 	http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -int handle_gpr(int optind, int argc, char *argv[]);
> -int handle_nia(int optind, int argc, char *argv[]);
> -int handle_spr(int optind, int argc, char *argv[]);
> -int handle_msr(int optind, int argc, char *argv[]);
> diff --git a/src/ring.c b/src/ring.c
> index b0c9376..58df4d1 100644
> --- a/src/ring.c
> +++ b/src/ring.c
> @@ -18,11 +18,12 @@
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> +#include <assert.h>
>  
> -#include <target.h>
> -#include <operations.h>
> +#include <libpdbg.h>
>  
>  #include "main.h"
> +#include "optcmd.h"
>  
>  static int pdbg_getring(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *len)
>  {
> @@ -51,31 +52,8 @@ static int pdbg_getring(struct pdbg_target *target, uint32_t index, uint64_t *ad
>  	return 1;
>  }
>  
> -int handle_getring(int optind, int argc, char *argv[])
> +static int _getring(uint64_t ring_addr, uint64_t ring_len)
>  {
> -	uint64_t ring_addr, ring_len;
> -	char *endptr;
> -
> -	if (optind + 2 >= argc) {
> -		printf("%s: command '%s' requires two arguments (address and length)\n",
> -		       argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	ring_addr = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse ring address '%s'\n",
> -		       argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> -
> -	ring_len = strtoull(argv[optind + 2], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse ring length '%s'\n",
> -		       argv[0], argv[optind], argv[optind + 2]);
> -		return -1;
> -	}
> -
>  	return for_each_target("chiplet", pdbg_getring, &ring_addr, &ring_len);
>  }
> +OPTCMD_DEFINE_CMD_WITH_ARGS(getring, _getring, (ADDRESS, DATA));
> diff --git a/src/ring.h b/src/ring.h
> deleted file mode 100644
> index a72c875..0000000
> --- a/src/ring.h
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -/* Copyright 2018 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - *      http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -int handle_getring(int optind, int argc, char *argv[]);
> diff --git a/src/scom.c b/src/scom.c
> index 4c59e2a..2372e91 100644
> --- a/src/scom.c
> +++ b/src/scom.c
> @@ -22,8 +22,9 @@
>  #include <libpdbg.h>
>  
>  #include "main.h"
> +#include "optcmd.h"
>  
> -static int getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused)
> +static int _getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *unused)
>  {
>  	uint64_t value;
>  
> @@ -35,7 +36,13 @@ static int getscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, u
>  	return 1;
>  }
>  
> -static int putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data)
> + int getscom(uint64_t addr)
> +{
> +	return for_each_target("pib", _getscom, &addr, NULL);
> +}
> +OPTCMD_DEFINE_CMD_WITH_ARGS(getscom, getscom, (ADDRESS));
> +
> +static int _putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, uint64_t *data)
>  {
>  	if (pib_write(target, *addr, *data))
>  		return 0;
> @@ -43,44 +50,9 @@ static int putscom(struct pdbg_target *target, uint32_t index, uint64_t *addr, u
>  	return 1;
>  }
>  
> -
> -int handle_scoms(int optind, int argc, char *argv[])
> + int putscom(uint64_t addr, uint64_t data, uint64_t mask)
>  {
> -	uint64_t addr;
> -	char *endptr;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires an address\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	addr = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse address '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> -
> -	if (strcmp(argv[optind], "putscom") == 0) {
> -		uint64_t data;
> -
> -		if (optind + 2 >= argc) {
> -			printf("%s: command '%s' requires data\n", argv[0], argv[optind]);
> -			return -1;
> -		}
> -
> -		errno = 0;
> -		data = strtoull(argv[optind + 2], &endptr, 0);
> -		if (errno || *endptr != '\0') {
> -			printf("%s: command '%s' couldn't parse data '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -			return -1;
> -		}
> -
> -		return for_each_target("pib", putscom, &addr, &data);
> -	}
> -
> -	return for_each_target("pib", getscom, &addr, NULL);
> +	/* TODO: Restore the <mask> functionality */
> +	return for_each_target("pib", _putscom, &addr, &data);
>  }
> -
> +OPTCMD_DEFINE_CMD_WITH_ARGS(putscom, putscom, (ADDRESS, DATA, DEFAULT_DATA("0xffffffffffffffff")));
> diff --git a/src/scom.h b/src/scom.h
> deleted file mode 100644
> index d4325b5..0000000
> --- a/src/scom.h
> +++ /dev/null
> @@ -1,18 +0,0 @@
> -/* Copyright 2017 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - * 	http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -#include <inttypes.h>
> -
> -int handle_scoms(int optind, int argc, char *argv[]);
> diff --git a/src/thread.c b/src/thread.c
> index e8b54cb..4b95636 100644
> --- a/src/thread.c
> +++ b/src/thread.c
> @@ -21,7 +21,7 @@
>  #include <libpdbg.h>
>  
>  #include "main.h"
> -#include "mem.h"
> +#include "optcmd.h"
>  
>  static int print_thread_status(struct pdbg_target *target, uint32_t index, uint64_t *arg, uint64_t *unused1)
>  {
> @@ -81,6 +81,57 @@ static int print_core_thread_status(struct pdbg_target *core_target, uint32_t in
>  	return rc;
>  }
>  
> +static bool is_real_address(struct thread_regs *regs, uint64_t addr)
> +{
> +	return true;
> +	if ((addr & 0xf000000000000000ULL) == 0xc000000000000000ULL)
> +		return true;
> +	return false;
> +}
> +
> +static int load8(struct pdbg_target *target, uint64_t addr, uint64_t *value)
> +{
> +	if (adu_getmem(target, addr, (uint8_t *)value, 8)) {
> +		pdbg_log(PDBG_ERROR, "Unable to read memory address=%016" PRIx64 ".\n", addr);
> +		return 0;
> +	}
> +
> +	return 1;
> +}
> +
> +static int dump_stack(struct thread_regs *regs)
> +{
> +	struct pdbg_target *target;
> +	uint64_t sp = regs->gprs[1];
> +	uint64_t pc;
> +
> +	pdbg_for_each_class_target("adu", target) {
> +		if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED)
> +			continue;
> +		break;
> +	}
> +
> +	printf("STACK:\n");
> +	if (!target)
> +		pdbg_log(PDBG_ERROR, "Unable to read memory (no ADU found)\n");
> +
> +	if (sp && is_real_address(regs, sp)) {
> +		if (!load8(target, sp, &sp))
> +			return 1;
> +		while (sp && is_real_address(regs, sp)) {
> +			if (!load8(target, sp + 16, &pc))
> +				return 1;
> +
> +			printf(" 0x%016" PRIx64 " 0x%16" PRIx64 "\n", sp, pc);
> +
> +			if (!load8(target, sp, &sp))
> +				return 1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int get_thread_max_index(struct pdbg_target *target, uint32_t index, uint64_t *maxindex, uint64_t *unused)
>  {
>  	if (index > *maxindex)
> @@ -140,48 +191,37 @@ static int state_thread(struct pdbg_target *thread_target, uint32_t index, uint6
>  	return 1;
>  }
>  
> -int thread_start(int optind, int argc, char *argv[])
> +static int thread_start(void)
>  {
>  	return for_each_target("thread", start_thread, NULL, NULL);
>  }
> +OPTCMD_DEFINE_CMD(start, thread_start);
>  
> -int thread_step(int optind, int argc, char *argv[])
> +static int thread_step(uint64_t count)
>  {
> -	uint64_t count;
> -	char *endptr;
> -
> -	if (optind + 1 >= argc) {
> -		printf("%s: command '%s' requires a count\n", argv[0], argv[optind]);
> -		return -1;
> -	}
> -
> -	errno = 0;
> -	count = strtoull(argv[optind + 1], &endptr, 0);
> -	if (errno || *endptr != '\0') {
> -		printf("%s: command '%s' couldn't parse count '%s'\n",
> -				argv[0], argv[optind], argv[optind + 1]);
> -		return -1;
> -	}
> -
>  	return for_each_target("thread", step_thread, &count, NULL);
>  }
> +OPTCMD_DEFINE_CMD_WITH_ARGS(step, thread_step, (DATA));
>  
> -int thread_stop(int optind, int argc, char *argv[])
> +static int thread_stop(void)
>  {
>  	return for_each_target("thread", stop_thread, NULL, NULL);
>  }
> +OPTCMD_DEFINE_CMD(stop, thread_stop);
>  
> -int thread_status_print(int optind, int argc, char *argv[])
> +static int thread_status_print(void)
>  {
>  	return for_each_target("pib", print_proc_thread_status, NULL, NULL);
>  }
> +OPTCMD_DEFINE_CMD(threadstatus, thread_status_print);
>  
> -int thread_sreset(int optind, int argc, char *argv[])
> +static int thread_sreset(void)
>  {
>  	return for_each_target("thread", sreset_thread, NULL, NULL);
>  }
> +OPTCMD_DEFINE_CMD(sreset, thread_sreset);
>  
> -int thread_state(int optind, int argc, char *argv[])
> +static int thread_state(void)
>  {
>  	int err;
>  
> @@ -191,3 +231,4 @@ int thread_state(int optind, int argc, char *argv[])
>  
>  	return err;
>  }
> +OPTCMD_DEFINE_CMD(regs, thread_state);
> diff --git a/src/thread.h b/src/thread.h
> deleted file mode 100644
> index 0c1caa2..0000000
> --- a/src/thread.h
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -/* Copyright 2017 IBM Corp.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at
> - *
> - * 	http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> - * implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -#include <inttypes.h>
> -
> -int thread_start(int optind, int argc, char *argv[]);
> -int thread_step(int optind, int argc, char *argv[]);
> -int thread_stop(int optind, int argc, char *argv[]);
> -int thread_status_print(int optind, int argc, char *argv[]);
> -int thread_sreset(int optind, int argc, char *argv[]);
> -int thread_state(int optind, int argc, char *argv[]);



More information about the Pdbg mailing list