Hi, When building dwz with -fsanitize=address, we run into some memory leaks: ... $ cp hello 1; ./dwz 1; cp 1 2; ./dwz -m 3 1 2 ./dwz: 1: DWARF compression not beneficial - old size 3372 new size 3372 ./dwz: 2: DWARF compression not beneficial - old size 3372 new size 3372 ================================================================= ==8024==ERROR: LeakSanitizer: detected memory leaks Direct leak of 432 byte(s) in 6 object(s) allocated from: #0 0x7f7ab92cc6d8 in __interceptor_calloc \ (/usr/lib64/libasan.so.4+0xdc6d8) #1 0x475dc1 in htab_try_create hashtab.c:164 #2 0x44c610 in build_abbrevs dwz.c:11230 #3 0x44ee00 in compute_abbrevs dwz.c:11510 #4 0x46f07c in dwz dwz.c:15396 #5 0x474e0d in dwz_files_1 dwz.c:16327 #6 0x475699 in dwz_files dwz.c:16417 #7 0x4759fc in main dwz.c:16458 #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349) Indirect leak of 2928 byte(s) in 6 object(s) allocated from: #0 0x7f7ab92cc6d8 in __interceptor_calloc \ (/usr/lib64/libasan.so.4+0xdc6d8) #1 0x475de7 in htab_try_create hashtab.c:168 #2 0x44c610 in build_abbrevs dwz.c:11230 #3 0x44ee00 in compute_abbrevs dwz.c:11510 #4 0x46f07c in dwz dwz.c:15396 #5 0x474e0d in dwz_files_1 dwz.c:16327 #6 0x475699 in dwz_files dwz.c:16417 #7 0x4759fc in main dwz.c:16458 #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349) SUMMARY: AddressSanitizer: 3360 byte(s) leaked in 12 allocation(s). ... A more concrete way to show some of the leaks is by using this patch on build_abbrevs: ... + assert (cu->cu_new_abbrev == NULL); cu->cu_new_abbrev = h; return 0; } ... which triggers here: ... #4 0x00000000004211b1 in build_abbrevs (cu=0x7ffff65f0e38, t=0x64e640, ndies=0x7fffffffd81c, vec=0x649280 <ob2>) at dwz.c:11239 #5 0x0000000000421db2 in compute_abbrevs (dso=0x0) at dwz.c:11511 #6 0x000000000042fa2c in write_multifile (dso=0x64c210) at dwz.c:15104 ... We could just do a htab_delete in build_abbrevs, which takes care of all the leaks detected by the assert. But write_multifile drops CUs from the cu list if cu->cu_die->die_no_multifile == 1, and if a dropped CU has cu->cu_new_abbrev != NULL then cu_new_abbrev is still leaked. Fix this by calling htab_delete in the loop that drops the CUs. Committed to trunk. Thanks, - Tom Fix memory leak in write_multifile 2021-03-24 Tom de Vries <tdevries@suse.de> PR dwz/27643 * dwz.c (write_multifile): Clean up cu->cu_new_abbrev to fix memory leak. --- dwz.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dwz.c b/dwz.c index c115b54..b212d6d 100644 --- a/dwz.c +++ b/dwz.c @@ -15092,10 +15092,15 @@ write_multifile (DSO *dso) dw_cu_ref *cup; for (cup = &first_cu; *cup && (*cup)->cu_kind != CU_TYPES; ) - if ((*cup)->cu_die->die_no_multifile == 0) - cup = &(*cup)->cu_next; - else - *cup = (*cup)->cu_next; + { + if ((*cup)->cu_new_abbrev) + htab_delete ((*cup)->cu_new_abbrev); + + if ((*cup)->cu_die->die_no_multifile == 0) + cup = &(*cup)->cu_next; + else + *cup = (*cup)->cu_next; + } *cup = NULL; multifile_mode = MULTIFILE_MODE_WR; if (tracing)