All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] makedumpfile/arm64: Add '--mem-usage' support
@ 2018-03-05 17:12 Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs Bhupesh Sharma
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Bhupesh Sharma @ 2018-03-05 17:12 UTC (permalink / raw)
  To: kexec
  Cc: Masaki Tachibana, bhsharma, bhupesh.linux, Takuya Nakayama,
	Daisuke Nishimura

Changes since v1:
----------------
- Updated patchset to read _stext symbol from '/proc/kallsyms' rather
  than from 'vmlinux' file.

Its good to have the makedumpfile '--mem-usage' support
for arm64 architecture as well, as it allows one to see the page numbers
of current system (1st kernel) in different use.

Using this we can know how many pages are dumpable when different
dump_level is specified.

Normally for x86_64, makedumpfile analyzes the 'System Ram' and
'kernel text' program segment of /proc/kcore excluding
the crashkernel range, then calculates the page number of different
kind per vmcoreinfo.

We use the similar logic for arm64, but in addition we determine
information like VA_BITS from kernel symbol like '_stext'.
This allows us to get the VA_BITS before 'set_kcore_vmcoreinfo()'
is called.

Also I have validated the '--mem-usage' makedumpfile option on several
ppc64/ppc64le and s390x machines, so update the makedumpfile.8
documentation to indicate that '--mem-usage' option is supported
not only on x86_64, but also on ppc64, s390x and arm64.

After this patch, when using the '--mem-usage' option with makedumpfile,
we get the correct information about the different pages. For e.g.
here is an output from my arm64 board:

TYPE		PAGES			EXCLUDABLE	DESCRIPTION
----------------------------------------------------------------------
ZERO		49524           	yes		Pages filled with zero
NON_PRI_CACHE	15143           	yes		Cache pages without private flag
PRI_CACHE	29147           	yes		Cache pages with private flag
USER		3684            	yes		User process pages
FREE		1450569         	yes		Free pages
KERN_DATA	14243           	no		Dumpable kernel data

page size:		65536
Total pages on system:	1562310
Total size on system:	102387548160     Byte

Cc: Masaki Tachibana <mas-tachibana@vf.jp.nec.com>
Cc: Takuya Nakayama <tak-nakayama@tg.jp.nec.com>
Cc: Daisuke Nishimura <dai-nishimura@rc.jp.nec.com>
Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>

Bhupesh Sharma (3):
  Add a new helper file 'tools.c' that provides some useful APIs
  arm64: Add support to read symbols like _stext from '/proc/kallsyms'
  Documentation: Update documentation regarding --mem-usage' option

 Makefile       |   2 +-
 arch/arm64.c   |  78 +++++-
 common.h       |   8 +
 makedumpfile.8 |   2 +-
 makedumpfile.h |  14 ++
 tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 864 insertions(+), 6 deletions(-)
 create mode 100644 tools.c

-- 
2.7.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
  2018-03-05 17:12 [PATCH v2 0/3] makedumpfile/arm64: Add '--mem-usage' support Bhupesh Sharma
@ 2018-03-05 17:12 ` Bhupesh Sharma
  2018-03-06 10:03   ` Masaki Tachibana
  2018-03-05 17:12 ` [PATCH v2 2/3] arm64: Add support to read symbols like _stext from '/proc/kallsyms' Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 3/3] Documentation: Update documentation regarding --mem-usage' option Bhupesh Sharma
  2 siblings, 1 reply; 7+ messages in thread
From: Bhupesh Sharma @ 2018-03-05 17:12 UTC (permalink / raw)
  To: kexec; +Cc: bhsharma, bhupesh.linux

This patch borrows the 'tools.c' helper file from the crash utility
project and adds it to the makedumpfile source code, to allow
some basic useful APIs to be present which can be invoked from
other source code files.

'tools.c' provides some useful APIs like 'htol' (convert
a string to a hexadecimal long value), etc. which can be
invoked by other functions (a functionality that is exposed
by follow-up patches).

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
 Makefile       |   2 +-
 common.h       |   8 +
 makedumpfile.h |  14 ++
 tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 789 insertions(+), 1 deletion(-)
 create mode 100644 tools.c

diff --git a/Makefile b/Makefile
index f4b7c56b6f3d..e870b1362c95 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
 endif
 
 SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
-SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
+SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
 OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
 SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c
 OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
diff --git a/common.h b/common.h
index 6ad3ca7b952c..6e2f657a79c7 100644
--- a/common.h
+++ b/common.h
@@ -19,6 +19,8 @@
 #define TRUE		(1)
 #define FALSE		(0)
 #define ERROR		(-1)
+#define UNUSED   	(-1)
+#define RETURN_ON_ERROR  	(0x2)
 
 #ifndef LONG_MAX
 #define LONG_MAX	((long)(~0UL>>1))
@@ -35,12 +37,18 @@
 #define round(x, y)	(((x) / (y)) * (y))
 #define roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
 
+#define NUM_HEX  (0x1)
+#define NUM_DEC  (0x2)
+#define NUM_EXPR (0x4)
+#define NUM_ANY  (NUM_HEX|NUM_DEC|NUM_EXPR)
+
 /*
  * Incorrect address
  */
 #define NOT_MEMMAP_ADDR	(0x0)
 #define NOT_KV_ADDR	(0x0)
 #define NOT_PADDR	(ULONGLONG_MAX)
+#define BADADDR  	((ulong)(-1))
 
 #endif  /* COMMON_H */
 
diff --git a/makedumpfile.h b/makedumpfile.h
index 01eece231475..0ce75e29fa7f 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -237,6 +237,9 @@ isAnon(unsigned long mapping)
 #define MIN_ELF_HEADER_SIZE \
 	MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
 static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
+#define STREQ(A, B) (string_exists((char *)A) && 	\
+		     string_exists((char *)B) && 	\
+	(strcmp((char *)(A), (char *)(B)) == 0))
 #define STRNEQ(A, B)(string_exists((char *)(A)) &&	\
 		     string_exists((char *)(B)) &&	\
 	(strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
@@ -2319,4 +2322,15 @@ int prepare_splitblock_table(void);
 int initialize_zlib(z_stream *stream, int level);
 int finalize_zlib(z_stream *stream);
 
+int parse_line(char *str, char *argv[]);
+char *shift_string_left(char *s, int cnt);
+char *clean_line(char *line);
+char *strip_linefeeds(char *line);
+char *strip_beginning_whitespace(char *line);
+char *strip_ending_whitespace(char *line);
+ulong htol(char *s, int flags, int *errptr);
+int hexadecimal(char *s, int count);
+int decimal(char *s, int count);
+int file_exists(char *file);
+
 #endif /* MAKEDUMPFILE_H */
diff --git a/tools.c b/tools.c
new file mode 100644
index 000000000000..746ffa104816
--- /dev/null
+++ b/tools.c
@@ -0,0 +1,766 @@
+/* tools.c - Borrowed from crash utility code
+ *           (https://github.com/crash-utility/crash)
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
+ * Copyright (C) 2002-2017 David Anderson
+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "common.h"
+#include "makedumpfile.h"
+#include <ctype.h>
+
+#define FAULT_ON_ERROR		(0x1)
+#define RETURN_ON_ERROR		(0x2)
+#define QUIET			(0x4)
+#define HEX_BIAS		(0x8)
+#define LONG_LONG		(0x10)
+#define RETURN_PARTIAL		(0x20)
+#define NO_DEVMEM_SWITCH	(0x40)
+
+#define MAX_HEXADDR_STRLEN	(16)
+
+#define FIRSTCHAR(s)		(s[0])
+
+/*
+ * Determine whether a file exists, using the caller's stat structure if
+ * one was passed in.
+ */
+int
+file_exists(char *file)
+{
+	struct stat sbuf;
+
+	if (stat(file, &sbuf) == 0)
+		return TRUE;
+
+	return FALSE;
+}
+
+/*
+ * Parse a line into tokens, populate the passed-in argv[] array, and
+ * return the count of arguments found. This function modifies the
+ * passed-string by inserting a NULL character at the end of each token.
+ * Expressions encompassed by parentheses, and strings encompassed by
+ * apostrophes, are collected into single tokens.
+ */
+int
+parse_line(char *str, char *argv[])
+{
+	int i, j, k;
+	int string;
+	int expression;
+
+	for (i = 0; i < MAXARGS; i++)
+		argv[i] = NULL;
+
+	clean_line(str);
+
+	if (str == NULL || strlen(str) == 0)
+		return(0);
+
+	i = j = k = 0;
+	string = expression = FALSE;
+
+	/*
+	 * Special handling for when the first character is a '"'.
+	 */
+	if (str[0] == '"') {
+next:
+		do {
+			i++;
+		} while ((str[i] != NULLCHAR) && (str[i] != '"'));
+
+		switch (str[i])
+		{
+		case NULLCHAR:
+			argv[j] = &str[k];
+			return j+1;
+		case '"':
+			argv[j++] = &str[k+1];
+			str[i++] = NULLCHAR;
+			if (str[i] == '"') {
+				k = i;
+				goto next;
+			}
+			break;
+		}
+	} else
+		argv[j++] = str;
+
+	while (TRUE) {
+		if (j == MAXARGS)
+			ERRMSG("too many arguments in string!\n");
+
+		while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
+			i++;
+		}
+
+		switch (str[i])
+		{
+		case ' ':
+		case '\t':
+			str[i++] = NULLCHAR;
+
+			while (str[i] == ' ' || str[i] == '\t') {
+				i++;
+			}
+
+			if (str[i] == '"') {
+				str[i] = ' ';
+				string = TRUE;
+				i++;
+			}
+
+			if (!string && str[i] == '(') {
+				expression = TRUE;
+			}
+
+			if (str[i] != NULLCHAR && str[i] != '\n') {
+				argv[j++] = &str[i];
+				if (string) {
+					string = FALSE;
+					while (str[i] != '"' && str[i] != NULLCHAR)
+						i++;
+					if (str[i] == '"')
+						str[i] = ' ';
+				}
+				if (expression) {
+					expression = FALSE;
+					while (str[i] != ')' && str[i] != NULLCHAR)
+						i++;
+				}
+				break;
+			}
+			/* else fall through */
+		case '\n':
+			str[i] = NULLCHAR;
+			/* keep falling... */
+		case NULLCHAR:
+			argv[j] = NULLCHAR;
+			return(j);
+		}
+	}
+}
+
+/*
+ * Defuse controversy re: extensions to ctype.h
+ */
+int
+whitespace(int c)
+{
+	return ((c == ' ') ||(c == '\t'));
+}
+
+int
+ascii(int c)
+{
+	return ((c >= 0) && (c <= 0x7f));
+}
+
+/*
+ * Strip line-ending whitespace and linefeeds.
+ */
+char *
+strip_line_end(char *line)
+{
+	strip_linefeeds(line);
+	strip_ending_whitespace(line);
+	return(line);
+}
+
+/*
+ * Strip line-beginning and line-ending whitespace and linefeeds.
+ */
+char *
+clean_line(char *line)
+{
+	strip_beginning_whitespace(line);
+	strip_linefeeds(line);
+	strip_ending_whitespace(line);
+	return(line);
+}
+
+/*
+ * Strip line-ending linefeeds in a string.
+ */
+char *
+strip_linefeeds(char *line)
+{
+	char *p;
+
+	if (line == NULL || strlen(line) == 0)
+		return(line);
+
+	p = &LASTCHAR(line);
+
+	while (*p == '\n') {
+		*p = NULLCHAR;
+		if (--p < line)
+			break;
+	}
+
+	return(line);
+}
+
+/*
+ * Strip a specified line-ending character in a string.
+ */
+char *
+strip_ending_char(char *line, char c)
+{
+	char *p;
+
+	if (line == NULL || strlen(line) == 0)
+		return(line);
+
+	p = &LASTCHAR(line);
+
+	if (*p == c)
+		*p = NULLCHAR;
+
+	return(line);
+}
+
+/*
+ * Strip a specified line-beginning character in a string.
+ */
+char *
+strip_beginning_char(char *line, char c)
+{
+	if (line == NULL || strlen(line) == 0)
+		return(line);
+
+	if (FIRSTCHAR(line) == c)
+		shift_string_left(line, 1);
+
+	return(line);
+}
+
+/*
+ * Strip line-ending whitespace.
+ */
+char *
+strip_ending_whitespace(char *line)
+{
+	char *p;
+
+	if (line == NULL || strlen(line) == 0)
+		return(line);
+
+	p = &LASTCHAR(line);
+
+	while (*p == ' ' || *p == '\t') {
+		*p = NULLCHAR;
+		if (p == line)
+			break;
+		p--;
+	}
+
+	return(line);
+}
+
+/*
+ * Strip line-beginning whitespace.
+ */
+char *
+strip_beginning_whitespace(char *line)
+{
+	char buf[BUFSIZE];
+	char *p;
+
+	if (line == NULL || strlen(line) == 0)
+		return(line);
+
+	strcpy(buf, line);
+	p = &buf[0];
+	while (*p == ' ' || *p == '\t')
+		p++;
+	strcpy(line, p);
+
+	return(line);
+}
+
+/*
+ * End line at first comma found.
+ */
+char *
+strip_comma(char *line)
+{
+	char *p;
+
+	if ((p = strstr(line, ",")))
+		*p = NULLCHAR;
+
+	return(line);
+}
+
+/*
+ * Strip the 0x from the beginning of a hexadecimal value string.
+ */
+char *
+strip_hex(char *line)
+{
+	if (STRNEQ(line, "0x"))
+		shift_string_left(line, 2);
+
+	return(line);
+}
+
+/*
+ * Turn a string into upper-case.
+ */
+char *
+upper_case(const char *s, char *buf)
+{
+	const char *p1;
+	char *p2;
+
+	p1 = s;
+	p2 = buf;
+
+	while (*p1) {
+		*p2 = toupper(*p1);
+		p1++, p2++;
+	}
+
+	*p2 = NULLCHAR;
+
+	return(buf);
+}
+
+/*
+ * Return pointer to first non-space/tab in a string.
+ */
+char *
+first_nonspace(char *s)
+{
+	return(s + strspn(s, " \t"));
+}
+
+/*
+ * Return pointer to first space/tab in a string. If none are found,
+ * return a pointer to the string terminating NULL.
+ */
+char *
+first_space(char *s)
+{
+	return(s + strcspn(s, " \t"));
+}
+
+/*
+ * Replace the first space/tab found in a string with a NULL character.
+ */
+char *
+null_first_space(char *s)
+{
+	char *p1;
+
+	p1 = first_space(s);
+	if (*p1)
+		*p1 = NULLCHAR;
+
+	return s;
+}
+
+/*
+ * Replace any instances of the characters in string c that are found in
+ * string s with the character passed in r.
+ */
+char *
+replace_string(char *s, char *c, char r)
+{
+	int i, j;
+
+	for (i = 0; s[i]; i++) {
+		for (j = 0; c[j]; j++) {
+			if (s[i] == c[j])
+				s[i] = r;
+		}
+	}
+
+	return s;
+}
+
+/*
+ * Find the rightmost instance of a substring in a string.
+ */
+char *
+strstr_rightmost(char *s, char *lookfor)
+{
+	char *next, *last, *p;
+
+	for (p = s, last = NULL; *p; p++) {
+		if (!(next = strstr(p, lookfor)))
+			break;
+		last = p = next;
+	}
+
+	return last;
+}
+
+/*
+ * Shifts the contents of a string to the left by cnt characters,
+ * disposing the leftmost characters.
+ */
+char *
+shift_string_left(char *s, int cnt)
+{
+	int origlen;
+
+	if (!cnt)
+		return(s);
+
+	origlen = strlen(s);
+	memmove(s, s+cnt, (origlen-cnt));
+	*(s+(origlen-cnt)) = NULLCHAR;
+	return(s);
+}
+
+/*
+ * Prints a string verbatim, allowing strings with % signs to be displayed
+ * without printf conversions.
+ */
+void
+print_verbatim(FILE *filep, char *line)
+{
+	int i;
+
+	for (i = 0; i < strlen(line); i++) {
+		fputc(line[i], filep);
+		fflush(filep);
+	}
+}
+
+char *
+fixup_percent(char *s)
+{
+	char *p1;
+
+	if ((p1 = strstr(s, "%")) == NULL)
+		return s;
+
+	s[strlen(s)+1] = NULLCHAR;
+	memmove(p1+1, p1, strlen(p1));
+	*p1 = '%';
+
+	return s;
+}
+
+/*
+ * Append a two-character string to a number to make 1, 2, 3 and 4 into
+ * 1st, 2nd, 3rd, 4th, and so on...
+ */
+char *
+ordinal(ulong val, char *buf)
+{
+	char *p1;
+
+	sprintf(buf, "%ld", val);
+	p1 = &buf[strlen(buf)-1];
+
+	switch (*p1)
+	{
+	case '1':
+		strcat(buf, "st");
+		break;
+	case '2':
+		strcat(buf, "nd");
+		break;
+	case '3':
+		strcat(buf, "rd");
+		break;
+	default:
+		strcat(buf, "th");
+		break;
+	}
+
+	return buf;
+}
+
+/*
+ * Determine whether a string contains only decimal characters.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+decimal(char *s, int count)
+{
+	char *p;
+	int cnt, digits;
+
+	if (!count) {
+		strip_line_end(s);
+		cnt = 0;
+	} else
+		cnt = count;
+
+	for (p = &s[0], digits = 0; *p; p++) {
+		switch(*p)
+		{
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			digits++;
+		case ' ':
+			break;
+		default:
+			return FALSE;
+		}
+
+		if (count && (--cnt == 0))
+			break;
+	}
+
+	return (digits ? TRUE : FALSE);
+}
+
+/*
+ * Determine whether a string contains only ASCII characters.
+ */
+int
+ascii_string(char *s)
+{
+	char *p;
+
+	for (p = &s[0]; *p; p++) {
+		if (!ascii(*p))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/*
+ * Check whether a string contains only printable ASCII characters.
+ */
+int
+printable_string(char *s)
+{
+	char *p;
+
+	for (p = &s[0]; *p; p++) {
+		if (!isprint(*p))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/*
+ * Convert a string to a hexadecimal long value.
+ */
+ulong
+htol(char *s, int flags, int *errptr)
+{
+	ulong i, j;
+	ulong n;
+
+	if (s == NULL) {
+		if (!(flags & QUIET))
+			ERRMSG("received NULL string\n");
+		goto htol_error;
+	}
+
+	if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
+		s += 2;
+
+	if (strlen(s) > MAX_HEXADDR_STRLEN) {
+		if (!(flags & QUIET))
+			ERRMSG("input string too large: \"%s\" (%d vs %d)\n", 
+					s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
+		goto htol_error;
+	}
+
+	for (n = i = 0; s[i] != 0; i++) {
+		switch (s[i])
+		{
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			j = (s[i] - 'a') + 10;
+			break;
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+			j = (s[i] - 'A') + 10;
+			break;
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case '0':
+			j = s[i] - '0';
+			break;
+		case 'x':
+		case 'X':
+		case 'h':
+			continue;
+		default:
+			if (!(flags & QUIET))
+				ERRMSG("invalid input: \"%s\"\n", s);
+			goto htol_error;
+		}
+		n = (16 * n) + j;
+	}
+
+	return(n);
+
+htol_error:
+	return BADADDR;
+}
+
+/*
+ * Determine whether a string contains only hexadecimal characters.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+hexadecimal(char *s, int count)
+{
+	char *p;
+	int cnt, digits;
+
+	if (!count) {
+		strip_line_end(s);
+		cnt = 0;
+	} else
+		cnt = count;
+
+	for (p = &s[0], digits = 0; *p; p++) {
+		switch(*p)
+		{
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case '0':
+			digits++;
+		case 'x':
+		case 'X':
+			break;
+
+		case ' ':
+			if (*(p+1) == NULLCHAR)
+				break;
+			else
+				return FALSE;
+		default:
+			return FALSE;
+		}
+
+		if (count && (--cnt == 0))
+			break;
+	}
+
+	return (digits ? TRUE : FALSE);
+}
+
+/*
+ * Determine whether a string contains only hexadecimal characters.
+ * and cannot be construed as a decimal number.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+hexadecimal_only(char *s, int count)
+{
+	char *p;
+	int cnt, only;
+
+	if (!count) {
+		strip_line_end(s);
+		cnt = 0;
+	} else
+		cnt = count;
+
+	only = 0;
+
+	for (p = &s[0]; *p; p++) {
+		switch(*p)
+		{
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+		case 'x':
+		case 'X':
+			only++;
+			break;
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case '0':
+			break;
+
+		case ' ':
+			if (*(p+1) == NULLCHAR)
+				break;
+			else
+				return FALSE;
+		default:
+			return FALSE;
+		}
+
+		if (count && (--cnt == 0))
+			break;
+	}
+
+	return only;
+}
-- 
2.7.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] arm64: Add support to read symbols like _stext from '/proc/kallsyms'
  2018-03-05 17:12 [PATCH v2 0/3] makedumpfile/arm64: Add '--mem-usage' support Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs Bhupesh Sharma
@ 2018-03-05 17:12 ` Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 3/3] Documentation: Update documentation regarding --mem-usage' option Bhupesh Sharma
  2 siblings, 0 replies; 7+ messages in thread
