This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH COMMITTED: Add -Map to gold
- From: Ian Lance Taylor <iant at google dot com>
- To: binutils at sourceware dot org
- Date: Wed, 21 May 2008 14:40:54 -0700
- Subject: 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;