* 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.
This commit is contained in:
Ian Lance Taylor 2008-05-21 21:37:44 +00:00
parent 9f61f19bbf
commit 7d9e3d9854
31 changed files with 1081 additions and 96 deletions

View File

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

View File

@ -45,6 +45,7 @@ CCFILES = \
gold.cc \
gold-threads.cc \
layout.cc \
mapfile.cc \
merge.cc \
object.cc \
options.cc \
@ -78,6 +79,7 @@ HFILES = \
gold.h \
gold-threads.h \
layout.h \
mapfile.h \
merge.h \
object.h \
options.h \

View File

@ -79,12 +79,12 @@ am__objects_1 = archive.$(OBJEXT) binary.$(OBJEXT) common.$(OBJEXT) \
defstd.$(OBJEXT) dirsearch.$(OBJEXT) dynobj.$(OBJEXT) \
dwarf_reader.$(OBJEXT) ehframe.$(OBJEXT) errors.$(OBJEXT) \
expression.$(OBJEXT) fileread.$(OBJEXT) gold.$(OBJEXT) \
gold-threads.$(OBJEXT) layout.$(OBJEXT) merge.$(OBJEXT) \
object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
parameters.$(OBJEXT) readsyms.$(OBJEXT) reloc.$(OBJEXT) \
resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
stringpool.$(OBJEXT) symtab.$(OBJEXT) target-select.$(OBJEXT) \
version.$(OBJEXT) workqueue.$(OBJEXT) \
gold-threads.$(OBJEXT) layout.$(OBJEXT) mapfile.$(OBJEXT) \
merge.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
output.$(OBJEXT) parameters.$(OBJEXT) readsyms.$(OBJEXT) \
reloc.$(OBJEXT) resolve.$(OBJEXT) script-sections.$(OBJEXT) \
script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
target-select.$(OBJEXT) version.$(OBJEXT) workqueue.$(OBJEXT) \
workqueue-threads.$(OBJEXT)
am__objects_2 =
am__objects_3 = yyscript.$(OBJEXT)
@ -325,6 +325,7 @@ CCFILES = \
gold.cc \
gold-threads.cc \
layout.cc \
mapfile.cc \
merge.cc \
object.cc \
options.cc \
@ -358,6 +359,7 @@ HFILES = \
gold.h \
gold-threads.h \
layout.h \
mapfile.h \
merge.h \
object.h \
options.h \
@ -531,6 +533,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@

View File

@ -31,6 +31,7 @@
#include "elfcpp.h"
#include "options.h"
#include "mapfile.h"
#include "fileread.h"
#include "readsyms.h"
#include "symtab.h"
@ -286,10 +287,11 @@ Archive::interpret_header(const Archive_header* hdr, off_t off,
void
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects)
Input_objects* input_objects, Mapfile* mapfile)
{
if (this->input_file_->options().whole_archive())
return this->include_all_members(symtab, layout, input_objects);
return this->include_all_members(symtab, layout, input_objects,
mapfile);
const size_t armap_size = this->armap_.size();
@ -343,8 +345,16 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
last_seen_offset = this->armap_[i].file_offset;
this->seen_offsets_.insert(last_seen_offset);
this->armap_checked_[i] = true;
std::string why;
if (sym == NULL)
{
why = "-u ";
why += sym_name;
}
this->include_member(symtab, layout, input_objects,
last_seen_offset);
last_seen_offset, mapfile, sym, why.c_str());
added_new_object = true;
}
}
@ -355,7 +365,7 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
void
Archive::include_all_members(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects)
Input_objects* input_objects, Mapfile* mapfile)
{
off_t off = sarmag;
off_t filesize = this->input_file_->file().filesize();
@ -385,7 +395,8 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
// Extended name table.
}
else
this->include_member(symtab, layout, input_objects, off);
this->include_member(symtab, layout, input_objects, off,
mapfile, NULL, "--whole-archive");
off += sizeof(Archive_header);
if (!this->is_thin_archive_)
@ -396,16 +407,20 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
}
// Include an archive member in the link. OFF is the file offset of
// the member header.
// the member header. WHY is the reason we are including this member.
void
Archive::include_member(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects, off_t off)
Input_objects* input_objects, off_t off,
Mapfile* mapfile, Symbol* sym, const char* why)
{
std::string n;
off_t nested_off;
this->read_header(off, false, &n, &nested_off);
if (mapfile != NULL)
mapfile->report_include_archive_member(this, n, sym, why);
Input_file* input_file;
off_t memoff;
@ -451,7 +466,8 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
this->nested_archives_.insert(std::make_pair(n, arch));
gold_assert(ins.second);
}
arch->include_member(symtab, layout, input_objects, nested_off);
arch->include_member(symtab, layout, input_objects, nested_off,
NULL, NULL, NULL);
return;
}
// This is an external member of a thin archive. Open the
@ -551,7 +567,7 @@ void
Add_archive_symbols::run(Workqueue*)
{
this->archive_->add_symbols(this->symtab_, this->layout_,
this->input_objects_);
this->input_objects_, this->mapfile_);
this->archive_->unlock_nested_archives();

View File

