extern size_t strlcpy(char *dest, const char *src, size_t size);
 #endif
 
+char *str_error_r(int errnum, char *buf, size_t buflen);
+
 #endif /* _LINUX_STRING_H_ */
 
--- /dev/null
+#undef _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <linux/string.h>
+
+/*
+ * The tools so far have been using the strerror_r() GNU variant, that returns
+ * a string, be it the buffer passed or something else.
+ *
+ * But that, besides being tricky in cases where we expect that the function
+ * using strerror_r() returns the error formatted in a provided buffer (we have
+ * to check if it returned something else and copy that instead), breaks the
+ * build on systems not using glibc, like Alpine Linux, where musl libc is
+ * used.
+ *
+ * So, introduce yet another wrapper, str_error_r(), that has the GNU
+ * interface, but uses the portable XSI variant of strerror_r(), so that users
+ * rest asured that the provided buffer is used and it is what is returned.
+ */
+char *str_error_r(int errnum, char *buf, size_t buflen)
+{
+       int err = strerror_r(errnum, buf, buflen);
+       if (err)
+               snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", errnum, buf, buflen, err);
+       return buf;
+}
 
 tools/lib/symbol/kallsyms.h
 tools/lib/find_bit.c
 tools/lib/bitmap.c
+tools/lib/str_error_r.c
 tools/include/asm/atomic.h
 tools/include/asm/barrier.h
 tools/include/asm/bug.h
 
        if (fd < 0) {
                pr_err("Error: sys_perf_event_open() syscall returned "
                       "with %d (%s)\n", fd,
-                      strerror_r(errno, sbuf, sizeof(sbuf)));
+                      str_error_r(errno, sbuf, sizeof(sbuf)));
                return -1;
        }
 
        addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
        if (addr == (void *)(-1)) {
                pr_err("Error: mmap() syscall returned with (%s)\n",
-                      strerror_r(errno, sbuf, sizeof(sbuf)));
+                      str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_close;
        }
 
 
                                                continue;
                                        }
                                        pr_warning("Couldn't add %s: %s\n",
-                                                  pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
+                                                  pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
                                }
 
                        strlist__delete(list);
                                                continue;
                                        }
                                        pr_warning("Couldn't remove %s: %s\n",
-                                                  pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
+                                                  pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
                                }
 
                        strlist__delete(list);
                                                continue;
                                        }
                                        pr_warning("Couldn't remove %s: %s\n",
-                                                  pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
+                                                  pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
                                }
 
                        strlist__delete(list);
                                                continue;
                                        }
                                        pr_warning("Couldn't update %s: %s\n",
-                                                  pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
+                                                  pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
                                }
 
                        strlist__delete(list);
 
                        free(man_page);
                }
                warning("failed to exec '%s': %s", path,
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
        }
 }
 
                        free(man_page);
                }
                warning("failed to exec '%s': %s", path,
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
        }
 }
 
                path = "man";
        execlp(path, "man", page, NULL);
        warning("failed to exec '%s': %s", path,
-               strerror_r(errno, sbuf, sizeof(sbuf)));
+               str_error_r(errno, sbuf, sizeof(sbuf)));
 }
 
 static void exec_man_cmd(const char *cmd, const char *page)
                free(shell_cmd);
        }
        warning("failed to exec '%s': %s", cmd,
-               strerror_r(errno, sbuf, sizeof(sbuf)));
+               str_error_r(errno, sbuf, sizeof(sbuf)));
 }
 
 static void add_man_viewer(const char *name)
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                printf("Couldn't create the events: %s\n",
-                      strerror_r(errno, sbuf, sizeof(sbuf)));
+                      str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out;
        }
 
        if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
                ui__error("Failed to mmap the events: %s\n",
-                         strerror_r(errno, sbuf, sizeof(sbuf)));
+                         str_error_r(errno, sbuf, sizeof(sbuf)));
                perf_evlist__close(evlist);
                goto out;
        }
 
 
        pr_err("%s", msg);
        pr_debug(" Reason: %s (Code: %d)",
-                strerror_r(-err, sbuf, sizeof(sbuf)), err);
+                str_error_r(-err, sbuf, sizeof(sbuf)), err);
        pr_err("\n");
 }
 
 
                        return -errno;
                } else {
                        pr_err("failed to mmap with %d (%s)\n", errno,
-                               strerror_r(errno, msg, sizeof(msg)));
+                               str_error_r(errno, msg, sizeof(msg)));
                        if (errno)
                                return -errno;
                        else
        if (perf_evlist__apply_filters(evlist, &pos)) {
                error("failed to set filter \"%s\" on event %s with %d (%s)\n",
                        pos->filter, perf_evsel__name(pos), errno,
-                       strerror_r(errno, msg, sizeof(msg)));
+                       str_error_r(errno, msg, sizeof(msg)));
                rc = -1;
                goto out;
        }
 
        if (forks && workload_exec_errno) {
                char msg[STRERR_BUFSIZE];
-               const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
+               const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
                pr_err("Workload failed: %s\n", emsg);
                err = -1;
                goto out_child;
 
                }
                pr_err("Error: sys_perf_event_open() syscall returned "
                       "with %d (%s)\n%s", fd,
-                      strerror_r(errno, sbuf, sizeof(sbuf)), info);
+                      str_error_r(errno, sbuf, sizeof(sbuf)), info);
                exit(EXIT_FAILURE);
        }
        return fd;
 
        if (perf_evlist__apply_filters(evsel_list, &counter)) {
                error("failed to set filter \"%s\" on event %s with %d (%s)\n",
                        counter->filter, perf_evsel__name(counter), errno,
-                       strerror_r(errno, msg, sizeof(msg)));
+                       str_error_r(errno, msg, sizeof(msg)));
                return -1;
        }
 
                wait(&status);
 
                if (workload_exec_errno) {
-                       const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
+                       const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
                        pr_err("Workload failed: %s\n", emsg);
                        return -1;
                }
 
 
        if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
                ui__error("Failed to mmap with %d (%s)\n",
-                           errno, strerror_r(errno, msg, sizeof(msg)));
+                           errno, str_error_r(errno, msg, sizeof(msg)));
                goto out_err;
        }
 
 
 out_err_cpu_topo: {
        char errbuf[BUFSIZ];
-       const char *err = strerror_r(-ret, errbuf, sizeof(errbuf));
+       const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
 
        ui__error("Could not read the CPU topology map: %s\n", err);
        goto out_delete;
 
        if (perf_evlist__create_maps(top.evlist, target) < 0) {
                ui__error("Couldn't create thread/CPU maps: %s\n",
-                         errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf)));
+                         errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
                goto out_delete_evlist;
        }
 
 
                fprintf(trace->output, ") = %ld", ret);
        } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
                char bf[STRERR_BUFSIZE];
