diff --git a/src/ftracetool.c b/src/ftracetool.c index d29a29c..1a7dbd1 100644 --- a/src/ftracetool.c +++ b/src/ftracetool.c @@ -17,6 +17,71 @@ #define CLEANUP(f) __attribute__((cleanup(f))) +struct ftt_mapping +{ + char *key; + char *value; + struct ftt_mapping *next; +}; + +static struct ftt_mapping *gs_mappings; + +static struct ftt_mapping *parse_mapping(const char *const raw_str) +{ + struct ftt_mapping *mapping = NULL; + char *const s = strchr(raw_str, '='); + if (s) + { + const size_t len = strlen(raw_str); + const size_t key_len = s - raw_str + 1; // including 0-terminator + const size_t value_len = len - key_len + 1; + if (key_len == 0 || value_len == 0) + { + return NULL; + } + mapping = calloc(1, sizeof(*mapping)); + if (!mapping) + { + return NULL; + } + mapping->key = calloc(key_len, sizeof(char)); + mapping->value = calloc(value_len, sizeof(char)); + if (!mapping->key || !mapping->value) + { + free(mapping->key); + free(mapping->value); + free(mapping); + return NULL; + } + + memcpy(mapping->key, raw_str, key_len - 1); + memcpy(mapping->value, s + 1, value_len - 1); + } + + return mapping; +} + +static int embed_mappings(sexp ctx) +{ + sexp_gc_var2(s_mapping, mapping_name); + sexp_gc_preserve2(ctx, mapping_name, s_mapping); + mapping_name = sexp_intern(ctx, "*ftt-mappings*", -1); + s_mapping = SEXP_NULL; + for (struct ftt_mapping const *mapping = gs_mappings; mapping; + mapping = mapping->next) + { + sexp_gc_var3(key, value, cell); + sexp_gc_preserve3(ctx, key, value, cell); + key = sexp_c_string(ctx, mapping->key, -1); + value = sexp_c_string(ctx, mapping->value, -1); + cell = sexp_cons(ctx, key, value); + s_mapping = sexp_cons(ctx, cell, s_mapping); + sexp_gc_release3(ctx); + } + sexp_env_define(ctx, sexp_context_env(ctx), mapping_name, s_mapping); + sexp_gc_release2(ctx); +} + static void show_version() { printf("ftracetool v%s\n", VERSION_STRING); @@ -25,6 +90,7 @@ static void show_version() static void show_usage() { printf("ftracetool v%s\n \ + -m key=value Set mapping\n \ -e Execute script\n \ -s Show symbols in elf file\n \ -v Show version\n \ @@ -248,6 +314,7 @@ static int do_execute_script(const char *const filename) ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0); sexp_load_standard_env(ctx, NULL, SEXP_SEVEN); sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1); + embed_mappings(ctx); sexp_gc_var1(filename_obj); @@ -279,7 +346,7 @@ int main(int argc, char **argv) char filename[NAME_MAX] = {}; bool execute_script = false; bool show_symbols_in_file = false; - while ((opt = getopt(argc, argv, "vhs:e:")) != -1) + while ((opt = getopt(argc, argv, "vhs:e:m:")) != -1) { switch (opt) { @@ -305,6 +372,16 @@ int main(int argc, char **argv) show_symbols_in_file = true; break; } + case 'm': + { + struct ftt_mapping *const mapping = parse_mapping(optarg); + if (mapping) + { + mapping->next = gs_mappings; + gs_mappings = mapping; + } + break; + } default: { show_usage();