@ -26,6 +26,7 @@
#include <string>
#include <vector>
#include "fileread.h"
#include "workqueue.h"
namespace gold
@ -75,6 +76,10 @@ class Archive
file()
{ return this->input_file_->file(); }
const File_read&
file() const
{ return this->input_file_->file(); }
// Lock the underlying file.
void
lock(const Task* t)
@ -112,7 +117,7 @@ class Archive
// Select members from the archive as needed and add them to the
// link.
void
add_symbols(Symbol_table*, Layout*, Input_objects*);
add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
private:
Archive(const Archive&);
@ -143,11 +148,12 @@ class Archive
// Include all the archive members in the link.
void
include_all_members(Symbol_table*, Layout*, Input_objects*);
include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);
// Include an archive member in the link.
void
include_member(Symbol_table*, Layout*, Input_objects*, off_t off);
include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
Mapfile*, Symbol*, const char* why);
// An entry in the archive map of symbols to object files.
struct Armap_entry
@ -201,12 +207,12 @@ class Add_archive_symbols : public Task
{
public:
Add_archive_symbols(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects,
Input_objects* input_objects, Mapfile* mapfile,
Archive* archive, Input_group* input_group,
Task_token* this_blocker,
Task_token* next_blocker)
: symtab_(symtab), layout_(layout), input_objects_(input_objects),
archive_(archive), input_group_(input_group),
mapfile_(mapfile), archive_(archive), input_group_(input_group),
this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
@ -235,6 +241,7 @@ class Add_archive_symbols : public Task
Symbol_table* symtab_;
Layout* layout_;
Input_objects* input_objects_;
Mapfile* mapfile_;
Archive* archive_;
Input_group* input_group_;
Task_token* this_blocker_;

View File

@ -25,6 +25,7 @@
#include <algorithm>
#include "workqueue.h"
#include "mapfile.h"
#include "layout.h"
#include "output.h"
#include "symtab.h"
@ -60,7 +61,7 @@ Allocate_commons_task::locks(Task_locker* tl)
void
Allocate_commons_task::run(Workqueue*)
{
this->symtab_->allocate_commons(this->layout_);
this->symtab_->allocate_commons(this->layout_, this->mapfile_);
}
// This class is used to sort the common symbol by size. We put the
@ -117,12 +118,12 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
// Allocate the common symbols.
void
Symbol_table::allocate_commons(Layout* layout)
Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
{
if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
this->do_allocate_commons<32>(layout);
this->do_allocate_commons<32>(layout, mapfile);
#else
gold_unreachable();
#endif
@ -130,7 +131,7 @@ Symbol_table::allocate_commons(Layout* layout)
else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
this->do_allocate_commons<64>(layout);
this->do_allocate_commons<64>(layout, mapfile);
#else
gold_unreachable();
#endif
@ -143,10 +144,12 @@ Symbol_table::allocate_commons(Layout* layout)
template<int size>
void
Symbol_table::do_allocate_commons(Layout* layout)
Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile)
{
this->do_allocate_commons_list<size>(layout, false, &this->commons_);
this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_);
this->do_allocate_commons_list<size>(layout, false, &this->commons_,
mapfile);
this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_,
mapfile);
}
// Allocate the common symbols in a list. IS_TLS indicates whether
@ -155,7 +158,8 @@ Symbol_table::do_allocate_commons(Layout* layout)
template<int size>
void
Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
Commons_type* commons)
Commons_type* commons,
Mapfile* mapfile)
{
typedef typename Sized_symbol<size>::Value_type Value_type;
typedef typename Sized_symbol<size>::Size_type Size_type;
@ -195,7 +199,10 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
// Place them in a newly allocated BSS section.
Output_data_space *poc = new Output_data_space(addralign);
Output_data_space *poc = new Output_data_space(addralign,
(is_tls
? "** tls common"
: "** common"));
const char* name = ".bss";
elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
@ -217,6 +224,13 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls,
if (sym == NULL)
break;
Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
// Record the symbol in the map file now, before we change its
// value. Pass the size in separately so that we don't have to
// templatize the map code, which is not performance sensitive.
if (mapfile != NULL)
mapfile->report_allocate_common(sym, ssym->symsize());
off = align_address(off, ssym->value());
ssym->allocate_common(poc, off);
off += ssym->symsize();

View File

@ -35,10 +35,10 @@ class Symbol_table;
class Allocate_commons_task : public Task
{
public:
Allocate_commons_task(Symbol_table* symtab, Layout* layout,
Allocate_commons_task(Symbol_table* symtab, Layout* layout, Mapfile* mapfile,
Task_token* symtab_lock, Task_token* blocker)
: symtab_(symtab), layout_(layout), symtab_lock_(symtab_lock),
blocker_(blocker)
: symtab_(symtab), layout_(layout), mapfile_(mapfile),
symtab_lock_(symtab_lock), blocker_(blocker)
{ }
// The standard Task methods.
@ -59,6 +59,7 @@ class Allocate_commons_task : public Task
private:
Symbol_table* symtab_;
Layout* layout_;
Mapfile* mapfile_;
Task_token* symtab_lock_;
Task_token* blocker_;
};

View File

@ -130,7 +130,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
if (this->dynbss_ == NULL)
{
this->dynbss_ = new Output_data_space(addralign);
this->dynbss_ = new Output_data_space(addralign, "** dynbss");
layout->add_output_section_data(".bss",
elfcpp::SHT_NOBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,

View File

@ -67,6 +67,7 @@ class Eh_frame_hdr : public Output_section_data
this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
}
protected:
// Set the final data size.
void
set_final_data_size();
@ -75,6 +76,11 @@ class Eh_frame_hdr : public Output_section_data
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** eh_frame_hdr")); }
private:
// Write the data to the file with the right endianness.
template<int size, bool big_endian>
@ -322,6 +328,7 @@ class Eh_frame : public Output_section_data
unsigned int
fde_count() const;
protected:
// Set the final data size.
void
set_final_data_size();
@ -340,6 +347,11 @@ class Eh_frame : public Output_section_data
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** eh_frame")); }
private:
// The comparison routine for the CIE map.
struct Cie_less

View File

@ -94,9 +94,9 @@ class Middle_runner : public Task_function_runner
Middle_runner(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
Layout* layout)
Layout* layout, Mapfile* mapfile)
: options_(options), input_objects_(input_objects), symtab_(symtab),
layout_(layout)
layout_(layout), mapfile_(mapfile)
{ }
void
@ -107,13 +107,14 @@ class Middle_runner : public Task_function_runner
const Input_objects* input_objects_;
Symbol_table* symtab_;
Layout* layout_;
Mapfile* mapfile_;
};
void
Middle_runner::run(Workqueue* workqueue, const Task* task)
{
queue_middle_tasks(this->options_, task, this->input_objects_, this->symtab_,
this->layout_, workqueue);
this->layout_, workqueue, this->mapfile_);
}
// Queue up the initial set of tasks for this link job.
@ -123,7 +124,7 @@ queue_initial_tasks(const General_options& options,
Dirsearch& search_path,
const Command_line& cmdline,
Workqueue* workqueue, Input_objects* input_objects,
Symbol_table* symtab, Layout* layout)
Symbol_table* symtab, Layout* layout, Mapfile* mapfile)
{
if (cmdline.begin() == cmdline.end())
gold_fatal(_("no input files"));
@ -145,15 +146,16 @@ queue_initial_tasks(const General_options& options,
Task_token* next_blocker = new Task_token(true);
next_blocker->add_blocker();
workqueue->queue(new Read_symbols(options, input_objects, symtab, layout,
&search_path, &*p, NULL, this_blocker,
next_blocker));
&search_path, mapfile, &*p, NULL,
this_blocker, next_blocker));
this_blocker = next_blocker;
}
workqueue->queue(new Task_function(new Middle_runner(options,
input_objects,
symtab,
layout),
layout,
mapfile),
this_blocker,
"Task_function Middle_runner"));
}
@ -168,7 +170,8 @@ queue_middle_tasks(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
Layout* layout,
Workqueue* workqueue)
Workqueue* workqueue,
Mapfile* mapfile)
{
// We have to support the case of not seeing any input objects, and
// generate an empty file. Existing builds depend on being able to
@ -272,8 +275,8 @@ queue_middle_tasks(const General_options& options,
if (parameters->options().define_common())
{
blocker->add_blocker();
workqueue->queue(new Allocate_commons_task(symtab, layout, symtab_lock,
blocker));
workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile,
symtab_lock, blocker));
}
// When all those tasks are complete, we can start laying out the
@ -284,7 +287,8 @@ queue_middle_tasks(const General_options& options,
input_objects,
symtab,
target,
layout),
layout,
mapfile),
blocker,
"Task_function Layout_task_runner"));
}

