]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* mapfile.cc: New file.
authorIan Lance Taylor <ian@airs.com>
Wed, 21 May 2008 21:37:44 +0000 (21:37 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 21 May 2008 21:37:44 +0000 (21:37 +0000)
* mapfile.h: New file.
* options.h (class General_options): Add -M/--print-map and -Map.
* options.cc (General_options::finalize): Make -M equivalent to
-Map -.
* main.cc: Include <cstdio> and "mapfile.h".
(main): Open mapfile if requested.
* gold.cc (class Middle_runner): Add mapfile_ field.  Update
constructor.  Change caller.
(queue_initial_tasks): Add mapfile parameter.  Change caller.
(queue_middle_tasks): Likewise.
* gold.h (queue_initial_tasks, queue_middle_tasks): Update
declarations.
* archive.cc: Include "mapfile.h".
(Archive::add_symbols): Add mapfile parameter.  Change all
callers.  Pass mapfile, symbol, and reason to include_member.
(Archive::include_all_members): Add mapfile parameter.  Change all
callers.
(Archive::include_member): Add mapfile, sym, and why parameters.
Change all callers.  Report inclusion to map file.
* archive.h: Include "fileread.h".
(class Archive): Update declarations.
(Archive::file): New const method.
(class Add_archive_symbols): Add mapfile_ field.  Update
constructor.  Change all callers.
* readsyms.h (class Read_symbols): Likewise.
(class Finish_group): Likewise.
(class Read_script): Likewise.
* common.cc: Include "mapfile.h".
(Symbol_table::allocate_commons): Add mapfile parameter.  Change
all callers.
(Symbol_table::do_allocate_commons): Likewise.
(Symbol_table::do_allocate_commons_list): Likewise.  Report common
symbol allocation to mapfile.
* common.h (class Allocate_commons_task): Add mapfile_ field.
Update constructor.  Change all callers.
* symtab.h (class Symbol_table): Update declarations.
* layout.cc: Include "mapfile.h".
(Layout_task_runner::run): Print information to mapfile.
(Layout::create_gold_note): Change Output_data_fixed_space to
Output_data_zero_fill.
(Layout::create_build_id): Likewise.
(Layout::print_to_mapfile): New function.
* layout.h (class Layout_task_runner): Add mapfile_ field.  Update
constructor.  Change caller.
(class Layout): Declare print_to_mapfile.
* output.cc (Output_section::Input_section::print_to_mapfile): New
function.
(Output_section::add_input_section): If producing a map, always
add to input_sections_ list.
(Output_section::do_print_to_mapfile): New function.
(Output_segment::print_sections_to_mapfile): New function.
(Output_segment::print_section_list_to_mapfile): New function.
* output.h: Include "mapfile.h".
(Output_data::print_to_mapfile): New function.
(Output_data::do_print_to_mapfile): New virtual function.
(Output_segment_headers::do_print_to_mapfile): New function.
(Output_file_header::do_print_to_mapfile): New function.
(Output_data_const::do_print_to_mapfile): New function.
(class Output_data_const_buffer): Add map_name_ field.  Update
constructor.  Change all callers.  Add do_print_to_mapfile
function.
(class Output_data_fixed_space): Likewise.
(class Output_data_space): Likewise.
(class Output_data_zero_fill): New class.
(Output_data_strtab::do_print_to_mapfile): New function.
(Output_data_reloc_base::do_print_to_mapfile): New function.
(Output_relocatable_relocs::do_print_to_mapfile): New function.
(Output_data_group::do_print_to_mapfile): New function.
(Output_data_got::do_print_to_mapfile): New function.
(Output_data_dynamic::do_print_to_mapfile): New function.
(Output_symtab_xindex::do_print_to_mapfile): New function.
(class Output_section): Declare do_print_to_mapflie.  Declare
print_to_mapfile in Input_section.
(class Output_segment): Declare new functions.
* object.h (Sized_relobj::symbol_count): New function.
* script-sections.cc
(Output_section_element_dot_assignment::set_section_addresses):
Change Output_data_fixed_space to Output_data_zero_fill.
(Output_data_expression::do_print_to_mapfile): New function.
* script.cc (read_input_script): Add mapfile parameter.  Change
all callers.
* script.h (read_input_script): Update declaration.
* ehframe.h (Eh_frame_hdr::do_print_to_mapfile): New function.
(Eh_frame::do_print_to_mapfile): New function.
* merge.h (Output_merge_data::do_print_to_mapfile): New function.
(Output_merge_string::do_print_to_mapfile): New function.
* i386.cc (Output_data_plt_i386::do_print_to_mapfile): New
function.
* sparc.cc (Output_data_plt_sparc::do_print_to_mapfile): New
function.
* x86_64.cc (Output_data_plt_x86_64::do_print_to_mapfile): New
function.
* Makefile.am (CCFILES): Add mapfile.cc.
(HFILES): Add mapfile.h.
* Makefile.in: Rebuild.

31 files changed:
gold/ChangeLog
gold/Makefile.am
gold/Makefile.in
gold/archive.cc
gold/archive.h
gold/common.cc
gold/common.h
gold/copy-relocs.cc
gold/ehframe.h
gold/gold.cc
gold/gold.h
gold/i386.cc
gold/layout.cc
gold/layout.h
gold/main.cc
gold/mapfile.cc [new file with mode: 0644]
gold/mapfile.h [new file with mode: 0644]
gold/merge.h
gold/object.h
gold/options.cc
gold/options.h
gold/output.cc
gold/output.h
gold/readsyms.cc
gold/readsyms.h
gold/script-sections.cc
gold/script.cc
gold/script.h
gold/sparc.cc
gold/symtab.h
gold/x86_64.cc

index bd4db9de4c60c5a0d40fdd65d7cbb7394e7d651d..c8843cef8dc9f203ffc076fe864d6b21eeb1ad84 100644 (file)
@@ -1,3 +1,102 @@
+2008-05-21  Ian Lance Taylor  <iant@google.com>
+
+       * mapfile.cc: New file.
+       * mapfile.h: New file.
+       * options.h (class General_options): Add -M/--print-map and -Map.
+       * options.cc (General_options::finalize): Make -M equivalent to
+       -Map -.
+       * main.cc: Include <cstdio> and "mapfile.h".
+       (main): Open mapfile if requested.
+       * gold.cc (class Middle_runner): Add mapfile_ field.  Update
+       constructor.  Change caller.
+       (queue_initial_tasks): Add mapfile parameter.  Change caller.
+       (queue_middle_tasks): Likewise.
+       * gold.h (queue_initial_tasks, queue_middle_tasks): Update
+       declarations.
+       * archive.cc: Include "mapfile.h".
+       (Archive::add_symbols): Add mapfile parameter.  Change all
+       callers.  Pass mapfile, symbol, and reason to include_member.
+       (Archive::include_all_members): Add mapfile parameter.  Change all
+       callers.
+       (Archive::include_member): Add mapfile, sym, and why parameters.
+       Change all callers.  Report inclusion to map file.
+       * archive.h: Include "fileread.h".
+       (class Archive): Update declarations.
+       (Archive::file): New const method.
+       (class Add_archive_symbols): Add mapfile_ field.  Update
+       constructor.  Change all callers.
+       * readsyms.h (class Read_symbols): Likewise.
+       (class Finish_group): Likewise.
+       (class Read_script): Likewise.
+       * common.cc: Include "mapfile.h".
+       (Symbol_table::allocate_commons): Add mapfile parameter.  Change
+       all callers.
+       (Symbol_table::do_allocate_commons): Likewise.
+       (Symbol_table::do_allocate_commons_list): Likewise.  Report common
+       symbol allocation to mapfile.
+       * common.h (class Allocate_commons_task): Add mapfile_ field.
+       Update constructor.  Change all callers.
+       * symtab.h (class Symbol_table): Update declarations.
+       * layout.cc: Include "mapfile.h".
+       (Layout_task_runner::run): Print information to mapfile.
+       (Layout::create_gold_note): Change Output_data_fixed_space to
+       Output_data_zero_fill.
+       (Layout::create_build_id): Likewise.
+       (Layout::print_to_mapfile): New function.
+       * layout.h (class Layout_task_runner): Add mapfile_ field.  Update
+       constructor.  Change caller.
+       (class Layout): Declare print_to_mapfile.
+       * output.cc (Output_section::Input_section::print_to_mapfile): New
+       function.
+       (Output_section::add_input_section): If producing a map, always
+       add to input_sections_ list.
+       (Output_section::do_print_to_mapfile): New function.
+       (Output_segment::print_sections_to_mapfile): New function.
+       (Output_segment::print_section_list_to_mapfile): New function.
+       * output.h: Include "mapfile.h".
+       (Output_data::print_to_mapfile): New function.
+       (Output_data::do_print_to_mapfile): New virtual function.
+       (Output_segment_headers::do_print_to_mapfile): New function.
+       (Output_file_header::do_print_to_mapfile): New function.
+       (Output_data_const::do_print_to_mapfile): New function.
+       (class Output_data_const_buffer): Add map_name_ field.  Update
+       constructor.  Change all callers.  Add do_print_to_mapfile
+       function.
+       (class Output_data_fixed_space): Likewise.
+       (class Output_data_space): Likewise.
+       (class Output_data_zero_fill): New class.
+       (Output_data_strtab::do_print_to_mapfile): New function.
+       (Output_data_reloc_base::do_print_to_mapfile): New function.
+       (Output_relocatable_relocs::do_print_to_mapfile): New function.
+       (Output_data_group::do_print_to_mapfile): New function.
+       (Output_data_got::do_print_to_mapfile): New function.
+       (Output_data_dynamic::do_print_to_mapfile): New function.
+       (Output_symtab_xindex::do_print_to_mapfile): New function.
+       (class Output_section): Declare do_print_to_mapflie.  Declare
+       print_to_mapfile in Input_section.
+       (class Output_segment): Declare new functions.
+       * object.h (Sized_relobj::symbol_count): New function.
+       * script-sections.cc
+       (Output_section_element_dot_assignment::set_section_addresses):
+       Change Output_data_fixed_space to Output_data_zero_fill.
+       (Output_data_expression::do_print_to_mapfile): New function.
+       * script.cc (read_input_script): Add mapfile parameter.  Change
+       all callers.
+       * script.h (read_input_script): Update declaration.
+       * ehframe.h (Eh_frame_hdr::do_print_to_mapfile): New function.
+       (Eh_frame::do_print_to_mapfile): New function.
+       * merge.h (Output_merge_data::do_print_to_mapfile): New function.
+       (Output_merge_string::do_print_to_mapfile): New function.
+       * i386.cc (Output_data_plt_i386::do_print_to_mapfile): New
+       function.
+       * sparc.cc (Output_data_plt_sparc::do_print_to_mapfile): New
+       function.
+       * x86_64.cc (Output_data_plt_x86_64::do_print_to_mapfile): New
+       function.
+       * Makefile.am (CCFILES): Add mapfile.cc.
+       (HFILES): Add mapfile.h.
+       * Makefile.in: Rebuild.
+
 2008-05-19  Ian Lance Taylor  <iant@google.com>
 
        * options.h (class General_options): Add -z relro.
index 020fd9586d50c0a8c4ae6ebd5fa5ab10ccea8be3..14c3c4bacb3ddb0bdc7ad5d4df5d858663bb9efb 100644 (file)
@@ -45,6 +45,7 @@ CCFILES = \
        gold.cc \
        gold-threads.cc \
        layout.cc \
+       mapfile.cc \
        merge.cc \
        object.cc \
        options.cc \
@@ -78,6 +79,7 @@ HFILES = \
        gold.h \
        gold-threads.h \
        layout.h \
+       mapfile.h \
        merge.h \
        object.h \
        options.h \
index cc1a9e4d77a9dbff818771be268c35a6dc91792a..5781ebcefbfb9013184b96d834e09a2277bfd96f 100644 (file)
@@ -79,12 +79,12 @@ am__objects_1 = archive.$(OBJEXT) binary.$(OBJEXT) common.$(OBJEXT) \
        defstd.$(OBJEXT) dirsearch.$(OBJEXT) dynobj.$(OBJEXT) \
        dwarf_reader.$(OBJEXT) ehframe.$(OBJEXT) errors.$(OBJEXT) \
        expression.$(OBJEXT) fileread.$(OBJEXT) gold.$(OBJEXT) \
-       gold-threads.$(OBJEXT) layout.$(OBJEXT) merge.$(OBJEXT) \
-       object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
-       parameters.$(OBJEXT) readsyms.$(OBJEXT) reloc.$(OBJEXT) \
-       resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
-       stringpool.$(OBJEXT) symtab.$(OBJEXT) target-select.$(OBJEXT) \
-       version.$(OBJEXT) workqueue.$(OBJEXT) \
+       gold-threads.$(OBJEXT) layout.$(OBJEXT) mapfile.$(OBJEXT) \
+       merge.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
+       output.$(OBJEXT) parameters.$(OBJEXT) readsyms.$(OBJEXT) \
+       reloc.$(OBJEXT) resolve.$(OBJEXT) script-sections.$(OBJEXT) \
+       script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
+       target-select.$(OBJEXT) version.$(OBJEXT) workqueue.$(OBJEXT) \
        workqueue-threads.$(OBJEXT)
 am__objects_2 =
 am__objects_3 = yyscript.$(OBJEXT)
@@ -325,6 +325,7 @@ CCFILES = \
        gold.cc \
        gold-threads.cc \
        layout.cc \
+       mapfile.cc \
        merge.cc \
        object.cc \
        options.cc \
@@ -358,6 +359,7 @@ HFILES = \
        gold.h \
        gold-threads.h \
        layout.h \
+       mapfile.h \
        merge.h \
        object.h \
        options.h \
@@ -531,6 +533,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
index 1e16de9c76e764234f64db1a5c52d7dfd9a546b5..0ff8aee2075bd1a3216e0c6c2151c578f2b082c3 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "elfcpp.h"
 #include "options.h"
+#include "mapfile.h"
 #include "fileread.h"
 #include "readsyms.h"
 #include "symtab.h"
@@ -286,10 +287,11 @@ Archive::interpret_header(const Archive_header* hdr, off_t off,
 
 void
 Archive::add_symbols(Symbol_table* symtab, Layout* layout,
-                    Input_objects* input_objects)
+                    Input_objects* input_objects, Mapfile* mapfile)
 {
   if (this->input_file_->options().whole_archive())
-    return this->include_all_members(symtab, layout, input_objects);
+    return this->include_all_members(symtab, layout, input_objects,
+                                    mapfile);
 
   const size_t armap_size = this->armap_.size();
 
@@ -343,8 +345,16 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
          last_seen_offset = this->armap_[i].file_offset;
          this->seen_offsets_.insert(last_seen_offset);
           this->armap_checked_[i] = true;
+
+         std::string why;
+         if (sym == NULL)
+           {
+             why = "-u ";
+             why += sym_name;
+           }
          this->include_member(symtab, layout, input_objects,
-                              last_seen_offset);
+                              last_seen_offset, mapfile, sym, why.c_str());
+
          added_new_object = true;
        }
     }
