diff options
author | Ian Lance Taylor <ian@airs.com> | 2008-05-21 21:37:44 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2008-05-21 21:37:44 +0000 |
commit | 7d9e3d985416edccb274f0c704901839234cf4a9 (patch) | |
tree | 967f5b9545762a0a2ed3cabf4a2e0e4fb1fd6fd3 /gold/mapfile.cc | |
parent | 9f61f19bbf80ed99be35a8e482b914eabca1b3d8 (diff) | |
download | gdb-7d9e3d985416edccb274f0c704901839234cf4a9.zip gdb-7d9e3d985416edccb274f0c704901839234cf4a9.tar.gz gdb-7d9e3d985416edccb274f0c704901839234cf4a9.tar.bz2 |
* 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.
Diffstat (limited to 'gold/mapfile.cc')
-rw-r--r-- | gold/mapfile.cc | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/gold/mapfile.cc b/gold/mapfile.cc new file mode 100644 index 0000000..e053419 --- /dev/null +++ b/gold/mapfile.cc @@ -0,0 +1,405 @@ +// mapfile.cc -- map file generation for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cerrno> +#include <cstdio> +#include <cstring> + +#include "archive.h" +#include "symtab.h" +#include "output.h" +#include "mapfile.h" + +// This file holds the code for printing information to the map file. +// In general we try to produce pretty much the same format as GNU ld. + +namespace gold +{ + +// Mapfile constructor. + +Mapfile::Mapfile() + : map_file_(NULL), + printed_archive_header_(false), + printed_common_header_(false), + printed_memory_map_header_(false) +{ +} + +// Mapfile destructor. + +Mapfile::~Mapfile() +{ + if (this->map_file_ != NULL) + this->close(); +} + +// Open the map file. + +bool +Mapfile::open(const char* map_filename) +{ + if (strcmp(map_filename, "-") == 0) + this->map_file_ = stdout; + else + { + this->map_file_ = ::fopen(map_filename, "w"); + if (this->map_file_ == NULL) + { + gold_error(_("cannot open map file %s: %s"), map_filename, + strerror(errno)); + return false; + } + } + return true; +} + +// Close the map file. + +void +Mapfile::close() +{ + if (fclose(this->map_file_) != 0) + gold_error(_("cannot close map file: %s"), strerror(errno)); + this->map_file_ = NULL; +} + +// Advance to a column. + +void +Mapfile::advance_to_column(size_t from, size_t to) +{ + if (from >= to - 1) + { + putc('\n', this->map_file_); + from = 0; + } + while (from < to) + { + putc(' ', this->map_file_); + ++from; + } +} + +// Report about including a member from an archive. + +void +Mapfile::report_include_archive_member(const Archive* archive, + const std::string& member_name, + const Symbol* sym, const char* why) +{ + // We print a header before the list of archive members, mainly for + // GNU ld compatibility. + if (!this->printed_archive_header_) + { + fprintf(this->map_file_, + _("Archive member included because of file (symbol)\n\n")); + this->printed_archive_header_ = true; + } + + fprintf(this->map_file_, "%s(%s)", archive->file().filename().c_str(), + member_name.c_str()); + + size_t len = (archive->file().filename().length() + + member_name.length() + + 2); + this->advance_to_column(len, 30); + + if (sym == NULL) + fprintf(this->map_file_, "%s", why); + else + { + switch (sym->source()) + { + case Symbol::FROM_OBJECT: + fprintf(this->map_file_, "%s", sym->object()->name().c_str()); + break; + + case Symbol::IS_UNDEFINED: + fprintf(this->map_file_, "-u"); + break; + + default: + case Symbol::IN_OUTPUT_DATA: + case Symbol::IN_OUTPUT_SEGMENT: + case Symbol::IS_CONSTANT: + // We should only see an undefined symbol here. + gold_unreachable(); + } + + fprintf(this->map_file_, " (%s)", sym->name()); + } + + putc('\n', this->map_file_); +} + +// Report allocating a common symbol. + +void +Mapfile::report_allocate_common(const Symbol* sym, uint64_t symsize) +{ + if (!this->printed_common_header_) + { + fprintf(this->map_file_, _("\nAllocating common symbols\n")); + fprintf(this->map_file_, + _("Common symbol size file\n\n")); + this->printed_common_header_ = true; + } + + std::string demangled_name = sym->demangled_name(); + fprintf(this->map_file_, "%s", demangled_name.c_str()); + + this->advance_to_column(demangled_name.length(), 20); + + char buf[50]; + snprintf(buf, sizeof buf, "0x%llx", static_cast<unsigned long long>(symsize)); + fprintf(this->map_file_, "%s", buf); + + size_t len = strlen(buf); + while (len < 18) + { + putc(' ', this->map_file_); + ++len; + } + + fprintf(this->map_file_, "%s\n", sym->object()->name().c_str()); +} + +// The space we make for a section name. + +const size_t Mapfile::section_name_map_length = 16; + +// Print the memory map header if necessary. + +void +Mapfile::print_memory_map_header() +{ + if (!this->printed_memory_map_header_) + { + fprintf(this->map_file_, _("\nMemory map\n\n")); + this->printed_memory_map_header_ = true; + } +} + +// Print the symbols associated with an input section. + +template<int size, bool big_endian> +void +Mapfile::print_input_section_symbols( + const Sized_relobj<size, big_endian>* relobj, + unsigned int shndx) +{ + unsigned int symcount = relobj->symbol_count(); + for (unsigned int i = relobj->local_symbol_count(); i < symcount; ++i) + { + const Symbol* sym = relobj->global_symbol(i); + bool is_ordinary; + if (sym != NULL + && sym->source() == Symbol::FROM_OBJECT + && sym->object() == relobj + && sym->shndx(&is_ordinary) == shndx + && is_ordinary + && sym->is_defined()) + { + for (size_t i = 0; i < Mapfile::section_name_map_length; ++i) + putc(' ', this->map_file_); + const Sized_symbol<size>* ssym = + static_cast<const Sized_symbol<size>*>(sym); + fprintf(this->map_file_, + "0x%0*llx %s\n", + size / 4, + static_cast<unsigned long long>(ssym->value()), + sym->demangled_name().c_str()); + } + } +} + +// Print an input section. + +void +Mapfile::print_input_section(Relobj* relobj, unsigned int shndx) +{ + putc(' ', this->map_file_); + + std::string name = relobj->section_name(shndx); + fprintf(this->map_file_, "%s", name.c_str()); + + this->advance_to_column(name.length() + 1, Mapfile::section_name_map_length); + + Output_section* os; + uint64_t addr; + if (!relobj->is_section_included(shndx)) + { + os = NULL; + addr = 0; + } + else + { + section_offset_type offset; + os = relobj->output_section(shndx, &offset); + if (offset == -1) + addr = ~0ULL; + else + addr = os->address() + offset; + } + + char sizebuf[50]; + snprintf(sizebuf, sizeof sizebuf, "0x%llx", + static_cast<unsigned long long>(relobj->section_size(shndx))); + + fprintf(this->map_file_, "0x%0*llx %10s %s\n", + parameters->target().get_size() / 4, + static_cast<unsigned long long>(addr), sizebuf, + relobj->name().c_str()); + + if (os != NULL) + { + switch (parameters->size_and_endianness()) + { +#ifdef HAVE_TARGET_32_LITTLE + case Parameters::TARGET_32_LITTLE: + { + const Sized_relobj<32, false>* sized_relobj = + static_cast<Sized_relobj<32, false>*>(relobj); + this->print_input_section_symbols(sized_relobj, shndx); + } + break; +#endif +#ifdef HAVE_TARGET_32_BIG + case Parameters::TARGET_32_BIG: + { + const Sized_relobj<32, true>* sized_relobj = + static_cast<Sized_relobj<32, true>*>(relobj); + this->print_input_section_symbols(sized_relobj, shndx); + } + break; +#endif +#ifdef HAVE_TARGET_64_LITTLE + case Parameters::TARGET_64_LITTLE: + { + const Sized_relobj<64, false>* sized_relobj = + static_cast<Sized_relobj<64, false>*>(relobj); + this->print_input_section_symbols(sized_relobj, shndx); + } + break; +#endif +#ifdef HAVE_TARGET_64_BIG + case Parameters::TARGET_64_BIG: + { + const Sized_relobj<64, true>* sized_relobj = + static_cast<Sized_relobj<64, true>*>(relobj); + this->print_input_section_symbols(sized_relobj, shndx); + } + break; +#endif + default: + gold_unreachable(); + } + } +} + +// Print an Output_section_data. This is printed to look like an +// input section. + +void +Mapfile::print_output_data(const Output_data* od, const char* name) +{ + this->print_memory_map_header(); + + putc(' ', this->map_file_); + + fprintf(this->map_file_, "%s", name); + + this->advance_to_column(strlen(name) + 1, Mapfile::section_name_map_length); + + char sizebuf[50]; + snprintf(sizebuf, sizeof sizebuf, "0x%llx", + static_cast<unsigned long long>(od->data_size())); + + fprintf(this->map_file_, "0x%0*llx %10s\n", + parameters->target().get_size() / 4, + static_cast<unsigned long long>(od->address()), + sizebuf); +} + +// Print the discarded input sections. + +void +Mapfile::print_discarded_sections(const Input_objects* input_objects) +{ + bool printed_header = false; + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Relobj* relobj = *p; + unsigned int shnum = relobj->shnum(); + for (unsigned int i = 0; i < shnum; ++i) + { + unsigned int sh_type = relobj->section_type(i); + if ((sh_type == elfcpp::SHT_PROGBITS + || sh_type == elfcpp::SHT_NOBITS + || sh_type == elfcpp::SHT_GROUP) + && !relobj->is_section_included(i)) + { + if (!printed_header) + { + fprintf(this->map_file_, _("\nDiscarded input sections\n\n")); + printed_header = true; + } + + this->print_input_section(relobj, i); + } + } + } +} + +// Print an output section. + +void +Mapfile::print_output_section(const Output_section* os) +{ + this->print_memory_map_header(); + + fprintf(this->map_file_, "\n%s", os->name()); + + this->advance_to_column(strlen(os->name()), Mapfile::section_name_map_length); + + char sizebuf[50]; + snprintf(sizebuf, sizeof sizebuf, "0x%llx", + static_cast<unsigned long long>(os->data_size())); + + fprintf(this->map_file_, "0x%0*llx %10s", + parameters->target().get_size() / 4, + static_cast<unsigned long long>(os->address()), sizebuf); + + if (os->has_load_address()) + fprintf(this->map_file_, " load address 0x%-*llx", + parameters->target().get_size() / 4, + static_cast<unsigned long long>(os->load_address())); + + putc('\n', this->map_file_); +} + +} // End namespace gold. |