X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=gold%2Fmapfile.cc;fp=gold%2Fmapfile.cc;h=a3ba52ba611b73b69ec8245549704701741ad153;hp=0000000000000000000000000000000000000000;hb=d5da4f291af551c0b8b79e1d4a9b173d60e5c10e;hpb=7b5ea4fcdf2819e070665ab5610f8b48e3867c10 diff --git a/gold/mapfile.cc b/gold/mapfile.cc new file mode 100644 index 0000000..a3ba52b --- /dev/null +++ b/gold/mapfile.cc @@ -0,0 +1,398 @@ +// mapfile.cc -- map file generation for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// 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 +#include +#include + +#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 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", member_name.c_str()); + + this->advance_to_column(member_name.length(), 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(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 +void +Mapfile::print_input_section_symbols( + const Sized_relobj* 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* ssym = + static_cast*>(sym); + fprintf(this->map_file_, + "0x%0*llx %s\n", + size / 4, + static_cast(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 + { + os = relobj->output_section(shndx); + addr = relobj->output_section_offset(shndx); + if (addr != -1ULL) + addr += os->address(); + } + + char sizebuf[50]; + snprintf(sizebuf, sizeof sizebuf, "0x%llx", + static_cast(relobj->section_size(shndx))); + + fprintf(this->map_file_, "0x%0*llx %10s %s\n", + parameters->target().get_size() / 4, + static_cast(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*>(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*>(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*>(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*>(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(od->data_size())); + + fprintf(this->map_file_, "0x%0*llx %10s\n", + parameters->target().get_size() / 4, + static_cast(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(os->data_size())); + + fprintf(this->map_file_, "0x%0*llx %10s", + parameters->target().get_size() / 4, + static_cast(os->address()), sizebuf); + + if (os->has_load_address()) + fprintf(this->map_file_, " load address 0x%-*llx", + parameters->target().get_size() / 4, + static_cast(os->load_address())); + + putc('\n', this->map_file_); +} + +} // End namespace gold.