@@ -355,7 +365,7 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
 
 void
 Archive::include_all_members(Symbol_table* symtab, Layout* layout,
-                             Input_objects* input_objects)
+                             Input_objects* input_objects, Mapfile* mapfile)
 {
   off_t off = sarmag;
   off_t filesize = this->input_file_->file().filesize();
@@ -385,7 +395,8 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
           // Extended name table.
         }
       else
-        this->include_member(symtab, layout, input_objects, off);
+        this->include_member(symtab, layout, input_objects, off,
+                            mapfile, NULL, "--whole-archive");
 
       off += sizeof(Archive_header);
       if (!this->is_thin_archive_)
@@ -396,16 +407,20 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
 }
 
 // Include an archive member in the link.  OFF is the file offset of
-// the member header.
+// the member header.  WHY is the reason we are including this member.
 
 void
 Archive::include_member(Symbol_table* symtab, Layout* layout,
-                       Input_objects* input_objects, off_t off)
+                       Input_objects* input_objects, off_t off,
+                       Mapfile* mapfile, Symbol* sym, const char* why)
 {
   std::string n;
   off_t nested_off;
   this->read_header(off, false, &n, &nested_off);
 
+  if (mapfile != NULL)
+    mapfile->report_include_archive_member(this, n, sym, why);
+
   Input_file* input_file;
   off_t memoff;
 
@@ -451,7 +466,8 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
                 this->nested_archives_.insert(std::make_pair(n, arch));
               gold_assert(ins.second);
             }
-          arch->include_member(symtab, layout, input_objects, nested_off);
+          arch->include_member(symtab, layout, input_objects, nested_off,
+                              NULL, NULL, NULL);
           return;
         }
       // This is an external member of a thin archive.  Open the
@@ -551,7 +567,7 @@ void
 Add_archive_symbols::run(Workqueue*)
 {
   this->archive_->add_symbols(this->symtab_, this->layout_,
-                             this->input_objects_);
+                             this->input_objects_, this->mapfile_);
 
   this->archive_->unlock_nested_archives();
 
index 818bd60c65e4bdfcfc594d8a11e7dd88bfc8e753..c8b05e442da25b853c93412158f381c7bceb1c20 100644 (file)
@@ -26,6 +26,7 @@
 #include <string>
 #include <vector>
 
+#include "fileread.h"
 #include "workqueue.h"
 
 namespace gold
@@ -75,6 +76,10 @@ class Archive
   file()
   { return this->input_file_->file(); }
 
+  const File_read&
+  file() const
+  { return this->input_file_->file(); }
+
   // Lock the underlying file.
   void
   lock(const Task* t)
@@ -112,7 +117,7 @@ class Archive
   // Select members from the archive as needed and add them to the
   // link.
   void
-  add_symbols(Symbol_table*, Layout*, Input_objects*);
+  add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
 
  private:
   Archive(const Archive&);
@@ -143,11 +148,12 @@ class Archive
 
   // Include all the archive members in the link.
   void
-  include_all_members(Symbol_table*, Layout*, Input_objects*);
+  include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);
 
   // Include an archive member in the link.
   void
-  include_member(Symbol_table*, Layout*, Input_objects*, off_t off);
+  include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
+                Mapfile*, Symbol*, const char* why);
 
   // An entry in the archive map of symbols to object files.
   struct Armap_entry
