X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Flayout.h;h=1712db95ea4646c4f0fdb754c65b8a9f6fbda220;hb=4e2b16973ed4771143d1b23d12f941743da4003e;hp=3e09d62ca30b1e4db2d1901284a1d1b9787abb28;hpb=9025d29d14ae287d2bc338ef1b0bfa043799e15c;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/layout.h b/gold/layout.h index 3e09d62ca3..1712db95ea 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -1,6 +1,6 @@ // layout.h -- lay out output file sections for gold -*- C++ -*- -// Copyright 2006, 2007 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -28,6 +28,7 @@ #include #include +#include "script.h" #include "workqueue.h" #include "object.h" #include "dynobj.h" @@ -45,6 +46,7 @@ class Output_section_headers; class Output_segment; class Output_data; class Output_data_dynamic; +class Eh_frame; class Target; // This task function handles mapping the input sections to output @@ -59,14 +61,15 @@ class Layout_task_runner : public Task_function_runner Layout_task_runner(const General_options& options, const Input_objects* input_objects, Symbol_table* symtab, + Target* target, Layout* layout) : options_(options), input_objects_(input_objects), symtab_(symtab), - layout_(layout) + target_(target), layout_(layout) { } // Run the operation. void - run(Workqueue*); + run(Workqueue*, const Task*); private: Layout_task_runner(const Layout_task_runner&); @@ -75,6 +78,7 @@ class Layout_task_runner : public Task_function_runner const General_options& options_; const Input_objects* input_objects_; Symbol_table* symtab_; + Target* target_; Layout* layout_; }; @@ -83,16 +87,71 @@ class Layout_task_runner : public Task_function_runner class Layout { public: - Layout(const General_options& options); + Layout(const General_options& options, Script_options*); // Given an input section SHNDX, named NAME, with data in SHDR, from // the object file OBJECT, return the output section where this - // input section should go. Set *OFFSET to the offset within the - // output section. + // input section should go. RELOC_SHNDX is the index of a + // relocation section which applies to this section, or 0 if none, + // or -1U if more than one. RELOC_TYPE is the type of the + // relocation section if there is one. Set *OFFSET to the offset + // within the output section. + template + Output_section* + layout(Sized_relobj *object, unsigned int shndx, + const char* name, const elfcpp::Shdr& shdr, + unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset); + + // Layout an input reloc section when doing a relocatable link. The + // section is RELOC_SHNDX in OBJECT, with data in SHDR. + // DATA_SECTION is the reloc section to which it refers. RR is the + // relocatable information. + template + Output_section* + layout_reloc(Sized_relobj* object, + unsigned int reloc_shndx, + const elfcpp::Shdr& shdr, + Output_section* data_section, + Relocatable_relocs* rr); + + // Layout a group section when doing a relocatable link. + template + void + layout_group(Symbol_table* symtab, + Sized_relobj* object, + unsigned int group_shndx, + const char* group_section_name, + const char* signature, + const elfcpp::Shdr& shdr, + const elfcpp::Elf_Word* contents); + + // Like layout, only for exception frame sections. OBJECT is an + // object file. SYMBOLS is the contents of the symbol table + // section, with size SYMBOLS_SIZE. SYMBOL_NAMES is the contents of + // the symbol name section, with size SYMBOL_NAMES_SIZE. SHNDX is a + // .eh_frame section in OBJECT. SHDR is the section header. + // RELOC_SHNDX is the index of a relocation section which applies to + // this section, or 0 if none, or -1U if more than one. RELOC_TYPE + // is the type of the relocation section if there is one. This + // returns the output section, and sets *OFFSET to the offset. template Output_section* - layout(Relobj *object, unsigned int shndx, const char* name, - const elfcpp::Shdr& shdr, off_t* offset); + layout_eh_frame(Sized_relobj* object, + const unsigned char* symbols, + off_t symbols_size, + const unsigned char* symbol_names, + off_t symbol_names_size, + unsigned int shndx, + const elfcpp::Shdr& shdr, + unsigned int reloc_shndx, unsigned int reloc_type, + off_t* offset); + + // Handle a GNU stack note. This is called once per input object + // file. SEEN_GNU_STACK is true if the object file has a + // .note.GNU-stack section. GNU_STACK_FLAGS is the section flags + // from that section if there was one. + void + layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags); // Add an Output_section_data to the layout. This is used for // special sections like the GOT section. @@ -103,11 +162,25 @@ class Layout // Create dynamic sections if necessary. void - create_initial_dynamic_sections(const Input_objects*, Symbol_table*); + create_initial_dynamic_sections(Symbol_table*); // Define __start and __stop symbols for output sections. void - define_section_symbols(Symbol_table*, const Target*); + define_section_symbols(Symbol_table*); + + // Create sections for linker scripts. + void + create_script_sections() + { this->script_options_->create_script_sections(this); } + + // Define symbols from any linker script. + void + define_script_symbols(Symbol_table* symtab) + { this->script_options_->add_symbols_to_table(symtab); } + + // Define symbols for group signatures. + void + define_group_signatures(Symbol_table*); // Return the Stringpool used for symbol names. const Stringpool* @@ -135,7 +208,17 @@ class Layout // Finalize the layout after all the input sections have been added. off_t - finalize(const Input_objects*, Symbol_table*); + finalize(const Input_objects*, Symbol_table*, Target*, const Task*); + + // Return whether any sections require postprocessing. + bool + any_postprocessing_sections() const + { return this->any_postprocessing_sections_; } + + // Return the size of the output file. + off_t + output_file_size() const + { return this->output_file_size_; } // Return the TLS segment. This will return NULL if there isn't // one. @@ -164,11 +247,20 @@ class Layout dynamic_data() const { return this->dynamic_data_; } + // Write out the output sections. + void + write_output_sections(Output_file* of) const; + // Write out data not associated with an input file or the symbol // table. void write_data(const Symbol_table*, Output_file*) const; + // Write out output sections which can not be written until all the + // input sections are complete. + void + write_sections_after_input_sections(Output_file* of); + // Return an output section named NAME, or NULL if there is none. Output_section* find_output_section(const char* name) const; @@ -179,11 +271,42 @@ class Layout find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set, elfcpp::Elf_Word clear) const; - // The list of segments. + // Return the number of segments we expect to produce. + size_t + expected_segment_count() const; + + // Set a flag to indicate that an object file uses the static TLS model. + void + set_has_static_tls() + { this->has_static_tls_ = true; } + + // Return true if any object file uses the static TLS model. + bool + has_static_tls() const + { return this->has_static_tls_; } + + // Return the options which may be set by a linker script. + Script_options* + script_options() + { return this->script_options_; } + + const Script_options* + script_options() const + { return this->script_options_; } + + // Rewrite output file in binary format. + void + write_binary(Output_file* in) const; + + // Dump statistical information to stderr. + void + print_stats() const; + + // A list of segments. typedef std::vector Segment_list; - // The list of sections not attached to a segment. + // A list of sections. typedef std::vector Section_list; @@ -191,6 +314,28 @@ class Layout // either a section or a segment. typedef std::vector Data_list; + // Store the allocated sections into the section list. This is used + // by the linker script code. + void + get_allocated_sections(Section_list*) const; + + // Make a section for a linker script to hold data. + Output_section* + make_output_section_for_script(const char* name); + + // Make a segment. This is used by the linker script code. + Output_segment* + make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags); + + // Return the number of segments. + size_t + segment_count() const + { return this->segment_list_.size(); } + + // Map from section flags to segment flags. + static elfcpp::Elf_Word + section_flags_to_segment(elfcpp::Elf_Xword flags); + private: Layout(const Layout&); Layout& operator=(const Layout&); @@ -206,18 +351,43 @@ class Layout static const Linkonce_mapping linkonce_mapping[]; static const int linkonce_mapping_count; - // Handle an exception frame section. - template + // During a relocatable link, a list of group sections and + // signatures. + struct Group_signature + { + // The group section. + Output_section* section; + // The signature. + const char* signature; + + Group_signature() + : section(NULL), signature(NULL) + { } + + Group_signature(Output_section* sectiona, const char* signaturea) + : section(sectiona), signature(signaturea) + { } + }; + typedef std::vector Group_signatures; + + // Create a .note section for gold. + void + create_gold_note(); + + // Record whether the stack must be executable. void - layout_eh_frame(Relobj*, unsigned int, const char*, - const elfcpp::Shdr&, - Output_section*, off_t*); + create_executable_stack_info(const Target*); // Find the first read-only PT_LOAD segment, creating one if // necessary. Output_segment* find_first_load_seg(); + // Count the local symbols in the regular symbol table and the dynamic + // symbol table, and build the respective string pools. + void + count_local_symbols(const Task*, const Input_objects*); + // Create the output sections for the symbol table. void create_symtab_sections(const Input_objects*, Symbol_table*, off_t*); @@ -227,16 +397,21 @@ class Layout create_shstrtab(); // Create the section header table. - Output_section_headers* + void create_shdrs(off_t*); // Create the dynamic symbol table. void - create_dynamic_symtab(const Target*, Symbol_table*, Output_section** pdynstr, + create_dynamic_symtab(const Input_objects*, Symbol_table*, + Output_section** pdynstr, unsigned int* plocal_dynamic_count, std::vector* pdynamic_symbols, Versions* versions); + // Assign offsets to each local portion of the dynamic symbol table. + void + assign_local_dynsym_offsets(const Input_objects*); + // Finish the .dynamic section and PT_DYNAMIC segment. void finish_dynamic_section(const Input_objects*, const Symbol_table*); @@ -248,6 +423,7 @@ class Layout // Create the version sections. void create_version_sections(const Versions*, + const Symbol_table*, unsigned int local_symcount, const std::vector& dynamic_symbols, const Output_section* dynstr); @@ -255,15 +431,15 @@ class Layout template void sized_create_version_sections(const Versions* versions, + const Symbol_table*, unsigned int local_symcount, const std::vector& dynamic_symbols, - const Output_section* dynstr - ACCEPT_SIZE_ENDIAN); + const Output_section* dynstr); // Return whether to include this section in the link. template bool - include_section(Object* object, const char* name, + include_section(Sized_relobj* object, const char* name, const elfcpp::Shdr&); // Return the output section name to use given an input section @@ -282,28 +458,62 @@ class Layout get_output_section(const char* name, Stringpool::Key name_key, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags); + // Choose the output section for NAME in RELOBJ. + Output_section* + choose_output_section(const Relobj* relobj, const char* name, + elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, + bool adjust_name); + // Create a new Output_section. Output_section* make_output_section(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags); + // Attach a section to a segment. + void + attach_to_segment(Output_section*, elfcpp::Elf_Xword flags); + + // Allocate a previously unallocated output section. + void + allocate_output_section(Output_section*, elfcpp::Elf_Xword flags); + // Set the final file offsets of all the segments. off_t set_segment_offsets(const Target*, Output_segment*, unsigned int* pshndx); - // Set the final file offsets and section indexes of all the - // sections not associated with a segment. + // Set the file offsets of the sections when doing a relocatable + // link. + off_t + set_relocatable_section_offsets(Output_data*, unsigned int* pshndx); + + // Set the final file offsets of all the sections not associated + // with a segment. We set section offsets in three passes: the + // first handles all allocated sections, the second sections that + // require postprocessing, and the last the late-bound STRTAB + // sections (probably only shstrtab, which is the one we care about + // because it holds section names). + enum Section_offset_pass + { + BEFORE_INPUT_SECTIONS_PASS, + POSTPROCESSING_SECTIONS_PASS, + STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS + }; off_t - set_section_offsets(off_t, unsigned int *pshndx); + set_section_offsets(off_t, Section_offset_pass pass); + + // Set the final section indexes of all the sections not associated + // with a segment. Returns the next unused index. + unsigned int + set_section_indexes(unsigned int pshndx); + + // Set the section addresses when using a script. + Output_segment* + set_section_addresses_from_script(Symbol_table*); // Return whether SEG1 comes before SEG2 in the output file. static bool segment_precedes(const Output_segment* seg1, const Output_segment* seg2); - // Map from section flags to segment flags. - static elfcpp::Elf_Word - section_flags_to_segment(elfcpp::Elf_Xword flags); - // A mapping used for group signatures. typedef Unordered_map Signatures; @@ -332,6 +542,8 @@ class Layout // A reference to the options on the command line. const General_options& options_; + // Information set by scripts or by command line options. + Script_options* script_options_; // The output section names. Stringpool namepool_; // The output symbol names. @@ -352,6 +564,8 @@ class Layout // The list of unattached Output_data objects which require special // handling because they are not Output_sections. Data_list special_output_list_; + // The section headers. + Output_section_headers* section_headers_; // A pointer to the PT_TLS segment if there is one. Output_segment* tls_segment_; // The SHT_SYMTAB output section. @@ -362,8 +576,69 @@ class Layout Output_section* dynamic_section_; // The dynamic data which goes into dynamic_section_. Output_data_dynamic* dynamic_data_; - // The exception frame section. + // The exception frame output section if there is one. Output_section* eh_frame_section_; + // The exception frame data for eh_frame_section_. + Eh_frame* eh_frame_data_; + // The exception frame header output section if there is one. + Output_section* eh_frame_hdr_section_; + // A list of group sections and their signatures. + Group_signatures group_signatures_; + // The size of the output file. + off_t output_file_size_; + // Whether we have seen an object file marked to require an + // executable stack. + bool input_requires_executable_stack_; + // Whether we have seen at least one object file with an executable + // stack marker. + bool input_with_gnu_stack_note_; + // Whether we have seen at least one object file without an + // executable stack marker. + bool input_without_gnu_stack_note_; + // Whether we have seen an object file that uses the static TLS model. + bool has_static_tls_; + // Whether any sections require postprocessing. + bool any_postprocessing_sections_; +}; + +// This task handles writing out data in output sections which is not +// part of an input section, or which requires special handling. When +// this is done, it unblocks both output_sections_blocker and +// final_blocker. + +class Write_sections_task : public Task +{ + public: + Write_sections_task(const Layout* layout, Output_file* of, + Task_token* output_sections_blocker, + Task_token* final_blocker) + : layout_(layout), of_(of), + output_sections_blocker_(output_sections_blocker), + final_blocker_(final_blocker) + { } + + // The standard Task methods. + + Task_token* + is_runnable(); + + void + locks(Task_locker*); + + void + run(Workqueue*); + + std::string + get_name() const + { return "Write_sections_task"; } + + private: + class Write_sections_locker; + + const Layout* layout_; + Output_file* of_; + Task_token* output_sections_blocker_; + Task_token* final_blocker_; }; // This task handles writing out data which is not part of a section @@ -379,15 +654,19 @@ class Write_data_task : public Task // The standard Task methods. - Is_runnable_type - is_runnable(Workqueue*); + Task_token* + is_runnable(); - Task_locker* - locks(Workqueue*); + void + locks(Task_locker*); void run(Workqueue*); + std::string + get_name() const + { return "Write_data_task"; } + private: const Layout* layout_; const Symbol_table* symtab_; @@ -400,47 +679,93 @@ class Write_data_task : public Task class Write_symbols_task : public Task { public: - Write_symbols_task(const Symbol_table* symtab, const Target* target, + Write_symbols_task(const Symbol_table* symtab, + const Input_objects* input_objects, const Stringpool* sympool, const Stringpool* dynpool, Output_file* of, Task_token* final_blocker) - : symtab_(symtab), target_(target), sympool_(sympool), dynpool_(dynpool), - of_(of), final_blocker_(final_blocker) + : symtab_(symtab), input_objects_(input_objects), sympool_(sympool), + dynpool_(dynpool), of_(of), final_blocker_(final_blocker) { } // The standard Task methods. - Is_runnable_type - is_runnable(Workqueue*); + Task_token* + is_runnable(); - Task_locker* - locks(Workqueue*); + void + locks(Task_locker*); void run(Workqueue*); + std::string + get_name() const + { return "Write_symbols_task"; } + private: const Symbol_table* symtab_; - const Target* target_; + const Input_objects* input_objects_; const Stringpool* sympool_; const Stringpool* dynpool_; Output_file* of_; Task_token* final_blocker_; }; +// This task handles writing out data in output sections which can't +// be written out until all the input sections have been handled. +// This is for sections whose contents is based on the contents of +// other output sections. + +class Write_after_input_sections_task : public Task +{ + public: + Write_after_input_sections_task(Layout* layout, Output_file* of, + Task_token* input_sections_blocker, + Task_token* final_blocker) + : layout_(layout), of_(of), + input_sections_blocker_(input_sections_blocker), + final_blocker_(final_blocker) + { } + + // The standard Task methods. + + Task_token* + is_runnable(); + + void + locks(Task_locker*); + + void + run(Workqueue*); + + std::string + get_name() const + { return "Write_after_input_sections_task"; } + + private: + Layout* layout_; + Output_file* of_; + Task_token* input_sections_blocker_; + Task_token* final_blocker_; +}; + // This task function handles closing the file. class Close_task_runner : public Task_function_runner { public: - Close_task_runner(Output_file* of) - : of_(of) + Close_task_runner(const General_options* options, const Layout* layout, + Output_file* of) + : options_(options), layout_(layout), of_(of) { } // Run the operation. void - run(Workqueue*); + run(Workqueue*, const Task*); private: + const General_options* options_; + const Layout* layout_; Output_file* of_; };