View File

@ -115,6 +115,7 @@ class Command_line;
class Input_argument_list;
class Dirsearch;
class Input_objects;
class Mapfile;
class Symbol;
class Symbol_table;
class Layout;
@ -241,7 +242,8 @@ queue_initial_tasks(const General_options&,
Workqueue*,
Input_objects*,
Symbol_table*,
Layout*);
Layout*,
Mapfile*);
// Queue up the middle set of tasks.
extern void
@ -250,7 +252,8 @@ queue_middle_tasks(const General_options&,
const Input_objects*,
Symbol_table*,
Layout*,
Workqueue*);
Workqueue*,
Mapfile*);
// Queue up the final set of tasks.
extern void

View File

@ -437,7 +437,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
this->got_plt_ = new Output_data_space(4);
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
@ -496,6 +496,11 @@ class Output_data_plt_i386 : public Output_section_data
void
do_adjust_output_section(Output_section* os);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** PLT")); }
private:
// The size of an entry in the PLT.
static const int plt_entry_size = 16;

View File

@ -35,6 +35,7 @@
#include "parameters.h"
#include "options.h"
#include "mapfile.h"
#include "script.h"
#include "script-sections.h"
#include "output.h"
@ -63,6 +64,13 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
// Now we know the final size of the output file and we know where
// each piece of information goes.
if (this->mapfile_ != NULL)
{
this->mapfile_->print_discarded_sections(this->input_objects_);
this->layout_->print_to_mapfile(this->mapfile_);
}
Output_file* of = new Output_file(parameters->options().output_file_name());
if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
of->set_is_temporary();
@ -1323,7 +1331,8 @@ Layout::create_note(const char* name, int note_type, size_t descsz,
elfcpp::SHT_NOTE,
flags);
Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
size / 8);
size / 8,
"** note header");
os->add_output_section_data(posd);
*trailing_padding = aligned_descsz - descsz;
@ -1351,7 +1360,7 @@ Layout::create_gold_note()
if (trailing_padding > 0)
{
posd = new Output_data_fixed_space(trailing_padding, 0);
posd = new Output_data_zero_fill(trailing_padding, 0);
os->add_output_section_data(posd);
}
}
@ -1488,7 +1497,7 @@ Layout::create_build_id()
if (trailing_padding != 0)
{
posd = new Output_data_fixed_space(trailing_padding, 0);
posd = new Output_data_zero_fill(trailing_padding, 0);
os->add_output_section_data(posd);
}
}
@ -1497,7 +1506,7 @@ Layout::create_build_id()
// We need to compute a checksum after we have completed the
// link.
gold_assert(trailing_padding == 0);
this->build_id_note_ = new Output_data_fixed_space(descsz, 4);
this->build_id_note_ = new Output_data_zero_fill(descsz, 4);
os->add_output_section_data(this->build_id_note_);
os->set_after_input_sections();
}
@ -2049,7 +2058,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
this->symtab_section_ = osymtab;
Output_section_data* pos = new Output_data_fixed_space(off - startoff,
align);
align,
"** symtab");
osymtab->add_output_section_data(pos);
// We generate a .symtab_shndx section if we have more than
@ -2230,7 +2240,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
false);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align);
align,
"** dynsym");
dynsym->add_output_section_data(odata);
dynsym->set_info(local_symcount);
@ -2309,7 +2320,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
align);
align,
"** hash");
hashsec->add_output_section_data(hashdata);
hashsec->set_link_section(dynsym);
@ -2333,7 +2345,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
align);
align,
"** hash");
hashsec->add_output_section_data(hashdata);
hashsec->set_link_section(dynsym);
@ -2435,7 +2448,8 @@ Layout::sized_create_version_sections(
dynamic_symbols,
&vbuf, &vsize);
Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2);
Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2,
"** versions");
vsec->add_output_section_data(vdata);
vsec->set_entsize(2);
@ -2458,9 +2472,8 @@ Layout::sized_create_version_sections(
versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
&vdsize, &vdentries);
Output_section_data* vddata = new Output_data_const_buffer(vdbuf,
vdsize,
4);
Output_section_data* vddata =
new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs");
vdsec->add_output_section_data(vddata);
vdsec->set_link_section(dynstr);
@ -2485,9 +2498,8 @@ Layout::sized_create_version_sections(
&vnbuf, &vnsize,
&vnentries);
Output_section_data* vndata = new Output_data_const_buffer(vnbuf,
vnsize,
4);
Output_section_data* vndata =
new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs");
vnsec->add_output_section_data(vndata);
vnsec->set_link_section(dynstr);
@ -3086,6 +3098,17 @@ Layout::write_binary(Output_file* in) const
out.close();
}
// Print the output sections to the map file.
void
Layout::print_to_mapfile(Mapfile* mapfile) const
{
for (Segment_list::const_iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
++p)
(*p)->print_sections_to_mapfile(mapfile);
}
// Print statistical information to stderr. This is used for --stats.
void

