// inremental.cc -- incremental linking test/deubg tool // Copyright 2009 Free Software Foundation, Inc. // Written by Rafael Avila de Espindola // 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 "gold.h" #include #include #include "incremental.h" namespace gold { class Output_file; } using namespace gold; int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } const char* filename = argv[1]; Output_file* file = new Output_file(filename); bool t = file->open_for_modification(); if (!t) { fprintf(stderr, "%s: open_for_modification(%s): %s\n", argv[0], filename, strerror(errno)); return 1; } Incremental_binary* inc = open_incremental_binary(file); if (inc == NULL) { fprintf(stderr, "%s: open_incremental_binary(%s): %s\n", argv[0], filename, strerror(errno)); return 1; } unsigned int strtab_shndx; Incremental_binary::Location location; t = inc->find_incremental_inputs_section(&location, &strtab_shndx); if (!t) { fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv[0], filename); 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 (p); const Incremental_inputs_entry_data* incremental_inputs = reinterpret_cast (p + sizeof(Incremental_inputs_header_data)); if (incremental_header->version != 1) { fprintf(stderr, "%s: %s: unknown incremental version %d\n", argv[0], filename, 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, "%s: %s: invalid string table section %u (type %d != %d)\n", argv[0], filename, strtab_shndx, elf_file.section_type(strtab_shndx), elfcpp::SHT_STRTAB); 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, "%s: %s: failed to get link command line: %zu out of range\n", argv[0], filename, static_cast(incremental_header->command_line_offset)); 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,"%s: %s: failed to get file name for object %u:" " %zu out of range\n", argv[0], filename, i, static_cast(input->filename_offset)); return 1; } printf(" %s\n", objname); printf(" Timestamp sec = %llu\n", static_cast(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"); if (input->data_offset != 0) { fprintf(stderr,"%s: %s: %u is a script but offset is not zero", argv[0], filename, i); return 1; } break; case INCREMENTAL_INPUT_INVALID: default: fprintf(stderr, "%s: invalid file type for object %u: %d\n", argv[0], i, input->input_type); return 1; } } return 0; }