|  | // binary_unittest.cc -- test Binary_to_elf | 
|  |  | 
|  | // Copyright (C) 2008-2017 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 <unistd.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  | #include <fcntl.h> | 
|  |  | 
|  | #include "elfcpp.h" | 
|  | #include "parameters.h" | 
|  | #include "errors.h" | 
|  | #include "options.h" | 
|  | #include "binary.h" | 
|  | #include "object.h" | 
|  | #include "descriptors.h" | 
|  |  | 
|  | #include "test.h" | 
|  | #include "testfile.h" | 
|  |  | 
|  | namespace | 
|  | { | 
|  |  | 
|  | ssize_t | 
|  | read_all (int fd, unsigned char* buf, ssize_t size) | 
|  | { | 
|  | ssize_t total_read = 0; | 
|  | while (size > 0) | 
|  | { | 
|  | ssize_t nread = ::read(fd, buf, size); | 
|  | if (nread < 0) | 
|  | return nread; | 
|  | if (nread == 0) | 
|  | break; | 
|  | buf += nread; | 
|  | size -= nread; | 
|  | total_read += nread; | 
|  | } | 
|  | return total_read; | 
|  | } | 
|  |  | 
|  | } // End anonymous namespace. | 
|  |  | 
|  | namespace gold_testsuite | 
|  | { | 
|  |  | 
|  | using namespace gold; | 
|  |  | 
|  | template<int size, bool big_endian> | 
|  | bool | 
|  | Sized_binary_test() | 
|  | { | 
|  | parameters_clear_target(); | 
|  | // We need a pretend Task. | 
|  | const Task* task = reinterpret_cast<const Task*>(-1); | 
|  |  | 
|  | // Use the executable itself as the binary data. | 
|  | struct stat st; | 
|  | CHECK(::stat(gold::program_name, &st) == 0); | 
|  | int o = open_descriptor(-1, gold::program_name, O_RDONLY); | 
|  | CHECK(o >= 0); | 
|  | unsigned char* filedata = new unsigned char[st.st_size]; | 
|  | CHECK(read_all(o, filedata, st.st_size) == static_cast<ssize_t>(st.st_size)); | 
|  | CHECK(::close(o) == 0); | 
|  |  | 
|  | Binary_to_elf binary(static_cast<elfcpp::EM>(0xffff), size, big_endian, | 
|  | gold::program_name); | 
|  |  | 
|  | CHECK(binary.convert(task)); | 
|  |  | 
|  | Input_file input_file(task, "test.o", binary.converted_data(), | 
|  | binary.converted_size()); | 
|  | Object* object = make_elf_object("test.o", &input_file, 0, | 
|  | binary.converted_data(), | 
|  | binary.converted_size(), NULL); | 
|  | CHECK(object != NULL); | 
|  | if (object == NULL) | 
|  | return false; | 
|  |  | 
|  | CHECK(!object->is_dynamic()); | 
|  | CHECK(object->shnum() == 5); | 
|  | CHECK(object->section_name(1) == ".data"); | 
|  | CHECK(object->section_flags(1) == (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE)); | 
|  | section_size_type len; | 
|  | const unsigned char* contents = object->section_contents(1, &len, false); | 
|  | CHECK(len == convert_to_section_size_type(st.st_size)); | 
|  | CHECK(memcmp(filedata, contents, len) == 0); | 
|  |  | 
|  | // Force the symbols to be read internally, so that | 
|  | // symbol_section_and_value will work. | 
|  | Read_symbols_data sd; | 
|  | object->read_symbols(&sd); | 
|  | delete sd.section_headers; | 
|  | sd.section_headers = NULL; | 
|  | delete sd.section_names; | 
|  | sd.section_names = NULL; | 
|  | delete sd.symbols; | 
|  | sd.symbols = NULL; | 
|  | delete sd.symbol_names; | 
|  | sd.symbol_names = NULL; | 
|  |  | 
|  | Sized_relobj_file<size, big_endian>* relobj = | 
|  | static_cast<Sized_relobj_file<size, big_endian>*>(object); | 
|  | typename Sized_relobj_file<size, big_endian>::Address value; | 
|  | bool is_ordinary; | 
|  | CHECK(relobj->symbol_section_and_value(0, &value, &is_ordinary) == 0); | 
|  | CHECK(is_ordinary); | 
|  | CHECK(value == 0); | 
|  | CHECK(relobj->symbol_section_and_value(1, &value, &is_ordinary) == 1); | 
|  | CHECK(is_ordinary); | 
|  | CHECK(value == 0); | 
|  | CHECK(relobj->symbol_section_and_value(2, &value, &is_ordinary) == 1); | 
|  | CHECK(is_ordinary); | 
|  | CHECK(static_cast<off_t>(value) == st.st_size); | 
|  | CHECK(relobj->symbol_section_and_value(3, &value, &is_ordinary) | 
|  | == elfcpp::SHN_ABS); | 
|  | CHECK(!is_ordinary); | 
|  | CHECK(static_cast<off_t>(value) == st.st_size); | 
|  |  | 
|  | object->unlock(task); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool | 
|  | Binary_test(Test_report*) | 
|  | { | 
|  | Errors errors(gold::program_name); | 
|  | set_parameters_errors(&errors); | 
|  |  | 
|  | General_options options; | 
|  | set_parameters_options(&options); | 
|  |  | 
|  | int fail = 0; | 
|  |  | 
|  | #ifdef HAVE_TARGET_32_LITTLE | 
|  | if (!Sized_binary_test<32, false>()) | 
|  | ++fail; | 
|  | CHECK(¶meters->target() == target_test_pointer_32_little); | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TARGET_32_BIG | 
|  | if (!Sized_binary_test<32, true>()) | 
|  | ++fail; | 
|  | CHECK(¶meters->target() == target_test_pointer_32_big); | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TARGET_64_LITTLE | 
|  | if (!Sized_binary_test<64, false>()) | 
|  | ++fail; | 
|  | CHECK(¶meters->target() == target_test_pointer_64_little); | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TARGET_64_BIG | 
|  | if (!Sized_binary_test<64, true>()) | 
|  | ++fail; | 
|  | CHECK(¶meters->target() == target_test_pointer_64_big); | 
|  | #endif | 
|  |  | 
|  | return fail == 0; | 
|  | } | 
|  |  | 
|  | Register_test binary_register("Binary", Binary_test); | 
|  |  | 
|  | } // End namespace gold_testsuite. |