Home | History | Annotate | Download | only in gold
      1 // merge.cc -- handle section merging for gold
      2 
      3 // Copyright (C) 2006-2016 Free Software Foundation, Inc.
      4 // Written by Ian Lance Taylor <iant (at) google.com>.
      5 
      6 // This file is part of gold.
      7 
      8 // This program is free software; you can redistribute it and/or modify
      9 // it under the terms of the GNU General Public License as published by
     10 // the Free Software Foundation; either version 3 of the License, or
     11 // (at your option) any later version.
     12 
     13 // This program is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // You should have received a copy of the GNU General Public License
     19 // along with this program; if not, write to the Free Software
     20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21 // MA 02110-1301, USA.
     22 
     23 #include "gold.h"
     24 
     25 #include <cstdlib>
     26 #include <algorithm>
     27 
     28 #include "merge.h"
     29 #include "compressed_output.h"
     30 
     31 namespace gold
     32 {
     33 
     34 // Class Object_merge_map.
     35 
     36 // Destructor.
     37 
     38 Object_merge_map::~Object_merge_map()
     39 {
     40   for (Section_merge_maps::iterator p = this->section_merge_maps_.begin();
     41        p != this->section_merge_maps_.end();
     42        ++p)
     43     delete p->second;
     44 }
     45 
     46 // Get the Input_merge_map to use for an input section, or NULL.
     47 
     48 const Object_merge_map::Input_merge_map*
     49 Object_merge_map::get_input_merge_map(unsigned int shndx) const
     50 {
     51   gold_assert(shndx != -1U);
     52   const Section_merge_maps &maps = this->section_merge_maps_;
     53   for (Section_merge_maps::const_iterator i = maps.begin(), e = maps.end();
     54        i != e; ++i)
     55     {
     56       if (i->first == shndx)
     57 	return i->second;
     58     }
     59   return NULL;
     60 }
     61 
     62 // Get or create the Input_merge_map to use for an input section.
     63 
     64 Object_merge_map::Input_merge_map*
     65 Object_merge_map::get_or_make_input_merge_map(
     66     const Output_section_data* output_data, unsigned int shndx) {
     67   Input_merge_map* map = this->get_input_merge_map(shndx);
     68   if (map != NULL)
     69     {
     70       // For a given input section in a given object, every mapping
     71       // must be done with the same Merge_map.
     72       gold_assert(map->output_data == output_data);
     73       return map;
     74     }
     75 
     76   Input_merge_map* new_map = new Input_merge_map;
     77   new_map->output_data = output_data;
     78   Section_merge_maps &maps = this->section_merge_maps_;
     79   maps.push_back(std::make_pair(shndx, new_map));
     80   return new_map;
     81 }
     82 
     83 // Add a mapping.
     84 
     85 void
     86 Object_merge_map::add_mapping(const Output_section_data* output_data,
     87 			      unsigned int shndx,
     88 			      section_offset_type input_offset,
     89 			      section_size_type length,
     90 			      section_offset_type output_offset)
     91 {
     92   Input_merge_map* map = this->get_or_make_input_merge_map(output_data, shndx);
     93   map->add_mapping(input_offset, length, output_offset);
     94 }
     95 
     96 void
     97 Object_merge_map::Input_merge_map::add_mapping(
     98     section_offset_type input_offset, section_size_type length,
     99     section_offset_type output_offset) {
    100   // Try to merge the new entry in the last one we saw.
    101   if (!this->entries.empty())
    102     {
    103       Input_merge_entry& entry(this->entries.back());
    104 
    105       // Use section_size_type to avoid signed/unsigned warnings.
    106       section_size_type input_offset_u = input_offset;
    107       section_size_type output_offset_u = output_offset;
    108 
    109       // If this entry is not in order, we need to sort the vector
    110       // before looking anything up.
    111       if (input_offset_u < entry.input_offset + entry.length)
    112 	{
    113 	  gold_assert(input_offset < entry.input_offset);
    114 	  gold_assert(input_offset_u + length
    115 		      <= static_cast<section_size_type>(entry.input_offset));
    116 	  this->sorted = false;
    117 	}
    118       else if (entry.input_offset + entry.length == input_offset_u
    119 	       && (output_offset == -1
    120 		   ? entry.output_offset == -1
    121 		   : entry.output_offset + entry.length == output_offset_u))
    122 	{
    123 	  entry.length += length;
    124 	  return;
    125 	}
    126     }
    127 
    128   Input_merge_entry entry;
    129   entry.input_offset = input_offset;
    130   entry.length = length;
    131   entry.output_offset = output_offset;
    132   this->entries.push_back(entry);
    133 }
    134 
    135 // Get the output offset for an input address.
    136 
    137 bool
    138 Object_merge_map::get_output_offset(unsigned int shndx,
    139 				    section_offset_type input_offset,
    140 				    section_offset_type* output_offset)
    141 {
    142   Input_merge_map* map = this->get_input_merge_map(shndx);
    143   if (map == NULL)
    144     return false;
    145 
    146   if (!map->sorted)
    147     {
    148       std::sort(map->entries.begin(), map->entries.end(),
    149 		Input_merge_compare());
    150       map->sorted = true;
    151     }
    152 
    153   Input_merge_entry entry;
    154   entry.input_offset = input_offset;
    155   std::vector<Input_merge_entry>::const_iterator p =
    156     std::upper_bound(map->entries.begin(), map->entries.end(),
    157 		     entry, Input_merge_compare());
    158   if (p == map->entries.begin())
    159     return false;
    160   --p;
    161   gold_assert(p->input_offset <= input_offset);
    162 
    163   if (input_offset - p->input_offset
    164       >= static_cast<section_offset_type>(p->length))
    165     return false;
    166 
    167   *output_offset = p->output_offset;
    168   if (*output_offset != -1)
    169     *output_offset += (input_offset - p->input_offset);
    170   return true;
    171 }
    172 
    173 // Return whether this is the merge map for section SHNDX.
    174 
    175 const Output_section_data*
    176 Object_merge_map::find_merge_section(unsigned int shndx) const {
    177   const Object_merge_map::Input_merge_map* map =
    178     this->get_input_merge_map(shndx);
    179   if (map == NULL)
    180     return NULL;
    181   return map->output_data;
    182 }
    183 
    184 // Initialize a mapping from input offsets to output addresses.
    185 
    186 template<int size>
    187 void
    188 Object_merge_map::initialize_input_to_output_map(
    189     unsigned int shndx,
    190     typename elfcpp::Elf_types<size>::Elf_Addr starting_address,
    191     Unordered_map<section_offset_type,
    192 		  typename elfcpp::Elf_types<size>::Elf_Addr>* initialize_map)
    193 {
    194   Input_merge_map* map = this->get_input_merge_map(shndx);
    195   gold_assert(map != NULL);
    196 
    197   gold_assert(initialize_map->empty());
    198   // We know how many entries we are going to add.
    199   // reserve_unordered_map takes an expected count of buckets, not a
    200   // count of elements, so double it to try to reduce collisions.
    201   reserve_unordered_map(initialize_map, map->entries.size() * 2);
    202 
    203   for (Input_merge_map::Entries::const_iterator p = map->entries.begin();
    204        p != map->entries.end();
    205        ++p)
    206     {
    207       section_offset_type output_offset = p->output_offset;
    208       if (output_offset != -1)
    209 	output_offset += starting_address;
    210       else
    211 	{
    212 	  // If we see a relocation against an address we have chosen
    213 	  // to discard, we relocate to zero.  FIXME: We could also
    214 	  // issue a warning in this case; that would require
    215 	  // reporting this somehow and checking it in the routines in
    216 	  // reloc.h.
    217 	  output_offset = 0;
    218 	}
    219       initialize_map->insert(std::make_pair(p->input_offset, output_offset));
    220     }
    221 }
    222 
    223 // Class Output_merge_base.
    224 
    225 // Return the output offset for an input offset.  The input address is
    226 // at offset OFFSET in section SHNDX in OBJECT.  If we know the
    227 // offset, set *POUTPUT and return true.  Otherwise return false.
    228 
    229 bool
    230 Output_merge_base::do_output_offset(const Relobj* object,
    231 				    unsigned int shndx,
    232 				    section_offset_type offset,
    233 				    section_offset_type* poutput) const
    234 {
    235   return object->merge_output_offset(shndx, offset, poutput);
    236 }
    237 
    238 // Record a merged input section for script processing.
    239 
    240 void
    241 Output_merge_base::record_input_section(Relobj* relobj, unsigned int shndx)
    242 {
    243   gold_assert(this->keeps_input_sections_ && relobj != NULL);
    244   // If this is the first input section, record it.  We need do this because
    245   // this->input_sections_ is unordered.
    246   if (this->first_relobj_ == NULL)
    247     {
    248       this->first_relobj_ = relobj;
    249       this->first_shndx_ = shndx;
    250     }
    251 
    252   std::pair<Input_sections::iterator, bool> result =
    253     this->input_sections_.insert(Section_id(relobj, shndx));
    254   // We should insert a merge section once only.
    255   gold_assert(result.second);
    256 }
    257 
    258 // Class Output_merge_data.
    259 
    260 // Compute the hash code for a fixed-size constant.
    261 
    262 size_t
    263 Output_merge_data::Merge_data_hash::operator()(Merge_data_key k) const
    264 {
    265   const unsigned char* p = this->pomd_->constant(k);
    266   section_size_type entsize =
    267     convert_to_section_size_type(this->pomd_->entsize());
    268 
    269   // Fowler/Noll/Vo (FNV) hash (type FNV-1a).
    270   if (sizeof(size_t) == 8)
    271     {
    272       size_t result = static_cast<size_t>(14695981039346656037ULL);
    273       for (section_size_type i = 0; i < entsize; ++i)
    274 	{
    275 	  result &= (size_t) *p++;
    276 	  result *= 1099511628211ULL;
    277 	}
    278       return result;
    279     }
    280   else
    281     {
    282       size_t result = 2166136261UL;
    283       for (section_size_type i = 0; i < entsize; ++i)
    284 	{
    285 	  result ^= (size_t) *p++;
    286 	  result *= 16777619UL;
    287 	}
    288       return result;
    289     }
    290 }
    291 
    292 // Return whether one hash table key equals another.
    293 
    294 bool
    295 Output_merge_data::Merge_data_eq::operator()(Merge_data_key k1,
    296 					     Merge_data_key k2) const
    297 {
    298   const unsigned char* p1 = this->pomd_->constant(k1);
    299   const unsigned char* p2 = this->pomd_->constant(k2);
    300   return memcmp(p1, p2, this->pomd_->entsize()) == 0;
    301 }
    302 
    303 // Add a constant to the end of the section contents.
    304 
    305 void
    306 Output_merge_data::add_constant(const unsigned char* p)
    307 {
    308   section_size_type entsize = convert_to_section_size_type(this->entsize());
    309   section_size_type addralign =
    310     convert_to_section_size_type(this->addralign());
    311   section_size_type addsize = std::max(entsize, addralign);
    312   if (this->len_ + addsize > this->alc_)
    313     {
    314       if (this->alc_ == 0)
    315 	this->alc_ = 128 * addsize;
    316       else
    317 	this->alc_ *= 2;
    318       this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->alc_));
    319       if (this->p_ == NULL)
    320 	gold_nomem();
    321     }
    322 
    323   memcpy(this->p_ + this->len_, p, entsize);
    324   if (addsize > entsize)
    325     memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
    326   this->len_ += addsize;
    327 }
    328 
    329 // Add the input section SHNDX in OBJECT to a merged output section
    330 // which holds fixed length constants.  Return whether we were able to
    331 // handle the section; if not, it will be linked as usual without
    332 // constant merging.
    333 
    334 bool
    335 Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
    336 {
    337   section_size_type len;
    338   bool is_new;
    339   const unsigned char* p = object->decompressed_section_contents(shndx, &len,
    340 								 &is_new);
    341 
    342   section_size_type entsize = convert_to_section_size_type(this->entsize());
    343 
    344   if (len % entsize != 0)
    345     {
    346       if (is_new)
    347 	delete[] p;
    348       return false;
    349     }
    350 
    351   this->input_count_ += len / entsize;
    352 
    353   Object_merge_map* merge_map = object->get_or_create_merge_map();
    354   Object_merge_map::Input_merge_map* input_merge_map =
    355     merge_map->get_or_make_input_merge_map(this, shndx);
    356 
    357   for (section_size_type i = 0; i < len; i += entsize, p += entsize)
    358     {
    359       // Add the constant to the section contents.  If we find that it
    360       // is already in the hash table, we will remove it again.
    361       Merge_data_key k = this->len_;
    362       this->add_constant(p);
    363 
    364       std::pair<Merge_data_hashtable::iterator, bool> ins =
    365 	this->hashtable_.insert(k);
    366 
    367       if (!ins.second)
    368 	{
    369 	  // Key was already present.  Remove the copy we just added.
    370 	  this->len_ -= entsize;
    371 	  k = *ins.first;
    372 	}
    373 
    374       // Record the offset of this constant in the output section.
    375       input_merge_map->add_mapping(i, entsize, k);
    376     }
    377 
    378   // For script processing, we keep the input sections.
    379   if (this->keeps_input_sections())
    380     record_input_section(object, shndx);
    381 
    382   if (is_new)
    383     delete[] p;
    384 
    385   return true;
    386 }
    387 
    388 // Set the final data size in a merged output section with fixed size
    389 // constants.
    390 
    391 void
    392 Output_merge_data::set_final_data_size()
    393 {
    394   // Release the memory we don't need.
    395   this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->len_));
    396   // An Output_merge_data object may be empty and realloc is allowed
    397   // to return a NULL pointer in this case.  An Output_merge_data is empty
    398   // if all its input sections have sizes that are not multiples of entsize.
    399   gold_assert(this->p_ != NULL || this->len_ == 0);
    400   this->set_data_size(this->len_);
    401 }
    402 
    403 // Write the data of a merged output section with fixed size constants
    404 // to the file.
    405 
    406 void
    407 Output_merge_data::do_write(Output_file* of)
    408 {
    409   of->write(this->offset(), this->p_, this->len_);
    410 }
    411 
    412 // Write the data to a buffer.
    413 
    414 void
    415 Output_merge_data::do_write_to_buffer(unsigned char* buffer)
    416 {
    417   memcpy(buffer, this->p_, this->len_);
    418 }
    419 
    420 // Print merge stats to stderr.
    421 
    422 void
    423 Output_merge_data::do_print_merge_stats(const char* section_name)
    424 {
    425   fprintf(stderr,
    426 	  _("%s: %s merged constants size: %lu; input: %zu; output: %zu\n"),
    427 	  program_name, section_name,
    428 	  static_cast<unsigned long>(this->entsize()),
    429 	  this->input_count_, this->hashtable_.size());
    430 }
    431 
    432 // Class Output_merge_string.
    433 
    434 // Add an input section to a merged string section.
    435 
    436 template<typename Char_type>
    437 bool
    438 Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
    439 						     unsigned int shndx)
    440 {
    441   section_size_type sec_len;
    442   bool is_new;
    443   const unsigned char* pdata = object->decompressed_section_contents(shndx,
    444 								     &sec_len,
    445 								     &is_new);
    446 
    447   const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
    448   const Char_type* pend = p + sec_len / sizeof(Char_type);
    449   const Char_type* pend0 = pend;
    450 
    451   if (sec_len % sizeof(Char_type) != 0)
    452     {
    453       object->error(_("mergeable string section length not multiple of "
    454 		      "character size"));
    455       if (is_new)
    456 	delete[] pdata;
    457       return false;
    458     }
    459 
    460   if (pend[-1] != 0)
    461     {
    462       gold_warning(_("%s: last entry in mergeable string section '%s' "
    463 		     "not null terminated"),
    464 		   object->name().c_str(),
    465 		   object->section_name(shndx).c_str());
    466       // Find the end of the last NULL-terminated string in the buffer.
    467       while (pend0 > p && pend0[-1] != 0)
    468 	--pend0;
    469     }
    470 
    471   Merged_strings_list* merged_strings_list =
    472       new Merged_strings_list(object, shndx);
    473   this->merged_strings_lists_.push_back(merged_strings_list);
    474   Merged_strings& merged_strings = merged_strings_list->merged_strings;
    475 
    476   // Count the number of non-null strings in the section and size the list.
    477   size_t count = 0;
    478   const Char_type* pt = p;
    479   while (pt < pend0)
    480     {
    481       size_t len = string_length(pt);
    482       if (len != 0)
    483 	++count;
    484       pt += len + 1;
    485     }
    486   if (pend0 < pend)
    487     ++count;
    488   merged_strings.reserve(count + 1);
    489 
    490   // The index I is in bytes, not characters.
    491   section_size_type i = 0;
    492 
    493   // We assume here that the beginning of the section is correctly
    494   // aligned, so each string within the section must retain the same
    495   // modulo.
    496   uintptr_t init_align_modulo = (reinterpret_cast<uintptr_t>(pdata)
    497 				 & (this->addralign() - 1));
    498   bool has_misaligned_strings = false;
    499 
    500   while (p < pend)
    501     {
    502       size_t len = p < pend0 ? string_length(p) : pend - p;
    503 
    504       // Within merge input section each string must be aligned.
    505       if (len != 0
    506 	  && ((reinterpret_cast<uintptr_t>(p) & (this->addralign() - 1))
    507 	      != init_align_modulo))
    508 	  has_misaligned_strings = true;
    509 
    510       Stringpool::Key key;
    511       this->stringpool_.add_with_length(p, len, true, &key);
    512 
    513       merged_strings.push_back(Merged_string(i, key));
    514       p += len + 1;
    515       i += (len + 1) * sizeof(Char_type);
    516     }
    517 
    518   // Record the last offset in the input section so that we can
    519   // compute the length of the last string.
    520   merged_strings.push_back(Merged_string(i, 0));
    521 
    522   this->input_count_ += count;
    523   this->input_size_ += i;
    524 
    525   if (has_misaligned_strings)
    526     gold_warning(_("%s: section %s contains incorrectly aligned strings;"
    527 		   " the alignment of those strings won't be preserved"),
    528 		 object->name().c_str(),
    529 		 object->section_name(shndx).c_str());
    530 
    531   // For script processing, we keep the input sections.
    532   if (this->keeps_input_sections())
    533     record_input_section(object, shndx);
    534 
    535   if (is_new)
    536     delete[] pdata;
    537 
    538   return true;
    539 }
    540 
    541 // Finalize the mappings from the input sections to the output
    542 // section, and return the final data size.
    543 
    544 template<typename Char_type>
    545 section_size_type
    546 Output_merge_string<Char_type>::finalize_merged_data()
    547 {
    548   this->stringpool_.set_string_offsets();
    549 
    550   for (typename Merged_strings_lists::const_iterator l =
    551 	 this->merged_strings_lists_.begin();
    552        l != this->merged_strings_lists_.end();
    553        ++l)
    554     {
    555       section_offset_type last_input_offset = 0;
    556       section_offset_type last_output_offset = 0;
    557       Relobj *object = (*l)->object;
    558       Object_merge_map* merge_map = object->get_or_create_merge_map();
    559       Object_merge_map::Input_merge_map* input_merge_map =
    560         merge_map->get_or_make_input_merge_map(this, (*l)->shndx);
    561 
    562       for (typename Merged_strings::const_iterator p =
    563 	     (*l)->merged_strings.begin();
    564 	   p != (*l)->merged_strings.end();
    565 	   ++p)
    566 	{
    567 	  section_size_type length = p->offset - last_input_offset;
    568 	  if (length > 0)
    569 	    input_merge_map->add_mapping(last_input_offset, length,
    570                                          last_output_offset);
    571 	  last_input_offset = p->offset;
    572 	  if (p->stringpool_key != 0)
    573 	    last_output_offset =
    574 	        this->stringpool_.get_offset_from_key(p->stringpool_key);
    575 	}
    576       delete *l;
    577     }
    578 
    579   // Save some memory.  This also ensures that this function will work
    580   // if called twice, as may happen if Layout::set_segment_offsets
    581   // finds a better alignment.
    582   this->merged_strings_lists_.clear();
    583 
    584   return this->stringpool_.get_strtab_size();
    585 }
    586 
    587 template<typename Char_type>
    588 void
    589 Output_merge_string<Char_type>::set_final_data_size()
    590 {
    591   const off_t final_data_size = this->finalize_merged_data();
    592   this->set_data_size(final_data_size);
    593 }
    594 
    595 // Write out a merged string section.
    596 
    597 template<typename Char_type>
    598 void
    599 Output_merge_string<Char_type>::do_write(Output_file* of)
    600 {
    601   this->stringpool_.write(of, this->offset());
    602 }
    603 
    604 // Write a merged string section to a buffer.
    605 
    606 template<typename Char_type>
    607 void
    608 Output_merge_string<Char_type>::do_write_to_buffer(unsigned char* buffer)
    609 {
    610   this->stringpool_.write_to_buffer(buffer, this->data_size());
    611 }
    612 
    613 // Return the name of the types of string to use with
    614 // do_print_merge_stats.
    615 
    616 template<typename Char_type>
    617 const char*
    618 Output_merge_string<Char_type>::string_name()
    619 {
    620   gold_unreachable();
    621   return NULL;
    622 }
    623 
    624 template<>
    625 const char*
    626 Output_merge_string<char>::string_name()
    627 {
    628   return "strings";
    629 }
    630 
    631 template<>
    632 const char*
    633 Output_merge_string<uint16_t>::string_name()
    634 {
    635   return "16-bit strings";
    636 }
    637 
    638 template<>
    639 const char*
    640 Output_merge_string<uint32_t>::string_name()
    641 {
    642   return "32-bit strings";
    643 }
    644 
    645 // Print merge stats to stderr.
    646 
    647 template<typename Char_type>
    648 void
    649 Output_merge_string<Char_type>::do_print_merge_stats(const char* section_name)
    650 {
    651   char buf[200];
    652   snprintf(buf, sizeof buf, "%s merged %s", section_name, this->string_name());
    653   fprintf(stderr, _("%s: %s input bytes: %zu\n"),
    654 	  program_name, buf, this->input_size_);
    655   fprintf(stderr, _("%s: %s input strings: %zu\n"),
    656 	  program_name, buf, this->input_count_);
    657   this->stringpool_.print_stats(buf);
    658 }
    659 
    660 // Instantiate the templates we need.
    661 
    662 template
    663 class Output_merge_string<char>;
    664 
    665 template
    666 class Output_merge_string<uint16_t>;
    667 
    668 template
    669 class Output_merge_string<uint32_t>;
    670 
    671 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
    672 template
    673 void
    674 Object_merge_map::initialize_input_to_output_map<32>(
    675     unsigned int shndx,
    676     elfcpp::Elf_types<32>::Elf_Addr starting_address,
    677     Unordered_map<section_offset_type, elfcpp::Elf_types<32>::Elf_Addr>*);
    678 #endif
    679 
    680 #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
    681 template
    682 void
    683 Object_merge_map::initialize_input_to_output_map<64>(
    684     unsigned int shndx,
    685     elfcpp::Elf_types<64>::Elf_Addr starting_address,
    686     Unordered_map<section_offset_type, elfcpp::Elf_types<64>::Elf_Addr>*);
    687 #endif
    688 
    689 } // End namespace gold.
    690