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

perf jitdump: Add sym/str-tables to build-ID generation

It was reported that python backtrace with JIT dump was broken after the
change to built-in SHA-1 implementation. It seems python generates the
same JIT code for each function. They will become separate DSOs but the
contents are the same. Only difference is in the symbol name.

But this caused a problem that every JIT'ed DSOs will have the same
build-ID which makes perf confused. And it resulted in no python
symbols (from JIT) in the output.

Looking back at the original code before the conversion, it used the
load_addr as well as the code section to distinguish each DSO. But it'd
be better to use contents of symtab and strtab instead as it aligns with
some linker behaviors.

This patch adds a buffer to save all the contents in a single place for
SHA-1 calculation. Probably we need to add sha1_update() or similar to
update the existing hash value with different contents and use it here.
But it's out of scope for this change and I'd like something that can be
backported to the stable trees easily.

Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Pablo Galindo <pablogsal@gmail.com>
Cc: Fangrui Song <maskray@sourceware.org>
Link: https://github.com/python/cpython/issues/139544
Fixes: e3f612c1d8f3945b ("perf genelf: Remove libcrypto dependency and use built-in sha1()")
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

+30 -2
+30 -2
tools/perf/util/genelf.c
··· 173 173 Elf_Shdr *shdr; 174 174 uint64_t eh_frame_base_offset; 175 175 char *strsym = NULL; 176 + void *build_id_data = NULL, *tmp; 177 + int build_id_data_len; 176 178 int symlen; 177 179 int retval = -1; 178 180 ··· 252 250 shdr->sh_addr = GEN_ELF_TEXT_OFFSET; 253 251 shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 254 252 shdr->sh_entsize = 0; 253 + 254 + build_id_data = malloc(csize); 255 + if (build_id_data == NULL) { 256 + warnx("cannot allocate build-id data"); 257 + goto error; 258 + } 259 + memcpy(build_id_data, code, csize); 260 + build_id_data_len = csize; 255 261 256 262 /* 257 263 * Setup .eh_frame_hdr and .eh_frame ··· 344 334 shdr->sh_entsize = sizeof(Elf_Sym); 345 335 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ 346 336 337 + tmp = realloc(build_id_data, build_id_data_len + sizeof(symtab)); 338 + if (tmp == NULL) { 339 + warnx("cannot allocate build-id data"); 340 + goto error; 341 + } 342 + memcpy(tmp + build_id_data_len, symtab, sizeof(symtab)); 343 + build_id_data = tmp; 344 + build_id_data_len += sizeof(symtab); 345 + 347 346 /* 348 347 * setup symbols string table 349 348 * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry ··· 395 376 shdr->sh_flags = 0; 396 377 shdr->sh_entsize = 0; 397 378 379 + tmp = realloc(build_id_data, build_id_data_len + symlen); 380 + if (tmp == NULL) { 381 + warnx("cannot allocate build-id data"); 382 + goto error; 383 + } 384 + memcpy(tmp + build_id_data_len, strsym, symlen); 385 + build_id_data = tmp; 386 + build_id_data_len += symlen; 387 + 398 388 /* 399 389 * setup build-id section 400 390 */ ··· 422 394 /* 423 395 * build-id generation 424 396 */ 425 - sha1(code, csize, bnote.build_id); 397 + sha1(build_id_data, build_id_data_len, bnote.build_id); 426 398 bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ 427 399 bnote.desc.descsz = sizeof(bnote.build_id); 428 400 bnote.desc.type = NT_GNU_BUILD_ID; ··· 467 439 (void)elf_end(e); 468 440 469 441 free(strsym); 470 - 442 + free(build_id_data); 471 443 472 444 return retval; 473 445 }