-               const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
+               const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
                           *e = audit_errno_to_name(-ret);
 
                fprintf(trace->output, ") = -1 %s %s", e, emsg);
        fprintf(trace->output,
                "Failed to set filter \"%s\" on event %s with %d (%s)\n",
                evsel->filter, perf_evsel__name(evsel), errno,
-               strerror_r(errno, errbuf, sizeof(errbuf)));
+               str_error_r(errno, errbuf, sizeof(errbuf)));
        goto out_delete_evlist;
 }
 out_error_mem:
 
        /* Check for ENOSPC and EIO errors.. */
        if (fflush(stdout)) {
                fprintf(stderr, "write failure on standard output: %s",
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out;
        }
        if (ferror(stdout)) {
        }
        if (fclose(stdout)) {
                fprintf(stderr, "close failed on standard output: %s",
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out;
        }
        status = 0;
        }
 
        fprintf(stderr, "Failed to run command '%s': %s\n",
-               cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
+               cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
 out:
        return 1;
 }
 
        err = perf_evlist__mmap(evlist, mmap_pages, true);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                return TEST_FAIL;
        }
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
        err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
 
        if (child < 0) {
                pr_err("failed to fork test: %s\n",
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
                return -1;
        }
 
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                return err;
        }
 
 
        sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
        if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
                pr_debug("sched_setaffinity() failed on CPU %d: %s ",
-                        cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf)));
+                        cpus->map[0], str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_free_cpus;
        }
 
                if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
                        pr_debug("failed to open counter: %s, "
                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
-                                strerror_r(errno, sbuf, sizeof(sbuf)));
+                                str_error_r(errno, sbuf, sizeof(sbuf)));
                        goto out_delete_evlist;
                }
 
 
        if (perf_evlist__mmap(evlist, 128, true) < 0) {
                pr_debug("failed to mmap events: %d (%s)\n", errno,
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
        if (perf_evsel__open(evsel, cpus, threads) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_evsel_delete;
        }
 
                if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
                        pr_debug("sched_setaffinity() failed on CPU %d: %s ",
                                 cpus->map[cpu],
-                                strerror_r(errno, sbuf, sizeof(sbuf)));
+                                str_error_r(errno, sbuf, sizeof(sbuf)));
                        goto out_close_fd;
                }
                for (i = 0; i < ncalls; ++i) {
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
        err = perf_evlist__mmap(evlist, UINT_MAX, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
        if (perf_evsel__open_per_thread(evsel, threads) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_evsel_delete;
        }
 
 
        err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
        if (err < 0) {
                pr_debug("sched__get_first_possible_cpu: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
         */
        if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
                pr_debug("sched_setaffinity: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
        err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
 
                err = -errno;
                pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)),
+                        str_error_r(errno, sbuf, sizeof(sbuf)),
                         knob, (u64)attr.sample_freq);
                goto out_delete_evlist;
        }
        err = perf_evlist__mmap(evlist, 128, true);
        if (err < 0) {
                pr_debug("failed to mmap event: %d (%s)\n", errno,
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("Couldn't open the evlist: %s\n",
-                        strerror_r(-err, sbuf, sizeof(sbuf)));
+                        str_error_r(-err, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
        if (perf_evlist__mmap(evlist, 128, true) < 0) {
                pr_debug("failed to mmap events: %d (%s)\n", errno,
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_delete_evlist;
        }
 
 
        fp = fopen(filename, "w");
        if (fp == NULL) {
                char bf[64];
-               const char *err = strerror_r(errno, bf, sizeof(bf));
+               const char *err = str_error_r(errno, bf, sizeof(bf));
                ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
                return -1;
        }
 
 libperf-y += stat-shadow.o
 libperf-y += record.o
 libperf-y += srcline.o
+libperf-y += str_error_r.o
 libperf-y += data.o
 libperf-y += tsc.o
 libperf-y += cloexec.o
        $(call rule_mkdir)
        $(call if_changed_dep,cc_o_c)
 
+$(OUTPUT)util/str_error_r.o: ../lib/str_error_r.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
+
 $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE
        $(call rule_mkdir)
        $(call if_changed_dep,cc_o_c)
 
                snprintf(buf, size, "Unknown bpf loader error %d", err);
        else
                snprintf(buf, size, "%s",
-                        strerror_r(err, sbuf, sizeof(sbuf)));
+                        str_error_r(err, sbuf, sizeof(sbuf)));
 
        buf[size - 1] = '\0';
        return -1;
 
 
        WARN_ONCE(err != EINVAL && err != EBUSY,
                  "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
-                 err, strerror_r(err, sbuf, sizeof(sbuf)));
+                 err, str_error_r(err, sbuf, sizeof(sbuf)));
 
        /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
        while (1) {
 
        if (WARN_ONCE(fd < 0 && err != EBUSY,
                      "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
-                     err, strerror_r(err, sbuf, sizeof(sbuf))))
+                     err, str_error_r(err, sbuf, sizeof(sbuf))))
                return -1;
 
        return 0;
 
                int err = errno;
 
                pr_err("failed to open %s: %s", file->path,
-                       strerror_r(err, sbuf, sizeof(sbuf)));
+                       str_error_r(err, sbuf, sizeof(sbuf)));
                if (err == ENOENT && !strcmp(file->path, "perf.data"))
                        pr_err("  (try 'perf record' first)");
                pr_err("\n");
 
        if (fd < 0)
                pr_err("failed to open %s : %s\n", file->path,
-                       strerror_r(errno, sbuf, sizeof(sbuf)));
+                       str_error_r(errno, sbuf, sizeof(sbuf)));
 
        return fd;
 }
 
 #define pr_oe_time(t, fmt, ...)  pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
 
