|
|
|
@ -17,6 +17,71 @@ |
|
|
|
|
|
|
|
|
|
|
|
#define CLEANUP(f) __attribute__((cleanup(f))) |
|
|
|
#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() |
|
|
|
static void show_version() |
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("ftracetool v%s\n", VERSION_STRING); |
|
|
|
printf("ftracetool v%s\n", VERSION_STRING); |
|
|
|
@ -25,6 +90,7 @@ static void show_version() |
|
|
|
static void show_usage() |
|
|
|
static void show_usage() |
|
|
|
{ |
|
|
|
{ |
|
|
|
printf("ftracetool v%s\n \
|
|
|
|
printf("ftracetool v%s\n \
|
|
|
|
|
|
|
|
-m key=value Set mapping\n \ |
|
|
|
-e Execute script\n \ |
|
|
|
-e Execute script\n \ |
|
|
|
-s Show symbols in elf file\n \ |
|
|
|
-s Show symbols in elf file\n \ |
|
|
|
-v Show version\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); |
|
|
|
ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0); |
|
|
|
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN); |
|
|
|
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN); |
|
|
|
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1); |
|
|
|
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1); |
|
|
|
|
|
|
|
embed_mappings(ctx); |
|
|
|
|
|
|
|
|
|
|
|
sexp_gc_var1(filename_obj); |
|
|
|
sexp_gc_var1(filename_obj); |
|
|
|
|
|
|
|
|
|
|
|
@ -279,7 +346,7 @@ int main(int argc, char **argv) |
|
|
|
char filename[NAME_MAX] = {}; |
|
|
|
char filename[NAME_MAX] = {}; |
|
|
|
bool execute_script = false; |
|
|
|
bool execute_script = false; |
|
|
|
bool show_symbols_in_file = 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) |
|
|
|
switch (opt) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -305,6 +372,16 @@ int main(int argc, char **argv) |
|
|
|
show_symbols_in_file = true; |
|
|
|
show_symbols_in_file = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
case 'm': |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct ftt_mapping *const mapping = parse_mapping(optarg); |
|
|
|
|
|
|
|
if (mapping) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mapping->next = gs_mappings; |
|
|
|
|
|
|
|
gs_mappings = mapping; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
default: |
|
|
|
default: |
|
|
|
{ |
|
|
|
{ |
|
|
|
show_usage(); |
|
|
|
show_usage(); |
|
|
|
|