Re: [PATCH v2 07/10] perf trace: Pretty print buffer data

Arnaldo Carvalho de Melo
2024-08-23T14:17:48Z

On Thu, Aug 15, 2024 at 09:36:23AM +0800, Howard Chu wrote:
> +#define MAX_CONTROL_CHAR 31
> +#define MAX_ASCII 127
> +
> +static size_t syscall_arg__scnprintf_buf(char *bf, size_t size, struct syscall_arg *arg)
> +{
> + char result[TRACE_AUG_MAX_BUF * 4], tens[4];
> + struct augmented_arg *augmented_arg = arg->augmented.args;
> + unsigned char *orig;
> + int i = 0, n, consumed, digits;
> +
> + if (augmented_arg == NULL)
> + return 0;
> +
> + orig = (unsigned char *)augmented_arg->value;
> + n = augmented_arg->size;
> +
> + memset(result, 0, sizeof(result));
> +
> + for (int j = 0; j < n && i < (int)sizeof(result) - 1; ++j) {
> + /* print control characters (0~31 and 127), and non-ascii characters in \(digits) */
> + if (orig[j] <= MAX_CONTROL_CHAR || orig[j] >= MAX_ASCII) {
> + result[i++] = '\\';
> +
> + /* convert to digits */
> + digits = scnprintf(tens, sizeof(result) - i, "%d", (int)orig[j]);
> + if (digits + i <= (int)sizeof(result) - 1) {
> + strncpy(result + i, tens, digits);
> + i += digits;
> + }
> + } else {
> + result[i++] = orig[j];
> + }
> + }
> +
> + consumed = sizeof(*augmented_arg) + augmented_arg->size;
> + arg->augmented.args = ((void *)arg->augmented.args) + consumed;
> + arg->augmented.size -= consumed;
> +
> + return scnprintf(bf, size, "\"%s\"", result);
> +}

Simplified the above to the one below to avoid using multiple buffers
and copying around, now testing:

+#define MAX_CONTROL_CHAR 31
+#define MAX_ASCII 127
+
+static size_t syscall_arg__scnprintf_buf(char *bf, size_t size, struct syscall_arg *arg)
+{
+ struct augmented_arg *augmented_arg = arg->augmented.args;
+ unsigned char *orig = (unsigned char *)augmented_arg->value;
+ size_t printed = 0;
+ int consumed;
+
+ if (augmented_arg == NULL)
+ return 0;
+
+ for (int j = 0; j < augmented_arg->size; ++j) {
+ bool control_char = orig[j] <= MAX_CONTROL_CHAR || orig[j] >= MAX_ASCII;
+ /* print control characters (0~31 and 127), and non-ascii characters in \(digits) */
+ printed += scnprintf(bf + printed, size - printed, control_char ? "\\%d" : "%c", (int)orig[j]);
+ }
+
+ consumed = sizeof(*augmented_arg) + augmented_arg->size;
+ arg->augmented.args = ((void *)arg->augmented.args) + consumed;
+ arg->augmented.size -= consumed;
+
+ return printed;
+}