This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH COMMITTED: Add -Map to gold


I was surprised to discover that the glibc build actually uses the
linker's -Map option.

I committed this patch to add -Map to gold.  My goal was to produce
output which is formatted pretty much like the output of GNU ld.  It's
not identical, since gold normally has no linker script, but it's
pretty close.

Ian


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.


Index: Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/Makefile.am,v
retrieving revision 1.35
diff -p -u -r1.35 Makefile.am
--- Makefile.am	16 Apr 2008 22:54:29 -0000	1.35
+++ Makefile.am	21 May 2008 21:17:08 -0000
@@ -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: archive.cc
===================================================================
RCS file: /cvs/src/src/gold/archive.cc,v
retrieving revision 1.30
diff -p -u -r1.30 archive.cc
--- archive.cc	7 May 2008 06:08:01 -0000	1.30
+++ archive.cc	21 May 2008 21:17:08 -0000
@@ -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_
 
 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* symta
 	  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* symta
 
 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_tabl
           // 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_tabl
 }
 
 // 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* sy
                 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: archive.h
===================================================================
RCS file: /cvs/src/src/gold/archive.h,v
retrieving revision 1.19
diff -p -u -r1.19 archive.h
--- archive.h	2 Apr 2008 20:58:21 -0000	1.19
+++ archive.h	21 May 2008 21:17:09 -0000
@@ -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: common.cc
===================================================================
RCS file: /cvs/src/src/gold/common.cc,v
retrieving revision 1.16
diff -p -u -r1.16 common.cc
--- common.cc	17 Apr 2008 07:12:00 -0000	1.16
+++ common.cc	21 May 2008 21:17:09 -0000
@@ -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
 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 Sym
 // 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* l
   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* l
 
 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
 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(L
 
   // 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(L
       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: common.h
===================================================================
RCS file: /cvs/src/src/gold/common.h,v
retrieving revision 1.6
diff -p -u -r1.6 common.h
--- common.h	17 Apr 2008 07:12:00 -0000	1.6
+++ common.h	21 May 2008 21:17:09 -0000
@@ -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 Tas
  private:
   Symbol_table* symtab_;
   Layout* layout_;
+  Mapfile* mapfile_;
   Task_token* symtab_lock_;
   Task_token* blocker_;
 };
Index: copy-relocs.cc
===================================================================
RCS file: /cvs/src/src/gold/copy-relocs.cc,v
retrieving revision 1.2
diff -p -u -r1.2 copy-relocs.cc
--- copy-relocs.cc	19 Apr 2008 18:30:58 -0000	1.2
+++ copy-relocs.cc	21 May 2008 21:17:09 -0000
@@ -130,7 +130,7 @@ Copy_relocs<sh_type, size, big_endian>::
 
   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: ehframe.h
===================================================================
RCS file: /cvs/src/src/gold/ehframe.h,v
retrieving revision 1.11
diff -p -u -r1.11 ehframe.h
--- ehframe.h	13 Mar 2008 21:04:21 -0000	1.11
+++ ehframe.h	21 May 2008 21:17:09 -0000
@@ -67,6 +67,7 @@ class Eh_frame_hdr : public Output_secti
       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_secti
   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_d
   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_d
   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: gold.cc
===================================================================
RCS file: /cvs/src/src/gold/gold.cc,v
retrieving revision 1.56
diff -p -u -r1.56 gold.cc
--- gold.cc	9 May 2008 14:13:06 -0000	1.56
+++ gold.cc	21 May 2008 21:17:09 -0000
@@ -94,9 +94,9 @@ class Middle_runner : public Task_functi
   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_functi
   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_option
 		    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_option
       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
 		   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
   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
 							    input_objects,
 							    symtab,
                                                             target,
-							    layout),
+							    layout,
+							    mapfile),
 				     blocker,
 				     "Task_function Layout_task_runner"));
 }
Index: gold.h
===================================================================
RCS file: /cvs/src/src/gold/gold.h,v
retrieving revision 1.26
diff -p -u -r1.26 gold.h
--- gold.h	17 Apr 2008 22:45:47 -0000	1.26
+++ gold.h	21 May 2008 21:17:09 -0000
@@ -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_option
 		    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: i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.76
diff -p -u -r1.76 i386.cc
--- i386.cc	20 May 2008 04:00:46 -0000	1.76
+++ i386.cc	21 May 2008 21:17:09 -0000
@@ -437,7 +437,7 @@ Target_i386::got_section(Symbol_table* s
       // 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 Outp
   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: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.104
diff -p -u -r1.104 layout.cc
--- layout.cc	20 May 2008 04:00:46 -0000	1.104
+++ layout.cc	21 May 2008 21:17:09 -0000
@@ -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* workq
 
   // 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, in
 						 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 Inp
       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 Inpu
 						       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 Inpu
 
       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 Inpu
 
       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) co
   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: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.58
diff -p -u -r1.58 layout.h
--- layout.h	20 May 2008 04:00:46 -0000	1.58
+++ layout.h	21 May 2008 21:17:09 -0000
@@ -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_f
 		     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_f
   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: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.24