@@ -201,12 +207,12 @@ class Add_archive_symbols : public Task
 {
  public:
   Add_archive_symbols(Symbol_table* symtab, Layout* layout,
-                     Input_objects* input_objects,
+                     Input_objects* input_objects, Mapfile* mapfile,
                      Archive* archive, Input_group* input_group,
                      Task_token* this_blocker,
                      Task_token* next_blocker)
     : symtab_(symtab), layout_(layout), input_objects_(input_objects),
-      archive_(archive), input_group_(input_group),
+      mapfile_(mapfile), archive_(archive), input_group_(input_group),
       this_blocker_(this_blocker), next_blocker_(next_blocker)
   { }
 
@@ -235,6 +241,7 @@ class Add_archive_symbols : public Task
   Symbol_table* symtab_;
   Layout* layout_;
   Input_objects* input_objects_;
+  Mapfile* mapfile_;
   Archive* archive_;
   Input_group* input_group_;
   Task_token* this_blocker_;
index 6789d5d087db87ab017cab8f76c010538a9526ac..632a20b6c9906469f516cc1d595bf795a3e38759 100644 (file)
@@ -25,6 +25,7 @@
 #include <algorithm>
 
 #include "workqueue.h"
+#include "mapfile.h"
 #include "layout.h"
 #include "output.h"
 #include "symtab.h"
@@ -60,7 +61,7 @@ Allocate_commons_task::locks(Task_locker* tl)
 void
 Allocate_commons_task::run(Workqueue*)
 {
-  this->symtab_->allocate_commons(this->layout_);
+  this->symtab_->allocate_commons(this->layout_, this->mapfile_);
 }
 
 // This class is used to sort the common symbol by size.  We put the
@@ -117,12 +118,12 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
 // Allocate the common symbols.
 
 void
-Symbol_table::allocate_commons(Layout* layout)
+Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
 {
   if (parameters->target().get_size() == 32)
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
-      this->do_allocate_commons<32>(layout);
+      this->do_allocate_commons<32>(layout, mapfile);
 #else
       gold_unreachable();
 #endif
@@ -130,7 +131,7 @@ Symbol_table::allocate_commons(Layout* layout)
   else if (parameters->target().get_size() == 64)
     {
 #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
-      this->do_allocate_commons<64>(layout);
+      this->do_allocate_commons<64>(layout, mapfile);
 #else
       gold_unreachable();
 #endif
@@ -143,10 +144,12 @@ Symbol_table::allocate_commons(Layout* layout)
 
 template<int size>
 void
-Symbol_table::do_allocate_commons(Layout* layout)
+Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile)
 {
-  this->do_allocate_commons_list<size>(layout, false, &this->commons_);
-  this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_);
+  this->do_allocate_commons_list<size>(layout, false, &this->commons_,
+                                      mapfile);
+  this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_,
+                                      mapfile);
 }
 
 // Allocate the common symbols in a list.  IS_TLS indicates whether
@@ -155,7 +158,8 @@ Symbol_table::do_allocate_commons(Layout* layout)
 template<int size>
 void
 Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
-                                      Commons_type* commons)
+                                      Commons_type* commons,
+                                      Mapfile* mapfile)
 {
   typedef typename Sized_symbol<size>::Value_type Value_type;
   typedef typename Sized_symbol<size>::Size_type Size_type;
@@ -195,7 +199,10 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
 
   // Place them in a newly allocated BSS section.
 
-  Output_data_space *poc = new Output_data_space(addralign);
+  Output_data_space *poc = new Output_data_space(addralign,
+                                                (is_tls
+                                                 ? "** tls common"
+                                                 : "** common"));
 
   const char* name = ".bss";
   elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
@@ -217,6 +224,13 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
       if (sym == NULL)
        break;
       Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
+
+      // Record the symbol in the map file now, before we change its
+      // value.  Pass the size in separately so that we don't have to
+      // templatize the map code, which is not performance sensitive.
+      if (mapfile != NULL)
+       mapfile->report_allocate_common(sym, ssym->symsize());
+
       off = align_address(off, ssym->value());
       ssym->allocate_common(poc, off);
       off += ssym->symsize();
index 6c281c917e0b3231970f2a0f6f1582213dea781f..96536040fc3f4fb1d4d7652b222fb1a4155fd238 100644 (file)
@@ -35,10 +35,10 @@ class Symbol_table;
 class Allocate_commons_task : public Task
 {
  public:
-  Allocate_commons_task(Symbol_table* symtab, Layout* layout,
+  Allocate_commons_task(Symbol_table* symtab, Layout* layout, Mapfile* mapfile,
                        Task_token* symtab_lock, Task_token* blocker)
-    : symtab_(symtab), layout_(layout), symtab_lock_(symtab_lock),
-      blocker_(blocker)
+    : symtab_(symtab), layout_(layout), mapfile_(mapfile),
+      symtab_lock_(symtab_lock), blocker_(blocker)
   { }
 
   // The standard Task methods.
@@ -59,6 +59,7 @@ class Allocate_commons_task : public Task
  private:
   Symbol_table* symtab_;
   Layout* layout_;
+  Mapfile* mapfile_;
   Task_token* symtab_lock_;
   Task_token* blocker_;
 };
index 3df50c8c67de3d45a0452bac67b5d828b6ef066c..c6cd994f8d937a7bc99d09884f848b4c471582ca 100644 (file)
@@ -130,7 +130,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
 
   if (this->dynbss_ == NULL)
     {
-      this->dynbss_ = new Output_data_space(addralign);
+      this->dynbss_ = new Output_data_space(addralign, "** dynbss");
       layout->add_output_section_data(".bss",
                                      elfcpp::SHT_NOBITS,
                                      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
index 47e3e4c00cabbc78a08e89bac6e3d82b050ffb7a..4726ffc436d7465e7cae42b4426a234006afa38c 100644 (file)
@@ -67,6 +67,7 @@ class Eh_frame_hdr : public Output_section_data
       this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
   }
 
+ protected:
   // Set the final data size.
   void
   set_final_data_size();
@@ -75,6 +76,11 @@ class Eh_frame_hdr : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** eh_frame_hdr")); }
+
  private:
   // Write the data to the file with the right endianness.
   template<int size, bool big_endian>
@@ -322,6 +328,7 @@ class Eh_frame : public Output_section_data
   unsigned int
   fde_count() const;
 
+ protected:
   // Set the final data size.
   void
   set_final_data_size();
@@ -340,6 +347,11 @@ class Eh_frame : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** eh_frame")); }
+
  private:
   // The comparison routine for the CIE map.
   struct Cie_less
index 267c4d11682d380a7be6737b37acd16f00ca4b46..42c6248d4b2b875bf8cca0b34c33410edcdc81b9 100644 (file)
@@ -94,9 +94,9 @@ class Middle_runner : public Task_function_runner
   Middle_runner(const General_options& options,
                const Input_objects* input_objects,
                Symbol_table* symtab,
-               Layout* layout)
+               Layout* layout, Mapfile* mapfile)
     : options_(options), input_objects_(input_objects), symtab_(symtab),
-      layout_(layout)
+      layout_(layout), mapfile_(mapfile)
   { }
 
   void
@@ -107,13 +107,14 @@ class Middle_runner : public Task_function_runner
   const Input_objects* input_objects_;
   Symbol_table* symtab_;
   Layout* layout_;
+  Mapfile* mapfile_;
 };
 
 void
 Middle_runner::run(Workqueue* workqueue, const Task* task)
 {
   queue_middle_tasks(this->options_, task, this->input_objects_, this->symtab_,
-                    this->layout_, workqueue);
+                    this->layout_, workqueue, this->mapfile_);
 }
 
 // Queue up the initial set of tasks for this link job.
@@ -123,7 +124,7 @@ queue_initial_tasks(const General_options& options,
                    Dirsearch& search_path,
                    const Command_line& cmdline,
                    Workqueue* workqueue, Input_objects* input_objects,
-                   Symbol_table* symtab, Layout* layout)
+                   Symbol_table* symtab, Layout* layout, Mapfile* mapfile)
 {
   if (cmdline.begin() == cmdline.end())
     gold_fatal(_("no input files"));
@@ -145,15 +146,16 @@ queue_initial_tasks(const General_options& options,
       Task_token* next_blocker = new Task_token(true);
       next_blocker->add_blocker();
       workqueue->queue(new Read_symbols(options, input_objects, symtab, layout,
-                                       &search_path, &*p, NULL, this_blocker,
-                                       next_blocker));
+                                       &search_path, mapfile, &*p, NULL,
+                                       this_blocker, next_blocker));
       this_blocker = next_blocker;
     }
 
   workqueue->queue(new Task_function(new Middle_runner(options,
                                                       input_objects,
                                                       symtab,
-                                                      layout),
+                                                      layout,
+                                                      mapfile),
                                     this_blocker,
                                     "Task_function Middle_runner"));
 }
@@ -168,7 +170,8 @@ queue_middle_tasks(const General_options& options,
                   const Input_objects* input_objects,
                   Symbol_table* symtab,
                   Layout* layout,
-                  Workqueue* workqueue)
+                  Workqueue* workqueue,
+                  Mapfile* mapfile)
 {
   // We have to support the case of not seeing any input objects, and
   // generate an empty file.  Existing builds depend on being able to
@@ -272,8 +275,8 @@ queue_middle_tasks(const General_options& options,
   if (parameters->options().define_common())
     {
       blocker->add_blocker();
-      workqueue->queue(new Allocate_commons_task(symtab, layout, symtab_lock,
-                                                blocker));
+      workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile,
+                                                symtab_lock, blocker));
     }
 
   // When all those tasks are complete, we can start laying out the
