Merge tag 'x86_timers_for_v6.1_rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-rpi.git] / scripts / kallsyms.c
index f18e6df..ff5e781 100644 (file)
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
-#define KSYM_NAME_LEN          128
+#define _stringify_1(x)        #x
+#define _stringify(x)  _stringify_1(x)
+
+#define KSYM_NAME_LEN          512
+
+/*
+ * A substantially bigger size than the current maximum.
+ *
+ * It cannot be defined as an expression because it gets stringified
+ * for the fscanf() format string. Therefore, a _Static_assert() is
+ * used instead to maintain the relationship with KSYM_NAME_LEN.
+ */
+#define KSYM_NAME_LEN_BUFFER   2048
+_Static_assert(
+       KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4,
+       "Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN"
+);
 
 struct sym_entry {
        unsigned long long addr;
@@ -119,6 +135,7 @@ static bool is_ignored_symbol(const char *name, char type)
                "__ThumbV7PILongThunk_",
                "__LA25Thunk_",         /* mips lld */
                "__microLA25Thunk_",
+               "__kcfi_typeid_",       /* CFI type identifiers */
                NULL
        };
 
@@ -198,15 +215,15 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
 
 static struct sym_entry *read_symbol(FILE *in)
 {
-       char name[500], type;
+       char name[KSYM_NAME_LEN_BUFFER+1], type;
        unsigned long long addr;
        unsigned int len;
        struct sym_entry *sym;
        int rc;
 
-       rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name);
+       rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN_BUFFER) "s\n", &addr, &type, name);
        if (rc != 3) {
-               if (rc != EOF && fgets(name, 500, in) == NULL)
+               if (rc != EOF && fgets(name, ARRAY_SIZE(name), in) == NULL)
                        fprintf(stderr, "Read error or end of file.\n");
                return NULL;
        }
@@ -471,12 +488,35 @@ static void write_src(void)
                if ((i & 0xFF) == 0)
                        markers[i >> 8] = off;
 
-               printf("\t.byte 0x%02x", table[i]->len);
+               /* There cannot be any symbol of length zero. */
+               if (table[i]->len == 0) {
+                       fprintf(stderr, "kallsyms failure: "
+                               "unexpected zero symbol length\n");
+                       exit(EXIT_FAILURE);
+               }
+
+               /* Only lengths that fit in up-to-two-byte ULEB128 are supported. */
+               if (table[i]->len > 0x3FFF) {
+                       fprintf(stderr, "kallsyms failure: "
+                               "unexpected huge symbol length\n");
+                       exit(EXIT_FAILURE);
+               }
+
+               /* Encode length with ULEB128. */
+               if (table[i]->len <= 0x7F) {
+                       /* Most symbols use a single byte for the length. */
+                       printf("\t.byte 0x%02x", table[i]->len);
+                       off += table[i]->len + 1;
+               } else {
+                       /* "Big" symbols use two bytes. */
+                       printf("\t.byte 0x%02x, 0x%02x",
+                               (table[i]->len & 0x7F) | 0x80,
+                               (table[i]->len >> 7) & 0x7F);
+                       off += table[i]->len + 2;
+               }
                for (k = 0; k < table[i]->len; k++)
                        printf(", 0x%02x", table[i]->sym[k]);
                printf("\n");
-
-               off += table[i]->len + 1;
        }
        printf("\n");