From: Bhupesh Sharma @ 2018-03-05 17:12 UTC (permalink / raw)
  To: kexec; +Cc: bhsharma, bhupesh.linux

On ARM64 platforms the VA_BITS supported by a linux kernel being run
can be selected by setting 'ARM64_VA_BITS_*' (see 'arch/arm64/Kconfig'
for details).

Now, to determine the 'info->page_offset' in arm64 makedumpfile
context ('arch/arm64.c') we need to determine the VA_BITS which was
selected by the underlying linux kernel.

There can be several ways to determine the VA_BITS, out of which
reading the '_stext' symbol and calculating the 'va_bits' using the
same is the simplest yet portable method.

For reading the kernel symbols like '_stext', we can read the
'/proc/kallsyms' file which contains these symbols and
works even in case of KASLR enabled arm64 kernels, as in those cases,
the '_stext' symbol will end up being randomized and hence
cannot be correctly read from the 'vmlinux' file.

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
 arch/arm64.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index 25d7a1f4db98..8a71abdabd59 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -48,6 +48,12 @@ static unsigned long kimage_voffset;
 #define SZ_64K			(64 * 1024)
 #define SZ_128M			(128 * 1024 * 1024)
 
+#define PAGE_OFFSET_36 ((0xffffffffffffffffUL) << 36)
+#define PAGE_OFFSET_39 ((0xffffffffffffffffUL) << 39)
+#define PAGE_OFFSET_42 ((0xffffffffffffffffUL) << 42)
+#define PAGE_OFFSET_47 ((0xffffffffffffffffUL) << 47)
+#define PAGE_OFFSET_48 ((0xffffffffffffffffUL) << 48)
+
 #define pgd_val(x)		((x).pgd)
 #define pud_val(x)		(pgd_val((x).pgd))
 #define pmd_val(x)		(pud_val((x).pud))
@@ -140,8 +146,6 @@ pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
 
 static int calculate_plat_config(void)
 {
-	va_bits = NUMBER(VA_BITS);
-
 	/* derive pgtable_level as per arch/arm64/Kconfig */
 	if ((PAGESIZE() == SZ_16K && va_bits == 36) ||
 			(PAGESIZE() == SZ_64K && va_bits == 42)) {
@@ -177,6 +181,45 @@ get_phys_base_arm64(void)
 	return TRUE;
 }
 
+ulong
+get_stext_symbol(void)
+{
+	int found;
+	FILE *fp;
+	char buf[BUFSIZE];
+	char *kallsyms[MAXARGS];
+	ulong kallsym;
+
+	if (!file_exists("/proc/kallsyms")) {
+		ERRMSG("(%s) does not exist, will not be able to read symbols. %s\n",
+		       "/proc/kallsyms", strerror(errno));
+		return FALSE;
+	}
+
+	if ((fp = fopen("/proc/kallsyms", "r")) == NULL) {
+		ERRMSG("Cannot open (%s) to read symbols. %s\n",
+		       "/proc/kallsyms", strerror(errno));
+		return FALSE;
+	}
+
+	found = FALSE;
+	kallsym = 0;
+
+	while (!found && fgets(buf, BUFSIZE, fp) &&
+	      (parse_line(buf, kallsyms) == 3)) {
+		if (hexadecimal(kallsyms[0], 0) &&
+		    STREQ(kallsyms[2], "_stext")) {
+			kallsym = htol(kallsyms[0], RETURN_ON_ERROR,
+					NULL);
+			found = TRUE;
+			break;
+		}
+	}
+	fclose(fp);
+
+	return(found ? kallsym : FALSE);
+}
+
 int
 get_machdep_info_arm64(void)
 {
@@ -188,12 +231,10 @@ get_machdep_info_arm64(void)
 	kimage_voffset = NUMBER(kimage_voffset);
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
-	info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
 
 	DEBUG_MSG("kimage_voffset   : %lx\n", kimage_voffset);
 	DEBUG_MSG("max_physmem_bits : %lx\n", info->max_physmem_bits);
 	DEBUG_MSG("section_size_bits: %lx\n", info->section_size_bits);
-	DEBUG_MSG("page_offset      : %lx\n", info->page_offset);
 
 	return TRUE;
 }
@@ -219,6 +260,35 @@ get_xen_info_arm64(void)
 int
 get_versiondep_info_arm64(void)
 {
+	ulong _stext;
+
+	_stext = get_stext_symbol();
+	if (!_stext) {
+		ERRMSG("Can't get the symbol of _stext.\n");
+		return FALSE;
+	}
+
+	/* Derive va_bits as per arch/arm64/Kconfig */
+	if ((_stext & PAGE_OFFSET_36) == PAGE_OFFSET_36) {
+		va_bits = 36;
+	} else if ((_stext & PAGE_OFFSET_39) == PAGE_OFFSET_39) {
+		va_bits = 39;
+	} else if ((_stext & PAGE_OFFSET_42) == PAGE_OFFSET_42) {
+		va_bits = 42;
+	} else if ((_stext & PAGE_OFFSET_47) == PAGE_OFFSET_47) {
+		va_bits = 47;
+	} else if ((_stext & PAGE_OFFSET_48) == PAGE_OFFSET_48) {
+		va_bits = 48;
+	} else {
+		ERRMSG("Cannot find a proper _stext for calculating VA_BITS\n");
+		return FALSE;
+	}
+
+	info->page_offset = (0xffffffffffffffffUL) << (va_bits - 1);
+
+	DEBUG_MSG("page_offset=%lx, va_bits=%d\n", info->page_offset,
+			va_bits);
+
 	return TRUE;
 }
 
-- 
2.7.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] Documentation: Update documentation regarding --mem-usage' option
  2018-03-05 17:12 [PATCH v2 0/3] makedumpfile/arm64: Add '--mem-usage' support Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs Bhupesh Sharma
  2018-03-05 17:12 ` [PATCH v2 2/3] arm64: Add support to read symbols like _stext from '/proc/kallsyms' Bhupesh Sharma
@ 2018-03-05 17:12 ` Bhupesh Sharma
  2 siblings, 0 replies; 7+ messages in thread