@@ -284,7 +287,8 @@ queue_middle_tasks(const General_options& options,
                                                            input_objects,
                                                            symtab,
                                                             target,
-                                                           layout),
+                                                           layout,
+                                                           mapfile),
                                     blocker,
                                     "Task_function Layout_task_runner"));
 }
index 62c014ead88d4eedd2548955fa2ed574200dfc10..03e73d3c023704adf6dc2cd0fb9e684ef25c5b01 100644 (file)
@@ -115,6 +115,7 @@ class Command_line;
 class Input_argument_list;
 class Dirsearch;
 class Input_objects;
+class Mapfile;
 class Symbol;
 class Symbol_table;
 class Layout;
@@ -241,7 +242,8 @@ queue_initial_tasks(const General_options&,
                    Workqueue*,
                    Input_objects*,
                    Symbol_table*,
-                   Layout*);
+                   Layout*,
+                   Mapfile*);
 
 // Queue up the middle set of tasks.
 extern void
@@ -250,7 +252,8 @@ queue_middle_tasks(const General_options&,
                   const Input_objects*,
                   Symbol_table*,
                   Layout*,
-                  Workqueue*);
+                  Workqueue*,
+                  Mapfile*);
 
 // Queue up the final set of tasks.
 extern void
index 4785fa66c2142f324ef66928c69354a1f1190ddd..948b5d6598c6869dbdb3d7c98175c0c793be476f 100644 (file)
@@ -437,7 +437,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
       // create another set of data in the .got section.  Note that we
       // always create a PLT if we create a GOT, although the PLT
       // might be empty.
-      this->got_plt_ = new Output_data_space(4);
+      this->got_plt_ = new Output_data_space(4, "** GOT PLT");
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
@@ -496,6 +496,11 @@ class Output_data_plt_i386 : public Output_section_data
   void
   do_adjust_output_section(Output_section* os);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
+
  private:
   // The size of an entry in the PLT.
   static const int plt_entry_size = 16;
index eae66794eb5b3d5c11ba0f503aa9f4577c211f9d..a4003d557367e2e56edbe715b4bf7113a70f97ce 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "parameters.h"
 #include "options.h"
+#include "mapfile.h"
 #include "script.h"
 #include "script-sections.h"
 #include "output.h"
@@ -63,6 +64,13 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
 
   // Now we know the final size of the output file and we know where
   // each piece of information goes.
+
+  if (this->mapfile_ != NULL)
+    {
+      this->mapfile_->print_discarded_sections(this->input_objects_);
+      this->layout_->print_to_mapfile(this->mapfile_);
+    }
+
   Output_file* of = new Output_file(parameters->options().output_file_name());
   if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
     of->set_is_temporary();
@@ -1323,7 +1331,8 @@ Layout::create_note(const char* name, int note_type, size_t descsz,
                                                 elfcpp::SHT_NOTE,
                                                 flags);
   Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
-                                                          size / 8);
+                                                          size / 8,
+                                                          "** note header");
   os->add_output_section_data(posd);
 
   *trailing_padding = aligned_descsz - descsz;
@@ -1351,7 +1360,7 @@ Layout::create_gold_note()
 
   if (trailing_padding > 0)
     {
-      posd = new Output_data_fixed_space(trailing_padding, 0);
+      posd = new Output_data_zero_fill(trailing_padding, 0);
       os->add_output_section_data(posd);
     }
 }
@@ -1488,7 +1497,7 @@ Layout::create_build_id()
 
       if (trailing_padding != 0)
        {
-         posd = new Output_data_fixed_space(trailing_padding, 0);
+         posd = new Output_data_zero_fill(trailing_padding, 0);
          os->add_output_section_data(posd);
        }
     }
@@ -1497,7 +1506,7 @@ Layout::create_build_id()
       // We need to compute a checksum after we have completed the
       // link.
       gold_assert(trailing_padding == 0);
-      this->build_id_note_ = new Output_data_fixed_space(descsz, 4);
+      this->build_id_note_ = new Output_data_zero_fill(descsz, 4);
       os->add_output_section_data(this->build_id_note_);
       os->set_after_input_sections();
     }
@@ -2049,7 +2058,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
       this->symtab_section_ = osymtab;
 
       Output_section_data* pos = new Output_data_fixed_space(off - startoff,
-                                                            align);
+                                                            align,
+                                                            "** symtab");
       osymtab->add_output_section_data(pos);
 
       // We generate a .symtab_shndx section if we have more than
@@ -2230,7 +2240,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
                                                       false);
 
   Output_section_data* odata = new Output_data_fixed_space(index * symsize,
-                                                          align);
+                                                          align,
+                                                          "** dynsym");
   dynsym->add_output_section_data(odata);
 
   dynsym->set_info(local_symcount);
@@ -2309,7 +2320,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
-                                                                  align);
+                                                                  align,
+                                                                  "** hash");
       hashsec->add_output_section_data(hashdata);
 
       hashsec->set_link_section(dynsym);
@@ -2333,7 +2345,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
                                                                   hashlen,
-                                                                  align);
+                                                                  align,
+                                                                  "** hash");
       hashsec->add_output_section_data(hashdata);
 
       hashsec->set_link_section(dynsym);
@@ -2435,7 +2448,8 @@ Layout::sized_create_version_sections(
                                                      dynamic_symbols,
                                                      &vbuf, &vsize);
 
-  Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2);
+  Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
+                                                           "** versions");
 
   vsec->add_output_section_data(vdata);
   vsec->set_entsize(2);
@@ -2458,9 +2472,8 @@ Layout::sized_create_version_sections(
       versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
                                                       &vdsize, &vdentries);
 
-      Output_section_data* vddata = new Output_data_const_buffer(vdbuf,
-                                                                vdsize,
-                                                                4);
+      Output_section_data* vddata =
+       new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
 
       vdsec->add_output_section_data(vddata);
       vdsec->set_link_section(dynstr);
@@ -2485,9 +2498,8 @@ Layout::sized_create_version_sections(
                                                        &vnbuf, &vnsize,
                                                        &vnentries);
 
-      Output_section_data* vndata = new Output_data_const_buffer(vnbuf,
-                                                                vnsize,
-                                                                4);
+      Output_section_data* vndata =
+       new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs");
 
       vnsec->add_output_section_data(vndata);
       vnsec->set_link_section(dynstr);
@@ -3086,6 +3098,17 @@ Layout::write_binary(Output_file* in) const
   out.close();
 }
 
+// Print the output sections to the map file.
+
+void
+Layout::print_to_mapfile(Mapfile* mapfile) const
+{
+  for (Segment_list::const_iterator p = this->segment_list_.begin();
+       p != this->segment_list_.end();
+       ++p)
+    (*p)->print_sections_to_mapfile(mapfile);
+}
+
 // Print statistical information to stderr.  This is used for --stats.
 
 void
index ede2604cb9c253a3680d65eaf7a1951a2bad192e..1c71d477078b1f1d315374f6f1ab5237bc684f92 100644 (file)
@@ -40,6 +40,7 @@ namespace gold
 
 class General_options;
 class Input_objects;
+class Mapfile;
 class Symbol_table;
 class Output_section_data;
 class Output_section;
@@ -64,9 +65,10 @@ class Layout_task_runner : public Task_function_runner
                     const Input_objects* input_objects,
                     Symbol_table* symtab,
                      Target* target,
-                    Layout* layout)
+                    Layout* layout,
+                    Mapfile* mapfile)
     : options_(options), input_objects_(input_objects), symtab_(symtab),
-      target_(target), layout_(layout)
+      target_(target), layout_(layout), mapfile_(mapfile)
   { }
 
   // Run the operation.
@@ -82,6 +84,7 @@ class Layout_task_runner : public Task_function_runner
   Symbol_table* symtab_;
   Target* target_;
   Layout* layout_;
+  Mapfile* mapfile_;
 };
 
 // This class handles the details of laying out input sections.
@@ -334,6 +337,10 @@ class Layout
   void
   write_binary(Output_file* in) const;
 
+  // Print output sections to the map file.
+  void
+  print_to_mapfile(Mapfile*) const;
+
   // Dump statistical information to stderr.
   void
   print_stats() const;
index c785da231eea51e376004df23c591d0f6f47b0fa..35772839e4fe9e5a3e820d6cf2610c57dd354b67 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "gold.h"
 
+#include <cstdio>
 #include <cstring>
 
 #ifdef HAVE_MALLINFO
@@ -34,6 +35,7 @@
 #include "options.h"
 #include "parameters.h"
 #include "errors.h"
+#include "mapfile.h"
 #include "dirsearch.h"
 #include "workqueue.h"
 #include "object.h"
@@ -165,6 +167,18 @@ main(int argc, char** argv)
   write_debug_script(command_line.options().output_file_name(),
                      program_name, args.c_str());
 
+  // If the user asked for a map file, open it.
+  Mapfile* mapfile = NULL;
+  if (command_line.options().user_set_Map())
+    {
+      mapfile = new Mapfile();
+      if (!mapfile->open(command_line.options().Map()))
+       {
+         delete mapfile;
+         mapfile = NULL;
+       }
+    }
+
   // The GNU linker ignores version scripts when generating
   // relocatable output.  If we are not compatible, then we break the
   // Linux kernel build, which uses a linker script with -r which must
