This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[GOLD][PATCH PROPOSAL] fix a symbol table output size miscalculation.


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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]