* 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-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.
gold.cc \
gold-threads.cc \
layout.cc \
+ mapfile.cc \
merge.cc \
object.cc \
options.cc \
gold.h \
gold-threads.h \
layout.h \
+ mapfile.h \
merge.h \
object.h \
options.h \
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)
gold.cc \
gold-threads.cc \
layout.cc \
+ mapfile.cc \
merge.cc \
object.cc \
options.cc \
gold.h \
gold-threads.h \
layout.h \
+ mapfile.h \
merge.h \
object.h \
options.h \
@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@
#include "elfcpp.h"
#include "options.h"
+#include "mapfile.h"
#include "fileread.h"
#include "readsyms.h"
#include "symtab.h"
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();
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;
}
}
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();
// 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_)
}
// 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;
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
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();
#include <string>
#include <vector>
+#include "fileread.h"
#include "workqueue.h"
namespace gold
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)
// 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&);
// 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
{
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)
{ }
Symbol_table* symtab_;
Layout* layout_;
Input_objects* input_objects_;
+ Mapfile* mapfile_;
Archive* archive_;
Input_group* input_group_;
Task_token* this_blocker_;
#include <algorithm>
#include "workqueue.h"
+#include "mapfile.h"
#include "layout.h"
#include "output.h"
#include "symtab.h"
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
// 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
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
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
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;
// 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;
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();
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.
private:
Symbol_table* symtab_;
Layout* layout_;
+ Mapfile* mapfile_;
Task_token* symtab_lock_;
Task_token* blocker_;
};
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,
this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
}
+ protected:
// Set the final data size.
void
set_final_data_size();
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>
unsigned int
fde_count() const;
+ protected:
// Set the final data size.
void
set_final_data_size();
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
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
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.
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"));
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"));
}
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
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
input_objects,
symtab,
target,
- layout),
+ layout,
+ mapfile),
blocker,
"Task_function Layout_task_runner"));
}
class Input_argument_list;
class Dirsearch;
class Input_objects;
+class Mapfile;
class Symbol;
class Symbol_table;
class Layout;
Workqueue*,
Input_objects*,
Symbol_table*,
- Layout*);
+ Layout*,
+ Mapfile*);
// Queue up the middle set of tasks.
extern void
const Input_objects*,
Symbol_table*,
Layout*,
- Workqueue*);
+ Workqueue*,
+ Mapfile*);
// Queue up the final set of tasks.
extern void
// 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),
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;
#include "parameters.h"
#include "options.h"
+#include "mapfile.h"
#include "script.h"
#include "script-sections.h"
#include "output.h"
// 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();
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;
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);
}
}
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);
}
}
// 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();
}
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
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);
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);
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);
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);
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);
&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);
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
class General_options;
class Input_objects;
+class Mapfile;
class Symbol_table;
class Output_section_data;
class Output_section;
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.
Symbol_table* symtab_;
Target* target_;
Layout* layout_;
+ Mapfile* mapfile_;
};
// This class handles the details of laying out input sections.
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;
#include "gold.h"
+#include <cstdio>
#include <cstring>
#ifdef HAVE_MALLINFO
#include "options.h"
#include "parameters.h"
#include "errors.h"
+#include "mapfile.h"
#include "dirsearch.h"
#include "workqueue.h"
#include "object.h"
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
// 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);
layout.print_stats();
}
+ if (mapfile != NULL)
+ mapfile->close();
+
if (parameters->options().fatal_warnings()
&& errors.warning_count() > 0
&& errors.error_count() == 0)
--- /dev/null
+// 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.
--- /dev/null
+// 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)
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);
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);
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*
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.
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"));
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.
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));
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
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)
#include <vector>
#include "elfcpp.h"
+#include "mapfile.h"
#include "layout.h"
#include "reloc-types.h"
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.
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.
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>
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>
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>
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_;
};
{
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:
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
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:
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
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.
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.
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_;
};
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)
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_;
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_;
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
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
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
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
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)
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&);
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.
workqueue->queue_next(new Add_archive_symbols(this->symtab_,
this->layout_,
this->input_objects_,
+ this->mapfile_,
arch,
this->input_group_,
this->this_blocker_,
this->layout_,
this->dirpath_,
this->input_objects_,
+ this->mapfile_,
this->input_group_,
this->input_argument_,
input_file,
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;
}
workqueue->queue_soon(new Finish_group(this->input_objects_,
this->symtab_,
this->layout_,
+ this->mapfile_,
input_group,
saw_undefined,
this_blocker,
Task_lock_obj<Archive> tl(this, *p);
(*p)->add_symbols(this->symtab_, this->layout_,
- this->input_objects_);
+ this->input_objects_, this->mapfile_);
}
}
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"),
// 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();
Symbol_table* symtab_;
Layout* layout_;
Dirsearch* dirpath_;
+ Mapfile* mapfile_;
const Input_argument* input_argument_;
Input_group* input_group_;
Task_token* this_blocker_;
{
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)
{ }
Input_objects* input_objects_;
Symbol_table* symtab_;
Layout* layout_;
+ Mapfile* mapfile_;
Input_group* input_group_;
int saw_undefined_;
Task_token* this_blocker_;
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();
Layout* layout_;
Dirsearch* dirpath_;
Input_objects* input_objects_;
+ Mapfile* mapfile_;
Input_group* input_group_;
const Input_argument* input_argument_;
Input_file* input_file_;
- *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);
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
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)
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;
}
class Command_line;
class Symbol_table;
class Layout;
+class Mapfile;
class Input_argument;
class Input_objects;
class Input_group;
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);
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);
namespace gold
{
+class Mapfile;
class Object;
class Relobj;
template<int size, bool big_endian>
// 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.
// 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>
// 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),
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;