@@ -198,7 +212,7 @@ main(int argc, char** argv)
   // Queue up the first set of tasks.
   queue_initial_tasks(command_line.options(), search_path,
                      command_line, &workqueue, &input_objects,
-                     &symtab, &layout);
+                     &symtab, &layout, mapfile);
 
   // Run the main task processing loop.
   workqueue.process(0);
@@ -220,6 +234,9 @@ main(int argc, char** argv)
       layout.print_stats();
     }
 
+  if (mapfile != NULL)
+    mapfile->close();
+
   if (parameters->options().fatal_warnings()
       && errors.warning_count() > 0
       && errors.error_count() == 0)
diff --git a/gold/mapfile.cc b/gold/mapfile.cc
new file mode 100644 (file)
index 0000000..e053419
--- /dev/null
@@ -0,0 +1,405 @@
+// mapfile.cc -- map file generation for gold
+
+// Copyright 2008 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include "gold.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+
+#include "archive.h"
+#include "symtab.h"
+#include "output.h"
+#include "mapfile.h"
+
+// This file holds the code for printing information to the map file.
+// In general we try to produce pretty much the same format as GNU ld.
+
+namespace gold
+{
+
+// Mapfile constructor.
+
+Mapfile::Mapfile()
+  : map_file_(NULL),
+    printed_archive_header_(false),
+    printed_common_header_(false),
+    printed_memory_map_header_(false)
+{
+}
+
+// Mapfile destructor.
+
+Mapfile::~Mapfile()
+{
+  if (this->map_file_ != NULL)
+    this->close();
+}
+
+// Open the map file.
+
+bool
+Mapfile::open(const char* map_filename)
+{
+  if (strcmp(map_filename, "-") == 0)
+    this->map_file_ = stdout;
+  else
+    {
+      this->map_file_ = ::fopen(map_filename, "w");
+      if (this->map_file_ == NULL)
+       {
+         gold_error(_("cannot open map file %s: %s"), map_filename,
+                    strerror(errno));
+         return false;
+       }
+    }
+  return true;
+}
+
+// Close the map file.
+
+void
+Mapfile::close()
+{
+  if (fclose(this->map_file_) != 0)
+    gold_error(_("cannot close map file: %s"), strerror(errno));
+  this->map_file_ = NULL;
+}
+
+// Advance to a column.
+
+void
+Mapfile::advance_to_column(size_t from, size_t to)
+{
+  if (from >= to - 1)
+    {
+      putc('\n', this->map_file_);
+      from = 0;
+    }
+  while (from < to)
+    {
+      putc(' ', this->map_file_);
+      ++from;
+    }
+}
+
+// Report about including a member from an archive.
+
+void
+Mapfile::report_include_archive_member(const Archive* archive,
+                                      const std::string& member_name,
+                                      const Symbol* sym, const char* why)
+{
+  // We print a header before the list of archive members, mainly for
+  // GNU ld compatibility.
+  if (!this->printed_archive_header_)
+    {
+      fprintf(this->map_file_,
+             _("Archive member included because of file (symbol)\n\n"));
+      this->printed_archive_header_ = true;
+    }
+
+  fprintf(this->map_file_, "%s(%s)", archive->file().filename().c_str(),
+         member_name.c_str());
+
+  size_t len = (archive->file().filename().length()
+               + member_name.length()
+               + 2);
+  this->advance_to_column(len, 30);
+
+  if (sym == NULL)
+    fprintf(this->map_file_, "%s", why);
+  else
+    {
+      switch (sym->source())
+       {
+       case Symbol::FROM_OBJECT:
+         fprintf(this->map_file_, "%s", sym->object()->name().c_str());
+         break;
+
+       case Symbol::IS_UNDEFINED:
+         fprintf(this->map_file_, "-u");
+         break;
+
+       default:
+       case Symbol::IN_OUTPUT_DATA:
+       case Symbol::IN_OUTPUT_SEGMENT:
+       case Symbol::IS_CONSTANT:
+         // We should only see an undefined symbol here.
+         gold_unreachable();
+       }
+
+      fprintf(this->map_file_, " (%s)", sym->name());
+    }
+
+  putc('\n', this->map_file_);
+}
+
+// Report allocating a common symbol.
+
+void
+Mapfile::report_allocate_common(const Symbol* sym, uint64_t symsize)
+{
+  if (!this->printed_common_header_)
+    {
+      fprintf(this->map_file_, _("\nAllocating common symbols\n"));
+      fprintf(this->map_file_,
+             _("Common symbol       size              file\n\n"));
+      this->printed_common_header_ = true;
+    }
+
+  std::string demangled_name = sym->demangled_name();
+  fprintf(this->map_file_, "%s", demangled_name.c_str());
+
+  this->advance_to_column(demangled_name.length(), 20);
+
+  char buf[50];
+  snprintf(buf, sizeof buf, "0x%llx", static_cast<unsigned long long>(symsize));
+  fprintf(this->map_file_, "%s", buf);
+
+  size_t len = strlen(buf);
+  while (len < 18)
+    {
+      putc(' ', this->map_file_);
+      ++len;
+    }
+
+  fprintf(this->map_file_, "%s\n", sym->object()->name().c_str());
+}
+
+// The space we make for a section name.
+
+const size_t Mapfile::section_name_map_length = 16;
+
+// Print the memory map header if necessary.
+
+void
+Mapfile::print_memory_map_header()
+{
+  if (!this->printed_memory_map_header_)
+    {
+      fprintf(this->map_file_, _("\nMemory map\n\n"));
+      this->printed_memory_map_header_ = true;
+    }
+}
+
+// Print the symbols associated with an input section.
+
+template<int size, bool big_endian>
+void
+Mapfile::print_input_section_symbols(
+    const Sized_relobj<size, big_endian>* relobj,
+    unsigned int shndx)
+{
+  unsigned int symcount = relobj->symbol_count();
+  for (unsigned int i = relobj->local_symbol_count(); i < symcount; ++i)
+    {
+      const Symbol* sym = relobj->global_symbol(i);
+      bool is_ordinary;
+      if (sym != NULL
+         && sym->source() == Symbol::FROM_OBJECT
+         && sym->object() == relobj
+         && sym->shndx(&is_ordinary) == shndx
+         && is_ordinary
+         && sym->is_defined())
+       {
+         for (size_t i = 0; i < Mapfile::section_name_map_length; ++i)
+           putc(' ', this->map_file_);
+         const Sized_symbol<size>* ssym =
+           static_cast<const Sized_symbol<size>*>(sym);
+         fprintf(this->map_file_,
+                 "0x%0*llx                %s\n",
+                 size / 4,
+                 static_cast<unsigned long long>(ssym->value()),
+                 sym->demangled_name().c_str());
+       }
+    }
+}
+
+// Print an input section.
+
+void
+Mapfile::print_input_section(Relobj* relobj, unsigned int shndx)
+{
+  putc(' ', this->map_file_);
+
+  std::string name = relobj->section_name(shndx);
+  fprintf(this->map_file_, "%s", name.c_str());
+
+  this->advance_to_column(name.length() + 1, Mapfile::section_name_map_length);
+
+  Output_section* os;
+  uint64_t addr;
+  if (!relobj->is_section_included(shndx))
+    {
+      os = NULL;
+      addr = 0;
+    }
+  else
+    {
+      section_offset_type offset;
+      os = relobj->output_section(shndx, &offset);
+      if (offset == -1)
+       addr = ~0ULL;
+      else
+       addr = os->address() + offset;
+    }
+
+  char sizebuf[50];
+  snprintf(sizebuf, sizeof sizebuf, "0x%llx",
+          static_cast<unsigned long long>(relobj->section_size(shndx)));
+
+  fprintf(this->map_file_, "0x%0*llx %10s %s\n",
+         parameters->target().get_size() / 4,
+         static_cast<unsigned long long>(addr), sizebuf,
+         relobj->name().c_str());
+
+  if (os != NULL)
+    {
+      switch (parameters->size_and_endianness())
+       {
+#ifdef HAVE_TARGET_32_LITTLE
+       case Parameters::TARGET_32_LITTLE:
+         {
+           const Sized_relobj<32, false>* sized_relobj =
+             static_cast<Sized_relobj<32, false>*>(relobj);
+           this->print_input_section_symbols(sized_relobj, shndx);
+         }
+         break;
+#endif
+#ifdef HAVE_TARGET_32_BIG
+       case Parameters::TARGET_32_BIG:
+         {
+           const Sized_relobj<32, true>* sized_relobj =
+             static_cast<Sized_relobj<32, true>*>(relobj);
+           this->print_input_section_symbols(sized_relobj, shndx);
+         }
+         break;
+#endif
+#ifdef HAVE_TARGET_64_LITTLE
+       case Parameters::TARGET_64_LITTLE:
+         {
+           const Sized_relobj<64, false>* sized_relobj =
+             static_cast<Sized_relobj<64, false>*>(relobj);
+           this->print_input_section_symbols(sized_relobj, shndx);
+         }
+         break;
+#endif
+#ifdef HAVE_TARGET_64_BIG
+       case Parameters::TARGET_64_BIG:
+         {
+           const Sized_relobj<64, true>* sized_relobj =
+             static_cast<Sized_relobj<64, true>*>(relobj);
+           this->print_input_section_symbols(sized_relobj, shndx);
+         }
+         break;
+#endif
+       default:
+         gold_unreachable();
+       }
+    }
+}
+
+// Print an Output_section_data.  This is printed to look like an
+// input section.
+
+void
+Mapfile::print_output_data(const Output_data* od, const char* name)
+{
+  this->print_memory_map_header();
+
+  putc(' ', this->map_file_);
+
+  fprintf(this->map_file_, "%s", name);
+
+  this->advance_to_column(strlen(name) + 1, Mapfile::section_name_map_length);
+
+  char sizebuf[50];
+  snprintf(sizebuf, sizeof sizebuf, "0x%llx",
+          static_cast<unsigned long long>(od->data_size()));
+
+  fprintf(this->map_file_, "0x%0*llx %10s\n",
+         parameters->target().get_size() / 4,
+         static_cast<unsigned long long>(od->address()),
+         sizebuf);
+}
+
+// Print the discarded input sections.
+
+void
+Mapfile::print_discarded_sections(const Input_objects* input_objects)
+{
+  bool printed_header = false;
+  for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
+       p != input_objects->relobj_end();
+       ++p)
+    {
+      Relobj* relobj = *p;
+      unsigned int shnum = relobj->shnum();
+      for (unsigned int i = 0; i < shnum; ++i)
+       {
+         unsigned int sh_type = relobj->section_type(i);
+         if ((sh_type == elfcpp::SHT_PROGBITS
+              || sh_type == elfcpp::SHT_NOBITS
+              || sh_type == elfcpp::SHT_GROUP)
+             && !relobj->is_section_included(i))
+           {
+             if (!printed_header)
+               {
+                 fprintf(this->map_file_, _("\nDiscarded input sections\n\n"));
+                 printed_header = true;
+               }
+
+             this->print_input_section(relobj, i);
+           }
+       }
+    }
+}
+
+// Print an output section.
+
+void
+Mapfile::print_output_section(const Output_section* os)
+{
+  this->print_memory_map_header();
+
+  fprintf(this->map_file_, "\n%s", os->name());
+
+  this->advance_to_column(strlen(os->name()), Mapfile::section_name_map_length);
+
+  char sizebuf[50];
+  snprintf(sizebuf, sizeof sizebuf, "0x%llx",
+          static_cast<unsigned long long>(os->data_size()));
+
+  fprintf(this->map_file_, "0x%0*llx %10s",
+         parameters->target().get_size() / 4,
+         static_cast<unsigned long long>(os->address()), sizebuf);
+
+  if (os->has_load_address())
+    fprintf(this->map_file_, " load address 0x%-*llx",
+           parameters->target().get_size() / 4,
+           static_cast<unsigned long long>(os->load_address()));
+
+  putc('\n', this->map_file_);
+}
+
+} // End namespace gold.
diff --git a/gold/mapfile.h b/gold/mapfile.h
new file mode 100644 (file)
index 0000000..e2cf085
--- /dev/null
@@ -0,0 +1,113 @@
+// mapfile.h -- map file generation for gold   -*- C++ -*-
+
+// Copyright 2008 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#ifndef GOLD_MAP_H
+#define GOLD_MAP_H
+
+#include <cstdio>
+#include <string>
+
+namespace gold
+{
+
+class Archive;
+class Symbol;
+class Relobj;
+template<int size, bool big_endian>
+class Sized_relobj;
+class Output_section;
+class Output_data;
+
+// This class manages map file output.
+
+class Mapfile
+{
+ public:
+  Mapfile();
+
+  ~Mapfile();
+
+  // Open the map file.  Return whether the open succeed.
+  bool
+  open(const char* map_filename);
+
+  // Close the map file.
+  void
+  close();
+
+  // Report that we are including a member from an archive.  This is
+  // called by the archive reading code.
+  void
+  report_include_archive_member(const Archive*, const std::string& member_name,
+                               const Symbol* sym, const char* why);
+
+  // Report allocating a common symbol.
+  void
+  report_allocate_common(const Symbol*, uint64_t symsize);
+
+  // Print discarded input sections.
+  void
+  print_discarded_sections(const Input_objects*);
+
+  // Print an output section.
+  void
+  print_output_section(const Output_section*);
+
+  // Print an input section.
+  void
+  print_input_section(Relobj*, unsigned int shndx);
+
+  // Print an Output_data.
+  void
+  print_output_data(const Output_data*, const char* name);
+
+ private:
+  // The space we allow for a section name.
+  static const size_t section_name_map_length;
+
+  // Advance to a column.
+  void
+  advance_to_column(size_t from, size_t to);
+
+  // Print the memory map header.
+  void
+  print_memory_map_header();
+
+  // Print symbols for an input section.
+  template<int size, bool big_endian>
+  void
+  print_input_section_symbols(const Sized_relobj<size, big_endian>*,
+                             unsigned int shndx);
+
+  // Map file to write to.
+  FILE* map_file_;
+  // Whether we have printed the archive member header.
+  bool printed_archive_header_;
+  // Whether we have printed the allocated common header.
+  bool printed_common_header_;
+  // Whether we have printed the memory map header.
+  bool printed_memory_map_header_;
+};
+
+} // End namespace gold.
+
+#endif // !defined(GOLD_MAP_H)
index cbc8bece427b3487b12ce7d1f02d2242a57ce1d5..2aeff1e6fa18cfeec4db6395840cd16c4e93b3f2 100644 (file)
@@ -283,6 +283,11 @@ class Output_merge_data : public Output_merge_base
   void
   do_write_to_buffer(unsigned char*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** merge constants")); }
+
   // Print merge stats to stderr.
   void
   do_print_merge_stats(const char* section_name);
@@ -400,6 +405,11 @@ class Output_merge_string : public Output_merge_base
   void
   do_write_to_buffer(unsigned char*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** merge strings")); }
+
   // Print merge stats to stderr.
   void
   do_print_merge_stats(const char* section_name);
index 52359afa367d07112231d19019fb26bf8be1fbd2..4a01843bd9da98cf9dba94ca03a7d546003006da 100644 (file)
@@ -1239,6 +1239,12 @@ class Sized_relobj : public Relobj
   void
   setup(const typename elfcpp::Ehdr<size, big_endian>&);
 
+  // Return the number of symbols.  This is only valid after
+  // Object::add_symbols has been called.
+  unsigned int
+  symbol_count() const
+  { return this->local_symbol_count_ + this->symbols_.size(); }
+
   // If SYM is the index of a global symbol in the object file's
   // symbol table, return the Symbol object.  Otherwise, return NULL.
   Symbol*
index 8d18c11fbc2f758445263c7a84b1ce7220877f90..da30a6da22364fb7fd243457c95b9f69c5e84c0c 100644 (file)
@@ -697,6 +697,13 @@ General_options::finalize()
       this->set_do_demangle(getenv("COLLECT_NO_DEMANGLE") == NULL);
     }
 
+  // -M is equivalent to "-Map -".
+  if (this->print_map() && !this->user_set_Map())
+    {
+      this->set_Map("-");
+      this->set_user_set_Map();
+    }
+
   // If --thread_count is specified, it applies to
   // --thread-count-{initial,middle,final}, though it doesn't override
   // them.
index 9a474df5c4e8e847559bf5ef4a709ed12a0fd3b8..e34e165ba76d2fd682d2681ec9f62a2d10d38273 100644 (file)
@@ -654,6 +654,11 @@ class General_options
   DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
                 N_("Ignored for compatibility"), N_("EMULATION"));
 