View File

@ -40,6 +40,7 @@ namespace gold
class General_options;
class Input_objects;
class Mapfile;
class Symbol_table;
class Output_section_data;
class Output_section;
@ -64,9 +65,10 @@ class Layout_task_runner : public Task_function_runner
const Input_objects* input_objects,
Symbol_table* symtab,
Target* target,
Layout* layout)
Layout* layout,
Mapfile* mapfile)
: options_(options), input_objects_(input_objects), symtab_(symtab),
target_(target), layout_(layout)
target_(target), layout_(layout), mapfile_(mapfile)
{ }
// Run the operation.
@ -82,6 +84,7 @@ class Layout_task_runner : public Task_function_runner
Symbol_table* symtab_;
Target* target_;
Layout* layout_;
Mapfile* mapfile_;
};
// This class handles the details of laying out input sections.
@ -334,6 +337,10 @@ class Layout
void
write_binary(Output_file* in) const;
// Print output sections to the map file.
void
print_to_mapfile(Mapfile*) const;
// Dump statistical information to stderr.
void
print_stats() const;

View File

@ -22,6 +22,7 @@
#include "gold.h"
#include <cstdio>
#include <cstring>
#ifdef HAVE_MALLINFO
@ -34,6 +35,7 @@
#include "options.h"
#include "parameters.h"
#include "errors.h"
#include "mapfile.h"
#include "dirsearch.h"
#include "workqueue.h"
#include "object.h"
@ -165,6 +167,18 @@ main(int argc, char** argv)
write_debug_script(command_line.options().output_file_name(),
program_name, args.c_str());
// If the user asked for a map file, open it.
Mapfile* mapfile = NULL;
if (command_line.options().user_set_Map())
{
mapfile = new Mapfile();
if (!mapfile->open(command_line.options().Map()))
{
delete mapfile;
mapfile = NULL;
}
}
// The GNU linker ignores version scripts when generating
// relocatable output. If we are not compatible, then we break the
// Linux kernel build, which uses a linker script with -r which must
@ -198,7 +212,7 @@ main(int argc, char** argv)
// Queue up the first set of tasks.
queue_initial_tasks(command_line.options(), search_path,
command_line, &workqueue, &input_objects,
&symtab, &layout);
&symtab, &layout, mapfile);
// Run the main task processing loop.
workqueue.process(0);
@ -220,6 +234,9 @@ main(int argc, char** argv)
layout.print_stats();
}
if (mapfile != NULL)
mapfile->close();
if (parameters->options().fatal_warnings()
&& errors.warning_count() > 0
&& errors.error_count() == 0)

