[PATCH v2 1/3] Add a new helper file 'tools.c' that provides some useful APIs
Masaki Tachibana
mas-tachibana at vf.jp.nec.com
Tue Mar 6 02:03:35 PST 2018
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 at lists.infradead.org] On Behalf Of Bhupesh Sharma
> Sent: Tuesday, March 06, 2018 2:13 AM
> To: kexec at lists.infradead.org
> Cc: bhsharma at redhat.com; bhupesh.linux at 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 at 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 at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
More information about the kexec
mailing list