summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2021-11-13 08:00:00 +0000
committerDmitry V. Levin <ldv@strace.io>2021-11-13 08:00:00 +0000
commit5ea8888ff8fbf224812651fd07e7873239a4782a (patch)
tree131cc7719bbe46eceed3d35f4741708353eb7fbc
parent5cad0ff0f30c2729fca215c733dac83e19752040 (diff)
downloadstrace-5ea8888ff8fbf224812651fd07e7873239a4782a.tar.gz
maint/gen: cleanup
* maint/gen/xmalloc.c: New file. * maint/gen/xmalloc.h: Likewise. * maint/gen/Makefile: Rewrite. * maint/gen/codegen.c: Add copyright header, wrap very long lines, use CLEANUP_FREE, xstrdup, and xasprintf. * maint/gen/ast.c: Add copyright header, wrap very long lines, use xstrdup. * maint/gen/ast.h: Add copyright header, wrap very long lines. * maint/gen/deflang.h: Add copyright header and include guard, wrap very long lines, add attributes to prototypes. * maint/gen/lex.l: Add copyright header, wrap very long lines, fix warnings, use xstrdup. * maint/gen/parse.y: Add copyright header, wrap very long lines, fix warnings. * maint/gen/preprocess.c: Add copyright header, wrap very long lines. * maint/gen/preprocess.h: Include "ast.h". * maint/gen/symbols.c: Wrap very long lines, use xasprintf. * maint/gen/symbols.h: Wrap very long lines. * maint/gen/defs/common.def: Add copyright header.
-rw-r--r--maint/gen/.gitignore9
-rw-r--r--maint/gen/Makefile34
-rw-r--r--maint/gen/ast.c113
-rw-r--r--maint/gen/ast.h57
-rw-r--r--maint/gen/codegen.c483
-rw-r--r--maint/gen/deflang.h36
-rw-r--r--maint/gen/defs/common.def11
-rw-r--r--maint/gen/lex.l62
-rw-r--r--maint/gen/parse.y68
-rw-r--r--maint/gen/preprocess.c72
-rw-r--r--maint/gen/preprocess.h36
-rw-r--r--maint/gen/symbols.c39
-rw-r--r--maint/gen/symbols.h9
-rw-r--r--maint/gen/xmalloc.c78
-rw-r--r--maint/gen/xmalloc.h36
15 files changed, 708 insertions, 435 deletions
diff --git a/maint/gen/.gitignore b/maint/gen/.gitignore
index d690f4c72..33ca87140 100644
--- a/maint/gen/.gitignore
+++ b/maint/gen/.gitignore
@@ -1,6 +1,5 @@
-lex.yy.c
-parse.tab.c
-parse.tab.h
-parse
-parse.output
+/lex.yy.c
+/parse.tab.c
+/parse.tab.h
+/*.d
/gen
diff --git a/maint/gen/Makefile b/maint/gen/Makefile
index 85d35d20d..f67a5ccd0 100644
--- a/maint/gen/Makefile
+++ b/maint/gen/Makefile
@@ -1,16 +1,34 @@
-CFLAGS += -ggdb -std=gnu99 -Wall -Wextra
+# Copyright (c) 2021 Dmitry V. Levin <ldv@strace.io>
+# Copyright (c) 2021 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
-all: gen
+CPPFLAGS = -std=gnu99 -O2 -D_GNU_SOURCE=1 -Wall -Wextra
+TARGET = gen
+OBJ = parse.tab.o lex.yy.o ast.o codegen.o symbols.o preprocess.o xmalloc.o
+DEPS = $(OBJ:.o=.d)
-gen: parse.tab.o lex.yy.o ast.o codegen.o symbols.o parse.tab.h lex.yy.c preprocess.o
- $(CC) $(CFLAGS) parse.tab.o lex.yy.o ast.o codegen.o symbols.o preprocess.o -o ./gen
+all: $(TARGET)
+
+gen: $(OBJ)
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $@
lex.yy.c: lex.l parse.tab.h
- flex lex.l
+ flex $<
parse.tab.c parse.tab.h: parse.y
- bison -d parse.y
+ bison -d $<
clean:
- rm -f lex.yy.o ast.o parse.tab.o codegen.o preprocess.o symbols.o
- rm -f gen parse.tab.c parse.tab.h lex.yy.c lex.yy.h
+ $(RM) $(TARGET) $(OBJ) $(DEPS) \
+ parse.tab.c parse.tab.h lex.yy.c
+
+%.d: %.c
+ $(CC) -MM $(CPPFLAGS) $< -o $@
+
+$(DEPS): parse.tab.h
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(DEPS)
+endif
diff --git a/maint/gen/ast.c b/maint/gen/ast.c
index ebab08538..ede0641ea 100644
--- a/maint/gen/ast.c
+++ b/maint/gen/ast.c
@@ -1,39 +1,20 @@
-#include "ast.h"
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include "ast.h"
#include "deflang.h"
#include "symbols.h"
#include "parse.tab.h"
-void *
-xmalloc(size_t n)
-{
- void *ret = malloc(n);
-
- if (!ret) {
- fprintf(stderr, "allocation failed\n");
- exit(EXIT_FAILURE);
- }
-
- return ret;
-}
-
-void *
-xcalloc(size_t n)
-{
- void *ret = calloc(1, n);
-
- if (!ret) {
- fprintf(stderr, "allocation failed\n");
- exit(EXIT_FAILURE);
- }
-
- return ret;
-}
-
struct ast_node *
create_ast_node(enum ast_node_type type, void *loc)
{
@@ -43,7 +24,7 @@ create_ast_node(enum ast_node_type type, void *loc)
.loc = {
.lineno = ((YYLTYPE *) loc)->first_line,
.colno = ((YYLTYPE *) loc)->first_column,
- .file = strdup(cur_filename)
+ .file = xstrdup(cur_filename)
},
.next = NULL
};
@@ -51,7 +32,8 @@ create_ast_node(enum ast_node_type type, void *loc)
}
struct ast_type_option_list *
-create_ast_type_option_list(struct ast_type_option *cur, struct ast_type_option_list *next)
+create_ast_type_option_list(struct ast_type_option *cur,
+ struct ast_type_option_list *next)
{
struct ast_type_option_list *list = xmalloc(sizeof *list);
*list = (struct ast_type_option_list) {
@@ -62,7 +44,8 @@ create_ast_type_option_list(struct ast_type_option *cur, struct ast_type_option_
}
struct ast_syscall_arg *
-create_ast_syscall_arg(char *name, struct ast_type *type, struct ast_syscall_arg *next)
+create_ast_syscall_arg(char *name, struct ast_type *type,
+ struct ast_syscall_arg *next)
{
struct ast_syscall_arg *arg = xmalloc(sizeof *arg);
*arg = (struct ast_syscall_arg) {
@@ -85,9 +68,11 @@ create_ast_flag_values(char *name, struct ast_flag_values *next)
}
struct ast_struct_element *
-create_ast_struct_element(char *name, struct ast_type *type, struct ast_struct_element *next)
+create_ast_struct_element(char *name, struct ast_type *type,
+ struct ast_struct_element *next)
{
- struct ast_struct_element *struct_element = xmalloc(sizeof *struct_element);
+ struct ast_struct_element *struct_element =
+ xmalloc(sizeof *struct_element);
*struct_element = (struct ast_struct_element) {
.name = name,
.type = type,
@@ -111,8 +96,9 @@ struct known_type_option {
static struct known_type_option *known_type_options = NULL;
static bool
-compare_type_option_list(struct ast_type_option_list *a, struct ast_type_option_list *b,
- bool match_templates)
+compare_type_option_list(struct ast_type_option_list *a,
+ struct ast_type_option_list *b,
+ bool match_templates)
{
struct ast_type_option_list *cur_a = a;
struct ast_type_option_list *cur_b = b;
@@ -123,9 +109,9 @@ compare_type_option_list(struct ast_type_option_list *a, struct ast_type_option_
}
if (cur_a->option->child_type == AST_TYPE_CHILD_TEMPLATE_ID ||
- cur_b->option->child_type == AST_TYPE_CHILD_TEMPLATE_ID) {
+ cur_b->option->child_type == AST_TYPE_CHILD_TEMPLATE_ID) {
if (match_templates) {
- // templates are able to match all other type options
+ /* templates can match all other type options */
cur_a = cur_a->next;
cur_b = cur_b->next;
continue;
@@ -138,14 +124,16 @@ compare_type_option_list(struct ast_type_option_list *a, struct ast_type_option_
}
if (cur_a->option->child_type == AST_TYPE_CHILD_NUMBER &&
- (cur_a->option->number.val != cur_b->option->number.val)) {
+ cur_a->option->number.val != cur_b->option->number.val) {
return false;
}
if (cur_a->option->child_type == AST_TYPE_CHILD_TYPE) {
- if (!(strcmp(cur_a->option->type->name, cur_b->option->type->name) == 0 &&
- compare_type_option_list(cur_a->option->type->options,
- cur_b->option->type->options, match_templates))) {
+ if (!(strcmp(cur_a->option->type->name,
+ cur_b->option->type->name) == 0 &&
+ compare_type_option_list(cur_a->option->type->options,
+ cur_b->option->type->options,
+ match_templates))) {
return false;
}
}
@@ -164,21 +152,23 @@ compare_type_option_list(struct ast_type_option_list *a, struct ast_type_option_
bool
ast_type_matching(struct ast_type *a, struct ast_type *b)
{
- return strcmp(a->name, b->name) == 0 && compare_type_option_list(a->options, b->options, true);
+ return strcmp(a->name, b->name) == 0 &&
+ compare_type_option_list(a->options, b->options, true);
}
struct ast_type *
create_or_get_type(char **error, char *name, struct ast_type_option_list *options)
{
- // check if we've seen this type before
- for (struct known_type *cur = known_types; cur != NULL; cur = cur->next) {
+ /* check if we've seen this type before */
+ for (struct known_type *cur = known_types;
+ cur != NULL; cur = cur->next) {
if (strcmp(cur->type.name, name) == 0 &&
- compare_type_option_list(cur->type.options, options, false)) {
+ compare_type_option_list(cur->type.options, options, false)) {
return &cur->type;
}
}
- // allocate a new type
+ /* allocate a new type */
struct known_type *type = xmalloc(sizeof *type);
char *status = resolve_type(&type->type, name, options);
@@ -201,15 +191,16 @@ create_or_get_type(char **error, char *name, struct ast_type_option_list *option
struct ast_type_option *
create_or_get_type_option_number(struct ast_number number)
{
- // check if we've seen this type option before
- for (struct known_type_option *cur = known_type_options; cur != NULL; cur = cur->next) {
+ /* check if we've seen this type option before */
+ for (struct known_type_option *cur = known_type_options;
+ cur != NULL; cur = cur->next) {
if (cur->type_option.child_type == AST_TYPE_CHILD_NUMBER &&
- cur->type_option.number.val == number.val) {
+ cur->type_option.number.val == number.val) {
return &cur->type_option;
}
}
- // allocate a new type option
+ /* allocate a new type option */
struct known_type_option *option = xmalloc(sizeof *option);
*option = (struct known_type_option) {
.type_option = {
@@ -241,16 +232,20 @@ create_type_template_identifier(struct ast_number number)
struct ast_type_option *
create_or_get_type_option_nested(struct ast_type *child)
{
- // check if we've seen this type option before
- for (struct known_type_option *cur = known_type_options; cur != NULL; cur = cur->next) {
- // since all types are allocated by create_or_get_type,
- // types that are equal have the same address
- if (cur->type_option.child_type == AST_TYPE_CHILD_TYPE && cur->type_option.type == child) {
+ /* check if we've seen this type option before */
+ for (struct known_type_option *cur = known_type_options;
+ cur != NULL; cur = cur->next) {
+ /*
+ * Since all types are allocated by create_or_get_type,
+ * types that are equal have the same address.
+ */
+ if (cur->type_option.child_type == AST_TYPE_CHILD_TYPE &&
+ cur->type_option.type == child) {
return &cur->type_option;
}
}
- // allocate a new type option
+ /* allocate a new type option */
struct known_type_option *option = xmalloc(sizeof *option);
*option = (struct known_type_option) {
.type_option = {
@@ -266,7 +261,8 @@ create_or_get_type_option_nested(struct ast_type *child)
}
struct ast_type_option *
-create_type_option_range(struct ast_type_option *min, struct ast_type_option *max)
+create_type_option_range(struct ast_type_option *min,
+ struct ast_type_option *max)
{
struct ast_type_option *ret = xmalloc(sizeof *ret);
*ret = (struct ast_type_option) {
@@ -294,7 +290,8 @@ free_ast_tree(struct ast_node *root)
free(root->include.value);
break;
case AST_STRUCT: {
- struct ast_struct_element *cur = root->ast_struct.elements;
+ struct ast_struct_element *cur =
+ root->ast_struct.elements;
while (cur != NULL) {
struct ast_struct_element *tmp = cur;
cur = tmp->next;
diff --git a/maint/gen/ast.h b/maint/gen/ast.h
index 2a5ee9805..863865c54 100644
--- a/maint/gen/ast.h
+++ b/maint/gen/ast.h
@@ -1,8 +1,16 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
#ifndef AST_H
-#define AST_H
+# define AST_H
-#include <stdbool.h>
-#include <stdint.h>
+# include <stdbool.h>
+# include <stdint.h>
struct ast_number {
char *raw;
@@ -44,27 +52,27 @@ struct ast_syscall_arg {
};
enum standard_types {
- // non-special type
+ /* non-special type */
TYPE_BASIC,
- // const[typ, val]
+ /* const[typ, val] */
TYPE_CONST,
- // ptr[dir, typ]
+ /* ptr[dir, typ] */
TYPE_PTR,
- // ref[argname]
+ /* ref[argname] */
TYPE_REF,
- // xorflags[flag_typ]
+ /* xorflags[flag_typ] */
TYPE_XORFLAGS,
- // orflags[flag_typ]
+ /* orflags[flag_typ] */
TYPE_ORFLAGS
};
-#define IS_IN_PTR(x) ((x)->type == TYPE_PTR && \
+# define IS_IN_PTR(x) ((x)->type == TYPE_PTR && \
((x)->ptr.dir == PTR_DIR_INOUT || (x)->ptr.dir == PTR_DIR_IN))
-#define IS_OUT_PTR(x) ((x)->type == TYPE_PTR && \
+# define IS_OUT_PTR(x) ((x)->type == TYPE_PTR && \
((x)->ptr.dir == PTR_DIR_INOUT || (x)->ptr.dir == PTR_DIR_OUT))
-#define IS_INOUT_PTR(x) ((x)->type == TYPE_PTR && (x)->ptr.dir == PTR_DIR_INOUT)
+# define IS_INOUT_PTR(x) ((x)->type == TYPE_PTR && (x)->ptr.dir == PTR_DIR_INOUT)
enum ptr_dir {
PTR_DIR_IN,
@@ -94,7 +102,7 @@ struct ast_type {
} array;
struct {
bool return_value;
- // only set if return_value is false
+ /* only set if return_value is false */
char *argname;
} ref;
struct {
@@ -152,7 +160,7 @@ struct ast_node {
enum ast_node_type type;
struct ast_loc loc;
- // used when this node's parent is AST_COMPOUND
+ /* used when this node's parent is AST_COMPOUND */
struct ast_node *next;
union {
@@ -187,26 +195,28 @@ struct ast_node *
create_ast_node(enum ast_node_type type, void *location);
struct ast_type_option_list *
-create_ast_type_option_list(struct ast_type_option *cur, struct ast_type_option_list *next);
+create_ast_type_option_list(struct ast_type_option *cur,
+ struct ast_type_option_list *next);
struct ast_struct_element *
-create_ast_struct_element(char *name, struct ast_type *type, struct ast_struct_element *next);
+create_ast_struct_element(char *name, struct ast_type *type,
+ struct ast_struct_element *next);
struct ast_syscall_arg *
-create_ast_syscall_arg(char *name, struct ast_type *type, struct ast_syscall_arg *next);
+create_ast_syscall_arg(char *name, struct ast_type *type,
+ struct ast_syscall_arg *next);
struct ast_flag_values *
create_ast_flag_values(char *name, struct ast_flag_values *next);
-// returns true if two types are equal; false otherwise
+/* Returns true if two types are equal; false otherwise. */
bool
ast_type_matching(struct ast_type *a, struct ast_type *b);
-/*
- * On error, returns NULL and sets an error string to error.
- */
+/* On error, returns NULL and sets an error string to error. */
struct ast_type *
-create_or_get_type(char **error, char *name, struct ast_type_option_list *options);
+create_or_get_type(char **error, char *name,
+ struct ast_type_option_list *options);
struct ast_type_option *
create_or_get_type_option_number(struct ast_number number);
@@ -215,7 +225,8 @@ struct ast_type_option *
create_or_get_type_option_nested(struct ast_type *child);
struct ast_type_option *
-create_type_option_range(struct ast_type_option *min, struct ast_type_option *max);
+create_type_option_range(struct ast_type_option *min,
+ struct ast_type_option *max);
struct ast_type_option *
create_type_template_identifier(struct ast_number number);
diff --git a/maint/gen/codegen.c b/maint/gen/codegen.c
index 05dfb08a5..8f2e0653b 100644
--- a/maint/gen/codegen.c
+++ b/maint/gen/codegen.c
@@ -1,3 +1,11 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
#include <assert.h>
#include <ctype.h>
#include <inttypes.h>
@@ -50,11 +58,6 @@ char *unsigned_int_types[] = {
static struct decoder_list *decoders = NULL;
-#define VARIANT_FUNC_NAME_LEN 64
-#define SYSCALL_RET_FLAG_LEN 64
-#define SYSCALL_ARG_STR_LEN 16
-#define DECODER_PROTOTYPE_LEN 128
-
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
/* convenience macros */
@@ -169,28 +172,28 @@ is_unsigned_integer_typename(const char *name)
/*
* Stores a string referring to the i-th argument in the current syscall.
*/
-static void
-get_syscall_arg_value(char out[static SYSCALL_ARG_STR_LEN], struct syscall *syscall, size_t i)
+static char *
+get_syscall_arg_value(struct syscall *syscall, size_t i)
{
if (syscall->is_ioctl) {
if (i >= 1 && i <= 2) {
const char *ioctl_args[3] = {"", "code", "arg"};
- snprintf(out, SYSCALL_ARG_STR_LEN, "%s", ioctl_args[i]);
- return;
+ return xstrdup(ioctl_args[i]);
}
- log_warning("ioctl decoder referenced OOB argument %zu", syscall->loc, i);
+ log_warning("ioctl decoder referenced OOB argument %zu",
+ syscall->loc, i);
}
- snprintf(out, SYSCALL_ARG_STR_LEN, "tcp->u_arg[%zu]", i);
+ return xasprintf("tcp->u_arg[%zu]", i);
}
/*
* Stores a string referring to the return value of the current syscall.
*/
-static void
-get_syscall_ret_value(char out[static SYSCALL_ARG_STR_LEN])
+static char *
+get_syscall_ret_value()
{
- snprintf(out, SYSCALL_ARG_STR_LEN, "tcp->u_rval");
+ return xstrdup("tcp->u_rval");
}
/*
@@ -208,22 +211,14 @@ type_to_ctype(const struct ast_type *type)
struct ast_node *def = symbol_get(type->name);
if (def != NULL && def->type == AST_STRUCT) {
- size_t len = sizeof("struct ") + strlen(type->name);
- char *ret = xmalloc(len);
- snprintf(ret, len, "struct %s", type->name);
- return ret;
+ return xasprintf("struct %s", type->name);
}
return type->name;
}
if (type->type == TYPE_PTR) {
- char *underlying = type_to_ctype(type->ptr.type);
-
- size_t len = strlen(underlying) + sizeof(" *");
- char *ret = xmalloc(len);
- snprintf(ret, len, "%s *", underlying);
- return ret;
+ return xasprintf("%s *", type_to_ctype(type->ptr.type));
}
if (type->type == TYPE_XORFLAGS) {
@@ -241,36 +236,27 @@ static char *
type_variable_declaration(const struct ast_type *type, const char *var_name) {
if (type->type == TYPE_BASIC && strcmp(type->name, "array") == 0) {
if (type->options != NULL && type->options->next != NULL) {
- struct ast_type_option *underlying_type = type->options->option;
- struct ast_type_option *member_count_type = type->options->next->option;
+ struct ast_type_option *underlying_type =
+ type->options->option;
+ struct ast_type_option *member_count_type =
+ type->options->next->option;
if (underlying_type->child_type == AST_TYPE_CHILD_TYPE &&
- member_count_type->child_type == AST_TYPE_CHILD_NUMBER) {
- char *underlying = type_to_ctype(underlying_type->type);
-
- size_t len = strlen(underlying) + sizeof("() [];") + strlen(var_name) + strlen(member_count_type->number.raw);
- char *ret = xmalloc(len);
- snprintf(ret, len, "%s %s[%s];", underlying, var_name, member_count_type->number.raw);
-
- return ret;
+ member_count_type->child_type == AST_TYPE_CHILD_NUMBER) {
+ return xasprintf("%s %s[%s];",
+ type_to_ctype(underlying_type->type),
+ var_name, member_count_type->number.raw);
}
}
}
- char *underlying = type_to_ctype(type);
-
- size_t len = strlen(underlying) + strlen(var_name) + sizeof(" ;");
- char *ret = xmalloc(len);
- snprintf(ret, len, "%s %s;", underlying, var_name);
-
- return ret;
+ return xasprintf("%s %s;", type_to_ctype(type), var_name);
}
/*
* Get flags to return from a SYS_FUNC.
*/
-static void
-get_sys_func_return_flags(char out[static SYSCALL_RET_FLAG_LEN], struct ast_type *type,
- bool is_ioctl)
+static char *
+get_sys_func_return_flags(struct ast_type *type, bool is_ioctl)
{
struct {
char *type;
@@ -297,9 +283,9 @@ get_sys_func_return_flags(char out[static SYSCALL_RET_FLAG_LEN], struct ast_type
}
if (following) {
- snprintf(out, SYSCALL_RET_FLAG_LEN, "%s | %s", base, following);
+ return xasprintf("%s | %s", base, following);
} else {
- snprintf(out, SYSCALL_RET_FLAG_LEN, "%s", base);
+ return xasprintf("%s", base);
}
}
@@ -313,47 +299,46 @@ get_sys_func_return_flags(char out[static SYSCALL_RET_FLAG_LEN], struct ast_type
* The specified type option MUST NOT be a range or a template id.
*/
static char *
-resolve_type_option_to_value(struct syscall *syscall, struct ast_type_option *option)
+resolve_type_option_to_value(struct syscall *syscall,
+ struct ast_type_option *option)
{
assert(option->child_type != AST_TYPE_CHILD_RANGE &&
- option->child_type != AST_TYPE_CHILD_TEMPLATE_ID);
+ option->child_type != AST_TYPE_CHILD_TEMPLATE_ID);
if (option->child_type == AST_TYPE_CHILD_NUMBER) {
- // return the number exactly as specified in the source file
+ /* return the number exactly as specified in the source file */
return option->number.raw;
} else if (option->child_type == AST_TYPE_CHILD_TYPE) {
if (option->type->type == TYPE_REF) {
- // identify which argument is being referred to
+ /* identify which argument is being referred to */
- // syscall return value
+ /* syscall return value */
if (option->type->ref.return_value) {
- char *ret = xmalloc(SYSCALL_ARG_STR_LEN);
- get_syscall_ret_value(ret);
- return ret;
+ return get_syscall_ret_value();
}
- // find syscall argument by name
+ /* find syscall argument by name */
bool found = false;
size_t index = 0;
for (; index < syscall->arg_count; ++index) {
- if (strcmp(option->type->ref.argname, syscall->args[index].name) == 0) {
+ if (strcmp(option->type->ref.argname,
+ syscall->args[index].name) == 0) {
found = true;
break;
}
}
if (found) {
- char *ret = xmalloc(SYSCALL_ARG_STR_LEN);
- get_syscall_arg_value(ret, syscall, index);
- return ret;
+ return get_syscall_arg_value(syscall, index);
}
- log_warning("Failed to resolve 'ref' type with value \"%s\" to argument",
- syscall->loc, option->type->ref.argname);
+ log_warning("Failed to resolve 'ref' type"
+ " with value \"%s\" to argument",
+ syscall->loc, option->type->ref.argname);
return "#error FAILED TO RESOLVE REF TYPE TO VALUE";
} else {
- // assume the given value is a constant or from a #define
+ /* assume the given value is a constant or from a #define */
return option->type->name;
}
}
@@ -387,29 +372,27 @@ store_single_value(FILE *out, struct ast_type *type, char *arg, int indent_level
static void
generate_printer(FILE *out, struct syscall *syscall, const char *argname,
- const char *arg, bool entering,
- struct ast_type *type, int indent_level);
+ const char *arg, bool entering,
+ struct ast_type *type, int indent_level);
static void
generate_printer_ptr(FILE *out, struct syscall *syscall, const char *argname,
- const char *arg, bool entering,
- struct ast_type *type, int indent_level)
+ const char *arg, bool entering,
+ struct ast_type *type, int indent_level)
{
- struct ast_type *underlying = type->ptr.type;
-
- // copy from target memory and use decoder for resulting value
- char var_name[32];
- snprintf(var_name, 32, "tmpvar_%s", argname);
-
+ /* copy from target memory and use decoder for resulting value */
if ((IS_IN_PTR(type) && entering) || (IS_OUT_PTR(type) && !entering)) {
- OUTFI("%s\n", type_variable_declaration(type->ptr.type, var_name));
+ CLEANUP_FREE char *var_name =
+ xasprintf("tmpvar_%s", argname);
+ OUTFI("%s\n",
+ type_variable_declaration(type->ptr.type, var_name));
OUTFI("if (!umove_or_printaddr(tcp, %s, &%s)) {\n",
- arg, var_name);
+ arg, var_name);
indent_level++;
OUTFI("tprint_indirect_begin();\n");
generate_printer(out, syscall, argname, var_name, entering,
- type->ptr.type, indent_level);
+ type->ptr.type, indent_level);
OUTFI("tprint_indirect_end();\n");
indent_level--;
@@ -419,8 +402,8 @@ generate_printer_ptr(FILE *out, struct syscall *syscall, const char *argname,
static void
generate_templated_printer(FILE *out, struct syscall *syscall,
- const char *arg, struct ast_type *arg_type,
- struct decoder templated_decoder)
+ const char *arg, struct ast_type *arg_type,
+ struct decoder templated_decoder)
{
struct {
char *value;
@@ -428,7 +411,7 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
} substitutions[256];
int subs_pos = 0;
- // Do a DFS over the template type to find substitution markers
+ /* Do a DFS over the template type to find substitution markers. */
struct dfs_stack_entry {
struct ast_type *template;
struct ast_type *actual;
@@ -455,23 +438,31 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
continue;
}
- struct ast_type_option_list *template_option = entry.template->options;
- struct ast_type_option_list *actual_option = entry.actual->options;
+ struct ast_type_option_list *template_option =
+ entry.template->options;
+ struct ast_type_option_list *actual_option =
+ entry.actual->options;
for (; actual_option != NULL && template_option != NULL;
- actual_option = actual_option->next, template_option = template_option->next) {
- if (template_option->option->child_type == AST_TYPE_CHILD_TEMPLATE_ID) {
- substitutions[subs_pos].value = resolve_type_option_to_value(syscall,
- actual_option->option);
- substitutions[subs_pos].template_id = template_option->option->template.id;
+ actual_option = actual_option->next,
+ template_option = template_option->next) {
+ if (template_option->option->child_type ==
+ AST_TYPE_CHILD_TEMPLATE_ID) {
+ substitutions[subs_pos].value =
+ resolve_type_option_to_value(syscall,
+ actual_option->option);
+ substitutions[subs_pos].template_id =
+ template_option->option->template.id;
subs_pos++;
continue;
}
- if (actual_option->option->child_type != template_option->option->child_type) {
+ if (actual_option->option->child_type !=
+ template_option->option->child_type) {
break;
}
- if (template_option->option->child_type == AST_TYPE_CHILD_TYPE) {
+ if (template_option->option->child_type ==
+ AST_TYPE_CHILD_TYPE) {
dfs_stack[stack_ptr] = (struct dfs_stack_entry) {
.template = template_option->option->type,
.actual = actual_option->option->type
@@ -481,7 +472,10 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
}
}
- // Output the template string and replace substitution markers with real values
+ /*
+ * Output the template string and replace substitution markers
+ * with real values.
+ */
const char *template = templated_decoder.fmt_string;
size_t template_len = strlen(template);
@@ -513,7 +507,7 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
in_template_number = false;
int found = -1;
- // find matching substitution
+ /* find matching substitution */
for (int j = 0; j < subs_pos; ++j) {
if (substitutions[j].template_id == cur) {
found = j;
@@ -522,8 +516,9 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
}
if (found == -1) {
- log_warning("Template variable $%" PRIdMAX " could not be resolved!",
- syscall->loc, cur);
+ log_warning("Template variable $%" PRIdMAX
+ " could not be resolved!",
+ syscall->loc, cur);
continue;
}
@@ -541,14 +536,18 @@ generate_templated_printer(FILE *out, struct syscall *syscall,
*/
static void
generate_printer(FILE *out, struct syscall *syscall,
- const char *argname, const char *arg, bool entering,
- struct ast_type *type, int indent_level)
+ const char *argname, const char *arg, bool entering,
+ struct ast_type *type, int indent_level)
{
- for (struct decoder_list *cur = decoders; cur != NULL; cur = cur->next) {
+ for (struct decoder_list *cur = decoders;
+ cur != NULL; cur = cur->next) {
if (ast_type_matching(cur->decoder.matching_type, type)) {
- OUTFI("/* using decoder from %s:%d:%d */\n", cur->decoder.loc.file,
- cur->decoder.loc.lineno, cur->decoder.loc.colno);
- generate_templated_printer(out, syscall, arg, type, cur->decoder);
+ OUTFI("/* using decoder from %s:%d:%d */\n",
+ cur->decoder.loc.file,
+ cur->decoder.loc.lineno,
+ cur->decoder.loc.colno);
+ generate_templated_printer(out, syscall, arg, type,
+ cur->decoder);
OUTC('\n');
return;
}
@@ -556,38 +555,51 @@ generate_printer(FILE *out, struct syscall *syscall,
if (type->type == TYPE_BASIC) {
if (is_signed_integer_typename(type->name)) {
- OUTFI("PRINT_VAL_D((%s) %s);\n", type_to_ctype(type), arg);
+ OUTFI("PRINT_VAL_D((%s) %s);\n",
+ type_to_ctype(type), arg);
return;
} else if (is_unsigned_integer_typename(type->name)) {
- OUTFI("PRINT_VAL_U((%s) %s);\n", type_to_ctype(type), arg);
+ OUTFI("PRINT_VAL_U((%s) %s);\n",
+ type_to_ctype(type), arg);
return;
}
- log_warning("No known printer for basic type %s", syscall->loc, type->name);
- outf_indent(indent_level, out, "#error UNHANDLED BASIC TYPE: %s\n", type->name);
+ log_warning("No known printer for basic type %s",
+ syscall->loc, type->name);
+ outf_indent(indent_level, out,
+ "#error UNHANDLED BASIC TYPE: %s\n", type->name);
} else if (type->type == TYPE_PTR) {
- generate_printer_ptr(out, syscall, argname, arg, entering, type, indent_level);
+ generate_printer_ptr(out, syscall, argname, arg, entering, type,
+ indent_level);
} else if (type->type == TYPE_ORFLAGS) {
- OUTFI("printflags(%s, %s, \"%s\");\n", type->orflags.flag_type->type->name, arg,
- type->orflags.dflt);
+ OUTFI("printflags(%s, %s, \"%s\");\n",
+ type->orflags.flag_type->type->name, arg,
+ type->orflags.dflt);
} else if (type->type == TYPE_XORFLAGS) {
- OUTFI("printxval(%s, %s, \"%s\");\n", type->xorflags.flag_type->type->name, arg,
- type->xorflags.dflt);
- } else if (strcmp(type->name, "stringnoz") == 0 || strcmp(type->name, "string") == 0) {
- log_warning("Type '%s' should be wrapped in a ptr type to indicate direction",
- syscall->loc, type->name);
+ OUTFI("printxval(%s, %s, \"%s\");\n",
+ type->xorflags.flag_type->type->name, arg,
+ type->xorflags.dflt);
+ } else if (strcmp(type->name, "stringnoz") == 0 ||
+ strcmp(type->name, "string") == 0) {
+ log_warning("Type '%s' should be wrapped in a ptr type"
+ " to indicate direction",
+ syscall->loc, type->name);
} else if (type->type == TYPE_CONST) {
if (!type->constt.real_type) {
- log_warning("Const type (%s) has no matching parent syscall argument.", syscall->loc,
- argname);
+ log_warning("Const type (%s) has no matching"
+ " parent syscall argument.",
+ syscall->loc, argname);
return;
}
- OUTFI("/* inherited parent type (%s) */\n", type_to_ctype(type->constt.real_type));
+ OUTFI("/* inherited parent type (%s) */\n",
+ type_to_ctype(type->constt.real_type));
generate_printer(out, syscall, argname, arg, entering,
- type->constt.real_type, indent_level);
+ type->constt.real_type, indent_level);
} else {
- log_warning("Type '%s' is currently unhandled", syscall->loc, type->name);
- outf_indent(indent_level, out, "#error UNHANDLED TYPE: %s\n", type->name);
+ log_warning("Type '%s' is currently unhandled",
+ syscall->loc, type->name);
+ outf_indent(indent_level, out,
+ "#error UNHANDLED TYPE: %s\n", type->name);
}
}
@@ -596,16 +608,18 @@ generate_return_flags(FILE *out, struct syscall *syscall, int indent_level)
{
struct ast_type ret = syscall->ret;
if (ret.type == TYPE_ORFLAGS) {
- OUTFI("tcp->auxstr = sprintflags(\"%s\", %s, (kernel_ulong_t) tcp->u_rval);\n",
- ret.orflags.dflt, ret.orflags.flag_type->type->name);
+ OUTFI("tcp->auxstr = sprintflags(\"%s\", %s"
+ ", (kernel_ulong_t) tcp->u_rval);\n",
+ ret.orflags.dflt, ret.orflags.flag_type->type->name);
OUTFI("return RVAL_STR;\n");
} else if (ret.type == TYPE_XORFLAGS) {
- OUTFI("tcp->auxstr = xlookup(%s, (kernel_ulong_t) tcp->u_rval);\n",
- ret.xorflags.flag_type->type->name);
+ OUTFI("tcp->auxstr = xlookup(%s"
+ ", (kernel_ulong_t) tcp->u_rval);\n",
+ ret.xorflags.flag_type->type->name);
OUTFI("return RVAL_STR;\n");
} else {
- char flags[SYSCALL_RET_FLAG_LEN];
- get_sys_func_return_flags(flags, &ret, syscall->is_ioctl);
+ CLEANUP_FREE char *flags =
+ get_sys_func_return_flags(&ret, syscall->is_ioctl);
OUTFI("return %s;\n", flags);
}
}
@@ -617,18 +631,17 @@ generate_return_flags(FILE *out, struct syscall *syscall, int indent_level)
* The is_leaf parameter should be set if corresponding syscall is a leaf node,
* i.e. has no sub syscalls.
*/
-static void
-get_variant_function_name(char out[static VARIANT_FUNC_NAME_LEN], char *variant_name, bool is_leaf)
+static char *
+get_variant_function_name(char *variant_name, bool is_leaf)
{
- snprintf(out, VARIANT_FUNC_NAME_LEN, "var_%s%s", is_leaf ? "leaf_" : "", variant_name);
- for (int i = 0; i < VARIANT_FUNC_NAME_LEN; ++i) {
- if (out[i] == '\0') {
- break;
- }
- if (out[i] == '$') {
- out[i] = '_';
+ char *out = xasprintf("var_%s%s",
+ is_leaf ? "leaf_" : "", variant_name);
+ for (char *p = out; *p; ++p) {
+ if (*p == '$') {
+ *p = '_';
}
}
+ return out;
}
/*
@@ -665,22 +678,23 @@ out_statement_condition_end(FILE *out, struct statement_condition *condition)
}
}
-static void
-get_decoder_prototype(char out[static DECODER_PROTOTYPE_LEN], bool internal,
- struct syscall *syscall, char *func_name)
+static char *
+get_decoder_prototype(bool internal, struct syscall *syscall, char *func_name)
{
- snprintf(out, DECODER_PROTOTYPE_LEN, "%sint\n"
- "%s(struct tcb *tcp%s)\n",
+ return xasprintf("%sint\n"
+ "%s(struct tcb *tcp%s)\n",
internal ? "static " : "",
func_name,
- syscall->is_ioctl ? ", unsigned int code, kernel_ulong_t arg" : "");
+ syscall->is_ioctl ?
+ ", unsigned int code, kernel_ulong_t arg" : "");
}
/*
* Prints out a decoder for the given system call.
*/
static void
-generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl_fallback)
+generate_decoder(FILE *out, struct syscall *syscall, bool is_variant,
+ bool ioctl_fallback)
{
int indent_level = 0;
@@ -690,12 +704,15 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
int arg_index = 0;
if (syscall->is_ioctl) {
- // no need to decode code, or arg for ioctl variant syscalls
+ /* no need to decode code, or arg for ioctl variant syscalls */
arg_offset = 2;
arg_index = 2;
}
- // determine which strategy to use depending on how many OUT ptrs there are
+ /*
+ * Determine which strategy to use depending on
+ * how many OUT ptrs there are.
+ */
size_t out_ptrs = 0;
for (size_t i = arg_offset; i < syscall->arg_count; i++) {
if (IS_OUT_PTR(syscall->args[i].type)) {
@@ -703,14 +720,12 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
}
}
- // output function declaration
+ /* output function declaration */
if (is_variant) {
- char func_name[VARIANT_FUNC_NAME_LEN];
- get_variant_function_name(func_name, syscall->name, true);
-
- char decoder_prototype[DECODER_PROTOTYPE_LEN];
- get_decoder_prototype(decoder_prototype, true, syscall, func_name);
-
+ CLEANUP_FREE char *func_name =
+ get_variant_function_name(syscall->name, true);
+ CLEANUP_FREE char *decoder_prototype =
+ get_decoder_prototype(true, syscall, func_name);
OUTSI(decoder_prototype);
} else {
OUTFI("SYS_FUNC(%s)\n", syscall->name);
@@ -725,21 +740,20 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
return;
}
- char arg_val[SYSCALL_ARG_STR_LEN];
-
if (out_ptrs == 0) {
if (syscall->is_ioctl) {
OUTFI("tprint_arg_next();\n");
}
- // 0 out ptrs: print all args in sysenter
+ /* 0 out ptrs: print all args in sysenter */
for (size_t i = arg_offset; i < syscall->arg_count; i++) {
struct syscall_argument arg = syscall->args[i];
- OUTFI("/* arg: %s (%s) */\n", arg.name, type_to_ctype(arg.type));
- get_syscall_arg_value(arg_val, syscall, arg_index++);
-
- generate_printer(out, syscall, arg.name, arg_val, true, arg.type,
- indent_level);
+ OUTFI("/* arg: %s (%s) */\n",
+ arg.name, type_to_ctype(arg.type));
+ CLEANUP_FREE char *arg_val =
+ get_syscall_arg_value(syscall, arg_index++);
+ generate_printer(out, syscall, arg.name, arg_val, true,
+ arg.type, indent_level);
if (i < syscall->arg_count - 1) {
OUTSI("tprint_arg_next();\n");
@@ -747,7 +761,10 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
OUTC('\n');
}
} else if (out_ptrs == 1) {
- // == 1 out ptrs: print args until the out ptr in sysenter, rest in sysexit
+ /*
+ * == 1 out ptrs: print args until the out ptr in sysenter,
+ * rest in sysexit
+ */
size_t cur = arg_offset;
OUTSI("if (entering(tcp)) {\n");
@@ -763,43 +780,54 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
break;
}
- OUTFI("/* arg: %s (%s) */\n", arg.name, type_to_ctype(arg.type));
- get_syscall_arg_value(arg_val, syscall, arg_index++);
-
- generate_printer(out, syscall, arg.name, arg_val, true, arg.type,
- indent_level);
+ OUTFI("/* arg: %s (%s) */\n",
+ arg.name, type_to_ctype(arg.type));
+ CLEANUP_FREE char *arg_val =
+ get_syscall_arg_value(syscall, arg_index++);
+ generate_printer(out, syscall, arg.name, arg_val, true,
+ arg.type, indent_level);
if (cur < syscall->arg_count - 1) {
OUTSI("tprint_arg_next();\n\n");
}
}
- if (cur < syscall->arg_count && IS_INOUT_PTR(syscall->args[cur].type)) {
- get_syscall_arg_value(arg_val, syscall, cur);
- store_single_value(out, syscall->args[cur].type, arg_val, indent_level);
+ if (cur < syscall->arg_count &&
+ IS_INOUT_PTR(syscall->args[cur].type)) {
+ CLEANUP_FREE char *arg_val =
+ get_syscall_arg_value(syscall, cur);
+ store_single_value(out, syscall->args[cur].type,
+ arg_val, indent_level);
}
OUTSI("return 0;\n");
indent_level--;
OUTSI("}\n");
- if (cur < syscall->arg_count && IS_INOUT_PTR(syscall->args[cur].type)) {
- // TODO: compare the current value with the previous value
- // and print only if changed
+ if (cur < syscall->arg_count &&
+ IS_INOUT_PTR(syscall->args[cur].type)) {
+ /*
+ * TODO:
+ * Compare the current value with the previous value
+ * and print only if changed.
+ */
}
for (; cur < syscall->arg_count; ++cur) {
struct syscall_argument arg = syscall->args[cur];
- OUTFI("/* arg: %s (%s) */\n", arg.name, type_to_ctype(arg.type));
- get_syscall_arg_value(arg_val, syscall, arg_index++);
+ OUTFI("/* arg: %s (%s) */\n",
+ arg.name, type_to_ctype(arg.type));
+ CLEANUP_FREE char *arg_val =
+ get_syscall_arg_value(syscall, arg_index++);
if (IS_INOUT_PTR(syscall->args[cur].type)) {
- generate_printer(out, syscall, arg.name, "get_tcb_priv_data(tcp)", false, arg.type,
- indent_level);
+ generate_printer(out, syscall, arg.name,
+ "get_tcb_priv_data(tcp)",
+ false, arg.type, indent_level);
}
- generate_printer(out, syscall, arg.name, arg_val, false, arg.type,
- indent_level);
+ generate_printer(out, syscall, arg.name, arg_val,
+ false, arg.type, indent_level);
if (cur < syscall->arg_count - 1) {
OUTSI("tprint_arg_next();\n");
@@ -807,7 +835,11 @@ generate_decoder(FILE *out, struct syscall *syscall, bool is_variant, bool ioctl
OUTC('\n');
}
} else {
- // TODO: > 1 out ptrs; store necessary ptr values using set_tcb_priv_data
+ /*
+ * TODO
+ * > 1 out ptrs;
+ * store necessary ptr values using set_tcb_priv_data
+ */
OUTSI("#error TODO\n");
}
@@ -838,24 +870,23 @@ output_defines(FILE *out, struct preprocessor_statement_list *defines)
* Outputs a function which delegates to the child syscalls based on the
* values of the child's const-typed arguments.
*
- * The is_variant flag indicates whether the group's base syscall is a child of
- * a variant syscall itself.
+ * The is_variant flag indicates whether the group's base syscall is a child
+ * of a variant syscall itself.
*/
void
-output_variant_syscall_group(FILE *out, struct syscall_group *group, bool is_variant)
+output_variant_syscall_group(FILE *out, struct syscall_group *group,
+ bool is_variant)
{
int indent_level = 0;
if (is_variant) {
- // variant system call
- char func_name[VARIANT_FUNC_NAME_LEN];
- get_variant_function_name(func_name, group->base->name, false);
-
- char decoder_prototype[DECODER_PROTOTYPE_LEN];
- get_decoder_prototype(decoder_prototype, false, group->base, func_name);
-
+ /* variant system call */
+ CLEANUP_FREE char *func_name =
+ get_variant_function_name(group->base->name, false);
+ CLEANUP_FREE char *decoder_prototype =
+ get_decoder_prototype(false, group->base, func_name);
OUTSI(decoder_prototype);
} else {
- // base system call
+ /* base system call */
OUTFI("SYS_FUNC(%s) {\n", group->base->name);
}
OUTSI("{\n");
@@ -871,7 +902,8 @@ output_variant_syscall_group(FILE *out, struct syscall_group *group, bool is_var
OUTS("if (");
bool first = true;
- for (size_t arg_idx = 0; arg_idx < cur_child->arg_count; ++arg_idx) {
+ for (size_t arg_idx = 0;
+ arg_idx < cur_child->arg_count; ++arg_idx) {
struct syscall_argument arg = cur_child->args[arg_idx];
if (arg.type->type != TYPE_CONST) {
@@ -884,28 +916,35 @@ output_variant_syscall_group(FILE *out, struct syscall_group *group, bool is_var
OUTS(" && ");
}
- char arg_str[SYSCALL_ARG_STR_LEN];
- get_syscall_arg_value(arg_str, cur_child, arg_idx);
-
- if (arg.type->constt.value->child_type == AST_TYPE_CHILD_RANGE) {
- OUTF("((%s) <= (%s) && (%s) <= (%s))", arg_str,
- resolve_type_option_to_value(cur_child, arg.type->constt.value->range.min),
- arg_str,
- resolve_type_option_to_value(cur_child, arg.type->constt.value->range.max)
+ CLEANUP_FREE char *arg_str =
+ get_syscall_arg_value(cur_child, arg_idx);
+
+ if (arg.type->constt.value->child_type ==
+ AST_TYPE_CHILD_RANGE) {
+ OUTF("((%s) <= (%s) && (%s) <= (%s))",
+ arg_str,
+ resolve_type_option_to_value(cur_child,
+ arg.type->constt.value->range.min),
+ arg_str,
+ resolve_type_option_to_value(cur_child,
+ arg.type->constt.value->range.max)
);
} else {
OUTF("(%s) == (%s)",
- arg_str,
- resolve_type_option_to_value(cur_child, arg.type->constt.value));
+ arg_str,
+ resolve_type_option_to_value(cur_child,
+ arg.type->constt.value));
}
}
OUTS(") {\n");
indent_level++;
- char func_name[VARIANT_FUNC_NAME_LEN];
- get_variant_function_name(func_name, cur_child->name, cur_child_grp->child_count == 0);
- OUTFI("return %s(tcp%s);\n", func_name, cur_child->is_ioctl ? ", code, arg" : "");
+ CLEANUP_FREE char *func_name =
+ get_variant_function_name(cur_child->name,
+ cur_child_grp->child_count == 0);
+ OUTFI("return %s(tcp%s);\n", func_name,
+ cur_child->is_ioctl ? ", code, arg" : "");
indent_level--;
OUTSI("} else ");
@@ -914,9 +953,10 @@ output_variant_syscall_group(FILE *out, struct syscall_group *group, bool is_var
OUTS("{\n");
indent_level++;
- char func_name[VARIANT_FUNC_NAME_LEN];
- get_variant_function_name(func_name, group->base->name, true);
- OUTFI("return %s(tcp%s);\n", func_name, group->base->is_ioctl ? ", code, arg" : "");
+ CLEANUP_FREE char *func_name =
+ get_variant_function_name(group->base->name, true);
+ OUTFI("return %s(tcp%s);\n", func_name,
+ group->base->is_ioctl ? ", code, arg" : "");
indent_level--;
OUTSI("}\n");
@@ -930,43 +970,56 @@ output_variant_syscall_group(FILE *out, struct syscall_group *group, bool is_var
*/
void
output_syscall_groups(FILE *out, struct syscall_group *groups,
- size_t group_count, struct syscall_group *parent)
+ size_t group_count, struct syscall_group *parent)
{
for (size_t i = 0; i < group_count; ++i) {
struct syscall_group *cur = &groups[i];
if (parent) {
- // store the real type of const parameters based on their parent
- for (size_t j = 0; j < cur->base->arg_count && j < parent->base->arg_count; ++j) {
- struct syscall_argument *cur_arg = &cur->base->args[j];
- struct syscall_argument *parent_arg = &parent->base->args[j];
+ /*
+ * Store the real type of const parameters
+ * based on their parent.
+ */
+ for (size_t j = 0;
+ j < cur->base->arg_count && j < parent->base->arg_count;
+ ++j) {
+ struct syscall_argument *cur_arg =
+ &cur->base->args[j];
+ struct syscall_argument *parent_arg =
+ &parent->base->args[j];
if (cur_arg->type->type == TYPE_CONST) {
if (parent_arg->type->type == TYPE_CONST) {
- cur_arg->type->constt.real_type = parent_arg->type->constt.real_type;
+ cur_arg->type->constt.real_type =
+ parent_arg->type->constt.real_type;
} else {
- cur_arg->type->constt.real_type = parent_arg->type;
+ cur_arg->type->constt.real_type =
+ parent_arg->type;
}
}
}
}
if (groups[i].child_count == 0) {
- generate_decoder(out, groups[i].base, parent != NULL, false);
+ generate_decoder(out, groups[i].base, parent != NULL,
+ false);
continue;
}
- output_syscall_groups(out, groups[i].children, groups[i].child_count, &groups[i]);
+ output_syscall_groups(out, groups[i].children,
+ groups[i].child_count, &groups[i]);
if (strcmp(groups[i].base->name, "ioctl") != 0) {
generate_decoder(out, groups[i].base, true, true);
- output_variant_syscall_group(out, &groups[i], parent != NULL);
+ output_variant_syscall_group(out, &groups[i],
+ parent != NULL);
}
}
}
bool
-generate_code(const char *in_filename, const char *out_filename, struct processed_ast *ast)
+generate_code(const char *in_filename, const char *out_filename,
+ struct processed_ast *ast)
{
FILE *out = fopen(out_filename, "w");
@@ -974,7 +1027,8 @@ generate_code(const char *in_filename, const char *out_filename, struct processe
return false;
}
- outf(out, "/* Generated by ./maint/gen/generate.sh from ./maint/gen/%s; do not edit. */\n\n", in_filename);
+ outf(out, "/* Generated by ./maint/gen/generate.sh"
+ " from ./maint/gen/%s; do not edit. */\n\n", in_filename);
outf(out, "%s",
"#include <stddef.h>\n"
"#include \"generated.h\"\n\n"
@@ -984,7 +1038,8 @@ generate_code(const char *in_filename, const char *out_filename, struct processe
decoders = ast->decoders;
output_defines(out, ast->preprocessor_stmts);
- output_syscall_groups(out, ast->syscall_groups, ast->syscall_group_count, NULL);
+ output_syscall_groups(out, ast->syscall_groups,
+ ast->syscall_group_count, NULL);
fclose(out);
diff --git a/maint/gen/deflang.h b/maint/gen/deflang.h
index 260b58260..6b99e9c96 100644
--- a/maint/gen/deflang.h
+++ b/maint/gen/deflang.h
@@ -1,29 +1,33 @@
-#include <stdbool.h>
-#include <stdio.h>
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
-#include "ast.h"
-#include "preprocess.h"
+#ifndef DEFLANG_H
+# define DEFLANG_H
+
+# include <stdbool.h>
+# include <stdio.h>
+
+# include "preprocess.h"
+# include "xmalloc.h"
-extern int yylineno;
extern FILE *yyin;
extern int last_line_location;
extern char *cur_filename;
-void *
-xmalloc(size_t n);
-
-void *
-xcalloc(size_t n);
-
-extern int
-yylex_destroy(void);
-
bool
lexer_init_newfile(char *filename);
void
-yyerror(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
+yyerror(const char *s, ...) ATTRIBUTE_FORMAT((printf, 1, 2));
bool
-generate_code(const char *in_filename, const char *out_filename, struct processed_ast *ast); \ No newline at end of file
+generate_code(const char *in_filename, const char *out_filename,
+ struct processed_ast *ast);
+
+#endif /* DEFLANG_H */
diff --git a/maint/gen/defs/common.def b/maint/gen/defs/common.def
index 5c1b5c396..2cffce7e6 100644
--- a/maint/gen/defs/common.def
+++ b/maint/gen/defs/common.def
@@ -1,3 +1,11 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
:fd %{ printfd(tcp, $$); %}
:uid %{ printuid($$); %}
:gid %{ printuid($$); %}
@@ -36,7 +44,8 @@
:ptr[in, array[uint32_t, $1]] %{
{
uint32_t int_buffer;
- print_array(tcp, $$, $1, &int_buffer, sizeof(int_buffer), tfetch_mem, print_uint_array_member, 0);
+ print_array(tcp, $$, $1, &int_buffer, sizeof(int_buffer),
+ tfetch_mem, print_uint_array_member, 0);
}
%}
diff --git a/maint/gen/lex.l b/maint/gen/lex.l
index 3e25a6145..22baca995 100644
--- a/maint/gen/lex.l
+++ b/maint/gen/lex.l
@@ -1,5 +1,12 @@
-%option noyywrap yylineno nodefault warn
-/* %option debug */
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+%option noyywrap nounput yylineno warn
%{
#include <stdio.h>
@@ -8,9 +15,6 @@
#include "ast.h"
#include "parse.tab.h"
-YYSTYPE yylval;
-YYLTYPE yylloc;
-
static void
update_yylloc();
@@ -25,9 +29,9 @@ struct saved_import_state {
int last_line_location;
};
-// a stack to store state before an import
+/* a stack to store state before an import */
static struct saved_import_state import_states[MAX_IMPORT_LEVEL];
-// the current index into import_states
+/* the current index into import_states */
static int import_level = 0;
char *cur_filename;
@@ -53,13 +57,13 @@ int last_line_location;
":" return T_COLON;
(-)?"0x"[0-9A-Fa-f]+ {
- yylval.number.raw = strdup(yytext);
+ yylval.number.raw = xstrdup(yytext);
yylval.number.val = strtol(yytext, NULL, 16);
return T_NUMBER;
}
(-)?[0-9]+ {
- yylval.number.raw = strdup(yytext);
+ yylval.number.raw = xstrdup(yytext);
yylval.number.val = strtol(yytext, NULL, 10);
return T_NUMBER;
}
@@ -68,14 +72,14 @@ int last_line_location;
int sign = (yytext[0] == '-') ? -1 : +1;
int offset = ((sign == -1) ? sizeof("-0b") : sizeof("0b")) - 1;
- // binary literals are supported in C by GNU extension
- yylval.number.raw = strdup(yytext);
+ /* binary literals are supported in C by GNU extension */
+ yylval.number.raw = xstrdup(yytext);
yylval.number.val = sign * strtol(yytext + offset, NULL, 2);
return T_NUMBER;
}
\'.\' {
- yylval.number.raw = strdup(yytext);
+ yylval.number.raw = xstrdup(yytext);
yylval.number.val = yytext[1];
return T_NUMBER;
}
@@ -91,31 +95,31 @@ int last_line_location;
yyerror("@ can only be used in @ret");
yyterminate();
}
- yylval.str = strdup(yytext);
+ yylval.str = xstrdup(yytext);
return T_IDENTIFIER;
}
(?x: "%{" ( [^%] | %+ [^}] )* %* "%}" ) {
- yylval.str = strdup(yytext + 2);
+ yylval.str = xstrdup(yytext + 2);
yylval.str[strlen(yylval.str) - 2] ='\0';
return T_DECODER_SOURCE;
}
"define".+ {
- yylval.str = strdup(yytext);
+ yylval.str = xstrdup(yytext);
return T_DEFINE;
}
"#ifdef".+ {
- yylval.str = strdup(yytext);
+ yylval.str = xstrdup(yytext);
return T_IFDEF;
}
"#ifndef".+ {
- yylval.str = strdup(yytext);
+ yylval.str = xstrdup(yytext);
return T_IFNDEF;
}
"include".+ {
- yylval.str = strdup(yytext);
+ yylval.str = xstrdup(yytext);
return T_INCLUDE;
}
"#endif".* {
@@ -127,23 +131,24 @@ int last_line_location;
}
<IMPORT>[^\n\"]+ {
if (import_level >= MAX_IMPORT_LEVEL) {
- fprintf(stderr, "imports are nested more than %d levels\n", MAX_IMPORT_LEVEL);
+ fprintf(stderr, "imports are nested more than %d levels\n",
+ MAX_IMPORT_LEVEL);
yyterminate();
}
- // eat characters until newline
+ /* eat characters until newline */
int c = input();
cur_location++;
while(c && c != '\n'){
cur_location++;
c = input();
}
- // update current location
+ /* update current location */
yylloc.last_line++;
yylloc.last_column = 1;
last_line_location = cur_location;
- // save current state
+ /* save current state */
import_states[import_level++] = (struct saved_import_state) {
.filename = cur_filename,
.location = yylloc,
@@ -151,7 +156,7 @@ int last_line_location;
.last_line_location = last_line_location
};
- cur_filename = strdup(yytext);
+ cur_filename = xstrdup(yytext);
yylloc = (struct YYLTYPE) {1, 1, 1, 1};
cur_location = 0;
@@ -160,7 +165,8 @@ int last_line_location;
yyin = fopen(yytext, "r");
if (yyin == NULL) {
- fprintf(stderr, "failed to import file '%s' on line %d\n", yytext, yylineno);
+ fprintf(stderr, "failed to import file '%s' on line %d\n",
+ yytext, yylineno);
yyterminate();
}
@@ -169,8 +175,10 @@ int last_line_location;
}
<<EOF>> {
- // emit a newline at the end of a file before EOF
- // to ensure the last statement in the file is terminated
+ /*
+ * Emit a newline at the end of a file before EOF
+ * to ensure the last statement in the file is terminated.
+ */
static int emitted_newline;
if (!emitted_newline) {
@@ -248,7 +256,7 @@ update_yylloc()
bool
lexer_init_newfile(char *filename)
{
- // clean up internal state managed by flex
+ /* clean up internal state managed by flex */
yylex_destroy();
yyin = fopen(filename, "r");
diff --git a/maint/gen/parse.y b/maint/gen/parse.y
index 23b773153..11e0830aa 100644
--- a/maint/gen/parse.y
+++ b/maint/gen/parse.y
@@ -1,3 +1,11 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
%define api.token.prefix {T_}
%define parse.lac full
%define parse.error detailed
@@ -20,6 +28,8 @@
static struct ast_node *root;
static void error_prev_decl(char *identifier, struct ast_node *prev);
+
+int yylex(void);
%}
%union {
@@ -317,49 +327,53 @@ flag_elements: IDENTIFIER "," flag_elements
static void error_prev_decl(char *identifier, struct ast_node *prev)
{
- yyerror("Previous declaration of %s at line %d col %d", identifier,
- prev->loc.lineno, prev->loc.colno);
+ yyerror("Previous declaration of %s at line %d col %d",
+ identifier, prev->loc.lineno, prev->loc.colno);
}
void
-yyerror (const char* fmt, ...)
+yyerror(const char* fmt, ...)
{
- char buffer[257] = {0};
-
- if (yyin == NULL) {
- return;
- }
-
- long int saved = ftell(yyin);
- fseek(yyin, last_line_location, SEEK_SET);
- fgets(buffer, 256, yyin);
- fseek(yyin, saved, SEEK_SET);
-
- // add a new line if necessary
- size_t len = strlen(buffer);
- if (len > 0 && buffer[len - 1] != '\n') {
- buffer[len] = '\n';
- buffer[len + 1] = '\0';
+ fprintf(stderr, "error %d: %s: line %d column %d\n",
+ yynerrs, cur_filename, yylloc.first_line, yylloc.first_column);
+ if (yyin) {
+ char buffer[257];
+ long int saved = ftell(yyin);
+ if (saved == -1 ||
+ fseek(yyin, last_line_location, SEEK_SET) != 0 ||
+ fgets(buffer, sizeof(buffer) - 1, yyin) == NULL) {
+ buffer[0] = '\0';
+ }
+ if (saved != -1) {
+ fseek(yyin, saved, SEEK_SET);
+ }
+
+ /* add a new line if necessary */
+ size_t len = strlen(buffer);
+ if (len > 0) {
+ if (buffer[len - 1] != '\n') {
+ buffer[len] = '\n';
+ buffer[len + 1] = '\0';
+ }
+ fprintf(stderr, "\t%s", buffer);
+ }
}
+ fprintf(stderr, "\t%*s ", yylloc.first_column, "^");
va_list args;
va_start(args, fmt);
-
- fprintf(stderr, "error %d: %s: line %d column %d\n", yynerrs, cur_filename,
- yylloc.first_line, yylloc.first_column);
- fprintf(stderr, "\t%s", buffer);
- fprintf(stderr, "\t%*s ", yylloc.first_column, "^");
vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
-
va_end(args);
+
+ fprintf(stderr, "\n");
}
int
main(int argc, char **argv)
{
if (argc < 3) {
- fprintf(stderr, "Usage: %s [input file] [output file]\n", argv[0]);
+ fprintf(stderr, "Usage: %s [input file] [output file]\n",
+ argv[0]);
return EXIT_FAILURE;
}
diff --git a/maint/gen/preprocess.c b/maint/gen/preprocess.c
index 333b56293..211b49a63 100644
--- a/maint/gen/preprocess.c
+++ b/maint/gen/preprocess.c
@@ -1,14 +1,19 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
#include <assert.h>
#include <ctype.h>
-#include <memory.h>
-#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "ast.h"
#include "deflang.h"
#include "symbols.h"
-#include "printf.h"
#define MAX_PREPROCESSOR_NEST 16
#define MAX_SYSCALL_COUNT 4096
@@ -31,7 +36,8 @@ create_statement_condition(struct condition_stack *stack)
if (stack->idx == 0) {
return NULL;
}
- struct statement_condition *ret = xmalloc((sizeof *ret) + stack->idx * (sizeof(char *)));
+ struct statement_condition *ret =
+ xmalloc((sizeof *ret) + stack->idx * (sizeof(char *)));
ret->count = stack->idx;
memcpy(ret->values, stack->stack, stack->idx * (sizeof(char *)));
return ret;
@@ -121,7 +127,8 @@ preprocess_rec(struct ast_node *root, struct condition_stack *cur,
arg_count++;
}
- struct syscall *new = xmalloc(sizeof(*new) + sizeof(struct syscall_argument) * arg_count);
+ struct syscall *new =
+ xmalloc(sizeof(*new) + sizeof(struct syscall_argument) * arg_count);
*new = (struct syscall) {
.name = root->syscall.name,
.conditions = create_statement_condition(cur),
@@ -156,7 +163,7 @@ preprocess_rec(struct ast_node *root, struct condition_stack *cur,
*/
static size_t
find_matching(struct syscall **syscall_buffer, size_t syscall_count,
- struct syscall_group *out)
+ struct syscall_group *out)
{
struct syscall *base = syscall_buffer[0];
assert(base != NULL);
@@ -165,11 +172,11 @@ find_matching(struct syscall **syscall_buffer, size_t syscall_count,
size_t matching = 0;
for (size_t i = 1; i < syscall_count; i++) {
struct syscall *cur = syscall_buffer[i];
- // all variants start with the same name as the base
+ /* all variants start with the same name as the base */
if (strncmp(cur->name, base->name, base_name_len) != 0) {
break;
}
- // and their last '$' is immediately after the base name
+ /* and their last '$' is immediately after the base name */
char *last_dollar = strrchr(cur->name, '$');
if (last_dollar == cur->name + base_name_len) {
matching++;
@@ -185,7 +192,8 @@ find_matching(struct syscall **syscall_buffer, size_t syscall_count,
return 1;
}
- struct syscall_group *children = xmalloc(sizeof(struct syscall_group) * matching);
+ struct syscall_group *children =
+ xmalloc(sizeof(struct syscall_group) * matching);
size_t children_idx = 0;
size_t i = 1;
@@ -196,13 +204,14 @@ find_matching(struct syscall **syscall_buffer, size_t syscall_count,
}
char *last_dollar = strrchr(cur->name, '$');
if (last_dollar != cur->name + base_name_len) {
- // not a direct subvariant
- fprintf(stderr, "not subvariant %s -> %s \n", base->name, cur->name);
+ /* not a direct subvariant */
+ fprintf(stderr, "not subvariant %s -> %s \n",
+ base->name, cur->name);
i += 1;
continue;
}
i += find_matching(syscall_buffer + i, syscall_count - i,
- children + children_idx);
+ children + children_idx);
children_idx++;
}
@@ -228,29 +237,40 @@ syscall_comparator(const void *a, const void *b)
static struct syscall_group *
group_syscall_variants(struct processing_state *state, size_t *out_count)
{
- // The idea is to sort the syscalls by name:
- // "prctl" "prctl$GET_FP_MODE"
- // "prctl$PR_CAP_AMBIENT" "prctl$PR_CAP_AMBIENT$PR_CAP_AMBIENT_LOWER"
- // This way, every variant will immediately follow the base syscall and will
- // be grouped into a syscall_group 'find_matching'.
+ /*
+ * The idea is to sort the syscalls by name:
+ * "prctl" "prctl$GET_FP_MODE"
+ * "prctl$PR_CAP_AMBIENT"
+ * "prctl$PR_CAP_AMBIENT$PR_CAP_AMBIENT_LOWER"
+ * This way, every variant will immediately follow the base syscall
+ * and will be grouped into a syscall_group 'find_matching'.
+ */
qsort(state->syscall_buffer, state->syscall_index,
- sizeof(struct syscall *), syscall_comparator);
+ sizeof(struct syscall *), syscall_comparator);
- // in the worst case (no variants), there can be MAX_SYSCALL_COUNT syscall groups
- struct syscall_group *scratch = xcalloc(sizeof(*scratch) * MAX_SYSCALL_COUNT);
+ /*
+ * In the worst case (no variants),
+ * there can be MAX_SYSCALL_COUNT syscall groups.
+ */
+ struct syscall_group *scratch =
+ xcalloc(MAX_SYSCALL_COUNT, sizeof(*scratch));
size_t groups = 0;
size_t i = 0;
while (i < state->syscall_index) {
- i += find_matching(state->syscall_buffer + i, state->syscall_index - i, scratch + groups);
+ i += find_matching(state->syscall_buffer + i,
+ state->syscall_index - i,
+ scratch + groups);
groups++;
}
- struct syscall_group *ret = realloc(scratch, sizeof(*scratch) * (groups + 1));
+ struct syscall_group *ret =
+ realloc(scratch, sizeof(*scratch) * (groups + 1));
if (ret == NULL) {
- fprintf(stderr, "realloc failed for %zu bytes\n", sizeof(*scratch) * groups);
+ fprintf(stderr, "realloc failed for %zu bytes\n",
+ sizeof(*scratch) * groups);
exit(1);
}
@@ -264,7 +284,8 @@ preprocess(struct ast_node *root)
struct processed_ast *ret = xmalloc(sizeof *ret);
struct processing_state state = (struct processing_state) {
- .syscall_buffer = xcalloc(sizeof(struct syscall *) * MAX_SYSCALL_COUNT),
+ .syscall_buffer =
+ xcalloc(MAX_SYSCALL_COUNT, sizeof(struct syscall *)),
.syscall_index = 0,
.struct_stmts = NULL,
.preprocessor_head = NULL,
@@ -277,7 +298,8 @@ preprocess(struct ast_node *root)
ret->preprocessor_stmts = state.preprocessor_head;
ret->struct_stmts = state.struct_stmts;
- ret->syscall_groups = group_syscall_variants(&state, &ret->syscall_group_count);
+ ret->syscall_groups =
+ group_syscall_variants(&state, &ret->syscall_group_count);
ret->decoders = state.decoder_head;
return ret;
diff --git a/maint/gen/preprocess.h b/maint/gen/preprocess.h
index 31bda8658..1a96f80fa 100644
--- a/maint/gen/preprocess.h
+++ b/maint/gen/preprocess.h
@@ -1,5 +1,15 @@
+/*
+ * Copyright (c) 2021 Srikavin Ramkumar <srikavinramkumar@gmail.com>
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
#ifndef PREPROCESS_H
-#define PREPROCESS_H
+# define PREPROCESS_H
+
+# include "ast.h"
/*
* Stores nested #ifdef/#ifndef statements sequentially (as a stack)
@@ -22,7 +32,7 @@ struct statement_condition {
struct preprocessor_statement {
struct ast_loc loc;
- // can be NULL
+ /* can be NULL */
struct statement_condition *conditions;
char *value;
@@ -38,7 +48,7 @@ struct struct_def {
char *name;
struct statement_condition *conditions;
- // TODO
+ /* TODO */
};
struct syscall_argument {
@@ -49,13 +59,15 @@ struct syscall_argument {
struct decoder {
struct ast_loc loc;
- // the type this decoder handles
+ /* the type this decoder handles */
struct ast_type *matching_type;
- // a format string containing C source code of a decoder capable of handling
- // arguments/return values of type 'matching_type'.
- // the first printf arg is a variable containing the value of the argument.
- // the second printf arg is the index of the argument.
+ /*
+ * A format string containing C source code of a decoder
+ * capable of handling arguments/return values of type 'matching_type'.
+ * The first printf arg is a variable containing the value of the
+ * argument, the second printf arg is the index of the argument.
+ */
char *fmt_string;
};
@@ -67,18 +79,18 @@ struct decoder_list {
struct syscall {
struct ast_loc loc;
- // can be NULL
+ /* can be NULL */
struct statement_condition *conditions;
- // name of the syscall
+ /* name of the syscall */
char *name;
bool is_ioctl;
- // the return value of the syscall
+ /* the return value of the syscall */
struct ast_type ret;
- // the defined arguments
+ /* the defined arguments */
size_t arg_count;
struct syscall_argument args[];
};
diff --git a/maint/gen/symbols.c b/maint/gen/symbols.c
index bf4e1d3a0..076e29fcb 100644
--- a/maint/gen/symbols.c
+++ b/maint/gen/symbols.c
@@ -24,7 +24,8 @@ struct symbol_entry *symbol_table;
struct ast_node *
symbol_get(char *name)
{
- for (struct symbol_entry *cur = symbol_table; cur != NULL; cur = cur->next) {
+ for (struct symbol_entry *cur = symbol_table;
+ cur != NULL; cur = cur->next) {
if (strcmp(cur->name, name) == 0) {
return cur->source;
}
@@ -55,7 +56,8 @@ symbol_add(char *name, struct ast_node *source)
char *
-resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *options)
+resolve_type(struct ast_type *out, char *name,
+ struct ast_type_option_list *options)
{
out->name = name;
out->options = options;
@@ -73,7 +75,8 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
};
size_t options_len = 0;
- for (struct ast_type_option_list *cur = options; cur != NULL; cur = cur->next) {
+ for (struct ast_type_option_list *cur = options;
+ cur != NULL; cur = cur->next) {
if (cur->option->child_type == AST_TYPE_CHILD_TEMPLATE_ID) {
return NULL;
}
@@ -84,10 +87,11 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
for (size_t i = 0; i < ARRAY_LEN(expected_options_len); ++i) {
if (strcmp(name, expected_options_len[i].name) == 0) {
if (options_len != expected_options_len[i].expected_args) {
- char *error = xmalloc(128);
- snprintf(error, 128, "type '%s' expects %zu type options; got %zu",
- name, expected_options_len[i].expected_args, options_len);
- return error;
+ return xasprintf("type '%s' expects %zu "
+ "type options; got %zu",
+ name,
+ expected_options_len[i].expected_args,
+ options_len);
}
}
}
@@ -99,7 +103,8 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
} else if (strcmp(name, "ptr") == 0) {
out->type = TYPE_PTR;
if (options->option->child_type != AST_TYPE_CHILD_TYPE) {
- return "first type option for ptr must be 'in', 'out' or 'inout'";
+ return "first type option for ptr must be"
+ " 'in', 'out' or 'inout'";
}
if (strcmp(options->option->type->name, "in") == 0) {
out->ptr.dir = PTR_DIR_IN;
@@ -108,13 +113,15 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
} else if (strcmp(options->option->type->name, "inout") == 0) {
out->ptr.dir = PTR_DIR_INOUT;
} else {
- return "first type option for ptr must be 'in', 'out' or 'inout'";
+ return "first type option for ptr must be"
+ " 'in', 'out' or 'inout'";
}
out->ptr.type = options->next->option->type;
} else if (strcmp(name, "ref") == 0) {
out->type = TYPE_REF;
if (options->option->child_type != AST_TYPE_CHILD_TYPE) {
- return "first type option for len must be the name of another argument or $ret";
+ return "first type option for len must be"
+ " the name of another argument or $ret";
}
if (strcmp(options->option->type->name, "@ret") == 0) {
out->ref.return_value = true;
@@ -129,8 +136,10 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
return "first type option for ptr must be a string";
}
out->xorflags.dflt = options->next->option->type->name;
- if (options->next->next->option->child_type != AST_TYPE_CHILD_TYPE) {
- return "third type option for xor_flags must be the underlying flag type";
+ if (options->next->next->option->child_type !=
+ AST_TYPE_CHILD_TYPE) {
+ return "third type option for xor_flags must be"
+ " the underlying flag type";
}
out->xorflags.underlying = options->next->next->option->type;
} else if (strcmp(name, "or_flags") == 0) {
@@ -140,8 +149,10 @@ resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *opti
return "first type option for ptr must be a string";
}
out->orflags.dflt = options->next->option->type->name;
- if (options->next->next->option->child_type != AST_TYPE_CHILD_TYPE) {
- return "third type option for or_flags must be the underlying flag type";
+ if (options->next->next->option->child_type !=
+ AST_TYPE_CHILD_TYPE) {
+ return "third type option for or_flags must be"
+ " the underlying flag type";
}
out->orflags.underlying = options->next->next->option->type;
}
diff --git a/maint/gen/symbols.h b/maint/gen/symbols.h
index 1737ddccf..1c2e8d47f 100644
--- a/maint/gen/symbols.h
+++ b/maint/gen/symbols.h
@@ -7,11 +7,9 @@
*/
#ifndef SYMBOLS_H
-#define SYMBOLS_H
+# define SYMBOLS_H
-#include <stdbool.h>
-
-#include "ast.h"
+# include "ast.h"
/*
* Returns a error string if the given type is
@@ -19,7 +17,8 @@
* valid.
*/
char *
-resolve_type(struct ast_type *out, char *name, struct ast_type_option_list *options);
+resolve_type(struct ast_type *out, char *name,
+ struct ast_type_option_list *options);
/*
* Returns NULL if successfully added a symbol.
diff --git a/maint/gen/xmalloc.c b/maint/gen/xmalloc.c
new file mode 100644
index 000000000..f3718a5ba
--- /dev/null
+++ b/maint/gen/xmalloc.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
+ * Copyright (c) 2015-2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmalloc.h"
+
+static void
+die_out_of_memory(void)
+{
+ fprintf(stderr, "allocation failed\n");
+ exit(EXIT_FAILURE);
+}
+
+void
+free_by_pointer(void *p) {
+ void **pp = (void **) p;
+ free(*pp);
+ *pp = NULL;
+}
+
+void *
+xmalloc(size_t n)
+{
+ void *p = malloc(n);
+
+ if (!p)
+ die_out_of_memory();
+
+ return p;
+}
+
+void *
+xcalloc(size_t nmemb, size_t size)
+{
+ void *p = calloc(nmemb, size);
+
+ if (!p)
+ die_out_of_memory();
+
+ return p;
+}
+
+char *
+xstrdup(const char *str)
+{
+ if (!str)
+ return NULL;
+
+ char *p = strdup(str);
+
+ if (!p)
+ die_out_of_memory();
+
+ return p;
+}
+
+char *
+xasprintf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ char *res;
+ if (vasprintf(&res, fmt, ap) < 0)
+ die_out_of_memory();
+
+ va_end(ap);
+ return res;
+}
diff --git a/maint/gen/xmalloc.h b/maint/gen/xmalloc.h
new file mode 100644
index 000000000..61b48ffda
--- /dev/null
+++ b/maint/gen/xmalloc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
+ * Copyright (c) 2015-2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef XMALLOC_H
+# define XMALLOC_H
+
+# define ATTRIBUTE_FORMAT(args) __attribute__((__format__ args))
+# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
+# define ATTRIBUTE_ALLOC_SIZE(args) __attribute__((__alloc_size__ args))
+# define ATTRIBUTE_CLEANUP(args) __attribute__((__cleanup__(args)))
+
+# define CLEANUP_FREE ATTRIBUTE_CLEANUP(free_by_pointer)
+
+void
+free_by_pointer(void *);
+
+void *
+xmalloc(size_t)
+ ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1));
+
+void *
+xcalloc(size_t nmemb, size_t size)
+ ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE((1, 2));
+
+char *
+xstrdup(const char *);
+
+char *xasprintf(const char *fmt, ...)
+ ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_MALLOC;
+
+#endif /* XMALLOC_H */