-#define STRERR_BUFSIZE 128     /* For the buffer size of strerror_r */
+#define STRERR_BUFSIZE 128     /* For the buffer size of str_error_r */
 
 int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void trace_event(union perf_event *event);
 
                        return fd;
 
                pr_debug("dso open failed: %s\n",
-                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                if (!dso__data_open_cnt || errno != EMFILE)
                        break;
 
        if (fstat(dso->data.fd, &st) < 0) {
                ret = -errno;
                pr_err("dso cache fstat failed: %s\n",
-                      strerror_r(errno, sbuf, sizeof(sbuf)));
+                      str_error_r(errno, sbuf, sizeof(sbuf)));
                dso->data.status = DSO_DATA_STATUS_ERROR;
                goto out;
        }
        BUG_ON(buflen == 0);
 
        if (errnum >= 0) {
-               const char *err = strerror_r(errnum, buf, buflen);
+               const char *err = str_error_r(errnum, buf, buflen);
 
                if (err != buf)
                        scnprintf(buf, buflen, "%s", err);
 
                               int err, char *buf, size_t size)
 {
        int printed, value;
-       char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
+       char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
 
        switch (err) {
        case EACCES:
 
 int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
 {
-       char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
+       char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
        int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
 
        switch (err) {
 
        "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
        "/bin/dmesg may provide additional information.\n"
        "No CONFIG_PERF_EVENTS=y kernel support configured?",
-                        err, strerror_r(err, sbuf, sizeof(sbuf)),
+                        err, str_error_r(err, sbuf, sizeof(sbuf)),
                         perf_evsel__name(evsel));
 }
 
 
        file = popen(cmd, "r");
        if (!file) {
                pr_err("ERROR: unable to popen cmd: %s\n",
-                      strerror_r(errno, serr, sizeof(serr)));
+                      str_error_r(errno, serr, sizeof(serr)));
                return -EINVAL;
        }
 
 
        if (ferror(file)) {
                pr_err("ERROR: error occurred when reading from pipe: %s\n",
-                      strerror_r(errno, serr, sizeof(serr)));
+                      str_error_r(errno, serr, sizeof(serr)));
                err = -EIO;
                goto errout;
        }
        if (path[0] != '-' && realpath(path, abspath) == NULL) {
                err = errno;
                pr_err("ERROR: problems with path %s: %s\n",
-                      path, strerror_r(err, serr, sizeof(serr)));
+                      path, str_error_r(err, serr, sizeof(serr)));
                return -err;
        }
 
        if (nr_cpus_avail <= 0) {
                pr_err(
 "WARNING:\tunable to get available CPUs in this system: %s\n"
-"        \tUse 128 instead.\n", strerror_r(errno, serr, sizeof(serr)));
+"        \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
                nr_cpus_avail = 128;
        }
        snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
 
                err = kernel_get_module_dso(module, &dso);
                if (err < 0) {
                        if (!dso || dso->load_errno == 0) {
-                               if (!strerror_r(-err, reason, STRERR_BUFSIZE))
+                               if (!str_error_r(-err, reason, STRERR_BUFSIZE))
                                        strcpy(reason, "(unknown)");
                        } else
                                dso__strerror_load(dso, reason, STRERR_BUFSIZE);
 error:
        if (ferror(fp)) {
                pr_warning("File read error: %s\n",
-                          strerror_r(errno, sbuf, sizeof(sbuf)));
+                          str_error_r(errno, sbuf, sizeof(sbuf)));
                return -1;
        }
        return 0;
        fp = fopen(lr->path, "r");
        if (fp == NULL) {
                pr_warning("Failed to open %s: %s\n", lr->path,
-                          strerror_r(errno, sbuf, sizeof(sbuf)));
+                          str_error_r(errno, sbuf, sizeof(sbuf)));
                return -errno;
        }
        /* Skip to starting line number */
 
        else
                pr_warning("Failed to open %cprobe_events: %s\n",
                           uprobe ? 'u' : 'k',
-                          strerror_r(-err, sbuf, sizeof(sbuf)));
+                          str_error_r(-err, sbuf, sizeof(sbuf)));
 }
 
 static void print_both_open_warning(int kerr, int uerr)
        else {
                char sbuf[STRERR_BUFSIZE];
                pr_warning("Failed to open kprobe events: %s.\n",
-                          strerror_r(-kerr, sbuf, sizeof(sbuf)));
+                          str_error_r(-kerr, sbuf, sizeof(sbuf)));
                pr_warning("Failed to open uprobe events: %s.\n",
-                          strerror_r(-uerr, sbuf, sizeof(sbuf)));
+                          str_error_r(-uerr, sbuf, sizeof(sbuf)));
        }
 }
 
                if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
                        ret = -errno;
                        pr_warning("Failed to write event: %s\n",
-                                  strerror_r(errno, sbuf, sizeof(sbuf)));
+                                  str_error_r(errno, sbuf, sizeof(sbuf)));
                }
        }
        free(buf);
        return 0;
 error:
        pr_warning("Failed to delete event: %s\n",
-                  strerror_r(-ret, buf, sizeof(buf)));
+                  str_error_r(-ret, buf, sizeof(buf)));
        return ret;
 }
 
 
                if (ret >= 16)
                        ret = -E2BIG;
                pr_warning("Failed to convert variable type: %s\n",
-                          strerror_r(-ret, sbuf, sizeof(sbuf)));
+                          str_error_r(-ret, sbuf, sizeof(sbuf)));
                return ret;
        }
        tvar->type = strdup(buf);
        fp = fopen(fname, "r");
        if (!fp) {
                pr_warning("Failed to open %s: %s\n", fname,
-                          strerror_r(errno, sbuf, sizeof(sbuf)));
+                          str_error_r(errno, sbuf, sizeof(sbuf)));
                return -errno;
        }
 
 
 ../lib/bitmap.c
 ../lib/find_bit.c
 ../lib/hweight.c
+../lib/str_error_r.c
 util/thread_map.c
 util/util.c
 util/xyarray.c
 
        BUG_ON(buflen == 0);
 
        if (errnum >= 0) {
-               const char *err = strerror_r(errnum, buf, buflen);
+               const char *err = str_error_r(errnum, buf, buflen);
 
                if (err != buf)
                        scnprintf(buf, buflen, "%s", err);
 
 void print_binary(unsigned char *data, size_t len,
                  size_t bytes_per_line, print_binary_t printer,
                  void *extra);
+
 #endif /* GIT_COMPAT_UTIL_H */