From: Bhupesh Sharma @ 2018-03-05 17:12 UTC (permalink / raw)
  To: kexec; +Cc: bhsharma, bhupesh.linux

Earlier patch in this patchset, enables the '--mem-usage' makedumpfile
option on arm64 platforms.

In addition, I have validated the '--mem-usage' makedumpfile option
on several ppc64/ppc64le and s390x machines, so update the
'makedumpfile.8' documentation to indicate that '--mem-usage' option is
supported not only on x86_64, but also on ppc64, s390x and arm64
platforms.

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
 makedumpfile.8 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/makedumpfile.8 b/makedumpfile.8
index 15db7947d62f..3ccfc65798be 100644
--- a/makedumpfile.8
+++ b/makedumpfile.8
@@ -593,7 +593,7 @@ last cleared on the crashed kernel, through "dmesg --clear" for example.
 
 .TP
 \fB\-\-mem-usage\fR
-This option is only for x86_64.
+This option is currently supported on x86_64, arm64, ppc64 and s390x.
 This option is used to show the page numbers of current system in different
 use. It should be executed in 1st kernel. By the help of this, user can know
 how many pages is dumpable when different dump_level is specified. It analyzes
-- 
2.7.4


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
  2018-03-05 17:12 ` [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs Bhupesh Sharma
@ 2018-03-06 10:03   ` Masaki Tachibana
  2018-03-06 10:17     ` Bhupesh Sharma
  0 siblings, 1 reply; 7+ messages in thread
From: Masaki Tachibana @ 2018-03-06 10:03 UTC (permalink / raw)
  To: Bhupesh Sharma; +Cc: Masahiko Hayashi, kexec

Hi bhupesh,

Thank you for your V2 patchset.

When you have introduced tools.c from crash utility,
you have deleted a part of htol()'s error handling 
that is unnecessary for makedumpfile as follows;

htol_error:			
-	switch (flags & (FAULT_ON_ERROR|RETURN_ON_ERROR))		
-	{		
-	case FAULT_ON_ERROR:		
-		RESTART();	
-			
-	case RETURN_ON_ERROR:		
-		if (errptr)	
-			*errptr = TRUE;
-		break;	
-	}		
-			
	return BADADDR;		
}			

As a result of this, htol() does not refer to 3rd parameter 'errptr'
and RETURN_ON_ERROR.
I understand that some codes are not used on makedumpfile's tools.c.
They may be used in the future.
However I think 'errptr' should be deleted, so I have tried modifying
your patches as follows;

$ diff "PATCH v2 13 Add a new helper file 'tools
.c' that provides some useful APIs.patch.old" "PATCH v2 13 Add a new helper file
 'tools.c' that provides some useful APIs.patch"
100c100
< +ulong htol(char *s, int flags, int *errptr);
---
> +ulong htol(char *s, int flags);
681c681
< +htol(char *s, int flags, int *errptr)
---
> +htol(char *s, int flags)

$ diff "PATCH v2 23 arm64 Add support to read sy
mbols like _stext from 'prockallsyms'.patch.old" "PATCH v2 23 arm64 Add support
to read symbols like _stext from 'prockallsyms'.patch"
62c62
< @@ -177,6 +181,45 @@ get_phys_base_arm64(void)
---
> @@ -177,6 +181,44 @@ get_phys_base_arm64(void)
94,95c94
< +                     kallsym = htol(kallsyms[0], RETURN_ON_ERROR,
< +                                     NULL);
---
> +                     kallsym = htol(kallsyms[0], 0);

How about this ?
If you agree, I'll merge the modified patchset into V1.6.4.

Thanks
Tachibana

> -----Original Message-----
> From: kexec [mailto:kexec-bounces@lists.infradead.org] On Behalf Of Bhupesh Sharma
> Sent: Tuesday, March 06, 2018 2:13 AM
> To: kexec@lists.infradead.org
> Cc: bhsharma@redhat.com; bhupesh.linux@gmail.com
> Subject: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
> 
> This patch borrows the 'tools.c' helper file from the crash utility
> project and adds it to the makedumpfile source code, to allow
> some basic useful APIs to be present which can be invoked from
> other source code files.
> 
> 'tools.c' provides some useful APIs like 'htol' (convert
> a string to a hexadecimal long value), etc. which can be
> invoked by other functions (a functionality that is exposed
> by follow-up patches).
> 
> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> ---
>  Makefile       |   2 +-
>  common.h       |   8 +
>  makedumpfile.h |  14 ++
>  tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 789 insertions(+), 1 deletion(-)
>  create mode 100644 tools.c
> 
> diff --git a/Makefile b/Makefile
> index f4b7c56b6f3d..e870b1362c95 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
>  endif
> 
>  SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
> -SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
> +SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
>  OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
>  SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c
> arch/sparc64.c
>  OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
> diff --git a/common.h b/common.h
> index 6ad3ca7b952c..6e2f657a79c7 100644
> --- a/common.h
> +++ b/common.h
> @@ -19,6 +19,8 @@
>  #define TRUE		(1)
>  #define FALSE		(0)
>  #define ERROR		(-1)
> +#define UNUSED   	(-1)
> +#define RETURN_ON_ERROR  	(0x2)
> 
>  #ifndef LONG_MAX
>  #define LONG_MAX	((long)(~0UL>>1))
> @@ -35,12 +37,18 @@
>  #define round(x, y)	(((x) / (y)) * (y))
>  #define roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
> 
> +#define NUM_HEX  (0x1)
> +#define NUM_DEC  (0x2)
> +#define NUM_EXPR (0x4)
> +#define NUM_ANY  (NUM_HEX|NUM_DEC|NUM_EXPR)
> +
>  /*
>   * Incorrect address
>   */
>  #define NOT_MEMMAP_ADDR	(0x0)
>  #define NOT_KV_ADDR	(0x0)
>  #define NOT_PADDR	(ULONGLONG_MAX)
> +#define BADADDR  	((ulong)(-1))
> 
>  #endif  /* COMMON_H */
> 
> diff --git a/makedumpfile.h b/makedumpfile.h
> index 01eece231475..0ce75e29fa7f 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -237,6 +237,9 @@ isAnon(unsigned long mapping)
>  #define MIN_ELF_HEADER_SIZE \
>  	MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
>  static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
> +#define STREQ(A, B) (string_exists((char *)A) && 	\
> +		     string_exists((char *)B) && 	\
> +	(strcmp((char *)(A), (char *)(B)) == 0))
>  #define STRNEQ(A, B)(string_exists((char *)(A)) &&	\
>  		     string_exists((char *)(B)) &&	\
>  	(strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
> @@ -2319,4 +2322,15 @@ int prepare_splitblock_table(void);
>  int initialize_zlib(z_stream *stream, int level);
>  int finalize_zlib(z_stream *stream);
> 
> +int parse_line(char *str, char *argv[]);
> +char *shift_string_left(char *s, int cnt);
> +char *clean_line(char *line);
> +char *strip_linefeeds(char *line);
> +char *strip_beginning_whitespace(char *line);
> +char *strip_ending_whitespace(char *line);
> +ulong htol(char *s, int flags, int *errptr);
> +int hexadecimal(char *s, int count);
> +int decimal(char *s, int count);
> +int file_exists(char *file);
> +
>  #endif /* MAKEDUMPFILE_H */
> diff --git a/tools.c b/tools.c
> new file mode 100644
> index 000000000000..746ffa104816
> --- /dev/null
> +++ b/tools.c
> @@ -0,0 +1,766 @@
> +/* tools.c - Borrowed from crash utility code
> + *           (https://github.com/crash-utility/crash)
> + *
> + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
> + * Copyright (C) 2002-2017 David Anderson
> + * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include "common.h"
> +#include "makedumpfile.h"
> +#include <ctype.h>
> +
> +#define FAULT_ON_ERROR		(0x1)
> +#define RETURN_ON_ERROR		(0x2)
> +#define QUIET			(0x4)
> +#define HEX_BIAS		(0x8)
> +#define LONG_LONG		(0x10)
> +#define RETURN_PARTIAL		(0x20)
> +#define NO_DEVMEM_SWITCH	(0x40)
> +
> +#define MAX_HEXADDR_STRLEN	(16)
> +
> +#define FIRSTCHAR(s)		(s[0])
> +
> +/*
> + * Determine whether a file exists, using the caller's stat structure if
> + * one was passed in.
> + */
> +int
> +file_exists(char *file)
> +{
> +	struct stat sbuf;
> +
> +	if (stat(file, &sbuf) == 0)
> +		return TRUE;
> +
> +	return FALSE;
> +}
> +
> +/*
> + * Parse a line into tokens, populate the passed-in argv[] array, and
> + * return the count of arguments found. This function modifies the
> + * passed-string by inserting a NULL character at the end of each token.
> + * Expressions encompassed by parentheses, and strings encompassed by
> + * apostrophes, are collected into single tokens.
> + */
> +int
> +parse_line(char *str, char *argv[])
> +{
> +	int i, j, k;
> +	int string;
> +	int expression;
> +
> +	for (i = 0; i < MAXARGS; i++)
> +		argv[i] = NULL;
> +
> +	clean_line(str);
> +
> +	if (str == NULL || strlen(str) == 0)
> +		return(0);
> +
> +	i = j = k = 0;
> +	string = expression = FALSE;
> +
> +	/*
> +	 * Special handling for when the first character is a '"'.
> +	 */
> +	if (str[0] == '"') {
> +next:
> +		do {
> +			i++;
> +		} while ((str[i] != NULLCHAR) && (str[i] != '"'));
> +
> +		switch (str[i])
> +		{
> +		case NULLCHAR:
> +			argv[j] = &str[k];
> +			return j+1;
> +		case '"':
> +			argv[j++] = &str[k+1];
> +			str[i++] = NULLCHAR;
> +			if (str[i] == '"') {
> +				k = i;
> +				goto next;
> +			}
> +			break;
> +		}
> +	} else
> +		argv[j++] = str;
> +
> +	while (TRUE) {
> +		if (j == MAXARGS)
> +			ERRMSG("too many arguments in string!\n");
> +
> +		while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
> +			i++;
> +		}
> +
> +		switch (str[i])
> +		{
> +		case ' ':
> +		case '\t':
> +			str[i++] = NULLCHAR;
> +
> +			while (str[i] == ' ' || str[i] == '\t') {
> +				i++;
> +			}
> +
> +			if (str[i] == '"') {
> +				str[i] = ' ';
> +				string = TRUE;
> +				i++;
> +			}
> +
> +			if (!string && str[i] == '(') {
> +				expression = TRUE;
> +			}
> +
> +			if (str[i] != NULLCHAR && str[i] != '\n') {
> +				argv[j++] = &str[i];
> +				if (string) {
> +					string = FALSE;
> +					while (str[i] != '"' && str[i] != NULLCHAR)
> +						i++;
> +					if (str[i] == '"')
> +						str[i] = ' ';
> +				}
> +				if (expression) {
> +					expression = FALSE;
> +					while (str[i] != ')' && str[i] != NULLCHAR)
> +						i++;
> +				}
> +				break;
> +			}
> +			/* else fall through */
> +		case '\n':
> +			str[i] = NULLCHAR;
> +			/* keep falling... */
> +		case NULLCHAR:
> +			argv[j] = NULLCHAR;
> +			return(j);
> +		}
> +	}
> +}
> +
> +/*
> + * Defuse controversy re: extensions to ctype.h
> + */
> +int
> +whitespace(int c)
> +{
> +	return ((c == ' ') ||(c == '\t'));
> +}
> +
> +int
> +ascii(int c)
> +{
> +	return ((c >= 0) && (c <= 0x7f));
> +}
> +
> +/*
> + * Strip line-ending whitespace and linefeeds.
> + */
> +char *
> +strip_line_end(char *line)
> +{
> +	strip_linefeeds(line);
> +	strip_ending_whitespace(line);
> +	return(line);
> +}
> +
> +/*
> + * Strip line-beginning and line-ending whitespace and linefeeds.
> + */
> +char *
> +clean_line(char *line)
> +{
> +	strip_beginning_whitespace(line);
> +	strip_linefeeds(line);
> +	strip_ending_whitespace(line);
> +	return(line);
> +}
> +
> +/*
> + * Strip line-ending linefeeds in a string.
> + */
> +char *
> +strip_linefeeds(char *line)
> +{
> +	char *p;
> +
> +	if (line == NULL || strlen(line) == 0)
> +		return(line);
> +
> +	p = &LASTCHAR(line);
> +
> +	while (*p == '\n') {
> +		*p = NULLCHAR;
> +		if (--p < line)
> +			break;
> +	}
> +
> +	return(line);
> +}
> +
> +/*
> + * Strip a specified line-ending character in a string.
> + */
> +char *
> +strip_ending_char(char *line, char c)
> +{
> +	char *p;
> +
> +	if (line == NULL || strlen(line) == 0)
> +		return(line);
> +
> +	p = &LASTCHAR(line);
> +
> +	if (*p == c)
> +		*p = NULLCHAR;
> +
> +	return(line);
> +}
> +
> +/*
> + * Strip a specified line-beginning character in a string.
> + */
> +char *
> +strip_beginning_char(char *line, char c)
> +{
> +	if (line == NULL || strlen(line) == 0)
> +		return(line);
> +
> +	if (FIRSTCHAR(line) == c)
> +		shift_string_left(line, 1);
> +
> +	return(line);
> +}
> +
> +/*
> + * Strip line-ending whitespace.
> + */
> +char *
> +strip_ending_whitespace(char *line)
> +{
> +	char *p;
> +
> +	if (line == NULL || strlen(line) == 0)
> +		return(line);
> +
> +	p = &LASTCHAR(line);
> +
> +	while (*p == ' ' || *p == '\t') {
> +		*p = NULLCHAR;
> +		if (p == line)
> +			break;
> +		p--;
> +	}
> +
> +	return(line);
> +}
> +
> +/*
> + * Strip line-beginning whitespace.
> + */
> +char *
> +strip_beginning_whitespace(char *line)
> +{
> +	char buf[BUFSIZE];
> +	char *p;
> +
> +	if (line == NULL || strlen(line) == 0)
> +		return(line);
> +
> +	strcpy(buf, line);
> +	p = &buf[0];
> +	while (*p == ' ' || *p == '\t')
> +		p++;
> +	strcpy(line, p);
> +
> +	return(line);
> +}
> +
> +/*
> + * End line at first comma found.
> + */
> +char *
> +strip_comma(char *line)
> +{
> +	char *p;
> +
> +	if ((p = strstr(line, ",")))
> +		*p = NULLCHAR;
> +
> +	return(line);
> +}
> +
> +/*
> + * Strip the 0x from the beginning of a hexadecimal value string.
> + */
> +char *
> +strip_hex(char *line)
> +{
> +	if (STRNEQ(line, "0x"))
> +		shift_string_left(line, 2);
> +
> +	return(line);
> +}
> +
> +/*
> + * Turn a string into upper-case.
> + */
> +char *
> +upper_case(const char *s, char *buf)
> +{
> +	const char *p1;
> +	char *p2;
> +
> +	p1 = s;
> +	p2 = buf;
> +
> +	while (*p1) {
> +		*p2 = toupper(*p1);
> +		p1++, p2++;
> +	}
> +
> +	*p2 = NULLCHAR;
> +
> +	return(buf);
> +}
> +
> +/*
> + * Return pointer to first non-space/tab in a string.
> + */
> +char *
> +first_nonspace(char *s)
> +{
> +	return(s + strspn(s, " \t"));
> +}
> +
> +/*
> + * Return pointer to first space/tab in a string. If none are found,
> + * return a pointer to the string terminating NULL.
> + */
> +char *
> +first_space(char *s)
> +{
> +	return(s + strcspn(s, " \t"));
> +}
> +
> +/*
> + * Replace the first space/tab found in a string with a NULL character.
> + */
> +char *
> +null_first_space(char *s)
> +{
> +	char *p1;
> +
> +	p1 = first_space(s);
> +	if (*p1)
> +		*p1 = NULLCHAR;
> +
> +	return s;
> +}
> +
> +/*
> + * Replace any instances of the characters in string c that are found in
> + * string s with the character passed in r.
> + */
> +char *
> +replace_string(char *s, char *c, char r)
> +{
> +	int i, j;
> +
> +	for (i = 0; s[i]; i++) {
> +		for (j = 0; c[j]; j++) {
> +			if (s[i] == c[j])
> +				s[i] = r;
> +		}
> +	}
> +
> +	return s;
> +}
> +
> +/*
> + * Find the rightmost instance of a substring in a string.
> + */
> +char *
> +strstr_rightmost(char *s, char *lookfor)
> +{
> +	char *next, *last, *p;
> +
> +	for (p = s, last = NULL; *p; p++) {
> +		if (!(next = strstr(p, lookfor)))
> +			break;
> +		last = p = next;
> +	}
> +
> +	return last;
> +}
> +
> +/*
> + * Shifts the contents of a string to the left by cnt characters,
> + * disposing the leftmost characters.
> + */
> +char *
> +shift_string_left(char *s, int cnt)
> +{
> +	int origlen;
> +
> +	if (!cnt)
> +		return(s);
> +
> +	origlen = strlen(s);
> +	memmove(s, s+cnt, (origlen-cnt));
> +	*(s+(origlen-cnt)) = NULLCHAR;
> +	return(s);
> +}
> +
> +/*
> + * Prints a string verbatim, allowing strings with % signs to be displayed
> + * without printf conversions.
> + */
> +void
> +print_verbatim(FILE *filep, char *line)
> +{
> +	int i;
> +
> +	for (i = 0; i < strlen(line); i++) {
> +		fputc(line[i], filep);
> +		fflush(filep);
> +	}
> +}
> +
> +char *
> +fixup_percent(char *s)
> +{
> +	char *p1;
> +
> +	if ((p1 = strstr(s, "%")) == NULL)
> +		return s;
> +
> +	s[strlen(s)+1] = NULLCHAR;
> +	memmove(p1+1, p1, strlen(p1));
> +	*p1 = '%';
> +
> +	return s;
> +}
> +
> +/*
> + * Append a two-character string to a number to make 1, 2, 3 and 4 into
> + * 1st, 2nd, 3rd, 4th, and so on...
> + */
> +char *
> +ordinal(ulong val, char *buf)
> +{
> +	char *p1;
> +
> +	sprintf(buf, "%ld", val);
> +	p1 = &buf[strlen(buf)-1];
> +
> +	switch (*p1)
> +	{
> +	case '1':
> +		strcat(buf, "st");
> +		break;
> +	case '2':
> +		strcat(buf, "nd");
> +		break;
> +	case '3':
> +		strcat(buf, "rd");
> +		break;
> +	default:
> +		strcat(buf, "th");
> +		break;
> +	}
> +
> +	return buf;
> +}
> +
> +/*
> + * Determine whether a string contains only decimal characters.
> + * If count is non-zero, limit the search to count characters.
> + */
> +int
> +decimal(char *s, int count)
> +{
> +	char *p;
> +	int cnt, digits;
> +
> +	if (!count) {
> +		strip_line_end(s);
> +		cnt = 0;
> +	} else
> +		cnt = count;
> +
> +	for (p = &s[0], digits = 0; *p; p++) {
> +		switch(*p)
> +		{
> +		case '0':
> +		case '1':
> +		case '2':
> +		case '3':
> +		case '4':
> +		case '5':
> +		case '6':
> +		case '7':
> +		case '8':
> +		case '9':
> +			digits++;
> +		case ' ':
> +			break;
> +		default:
> +			return FALSE;
> +		}
> +
> +		if (count && (--cnt == 0))
> +			break;
> +	}
> +
> +	return (digits ? TRUE : FALSE);
> +}
> +
> +/*
> + * Determine whether a string contains only ASCII characters.
> + */
> +int
> +ascii_string(char *s)
> +{
> +	char *p;
> +
> +	for (p = &s[0]; *p; p++) {
> +		if (!ascii(*p))
> +			return FALSE;
> +	}
> +
> +	return TRUE;
> +}
> +
> +/*
> + * Check whether a string contains only printable ASCII characters.
> + */
> +int
> +printable_string(char *s)
> +{
> +	char *p;
> +
> +	for (p = &s[0]; *p; p++) {
> +		if (!isprint(*p))
> +			return FALSE;
> +	}
> +
> +	return TRUE;
> +}
> +
> +/*
> + * Convert a string to a hexadecimal long value.
> + */
> +ulong
> +htol(char *s, int flags, int *errptr)
> +{
> +	ulong i, j;
> +	ulong n;
> +
> +	if (s == NULL) {
> +		if (!(flags & QUIET))
> +			ERRMSG("received NULL string\n");
> +		goto htol_error;
> +	}
> +
> +	if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
> +		s += 2;
> +
> +	if (strlen(s) > MAX_HEXADDR_STRLEN) {
> +		if (!(flags & QUIET))
> +			ERRMSG("input string too large: \"%s\" (%d vs %d)\n",
> +					s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
> +		goto htol_error;
> +	}
> +
> +	for (n = i = 0; s[i] != 0; i++) {
> +		switch (s[i])
> +		{
> +		case 'a':
> +		case 'b':
> +		case 'c':
> +		case 'd':
> +		case 'e':
> +		case 'f':
> +			j = (s[i] - 'a') + 10;
> +			break;
> +		case 'A':
> +		case 'B':
> +		case 'C':
> +		case 'D':
> +		case 'E':
> +		case 'F':
> +			j = (s[i] - 'A') + 10;
> +			break;
> +		case '1':
> +		case '2':
> +		case '3':
> +		case '4':
> +		case '5':
> +		case '6':
> +		case '7':
> +		case '8':
> +		case '9':
> +		case '0':
> +			j = s[i] - '0';
> +			break;
> +		case 'x':
> +		case 'X':
> +		case 'h':
> +			continue;
> +		default:
> +			if (!(flags & QUIET))
> +				ERRMSG("invalid input: \"%s\"\n", s);
> +			goto htol_error;
> +		}
> +		n = (16 * n) + j;
> +	}
> +
> +	return(n);
> +
> +htol_error:
> +	return BADADDR;
> +}
> +
> +/*
> + * Determine whether a string contains only hexadecimal characters.
> + * If count is non-zero, limit the search to count characters.
> + */
> +int
> +hexadecimal(char *s, int count)
> +{
> +	char *p;
> +	int cnt, digits;
> +
> +	if (!count) {
> +		strip_line_end(s);
> +		cnt = 0;
> +	} else
> +		cnt = count;
> +
> +	for (p = &s[0], digits = 0; *p; p++) {
> +		switch(*p)
> +		{
> +		case 'a':
> +		case 'b':
> +		case 'c':
> +		case 'd':
> +		case 'e':
> +		case 'f':
> +		case 'A':
> +		case 'B':
> +		case 'C':
> +		case 'D':
> +		case 'E':
> +		case 'F':
> +		case '1':
> +		case '2':
> +		case '3':
> +		case '4':
> +		case '5':
> +		case '6':
> +		case '7':
> +		case '8':
> +		case '9':
> +		case '0':
> +			digits++;
> +		case 'x':
> +		case 'X':
> +			break;
> +
> +		case ' ':
> +			if (*(p+1) == NULLCHAR)
> +				break;
> +			else
> +				return FALSE;
> +		default:
> +			return FALSE;
> +		}
> +
> +		if (count && (--cnt == 0))
> +			break;
> +	}
> +
> +	return (digits ? TRUE : FALSE);
> +}
> +
> +/*
> + * Determine whether a string contains only hexadecimal characters.
> + * and cannot be construed as a decimal number.
> + * If count is non-zero, limit the search to count characters.
> + */
> +int
> +hexadecimal_only(char *s, int count)
> +{
> +	char *p;
> +	int cnt, only;
> +
> +	if (!count) {
> +		strip_line_end(s);
> +		cnt = 0;
> +	} else
> +		cnt = count;
> +
> +	only = 0;
> +
> +	for (p = &s[0]; *p; p++) {
> +		switch(*p)
> +		{
> +		case 'a':
> +		case 'b':
> +		case 'c':
> +		case 'd':
> +		case 'e':
> +		case 'f':
> +		case 'A':
> +		case 'B':
> +		case 'C':
> +		case 'D':
> +		case 'E':
> +		case 'F':
> +		case 'x':
> +		case 'X':
> +			only++;
> +			break;
> +		case '1':
> +		case '2':
> +		case '3':
> +		case '4':
> +		case '5':
> +		case '6':
> +		case '7':
> +		case '8':
> +		case '9':
> +		case '0':
> +			break;
> +
> +		case ' ':
> +			if (*(p+1) == NULLCHAR)
> +				break;
> +			else
> +				return FALSE;
> +		default:
> +			return FALSE;
> +		}
> +
> +		if (count && (--cnt == 0))
> +			break;
> +	}
> +
> +	return only;
> +}
> --
> 2.7.4
> 
> 
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
  2018-03-06 10:03   ` Masaki Tachibana