405
gold/mapfile.cc Normal file
View File

@ -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.

113
gold/mapfile.h Normal file
View File

@ -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)

View File

@ -283,6 +283,11 @@ class Output_merge_data : public Output_merge_base
void
do_write_to_buffer(unsigned char*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** merge constants")); }
// Print merge stats to stderr.
void
do_print_merge_stats(const char* section_name);
@ -400,6 +405,11 @@ class Output_merge_string : public Output_merge_base
void
do_write_to_buffer(unsigned char*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** merge strings")); }
// Print merge stats to stderr.
void
do_print_merge_stats(const char* section_name);

View File

@ -1239,6 +1239,12 @@ class Sized_relobj : public Relobj
void
setup(const typename elfcpp::Ehdr<size, big_endian>&);
// Return the number of symbols. This is only valid after
// Object::add_symbols has been called.
unsigned int
symbol_count() const
{ return this->local_symbol_count_ + this->symbols_.size(); }
// If SYM is the index of a global symbol in the object file's
// symbol table, return the Symbol object. Otherwise, return NULL.
Symbol*

View File

@ -697,6 +697,13 @@ General_options::finalize()
this->set_do_demangle(getenv("COLLECT_NO_DEMANGLE") == NULL);
}
// -M is equivalent to "-Map -".
if (this->print_map() && !this->user_set_Map())
{
this->set_Map("-");
this->set_user_set_Map();
}
// If --thread_count is specified, it applies to
// --thread-count-{initial,middle,final}, though it doesn't override
// them.

View File

@ -654,6 +654,11 @@ class General_options
DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
N_("Ignored for compatibility"), N_("EMULATION"));
DEFINE_bool(print_map, options::TWO_DASHES, 'M', false,
N_("Write map file on standard output"), NULL);
DEFINE_string(Map, options::ONE_DASH, '\0', NULL, N_("Write map file"),
N_("MAPFILENAME"));
DEFINE_enable(new_dtags, options::EXACTLY_TWO_DASHES, '\0', false,
N_("Enable use of DT_RUNPATH and DT_FLAGS"),
N_("Disable use of DT_RUNPATH and DT_FLAGS"));

View File

@ -1701,6 +1701,25 @@ Output_section::Input_section::write_to_buffer(unsigned char* buffer)
this->u2_.posd->write_to_buffer(buffer);
}
// Print to a map file.
void
Output_section::Input_section::print_to_mapfile(Mapfile* mapfile) const
{
switch (this->shndx_)
{
case OUTPUT_SECTION_CODE:
case MERGE_DATA_SECTION_CODE:
case MERGE_STRING_SECTION_CODE:
this->u2_.posd->print_to_mapfile(mapfile);
break;
default:
mapfile->print_input_section(this->u2_.object, this->shndx_);
break;
}
}
// Output_section methods.
// Construct an Output_section. NAME will point into a Stringpool.
@ -1859,7 +1878,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
if (have_sections_script
|| !this->input_sections_.empty()
|| this->may_sort_attached_input_sections()
|| this->must_sort_attached_input_sections())
|| this->must_sort_attached_input_sections()
|| parameters->options().user_set_Map())
this->input_sections_.push_back(Input_section(object, shndx,
shdr.get_sh_size(),
addralign));
@ -2546,6 +2566,19 @@ Output_section::add_input_section_for_script(Relobj* object,
data_size, addralign));
}
// Print to the map file.
void
Output_section::do_print_to_mapfile(Mapfile* mapfile) const
{
mapfile->print_output_section(this);
for (Input_section_list::const_iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
++p)
p->print_to_mapfile(mapfile);
}
// Print stats for merge sections to stderr.
void
@ -3236,6 +3269,29 @@ Output_segment::write_section_headers_list(const Layout* layout,
return v;
}
// Print the output sections to the map file.
void
Output_segment::print_sections_to_mapfile(Mapfile* mapfile) const
{
if (this->type() != elfcpp::PT_LOAD)
return;
this->print_section_list_to_mapfile(mapfile, &this->output_data_);
this->print_section_list_to_mapfile(mapfile, &this->output_bss_);
}
// Print an output section list to the map file.
void
Output_segment::print_section_list_to_mapfile(Mapfile* mapfile,
const Output_data_list* pdl) const
{
for (Output_data_list::const_iterator p = pdl->begin();
p != pdl->end();
++p)
(*p)->print_to_mapfile(mapfile);
}
// Output_file methods.
Output_file::Output_file(const char* name)

View File

