This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[GOLD][PATCH PROPOSAL] fix a symbol table output size miscalculation.
- From: Viktor Kutuzov <vkutuzov at accesssoftek dot com>
- To: Ian Lance Taylor <iant at google dot com>
- Cc: binutils <binutils at sourceware dot org>
- Date: Wed, 10 Feb 2010 15:32:02 -0800
- Subject: [GOLD][PATCH PROPOSAL] fix a symbol table output size miscalculation.
- Reply-to: vkutuzov at accesssoftek dot com
Hi Ian,
Following up the problems exposed by the glibc build.
There is another one in the Sized_relobj::write_local_symbols method
(object.cc). The symbol table output size gets miscalculated if any
symbol has discarded output section.
Both
object.cc, ln 1905: off_t output_size = this->output_local_symbol_count_
* sym_size;
and
object.cc, ln 1910: off_t dyn_output_size =
this->output_local_dynsym_count_ * sym_size;
contains an extra sym_size for each symbol with discarded output
section. Then asserts get triggered at the end:
object.cc, ln1987: gold_assert(ov - oview == output_size);
and
object.cc, ln1993: gold_assert(dyn_ov - dyn_oview ==
dyn_output_size);
Please find attached the patch that fixes this issue.
However, I don't like nested loops there, so if anyone will propose a
more elegant solution that will be great.
Thank you.
-Viktor.
Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.118
diff -u -p -r1.118 object.cc
--- object.cc 15 Jan 2010 01:44:22 -0000 1.118
+++ object.cc 10 Feb 2010 19:53:53 -0000
@@ -1900,21 +1904,44 @@ Sized_relobj<size, big_endian>::write_lo
false);
const char* pnames = reinterpret_cast<const char*>(pnamesu);
+ const Output_sections out_sections(this->output_sections());
+
// Get views into the output file for the portions of the symbol table
// and the dynamic symbol table that we will be writing.
- off_t output_size = this->output_local_symbol_count_ * sym_size;
+ off_t output_size = 0;
+ off_t dyn_output_size = 0;
+ // Skip first entry.
+ const unsigned char* _psyms = psyms + sym_size;
+ for (unsigned int i = 1; i < loccount; ++i, _psyms += sym_size)
+ {
+ elfcpp::Sym<size, big_endian> isym(_psyms);
+
+ Symbol_value<size>& lv(this->local_values_[i]);
+
+ bool is_ordinary;
+ unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
+ &is_ordinary);
+ if (is_ordinary)
+ {
+ gold_assert(st_shndx < out_sections.size());
+ if (out_sections[st_shndx] == NULL)
+ continue;
+ }
+ if (!strip_all && lv.needs_output_symtab_entry())
+ output_size += sym_size;
+ if (lv.needs_output_dynsym_entry())
+ dyn_output_size += sym_size;
+ }
+
unsigned char* oview = NULL;
if (output_size > 0)
oview = of->get_output_view(this->local_symbol_offset_, output_size);
- off_t dyn_output_size = this->output_local_dynsym_count_ * sym_size;
unsigned char* dyn_oview = NULL;
if (dyn_output_size > 0)
dyn_oview = of->get_output_view(this->local_dynsym_offset_,
dyn_output_size);
- const Output_sections out_sections(this->output_sections());
-
gold_assert(this->local_values_.size() == loccount);
unsigned char* ov = oview;