"Hardware breakpoint",
 };
 
+static int cmp_string(const void *a, const void *b)
+{
+       const char * const *as = a;
+       const char * const *bs = b;
+
+       return strcmp(*as, *bs);
+}
+
 /*
  * Print the events from <debugfs_mount_point>/tracing/events
  */
        struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
        char evt_path[MAXPATHLEN];
        char dir_path[MAXPATHLEN];
+       char **evt_list = NULL;
+       unsigned int evt_i = 0, evt_num = 0;
+       bool evt_num_known = false;
 
+restart:
        sys_dir = opendir(tracing_events_path);
        if (!sys_dir)
                return;
 
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_close_sys_dir;
+       }
+
        for_each_subsystem(sys_dir, sys_dirent, sys_next) {
                if (subsys_glob != NULL &&
                    !strglobmatch(sys_dirent.d_name, subsys_glob))
                            !strglobmatch(evt_dirent.d_name, event_glob))
                                continue;
 
-                       if (name_only) {
-                               printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
+                       if (!evt_num_known) {
+                               evt_num++;
                                continue;
                        }
 
                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
                                 sys_dirent.d_name, evt_dirent.d_name);
-                       printf("  %-50s [%s]\n", evt_path,
-                               event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+
+                       evt_list[evt_i] = strdup(evt_path);
+                       if (evt_list[evt_i] == NULL)
+                               goto out_close_evt_dir;
+                       evt_i++;
                }
                closedir(evt_dir);
        }
        closedir(sys_dir);
+
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++],
+                               event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+       }
+       if (evt_num)
+               printf("\n");
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return;
+
+out_close_evt_dir:
+       closedir(evt_dir);
+out_close_sys_dir:
+       closedir(sys_dir);
+
+       printf("FATAL: not enough memory to print %s\n",
+                       event_type_descriptors[PERF_TYPE_TRACEPOINT]);
+       if (evt_list)
+               goto out_free;
 }
 
 /*
                                unsigned max)
 {
        char name[64];
-       unsigned i;
+       unsigned int i, evt_i = 0, evt_num = 0;
+       char **evt_list = NULL;
+       bool evt_num_known = false;
+
+restart:
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_enomem;
+               syms -= max;
+       }
 
        for (i = 0; i < max ; i++, syms++) {
                if (!is_event_supported(type, i))
                        continue;
 
+               if (!evt_num_known) {
+                       evt_num++;
+                       continue;
+               }
+
                if (strlen(syms->alias))
                        snprintf(name, sizeof(name),  "%s OR %s",
                                 syms->symbol, syms->alias);
                else
                        snprintf(name, sizeof(name), "%s", syms->symbol);
 
-               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
+               evt_list[evt_i] = strdup(name);
+               if (evt_list[evt_i] == NULL)
+                       goto out_enomem;
+               evt_i++;
+       }
+
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
        }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num)
+               printf("  %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
+       if (evt_num)
+               printf("\n");
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return;
+
+out_enomem:
+       printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
+       if (evt_list)
+               goto out_free;
 }
 
 void print_events_type(u8 type)
 
 int print_hwcache_events(const char *event_glob, bool name_only)
 {
-       unsigned int type, op, i, printed = 0;
+       unsigned int type, op, i, evt_i = 0, evt_num = 0;
        char name[64];
+       char **evt_list = NULL;
+       bool evt_num_known = false;
+
+restart:
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_enomem;
+       }
 
        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
                                                        type | (op << 8) | (i << 16)))
                                        continue;
 
-                               if (name_only)
-                                       printf("%s ", name);
-                               else
-                                       printf("  %-50s [%s]\n", name,
-                                              event_type_descriptors[PERF_TYPE_HW_CACHE]);
-                               ++printed;
+                               if (!evt_num_known) {
+                                       evt_num++;
+                                       continue;
+                               }
+
+                               evt_list[evt_i] = strdup(name);
+                               if (evt_list[evt_i] == NULL)
+                                       goto out_enomem;
+                               evt_i++;
                        }
                }
        }
 
-       if (printed)
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++],
+                               event_type_descriptors[PERF_TYPE_HW_CACHE]);
+       }
+       if (evt_num)
                printf("\n");
-       return printed;
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return evt_num;
+
+out_enomem:
+       printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
+       if (evt_list)
+               goto out_free;
+       return evt_num;
 }
 
 static void print_symbol_events(const char *event_glob, unsigned type,
                                struct event_symbol *syms, unsigned max,
                                bool name_only)
 {
-       unsigned i, printed = 0;
+       unsigned int i, evt_i = 0, evt_num = 0;
        char name[MAX_NAME_LEN];
+       char **evt_list = NULL;
+       bool evt_num_known = false;
+
+restart:
+       if (evt_num_known) {
+               evt_list = zalloc(sizeof(char *) * evt_num);
+               if (!evt_list)
+                       goto out_enomem;
+               syms -= max;
+       }
 
        for (i = 0; i < max; i++, syms++) {
 
                if (!is_event_supported(type, i))
                        continue;
 
-               if (name_only) {
-                       printf("%s ", syms->symbol);
+               if (!evt_num_known) {
+                       evt_num++;
                        continue;
                }
 
-               if (strlen(syms->alias))
+               if (!name_only && strlen(syms->alias))
                        snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
                else
                        strncpy(name, syms->symbol, MAX_NAME_LEN);
 
-               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
-
-               printed++;
+               evt_list[evt_i] = strdup(name);
+               if (evt_list[evt_i] == NULL)
+                       goto out_enomem;
+               evt_i++;
        }
 
-       if (printed)
+       if (!evt_num_known) {
+               evt_num_known = true;
+               goto restart;
+       }
+       qsort(evt_list, evt_num, sizeof(char *), cmp_string);
+       evt_i = 0;
+       while (evt_i < evt_num) {
+               if (name_only) {
+                       printf("%s ", evt_list[evt_i++]);
+                       continue;
+               }
+               printf("  %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
+       }
+       if (evt_num)
                printf("\n");
+
+out_free:
+       evt_num = evt_i;
+       for (evt_i = 0; evt_i < evt_num; evt_i++)
+               zfree(&evt_list[evt_i]);
+       zfree(&evt_list);
+       return;
+
+out_enomem:
+       printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
+       if (evt_list)
+               goto out_free;
 }
 
 /*