X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gold%2Fmerge.cc;h=6d444e6cb0a09314e95d55dcd45a27f52417a99c;hb=d0ae9fbda7513c1cab463bf1a9b21fdef40e7c56;hp=4fcbc1092a908e4cbfe72331d78e801cbbfe7bb4;hpb=ca09d69af126b596bf21c9d3f7639cae5cd32533;p=binutils-gdb.git diff --git a/gold/merge.cc b/gold/merge.cc index 4fcbc1092a9..6d444e6cb0a 100644 --- a/gold/merge.cc +++ b/gold/merge.cc @@ -1,6 +1,6 @@ // merge.cc -- handle section merging for gold -// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc. +// Copyright (C) 2006-2014 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -242,6 +242,7 @@ Merge_map::add_mapping(Relobj* object, unsigned int shndx, section_offset_type offset, section_size_type length, section_offset_type output_offset) { + gold_assert(object != NULL); Object_merge_map* object_merge_map = object->merge_map(); if (object_merge_map == NULL) { @@ -405,27 +406,16 @@ bool Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx) { section_size_type len; - section_size_type uncompressed_size = 0; - unsigned char* uncompressed_data = NULL; - const unsigned char* p = object->section_contents(shndx, &len, false); - - if (object->section_is_compressed(shndx, &uncompressed_size)) - { - uncompressed_data = new unsigned char[uncompressed_size]; - if (!decompress_input_section(p, len, uncompressed_data, - uncompressed_size)) - object->error(_("could not decompress section %s"), - object->section_name(shndx).c_str()); - p = uncompressed_data; - len = uncompressed_size; - } + bool is_new; + const unsigned char* p = object->decompressed_section_contents(shndx, &len, + &is_new); section_size_type entsize = convert_to_section_size_type(this->entsize()); if (len % entsize != 0) { - if (uncompressed_data != NULL) - delete[] uncompressed_data; + if (is_new) + delete[] p; return false; } @@ -456,8 +446,8 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx) if (this->keeps_input_sections()) record_input_section(object, shndx); - if (uncompressed_data != NULL) - delete[] uncompressed_data; + if (is_new) + delete[] p; return true; } @@ -515,32 +505,22 @@ bool Output_merge_string::do_add_input_section(Relobj* object, unsigned int shndx) { - section_size_type len; - section_size_type uncompressed_size = 0; - unsigned char* uncompressed_data = NULL; - const unsigned char* pdata = object->section_contents(shndx, &len, false); - - if (object->section_is_compressed(shndx, &uncompressed_size)) - { - uncompressed_data = new unsigned char[uncompressed_size]; - if (!decompress_input_section(pdata, len, uncompressed_data, - uncompressed_size)) - object->error(_("could not decompress section %s"), - object->section_name(shndx).c_str()); - pdata = uncompressed_data; - len = uncompressed_size; - } + section_size_type sec_len; + bool is_new; + const unsigned char* pdata = object->decompressed_section_contents(shndx, + &sec_len, + &is_new); const Char_type* p = reinterpret_cast(pdata); - const Char_type* pend = p + len / sizeof(Char_type); + const Char_type* pend = p + sec_len / sizeof(Char_type); const Char_type* pend0 = pend; - if (len % sizeof(Char_type) != 0) + if (sec_len % sizeof(Char_type) != 0) { object->error(_("mergeable string section length not multiple of " "character size")); - if (uncompressed_data != NULL) - delete[] uncompressed_data; + if (is_new) + delete[] pdata; return false; } @@ -560,25 +540,44 @@ Output_merge_string::do_add_input_section(Relobj* object, this->merged_strings_lists_.push_back(merged_strings_list); Merged_strings& merged_strings = merged_strings_list->merged_strings; - // Count the number of strings in the section and size the list. + // Count the number of non-null strings in the section and size the list. size_t count = 0; - for (const Char_type* pt = p; pt < pend0; pt += string_length(pt) + 1) - ++count; + const Char_type* pt = p; + while (pt < pend0) + { + size_t len = string_length(pt); + if (len != 0) + ++count; + pt += len + 1; + } if (pend0 < pend) ++count; merged_strings.reserve(count + 1); // The index I is in bytes, not characters. section_size_type i = 0; + + // We assume here that the beginning of the section is correctly + // aligned, so each string within the section must retain the same + // modulo. + uintptr_t init_align_modulo = (reinterpret_cast(pdata) + & (this->addralign() - 1)); + bool has_misaligned_strings = false; + while (p < pend0) { size_t len = string_length(p); + // Within merge input section each string must be aligned. + if (len != 0 + && ((reinterpret_cast(p) & (this->addralign() - 1)) + != init_align_modulo)) + has_misaligned_strings = true; + Stringpool::Key key; this->stringpool_.add_with_length(p, len, true, &key); merged_strings.push_back(Merged_string(i, key)); - p += len + 1; i += (len + 1) * sizeof(Char_type); } @@ -599,14 +598,20 @@ Output_merge_string::do_add_input_section(Relobj* object, merged_strings.push_back(Merged_string(i, 0)); this->input_count_ += count; - this->input_size_ += len; + this->input_size_ += i; + + if (has_misaligned_strings) + gold_warning(_("%s: section %s contains incorrectly aligned strings;" + " the alignment of those strings won't be preserved"), + object->name().c_str(), + object->section_name(shndx).c_str()); // For script processing, we keep the input sections. if (this->keeps_input_sections()) record_input_section(object, shndx); - if (uncompressed_data != NULL) - delete[] uncompressed_data; + if (is_new) + delete[] pdata; return true; }