+  DEFINE_bool(print_map, options::TWO_DASHES, 'M', false,
+             N_("Write map file on standard output"), NULL);
+  DEFINE_string(Map, options::ONE_DASH, '\0', NULL, N_("Write map file"),
+               N_("MAPFILENAME"));
+
   DEFINE_enable(new_dtags, options::EXACTLY_TWO_DASHES, '\0', false,
                N_("Enable use of DT_RUNPATH and DT_FLAGS"),
                N_("Disable use of DT_RUNPATH and DT_FLAGS"));
index b5791f4db64d8bb234550e2816836c6347f3941d..a3dab399ad56c4ddca15dabe9f801074adfb4ac8 100644 (file)
@@ -1701,6 +1701,25 @@ Output_section::Input_section::write_to_buffer(unsigned char* buffer)
     this->u2_.posd->write_to_buffer(buffer);
 }
 
+// Print to a map file.
+
+void
+Output_section::Input_section::print_to_mapfile(Mapfile* mapfile) const
+{
+  switch (this->shndx_)
+    {
+    case OUTPUT_SECTION_CODE:
+    case MERGE_DATA_SECTION_CODE:
+    case MERGE_STRING_SECTION_CODE:
+      this->u2_.posd->print_to_mapfile(mapfile);
+      break;
+
+    default:
+      mapfile->print_input_section(this->u2_.object, this->shndx_);
+      break;
+    }
+}
+
 // Output_section methods.
 
 // Construct an Output_section.  NAME will point into a Stringpool.
@@ -1859,7 +1878,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
   if (have_sections_script
       || !this->input_sections_.empty()
       || this->may_sort_attached_input_sections()
-      || this->must_sort_attached_input_sections())
+      || this->must_sort_attached_input_sections()
+      || parameters->options().user_set_Map())
     this->input_sections_.push_back(Input_section(object, shndx,
                                                  shdr.get_sh_size(),
                                                  addralign));
@@ -2546,6 +2566,19 @@ Output_section::add_input_section_for_script(Relobj* object,
                                                data_size, addralign));
 }
 
