mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-21 01:53:05 +00:00
* 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:
parent
9f61f19bbf
commit
7d9e3d9854
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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@
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
26
gold/gold.cc
26
gold/gold.cc
@ -94,9 +94,9 @@ class Middle_runner : public Task_function_runner
|
||||
Middle_runner(const General_options& options,
|
||||
const Input_objects* input_objects,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout)
|
||||
Layout* layout, Mapfile* mapfile)
|
||||
: options_(options), input_objects_(input_objects), symtab_(symtab),
|
||||
layout_(layout)
|
||||
layout_(layout), mapfile_(mapfile)
|
||||
{ }
|
||||
|
||||
void
|
||||
@ -107,13 +107,14 @@ class Middle_runner : public Task_function_runner
|
||||
const Input_objects* input_objects_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
Mapfile* mapfile_;
|
||||
};
|
||||
|
||||
void
|
||||
Middle_runner::run(Workqueue* workqueue, const Task* task)
|
||||
{
|
||||
queue_middle_tasks(this->options_, task, this->input_objects_, this->symtab_,
|
||||
this->layout_, workqueue);
|
||||
this->layout_, workqueue, this->mapfile_);
|
||||
}
|
||||
|
||||
// Queue up the initial set of tasks for this link job.
|
||||
@ -123,7 +124,7 @@ queue_initial_tasks(const General_options& options,
|
||||
Dirsearch& search_path,
|
||||
const Command_line& cmdline,
|
||||
Workqueue* workqueue, Input_objects* input_objects,
|
||||
Symbol_table* symtab, Layout* layout)
|
||||
Symbol_table* symtab, Layout* layout, Mapfile* mapfile)
|
||||
{
|
||||
if (cmdline.begin() == cmdline.end())
|
||||
gold_fatal(_("no input files"));
|
||||
@ -145,15 +146,16 @@ queue_initial_tasks(const General_options& options,
|
||||
Task_token* next_blocker = new Task_token(true);
|
||||
next_blocker->add_blocker();
|
||||
workqueue->queue(new Read_symbols(options, input_objects, symtab, layout,
|
||||
&search_path, &*p, NULL, this_blocker,
|
||||
next_blocker));
|
||||
&search_path, mapfile, &*p, NULL,
|
||||
this_blocker, next_blocker));
|
||||
this_blocker = next_blocker;
|
||||
}
|
||||
|
||||
workqueue->queue(new Task_function(new Middle_runner(options,
|
||||
input_objects,
|
||||
symtab,
|
||||
layout),
|
||||
layout,
|
||||
mapfile),
|
||||
this_blocker,
|
||||
"Task_function Middle_runner"));
|
||||
}
|
||||
@ -168,7 +170,8 @@ queue_middle_tasks(const General_options& options,
|
||||
const Input_objects* input_objects,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Workqueue* workqueue)
|
||||
Workqueue* workqueue,
|
||||
Mapfile* mapfile)
|
||||
{
|
||||
// We have to support the case of not seeing any input objects, and
|
||||
// generate an empty file. Existing builds depend on being able to
|
||||
@ -272,8 +275,8 @@ queue_middle_tasks(const General_options& options,
|
||||
if (parameters->options().define_common())
|
||||
{
|
||||
blocker->add_blocker();
|
||||
workqueue->queue(new Allocate_commons_task(symtab, layout, symtab_lock,
|
||||
blocker));
|
||||
workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile,
|
||||
symtab_lock, blocker));
|
||||
}
|
||||
|
||||
// When all those tasks are complete, we can start laying out the
|
||||
@ -284,7 +287,8 @@ queue_middle_tasks(const General_options& options,
|
||||
input_objects,
|
||||
symtab,
|
||||
target,
|
||||
layout),
|
||||
layout,
|
||||
mapfile),
|
||||
blocker,
|
||||
"Task_function Layout_task_runner"));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
19
gold/main.cc
19
gold/main.cc
@ -22,6 +22,7 @@
|
||||
|
||||
#include "gold.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HAVE_MALLINFO
|
||||
@ -34,6 +35,7 @@
|
||||
#include "options.h"
|
||||
#include "parameters.h"
|
||||
#include "errors.h"
|
||||
#include "mapfile.h"
|
||||
#include "dirsearch.h"
|
||||
#include "workqueue.h"
|
||||
#include "object.h"
|
||||
@ -165,6 +167,18 @@ main(int argc, char** argv)
|
||||
write_debug_script(command_line.options().output_file_name(),
|
||||
program_name, args.c_str());
|
||||
|
||||
// If the user asked for a map file, open it.
|
||||
Mapfile* mapfile = NULL;
|
||||
if (command_line.options().user_set_Map())
|
||||
{
|
||||
mapfile = new Mapfile();
|
||||
if (!mapfile->open(command_line.options().Map()))
|
||||
{
|
||||
delete mapfile;
|
||||
mapfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// The GNU linker ignores version scripts when generating
|
||||
// relocatable output. If we are not compatible, then we break the
|
||||
// Linux kernel build, which uses a linker script with -r which must
|
||||
@ -198,7 +212,7 @@ main(int argc, char** argv)
|
||||
// Queue up the first set of tasks.
|
||||
queue_initial_tasks(command_line.options(), search_path,
|
||||
command_line, &workqueue, &input_objects,
|
||||
&symtab, &layout);
|
||||
&symtab, &layout, mapfile);
|
||||
|
||||
// Run the main task processing loop.
|
||||
workqueue.process(0);
|
||||
@ -220,6 +234,9 @@ main(int argc, char** argv)
|
||||
layout.print_stats();
|
||||
}
|
||||
|
||||
if (mapfile != NULL)
|
||||
mapfile->close();
|
||||
|
||||
if (parameters->options().fatal_warnings()
|
||||
&& errors.warning_count() > 0
|
||||
&& errors.error_count() == 0)
|
||||
|
405
gold/mapfile.cc
Normal file
405
gold/mapfile.cc
Normal 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
113
gold/mapfile.h
Normal 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)
|
10
gold/merge.h
10
gold/merge.h
@ -283,6 +283,11 @@ class Output_merge_data : public Output_merge_base
|
||||
void
|
||||
do_write_to_buffer(unsigned char*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** merge constants")); }
|
||||
|
||||
// Print merge stats to stderr.
|
||||
void
|
||||
do_print_merge_stats(const char* section_name);
|
||||
@ -400,6 +405,11 @@ class Output_merge_string : public Output_merge_base
|
||||
void
|
||||
do_write_to_buffer(unsigned char*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** merge strings")); }
|
||||
|
||||
// Print merge stats to stderr.
|
||||
void
|
||||
do_print_merge_stats(const char* section_name);
|
||||
|
@ -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*
|
||||
|
@ -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.
|
||||
|
@ -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"));
|
||||
|
@ -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)
|
||||
|
155
gold/output.h
155
gold/output.h
@ -27,6 +27,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "elfcpp.h"
|
||||
#include "mapfile.h"
|
||||
#include "layout.h"
|
||||
#include "reloc-types.h"
|
||||
|
||||
@ -240,6 +241,11 @@ class Output_data
|
||||
is_data_size_valid() const
|
||||
{ return this->is_data_size_valid_; }
|
||||
|
||||
// Print information to the map file.
|
||||
void
|
||||
print_to_mapfile(Mapfile* mapfile) const
|
||||
{ return this->do_print_to_mapfile(mapfile); }
|
||||
|
||||
protected:
|
||||
// Functions that child classes may or in some cases must implement.
|
||||
|
||||
@ -316,6 +322,12 @@ class Output_data
|
||||
do_tls_offset() const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Print to the map file. This only needs to be implemented by
|
||||
// classes which may appear in a PT_LOAD segment.
|
||||
virtual void
|
||||
do_print_to_mapfile(Mapfile*) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Functions that child classes may call.
|
||||
|
||||
// Set the size of the data.
|
||||
@ -397,6 +409,11 @@ class Output_section_headers : public Output_data
|
||||
do_addralign() const
|
||||
{ return Output_data::default_alignment(); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** section headers")); }
|
||||
|
||||
private:
|
||||
// Write the data to the file with the right size and endianness.
|
||||
template<int size, bool big_endian>
|
||||
@ -428,6 +445,11 @@ class Output_segment_headers : public Output_data
|
||||
do_addralign() const
|
||||
{ return Output_data::default_alignment(); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** segment headers")); }
|
||||
|
||||
private:
|
||||
// Write the data to the file with the right size and endianness.
|
||||
template<int size, bool big_endian>
|
||||
@ -462,6 +484,11 @@ class Output_file_header : public Output_data
|
||||
do_addralign() const
|
||||
{ return Output_data::default_alignment(); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** file header")); }
|
||||
|
||||
private:
|
||||
// Write the data to the file with the right size and endianness.
|
||||
template<int size, bool big_endian>
|
||||
@ -663,6 +690,11 @@ class Output_data_const : public Output_section_data
|
||||
do_write_to_buffer(unsigned char* buffer)
|
||||
{ memcpy(buffer, this->data_.data(), this->data_.size()); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** fill")); }
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
};
|
||||
@ -674,8 +706,9 @@ class Output_data_const_buffer : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_data_const_buffer(const unsigned char* p, off_t len,
|
||||
uint64_t addralign)
|
||||
: Output_section_data(len, addralign), p_(p)
|
||||
uint64_t addralign, const char* map_name)
|
||||
: Output_section_data(len, addralign),
|
||||
p_(p), map_name_(map_name)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
@ -688,8 +721,17 @@ class Output_data_const_buffer : public Output_section_data
|
||||
do_write_to_buffer(unsigned char* buffer)
|
||||
{ memcpy(buffer, this->p_, this->data_size()); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _(this->map_name_)); }
|
||||
|
||||
private:
|
||||
// The data to output.
|
||||
const unsigned char* p_;
|
||||
// Name to use in a map file. Maps are a rarely used feature, but
|
||||
// the space usage is minor as aren't very many of these objects.
|
||||
const char* map_name_;
|
||||
};
|
||||
|
||||
// A place holder for a fixed amount of data written out via some
|
||||
@ -698,8 +740,10 @@ class Output_data_const_buffer : public Output_section_data
|
||||
class Output_data_fixed_space : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_data_fixed_space(off_t data_size, uint64_t addralign)
|
||||
: Output_section_data(data_size, addralign)
|
||||
Output_data_fixed_space(off_t data_size, uint64_t addralign,
|
||||
const char* map_name)
|
||||
: Output_section_data(data_size, addralign),
|
||||
map_name_(map_name)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
@ -708,6 +752,16 @@ class Output_data_fixed_space : public Output_section_data
|
||||
void
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _(this->map_name_)); }
|
||||
|
||||
private:
|
||||
// Name to use in a map file. Maps are a rarely used feature, but
|
||||
// the space usage is minor as aren't very many of these objects.
|
||||
const char* map_name_;
|
||||
};
|
||||
|
||||
// A place holder for variable sized data written out via some other
|
||||
@ -716,8 +770,9 @@ class Output_data_fixed_space : public Output_section_data
|
||||
class Output_data_space : public Output_section_data_build
|
||||
{
|
||||
public:
|
||||
explicit Output_data_space(uint64_t addralign)
|
||||
: Output_section_data_build(addralign)
|
||||
explicit Output_data_space(uint64_t addralign, const char* map_name)
|
||||
: Output_section_data_build(addralign),
|
||||
map_name_(map_name)
|
||||
{ }
|
||||
|
||||
// Set the alignment.
|
||||
@ -731,6 +786,38 @@ class Output_data_space : public Output_section_data_build
|
||||
void
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _(this->map_name_)); }
|
||||
|
||||
private:
|
||||
// Name to use in a map file. Maps are a rarely used feature, but
|
||||
// the space usage is minor as aren't very many of these objects.
|
||||
const char* map_name_;
|
||||
};
|
||||
|
||||
// Fill fixed space with zeroes. This is just like
|
||||
// Output_data_fixed_space, except that the map name is known.
|
||||
|
||||
class Output_data_zero_fill : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_data_zero_fill(off_t data_size, uint64_t addralign)
|
||||
: Output_section_data(data_size, addralign)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
// There is no data to write out.
|
||||
void
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, "** zero fill"); }
|
||||
};
|
||||
|
||||
// A string table which goes into an output section.
|
||||
@ -757,6 +844,11 @@ class Output_data_strtab : public Output_section_data
|
||||
do_write_to_buffer(unsigned char* buffer)
|
||||
{ this->strtab_->write_to_buffer(buffer, this->data_size()); }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** string table")); }
|
||||
|
||||
private:
|
||||
Stringpool* strtab_;
|
||||
};
|
||||
@ -1056,6 +1148,16 @@ class Output_data_reloc_base : public Output_section_data_build
|
||||
void
|
||||
do_adjust_output_section(Output_section *os);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{
|
||||
mapfile->print_output_data(this,
|
||||
(dynamic
|
||||
? _("** dynamic relocs")
|
||||
: _("** relocs")));
|
||||
}
|
||||
|
||||
// Add a relocation entry.
|
||||
void
|
||||
add(Output_data *od, const Output_reloc_type& reloc)
|
||||
@ -1380,6 +1482,11 @@ class Output_relocatable_relocs : public Output_section_data
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** relocs")); }
|
||||
|
||||
private:
|
||||
// The relocs associated with this input section.
|
||||
Relocatable_relocs* rr_;
|
||||
@ -1400,6 +1507,11 @@ class Output_data_group : public Output_section_data
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** group")); }
|
||||
|
||||
private:
|
||||
// The input object.
|
||||
Sized_relobj<size, big_endian>* relobj_;
|
||||
@ -1502,6 +1614,11 @@ class Output_data_got : public Output_section_data_build
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** GOT")); }
|
||||
|
||||
private:
|
||||
// This POD class holds a single GOT entry.
|
||||
class Got_entry
|
||||
@ -1639,6 +1756,11 @@ class Output_data_dynamic : public Output_section_data
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** dynamic")); }
|
||||
|
||||
private:
|
||||
// This POD class holds a single dynamic entry.
|
||||
class Dynamic_entry
|
||||
@ -1752,6 +1874,11 @@ class Output_symtab_xindex : public Output_section_data
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** symtab xindex")); }
|
||||
|
||||
private:
|
||||
template<bool big_endian>
|
||||
void
|
||||
@ -2262,6 +2389,10 @@ class Output_section : public Output_data
|
||||
do_finalize_name(Layout*)
|
||||
{ }
|
||||
|
||||
// Print to the map file.
|
||||
virtual void
|
||||
do_print_to_mapfile(Mapfile*) const;
|
||||
|
||||
// Record that this section requires postprocessing after all
|
||||
// relocations have been applied. This is called by a child class.
|
||||
void
|
||||
@ -2439,6 +2570,10 @@ class Output_section : public Output_data
|
||||
void
|
||||
write_to_buffer(unsigned char*);
|
||||
|
||||
// Print to a map file.
|
||||
void
|
||||
print_to_mapfile(Mapfile*) const;
|
||||
|
||||
// Print statistics about merge sections to stderr.
|
||||
void
|
||||
print_merge_stats(const char* section_name)
|
||||
@ -2802,6 +2937,10 @@ class Output_segment
|
||||
write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
|
||||
unsigned int* pshndx) const;
|
||||
|
||||
// Print the output sections in the map file.
|
||||
void
|
||||
print_sections_to_mapfile(Mapfile*) const;
|
||||
|
||||
private:
|
||||
Output_segment(const Output_segment&);
|
||||
Output_segment& operator=(const Output_segment&);
|
||||
@ -2844,6 +2983,10 @@ class Output_segment
|
||||
const Output_data_list*, unsigned char* v,
|
||||
unsigned int* pshdx) const;
|
||||
|
||||
// Print a section list to the mapfile.
|
||||
void
|
||||
print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const;
|
||||
|
||||
// The list of output data with contents attached to this segment.
|
||||
Output_data_list output_data_;
|
||||
// The list of output data without contents attached to this segment.
|
||||
|
@ -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"),
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user