clang(1) and gcc(1) have two different ways to generate names for
non-global variables declared as static:

  $ nm bsd.gcc |grep faultbuf                                      
  ffffffff81daba40 b faultbuf.6183
        
  $ nm bsd.clang |grep faultbuf
  ffffffff81f52f30 b pageflttrap.faultbuf

Diff below adds this heuristic in ctfconv(1) to make sure the correct
type is picked for clang-generated binaries.

While here skip well known meta symbols to keep the CTF section small.

ok?

Index: ctfconv.c
===================================================================
RCS file: /cvs/src/usr.bin/ctfconv/ctfconv.c,v
retrieving revision 1.17
diff -u -p -r1.17 ctfconv.c
--- ctfconv.c   8 Aug 2018 20:15:17 -0000       1.17
+++ ctfconv.c   5 Nov 2019 17:05:22 -0000
@@ -27,6 +27,7 @@
 #include <elf.h>
 #include <err.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <locale.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -51,6 +52,7 @@ int            convert(const char *);
 int             generate(const char *, const char *, int);
 int             elf_convert(char *, size_t);
 void            elf_sort(void);
+char           *guess_static_local_name(char *);
 struct itype   *find_symb(struct itype *, size_t);
 void            dump_type(struct itype *);
 void            dump_func(struct itype *, int *);
@@ -261,6 +263,50 @@ elf_convert(char *p, size_t filesize)
        return 0;
 }
 
+/*
+ * Guess which part of a local symbol name correspond to the variable
+ * name.
+ *
+ * gcc 4.2.1 emits:
+ *
+ *     varname.id
+ *
+ * clang 8 emits:
+ *
+ *     funcname.varname
+ *
+ */
+char *
+guess_static_local_name(char *sname)
+{
+       const char *errstr;
+       char *first, *second;
+
+       first = strtok(sname, ".");
+       if (first == NULL)
+               return NULL;
+
+       /* Skip meta symbols - gcc style. */
+       if (strncmp(first, "__func__", sizeof("__func__") - 1) == 0 ||
+           strncmp(first, "__FUNCTION__", sizeof("__FUNCTION__") - 1) == 0 ||
+           strncmp(first, "__warned", sizeof("__warned") - 1) == 0)
+               return NULL;
+
+       second = strtok(NULL, "\0");
+       if (second == NULL)
+               return first;
+
+       /* Skip meta symbols - clang style. */
+       if (strncmp(second, "__warned", sizeof("__warned") - 1) == 0)
+               return NULL;
+
+       /* If `second' isn't a number, assume clang-style name. */
+       if (strtonum(second, 1, INT_MAX, &errstr) == 0)
+               return second;
+
+       return first;
+}
+
 struct itype *
 find_symb(struct itype *tmp, size_t stroff)
 {
@@ -270,13 +316,8 @@ find_symb(struct itype *tmp, size_t stro
        if (strtab == NULL || stroff >= strtabsz)
                return NULL;
 
-       /*
-        * Skip local suffix
-        *
-        * FIXME: only skip local copies.
-        */
        sname = xstrdup(strtab + stroff);
-       if ((p = strtok(sname, ".")) == NULL) {
+       if ((p = guess_static_local_name(sname)) == NULL) {
                free(sname);
                return NULL;
        }

Reply via email to