diff -p -u -r1.24 main.cc
--- main.cc	6 May 2008 18:32:38 -0000	1.24
+++ main.cc	21 May 2008 21:17:09 -0000
@@ -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)
Index: mapfile.cc
===================================================================
RCS file: mapfile.cc
diff -N mapfile.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mapfile.cc	21 May 2008 21:17:09 -0000
@@ -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.
Index: mapfile.h
===================================================================
RCS file: mapfile.h
diff -N mapfile.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mapfile.h	21 May 2008 21:17:09 -0000
@@ -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: merge.h
===================================================================
RCS file: /cvs/src/src/gold/merge.h,v
retrieving revision 1.18
diff -p -u -r1.18 merge.h
--- merge.h	13 Mar 2008 21:04:21 -0000	1.18
+++ merge.h	21 May 2008 21:17:09 -0000
@@ -283,6 +283,11 @@ class Output_merge_data : public Output_
   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 Outpu
   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: object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.59
diff -p -u -r1.59 object.h
--- object.h	1 May 2008 01:23:21 -0000	1.59
+++ object.h	21 May 2008 21:17:09 -0000
@@ -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: options.cc
===================================================================
RCS file: /cvs/src/src/gold/options.cc,v
retrieving revision 1.72
diff -p -u -r1.72 options.cc
--- options.cc	6 May 2008 20:40:33 -0000	1.72
+++ options.cc	21 May 2008 21:17:09 -0000
@@ -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: options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.78
diff -p -u -r1.78 options.h
--- options.h	20 May 2008 04:00:46 -0000	1.78
+++ options.h	21 May 2008 21:17:09 -0000
@@ -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: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.78
diff -p -u -r1.78 output.cc
--- output.cc	20 May 2008 04:00:46 -0000	1.78
+++ output.cc	21 May 2008 21:17:09 -0000
@@ -1701,6 +1701,25 @@ Output_section::Input_section::write_to_
     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_
   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_sc
 						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_li
   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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.71
diff -p -u -r1.71 output.h
--- output.h	20 May 2008 04:00:46 -0000	1.71
+++ output.h	21 May 2008 21:17:09 -0000
@@ -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 Ou
   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 Ou
   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
   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_
   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 
 {
  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 
   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 
 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 O
   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 O
 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_
   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
   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 Ou
   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
   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_
   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_se
   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 Outpu
   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 Outp
   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_dat
   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_dat
     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: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.28
diff -p -u -r1.28 readsyms.cc
--- readsyms.cc	23 Apr 2008 17:29:04 -0000	1.28
+++ readsyms.cc	21 May 2008 21:17:09 -0000
@@ -220,6 +220,7 @@ Read_symbols::do_read_symbols(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*
 					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* workqu
       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* workqu
   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: readsyms.h
===================================================================
RCS file: /cvs/src/src/gold/readsyms.h,v
retrieving revision 1.15
diff -p -u -r1.15 readsyms.h
--- readsyms.h	13 Mar 2008 21:04:21 -0000	1.15
+++ readsyms.h	21 May 2008 21:17:09 -0000
@@ -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: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.13
diff -p -u -r1.13 script-sections.cc
--- script-sections.cc	15 Apr 2008 22:50:37 -0000	1.13
+++ script-sections.cc	21 May 2008 21:17:09 -0000
@@ -426,7 +426,7 @@ Output_section_element_dot_assignment::s
 							      - *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 Ou
   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: script.cc
===================================================================
RCS file: /cvs/src/src/gold/script.cc,v
retrieving revision 1.42
diff -p -u -r1.42 script.cc
--- script.cc	26 Mar 2008 23:36:46 -0000	1.42
+++ script.cc	21 May 2008 21:17:09 -0000
@@ -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, 
 	  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: script.h
===================================================================
RCS file: /cvs/src/src/gold/script.h,v
retrieving revision 1.18
diff -p -u -r1.18 script.h
--- script.h	26 Mar 2008 23:36:46 -0000	1.18
+++ script.h	21 May 2008 21:17:09 -0000
@@ -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: sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.7
diff -p -u -r1.7 sparc.cc
--- sparc.cc	20 May 2008 04:00:46 -0000	1.7
+++ sparc.cc	21 May 2008 21:17:09 -0000
@@ -1059,6 +1059,11 @@ class Output_data_plt_sparc : public Out
  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: symtab.h
===================================================================
RCS file: /cvs/src/src/gold/symtab.h,v
retrieving revision 1.78
diff -p -u -r1.78 symtab.h
--- symtab.h	8 May 2008 18:44:33 -0000	1.78
+++ symtab.h	21 May 2008 21:17:09 -0000
@@ -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: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.69
diff -p -u -r1.69 x86_64.cc
--- x86_64.cc	20 May 2008 04:00:46 -0000	1.69
+++ x86_64.cc	21 May 2008 21:17:09 -0000
@@ -446,7 +446,7 @@ Target_x86_64::got_section(Symbol_table*
       // 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 Ou
   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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]