From a3fce6e82d24afe186a46461b9cf931f2f023f36 Mon Sep 17 00:00:00 2001 From: Jiajie Li Date: Mon, 12 Oct 2020 13:48:18 +0800 Subject: [PATCH 28/89] kpatch_parse: Split function is_variable_start The function is_variable_start is arch related, since different arch may use different assembly directives to describe variables. So let's make two definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c Signed-off-by: Jiajie Li Signed-off-by: Ying Fang --- src/arch/aarch64/arch_parse.c | 69 ++++++++++++++++++++++++++++++++++ src/arch/x86/arch_parse.c | 69 ++++++++++++++++++++++++++++++++++ src/include/kpatch_parse.h | 1 + src/kpatch_parse.c | 71 +---------------------------------- 4 files changed, 140 insertions(+), 70 deletions(-) diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c index 1233e03..abbc38c 100644 --- a/src/arch/aarch64/arch_parse.c +++ b/src/arch/aarch64/arch_parse.c @@ -4,6 +4,75 @@ #include "include/kpatch_parse.h" #include "include/kpatch_flags.h" +int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm) +{ + char *s; + int l0 = l, globl = 0; + kpstr_t nm2, attr; + + kpstrset(nm, "", 0); + for ( ; cline(f, l); l++) { + + /* first verify that all the commands we met has the same symbol name... just to be safe! */ + s = cline(f, l); + if (*s == '\0' && l != l0) + continue; + switch (ctype(f, l)) { + case DIRECTIVE_TYPE: + case DIRECTIVE_GLOBL: + case DIRECTIVE_LOCAL: + get_token(&s, &nm2); + case DIRECTIVE_LABEL: + get_token(&s, &nm2); + if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */ + return 0; + *nm = nm2; + break; + } + + switch (ctype(f, l)) { + case DIRECTIVE_TEXT: + case DIRECTIVE_DATA: + case DIRECTIVE_BSS: + case DIRECTIVE_SECTION: + case DIRECTIVE_PUSHSECTION: + case DIRECTIVE_POPSECTION: + case DIRECTIVE_PREVIOUS: + case DIRECTIVE_SUBSECTION: + break; + case DIRECTIVE_TYPE: + get_type_args(cline(f, l), &nm2, &attr); + if (kpstrcmpz(&attr, "%object") && kpstrcmpz(&attr, "%tls_object")) + return 0; + break; + case DIRECTIVE_GLOBL: + globl = 1; + break; + case DIRECTIVE_ALIGN: + break; + case DIRECTIVE_COMMENT: + case DIRECTIVE_SIZE: + /* can't start with .size */ + if (l0 == l) + return 0; + break; + case DIRECTIVE_LABEL: + if (!is_data_sect(csect(f, l))) + return 0; + /* fall throught */ + case DIRECTIVE_LOCAL: + if (e) + *e = l + 1; + if (pglobl) + *pglobl = globl; + return 1; + default: + return 0; + } + } + return 0; +} + /* break manually crafted multiple statements separated by ; to separate lines */ void init_multilines(struct kp_file *f) { diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c index 92ff483..ca57507 100644 --- a/src/arch/x86/arch_parse.c +++ b/src/arch/x86/arch_parse.c @@ -4,6 +4,75 @@ #include "include/kpatch_parse.h" #include "include/kpatch_flags.h" +int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm) +{ + char *s; + int l0 = l, globl = 0; + kpstr_t nm2, attr; + + kpstrset(nm, "", 0); + for ( ; cline(f, l); l++) { + + /* first verify that all the commands we met has the same symbol name... just to be safe! */ + s = cline(f, l); + if (*s == '\0' && l != l0) + continue; + switch (ctype(f, l)) { + case DIRECTIVE_TYPE: + case DIRECTIVE_GLOBL: + case DIRECTIVE_LOCAL: + get_token(&s, &nm2); + case DIRECTIVE_LABEL: + get_token(&s, &nm2); + if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */ + return 0; + *nm = nm2; + break; + } + + switch (ctype(f, l)) { + case DIRECTIVE_TEXT: + case DIRECTIVE_DATA: + case DIRECTIVE_BSS: + case DIRECTIVE_SECTION: + case DIRECTIVE_PUSHSECTION: + case DIRECTIVE_POPSECTION: + case DIRECTIVE_PREVIOUS: + case DIRECTIVE_SUBSECTION: + break; + case DIRECTIVE_TYPE: + get_type_args(cline(f, l), &nm2, &attr); + if (kpstrcmpz(&attr, "@object")) + return 0; + break; + case DIRECTIVE_GLOBL: + globl = 1; + break; + case DIRECTIVE_ALIGN: + break; + case DIRECTIVE_COMMENT: + case DIRECTIVE_SIZE: + /* can't start with .size */ + if (l0 == l) + return 0; + break; + case DIRECTIVE_LABEL: + if (!is_data_sect(csect(f, l))) + return 0; + /* fall throught */ + case DIRECTIVE_LOCAL: + if (e) + *e = l + 1; + if (pglobl) + *pglobl = globl; + return 1; + default: + return 0; + } + } + return 0; +} + /* break manually crafted multiple statements separated by ; to separate lines */ void init_multilines(struct kp_file *f) { diff --git a/src/include/kpatch_parse.h b/src/include/kpatch_parse.h index e1b7501..0f41509 100644 --- a/src/include/kpatch_parse.h +++ b/src/include/kpatch_parse.h @@ -109,6 +109,7 @@ void __get_token(char **str, kpstr_t *x, const char *delim); int is_function_start(struct kp_file *f, int l, kpstr_t *nm); int is_function_end(struct kp_file *f, int l, kpstr_t *nm); +void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr); int is_variable_start(struct kp_file *f, int l, int *e, int *globl, kpstr_t *nm); int is_data_def(char *s, int type); diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c index 857dbf3..a3be7c0 100644 --- a/src/kpatch_parse.c +++ b/src/kpatch_parse.c @@ -93,7 +93,7 @@ static struct { }; /* parse arguments of .type command */ -static void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr) +void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr) { kpstr_t t, t2; @@ -674,75 +674,6 @@ int is_function_end(struct kp_file *f, int l, kpstr_t *nm) return 1; } -int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm) -{ - char *s; - int l0 = l, globl = 0; - kpstr_t nm2, attr; - - kpstrset(nm, "", 0); - for ( ; cline(f, l); l++) { - - /* first verify that all the commands we met has the same symbol name... just to be safe! */ - s = cline(f, l); - if (*s == '\0' && l != l0) - continue; - switch (ctype(f, l)) { - case DIRECTIVE_TYPE: - case DIRECTIVE_GLOBL: - case DIRECTIVE_LOCAL: - get_token(&s, &nm2); - case DIRECTIVE_LABEL: - get_token(&s, &nm2); - if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */ - return 0; - *nm = nm2; - break; - } - - switch (ctype(f, l)) { - case DIRECTIVE_TEXT: - case DIRECTIVE_DATA: - case DIRECTIVE_BSS: - case DIRECTIVE_SECTION: - case DIRECTIVE_PUSHSECTION: - case DIRECTIVE_POPSECTION: - case DIRECTIVE_PREVIOUS: - case DIRECTIVE_SUBSECTION: - break; - case DIRECTIVE_TYPE: - get_type_args(cline(f, l), &nm2, &attr); - if (kpstrcmpz(&attr, "@object")) - return 0; - break; - case DIRECTIVE_GLOBL: - globl = 1; - break; - case DIRECTIVE_ALIGN: - break; - case DIRECTIVE_COMMENT: - case DIRECTIVE_SIZE: - /* can't start with .size */ - if (l0 == l) - return 0; - break; - case DIRECTIVE_LABEL: - if (!is_data_sect(csect(f, l))) - return 0; - /* fall throught */ - case DIRECTIVE_LOCAL: - if (e) - *e = l + 1; - if (pglobl) - *pglobl = globl; - return 1; - default: - return 0; - } - } - return 0; -} - int is_data_def(char *s, int type) { kpstr_t t; -- 2.23.0