@ 2018-03-06 10:17     ` Bhupesh Sharma
  2018-03-08  4:45       ` Masaki Tachibana
  0 siblings, 1 reply; 7+ messages in thread
From: Bhupesh Sharma @ 2018-03-06 10:17 UTC (permalink / raw)
  To: Masaki Tachibana; +Cc: Masahiko Hayashi, kexec

Hello Masaki,

On Tue, Mar 6, 2018 at 3:33 PM, Masaki Tachibana
<mas-tachibana@vf.jp.nec.com> wrote:
> Hi bhupesh,
>
> Thank you for your V2 patchset.
>
> When you have introduced tools.c from crash utility,
> you have deleted a part of htol()'s error handling
> that is unnecessary for makedumpfile as follows;
>
> htol_error:
> -       switch (flags & (FAULT_ON_ERROR|RETURN_ON_ERROR))
> -       {
> -       case FAULT_ON_ERROR:
> -               RESTART();
> -
> -       case RETURN_ON_ERROR:
> -               if (errptr)
> -                       *errptr = TRUE;
> -               break;
> -       }
> -
>         return BADADDR;
> }
>
> As a result of this, htol() does not refer to 3rd parameter 'errptr'
> and RETURN_ON_ERROR.
> I understand that some codes are not used on makedumpfile's tools.c.
> They may be used in the future.

Indeed the 3rd parameter in 'htol()' is not currently needed by
makedumpfile code, but like you mentioned I earlier thought it might
be required for future compatibility some some future feature
addition.

