diff options
author | Cary Coutant <ccoutant@google.com> | 2015-02-03 19:54:57 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2015-02-03 20:03:42 -0800 |
commit | 2cfbf2fece582c29df348104b28677c38a8301f4 (patch) | |
tree | ab77dd5b5a56e32e52a6e9824298d9afdd7ea093 /gold/testsuite/plugin_test.c | |
parent | 8265ef950202a4bf0d3444802ad5d7087b4b185d (diff) | |
download | gdb-2cfbf2fece582c29df348104b28677c38a8301f4.zip gdb-2cfbf2fece582c29df348104b28677c38a8301f4.tar.gz gdb-2cfbf2fece582c29df348104b28677c38a8301f4.tar.bz2 |
Fix a file descriptor leak in gold.
When an LTO linker plugin claims an external member of a thin archive, gold
does not properly unlock the file and make its file descriptor available for
reuse. This patch fixes the problem by modifying Archive::include_member to
unlock the object file via an RAII class instance, ensuring that it will be
unlocked no matter what path is taken through the function.
gold/
PR gold/15660
* archive.cc (Thin_archive_object_unlocker): New class.
(Archive::include_member): Unlock external members of thin archives.
* testsuite/Makefile.am (plugin_test_1): Rename .syms files.
(plugin_test_2): Likewise.
(plugin_test_3): Likewise.
(plugin_test_4): Likewise.
(plugin_test_5): Likewise.
(plugin_test_6): Likewise.
(plugin_test_7): Likewise.
(plugin_test_8): Likewise.
(plugin_test_9): Likewise.
(plugin_test_10): Likewise.
(plugin_test_11): New test case.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
file to decide whether to claim file.
(all_symbols_read_hook): Likewise.
* testsuite/plugin_test_1.sh: Adjust expected output.
* testsuite/plugin_test_2.sh: Likewise.
* testsuite/plugin_test_3.sh: Likewise.
* testsuite/plugin_test_6.sh: Likewise.
* testsuite/plugin_test_tls.sh: Likewise.
* testsuite/plugin_test_11.sh: New testcase.
Diffstat (limited to 'gold/testsuite/plugin_test.c')
-rw-r--r-- | gold/testsuite/plugin_test.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/gold/testsuite/plugin_test.c b/gold/testsuite/plugin_test.c index d2175e8..cf6adf3 100644 --- a/gold/testsuite/plugin_test.c +++ b/gold/testsuite/plugin_test.c @@ -263,15 +263,35 @@ claim_file_hook (const struct ld_plugin_input_file* file, int* claimed) int vis; int is_comdat; int i; + int irfile_was_opened = 0; + char syms_name[80]; (*message)(LDPL_INFO, "%s: claim file hook called (offset = %ld, size = %ld)", file->name, (long)file->offset, (long)file->filesize); + /* Look for matching syms file for an archive member. */ + if (file->offset == 0) + snprintf(syms_name, sizeof(syms_name), "%s.syms", file->name); + else + snprintf(syms_name, sizeof(syms_name), "%s-%d.syms", + file->name, (int)file->offset); + irfile = fopen(syms_name, "r"); + if (irfile != NULL) + { + irfile_was_opened = 1; + end_offset = 1 << 20; + } + + /* Otherwise, see if the file itself is a syms file. */ + if (!irfile_was_opened) + { + irfile = fdopen(file->fd, "r"); + (void)fseek(irfile, file->offset, SEEK_SET); + end_offset = file->offset + file->filesize; + } + /* Look for the beginning of output from readelf -s. */ - irfile = fdopen(file->fd, "r"); - (void)fseek(irfile, file->offset, SEEK_SET); - end_offset = file->offset + file->filesize; len = fread(buf, 1, 13, irfile); if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0) return LDPS_OK; @@ -378,6 +398,8 @@ claim_file_hook (const struct ld_plugin_input_file* file, int* claimed) (*add_symbols)(file->handle, nsyms, syms); *claimed = 1; + if (irfile_was_opened) + fclose(irfile); return LDPS_OK; } @@ -474,12 +496,31 @@ all_symbols_read_hook(void) claimed_file != NULL; claimed_file = claimed_file->next) { + int irfile_was_opened = 0; + char syms_name[80]; + (*get_input_file) (claimed_file->handle, &file); + if (file.offset == 0) + snprintf(syms_name, sizeof(syms_name), "%s.syms", file.name); + else + snprintf(syms_name, sizeof(syms_name), "%s-%d.syms", + file.name, (int)file.offset); + irfile = fopen(syms_name, "r"); + if (irfile != NULL) + { + irfile_was_opened = 1; + end_offset = 1 << 20; + } + + if (!irfile_was_opened) + { + irfile = fdopen(file.fd, "r"); + (void)fseek(irfile, file.offset, SEEK_SET); + end_offset = file.offset + file.filesize; + } + /* Look for the beginning of output from readelf -s. */ - irfile = fdopen(file.fd, "r"); - (void)fseek(irfile, file.offset, SEEK_SET); - end_offset = file.offset + file.filesize; len = fread(buf, 1, 13, irfile); if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0) { @@ -509,6 +550,9 @@ all_symbols_read_hook(void) } } + if (irfile_was_opened) + fclose(irfile); + (*release_input_file) (claimed_file->handle); if (filename == NULL) |