From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id 99F5D3953801 for ; Tue, 10 Mar 2020 00:12:29 +0000 (GMT) Received: by mail-pl1-x62d.google.com with SMTP id b22so4665218pls.12 for ; Mon, 09 Mar 2020 17:12:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=D9Ono+ud5GTNKzNhT4VabJP/KqCOaXkKYBPhlFex2l0=; b=qwsgW/aQzYG1M6PtI2w8fQMqBU9kYVT+IpNjJKodT3F0g6foKornIEK5RmWJwWw+0y WdnRFRLKw6us5nB6yZa8lhgg32Ug8lLy9Y+fTJ0RHVE6PF5PUrD3tbPscTLXEkbiygS9 jZJK+6y3380zggZ+rmIiqzHgsHz3U+qNyEhctiDoalRsBja88RtlwCIiyijv8yl08fSy nJzsD7xb2uOY4Cm+v+U17ruSA4lzyWIxTorSFgEMNnecPh9gn8V1U0g1dUlyZDuNBNLA fdRrAvJUmnG+LykCN06mCd77PcMwNNZ4cGtTHxe7t7d2ciYXzl+XeWwSf0hXGIWk67Ic CHYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=D9Ono+ud5GTNKzNhT4VabJP/KqCOaXkKYBPhlFex2l0=; b=eFIska+8T5odf3SluD61S3hyO9hHsqtHX1LiGVEhghOzzKmN74aTzTm2KbWT4/JX52 sW4B7MxWxXvnqMMR3xBngmCB32Z5g5PxCjuimZEUkBD21HOuxkWEG7XYct4IueatwJgw 4vRR7sdir6tRrqkwJUeHRciC5swxOPhOQngnsPWwJEYx3wAULUo/XZX647z8acek1CQ4 5fysHNQLL/1fDVXfx2YXOJvRXSjEKsy8+7+CJGyntTAiSU8EZNeavWirFtIVvbYfdaDL 5pSotDPPejERJ4p5G5LIb4EKRsNLFRCFays+l7HD2Zzv/0l7owka7BmMIbfU+SzDqV3K EF5g== X-Gm-Message-State: ANhLgQ25WfxLOux2cFPmxD9MfrAcZinOgpC9phGHhRxDaOJpp4Rgq7Mh YQ84qw8kbeVBPtR2UnbKHB7v1kZU X-Google-Smtp-Source: ADFU+vueZ+qKwcAUinX/aIv/9i23wyZI3wsuflUcPXjwzyNWia/TqvN9loU25+wXruHK2ddXOHAB1A== X-Received: by 2002:a17:90b:1104:: with SMTP id gi4mr1972521pjb.117.1583799147760; Mon, 09 Mar 2020 17:12:27 -0700 (PDT) Received: from gnu-cfl-2.localdomain (c-73-93-86-59.hsd1.ca.comcast.net. [73.93.86.59]) by smtp.gmail.com with ESMTPSA id u13sm616535pjn.29.2020.03.09.17.12.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Mar 2020 17:12:26 -0700 (PDT) Received: from gnu-cfl-2.hsd1.ca.comcast.net (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id E6E40C04D8 for ; Mon, 9 Mar 2020 17:12:24 -0700 (PDT) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH 3/7] readelf: Compute dynamic symbol table size from hash table Date: Mon, 9 Mar 2020 17:12:20 -0700 Message-Id: <20200310001224.131714-5-hjl.tools@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200310001224.131714-1-hjl.tools@gmail.com> References: <20200310001224.131714-1-hjl.tools@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-27.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Mar 2020 00:12:30 -0000 When reconstructing dynamic symbol table from the PT_DYNAMIC segment, compute dynamic symbol table size from hash table. For DT_HASH, the number of dynamic symbol table entries equals the number of chains. For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL indings are in hash table. Since in dynamic symbol table, all symbols with STB_LOCAL binding are placed before symbols with other bindings and all undefined symbols are placed before defined ones, the highest symbol index in DT_GNU_HASH and DT_MIPS_XHASH is the highest dynamic symbol table index. Also iterate dynamic symbol table to print each entry so that output of "readelf -D -s" without section header is similar to "readelf -s" with section header. ` binutils/ PR ld/25617 * readelf.c (process_dynamic_section): Use DT_SYMTAB and DT_SYMENT to reconstruct dynamic symbol table, assuming dynamic symbol table ends at the end of PT_LOAD segment. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string table. Set dynamic_info_DT_MIPS_XHASH and dynamic_info_DT_GNU_HASH for -D. (get_symbol_index_type): Don't print "bad section index" when there is no section header. (print_dynamic_symbol): Don't print bucket number. (process_symbol_table): Compute dynamic symbol table size from hash table and iterate dynamic symbol table to print each entry. ld/ PR ld/25617 * testsuite/ld-elf/hash.d: Updated. * testsuite/ld-elf/pr13195.d: Likewise. * testsuite/ld-elfvsb/hidden2.d: Likewise. * testsuite/ld-mips-elf/hash2.d: Likewise. --- binutils/readelf.c | 226 ++++++++++++++++--------------- ld/testsuite/ld-elf/hash.d | 8 +- ld/testsuite/ld-elf/pr13195.d | 2 +- ld/testsuite/ld-elfvsb/hidden2.d | 2 +- ld/testsuite/ld-mips-elf/hash2.d | 8 +- 5 files changed, 125 insertions(+), 121 deletions(-) diff --git a/binutils/readelf.c b/binutils/readelf.c index 260ea33ba4..7ae6201c55 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -9863,102 +9863,103 @@ process_dynamic_section (Filedata * filedata) /* Find the appropriate symbol table. */ if (dynamic_symbols == NULL) - { - for (entry = dynamic_section; - entry < dynamic_section + dynamic_nent; - ++entry) - { - Elf_Internal_Shdr section; + for (entry = dynamic_section; + entry < dynamic_section + dynamic_nent; + ++entry) + { + if (entry->d_tag == DT_SYMTAB) + dynamic_info[DT_SYMTAB] = entry->d_un.d_val; - if (entry->d_tag != DT_SYMTAB) - continue; + if (entry->d_tag == DT_SYMENT) + dynamic_info[DT_SYMENT] = entry->d_un.d_val; - dynamic_info[DT_SYMTAB] = entry->d_un.d_val; + if (dynamic_info[DT_SYMTAB] && dynamic_info[DT_SYMENT]) + { + Elf_Internal_Phdr *seg; + bfd_vma vma = dynamic_info[DT_SYMTAB]; - /* Since we do not know how big the symbol table is, - we default to reading in the entire file (!) and - processing that. This is overkill, I know, but it - should work. */ - section.sh_offset = offset_from_vma (filedata, entry->d_un.d_val, 0); - if ((bfd_size_type) section.sh_offset > filedata->file_size) - { - /* See PR 21379 for a reproducer. */ - error (_("Invalid DT_SYMTAB entry: %lx\n"), - (long) section.sh_offset); - return FALSE; - } + if (! get_program_headers (filedata)) + { + warn (_("Cannot interpret virtual addresses without program headers.\n")); + break; + } - if (archive_file_offset != 0) - section.sh_size = archive_file_size - section.sh_offset; - else - section.sh_size = filedata->file_size - section.sh_offset; + for (seg = filedata->program_headers; + seg < filedata->program_headers + filedata->file_header.e_phnum; + ++seg) + { + if (seg->p_type != PT_LOAD) + continue; - if (is_32bit_elf) - section.sh_entsize = sizeof (Elf32_External_Sym); - else - section.sh_entsize = sizeof (Elf64_External_Sym); - section.sh_name = filedata->string_table_length; + if ((seg->p_offset + seg->p_filesz) + > filedata->file_size) + { + /* See PR 21379 for a reproducer. */ + error (_("Invalid PT_LOAD entry\n")); + return FALSE; + } - if (dynamic_symbols != NULL) - { - error (_("Multiple dynamic symbol table sections found\n")); - free (dynamic_symbols); - } - dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms); - if (num_dynamic_syms < 1) - { - error (_("Unable to determine the number of symbols to load\n")); - continue; - } - } - } + if (vma >= (seg->p_vaddr & -seg->p_align) + && vma <= seg->p_vaddr + seg->p_filesz) + { + /* Since we do not know how big the symbol table is, + we default to reading in up to the end of PT_LOAD + segment and processing that. This is overkill, I + know, but it should work. */ + Elf_Internal_Shdr section; + bfd_size_type offset = (vma - seg->p_vaddr + + seg->p_offset); + bfd_size_type max_symtab_size + = seg->p_offset + seg->p_filesz - offset; + section.sh_offset = offset; + section.sh_size = max_symtab_size; + section.sh_entsize = dynamic_info[DT_SYMENT]; + section.sh_name = filedata->string_table_length; + dynamic_symbols = GET_ELF_SYMBOLS (filedata, + §ion, + & num_dynamic_syms); + if (dynamic_symbols == NULL) + error (_("Corrupt DT_SYMTAB dynamic entry\n")); + } + } + + break; + } + } /* Similarly find a string table. */ if (dynamic_strings == NULL) - { - for (entry = dynamic_section; - entry < dynamic_section + dynamic_nent; - ++entry) - { - unsigned long offset; - long str_tab_len; - - if (entry->d_tag != DT_STRTAB) - continue; - + for (entry = dynamic_section; + entry < dynamic_section + dynamic_nent; + ++entry) + { + if (entry->d_tag == DT_STRTAB) dynamic_info[DT_STRTAB] = entry->d_un.d_val; - /* Since we do not know how big the string table is, - we default to reading in the entire file (!) and - processing that. This is overkill, I know, but it - should work. */ + if (entry->d_tag == DT_STRSZ) + dynamic_info[DT_STRSZ] = entry->d_un.d_val; - offset = offset_from_vma (filedata, entry->d_un.d_val, 0); - - if (archive_file_offset != 0) - str_tab_len = archive_file_size - offset; - else - str_tab_len = filedata->file_size - offset; - - if (str_tab_len < 1) - { - error - (_("Unable to determine the length of the dynamic string table\n")); - continue; - } - - if (dynamic_strings != NULL) - { - error (_("Multiple dynamic string tables found\n")); - free (dynamic_strings); - } + if (dynamic_info[DT_STRTAB] && dynamic_info[DT_STRSZ]) + { + unsigned long offset; + bfd_size_type str_tab_len = dynamic_info[DT_STRSZ]; + + offset = offset_from_vma (filedata, + dynamic_info[DT_STRTAB], + str_tab_len); + dynamic_strings = (char *) get_data (NULL, filedata, offset, 1, + str_tab_len, + _("dynamic string table")); + if (dynamic_strings == NULL) + { + error (_("Corrupt DT_STRTAB dynamic entry\n")); + break; + } - dynamic_strings = (char *) get_data (NULL, filedata, offset, 1, - str_tab_len, - _("dynamic string table")); - dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len; - } - } + dynamic_strings_length = str_tab_len; + break; + } + } /* And find the syminfo section if available. */ if (dynamic_syminfo == NULL) @@ -10515,6 +10516,14 @@ process_dynamic_section (Filedata * filedata) putchar ('\n'); } } + else if (do_using_dynamic + && (filedata->file_header.e_machine == EM_MIPS + || filedata->file_header.e_machine == EM_MIPS_RS3_LE) + && entry->d_tag == DT_MIPS_XHASH) + { + dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val; + dynamic_info_DT_GNU_HASH = entry->d_un.d_val; + } break; } } @@ -11401,7 +11410,8 @@ get_symbol_index_type (Filedata * filedata, unsigned int type) sprintf (buff, "OS [0x%04x]", type & 0xffff); else if (type >= SHN_LORESERVE) sprintf (buff, "RSV[0x%04x]", type & 0xffff); - else if (type >= filedata->file_header.e_shnum) + else if (filedata->file_header.e_shnum != 0 + && type >= filedata->file_header.e_shnum) sprintf (buff, _("bad section index[%3d]"), type); else sprintf (buff, "%3d", type); @@ -11471,7 +11481,7 @@ get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_si } static void -print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn) +print_dynamic_symbol (Filedata * filedata, bfd_vma si) { Elf_Internal_Sym * psym; int n; @@ -11479,7 +11489,7 @@ print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn) n = print_vma (si, DEC_5); if (n < 5) fputs (&" "[n], stdout); - printf (" %3lu: ", hn); + fputs (": ", stdout); if (dynamic_symbols == NULL || si >= num_dynamic_syms) { @@ -11915,41 +11925,26 @@ process_symbol_table (Filedata * filedata) if (dynamic_info[DT_HASH]) { - bfd_vma si; - char *visited; - printf (_("\nSymbol table for image:\n")); if (is_32bit_elf) - printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); else - printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); - visited = xcmalloc (nchains, 1); - memset (visited, 0, nchains); - for (hn = 0; hn < nbuckets; hn++) - { - for (si = buckets[hn]; si > 0; si = chains[si]) - { - print_dynamic_symbol (filedata, si, hn); - if (si >= nchains || visited[si]) - { - error (_("histogram chain is corrupt\n")); - break; - } - visited[si] = 1; - } - } - free (visited); + for (hn = 0; hn < nchains; hn++) + print_dynamic_symbol (filedata, hn); } if (dynamic_info_DT_GNU_HASH) { + unsigned long num_of_syms = 0; + printf (_("\nSymbol table of `%s' for image:\n"), GNU_HASH_SECTION_NAME); if (is_32bit_elf) - printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); else - printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); for (hn = 0; hn < ngnubuckets; ++hn) if (gnubuckets[hn] != 0) @@ -11960,13 +11955,22 @@ process_symbol_table (Filedata * filedata) do { if (dynamic_info_DT_MIPS_XHASH) - print_dynamic_symbol (filedata, mipsxlat[off], hn); + { + if (mipsxlat[off] >= num_of_syms) + num_of_syms = mipsxlat[off] + 1; + } else - print_dynamic_symbol (filedata, si, hn); + { + if (si >= num_of_syms) + num_of_syms = si + 1; + } si++; } while (off < ngnuchains && (gnuchains[off++] & 1) == 0); } + + for (hn = 0; hn < num_of_syms; hn++) + print_dynamic_symbol (filedata, hn); } } else if ((do_dyn_syms || (do_syms && !do_using_dynamic)) diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d index efe675e0c7..a0bebb0b00 100644 --- a/ld/testsuite/ld-elf/hash.d +++ b/ld/testsuite/ld-elf/hash.d @@ -9,11 +9,11 @@ #... +0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+ #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main + +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start #... diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d index 8a0f9bd805..fb02e22afa 100644 --- a/ld/testsuite/ld-elf/pr13195.d +++ b/ld/testsuite/ld-elf/pr13195.d @@ -5,5 +5,5 @@ # generic linker targets don't support --gc-sections, nor do a bunch of others #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo #pass diff --git a/ld/testsuite/ld-elfvsb/hidden2.d b/ld/testsuite/ld-elfvsb/hidden2.d index 72a42d57bc..8fe2da65b9 100644 --- a/ld/testsuite/ld-elfvsb/hidden2.d +++ b/ld/testsuite/ld-elfvsb/hidden2.d @@ -5,5 +5,5 @@ Symbol table for image: #... -[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo +[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo #pass diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d index 122edb80e1..a0fe4266f2 100644 --- a/ld/testsuite/ld-mips-elf/hash2.d +++ b/ld/testsuite/ld-mips-elf/hash2.d @@ -6,11 +6,11 @@ #... +0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+ #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main #... - +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start #... -- 2.24.1