+// Print to the map file.
+
+void
+Output_section::do_print_to_mapfile(Mapfile* mapfile) const
+{
+  mapfile->print_output_section(this);
+
+  for (Input_section_list::const_iterator p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    p->print_to_mapfile(mapfile);
+}
+
 // Print stats for merge sections to stderr.
 
 void
@@ -3236,6 +3269,29 @@ Output_segment::write_section_headers_list(const Layout* layout,
   return v;
 }
 
+// Print the output sections to the map file.
+
+void
+Output_segment::print_sections_to_mapfile(Mapfile* mapfile) const
+{
+  if (this->type() != elfcpp::PT_LOAD)
+    return;
+  this->print_section_list_to_mapfile(mapfile, &this->output_data_);
+  this->print_section_list_to_mapfile(mapfile, &this->output_bss_);
+}
+
+// Print an output section list to the map file.
+
+void
+Output_segment::print_section_list_to_mapfile(Mapfile* mapfile,
+                                             const Output_data_list* pdl) const
+{
+  for (Output_data_list::const_iterator p = pdl->begin();
+       p != pdl->end();
+       ++p)
+    (*p)->print_to_mapfile(mapfile);
+}
+
 // Output_file methods.
 
 Output_file::Output_file(const char* name)
index a8f2f39017d9f7deb0bb3ed637d29dfc9438b25d..dceaceb7949eb74e3a9eedbdf91f5923de556486 100644 (file)
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include "elfcpp.h"
+#include "mapfile.h"
 #include "layout.h"
 #include "reloc-types.h"
 
@@ -240,6 +241,11 @@ class Output_data
   is_data_size_valid() const
   { return this->is_data_size_valid_; }
 
+  // Print information to the map file.
+  void
+  print_to_mapfile(Mapfile* mapfile) const
+  { return this->do_print_to_mapfile(mapfile); }
+
  protected:
   // Functions that child classes may or in some cases must implement.
 
@@ -316,6 +322,12 @@ class Output_data
   do_tls_offset() const
   { gold_unreachable(); }
 
+  // Print to the map file.  This only needs to be implemented by
+  // classes which may appear in a PT_LOAD segment.
+  virtual void
+  do_print_to_mapfile(Mapfile*) const
+  { gold_unreachable(); }
+
   // Functions that child classes may call.
 
   // Set the size of the data.
@@ -397,6 +409,11 @@ class Output_section_headers : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** section headers")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -428,6 +445,11 @@ class Output_segment_headers : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** segment headers")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -462,6 +484,11 @@ class Output_file_header : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** file header")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -663,6 +690,11 @@ class Output_data_const : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { memcpy(buffer, this->data_.data(), this->data_.size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** fill")); }
+
  private:
   std::string data_;
 };
@@ -674,8 +706,9 @@ class Output_data_const_buffer : public Output_section_data
 {
  public:
   Output_data_const_buffer(const unsigned char* p, off_t len,
-                          uint64_t addralign)
-    : Output_section_data(len, addralign), p_(p)
+                          uint64_t addralign, const char* map_name)
+    : Output_section_data(len, addralign),
+      p_(p), map_name_(map_name)
   { }
 
  protected:
@@ -688,8 +721,17 @@ class Output_data_const_buffer : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { memcpy(buffer, this->p_, this->data_size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
  private:
+  // The data to output.
   const unsigned char* p_;
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
 };
 
 // A place holder for a fixed amount of data written out via some
@@ -698,8 +740,10 @@ class Output_data_const_buffer : public Output_section_data
 class Output_data_fixed_space : public Output_section_data
 {
  public:
-  Output_data_fixed_space(off_t data_size, uint64_t addralign)
-    : Output_section_data(data_size, addralign)
+  Output_data_fixed_space(off_t data_size, uint64_t addralign,
+                         const char* map_name)
+    : Output_section_data(data_size, addralign),
+      map_name_(map_name)
   { }
 
  protected:
@@ -708,6 +752,16 @@ class Output_data_fixed_space : public Output_section_data
   void
   do_write(Output_file*)
   { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
+ private:
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
 };
 
 // A place holder for variable sized data written out via some other
@@ -716,8 +770,9 @@ class Output_data_fixed_space : public Output_section_data
 class Output_data_space : public Output_section_data_build
 {
  public:
-  explicit Output_data_space(uint64_t addralign)
-    : Output_section_data_build(addralign)
+  explicit Output_data_space(uint64_t addralign, const char* map_name)
+    : Output_section_data_build(addralign),
+      map_name_(map_name)
   { }
 
   // Set the alignment.
@@ -731,6 +786,38 @@ class Output_data_space : public Output_section_data_build
   void
   do_write(Output_file*)
   { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
+ private:
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
+};
+
+// Fill fixed space with zeroes.  This is just like
+// Output_data_fixed_space, except that the map name is known.
+
+class Output_data_zero_fill : public Output_section_data
+{
+ public:
+  Output_data_zero_fill(off_t data_size, uint64_t addralign)
+    : Output_section_data(data_size, addralign)
+  { }
+
+ protected:
+  // There is no data to write out.
+  void
+  do_write(Output_file*)
+  { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, "** zero fill"); }
 };
 
 // A string table which goes into an output section.
@@ -757,6 +844,11 @@ class Output_data_strtab : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { this->strtab_->write_to_buffer(buffer, this->data_size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** string table")); }
+
  private:
   Stringpool* strtab_;
 };
@@ -1056,6 +1148,16 @@ class Output_data_reloc_base : public Output_section_data_build
   void
   do_adjust_output_section(Output_section *os);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  {
+    mapfile->print_output_data(this,
+                              (dynamic
+                               ? _("** dynamic relocs")
+                               : _("** relocs")));
+  }
+
   // Add a relocation entry.
   void
   add(Output_data *od, const Output_reloc_type& reloc)
@@ -1380,6 +1482,11 @@ class Output_relocatable_relocs : public Output_section_data
   do_write(Output_file*)
   { }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** relocs")); }
+
  private:
   // The relocs associated with this input section.
   Relocatable_relocs* rr_;
@@ -1400,6 +1507,11 @@ class Output_data_group : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** group")); }
+
  private:
   // The input object.
   Sized_relobj<size, big_endian>* relobj_;
@@ -1502,6 +1614,11 @@ class Output_data_got : public Output_section_data_build
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** GOT")); }
+
  private:
   // This POD class holds a single GOT entry.
   class Got_entry
@@ -1639,6 +1756,11 @@ class Output_data_dynamic : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** dynamic")); }
+
  private:
   // This POD class holds a single dynamic entry.
   class Dynamic_entry
@@ -1752,6 +1874,11 @@ class Output_symtab_xindex : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** symtab xindex")); }
+
  private:
   template<bool big_endian>
   void
@@ -2262,6 +2389,10 @@ class Output_section : public Output_data
   do_finalize_name(Layout*)
   { }
 
+  // Print to the map file.
+  virtual void
+  do_print_to_mapfile(Mapfile*) const;
+
   // Record that this section requires postprocessing after all
   // relocations have been applied.  This is called by a child class.
   void
@@ -2439,6 +2570,10 @@ class Output_section : public Output_data
     void
     write_to_buffer(unsigned char*);
 
+    // Print to a map file.
+    void
+    print_to_mapfile(Mapfile*) const;
+
     // Print statistics about merge sections to stderr.
     void
     print_merge_stats(const char* section_name)
@@ -2802,6 +2937,10 @@ class Output_segment
   write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
                        unsigned int* pshndx) const;
 
+  // Print the output sections in the map file.
+  void
+  print_sections_to_mapfile(Mapfile*) const;
+
  private:
   Output_segment(const Output_segment&);
   Output_segment& operator=(const Output_segment&);
@@ -2844,6 +2983,10 @@ class Output_segment
                             const Output_data_list*, unsigned char* v,
                             unsigned int* pshdx) const;
 
+  // Print a section list to the mapfile.
+  void
+  print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const;
+
   // The list of output data with contents attached to this segment.
   Output_data_list output_data_;
   // The list of output data without contents attached to this segment.
index 18b91b42b79ed52b2b681e52100d18c6073be619..bfb850a8e4a82d8454262571a0c5a99d982da7d7 100644 (file)
@@ -220,6 +220,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
          workqueue->queue_next(new Add_archive_symbols(this->symtab_,
                                                        this->layout_,
                                                        this->input_objects_,
+                                                       this->mapfile_,
                                                        arch,
                                                        this->input_group_,
                                                        this->this_blocker_,
@@ -239,6 +240,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
                                        this->layout_,
                                        this->dirpath_,
                                        this->input_objects_,
+                                       this->mapfile_,
                                        this->input_group_,
                                        this->input_argument_,
                                        input_file,
@@ -274,7 +276,8 @@ Read_symbols::do_group(Workqueue* workqueue)
       workqueue->queue_soon(new Read_symbols(this->options_,
                                             this->input_objects_,
                                             this->symtab_, this->layout_,
-                                            this->dirpath_, arg, input_group,
+                                            this->dirpath_, this->mapfile_,
+                                            arg, input_group,
                                             this_blocker, next_blocker));
       this_blocker = next_blocker;
     }
@@ -283,6 +286,7 @@ Read_symbols::do_group(Workqueue* workqueue)
   workqueue->queue_soon(new Finish_group(this->input_objects_,
                                         this->symtab_,
                                         this->layout_,
+                                        this->mapfile_,
                                         input_group,
                                         saw_undefined,
                                         this_blocker,
@@ -411,7 +415,7 @@ Finish_group::run(Workqueue*)
          Task_lock_obj<Archive> tl(this, *p);
 
          (*p)->add_symbols(this->symtab_, this->layout_,
-                           this->input_objects_);
+                           this->input_objects_, this->mapfile_);
        }
     }
 
@@ -459,9 +463,9 @@ Read_script::run(Workqueue* workqueue)
   bool used_next_blocker;
   if (!read_input_script(workqueue, this->options_, this->symtab_,
                         this->layout_, this->dirpath_, this->input_objects_,
-                        this->input_group_, this->input_argument_,
-                        this->input_file_, this->next_blocker_,
-                        &used_next_blocker))
+                        this->mapfile_, this->input_group_,
+                        this->input_argument_, this->input_file_,
+                        this->next_blocker_, &used_next_blocker))
     {
       // Here we have to handle any other input file types we need.
       gold_error(_("%s: not an object or archive"),
index 0ad89f8fc35eb8d0021c8cc391afdeb488185161..f93d6dbc99cd34c08fe082ab47737dd20c21a660 100644 (file)
@@ -56,12 +56,13 @@ class Read_symbols : public Task
   // symbols.
   Read_symbols(const General_options& options, Input_objects* input_objects,
               Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
-              const Input_argument* input_argument, Input_group* input_group,
-              Task_token* this_blocker, Task_token* next_blocker)
+              Mapfile* mapfile, const Input_argument* input_argument,
+              Input_group* input_group, Task_token* this_blocker,
+              Task_token* next_blocker)
     : options_(options), input_objects_(input_objects), symtab_(symtab),
-      layout_(layout), dirpath_(dirpath), input_argument_(input_argument),
-      input_group_(input_group), this_blocker_(this_blocker),
-      next_blocker_(next_blocker)
+      layout_(layout), dirpath_(dirpath), mapfile_(mapfile),
+      input_argument_(input_argument), input_group_(input_group),
+      this_blocker_(this_blocker), next_blocker_(next_blocker)
   { }
 
   ~Read_symbols();
@@ -94,6 +95,7 @@ class Read_symbols : public Task
   Symbol_table* symtab_;
   Layout* layout_;
   Dirsearch* dirpath_;
+  Mapfile* mapfile_;
   const Input_argument* input_argument_;
   Input_group* input_group_;
   Task_token* this_blocker_;
@@ -184,11 +186,11 @@ class Finish_group : public Task
 {
  public:
   Finish_group(Input_objects* input_objects, Symbol_table* symtab,
-              Layout* layout, Input_group* input_group,
+              Layout* layout, Mapfile* mapfile, Input_group* input_group,
               int saw_undefined, Task_token* this_blocker,
               Task_token* next_blocker)
     : input_objects_(input_objects), symtab_(symtab),
-      layout_(layout), input_group_(input_group),
+      layout_(layout), mapfile_(mapfile), input_group_(input_group),
       saw_undefined_(saw_undefined), this_blocker_(this_blocker),
       next_blocker_(next_blocker)
   { }
@@ -214,6 +216,7 @@ class Finish_group : public Task
   Input_objects* input_objects_;
   Symbol_table* symtab_;
   Layout* layout_;
+  Mapfile* mapfile_;
   Input_group* input_group_;
   int saw_undefined_;
   Task_token* this_blocker_;
@@ -229,13 +232,15 @@ class Read_script : public Task
  public:
   Read_script(const General_options& options, Symbol_table* symtab,
              Layout* layout, Dirsearch* dirpath, Input_objects* input_objects,
-             Input_group* input_group, const Input_argument* input_argument,
+             Mapfile* mapfile, Input_group* input_group,
+             const Input_argument* input_argument,
              Input_file* input_file, Task_token* this_blocker,
              Task_token* next_blocker)
     : options_(options), symtab_(symtab), layout_(layout), dirpath_(dirpath),
-      input_objects_(input_objects), input_group_(input_group),
-      input_argument_(input_argument), input_file_(input_file),
-      this_blocker_(this_blocker), next_blocker_(next_blocker)
+      input_objects_(input_objects), mapfile_(mapfile),
+      input_group_(input_group), input_argument_(input_argument),
+      input_file_(input_file), this_blocker_(this_blocker),
+      next_blocker_(next_blocker)
   { }
 
   ~Read_script();
@@ -260,6 +265,7 @@ class Read_script : public Task
   Layout* layout_;
   Dirsearch* dirpath_;
   Input_objects* input_objects_;
+  Mapfile* mapfile_;
   Input_group* input_group_;
   const Input_argument* input_argument_;
   Input_file* input_file_;
index 55db831ae7e647efd8a34e126e5a7112ae3b96cb..7f3a4daa9cd57a087c1d76506675ce5a501fb325 100644 (file)
@@ -426,7 +426,7 @@ Output_section_element_dot_assignment::set_section_addresses(
                                                              - *dot_value);
       Output_section_data* posd;
       if (fill->empty())
-       posd = new Output_data_fixed_space(length, 0);
+       posd = new Output_data_zero_fill(length, 0);
       else
        {
          std::string this_fill = this->get_fill_string(fill, length);
@@ -482,6 +482,11 @@ class Output_data_expression : public Output_section_data
   void
   do_write_to_buffer(unsigned char*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** expression")); }
+
  private:
   template<bool big_endian>
   void
index a808b2e31d1c4d734d89a70e77c8b67d1077628b..4b2c3379f2b288955a136cdc2266ef2c7164830b 100644 (file)
@@ -1313,7 +1313,7 @@ bool
 read_input_script(Workqueue* workqueue, const General_options& options,
                  Symbol_table* symtab, Layout* layout,
                  Dirsearch* dirsearch, Input_objects* input_objects,
-                 Input_group* input_group,
+                 Mapfile* mapfile, Input_group* input_group,
                  const Input_argument* input_argument,
                  Input_file* input_file, Task_token* next_blocker,
                  bool* used_next_blocker)
@@ -1353,7 +1353,7 @@ read_input_script(Workqueue* workqueue, const General_options& options,
          nb->add_blocker();
        }
       workqueue->queue_soon(new Read_symbols(options, input_objects, symtab,
-                                            layout, dirsearch, &*p,
+                                            layout, dirsearch, mapfile, &*p,
                                             input_group, this_blocker, nb));
       this_blocker = nb;
     }
index af0f53cb4aefca5da8f503fef290ff003b012bfe..ea4b6aff29e92a4e50e7db8e48331076912202b9 100644 (file)
@@ -43,6 +43,7 @@ class General_options;
 class Command_line;
 class Symbol_table;
 class Layout;
+class Mapfile;
 class Input_argument;
 class Input_objects;
 class Input_group;
@@ -393,7 +394,7 @@ class Script_options
 
 bool
 read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*,
-                 Dirsearch*, Input_objects*, Input_group*,
+                 Dirsearch*, Input_objects*, Mapfile*, Input_group*,
                  const Input_argument*, Input_file*,
                  Task_token* next_blocker, bool* used_next_blocker);
 
index 13a069ec4cfdb5debca41d195525f19903ccb107..aa8bbbd912e2d765cdf8402a7c2ac7a22ca6b67e 100644 (file)
@@ -1059,6 +1059,11 @@ class Output_data_plt_sparc : public Output_section_data
  protected:
   void do_adjust_output_section(Output_section* os);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
+
  private:
   // The size of an entry in the PLT.
   static const int base_plt_entry_size = (size == 32 ? 12 : 32);
index d4ca787495ff5186701836926b2ae8757cc49bd4..7d99cd52bb61303d002ad5760ee73d119beaefde 100644 (file)
@@ -38,6 +38,7 @@
 namespace gold
 {
 
+class Mapfile;
 class Object;
 class Relobj;
 template<int size, bool big_endian>
@@ -1177,7 +1178,7 @@ class Symbol_table
 
   // Allocate the common symbols
   void
-  allocate_commons(Layout*);
+  allocate_commons(Layout*, Mapfile*);
 
   // Add a warning for symbol NAME in object OBJ.  WARNING is the text
   // of the warning.
@@ -1374,12 +1375,12 @@ class Symbol_table
   // Allocate the common symbols, sized version.
   template<int size>
   void
-  do_allocate_commons(Layout*);
+  do_allocate_commons(Layout*, Mapfile*);
 
   // Allocate the common symbols from one list.
   template<int size>
   void
-  do_allocate_commons_list(Layout*, bool is_tls, Commons_type*);
+  do_allocate_commons_list(Layout*, bool is_tls, Commons_type*, Mapfile*);
 
   // Implement detect_odr_violations.
   template<int size, bool big_endian>
index f523ae9f26449291a4f238cde54a334b28f6a6d7..356505c18355acd0b91bc34f989f88e9f18d890b 100644 (file)
@@ -446,7 +446,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
       // create another set of data in the .got section.  Note that we
       // always create a PLT if we create a GOT, although the PLT
       // might be empty.
-      this->got_plt_ = new Output_data_space(8);
+      this->got_plt_ = new Output_data_space(8, "** GOT PLT");
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                           (elfcpp::SHF_ALLOC
                                            | elfcpp::SHF_WRITE),
@@ -526,6 +526,11 @@ class Output_data_plt_x86_64 : public Output_section_data
   void
   do_adjust_output_section(Output_section* os);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
+
  private:
   // The size of an entry in the PLT.
   static const int plt_entry_size = 16;