perf-y += sigtrap.o
 perf-y += event_groups.o
 perf-y += symbols.o
+perf-y += util.o
 
 ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 
        &suite__sigtrap,
        &suite__event_groups,
        &suite__symbols,
+       &suite__util,
        NULL,
 };
 
 
 DECLARE_SUITE(sigtrap);
 DECLARE_SUITE(event_groups);
 DECLARE_SUITE(symbols);
+DECLARE_SUITE(util);
 
 /*
  * PowerPC and S390 do not support creation of instruction breakpoints using the
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+#include "tests.h"
+#include "util/debug.h"
+
+#include <linux/compiler.h>
+#include <stdlib.h>
+#include <string2.h>
+
+static int test_strreplace(char needle, const char *haystack,
+                          const char *replace, const char *expected)
+{
+       char *new = strreplace_chars(needle, haystack, replace);
+       int ret = strcmp(new, expected);
+
+       free(new);
+       return ret == 0;
+}
+
+static int test__util(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
+{
+       TEST_ASSERT_VAL("empty string", test_strreplace(' ', "", "123", ""));
+       TEST_ASSERT_VAL("no match", test_strreplace('5', "123", "4", "123"));
+       TEST_ASSERT_VAL("replace 1", test_strreplace('3', "123", "4", "124"));
+       TEST_ASSERT_VAL("replace 2", test_strreplace('a', "abcabc", "ef", "efbcefbc"));
+       TEST_ASSERT_VAL("replace long", test_strreplace('a', "abcabc", "longlong",
+                                                       "longlongbclonglongbc"));
+
+       return 0;
+}
+
+DEFINE_SUITE("util", util);
 
                return c - 'a' + 10;
        return c - 'A' + 10;
 }
+
+/*
+ * Replace all occurrences of character 'needle' in string 'haystack' with
+ * string 'replace'
+ *
+ * The new string could be longer so a new string is returned which must be
+ * freed.
+ */
+char *strreplace_chars(char needle, const char *haystack, const char *replace)
+{
+       int replace_len = strlen(replace);
+       char *new_s, *to;
+       const char *loc = strchr(haystack, needle);
+       const char *from = haystack;
+       int num = 0;
+
+       /* Count occurrences */
+       while (loc) {
+               loc = strchr(loc + 1, needle);
+               num++;
+       }
+
+       /* Allocate enough space for replacements and reset first location */
+       new_s = malloc(strlen(haystack) + (num * (replace_len - 1) + 1));
+       if (!new_s)
+               return NULL;
+       loc = strchr(haystack, needle);
+       to = new_s;
+
+       while (loc) {
+               /* Copy original string up to found char and update positions */
+               memcpy(to, from, 1 + loc - from);
+               to += loc - from;
+               from = loc + 1;
+
+               /* Copy replacement string and update positions */
+               memcpy(to, replace, replace_len);
+               to += replace_len;
+
+               /* needle next occurrence or end of string */
+               loc = strchr(from, needle);
+       }
+
+       /* Copy any remaining chars + null */
+       strcpy(to, from);
+
+       return new_s;
+}
 
 char *strdup_esc(const char *str);
 
 unsigned int hex(char c);
+char *strreplace_chars(char needle, const char *haystack, const char *replace);
 
 #endif /* PERF_STRING_H */