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

perf symbols: Preparation for compressed kernel module support

This patch adds basic support to handle compressed kernel module as some
distro (such as Archlinux) carries on it now. The actual work using
compression library will be added later.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1415063674-17206-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
c00c48fc 758008b2

+141 -3
+75
tools/perf/util/dso.c
··· 21 21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 22 22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 23 23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 24 + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', 24 25 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 25 26 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 27 + [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', 26 28 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 27 29 }; 28 30 ··· 114 112 break; 115 113 116 114 case DSO_BINARY_TYPE__GUEST_KMODULE: 115 + case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: 117 116 path__join3(filename, size, symbol_conf.symfs, 118 117 root_dir, dso->long_name); 119 118 break; 120 119 121 120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 121 + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: 122 122 __symbol__join_symfs(filename, size, dso->long_name); 123 123 break; 124 124 ··· 139 135 } 140 136 141 137 return ret; 138 + } 139 + 140 + static int decompress_dummy(const char *input __maybe_unused, 141 + int output __maybe_unused) 142 + { 143 + return -1; 144 + } 145 + 146 + static const struct { 147 + const char *fmt; 148 + int (*decompress)(const char *input, int output); 149 + } compressions[] = { 150 + { "gz", decompress_dummy }, 151 + { NULL, }, 152 + }; 153 + 154 + bool is_supported_compression(const char *ext) 155 + { 156 + unsigned i; 157 + 158 + for (i = 0; compressions[i].fmt; i++) { 159 + if (!strcmp(ext, compressions[i].fmt)) 160 + return true; 161 + } 162 + return false; 163 + } 164 + 165 + bool is_kmodule_extension(const char *ext) 166 + { 167 + if (strncmp(ext, "ko", 2)) 168 + return false; 169 + 170 + if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3))) 171 + return true; 172 + 173 + return false; 174 + } 175 + 176 + bool is_kernel_module(const char *pathname, bool *compressed) 177 + { 178 + const char *ext = strrchr(pathname, '.'); 179 + 180 + if (ext == NULL) 181 + return false; 182 + 183 + if (is_supported_compression(ext + 1)) { 184 + if (compressed) 185 + *compressed = true; 186 + ext -= 3; 187 + } else if (compressed) 188 + *compressed = false; 189 + 190 + return is_kmodule_extension(ext + 1); 191 + } 192 + 193 + bool decompress_to_file(const char *ext, const char *filename, int output_fd) 194 + { 195 + unsigned i; 196 + 197 + for (i = 0; compressions[i].fmt; i++) { 198 + if (!strcmp(ext, compressions[i].fmt)) 199 + return !compressions[i].decompress(filename, 200 + output_fd); 201 + } 202 + return false; 203 + } 204 + 205 + bool dso__needs_decompress(struct dso *dso) 206 + { 207 + return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || 208 + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 142 209 } 143 210 144 211 /*
+7
tools/perf/util/dso.h
··· 22 22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 23 23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 24 24 DSO_BINARY_TYPE__GUEST_KMODULE, 25 + DSO_BINARY_TYPE__GUEST_KMODULE_COMP, 25 26 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 27 + DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, 26 28 DSO_BINARY_TYPE__KCORE, 27 29 DSO_BINARY_TYPE__GUEST_KCORE, 28 30 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, ··· 187 185 char dso__symtab_origin(const struct dso *dso); 188 186 int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 189 187 char *root_dir, char *filename, size_t size); 188 + bool is_supported_compression(const char *ext); 189 + bool is_kmodule_extension(const char *ext); 190 + bool is_kernel_module(const char *pathname, bool *compressed); 191 + bool decompress_to_file(const char *ext, const char *filename, int output_fd); 192 + bool dso__needs_decompress(struct dso *dso); 190 193 191 194 /* 192 195 * The dso__data_* external interface provides following functions:
+18 -1
tools/perf/util/machine.c
··· 464 464 { 465 465 struct map *map; 466 466 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 467 + bool compressed; 467 468 468 469 if (dso == NULL) 469 470 return NULL; ··· 477 476 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 478 477 else 479 478 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 479 + 480 + /* _KMODULE_COMP should be next to _KMODULE */ 481 + if (is_kernel_module(filename, &compressed) && compressed) 482 + dso->symtab_type++; 483 + 480 484 map_groups__insert(&machine->kmaps, map); 481 485 return map; 482 486 } ··· 867 861 struct map *map; 868 862 char *long_name; 869 863 870 - if (dot == NULL || strcmp(dot, ".ko")) 864 + if (dot == NULL) 871 865 continue; 866 + 867 + /* On some system, modules are compressed like .ko.gz */ 868 + if (is_supported_compression(dot + 1) && 869 + is_kmodule_extension(dot - 2)) 870 + dot -= 3; 871 + 872 872 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 873 873 (int)(dot - dent->d_name), dent->d_name); 874 874 ··· 1055 1043 ++name; /* skip / */ 1056 1044 dot = strrchr(name, '.'); 1057 1045 if (dot == NULL) 1046 + goto out_problem; 1047 + /* On some system, modules are compressed like .ko.gz */ 1048 + if (is_supported_compression(dot + 1)) 1049 + dot -= 3; 1050 + if (!is_kmodule_extension(dot + 1)) 1058 1051 goto out_problem; 1059 1052 snprintf(short_module_name, sizeof(short_module_name), 1060 1053 "[%.*s]", (int)(dot - name), name);
+34 -1
tools/perf/util/symbol-elf.c
··· 546 546 return 0; 547 547 } 548 548 549 + static int decompress_kmodule(struct dso *dso, const char *name, 550 + enum dso_binary_type type) 551 + { 552 + int fd; 553 + const char *ext = strrchr(name, '.'); 554 + char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 555 + 556 + if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 557 + type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || 558 + type != dso->symtab_type) 559 + return -1; 560 + 561 + if (!ext || !is_supported_compression(ext + 1)) 562 + return -1; 563 + 564 + fd = mkstemp(tmpbuf); 565 + if (fd < 0) 566 + return -1; 567 + 568 + if (!decompress_to_file(ext + 1, name, fd)) { 569 + close(fd); 570 + fd = -1; 571 + } 572 + 573 + unlink(tmpbuf); 574 + 575 + return fd; 576 + } 577 + 549 578 bool symsrc__possibly_runtime(struct symsrc *ss) 550 579 { 551 580 return ss->dynsym || ss->opdsec; ··· 600 571 Elf *elf; 601 572 int fd; 602 573 603 - fd = open(name, O_RDONLY); 574 + if (dso__needs_decompress(dso)) 575 + fd = decompress_kmodule(dso, name, type); 576 + else 577 + fd = open(name, O_RDONLY); 578 + 604 579 if (fd < 0) 605 580 return -1; 606 581
+7 -1
tools/perf/util/symbol.c
··· 51 51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 52 52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 53 53 DSO_BINARY_TYPE__GUEST_KMODULE, 54 + DSO_BINARY_TYPE__GUEST_KMODULE_COMP, 54 55 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 56 + DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, 55 57 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 56 58 DSO_BINARY_TYPE__NOT_FOUND, 57 59 }; ··· 1302 1300 return dso->kernel == DSO_TYPE_GUEST_KERNEL; 1303 1301 1304 1302 case DSO_BINARY_TYPE__GUEST_KMODULE: 1303 + case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: 1305 1304 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 1305 + case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: 1306 1306 /* 1307 1307 * kernel modules know their symtab type - it's set when 1308 1308 * creating a module dso in machine__new_module(). ··· 1372 1368 return -1; 1373 1369 1374 1370 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 1375 - dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; 1371 + dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || 1372 + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || 1373 + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 1376 1374 1377 1375 /* 1378 1376 * Iterate over candidate debug images.