@ -27,6 +27,7 @@
#include <vector>
#include "elfcpp.h"
#include "mapfile.h"
#include "layout.h"
#include "reloc-types.h"
@ -240,6 +241,11 @@ class Output_data
is_data_size_valid() const
{ return this->is_data_size_valid_; }
// Print information to the map file.
void
print_to_mapfile(Mapfile* mapfile) const
{ return this->do_print_to_mapfile(mapfile); }
protected:
// Functions that child classes may or in some cases must implement.
@ -316,6 +322,12 @@ class Output_data
do_tls_offset() const
{ gold_unreachable(); }
// Print to the map file. This only needs to be implemented by
// classes which may appear in a PT_LOAD segment.
virtual void
do_print_to_mapfile(Mapfile*) const
{ gold_unreachable(); }
// Functions that child classes may call.
// Set the size of the data.
@ -397,6 +409,11 @@ class Output_section_headers : public Output_data
do_addralign() const
{ return Output_data::default_alignment(); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** section headers")); }
private:
// Write the data to the file with the right size and endianness.
template<int size, bool big_endian>
@ -428,6 +445,11 @@ class Output_segment_headers : public Output_data
do_addralign() const
{ return Output_data::default_alignment(); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** segment headers")); }
private:
// Write the data to the file with the right size and endianness.
template<int size, bool big_endian>
@ -462,6 +484,11 @@ class Output_file_header : public Output_data
do_addralign() const
{ return Output_data::default_alignment(); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** file header")); }
private:
// Write the data to the file with the right size and endianness.
template<int size, bool big_endian>
@ -663,6 +690,11 @@ class Output_data_const : public Output_section_data
do_write_to_buffer(unsigned char* buffer)
{ memcpy(buffer, this->data_.data(), this->data_.size()); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** fill")); }
private:
std::string data_;
};
@ -674,8 +706,9 @@ class Output_data_const_buffer : public Output_section_data
{
public:
Output_data_const_buffer(const unsigned char* p, off_t len,
uint64_t addralign)
: Output_section_data(len, addralign), p_(p)
uint64_t addralign, const char* map_name)
: Output_section_data(len, addralign),
p_(p), map_name_(map_name)
{ }
protected:
@ -688,8 +721,17 @@ class Output_data_const_buffer : public Output_section_data
do_write_to_buffer(unsigned char* buffer)
{ memcpy(buffer, this->p_, this->data_size()); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _(this->map_name_)); }
private:
// The data to output.
const unsigned char* p_;
// Name to use in a map file. Maps are a rarely used feature, but
// the space usage is minor as aren't very many of these objects.
const char* map_name_;
};
// A place holder for a fixed amount of data written out via some
@ -698,8 +740,10 @@ class Output_data_const_buffer : public Output_section_data
class Output_data_fixed_space : public Output_section_data
{
public:
Output_data_fixed_space(off_t data_size, uint64_t addralign)
: Output_section_data(data_size, addralign)
Output_data_fixed_space(off_t data_size, uint64_t addralign,
const char* map_name)
: Output_section_data(data_size, addralign),
map_name_(map_name)
{ }
protected:
@ -708,6 +752,16 @@ class Output_data_fixed_space : public Output_section_data
void
do_write(Output_file*)
{ }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _(this->map_name_)); }
private:
// Name to use in a map file. Maps are a rarely used feature, but
// the space usage is minor as aren't very many of these objects.
const char* map_name_;
};
// A place holder for variable sized data written out via some other
@ -716,8 +770,9 @@ class Output_data_fixed_space : public Output_section_data
class Output_data_space : public Output_section_data_build
{
public:
explicit Output_data_space(uint64_t addralign)
: Output_section_data_build(addralign)
explicit Output_data_space(uint64_t addralign, const char* map_name)
: Output_section_data_build(addralign),
map_name_(map_name)
{ }
// Set the alignment.
@ -731,6 +786,38 @@ class Output_data_space : public Output_section_data_build
void
do_write(Output_file*)
{ }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _(this->map_name_)); }
private:
// Name to use in a map file. Maps are a rarely used feature, but
// the space usage is minor as aren't very many of these objects.
const char* map_name_;
};
// Fill fixed space with zeroes. This is just like
// Output_data_fixed_space, except that the map name is known.
class Output_data_zero_fill : public Output_section_data
{
public:
Output_data_zero_fill(off_t data_size, uint64_t addralign)
: Output_section_data(data_size, addralign)
{ }
protected:
// There is no data to write out.
void
do_write(Output_file*)
{ }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, "** zero fill"); }
};
// A string table which goes into an output section.
@ -757,6 +844,11 @@ class Output_data_strtab : public Output_section_data
do_write_to_buffer(unsigned char* buffer)
{ this->strtab_->write_to_buffer(buffer, this->data_size()); }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** string table")); }
private:
Stringpool* strtab_;
};
@ -1056,6 +1148,16 @@ class Output_data_reloc_base : public Output_section_data_build
void
do_adjust_output_section(Output_section *os);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{
mapfile->print_output_data(this,
(dynamic
? _("** dynamic relocs")
: _("** relocs")));
}
// Add a relocation entry.
void
add(Output_data *od, const Output_reloc_type& reloc)
@ -1380,6 +1482,11 @@ class Output_relocatable_relocs : public Output_section_data
do_write(Output_file*)
{ }
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** relocs")); }
private:
// The relocs associated with this input section.
Relocatable_relocs* rr_;
@ -1400,6 +1507,11 @@ class Output_data_group : public Output_section_data
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** group")); }
private:
// The input object.
Sized_relobj<size, big_endian>* relobj_;
@ -1502,6 +1614,11 @@ class Output_data_got : public Output_section_data_build
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** GOT")); }
private:
// This POD class holds a single GOT entry.
class Got_entry
@ -1639,6 +1756,11 @@ class Output_data_dynamic : public Output_section_data
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** dynamic")); }
private:
// This POD class holds a single dynamic entry.
class Dynamic_entry
@ -1752,6 +1874,11 @@ class Output_symtab_xindex : public Output_section_data
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** symtab xindex")); }
private:
template<bool big_endian>
void
@ -2262,6 +2389,10 @@ class Output_section : public Output_data
do_finalize_name(Layout*)
{ }
// Print to the map file.
virtual void
do_print_to_mapfile(Mapfile*) const;
// Record that this section requires postprocessing after all
// relocations have been applied. This is called by a child class.
void
@ -2439,6 +2570,10 @@ class Output_section : public Output_data
void
write_to_buffer(unsigned char*);
// Print to a map file.
void
print_to_mapfile(Mapfile*) const;
// Print statistics about merge sections to stderr.
void
print_merge_stats(const char* section_name)
@ -2802,6 +2937,10 @@ class Output_segment
write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
unsigned int* pshndx) const;
// Print the output sections in the map file.
void
print_sections_to_mapfile(Mapfile*) const;
private:
Output_segment(const Output_segment&);
Output_segment& operator=(const Output_segment&);
@ -2844,6 +2983,10 @@ class Output_segment
const Output_data_list*, unsigned char* v,
unsigned int* pshdx) const;
// Print a section list to the mapfile.
void
print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const;
// The list of output data with contents attached to this segment.
Output_data_list output_data_;
// The list of output data without contents attached to this segment.

