This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch][gold] Add a tool for dumping incremental linking information
- From: Rafael Espindola <espindola at google dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: Ian Lance Taylor <iant at google dot com>, Mikolaj Zalewski <mikolajz at google dot com>
- Date: Mon, 23 Nov 2009 17:11:25 -0500
- Subject: [patch][gold] Add a tool for dumping incremental linking information
The attached patch adds a simple tool that dumps the incremental
linking information. I intend to use it for testing. I should have a
patch that actually uses it tomorrow or the day after.
Once incremental linking is more mature, I will port this into
readelf. For now it is a standalone tool and I have used some gold
classes for convenience. Let me know if you would like it to be fully
independent from the start.
I have also included a small fix. The file elfcpp_file.h uses the
definition of Elf_sizes, so it should include elfcpp.h to get it.
elfcpp/
2009-11-23 Rafael Avila de Espindola <espindola@google.com>
* elfcpp_file.h: Include elfcpp.h.
gold/
2009-11-23 Rafael Avila de Espindola <espindola@google.com>
* Makefile.am: Build incremental-dump
* Makefile.in: Regenerate.
* incremental-dump.cc: New.
Cheers,
--
Rafael Ãvila de EspÃndola
diff --git a/elfcpp/elfcpp_file.h b/elfcpp/elfcpp_file.h
index cc61622..39347ae 100644
--- a/elfcpp/elfcpp_file.h
+++ b/elfcpp/elfcpp_file.h
@@ -60,6 +60,8 @@
#include <cstdio>
#include <cstring>
+#include "elfcpp.h" //for Elf_sizes
+
namespace elfcpp
{
diff --git a/gold/Makefile.am b/gold/Makefile.am
index 8d8b617..175bd23 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -34,7 +34,7 @@ AM_YFLAGS = -d
am__skiplex =
am__skipyacc =
-noinst_PROGRAMS = ld-new
+noinst_PROGRAMS = ld-new incremental-dump
noinst_LIBRARIES = libgold.a
CCFILES = \
@@ -151,6 +151,10 @@ ld_new_LDADD = $(ldadd_var)
EXTRA_ld_new_SOURCES = $(TARGETSOURCES)
+incremental_dump_SOURCES = incremental-dump.cc
+incremental_dump_DEPENDENCIES = $(TARGETOBJS) libgold.a $(LIBIBERTY)
+incremental_dump_LDADD = $(TARGETOBJS) libgold.a $(LIBIBERTY)
+
# Use an explicit dependency for the bison generated header file.
expression.$(OBJEXT): yyscript.h
script-sections.$(OBJEXT): yyscript.h
diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc
new file mode 100644
index 0000000..e65cb70
--- /dev/null
+++ b/gold/incremental-dump.cc
@@ -0,0 +1,200 @@
+// inremental.cc -- incremental linking test/deubg tool
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Rafael Avila de Espindola <rafael.espindola@gmail.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.
+
+
+// This file is a (still incomplete) test/debug tool that should display
+// all information available in the incremental linking sections in a
+// format that is easy to read.
+// Once the format is a bit more stable, this should probably be moved to
+// readelf. Because of that, the use of gold's data structures and functions
+// is just a short term convenience and not a design decision.
+
+#include <stdio.h>
+#include "gold.h"
+#include "incremental.h"
+
+namespace gold
+{
+ class Output_file;
+}
+
+using namespace gold;
+
+// Header of the .gnu_incremental_input section.
+struct Incremental_inputs_header_data
+{
+ // Incremental linker version.
+ elfcpp::Elf_Word version;
+
+ // Numer of input files in the link.
+ elfcpp::Elf_Word input_file_count;
+
+ // Offset of command line options in .gnu_incremental_strtab.
+ elfcpp::Elf_Word command_line_offset;
+
+ // Padding.
+ elfcpp::Elf_Word reserved;
+};
+
+// Data stored in .gnu_incremental_input after the header for each of the
+// Incremental_input_header_data::input_file_count input entries.
+struct Incremental_inputs_entry_data
+{
+ // Offset of file name in .gnu_incremental_strtab section.
+ elfcpp::Elf_Word filename_offset;
+
+ // Offset of data in .gnu_incremental_input.
+ elfcpp::Elf_Word data_offset;
+
+ // Timestamp (in seconds).
+ elfcpp::Elf_Xword timestamp_sec;
+
+ // Nano-second part of timestamp (if supported).
+ elfcpp::Elf_Word timestamp_nsec;
+
+ // Type of the input entry.
+ elfcpp::Elf_Half input_type;
+
+ // Padding.
+ elfcpp::Elf_Half reserved;
+};
+
+int
+main(int argc, char** argv)
+{
+ if (argc != 2)
+ {
+ fprintf(stderr, "usage: incremental-dump <file>\n");
+ return 1;
+ }
+ const char* filename = argv[1];
+
+ Output_file* file = new Output_file(filename);
+
+ bool t = file->open_for_modification();
+ if (!t)
+ {
+ fprintf(stderr, "failed to open file %s\n", filename);
+ return 1;
+ }
+
+ Incremental_binary* inc = open_incremental_binary(file);
+
+ if (inc == NULL)
+ {
+ fprintf(stderr, "Failed to open file %s\n", filename);
+ return 1;
+ }
+
+ unsigned int strtab_shndx;
+ Incremental_binary::Location location;
+
+ t = inc->find_incremental_inputs_section(&location, &strtab_shndx);
+ if (!t)
+ {
+ fprintf(stderr, "File has no .gnu_incremental_inputs section\n");
+ return 1;
+ }
+
+ Incremental_binary::View inputs_view(inc->view(location));
+ const unsigned char *p = inputs_view.data();
+
+ const Incremental_inputs_header_data* incremental_header =
+ reinterpret_cast<const Incremental_inputs_header_data*> (p);
+
+ const Incremental_inputs_entry_data* incremental_inputs =
+ reinterpret_cast<const Incremental_inputs_entry_data*>
+ (p + sizeof(Incremental_inputs_header_data));
+
+ if (incremental_header->version != 1)
+ {
+ fprintf(stderr, "unknown version %d\n", incremental_header->version);
+ return 1;
+ }
+
+ elfcpp::Elf_file<64, false, Incremental_binary> elf_file(inc);
+
+ if (elf_file.section_type(strtab_shndx) != elfcpp::SHT_STRTAB)
+ {
+ fprintf(stderr, "invalid string table section\n");
+ return 1;
+ }
+
+ Incremental_binary::Location
+ strtab_location(elf_file.section_contents(strtab_shndx));
+
+ Incremental_binary::View strtab_view(inc->view(strtab_location));
+ p = strtab_view.data();
+
+ elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
+ const char* command_line;
+ t = strtab.get_c_string(incremental_header->command_line_offset,
+ &command_line);
+
+ if (!t)
+ {
+ fprintf(stderr, "Failed to get the link command line\n");
+ return 1;
+ }
+
+ printf("Link command line: %s\n", command_line);
+
+ printf("input files:\n");
+ for (unsigned i = 0; i < incremental_header->input_file_count; ++i)
+ {
+ const Incremental_inputs_entry_data* input = &incremental_inputs[i];
+ const char *objname;
+
+ t = strtab.get_c_string(input->filename_offset, &objname);
+ if (!t)
+ {
+ fprintf(stderr, "Failed to get the name of an object file\n");
+ return 1;
+ }
+ printf(" %s\n", objname);
+ printf(" timestamp sec = %ld\n", input->timestamp_sec);
+ printf(" timestamp nsec = %d\n", input->timestamp_nsec);
+ printf(" type = ");
+ // TODO: print the data at input->data_offset once we have it.
+ switch (input->input_type)
+ {
+ case INCREMENTAL_INPUT_OBJECT:
+ printf("object\n");
+ break;
+ case INCREMENTAL_INPUT_ARCHIVE:
+ printf("archive\n");
+ break;
+ case INCREMENTAL_INPUT_SHARED_LIBRARY:
+ printf("shared library\n");
+ break;
+ case INCREMENTAL_INPUT_SCRIPT:
+ printf("linker script\n");
+ break;
+ case INCREMENTAL_INPUT_INVALID:
+ default:
+ fprintf(stderr, "Unknown file type\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}