X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gold%2Flayout.cc;h=7cbbe39b87d590927038190aa94045fc218a0507;hb=2fb062bac3e5f102f8608df5548bebf2682b0fec;hp=250782a92bead199a193ca48ed9c6d4b7e41c70c;hpb=b1b00fcc619cfa409c4e244f609ab82f3a3c37d2;p=platform%2Fupstream%2Fbinutils.git diff --git a/gold/layout.cc b/gold/layout.cc index 250782a..7cbbe39 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1,7 +1,6 @@ // layout.cc -- lay out output file sections for gold -// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 -// Free Software Foundation, Inc. +// Copyright (C) 2006-2014 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -236,6 +235,54 @@ Free_list::print_stats() program_name, Free_list::num_allocate_visits); } +// A Hash_task computes the MD5 checksum of an array of char. +// It has a blocker on either side (i.e., the task cannot run until +// the first is unblocked, and it unblocks the second after running). + +class Hash_task : public Task +{ + public: + Hash_task(const unsigned char* src, + size_t size, + unsigned char* dst, + Task_token* build_id_blocker, + Task_token* final_blocker) + : src_(src), size_(size), dst_(dst), build_id_blocker_(build_id_blocker), + final_blocker_(final_blocker) + { } + + void + run(Workqueue*) + { md5_buffer(reinterpret_cast(src_), size_, dst_); } + + Task_token* + is_runnable(); + + // Unblock FINAL_BLOCKER_ when done. + void + locks(Task_locker* tl) + { tl->add(this, this->final_blocker_); } + + std::string + get_name() const + { return "Hash_task"; } + + private: + const unsigned char* const src_; + const size_t size_; + unsigned char* const dst_; + Task_token* const build_id_blocker_; + Task_token* const final_blocker_; +}; + +Task_token* +Hash_task::is_runnable() +{ + if (this->build_id_blocker_->is_blocked()) + return this->build_id_blocker_; + return NULL; +} + // Layout::Relaxation_debug_check methods. // Check that sections and special data are in reset states. @@ -245,7 +292,8 @@ Free_list::print_stats() void Layout::Relaxation_debug_check::check_output_data_for_reset_values( const Layout::Section_list& sections, - const Layout::Data_list& special_outputs) + const Layout::Data_list& special_outputs, + const Layout::Data_list& relax_outputs) { for(Layout::Section_list::const_iterator p = sections.begin(); p != sections.end(); @@ -256,6 +304,8 @@ Layout::Relaxation_debug_check::check_output_data_for_reset_values( p != special_outputs.end(); ++p) gold_assert((*p)->address_and_file_offset_have_reset_values()); + + gold_assert(relax_outputs.empty()); } // Save information of SECTIONS for checking later. @@ -317,6 +367,10 @@ Layout::Relaxation_debug_check::verify_sections( void Layout_task_runner::run(Workqueue* workqueue, const Task* task) { + // See if any of the input definitions violate the One Definition Rule. + // TODO: if this is too slow, do this as a task, rather than inline. + this->symtab_->detect_odr_violations(task, this->options_.output_file_name()); + Layout* layout = this->layout_; off_t file_size = layout->finalize(this->input_objects_, this->symtab_, @@ -376,6 +430,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) section_list_(), unattached_section_list_(), special_output_list_(), + relax_output_list_(), section_headers_(NULL), tls_segment_(NULL), relro_segment_(NULL), @@ -394,6 +449,9 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) eh_frame_hdr_section_(NULL), gdb_index_data_(NULL), build_id_note_(NULL), + array_of_hashes_(NULL), + size_of_array_of_hashes_(0), + input_view_(NULL), debug_abbrev_(NULL), debug_info_(NULL), group_signatures_(), @@ -505,7 +563,9 @@ static const char* gdb_fast_lookup_sections[] = { "aranges", "pubnames", + "gnu_pubnames", "pubtypes", + "gnu_pubtypes", }; // Returns whether the given debug section is in the list of @@ -586,7 +646,13 @@ Layout::include_section(Sized_relobj_file*, const char* name, && (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE)) return false; - switch (shdr.get_sh_type()) + elfcpp::Elf_Word sh_type = shdr.get_sh_type(); + + if ((sh_type >= elfcpp::SHT_LOOS && sh_type <= elfcpp::SHT_HIOS) + || (sh_type >= elfcpp::SHT_LOPROC && sh_type <= elfcpp::SHT_HIPROC)) + return parameters->target().should_include_section(sh_type); + + switch (sh_type) { case elfcpp::SHT_NULL: case elfcpp::SHT_SYMTAB: @@ -1043,7 +1109,7 @@ Layout::special_ordering_of_input_section(const char* name) // wind up in the .text section. Sections that start with these // prefixes must appear first, and must appear in the order listed // here. - static const char* const text_section_sort[] = + static const char* const text_section_sort[] = { ".text.unlikely", ".text.exit", @@ -1103,7 +1169,7 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, = this->section_segment_map_.find(Const_section_id(object, shndx)); if (it == this->section_segment_map_.end()) { - os = this->choose_output_section(object, name, sh_type, + os = this->choose_output_section(object, name, sh_type, shdr.get_sh_flags(), true, ORDER_INVALID, false); } @@ -1149,7 +1215,8 @@ Layout::layout(Sized_relobj_file* object, unsigned int shndx, // By default the GNU linker sorts some special text sections ahead // of others. We are compatible. - if (!this->script_options_->saw_sections_clause() + if (parameters->options().text_reorder() + && !this->script_options_->saw_sections_clause() && !this->is_section_ordering_specified() && !parameters->options().relocatable() && Layout::special_ordering_of_input_section(name) >= 0) @@ -1198,7 +1265,7 @@ void Layout::insert_section_segment_map(Const_section_id secn, Unique_segment_info *s) { - gold_assert(this->unique_segment_for_sections_specified_); + gold_assert(this->unique_segment_for_sections_specified_); this->section_segment_map_[secn] = s; } @@ -1646,12 +1713,17 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, // sections before other .text sections. We are compatible. We // need to know that this might happen before we attach any input // sections. - if (!this->script_options_->saw_sections_clause() + if (parameters->options().text_reorder() + && !this->script_options_->saw_sections_clause() && !this->is_section_ordering_specified() && !parameters->options().relocatable() && strcmp(name, ".text") == 0) os->set_may_sort_attached_input_sections(); + // GNU linker sorts section by name with --sort-section=name. + if (strcmp(parameters->options().sort_section(), "name") == 0) + os->set_must_sort_attached_input_sections(); + // Check for .stab*str sections, as .stab* sections need to link to // them. if (type == elfcpp::SHT_STRTAB @@ -1833,44 +1905,44 @@ Layout::attach_allocated_section_to_segment(const Target* target, if (!os->is_unique_segment()) { for (p = this->segment_list_.begin(); - p != this->segment_list_.end(); + p != this->segment_list_.end(); ++p) { - if ((*p)->type() != elfcpp::PT_LOAD) - continue; - if ((*p)->is_unique_segment()) - continue; - if (!parameters->options().omagic() - && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W)) - continue; - if ((target->isolate_execinstr() || parameters->options().rosegment()) - && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X)) - continue; - // If -Tbss was specified, we need to separate the data and BSS - // segments. - if (parameters->options().user_set_Tbss()) - { - if ((os->type() == elfcpp::SHT_NOBITS) - == (*p)->has_any_data_sections()) - continue; - } - if (os->is_large_data_section() && !(*p)->is_large_data_segment()) - continue; - - if (is_address_set) - { - if ((*p)->are_addresses_set()) - continue; - - (*p)->add_initial_output_data(os); - (*p)->update_flags_for_output_section(seg_flags); - (*p)->set_addresses(addr, addr); - break; - } - - (*p)->add_output_section_to_load(this, os, seg_flags); - break; - } + if ((*p)->type() != elfcpp::PT_LOAD) + continue; + if ((*p)->is_unique_segment()) + continue; + if (!parameters->options().omagic() + && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W)) + continue; + if ((target->isolate_execinstr() || parameters->options().rosegment()) + && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X)) + continue; + // If -Tbss was specified, we need to separate the data and BSS + // segments. + if (parameters->options().user_set_Tbss()) + { + if ((os->type() == elfcpp::SHT_NOBITS) + == (*p)->has_any_data_sections()) + continue; + } + if (os->is_large_data_section() && !(*p)->is_large_data_segment()) + continue; + + if (is_address_set) + { + if ((*p)->are_addresses_set()) + continue; + + (*p)->add_initial_output_data(os); + (*p)->update_flags_for_output_section(seg_flags); + (*p)->set_addresses(addr, addr); + break; + } + + (*p)->add_output_section_to_load(this, os, seg_flags); + break; + } } if (p == this->segment_list_.end() @@ -2280,6 +2352,20 @@ Layout::clean_up_after_relaxation() ++p) delete *p; this->script_output_section_data_list_.clear(); + + // Special-case fill output objects are recreated each time through + // the relaxation loop. + this->reset_relax_output(); +} + +void +Layout::reset_relax_output() +{ + for (Data_list::const_iterator p = this->relax_output_list_.begin(); + p != this->relax_output_list_.end(); + ++p) + delete *p; + this->relax_output_list_.clear(); } // Prepare for relaxation. @@ -2302,12 +2388,29 @@ Layout::prepare_for_relaxation() if (is_debugging_enabled(DEBUG_RELAXATION)) this->relaxation_debug_check_->check_output_data_for_reset_values( - this->section_list_, this->special_output_list_); + this->section_list_, this->special_output_list_, + this->relax_output_list_); // Also enable recording of output section data from scripts. this->record_output_section_data_from_script_ = true; } +// If the user set the address of the text segment, that may not be +// compatible with putting the segment headers and file headers into +// that segment. For isolate_execinstr() targets, it's the rodata +// segment rather than text where we might put the headers. +static inline bool +load_seg_unusable_for_headers(const Target* target) +{ + const General_options& options = parameters->options(); + if (target->isolate_execinstr()) + return (options.user_set_Trodata_segment() + && options.Trodata_segment() % target->abi_pagesize() != 0); + else + return (options.user_set_Ttext() + && options.Ttext() % target->abi_pagesize() != 0); +} + // Relaxation loop body: If target has no relaxation, this runs only once // Otherwise, the target relaxation hook is called at the end of // each iteration. If the hook returns true, it means re-layout of @@ -2360,11 +2463,7 @@ Layout::relaxation_loop_body( != General_options::OBJECT_FORMAT_ELF) load_seg = NULL; - // If the user set the address of the text segment, that may not be - // compatible with putting the segment headers and file headers into - // that segment. - if (parameters->options().user_set_Ttext() - && parameters->options().Ttext() % target->abi_pagesize() != 0) + if (load_seg_unusable_for_headers(target)) { load_seg = NULL; phdr_seg = NULL; @@ -2652,12 +2751,14 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // If there is a load segment that contains the file and program headers, // provide a symbol __ehdr_start pointing there. // A program can use this to examine itself robustly. - if (load_seg != NULL) - symtab->define_in_output_segment("__ehdr_start", NULL, - Symbol_table::PREDEFINED, load_seg, 0, 0, - elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL, - elfcpp::STV_DEFAULT, 0, - Symbol::SEGMENT_START, true); + Symbol *ehdr_start = symtab->lookup("__ehdr_start"); + if (ehdr_start != NULL && ehdr_start->is_predefined()) + { + if (load_seg != NULL) + ehdr_start->set_output_segment(load_seg, Symbol::SEGMENT_START); + else + ehdr_start->set_undefined(); + } // Set the file offsets of all the non-data sections we've seen so // far which don't have to wait for the input sections. We need @@ -2918,7 +3019,7 @@ Layout::create_build_id() std::string desc; if (strcmp(style, "md5") == 0) descsz = 128 / 8; - else if (strcmp(style, "sha1") == 0) + else if ((strcmp(style, "sha1") == 0) || (strcmp(style, "tree") == 0)) descsz = 160 / 8; else if (strcmp(style, "uuid") == 0) { @@ -3169,12 +3270,14 @@ Layout::segment_precedes(const Output_segment* seg1, // The order of non-PT_LOAD segments is unimportant. We simply sort // by the numeric segment type and flags values. There should not - // be more than one segment with the same type and flags. + // be more than one segment with the same type and flags, except + // when a linker script specifies such. if (type1 != elfcpp::PT_LOAD) { if (type1 != type2) return type1 < type2; - gold_assert(flags1 != flags2); + gold_assert(flags1 != flags2 + || this->script_options_->saw_phdrs_clause()); return flags1 < flags2; } @@ -3256,6 +3359,20 @@ align_file_offset(off_t off, uint64_t addr, uint64_t abi_pagesize) return aligned_off; } +// On targets where the text segment contains only executable code, +// a non-executable segment is never the text segment. + +static inline bool +is_text_segment(const Target* target, const Output_segment* seg) +{ + elfcpp::Elf_Xword flags = seg->flags(); + if ((flags & elfcpp::PF_W) != 0) + return false; + if ((flags & elfcpp::PF_X) == 0) + return !target->isolate_execinstr(); + return true; +} + // Set the file offsets of all the segments, and all the sections they // contain. They have all been created. LOAD_SEG must be be laid out // first. Return the offset of the data to follow. @@ -3347,10 +3464,17 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, addr = (*p)->paddr(); } else if (parameters->options().user_set_Ttext() - && ((*p)->flags() & elfcpp::PF_W) == 0) + && (parameters->options().omagic() + || is_text_segment(target, *p))) { are_addresses_set = true; } + else if (parameters->options().user_set_Trodata_segment() + && ((*p)->flags() & (elfcpp::PF_W | elfcpp::PF_X)) == 0) + { + addr = parameters->options().Trodata_segment(); + are_addresses_set = true; + } else if (parameters->options().user_set_Tdata() && ((*p)->flags() & elfcpp::PF_W) != 0 && (!parameters->options().user_set_Tbss() @@ -3397,7 +3521,10 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // If the target wants a fixed minimum distance from the // text segment to the read-only segment, move up now. - uint64_t min_addr = start_addr + target->rosegment_gap(); + uint64_t min_addr = + start_addr + (parameters->options().user_set_rosegment_gap() + ? parameters->options().rosegment_gap() + : target->rosegment_gap()); if (addr < min_addr) addr = min_addr; @@ -3418,7 +3545,13 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, if (!parameters->options().nmagic() && !parameters->options().omagic()) - off = align_file_offset(off, addr, abi_pagesize); + { + // Here we are also taking care of the case when + // the maximum segment alignment is larger than the page size. + off = align_file_offset(off, addr, + std::max(abi_pagesize, + (*p)->maximum_alignment())); + } else { // This is -N or -n with a section script which prevents @@ -3435,7 +3568,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, unsigned int shndx_hold = *pshndx; bool has_relro = false; - uint64_t new_addr = (*p)->set_section_addresses(this, false, addr, + uint64_t new_addr = (*p)->set_section_addresses(target, this, + false, addr, &increase_relro, &has_relro, &off, pshndx); @@ -3476,7 +3610,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, increase_relro = 0; has_relro = false; - new_addr = (*p)->set_section_addresses(this, true, addr, + new_addr = (*p)->set_section_addresses(target, this, + true, addr, &increase_relro, &has_relro, &off, pshndx); @@ -3512,6 +3647,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // so they land after the segments starting at LOAD_SEG. off = align_file_offset(off, 0, target->abi_pagesize()); + this->reset_relax_output(); + for (Segment_list::iterator p = this->segment_list_.begin(); *p != load_seg; ++p) @@ -3525,8 +3662,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, bool has_relro = false; const uint64_t old_addr = (*p)->vaddr(); const uint64_t old_end = old_addr + (*p)->memsz(); - uint64_t new_addr = (*p)->set_section_addresses(this, true, - old_addr, + uint64_t new_addr = (*p)->set_section_addresses(target, this, + true, old_addr, &increase_relro, &has_relro, &off, @@ -3587,7 +3724,8 @@ Layout::set_relocatable_section_offsets(Output_data* file_header, (*p)->set_address(0); (*p)->set_file_offset(off); (*p)->finalize_data_size(); - off += (*p)->data_size(); + if ((*p)->type() != elfcpp::SHT_NOBITS) + off += (*p)->data_size(); (*p)->set_out_shndx(*pshndx); ++*pshndx; @@ -4152,7 +4290,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, false, ORDER_DYNAMIC_LINKER, false); - + *pdynstr = dynstr; if (dynstr != NULL) { Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); @@ -4168,22 +4306,22 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, odyn->add_section_address(elfcpp::DT_STRTAB, dynstr); odyn->add_section_size(elfcpp::DT_STRSZ, dynstr); } - - *pdynstr = dynstr; } - // Create the hash tables. + // Create the hash tables. The Gnu-style hash table must be + // built first, because it changes the order of the symbols + // in the dynamic symbol table. - if (strcmp(parameters->options().hash_style(), "sysv") == 0 + if (strcmp(parameters->options().hash_style(), "gnu") == 0 || strcmp(parameters->options().hash_style(), "both") == 0) { unsigned char* phash; unsigned int hashlen; - Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount, + Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); Output_section* hashsec = - this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, + this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); @@ -4198,23 +4336,28 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, { if (dynsym != NULL) hashsec->set_link_section(dynsym); - hashsec->set_entsize(4); - } - if (odyn != NULL) - odyn->add_section_address(elfcpp::DT_HASH, hashsec); + // For a 64-bit target, the entries in .gnu.hash do not have + // a uniform size, so we only set the entry size for a + // 32-bit target. + if (parameters->target().get_size() == 32) + hashsec->set_entsize(4); + + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + } } - if (strcmp(parameters->options().hash_style(), "gnu") == 0 + if (strcmp(parameters->options().hash_style(), "sysv") == 0 || strcmp(parameters->options().hash_style(), "both") == 0) { unsigned char* phash; unsigned int hashlen; - Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount, + Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); Output_section* hashsec = - this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, + this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); @@ -4229,16 +4372,11 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, { if (dynsym != NULL) hashsec->set_link_section(dynsym); - - // For a 64-bit target, the entries in .gnu.hash do not have - // a uniform size, so we only set the entry size for a - // 32-bit target. - if (parameters->target().get_size() == 32) - hashsec->set_entsize(4); - - if (odyn != NULL) - odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + hashsec->set_entsize(4); } + + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_HASH, hashsec); } } @@ -5164,6 +5302,13 @@ Layout::write_data(const Symbol_table* symtab, Output_file* of) const p != this->special_output_list_.end(); ++p) (*p)->write(of); + + // Write out the Output_data which are not in an Output_section + // and are regenerated in each iteration of relaxation. + for (Data_list::const_iterator p = this->relax_output_list_.begin(); + p != this->relax_output_list_.end(); + ++p) + (*p)->write(of); } // Write out the Output_sections which can only be written after the @@ -5204,9 +5349,53 @@ Layout::write_sections_after_input_sections(Output_file* of) this->section_headers_->write(of); } -// If the build ID requires computing a checksum, do so here, and -// write it out. We compute a checksum over the entire file because -// that is simplest. +// Build IDs can be computed as a "flat" sha1 or md5 of a string of bytes, +// or as a "tree" where each chunk of the string is hashed and then those +// hashes are put into a (much smaller) string which is hashed with sha1. +// We compute a checksum over the entire file because that is simplest. + +Task_token* +Layout::queue_build_id_tasks(Workqueue* workqueue, Task_token* build_id_blocker, + Output_file* of) +{ + const size_t filesize = (this->output_file_size() <= 0 ? 0 + : static_cast(this->output_file_size())); + if (this->build_id_note_ != NULL + && strcmp(parameters->options().build_id(), "tree") == 0 + && parameters->options().build_id_chunk_size_for_treehash() > 0 + && filesize > 0 + && (filesize >= + parameters->options().build_id_min_file_size_for_treehash())) + { + static const size_t MD5_OUTPUT_SIZE_IN_BYTES = 16; + const size_t chunk_size = + parameters->options().build_id_chunk_size_for_treehash(); + const size_t num_hashes = ((filesize - 1) / chunk_size) + 1; + Task_token* post_hash_tasks_blocker = new Task_token(true); + post_hash_tasks_blocker->add_blockers(num_hashes); + this->size_of_array_of_hashes_ = num_hashes * MD5_OUTPUT_SIZE_IN_BYTES; + const unsigned char* src = of->get_input_view(0, filesize); + this->input_view_ = src; + unsigned char *dst = new unsigned char[this->size_of_array_of_hashes_]; + this->array_of_hashes_ = dst; + for (size_t i = 0, src_offset = 0; i < num_hashes; + i++, dst += MD5_OUTPUT_SIZE_IN_BYTES, src_offset += chunk_size) + { + size_t size = std::min(chunk_size, filesize - src_offset); + workqueue->queue(new Hash_task(src + src_offset, + size, + dst, + build_id_blocker, + post_hash_tasks_blocker)); + } + return post_hash_tasks_blocker; + } + return build_id_blocker; +} + +// If a tree-style build ID was requested, the parallel part of that computation +// is already done, and the final hash-of-hashes is computed here. For other +// types of build IDs, all the work is done here. void Layout::write_build_id(Output_file* of) const @@ -5214,34 +5403,39 @@ Layout::write_build_id(Output_file* of) const if (this->build_id_note_ == NULL) return; - const unsigned char* iv = of->get_input_view(0, this->output_file_size_); - unsigned char* ov = of->get_output_view(this->build_id_note_->offset(), this->build_id_note_->data_size()); - const char* style = parameters->options().build_id(); - if (strcmp(style, "sha1") == 0) + if (this->array_of_hashes_ == NULL) { - sha1_ctx ctx; - sha1_init_ctx(&ctx); - sha1_process_bytes(iv, this->output_file_size_, &ctx); - sha1_finish_ctx(&ctx, ov); + const size_t output_file_size = this->output_file_size(); + const unsigned char* iv = of->get_input_view(0, output_file_size); + const char* style = parameters->options().build_id(); + + // If we get here with style == "tree" then the output must be + // too small for chunking, and we use SHA-1 in that case. + if ((strcmp(style, "sha1") == 0) || (strcmp(style, "tree") == 0)) + sha1_buffer(reinterpret_cast(iv), output_file_size, ov); + else if (strcmp(style, "md5") == 0) + md5_buffer(reinterpret_cast(iv), output_file_size, ov); + else + gold_unreachable(); + + of->free_input_view(0, output_file_size, iv); } - else if (strcmp(style, "md5") == 0) + else { - md5_ctx ctx; - md5_init_ctx(&ctx); - md5_process_bytes(iv, this->output_file_size_, &ctx); - md5_finish_ctx(&ctx, ov); + // Non-overlapping substrings of the output file have been hashed. + // Compute SHA-1 hash of the hashes. + sha1_buffer(reinterpret_cast(this->array_of_hashes_), + this->size_of_array_of_hashes_, ov); + delete[] this->array_of_hashes_; + of->free_input_view(0, this->output_file_size(), this->input_view_); } - else - gold_unreachable(); of->write_output_view(this->build_id_note_->offset(), this->build_id_note_->data_size(), ov); - - of->free_input_view(0, this->output_file_size_, iv); } // Write out a binary file. This is called after the link is @@ -5302,6 +5496,10 @@ Layout::print_to_mapfile(Mapfile* mapfile) const p != this->segment_list_.end(); ++p) (*p)->print_sections_to_mapfile(mapfile); + for (Section_list::const_iterator p = this->unattached_section_list_.begin(); + p != this->unattached_section_list_.end(); + ++p) + (*p)->print_to_mapfile(mapfile); } // Print statistical information to stderr. This is used for --stats. @@ -5336,6 +5534,8 @@ void Write_sections_task::locks(Task_locker* tl) { tl->add(this, this->output_sections_blocker_); + if (this->input_sections_blocker_ != NULL) + tl->add(this, this->input_sections_blocker_); tl->add(this, this->final_blocker_); } @@ -5431,12 +5631,14 @@ Write_after_input_sections_task::run(Workqueue*) // Close_task_runner methods. -// Run the task--close the file. +// Finish up the build ID computation, if necessary, and write a binary file, +// if necessary. Then close the output file. void Close_task_runner::run(Workqueue*, const Task*) { - // If we need to compute a checksum for the BUILD if, we do so here. + // At this point the multi-threaded part of the build ID computation, + // if any, is done. See queue_build_id_tasks(). this->layout_->write_build_id(this->of_); // If we've been asked to create a binary file, we do so here.