View File

@ -220,6 +220,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
workqueue->queue_next(new Add_archive_symbols(this->symtab_,
this->layout_,
this->input_objects_,
this->mapfile_,
arch,
this->input_group_,
this->this_blocker_,
@ -239,6 +240,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
this->layout_,
this->dirpath_,
this->input_objects_,
this->mapfile_,
this->input_group_,
this->input_argument_,
input_file,
@ -274,7 +276,8 @@ Read_symbols::do_group(Workqueue* workqueue)
workqueue->queue_soon(new Read_symbols(this->options_,
this->input_objects_,
this->symtab_, this->layout_,
this->dirpath_, arg, input_group,
this->dirpath_, this->mapfile_,
arg, input_group,
this_blocker, next_blocker));
this_blocker = next_blocker;
}
@ -283,6 +286,7 @@ Read_symbols::do_group(Workqueue* workqueue)
workqueue->queue_soon(new Finish_group(this->input_objects_,
this->symtab_,
this->layout_,
this->mapfile_,
input_group,
saw_undefined,
this_blocker,
@ -411,7 +415,7 @@ Finish_group::run(Workqueue*)
Task_lock_obj<Archive> tl(this, *p);
(*p)->add_symbols(this->symtab_, this->layout_,
this->input_objects_);
this->input_objects_, this->mapfile_);
}
}
@ -459,9 +463,9 @@ Read_script::run(Workqueue* workqueue)
bool used_next_blocker;
if (!read_input_script(workqueue, this->options_, this->symtab_,
this->layout_, this->dirpath_, this->input_objects_,
this->input_group_, this->input_argument_,
this->input_file_, this->next_blocker_,
&used_next_blocker))
this->mapfile_, this->input_group_,
this->input_argument_, this->input_file_,
this->next_blocker_, &used_next_blocker))
{
// Here we have to handle any other input file types we need.
gold_error(_("%s: not an object or archive"),

View File

@ -56,12 +56,13 @@ class Read_symbols : public Task
// symbols.
Read_symbols(const General_options& options, Input_objects* input_objects,
Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
const Input_argument* input_argument, Input_group* input_group,
Task_token* this_blocker, Task_token* next_blocker)
Mapfile* mapfile, const Input_argument* input_argument,
Input_group* input_group, Task_token* this_blocker,
Task_token* next_blocker)
: options_(options), input_objects_(input_objects), symtab_(symtab),
layout_(layout), dirpath_(dirpath), input_argument_(input_argument),
input_group_(input_group), this_blocker_(this_blocker),
next_blocker_(next_blocker)
layout_(layout), dirpath_(dirpath), mapfile_(mapfile),
input_argument_(input_argument), input_group_(input_group),
this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
~Read_symbols();
@ -94,6 +95,7 @@ class Read_symbols : public Task
Symbol_table* symtab_;
Layout* layout_;
Dirsearch* dirpath_;
Mapfile* mapfile_;
const Input_argument* input_argument_;
Input_group* input_group_;
Task_token* this_blocker_;
@ -184,11 +186,11 @@ class Finish_group : public Task
{
public:
Finish_group(Input_objects* input_objects, Symbol_table* symtab,
Layout* layout, Input_group* input_group,
Layout* layout, Mapfile* mapfile, Input_group* input_group,
int saw_undefined, Task_token* this_blocker,
Task_token* next_blocker)
: input_objects_(input_objects), symtab_(symtab),
layout_(layout), input_group_(input_group),
layout_(layout), mapfile_(mapfile), input_group_(input_group),
saw_undefined_(saw_undefined), this_blocker_(this_blocker),
next_blocker_(next_blocker)
{ }
@ -214,6 +216,7 @@ class Finish_group : public Task
Input_objects* input_objects_;
Symbol_table* symtab_;
Layout* layout_;
Mapfile* mapfile_;
Input_group* input_group_;
int saw_undefined_;
Task_token* this_blocker_;
@ -229,13 +232,15 @@ class Read_script : public Task
public:
Read_script(const General_options& options, Symbol_table* symtab,
Layout* layout, Dirsearch* dirpath, Input_objects* input_objects,
Input_group* input_group, const Input_argument* input_argument,
Mapfile* mapfile, Input_group* input_group,
const Input_argument* input_argument,
Input_file* input_file, Task_token* this_blocker,
Task_token* next_blocker)
: options_(options), symtab_(symtab), layout_(layout), dirpath_(dirpath),
input_objects_(input_objects), input_group_(input_group),
input_argument_(input_argument), input_file_(input_file),
this_blocker_(this_blocker), next_blocker_(next_blocker)
input_objects_(input_objects), mapfile_(mapfile),
input_group_(input_group), input_argument_(input_argument),
input_file_(input_file), this_blocker_(this_blocker),
next_blocker_(next_blocker)
{ }
~Read_script();
@ -260,6 +265,7 @@ class Read_script : public Task
Layout* layout_;
Dirsearch* dirpath_;
Input_objects* input_objects_;
Mapfile* mapfile_;
Input_group* input_group_;
const Input_argument* input_argument_;
Input_file* input_file_;

View File

@ -426,7 +426,7 @@ Output_section_element_dot_assignment::set_section_addresses(
- *dot_value);
Output_section_data* posd;
if (fill->empty())
posd = new Output_data_fixed_space(length, 0);
posd = new Output_data_zero_fill(length, 0);
else
{
std::string this_fill = this->get_fill_string(fill, length);
@ -482,6 +482,11 @@ class Output_data_expression : public Output_section_data
void
do_write_to_buffer(unsigned char*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** expression")); }
private:
template<bool big_endian>
void

View File

@ -1313,7 +1313,7 @@ bool
read_input_script(Workqueue* workqueue, const General_options& options,
Symbol_table* symtab, Layout* layout,
Dirsearch* dirsearch, Input_objects* input_objects,
Input_group* input_group,
Mapfile* mapfile, Input_group* input_group,
const Input_argument* input_argument,
Input_file* input_file, Task_token* next_blocker,
bool* used_next_blocker)
@ -1353,7 +1353,7 @@ read_input_script(Workqueue* workqueue, const General_options& options,
nb->add_blocker();
}
workqueue->queue_soon(new Read_symbols(options, input_objects, symtab,
layout, dirsearch, &*p,
layout, dirsearch, mapfile, &*p,
input_group, this_blocker, nb));
this_blocker = nb;
}

View File

@ -43,6 +43,7 @@ class General_options;
class Command_line;
class Symbol_table;
class Layout;
class Mapfile;
class Input_argument;
class Input_objects;
class Input_group;
@ -393,7 +394,7 @@ class Script_options
bool
read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*,
Dirsearch*, Input_objects*, Input_group*,
Dirsearch*, Input_objects*, Mapfile*, Input_group*,
const Input_argument*, Input_file*,
Task_token* next_blocker, bool* used_next_blocker);

View File

@ -1059,6 +1059,11 @@ class Output_data_plt_sparc : public Output_section_data
protected:
void do_adjust_output_section(Output_section* os);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** PLT")); }
private:
// The size of an entry in the PLT.
static const int base_plt_entry_size = (size == 32 ? 12 : 32);

View File

@ -38,6 +38,7 @@
namespace gold
{
class Mapfile;
class Object;
class Relobj;
template<int size, bool big_endian>
@ -1177,7 +1178,7 @@ class Symbol_table
// Allocate the common symbols
void
allocate_commons(Layout*);
allocate_commons(Layout*, Mapfile*);
// Add a warning for symbol NAME in object OBJ. WARNING is the text
// of the warning.
@ -1374,12 +1375,12 @@ class Symbol_table
// Allocate the common symbols, sized version.
template<int size>
void
do_allocate_commons(Layout*);
do_allocate_commons(Layout*, Mapfile*);
// Allocate the common symbols from one list.
template<int size>
void
do_allocate_commons_list(Layout*, bool is_tls, Commons_type*);
do_allocate_commons_list(Layout*, bool is_tls, Commons_type*, Mapfile*);
// Implement detect_odr_violations.
template<int size, bool big_endian>

View File

@ -446,7 +446,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
this->got_plt_ = new Output_data_space(8);
this->got_plt_ = new Output_data_space(8, "** GOT PLT");
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
@ -526,6 +526,11 @@ class Output_data_plt_x86_64 : public Output_section_data
void
do_adjust_output_section(Output_section* os);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** PLT")); }
private:
// The size of an entry in the PLT.
static const int plt_entry_size = 16;