> However I think 'errptr' should be deleted, so I have tried modifying
> your patches as follows;
> $ diff "PATCH v2 13 Add a new helper file 'tools
> .c' that provides some useful APIs.patch.old" "PATCH v2 13 Add a new helper file
>  'tools.c' that provides some useful APIs.patch"
> 100c100
> < +ulong htol(char *s, int flags, int *errptr);
> ---
>> +ulong htol(char *s, int flags);
> 681c681
> < +htol(char *s, int flags, int *errptr)
> ---
>> +htol(char *s, int flags)
>
> $ diff "PATCH v2 23 arm64 Add support to read sy
> mbols like _stext from 'prockallsyms'.patch.old" "PATCH v2 23 arm64 Add support
> to read symbols like _stext from 'prockallsyms'.patch"
> 62c62
> < @@ -177,6 +181,45 @@ get_phys_base_arm64(void)
> ---
>> @@ -177,6 +181,44 @@ get_phys_base_arm64(void)
> 94,95c94
> < +                     kallsym = htol(kallsyms[0], RETURN_ON_ERROR,
> < +                                     NULL);
> ---
>> +                     kallsym = htol(kallsyms[0], 0);
>
> How about this ?
> If you agree, I'll merge the modified patchset into V1.6.4.

Yes. This seems fine to me. We can add the 3rd parameter to 'htol'
later if its needed in future.

Please feel free to merge the modified patchset into V1.6.4

Regards,
Bhupesh

