summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog99
-rw-r--r--gold/Makefile.am2
-rw-r--r--gold/Makefile.in15
-rw-r--r--gold/archive.cc34
-rw-r--r--gold/archive.h17
-rw-r--r--gold/common.cc32
-rw-r--r--gold/common.h7
-rw-r--r--gold/copy-relocs.cc2
-rw-r--r--gold/ehframe.h12
-rw-r--r--gold/gold.cc26
-rw-r--r--gold/gold.h7
-rw-r--r--gold/i386.cc7
-rw-r--r--gold/layout.cc53
-rw-r--r--gold/layout.h11
-rw-r--r--gold/main.cc19
-rw-r--r--gold/mapfile.cc405
-rw-r--r--gold/mapfile.h113
-rw-r--r--gold/merge.h10
-rw-r--r--gold/object.h6
-rw-r--r--gold/options.cc7
-rw-r--r--gold/options.h5
-rw-r--r--gold/output.cc58
-rw-r--r--gold/output.h155
-rw-r--r--gold/readsyms.cc14
-rw-r--r--gold/readsyms.h28
-rw-r--r--gold/script-sections.cc7
-rw-r--r--gold/script.cc4
-rw-r--r--gold/script.h3
-rw-r--r--gold/sparc.cc5
-rw-r--r--gold/symtab.h7
-rw-r--r--gold/x86_64.cc7
31 files changed, 1081 insertions, 96 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index bd4db9de4c6..c8843cef8dc 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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.
diff --git a/gold/Makefile.am b/gold/Makefile.am
index 020fd9586d5..14c3c4bacb3 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -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 \
diff --git a/gold/Makefile.in b/gold/Makefile.in
index cc1a9e4d77a..5781ebcefbf 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -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@
diff --git a/gold/archive.cc b/gold/archive.cc
index 1e16de9c76e..0ff8aee2075 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -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();
diff --git a/gold/archive.h b/gold/archive.h
index 818bd60c65e..c8b05e442da 100644
--- a/gold/archive.h
+++ b/gold/archive.h
@@ -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_;
diff --git a/gold/common.cc b/gold/common.cc
index 6789d5d087d..632a20b6c99 100644
--- a/gold/common.cc
+++ b/gold/common.cc
@@ -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();
diff --git a/gold/common.h b/gold/common.h
index 6c281c917e0..96536040fc3 100644
--- a/gold/common.h
+++ b/gold/common.h
@@ -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_;
};
diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc
index 3df50c8c67d..c6cd994f8d9 100644
--- a/gold/copy-relocs.cc
+++ b/gold/copy-relocs.cc
@@ -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,
diff --git a/gold/ehframe.h b/gold/ehframe.h
index 47e3e4c00ca..4726ffc436d 100644
--- a/gold/ehframe.h
+++ b/gold/ehframe.h
@@ -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
diff --git a/gold/gold.cc b/gold/gold.cc
index 267c4d11682..42c6248d4b2 100644
--- a/gold/gold.cc
+++ b/gold/gold.cc
@@ -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"));
}
diff --git a/gold/gold.h b/gold/gold.h
index 62c014ead88..03e73d3c023 100644
--- a/gold/gold.h
+++ b/gold/gold.h
@@ -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
diff --git a/gold/i386.cc b/gold/i386.cc
index 4785fa66c21..948b5d6598c 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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;
diff --git a/gold/layout.cc b/gold/layout.cc
index eae66794eb5..a4003d55736 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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
diff --git a/gold/layout.h b/gold/layout.h
index ede2604cb9c..1c71d477078 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -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;
diff --git a/gold/main.cc b/gold/main.cc
index c785da231ee..35772839e4f 100644
--- a/gold/main.cc
+++ b/gold/main.cc
@@ -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
index 00000000000..e053419c092
--- /dev/null
+++ b/gold/mapfile.cc
@@ -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
index 00000000000..e2cf0855587
--- /dev/null
+++ b/gold/mapfile.h
@@ -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)
diff --git a/gold/merge.h b/gold/merge.h
index cbc8bece427..2aeff1e6fa1 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -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);
diff --git a/gold/object.h b/gold/object.h
index 52359afa367..4a01843bd9d 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -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*
diff --git a/gold/options.cc b/gold/options.cc
index 8d18c11fbc2..da30a6da223 100644
--- a/gold/options.cc
+++ b/gold/options.cc
@@ -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.
diff --git a/gold/options.h b/gold/options.h
index 9a474df5c4e..e34e165ba76 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -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"));
diff --git a/gold/output.cc b/gold/output.cc
index b5791f4db64..a3dab399ad5 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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)
diff --git a/gold/output.h b/gold/output.h
index a8f2f39017d..dceaceb7949 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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.
diff --git a/gold/readsyms.cc b/gold/readsyms.cc
index 18b91b42b79..bfb850a8e4a 100644
--- a/gold/readsyms.cc
+++ b/gold/readsyms.cc
@@ -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"),
diff --git a/gold/readsyms.h b/gold/readsyms.h
index 0ad89f8fc35..f93d6dbc99c 100644
--- a/gold/readsyms.h
+++ b/gold/readsyms.h
@@ -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_;
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index 55db831ae7e..7f3a4daa9cd 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -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
diff --git a/gold/script.cc b/gold/script.cc
index a808b2e31d1..4b2c3379f2b 100644
--- a/gold/script.cc
+++ b/gold/script.cc
@@ -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;
}
diff --git a/gold/script.h b/gold/script.h
index af0f53cb4ae..ea4b6aff29e 100644
--- a/gold/script.h
+++ b/gold/script.h
@@ -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);
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 13a069ec4cf..aa8bbbd912e 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -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);
diff --git a/gold/symtab.h b/gold/symtab.h
index d4ca787495f..7d99cd52bb6 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -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>
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index f523ae9f264..356505c1835 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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;