From 41303bbc70f1087c0173eb52e85087d4acd11a82 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 4 Sep 2018 17:18:37 -0700 Subject: [PATCH] garmin: improve on debug log output for unknown fields Yes, the hexdump was simple, but it was really hard to read, and we can do so much better, including taking empty data into account, and formatting it by the actual size of the individual fields. So this improves on the debug log, so that when we decide to try to parse new field information, the data will be in a somewhat more legible format that makes more sense. And getting rid of the empty fields makes it much clearer what data might be even remotely interesting. Signed-off-by: Linus Torvalds --- src/garmin_parser.c | 73 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/src/garmin_parser.c b/src/garmin_parser.c index 7e35e32..1662249 100644 --- a/src/garmin_parser.c +++ b/src/garmin_parser.c @@ -747,6 +747,70 @@ static int traverse_compressed(struct garmin_parser_t *garmin, return -1; } +static int all_data_inval(const unsigned char *data, int base_type, int len) +{ + int base_size = base_type_info[base_type].type_size; + unsigned long long invalid = base_type_info[base_type].type_inval; + + while (len > 0) { + unsigned long long val = 0; + memcpy(&val, data, base_size); + if (val != invalid) + return 0; + data += base_size; + len -= base_size; + } + return 1; +} + +static void unknown_field(struct garmin_parser_t *garmin, const unsigned char *data, + const char *msg_name, unsigned int field_nr, + int base_type, int len) +{ + char buffer[80]; + const char *str = (const char *)data; + + /* Skip empty strings */ + if (base_type == 7 && !*str) + return; + + /* Turn non-string data into hex values */ + if (base_type != 7) { + int pos = 0; + int base_size = base_type_info[base_type].type_size; + const char *sep = ""; + + /* Skip empty data */ + if (all_data_inval(data, base_type, len)) + return; + + str = buffer; + while (len > 0) { + long long val; + /* Space + hex + NUL */ + int need = 2+base_size*2; + + /* The "-4" is because we reserve that " ..\0" at the end */ + if (pos + need >= sizeof(buffer)-4) { + strcpy(buffer+pos, " .."); + break; + } + + val = 0; + memcpy(&val, data, base_size); + + pos += sprintf(buffer+pos, "%s%0*llx", sep, base_size*2, val); + sep = " "; + + data += base_size; + len -= base_size; + } + } + + DEBUG(garmin->base.context, "%s/%d %s '%s'", msg_name, field_nr, base_type_info[base_type].type_name, str); +} + + static int traverse_regular(struct garmin_parser_t *garmin, const unsigned char *data, unsigned int size, unsigned char type, unsigned int *timep) @@ -766,7 +830,6 @@ static int traverse_regular(struct garmin_parser_t *garmin, unsigned int field_nr = field[0]; unsigned int len = field[1]; unsigned int base_type = field[2] & 0x7f; - static const int base_size_array[] = { 1, 1, 1, 2, 2, 4, 4, 1, 4, 8, 1, 2, 4, 1, 8, 8, 8 }; const struct field_desc *field_desc; unsigned int base_size; @@ -787,7 +850,7 @@ static int traverse_regular(struct garmin_parser_t *garmin, total_len += size; continue; } - base_size = base_size_array[base_type]; + base_size = base_type_info[base_type].type_size; if (len % base_size) { ERROR(garmin->base.context, "Data traversal size not a multiple of base size (%d vs %d)\n", len, base_size); return -1; @@ -827,8 +890,7 @@ static int traverse_regular(struct garmin_parser_t *garmin, if (field_desc) { field_desc->parse(garmin, base_type, data); } else { - DEBUG(garmin->base.context, "%s/%d %s", msg_name, field_nr, base_type_info[base_type].type_name); - HEXDUMP(garmin->base.context, DC_LOGLEVEL_DEBUG, "next", data, len); + unknown_field(garmin, data, msg_name, field_nr, base_type, len); } data += len; @@ -920,6 +982,9 @@ traverse_data(struct garmin_parser_t *garmin) // The data starts with our filename fingerprint. Skip it. if (len < FIT_NAME_SIZE) return DC_STATUS_IO; + + DEBUG(garmin->base.context, "file %s", data); + data += FIT_NAME_SIZE; len -= FIT_NAME_SIZE;