>
>> -----Original Message-----
>> From: kexec [mailto:kexec-bounces@lists.infradead.org] On Behalf Of Bhupesh Sharma
>> Sent: Tuesday, March 06, 2018 2:13 AM
>> To: kexec@lists.infradead.org
>> Cc: bhsharma@redhat.com; bhupesh.linux@gmail.com
>> Subject: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
>>
>> This patch borrows the 'tools.c' helper file from the crash utility
>> project and adds it to the makedumpfile source code, to allow
>> some basic useful APIs to be present which can be invoked from
>> other source code files.
>>
>> 'tools.c' provides some useful APIs like 'htol' (convert
>> a string to a hexadecimal long value), etc. which can be
>> invoked by other functions (a functionality that is exposed
>> by follow-up patches).
>>
>> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
>> ---
>>  Makefile       |   2 +-
>>  common.h       |   8 +
>>  makedumpfile.h |  14 ++
>>  tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 789 insertions(+), 1 deletion(-)
>>  create mode 100644 tools.c
>>
>> diff --git a/Makefile b/Makefile
>> index f4b7c56b6f3d..e870b1362c95 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
>>  endif
>>
>>  SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
>> -SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
>> +SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
>>  OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
>>  SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c
>> arch/sparc64.c
>>  OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
>> diff --git a/common.h b/common.h
>> index 6ad3ca7b952c..6e2f657a79c7 100644
>> --- a/common.h
>> +++ b/common.h
>> @@ -19,6 +19,8 @@
>>  #define TRUE         (1)
>>  #define FALSE                (0)
>>  #define ERROR                (-1)
>> +#define UNUSED       (-1)
>> +#define RETURN_ON_ERROR      (0x2)
>>
>>  #ifndef LONG_MAX
>>  #define LONG_MAX     ((long)(~0UL>>1))
>> @@ -35,12 +37,18 @@
>>  #define round(x, y)  (((x) / (y)) * (y))
>>  #define roundup(x, y)        ((((x) + ((y) - 1)) / (y)) * (y))
>>
>> +#define NUM_HEX  (0x1)
>> +#define NUM_DEC  (0x2)
>> +#define NUM_EXPR (0x4)
>> +#define NUM_ANY  (NUM_HEX|NUM_DEC|NUM_EXPR)
>> +
>>  /*
>>   * Incorrect address
>>   */
>>  #define NOT_MEMMAP_ADDR      (0x0)
>>  #define NOT_KV_ADDR  (0x0)
>>  #define NOT_PADDR    (ULONGLONG_MAX)
>> +#define BADADDR      ((ulong)(-1))
>>
>>  #endif  /* COMMON_H */
>>
>> diff --git a/makedumpfile.h b/makedumpfile.h
>> index 01eece231475..0ce75e29fa7f 100644
>> --- a/makedumpfile.h
>> +++ b/makedumpfile.h
>> @@ -237,6 +237,9 @@ isAnon(unsigned long mapping)
>>  #define MIN_ELF_HEADER_SIZE \
>>       MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
>>  static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
>> +#define STREQ(A, B) (string_exists((char *)A) &&     \
>> +                  string_exists((char *)B) &&        \
>> +     (strcmp((char *)(A), (char *)(B)) == 0))
>>  #define STRNEQ(A, B)(string_exists((char *)(A)) &&   \
>>                    string_exists((char *)(B)) &&      \
>>       (strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
>> @@ -2319,4 +2322,15 @@ int prepare_splitblock_table(void);
>>  int initialize_zlib(z_stream *stream, int level);
>>  int finalize_zlib(z_stream *stream);
>>
>> +int parse_line(char *str, char *argv[]);
>> +char *shift_string_left(char *s, int cnt);
>> +char *clean_line(char *line);
>> +char *strip_linefeeds(char *line);
>> +char *strip_beginning_whitespace(char *line);
>> +char *strip_ending_whitespace(char *line);
>> +ulong htol(char *s, int flags, int *errptr);
>> +int hexadecimal(char *s, int count);
>> +int decimal(char *s, int count);
>> +int file_exists(char *file);
>> +
>>  #endif /* MAKEDUMPFILE_H */
>> diff --git a/tools.c b/tools.c
>> new file mode 100644
>> index 000000000000..746ffa104816
>> --- /dev/null
>> +++ b/tools.c
>> @@ -0,0 +1,766 @@
>> +/* tools.c - Borrowed from crash utility code
>> + *           (https://github.com/crash-utility/crash)
>> + *
>> + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
>> + * Copyright (C) 2002-2017 David Anderson
>> + * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include "common.h"
>> +#include "makedumpfile.h"
>> +#include <ctype.h>
>> +
>> +#define FAULT_ON_ERROR               (0x1)
>> +#define RETURN_ON_ERROR              (0x2)
>> +#define QUIET                        (0x4)
>> +#define HEX_BIAS             (0x8)
>> +#define LONG_LONG            (0x10)
>> +#define RETURN_PARTIAL               (0x20)
>> +#define NO_DEVMEM_SWITCH     (0x40)
>> +
>> +#define MAX_HEXADDR_STRLEN   (16)
>> +
>> +#define FIRSTCHAR(s)         (s[0])
>> +
>> +/*
>> + * Determine whether a file exists, using the caller's stat structure if
>> + * one was passed in.
>> + */
>> +int
>> +file_exists(char *file)
>> +{
>> +     struct stat sbuf;
>> +
>> +     if (stat(file, &sbuf) == 0)
>> +             return TRUE;
>> +
>> +     return FALSE;
>> +}
>> +
>> +/*
>> + * Parse a line into tokens, populate the passed-in argv[] array, and
>> + * return the count of arguments found. This function modifies the
>> + * passed-string by inserting a NULL character at the end of each token.
>> + * Expressions encompassed by parentheses, and strings encompassed by
>> + * apostrophes, are collected into single tokens.
>> + */
>> +int
>> +parse_line(char *str, char *argv[])
>> +{
>> +     int i, j, k;
>> +     int string;
>> +     int expression;
>> +
>> +     for (i = 0; i < MAXARGS; i++)
>> +             argv[i] = NULL;
>> +
>> +     clean_line(str);
>> +
>> +     if (str == NULL || strlen(str) == 0)
>> +             return(0);
>> +
>> +     i = j = k = 0;
>> +     string = expression = FALSE;
>> +
>> +     /*
>> +      * Special handling for when the first character is a '"'.
>> +      */
>> +     if (str[0] == '"') {
>> +next:
>> +             do {
>> +                     i++;
>> +             } while ((str[i] != NULLCHAR) && (str[i] != '"'));
>> +
>> +             switch (str[i])
>> +             {
>> +             case NULLCHAR:
>> +                     argv[j] = &str[k];
>> +                     return j+1;
>> +             case '"':
>> +                     argv[j++] = &str[k+1];
>> +                     str[i++] = NULLCHAR;
>> +                     if (str[i] == '"') {
>> +                             k = i;
>> +                             goto next;
>> +                     }
>> +                     break;
>> +             }
>> +     } else
>> +             argv[j++] = str;
>> +
>> +     while (TRUE) {
>> +             if (j == MAXARGS)
>> +                     ERRMSG("too many arguments in string!\n");
>> +
>> +             while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
>> +                     i++;
>> +             }
>> +
>> +             switch (str[i])
>> +             {
>> +             case ' ':
>> +             case '\t':
>> +                     str[i++] = NULLCHAR;
>> +
>> +                     while (str[i] == ' ' || str[i] == '\t') {
>> +                             i++;
>> +                     }
>> +
>> +                     if (str[i] == '"') {
>> +                             str[i] = ' ';
>> +                             string = TRUE;
>> +                             i++;
>> +                     }
>> +
>> +                     if (!string && str[i] == '(') {
>> +                             expression = TRUE;
>> +                     }
>> +
>> +                     if (str[i] != NULLCHAR && str[i] != '\n') {
>> +                             argv[j++] = &str[i];
>> +                             if (string) {
>> +                                     string = FALSE;
>> +                                     while (str[i] != '"' && str[i] != NULLCHAR)
>> +                                             i++;
>> +                                     if (str[i] == '"')
>> +                                             str[i] = ' ';
>> +                             }
>> +                             if (expression) {
>> +                                     expression = FALSE;
>> +                                     while (str[i] != ')' && str[i] != NULLCHAR)
>> +                                             i++;
>> +                             }
>> +                             break;
>> +                     }
>> +                     /* else fall through */
>> +             case '\n':
>> +                     str[i] = NULLCHAR;
>> +                     /* keep falling... */
>> +             case NULLCHAR:
>> +                     argv[j] = NULLCHAR;
>> +                     return(j);
>> +             }
>> +     }
>> +}
>> +
>> +/*
>> + * Defuse controversy re: extensions to ctype.h
>> + */
>> +int
>> +whitespace(int c)
>> +{
>> +     return ((c == ' ') ||(c == '\t'));
>> +}
>> +
>> +int
>> +ascii(int c)
>> +{
>> +     return ((c >= 0) && (c <= 0x7f));
>> +}
>> +
>> +/*
>> + * Strip line-ending whitespace and linefeeds.
>> + */
>> +char *
>> +strip_line_end(char *line)
>> +{
>> +     strip_linefeeds(line);
>> +     strip_ending_whitespace(line);
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip line-beginning and line-ending whitespace and linefeeds.
>> + */
>> +char *
>> +clean_line(char *line)
>> +{
>> +     strip_beginning_whitespace(line);
>> +     strip_linefeeds(line);
>> +     strip_ending_whitespace(line);
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip line-ending linefeeds in a string.
>> + */
>> +char *
>> +strip_linefeeds(char *line)
>> +{
>> +     char *p;
>> +
>> +     if (line == NULL || strlen(line) == 0)
>> +             return(line);
>> +
>> +     p = &LASTCHAR(line);
>> +
>> +     while (*p == '\n') {
>> +             *p = NULLCHAR;
>> +             if (--p < line)
>> +                     break;
>> +     }
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip a specified line-ending character in a string.
>> + */
>> +char *
>> +strip_ending_char(char *line, char c)
>> +{
>> +     char *p;
>> +
>> +     if (line == NULL || strlen(line) == 0)
>> +             return(line);
>> +
>> +     p = &LASTCHAR(line);
>> +
>> +     if (*p == c)
>> +             *p = NULLCHAR;
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip a specified line-beginning character in a string.
>> + */
>> +char *
>> +strip_beginning_char(char *line, char c)
>> +{
>> +     if (line == NULL || strlen(line) == 0)
>> +             return(line);
>> +
>> +     if (FIRSTCHAR(line) == c)
>> +             shift_string_left(line, 1);
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip line-ending whitespace.
>> + */
>> +char *
>> +strip_ending_whitespace(char *line)
>> +{
>> +     char *p;
>> +
>> +     if (line == NULL || strlen(line) == 0)
>> +             return(line);
>> +
>> +     p = &LASTCHAR(line);
>> +
>> +     while (*p == ' ' || *p == '\t') {
>> +             *p = NULLCHAR;
>> +             if (p == line)
>> +                     break;
>> +             p--;
>> +     }
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip line-beginning whitespace.
>> + */
>> +char *
>> +strip_beginning_whitespace(char *line)
>> +{
>> +     char buf[BUFSIZE];
>> +     char *p;
>> +
>> +     if (line == NULL || strlen(line) == 0)
>> +             return(line);
>> +
>> +     strcpy(buf, line);
>> +     p = &buf[0];
>> +     while (*p == ' ' || *p == '\t')
>> +             p++;
>> +     strcpy(line, p);
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * End line at first comma found.
>> + */
>> +char *
>> +strip_comma(char *line)
>> +{
>> +     char *p;
>> +
>> +     if ((p = strstr(line, ",")))
>> +             *p = NULLCHAR;
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Strip the 0x from the beginning of a hexadecimal value string.
>> + */
>> +char *
>> +strip_hex(char *line)
>> +{
>> +     if (STRNEQ(line, "0x"))
>> +             shift_string_left(line, 2);
>> +
>> +     return(line);
>> +}
>> +
>> +/*
>> + * Turn a string into upper-case.
>> + */
>> +char *
>> +upper_case(const char *s, char *buf)
>> +{
>> +     const char *p1;
>> +     char *p2;
>> +
>> +     p1 = s;
>> +     p2 = buf;
>> +
>> +     while (*p1) {
>> +             *p2 = toupper(*p1);
>> +             p1++, p2++;
>> +     }
>> +
>> +     *p2 = NULLCHAR;
>> +
>> +     return(buf);
>> +}
>> +
>> +/*
>> + * Return pointer to first non-space/tab in a string.
>> + */
>> +char *
>> +first_nonspace(char *s)
>> +{
>> +     return(s + strspn(s, " \t"));
>> +}
>> +
>> +/*
>> + * Return pointer to first space/tab in a string. If none are found,
>> + * return a pointer to the string terminating NULL.
>> + */
>> +char *
>> +first_space(char *s)
>> +{
>> +     return(s + strcspn(s, " \t"));
>> +}
>> +
>> +/*
>> + * Replace the first space/tab found in a string with a NULL character.
>> + */
>> +char *
>> +null_first_space(char *s)
>> +{
>> +     char *p1;
>> +
>> +     p1 = first_space(s);
>> +     if (*p1)
>> +             *p1 = NULLCHAR;
>> +
>> +     return s;
>> +}
>> +
>> +/*
>> + * Replace any instances of the characters in string c that are found in
>> + * string s with the character passed in r.
>> + */
>> +char *
>> +replace_string(char *s, char *c, char r)
>> +{
>> +     int i, j;
>> +
>> +     for (i = 0; s[i]; i++) {
>> +             for (j = 0; c[j]; j++) {
>> +                     if (s[i] == c[j])
>> +                             s[i] = r;
>> +             }
>> +     }
>> +
>> +     return s;
>> +}
>> +
>> +/*
>> + * Find the rightmost instance of a substring in a string.
>> + */
>> +char *
>> +strstr_rightmost(char *s, char *lookfor)
>> +{
>> +     char *next, *last, *p;
>> +
>> +     for (p = s, last = NULL; *p; p++) {
>> +             if (!(next = strstr(p, lookfor)))
>> +                     break;
>> +             last = p = next;
>> +     }
>> +
>> +     return last;
>> +}
>> +
>> +/*
>> + * Shifts the contents of a string to the left by cnt characters,
>> + * disposing the leftmost characters.
>> + */
>> +char *
>> +shift_string_left(char *s, int cnt)
>> +{
>> +     int origlen;
>> +
>> +     if (!cnt)
>> +             return(s);
>> +
>> +     origlen = strlen(s);
>> +     memmove(s, s+cnt, (origlen-cnt));
>> +     *(s+(origlen-cnt)) = NULLCHAR;
>> +     return(s);
>> +}
>> +
>> +/*
>> + * Prints a string verbatim, allowing strings with % signs to be displayed
>> + * without printf conversions.
>> + */
>> +void
>> +print_verbatim(FILE *filep, char *line)
>> +{
>> +     int i;
>> +
>> +     for (i = 0; i < strlen(line); i++) {
>> +             fputc(line[i], filep);
>> +             fflush(filep);
>> +     }
>> +}
>> +
>> +char *
>> +fixup_percent(char *s)
>> +{
>> +     char *p1;
>> +
>> +     if ((p1 = strstr(s, "%")) == NULL)
>> +             return s;
>> +
>> +     s[strlen(s)+1] = NULLCHAR;
>> +     memmove(p1+1, p1, strlen(p1));
>> +     *p1 = '%';
>> +
>> +     return s;
>> +}
>> +
>> +/*
>> + * Append a two-character string to a number to make 1, 2, 3 and 4 into
>> + * 1st, 2nd, 3rd, 4th, and so on...
>> + */
>> +char *
>> +ordinal(ulong val, char *buf)
>> +{
>> +     char *p1;
>> +
>> +     sprintf(buf, "%ld", val);
>> +     p1 = &buf[strlen(buf)-1];
>> +
>> +     switch (*p1)
>> +     {
>> +     case '1':
>> +             strcat(buf, "st");
>> +             break;
>> +     case '2':
>> +             strcat(buf, "nd");
>> +             break;
>> +     case '3':
>> +             strcat(buf, "rd");
>> +             break;
>> +     default:
>> +             strcat(buf, "th");
>> +             break;
>> +     }
>> +
>> +     return buf;
>> +}
>> +
>> +/*
>> + * Determine whether a string contains only decimal characters.
>> + * If count is non-zero, limit the search to count characters.
>> + */
>> +int
>> +decimal(char *s, int count)
>> +{
>> +     char *p;
>> +     int cnt, digits;
>> +
>> +     if (!count) {
>> +             strip_line_end(s);
>> +             cnt = 0;
>> +     } else
>> +             cnt = count;
>> +
>> +     for (p = &s[0], digits = 0; *p; p++) {
>> +             switch(*p)
>> +             {
>> +             case '0':
>> +             case '1':
>> +             case '2':
>> +             case '3':
>> +             case '4':
>> +             case '5':
>> +             case '6':
>> +             case '7':
>> +             case '8':
>> +             case '9':
>> +                     digits++;
>> +             case ' ':
>> +                     break;
>> +             default:
>> +                     return FALSE;
>> +             }
>> +
>> +             if (count && (--cnt == 0))
>> +                     break;
>> +     }
>> +
>> +     return (digits ? TRUE : FALSE);
>> +}
>> +
>> +/*
>> + * Determine whether a string contains only ASCII characters.
>> + */
>> +int
>> +ascii_string(char *s)
>> +{
>> +     char *p;
>> +
>> +     for (p = &s[0]; *p; p++) {
>> +             if (!ascii(*p))
>> +                     return FALSE;
>> +     }
>> +
>> +     return TRUE;
>> +}
>> +
>> +/*
>> + * Check whether a string contains only printable ASCII characters.
>> + */
>> +int
>> +printable_string(char *s)
>> +{
>> +     char *p;
>> +
>> +     for (p = &s[0]; *p; p++) {
>> +             if (!isprint(*p))
>> +                     return FALSE;
>> +     }
>> +
>> +     return TRUE;
>> +}
>> +
>> +/*
>> + * Convert a string to a hexadecimal long value.
>> + */
>> +ulong
>> +htol(char *s, int flags, int *errptr)
>> +{
>> +     ulong i, j;
>> +     ulong n;
>> +
>> +     if (s == NULL) {
>> +             if (!(flags & QUIET))
>> +                     ERRMSG("received NULL string\n");
>> +             goto htol_error;
>> +     }
>> +
>> +     if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
>> +             s += 2;
>> +
>> +     if (strlen(s) > MAX_HEXADDR_STRLEN) {
>> +             if (!(flags & QUIET))
>> +                     ERRMSG("input string too large: \"%s\" (%d vs %d)\n",
>> +                                     s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
>> +             goto htol_error;
>> +     }
>> +
>> +     for (n = i = 0; s[i] != 0; i++) {
>> +             switch (s[i])
>> +             {
>> +             case 'a':
>> +             case 'b':
>> +             case 'c':
>> +             case 'd':
>> +             case 'e':
>> +             case 'f':
>> +                     j = (s[i] - 'a') + 10;
>> +                     break;
>> +             case 'A':
>> +             case 'B':
>> +             case 'C':
>> +             case 'D':
>> +             case 'E':
>> +             case 'F':
>> +                     j = (s[i] - 'A') + 10;
>> +                     break;
>> +             case '1':
>> +             case '2':
>> +             case '3':
>> +             case '4':
>> +             case '5':
>> +             case '6':
>> +             case '7':
>> +             case '8':
>> +             case '9':
>> +             case '0':
>> +                     j = s[i] - '0';
>> +                     break;
>> +             case 'x':
>> +             case 'X':
>> +             case 'h':
>> +                     continue;
>> +             default:
>> +                     if (!(flags & QUIET))
>> +                             ERRMSG("invalid input: \"%s\"\n", s);
>> +                     goto htol_error;
>> +             }
>> +             n = (16 * n) + j;
>> +     }
>> +
>> +     return(n);
>> +
>> +htol_error:
>> +     return BADADDR;
>> +}
>> +
>> +/*
>> + * Determine whether a string contains only hexadecimal characters.
>> + * If count is non-zero, limit the search to count characters.
>> + */
>> +int
>> +hexadecimal(char *s, int count)
>> +{
>> +     char *p;
>> +     int cnt, digits;
>> +
>> +     if (!count) {
>> +             strip_line_end(s);
>> +             cnt = 0;
>> +     } else
>> +             cnt = count;
>> +
>> +     for (p = &s[0], digits = 0; *p; p++) {
>> +             switch(*p)
>> +             {
>> +             case 'a':
>> +             case 'b':
>> +             case 'c':
>> +             case 'd':
>> +             case 'e':
>> +             case 'f':
>> +             case 'A':
>> +             case 'B':
>> +             case 'C':
>> +             case 'D':
>> +             case 'E':
>> +             case 'F':
>> +             case '1':
>> +             case '2':
>> +             case '3':
>> +             case '4':
>> +             case '5':
>> +             case '6':
>> +             case '7':
>> +             case '8':
>> +             case '9':
>> +             case '0':
>> +                     digits++;
>> +             case 'x':
>> +             case 'X':
>> +                     break;
>> +
>> +             case ' ':
>> +                     if (*(p+1) == NULLCHAR)
>> +                             break;
>> +                     else
>> +                             return FALSE;
>> +             default:
>> +                     return FALSE;
>> +             }
>> +
>> +             if (count && (--cnt == 0))
>> +                     break;
>> +     }
>> +
>> +     return (digits ? TRUE : FALSE);
>> +}
>> +
>> +/*
>> + * Determine whether a string contains only hexadecimal characters.
>> + * and cannot be construed as a decimal number.
>> + * If count is non-zero, limit the search to count characters.
>> + */
>> +int
>> +hexadecimal_only(char *s, int count)
>> +{
>> +     char *p;
>> +     int cnt, only;
>> +
>> +     if (!count) {
>> +             strip_line_end(s);
>> +             cnt = 0;
>> +     } else
>> +             cnt = count;
>> +
>> +     only = 0;
>> +
>> +     for (p = &s[0]; *p; p++) {
>> +             switch(*p)
>> +             {
>> +             case 'a':
>> +             case 'b':
>> +             case 'c':
>> +             case 'd':
>> +             case 'e':
>> +             case 'f':
>> +             case 'A':
>> +             case 'B':
>> +             case 'C':
>> +             case 'D':
>> +             case 'E':
>> +             case 'F':
>> +             case 'x':
>> +             case 'X':
>> +                     only++;
>> +                     break;
>> +             case '1':
>> +             case '2':
>> +             case '3':
>> +             case '4':
>> +             case '5':
>> +             case '6':
>> +             case '7':
>> +             case '8':
>> +             case '9':
>> +             case '0':
>> +                     break;
>> +
>> +             case ' ':
>> +                     if (*(p+1) == NULLCHAR)
>> +                             break;
>> +                     else
>> +                             return FALSE;
>> +             default:
>> +                     return FALSE;
>> +             }
>> +
>> +             if (count && (--cnt == 0))
>> +                     break;
>> +     }
>> +
>> +     return only;
>> +}
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> kexec mailing list
>> kexec@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
>
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
  2018-03-06 10:17     ` Bhupesh Sharma
@ 2018-03-08  4:45       ` Masaki Tachibana
  0 siblings, 0 replies; 7+ messages in thread
From: Masaki Tachibana @ 2018-03-08  4:45 UTC (permalink / raw)
  To: Bhupesh Sharma; +Cc: kexec, Masahiko Hayashi

Hi Bhupesh,


> -----Original Message-----
> From: Bhupesh Sharma [mailto:bhsharma@redhat.com]
> Sent: Tuesday, March 06, 2018 7:17 PM
> To: Tachibana Masaki() <mas-tachibana@vf.jp.nec.com>
> Cc: kexec@lists.infradead.org; Hayashi Masahiko() <mas-hayashi@tg.jp.nec.com>
> Subject: Re: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
> 
> Hello Masaki,
> 
> On Tue, Mar 6, 2018 at 3:33 PM, Masaki Tachibana
> <mas-tachibana@vf.jp.nec.com> wrote:
> > Hi bhupesh,
> >
> > Thank you for your V2 patchset.
> >
> > When you have introduced tools.c from crash utility,
> > you have deleted a part of htol()'s error handling
> > that is unnecessary for makedumpfile as follows;
> >
> > htol_error:
> > -       switch (flags & (FAULT_ON_ERROR|RETURN_ON_ERROR))
> > -       {
> > -       case FAULT_ON_ERROR:
> > -               RESTART();
> > -
> > -       case RETURN_ON_ERROR:
> > -               if (errptr)
> > -                       *errptr = TRUE;
> > -               break;
> > -       }
> > -
> >         return BADADDR;
> > }
> >
> > As a result of this, htol() does not refer to 3rd parameter 'errptr'
> > and RETURN_ON_ERROR.
> > I understand that some codes are not used on makedumpfile's tools.c.
> > They may be used in the future.
> 
> Indeed the 3rd parameter in 'htol()' is not currently needed by
> makedumpfile code, but like you mentioned I earlier thought it might
> be required for future compatibility some some future feature
> addition.
> 
> > However I think 'errptr' should be deleted, so I have tried modifying
> > your patches as follows;
> > $ diff "PATCH v2 13 Add a new helper file 'tools
> > .c' that provides some useful APIs.patch.old" "PATCH v2 13 Add a new helper file
> >  'tools.c' that provides some useful APIs.patch"
> > 100c100
> > < +ulong htol(char *s, int flags, int *errptr);
> > ---
> >> +ulong htol(char *s, int flags);
> > 681c681
> > < +htol(char *s, int flags, int *errptr)
> > ---
> >> +htol(char *s, int flags)
> >
> > $ diff "PATCH v2 23 arm64 Add support to read sy
> > mbols like _stext from 'prockallsyms'.patch.old" "PATCH v2 23 arm64 Add support
> > to read symbols like _stext from 'prockallsyms'.patch"
> > 62c62
> > < @@ -177,6 +181,45 @@ get_phys_base_arm64(void)
> > ---
> >> @@ -177,6 +181,44 @@ get_phys_base_arm64(void)
> > 94,95c94
> > < +                     kallsym = htol(kallsyms[0], RETURN_ON_ERROR,
> > < +                                     NULL);
> > ---
> >> +                     kallsym = htol(kallsyms[0], 0);
> >
> > How about this ?
> > If you agree, I'll merge the modified patchset into V1.6.4.
> 
> Yes. This seems fine to me. We can add the 3rd parameter to 'htol'
> later if its needed in future.
> 
> Please feel free to merge the modified patchset into V1.6.4

OK. I will merge the modified patchset into V1.6.4.


Thanks
Tachibana

> 
> Regards,
> Bhupesh
> 
> >
> >> -----Original Message-----
> >> From: kexec [mailto:kexec-bounces@lists.infradead.org] On Behalf Of Bhupesh Sharma
> >> Sent: Tuesday, March 06, 2018 2:13 AM
> >> To: kexec@lists.infradead.org
> >> Cc: bhsharma@redhat.com; bhupesh.linux@gmail.com
> >> Subject: [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
> >>
> >> This patch borrows the 'tools.c' helper file from the crash utility
> >> project and adds it to the makedumpfile source code, to allow
> >> some basic useful APIs to be present which can be invoked from
> >> other source code files.
> >>
> >> 'tools.c' provides some useful APIs like 'htol' (convert
> >> a string to a hexadecimal long value), etc. which can be
> >> invoked by other functions (a functionality that is exposed
> >> by follow-up patches).
> >>
> >> Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> >> ---
> >>  Makefile       |   2 +-
> >>  common.h       |   8 +
> >>  makedumpfile.h |  14 ++
> >>  tools.c        | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 789 insertions(+), 1 deletion(-)
> >>  create mode 100644 tools.c
> >>
> >> diff --git a/Makefile b/Makefile
> >> index f4b7c56b6f3d..e870b1362c95 100644
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
> >>  endif
> >>
> >>  SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
> >> -SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
> >> +SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
> >>  OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
> >>  SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c
> >> arch/sparc64.c
> >>  OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
> >> diff --git a/common.h b/common.h
> >> index 6ad3ca7b952c..6e2f657a79c7 100644
> >> --- a/common.h
> >> +++ b/common.h
> >> @@ -19,6 +19,8 @@
> >>  #define TRUE         (1)
> >>  #define FALSE                (0)
> >>  #define ERROR                (-1)
> >> +#define UNUSED       (-1)
> >> +#define RETURN_ON_ERROR      (0x2)
> >>
> >>  #ifndef LONG_MAX
> >>  #define LONG_MAX     ((long)(~0UL>>1))
> >> @@ -35,12 +37,18 @@
> >>  #define round(x, y)  (((x) / (y)) * (y))
> >>  #define roundup(x, y)        ((((x) + ((y) - 1)) / (y)) * (y))
> >>
> >> +#define NUM_HEX  (0x1)
> >> +#define NUM_DEC  (0x2)
> >> +#define NUM_EXPR (0x4)
> >> +#define NUM_ANY  (NUM_HEX|NUM_DEC|NUM_EXPR)
> >> +
> >>  /*
> >>   * Incorrect address
> >>   */
> >>  #define NOT_MEMMAP_ADDR      (0x0)
> >>  #define NOT_KV_ADDR  (0x0)
> >>  #define NOT_PADDR    (ULONGLONG_MAX)
> >> +#define BADADDR      ((ulong)(-1))
> >>
> >>  #endif  /* COMMON_H */
> >>
> >> diff --git a/makedumpfile.h b/makedumpfile.h
> >> index 01eece231475..0ce75e29fa7f 100644
> >> --- a/makedumpfile.h
> >> +++ b/makedumpfile.h
> >> @@ -237,6 +237,9 @@ isAnon(unsigned long mapping)
> >>  #define MIN_ELF_HEADER_SIZE \
> >>       MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
> >>  static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
> >> +#define STREQ(A, B) (string_exists((char *)A) &&     \
> >> +                  string_exists((char *)B) &&        \
> >> +     (strcmp((char *)(A), (char *)(B)) == 0))
> >>  #define STRNEQ(A, B)(string_exists((char *)(A)) &&   \
> >>                    string_exists((char *)(B)) &&      \
> >>       (strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
> >> @@ -2319,4 +2322,15 @@ int prepare_splitblock_table(void);
> >>  int initialize_zlib(z_stream *stream, int level);
> >>  int finalize_zlib(z_stream *stream);
> >>
> >> +int parse_line(char *str, char *argv[]);
> >> +char *shift_string_left(char *s, int cnt);
> >> +char *clean_line(char *line);
> >> +char *strip_linefeeds(char *line);
> >> +char *strip_beginning_whitespace(char *line);
> >> +char *strip_ending_whitespace(char *line);
> >> +ulong htol(char *s, int flags, int *errptr);
> >> +int hexadecimal(char *s, int count);
> >> +int decimal(char *s, int count);
> >> +int file_exists(char *file);
> >> +
> >>  #endif /* MAKEDUMPFILE_H */
> >> diff --git a/tools.c b/tools.c
> >> new file mode 100644
> >> index 000000000000..746ffa104816
> >> --- /dev/null
> >> +++ b/tools.c
> >> @@ -0,0 +1,766 @@
> >> +/* tools.c - Borrowed from crash utility code
> >> + *           (https://github.com/crash-utility/crash)
> >> + *
> >> + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
> >> + * Copyright (C) 2002-2017 David Anderson
> >> + * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as published by
> >> + * the Free Software Foundation; either version 2 of the License, or
> >> + * (at your option) any later version.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + */
> >> +
> >> +#include "common.h"
> >> +#include "makedumpfile.h"
> >> +#include <ctype.h>
> >> +
> >> +#define FAULT_ON_ERROR               (0x1)
> >> +#define RETURN_ON_ERROR              (0x2)
> >> +#define QUIET                        (0x4)
> >> +#define HEX_BIAS             (0x8)
> >> +#define LONG_LONG            (0x10)
> >> +#define RETURN_PARTIAL               (0x20)
> >> +#define NO_DEVMEM_SWITCH     (0x40)
> >> +
> >> +#define MAX_HEXADDR_STRLEN   (16)
> >> +
> >> +#define FIRSTCHAR(s)         (s[0])
> >> +
> >> +/*
> >> + * Determine whether a file exists, using the caller's stat structure if
> >> + * one was passed in.
> >> + */
> >> +int
> >> +file_exists(char *file)
> >> +{
> >> +     struct stat sbuf;
> >> +
> >> +     if (stat(file, &sbuf) == 0)
> >> +             return TRUE;
> >> +
> >> +     return FALSE;
> >> +}
> >> +
> >> +/*
> >> + * Parse a line into tokens, populate the passed-in argv[] array, and
> >> + * return the count of arguments found. This function modifies the
> >> + * passed-string by inserting a NULL character at the end of each token.
> >> + * Expressions encompassed by parentheses, and strings encompassed by
> >> + * apostrophes, are collected into single tokens.
> >> + */
> >> +int
> >> +parse_line(char *str, char *argv[])
> >> +{
> >> +     int i, j, k;
> >> +     int string;
> >> +     int expression;
> >> +
> >> +     for (i = 0; i < MAXARGS; i++)
> >> +             argv[i] = NULL;
> >> +
> >> +     clean_line(str);
> >> +
> >> +     if (str == NULL || strlen(str) == 0)
> >> +             return(0);
> >> +
> >> +     i = j = k = 0;
> >> +     string = expression = FALSE;
> >> +
> >> +     /*
> >> +      * Special handling for when the first character is a '"'.
> >> +      */
> >> +     if (str[0] == '"') {
> >> +next:
> >> +             do {
> >> +                     i++;
> >> +             } while ((str[i] != NULLCHAR) && (str[i] != '"'));
> >> +
> >> +             switch (str[i])
> >> +             {
> >> +             case NULLCHAR:
> >> +                     argv[j] = &str[k];
> >> +                     return j+1;
> >> +             case '"':
> >> +                     argv[j++] = &str[k+1];
> >> +                     str[i++] = NULLCHAR;
> >> +                     if (str[i] == '"') {
> >> +                             k = i;
> >> +                             goto next;
> >> +                     }
> >> +                     break;
> >> +             }
> >> +     } else
> >> +             argv[j++] = str;
> >> +
> >> +     while (TRUE) {
> >> +             if (j == MAXARGS)
> >> +                     ERRMSG("too many arguments in string!\n");
> >> +
> >> +             while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
> >> +                     i++;
> >> +             }
> >> +
> >> +             switch (str[i])
> >> +             {
> >> +             case ' ':
> >> +             case '\t':
> >> +                     str[i++] = NULLCHAR;
> >> +
> >> +                     while (str[i] == ' ' || str[i] == '\t') {
> >> +                             i++;
> >> +                     }
> >> +
> >> +                     if (str[i] == '"') {
> >> +                             str[i] = ' ';
> >> +                             string = TRUE;
> >> +                             i++;
> >> +                     }
> >> +
> >> +                     if (!string && str[i] == '(') {
> >> +                             expression = TRUE;
> >> +                     }
> >> +
> >> +                     if (str[i] != NULLCHAR && str[i] != '\n') {
> >> +                             argv[j++] = &str[i];
> >> +                             if (string) {
> >> +                                     string = FALSE;
> >> +                                     while (str[i] != '"' && str[i] != NULLCHAR)
> >> +                                             i++;
> >> +                                     if (str[i] == '"')
> >> +                                             str[i] = ' ';
> >> +                             }
> >> +                             if (expression) {
> >> +                                     expression = FALSE;
> >> +                                     while (str[i] != ')' && str[i] != NULLCHAR)
> >> +                                             i++;
> >> +                             }
> >> +                             break;
> >> +                     }
> >> +                     /* else fall through */
> >> +             case '\n':
> >> +                     str[i] = NULLCHAR;
> >> +                     /* keep falling... */
> >> +             case NULLCHAR:
> >> +                     argv[j] = NULLCHAR;
> >> +                     return(j);
> >> +             }
> >> +     }
> >> +}
> >> +
> >> +/*
> >> + * Defuse controversy re: extensions to ctype.h
> >> + */
> >> +int
> >> +whitespace(int c)
> >> +{
> >> +     return ((c == ' ') ||(c == '\t'));
> >> +}
> >> +
> >> +int
> >> +ascii(int c)
> >> +{
> >> +     return ((c >= 0) && (c <= 0x7f));
> >> +}
> >> +
> >> +/*
> >> + * Strip line-ending whitespace and linefeeds.
> >> + */
> >> +char *
> >> +strip_line_end(char *line)
> >> +{
> >> +     strip_linefeeds(line);
> >> +     strip_ending_whitespace(line);
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip line-beginning and line-ending whitespace and linefeeds.
> >> + */
> >> +char *
> >> +clean_line(char *line)
> >> +{
> >> +     strip_beginning_whitespace(line);
> >> +     strip_linefeeds(line);
> >> +     strip_ending_whitespace(line);
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip line-ending linefeeds in a string.
> >> + */
> >> +char *
> >> +strip_linefeeds(char *line)
> >> +{
> >> +     char *p;
> >> +
> >> +     if (line == NULL || strlen(line) == 0)
> >> +             return(line);
> >> +
> >> +     p = &LASTCHAR(line);
> >> +
> >> +     while (*p == '\n') {
> >> +             *p = NULLCHAR;
> >> +             if (--p < line)
> >> +                     break;
> >> +     }
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip a specified line-ending character in a string.
> >> + */
> >> +char *
> >> +strip_ending_char(char *line, char c)
> >> +{
> >> +     char *p;
> >> +
> >> +     if (line == NULL || strlen(line) == 0)
> >> +             return(line);
> >> +
> >> +     p = &LASTCHAR(line);
> >> +
> >> +     if (*p == c)
> >> +             *p = NULLCHAR;
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip a specified line-beginning character in a string.
> >> + */
> >> +char *
> >> +strip_beginning_char(char *line, char c)
> >> +{
> >> +     if (line == NULL || strlen(line) == 0)
> >> +             return(line);
> >> +
> >> +     if (FIRSTCHAR(line) == c)
> >> +             shift_string_left(line, 1);
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip line-ending whitespace.
> >> + */
> >> +char *
> >> +strip_ending_whitespace(char *line)
> >> +{
> >> +     char *p;
> >> +
> >> +     if (line == NULL || strlen(line) == 0)
> >> +             return(line);
> >> +
> >> +     p = &LASTCHAR(line);
> >> +
> >> +     while (*p == ' ' || *p == '\t') {
> >> +             *p = NULLCHAR;
> >> +             if (p == line)
> >> +                     break;
> >> +             p--;
> >> +     }
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip line-beginning whitespace.
> >> + */
> >> +char *
> >> +strip_beginning_whitespace(char *line)
> >> +{
> >> +     char buf[BUFSIZE];
> >> +     char *p;
> >> +
> >> +     if (line == NULL || strlen(line) == 0)
> >> +             return(line);
> >> +
> >> +     strcpy(buf, line);
> >> +     p = &buf[0];
> >> +     while (*p == ' ' || *p == '\t')
> >> +             p++;
> >> +     strcpy(line, p);
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * End line at first comma found.
> >> + */
> >> +char *
> >> +strip_comma(char *line)
> >> +{
> >> +     char *p;
> >> +
> >> +     if ((p = strstr(line, ",")))
> >> +             *p = NULLCHAR;
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Strip the 0x from the beginning of a hexadecimal value string.
> >> + */
> >> +char *
> >> +strip_hex(char *line)
> >> +{
> >> +     if (STRNEQ(line, "0x"))
> >> +             shift_string_left(line, 2);
> >> +
> >> +     return(line);
> >> +}
> >> +
> >> +/*
> >> + * Turn a string into upper-case.
> >> + */
> >> +char *
> >> +upper_case(const char *s, char *buf)
> >> +{
> >> +     const char *p1;
> >> +     char *p2;
> >> +
> >> +     p1 = s;
> >> +     p2 = buf;
> >> +
> >> +     while (*p1) {
> >> +             *p2 = toupper(*p1);
> >> +             p1++, p2++;
> >> +     }
> >> +
> >> +     *p2 = NULLCHAR;
> >> +
> >> +     return(buf);
> >> +}
> >> +
> >> +/*
> >> + * Return pointer to first non-space/tab in a string.
> >> + */
> >> +char *
> >> +first_nonspace(char *s)
> >> +{
> >> +     return(s + strspn(s, " \t"));
> >> +}
> >> +
> >> +/*
> >> + * Return pointer to first space/tab in a string. If none are found,
> >> + * return a pointer to the string terminating NULL.
> >> + */
> >> +char *
> >> +first_space(char *s)
> >> +{
> >> +     return(s + strcspn(s, " \t"));
> >> +}
> >> +
> >> +/*
> >> + * Replace the first space/tab found in a string with a NULL character.
> >> + */
> >> +char *
> >> +null_first_space(char *s)
> >> +{
> >> +     char *p1;
> >> +
> >> +     p1 = first_space(s);
> >> +     if (*p1)
> >> +             *p1 = NULLCHAR;
> >> +
> >> +     return s;
> >> +}
> >> +
> >> +/*
> >> + * Replace any instances of the characters in string c that are found in
> >> + * string s with the character passed in r.
> >> + */
> >> +char *
> >> +replace_string(char *s, char *c, char r)
> >> +{
> >> +     int i, j;
> >> +
> >> +     for (i = 0; s[i]; i++) {
> >> +             for (j = 0; c[j]; j++) {
> >> +                     if (s[i] == c[j])
> >> +                             s[i] = r;
> >> +             }
> >> +     }
> >> +
> >> +     return s;
> >> +}
> >> +
> >> +/*
> >> + * Find the rightmost instance of a substring in a string.
> >> + */
> >> +char *
> >> +strstr_rightmost(char *s, char *lookfor)
> >> +{
> >> +     char *next, *last, *p;
> >> +
> >> +     for (p = s, last = NULL; *p; p++) {
> >> +             if (!(next = strstr(p, lookfor)))
> >> +                     break;
> >> +             last = p = next;
> >> +     }
> >> +
> >> +     return last;
> >> +}
> >> +
> >> +/*
> >> + * Shifts the contents of a string to the left by cnt characters,
> >> + * disposing the leftmost characters.
> >> + */
> >> +char *
> >> +shift_string_left(char *s, int cnt)
> >> +{
> >> +     int origlen;
> >> +
> >> +     if (!cnt)
> >> +             return(s);
> >> +
> >> +     origlen = strlen(s);
> >> +     memmove(s, s+cnt, (origlen-cnt));
> >> +     *(s+(origlen-cnt)) = NULLCHAR;
> >> +     return(s);
> >> +}
> >> +
> >> +/*
> >> + * Prints a string verbatim, allowing strings with % signs to be displayed
> >> + * without printf conversions.
> >> + */
> >> +void
> >> +print_verbatim(FILE *filep, char *line)
> >> +{
> >> +     int i;
> >> +
> >> +     for (i = 0; i < strlen(line); i++) {
> >> +             fputc(line[i], filep);
> >> +             fflush(filep);
> >> +     }
> >> +}
> >> +
> >> +char *
> >> +fixup_percent(char *s)
> >> +{
> >> +     char *p1;
> >> +
> >> +     if ((p1 = strstr(s, "%")) == NULL)
> >> +             return s;
> >> +
> >> +     s[strlen(s)+1] = NULLCHAR;
> >> +     memmove(p1+1, p1, strlen(p1));
> >> +     *p1 = '%';
> >> +
> >> +     return s;
> >> +}
> >> +
> >> +/*
> >> + * Append a two-character string to a number to make 1, 2, 3 and 4 into
> >> + * 1st, 2nd, 3rd, 4th, and so on...
> >> + */
> >> +char *
> >> +ordinal(ulong val, char *buf)
> >> +{
> >> +     char *p1;
> >> +
> >> +     sprintf(buf, "%ld", val);
> >> +     p1 = &buf[strlen(buf)-1];
> >> +
> >> +     switch (*p1)
> >> +     {
> >> +     case '1':
> >> +             strcat(buf, "st");
> >> +             break;
> >> +     case '2':
> >> +             strcat(buf, "nd");
> >> +             break;
> >> +     case '3':
> >> +             strcat(buf, "rd");
> >> +             break;
> >> +     default:
> >> +             strcat(buf, "th");
> >> +             break;
> >> +     }
> >> +
> >> +     return buf;
> >> +}
> >> +
> >> +/*
> >> + * Determine whether a string contains only decimal characters.
> >> + * If count is non-zero, limit the search to count characters.
> >> + */
> >> +int
> >> +decimal(char *s, int count)
> >> +{
> >> +     char *p;
> >> +     int cnt, digits;
> >> +
> >> +     if (!count) {
> >> +             strip_line_end(s);
> >> +             cnt = 0;
> >> +     } else
> >> +             cnt = count;
> >> +
> >> +     for (p = &s[0], digits = 0; *p; p++) {
> >> +             switch(*p)
> >> +             {
> >> +             case '0':
> >> +             case '1':
> >> +             case '2':
> >> +             case '3':
> >> +             case '4':
> >> +             case '5':
> >> +             case '6':
> >> +             case '7':
> >> +             case '8':
> >> +             case '9':
> >> +                     digits++;
> >> +             case ' ':
> >> +                     break;
> >> +             default:
> >> +                     return FALSE;
> >> +             }
> >> +
> >> +             if (count && (--cnt == 0))
> >> +                     break;
> >> +     }
> >> +
> >> +     return (digits ? TRUE : FALSE);
> >> +}
> >> +
> >> +/*
> >> + * Determine whether a string contains only ASCII characters.
> >> + */
> >> +int
> >> +ascii_string(char *s)
> >> +{
> >> +     char *p;
> >> +
> >> +     for (p = &s[0]; *p; p++) {
> >> +             if (!ascii(*p))
> >> +                     return FALSE;
> >> +     }
> >> +
> >> +     return TRUE;
> >> +}
> >> +
> >> +/*
> >> + * Check whether a string contains only printable ASCII characters.
> >> + */
> >> +int
> >> +printable_string(char *s)
> >> +{
> >> +     char *p;
> >> +
> >> +     for (p = &s[0]; *p; p++) {
> >> +             if (!isprint(*p))
> >> +                     return FALSE;
> >> +     }
> >> +
> >> +     return TRUE;
> >> +}
> >> +
> >> +/*
> >> + * Convert a string to a hexadecimal long value.
> >> + */
> >> +ulong
> >> +htol(char *s, int flags, int *errptr)
> >> +{
> >> +     ulong i, j;
> >> +     ulong n;
> >> +
> >> +     if (s == NULL) {
> >> +             if (!(flags & QUIET))
> >> +                     ERRMSG("received NULL string\n");
> >> +             goto htol_error;
> >> +     }
> >> +
> >> +     if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
> >> +             s += 2;
> >> +
> >> +     if (strlen(s) > MAX_HEXADDR_STRLEN) {
> >> +             if (!(flags & QUIET))
> >> +                     ERRMSG("input string too large: \"%s\" (%d vs %d)\n",
> >> +                                     s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
> >> +             goto htol_error;
> >> +     }
> >> +
> >> +     for (n = i = 0; s[i] != 0; i++) {
> >> +             switch (s[i])
> >> +             {
> >> +             case 'a':
> >> +             case 'b':
> >> +             case 'c':
> >> +             case 'd':
> >> +             case 'e':
> >> +             case 'f':
> >> +                     j = (s[i] - 'a') + 10;
> >> +                     break;
> >> +             case 'A':
> >> +             case 'B':
> >> +             case 'C':
> >> +             case 'D':
> >> +             case 'E':
> >> +             case 'F':
> >> +                     j = (s[i] - 'A') + 10;
> >> +                     break;
> >> +             case '1':
> >> +             case '2':
> >> +             case '3':
> >> +             case '4':
> >> +             case '5':
> >> +             case '6':
> >> +             case '7':
> >> +             case '8':
> >> +             case '9':
> >> +             case '0':
> >> +                     j = s[i] - '0';
> >> +                     break;
> >> +             case 'x':
> >> +             case 'X':
> >> +             case 'h':
> >> +                     continue;
> >> +             default:
> >> +                     if (!(flags & QUIET))
> >> +                             ERRMSG("invalid input: \"%s\"\n", s);
> >> +                     goto htol_error;
> >> +             }
> >> +             n = (16 * n) + j;
> >> +     }
> >> +
> >> +     return(n);
> >> +
> >> +htol_error:
> >> +     return BADADDR;
> >> +}
> >> +
> >> +/*
> >> + * Determine whether a string contains only hexadecimal characters.
> >> + * If count is non-zero, limit the search to count characters.
> >> + */
> >> +int
> >> +hexadecimal(char *s, int count)
> >> +{
> >> +     char *p;
> >> +     int cnt, digits;
> >> +
> >> +     if (!count) {
> >> +             strip_line_end(s);
> >> +             cnt = 0;
> >> +     } else
> >> +             cnt = count;
> >> +
> >> +     for (p = &s[0], digits = 0; *p; p++) {
> >> +             switch(*p)
> >> +             {
> >> +             case 'a':
> >> +             case 'b':
> >> +             case 'c':
> >> +             case 'd':
> >> +             case 'e':
> >> +             case 'f':
> >> +             case 'A':
> >> +             case 'B':
> >> +             case 'C':
> >> +             case 'D':
> >> +             case 'E':
> >> +             case 'F':
> >> +             case '1':
> >> +             case '2':
> >> +             case '3':
> >> +             case '4':
> >> +             case '5':
> >> +             case '6':
> >> +             case '7':
> >> +             case '8':
> >> +             case '9':
> >> +             case '0':
> >> +                     digits++;
> >> +             case 'x':
> >> +             case 'X':
> >> +                     break;
> >> +
> >> +             case ' ':
> >> +                     if (*(p+1) == NULLCHAR)
> >> +                             break;
> >> +                     else
> >> +                             return FALSE;
> >> +             default:
> >> +                     return FALSE;
> >> +             }
> >> +
> >> +             if (count && (--cnt == 0))
> >> +                     break;
> >> +     }
> >> +
> >> +     return (digits ? TRUE : FALSE);
> >> +}
> >> +
> >> +/*
> >> + * Determine whether a string contains only hexadecimal characters.
> >> + * and cannot be construed as a decimal number.
> >> + * If count is non-zero, limit the search to count characters.
> >> + */
> >> +int
> >> +hexadecimal_only(char *s, int count)
> >> +{
> >> +     char *p;
> >> +     int cnt, only;
> >> +
> >> +     if (!count) {
> >> +             strip_line_end(s);
> >> +             cnt = 0;
> >> +     } else
> >> +             cnt = count;
> >> +
> >> +     only = 0;
> >> +
> >> +     for (p = &s[0]; *p; p++) {
> >> +             switch(*p)
> >> +             {
> >> +             case 'a':
> >> +             case 'b':
> >> +             case 'c':
> >> +             case 'd':
> >> +             case 'e':
> >> +             case 'f':
> >> +             case 'A':
> >> +             case 'B':
> >> +             case 'C':
> >> +             case 'D':
> >> +             case 'E':
> >> +             case 'F':
> >> +             case 'x':
> >> +             case 'X':
> >> +                     only++;
> >> +                     break;
> >> +             case '1':
> >> +             case '2':
> >> +             case '3':
> >> +             case '4':
> >> +             case '5':
> >> +             case '6':
> >> +             case '7':
> >> +             case '8':
> >> +             case '9':
> >> +             case '0':
> >> +                     break;
> >> +
> >> +             case ' ':
> >> +                     if (*(p+1) == NULLCHAR)
> >> +                             break;
> >> +                     else
> >> +                             return FALSE;
> >> +             default:
> >> +                     return FALSE;
> >> +             }
> >> +
> >> +             if (count && (--cnt == 0))
> >> +                     break;
> >> +     }
> >> +
> >> +     return only;
> >> +}
> >> --
> >> 2.7.4
> >>
> >>
> >> _______________________________________________
> >> kexec mailing list
> >> kexec@lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/kexec
> >
> >

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-03-08  4:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-05 17:12 [PATCH v2 0/3] makedumpfile/arm64: Add '--mem-usage' support Bhupesh Sharma
2018-03-05 17:12 ` [PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs Bhupesh Sharma
2018-03-06 10:03   ` Masaki Tachibana
2018-03-06 10:17     ` Bhupesh Sharma
2018-03-08  4:45       ` Masaki Tachibana
2018-03-05 17:12 ` [PATCH v2 2/3] arm64: Add support to read symbols like _stext from '/proc/kallsyms' Bhupesh Sharma
2018-03-05 17:12 ` [PATCH v2 3/3] Documentation: Update documentation regarding --mem-usage' option Bhupesh Sharma

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.