Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gendwarfksyms: Expand base_type

Start making gendwarfksyms more useful by adding support for
expanding DW_TAG_base_type types and basic DWARF attributes.

Example:

$ echo loops_per_jiffy | \
scripts/gendwarfksyms/gendwarfksyms \
--debug --dump-dies vmlinux.o
...
gendwarfksyms: process_symbol: loops_per_jiffy
variable base_type unsigned long byte_size(8) encoding(7)
...

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>

authored by

Sami Tolvanen and committed by
Masahiro Yamada
5b7780e8 e982abf4

+160
+160
scripts/gendwarfksyms/dwarf.c
··· 3 3 * Copyright (C) 2024 Google LLC 4 4 */ 5 5 6 + #include <inttypes.h> 7 + #include <stdarg.h> 6 8 #include "gendwarfksyms.h" 9 + 10 + #define DEFINE_GET_ATTR(attr, type) \ 11 + static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \ 12 + type *value) \ 13 + { \ 14 + Dwarf_Attribute da; \ 15 + return dwarf_attr(die, id, &da) && \ 16 + !dwarf_form##attr(&da, value); \ 17 + } 18 + 19 + DEFINE_GET_ATTR(udata, Dwarf_Word) 7 20 8 21 static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *value) 9 22 { ··· 80 67 fputs(s, stderr); 81 68 } 82 69 70 + #define MAX_FMT_BUFFER_SIZE 128 71 + 72 + static void process_fmt(const char *fmt, ...) 73 + { 74 + char buf[MAX_FMT_BUFFER_SIZE]; 75 + va_list args; 76 + 77 + va_start(args, fmt); 78 + 79 + if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >= sizeof(buf)) 80 + error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE"); 81 + 82 + process(buf); 83 + va_end(args); 84 + } 85 + 86 + #define MAX_FQN_SIZE 64 87 + 88 + /* Get a fully qualified name from DWARF scopes */ 89 + static char *get_fqn(Dwarf_Die *die) 90 + { 91 + const char *list[MAX_FQN_SIZE]; 92 + Dwarf_Die *scopes = NULL; 93 + bool has_name = false; 94 + char *fqn = NULL; 95 + char *p; 96 + int count = 0; 97 + int len = 0; 98 + int res; 99 + int i; 100 + 101 + res = checkp(dwarf_getscopes_die(die, &scopes)); 102 + if (!res) { 103 + list[count] = get_name_attr(die); 104 + 105 + if (!list[count]) 106 + return NULL; 107 + 108 + len += strlen(list[count]); 109 + count++; 110 + 111 + goto done; 112 + } 113 + 114 + for (i = res - 1; i >= 0 && count < MAX_FQN_SIZE; i--) { 115 + if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) 116 + continue; 117 + 118 + list[count] = get_name_attr(&scopes[i]); 119 + 120 + if (list[count]) { 121 + has_name = true; 122 + } else { 123 + list[count] = "<anonymous>"; 124 + has_name = false; 125 + } 126 + 127 + len += strlen(list[count]); 128 + count++; 129 + 130 + if (i > 0) { 131 + list[count++] = "::"; 132 + len += 2; 133 + } 134 + } 135 + 136 + free(scopes); 137 + 138 + if (count == MAX_FQN_SIZE) 139 + warn("increase MAX_FQN_SIZE: reached the maximum"); 140 + 141 + /* Consider the DIE unnamed if the last scope doesn't have a name */ 142 + if (!has_name) 143 + return NULL; 144 + done: 145 + fqn = xmalloc(len + 1); 146 + *fqn = '\0'; 147 + 148 + p = fqn; 149 + for (i = 0; i < count; i++) 150 + p = stpcpy(p, list[i]); 151 + 152 + return fqn; 153 + } 154 + 155 + static void process_fqn(Dwarf_Die *die) 156 + { 157 + process(" "); 158 + process(get_fqn(die) ?: ""); 159 + } 160 + 161 + #define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) \ 162 + static void process_##attribute##_attr(Dwarf_Die *die) \ 163 + { \ 164 + Dwarf_Word value; \ 165 + if (get_udata_attr(die, DW_AT_##attribute, &value)) \ 166 + process_fmt(" " #attribute "(%" PRIu64 ")", value); \ 167 + } 168 + 169 + DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) 170 + DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) 171 + DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) 172 + 83 173 bool match_all(Dwarf_Die *die) 84 174 { 85 175 return true; ··· 204 88 } 205 89 206 90 res = checkp(dwarf_siblingof(&current, &current)); 91 + } 92 + 93 + return 0; 94 + } 95 + 96 + static int process_type(struct state *state, Dwarf_Die *die); 97 + 98 + static void process_type_attr(struct state *state, Dwarf_Die *die) 99 + { 100 + Dwarf_Die type; 101 + 102 + if (get_ref_die_attr(die, DW_AT_type, &type)) { 103 + check(process_type(state, &type)); 104 + return; 105 + } 106 + 107 + /* Compilers can omit DW_AT_type -- print out 'void' to clarify */ 108 + process("base_type void"); 109 + } 110 + 111 + static void process_base_type(struct state *state, Dwarf_Die *die) 112 + { 113 + process("base_type"); 114 + process_fqn(die); 115 + process_byte_size_attr(die); 116 + process_encoding_attr(die); 117 + process_alignment_attr(die); 118 + } 119 + 120 + #define PROCESS_TYPE(type) \ 121 + case DW_TAG_##type##_type: \ 122 + process_##type##_type(state, die); \ 123 + break; 124 + 125 + static int process_type(struct state *state, Dwarf_Die *die) 126 + { 127 + int tag = dwarf_tag(die); 128 + 129 + switch (tag) { 130 + PROCESS_TYPE(base) 131 + default: 132 + debug("unimplemented type: %x", tag); 133 + break; 207 134 } 208 135 209 136 return 0; ··· 278 119 static int __process_variable(struct state *state, Dwarf_Die *die) 279 120 { 280 121 process("variable "); 122 + process_type_attr(state, die); 281 123 return 0; 282 124 } 283 125