1*2a6b7db3Sskrll // binary.cc -- binary input files for gold 2*2a6b7db3Sskrll 3*2a6b7db3Sskrll // Copyright 2008 Free Software Foundation, Inc. 4*2a6b7db3Sskrll // Written by Ian Lance Taylor <iant@google.com>. 5*2a6b7db3Sskrll 6*2a6b7db3Sskrll // This file is part of gold. 7*2a6b7db3Sskrll 8*2a6b7db3Sskrll // This program is free software; you can redistribute it and/or modify 9*2a6b7db3Sskrll // it under the terms of the GNU General Public License as published by 10*2a6b7db3Sskrll // the Free Software Foundation; either version 3 of the License, or 11*2a6b7db3Sskrll // (at your option) any later version. 12*2a6b7db3Sskrll 13*2a6b7db3Sskrll // This program is distributed in the hope that it will be useful, 14*2a6b7db3Sskrll // but WITHOUT ANY WARRANTY; without even the implied warranty of 15*2a6b7db3Sskrll // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*2a6b7db3Sskrll // GNU General Public License for more details. 17*2a6b7db3Sskrll 18*2a6b7db3Sskrll // You should have received a copy of the GNU General Public License 19*2a6b7db3Sskrll // along with this program; if not, write to the Free Software 20*2a6b7db3Sskrll // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21*2a6b7db3Sskrll // MA 02110-1301, USA. 22*2a6b7db3Sskrll 23*2a6b7db3Sskrll #include "gold.h" 24*2a6b7db3Sskrll 25*2a6b7db3Sskrll #include <cerrno> 26*2a6b7db3Sskrll #include <cstring> 27*2a6b7db3Sskrll #include "safe-ctype.h" 28*2a6b7db3Sskrll 29*2a6b7db3Sskrll #include "elfcpp.h" 30*2a6b7db3Sskrll #include "stringpool.h" 31*2a6b7db3Sskrll #include "fileread.h" 32*2a6b7db3Sskrll #include "output.h" 33*2a6b7db3Sskrll #include "binary.h" 34*2a6b7db3Sskrll 35*2a6b7db3Sskrll // Support for reading binary files as input. These become blobs in 36*2a6b7db3Sskrll // the final output. These files are treated as though they have a 37*2a6b7db3Sskrll // single .data section and define three symbols: 38*2a6b7db3Sskrll // _binary_FILENAME_start, _binary_FILENAME_end, _binary_FILENAME_end. 39*2a6b7db3Sskrll // The FILENAME is the name of the input file, with any 40*2a6b7db3Sskrll // non-alphanumeric character changed to an underscore. 41*2a6b7db3Sskrll 42*2a6b7db3Sskrll // We implement this by creating an ELF file in memory. 43*2a6b7db3Sskrll 44*2a6b7db3Sskrll namespace gold 45*2a6b7db3Sskrll { 46*2a6b7db3Sskrll 47*2a6b7db3Sskrll // class Binary_to_elf. 48*2a6b7db3Sskrll 49*2a6b7db3Sskrll Binary_to_elf::Binary_to_elf(elfcpp::EM machine, int size, bool big_endian, 50*2a6b7db3Sskrll const std::string& filename) 51*2a6b7db3Sskrll : elf_machine_(machine), size_(size), big_endian_(big_endian), 52*2a6b7db3Sskrll filename_(filename), data_(NULL), filesize_(0) 53*2a6b7db3Sskrll { 54*2a6b7db3Sskrll } 55*2a6b7db3Sskrll 56*2a6b7db3Sskrll Binary_to_elf::~Binary_to_elf() 57*2a6b7db3Sskrll { 58*2a6b7db3Sskrll if (this->data_ != NULL) 59*2a6b7db3Sskrll delete[] this->data_; 60*2a6b7db3Sskrll } 61*2a6b7db3Sskrll 62*2a6b7db3Sskrll // Given FILENAME, create a buffer which looks like an ELF file with 63*2a6b7db3Sskrll // the contents of FILENAME as the contents of the only section. The 64*2a6b7db3Sskrll // TASK parameters is mainly for debugging, and records who holds 65*2a6b7db3Sskrll // locks. 66*2a6b7db3Sskrll 67*2a6b7db3Sskrll bool 68*2a6b7db3Sskrll Binary_to_elf::convert(const Task* task) 69*2a6b7db3Sskrll { 70*2a6b7db3Sskrll if (this->size_ == 32) 71*2a6b7db3Sskrll { 72*2a6b7db3Sskrll if (!this->big_endian_) 73*2a6b7db3Sskrll { 74*2a6b7db3Sskrll #ifdef HAVE_TARGET_32_LITTLE 75*2a6b7db3Sskrll return this->sized_convert<32, false>(task); 76*2a6b7db3Sskrll #else 77*2a6b7db3Sskrll gold_unreachable(); 78*2a6b7db3Sskrll #endif 79*2a6b7db3Sskrll } 80*2a6b7db3Sskrll else 81*2a6b7db3Sskrll { 82*2a6b7db3Sskrll #ifdef HAVE_TARGET_32_BIG 83*2a6b7db3Sskrll return this->sized_convert<32, true>(task); 84*2a6b7db3Sskrll #else 85*2a6b7db3Sskrll gold_unreachable(); 86*2a6b7db3Sskrll #endif 87*2a6b7db3Sskrll } 88*2a6b7db3Sskrll } 89*2a6b7db3Sskrll else if (this->size_ == 64) 90*2a6b7db3Sskrll { 91*2a6b7db3Sskrll if (!this->big_endian_) 92*2a6b7db3Sskrll { 93*2a6b7db3Sskrll #ifdef HAVE_TARGET_64_LITTLE 94*2a6b7db3Sskrll return this->sized_convert<64, false>(task); 95*2a6b7db3Sskrll #else 96*2a6b7db3Sskrll gold_unreachable(); 97*2a6b7db3Sskrll #endif 98*2a6b7db3Sskrll } 99*2a6b7db3Sskrll else 100*2a6b7db3Sskrll { 101*2a6b7db3Sskrll #ifdef HAVE_TARGET_64_BIG 102*2a6b7db3Sskrll return this->sized_convert<64, true>(task); 103*2a6b7db3Sskrll #else 104*2a6b7db3Sskrll gold_unreachable(); 105*2a6b7db3Sskrll #endif 106*2a6b7db3Sskrll } 107*2a6b7db3Sskrll } 108*2a6b7db3Sskrll else 109*2a6b7db3Sskrll gold_unreachable(); 110*2a6b7db3Sskrll } 111*2a6b7db3Sskrll 112*2a6b7db3Sskrll // We are going to create: 113*2a6b7db3Sskrll // * The ELF file header. 114*2a6b7db3Sskrll // * Five sections: null section, .data, .symtab, .strtab, .shstrtab 115*2a6b7db3Sskrll // * The contents of the file. 116*2a6b7db3Sskrll // * Four symbols: null, begin, end, size. 117*2a6b7db3Sskrll // * Three symbol names. 118*2a6b7db3Sskrll // * Four section names. 119*2a6b7db3Sskrll 120*2a6b7db3Sskrll template<int size, bool big_endian> 121*2a6b7db3Sskrll bool 122*2a6b7db3Sskrll Binary_to_elf::sized_convert(const Task* task) 123*2a6b7db3Sskrll { 124*2a6b7db3Sskrll // Read the input file. 125*2a6b7db3Sskrll 126*2a6b7db3Sskrll File_read f; 127*2a6b7db3Sskrll if (!f.open(task, this->filename_)) 128*2a6b7db3Sskrll { 129*2a6b7db3Sskrll gold_error(_("cannot open %s: %s:"), this->filename_.c_str(), 130*2a6b7db3Sskrll strerror(errno)); 131*2a6b7db3Sskrll return false; 132*2a6b7db3Sskrll } 133*2a6b7db3Sskrll 134*2a6b7db3Sskrll section_size_type filesize = convert_to_section_size_type(f.filesize()); 135*2a6b7db3Sskrll const unsigned char* fileview = f.get_view(0, 0, filesize, false, false); 136*2a6b7db3Sskrll 137*2a6b7db3Sskrll unsigned int align; 138*2a6b7db3Sskrll if (size == 32) 139*2a6b7db3Sskrll align = 4; 140*2a6b7db3Sskrll else if (size == 64) 141*2a6b7db3Sskrll align = 8; 142*2a6b7db3Sskrll else 143*2a6b7db3Sskrll gold_unreachable(); 144*2a6b7db3Sskrll section_size_type aligned_filesize = align_address(filesize, align); 145*2a6b7db3Sskrll 146*2a6b7db3Sskrll // Build the stringpool for the symbol table. 147*2a6b7db3Sskrll 148*2a6b7db3Sskrll std::string mangled_name = this->filename_; 149*2a6b7db3Sskrll for (std::string::iterator p = mangled_name.begin(); 150*2a6b7db3Sskrll p != mangled_name.end(); 151*2a6b7db3Sskrll ++p) 152*2a6b7db3Sskrll if (!ISALNUM(*p)) 153*2a6b7db3Sskrll *p = '_'; 154*2a6b7db3Sskrll mangled_name = "_binary_" + mangled_name; 155*2a6b7db3Sskrll std::string start_symbol_name = mangled_name + "_start"; 156*2a6b7db3Sskrll std::string end_symbol_name = mangled_name + "_end"; 157*2a6b7db3Sskrll std::string size_symbol_name = mangled_name + "_size"; 158*2a6b7db3Sskrll 159*2a6b7db3Sskrll Stringpool strtab; 160*2a6b7db3Sskrll strtab.add(start_symbol_name.c_str(), false, NULL); 161*2a6b7db3Sskrll strtab.add(end_symbol_name.c_str(), false, NULL); 162*2a6b7db3Sskrll strtab.add(size_symbol_name.c_str(), false, NULL); 163*2a6b7db3Sskrll strtab.set_string_offsets(); 164*2a6b7db3Sskrll 165*2a6b7db3Sskrll // Build the stringpool for the section name table. 166*2a6b7db3Sskrll 167*2a6b7db3Sskrll Stringpool shstrtab; 168*2a6b7db3Sskrll shstrtab.add(".data", false, NULL); 169*2a6b7db3Sskrll shstrtab.add(".symtab", false, NULL); 170*2a6b7db3Sskrll shstrtab.add(".strtab", false, NULL); 171*2a6b7db3Sskrll shstrtab.add(".shstrtab", false, NULL); 172*2a6b7db3Sskrll shstrtab.set_string_offsets(); 173*2a6b7db3Sskrll 174*2a6b7db3Sskrll // Work out the size of the generated file, and the offsets of the 175*2a6b7db3Sskrll // various sections, and allocate a buffer. 176*2a6b7db3Sskrll 177*2a6b7db3Sskrll const int sym_size = elfcpp::Elf_sizes<size>::sym_size; 178*2a6b7db3Sskrll 179*2a6b7db3Sskrll size_t output_size = (elfcpp::Elf_sizes<size>::ehdr_size 180*2a6b7db3Sskrll + 5 * elfcpp::Elf_sizes<size>::shdr_size); 181*2a6b7db3Sskrll size_t data_offset = output_size; 182*2a6b7db3Sskrll output_size += aligned_filesize; 183*2a6b7db3Sskrll size_t symtab_offset = output_size; 184*2a6b7db3Sskrll output_size += 4 * sym_size; 185*2a6b7db3Sskrll size_t strtab_offset = output_size; 186*2a6b7db3Sskrll output_size += strtab.get_strtab_size(); 187*2a6b7db3Sskrll size_t shstrtab_offset = output_size; 188*2a6b7db3Sskrll output_size += shstrtab.get_strtab_size(); 189*2a6b7db3Sskrll 190*2a6b7db3Sskrll unsigned char* buffer = new unsigned char[output_size]; 191*2a6b7db3Sskrll 192*2a6b7db3Sskrll // Write out the data. 193*2a6b7db3Sskrll 194*2a6b7db3Sskrll unsigned char* pout = buffer; 195*2a6b7db3Sskrll 196*2a6b7db3Sskrll this->write_file_header<size, big_endian>(&pout); 197*2a6b7db3Sskrll 198*2a6b7db3Sskrll this->write_section_header<size, big_endian>("", &shstrtab, elfcpp::SHT_NULL, 199*2a6b7db3Sskrll 0, 0, 0, 0, 0, 200*2a6b7db3Sskrll 0, 0, &pout); 201*2a6b7db3Sskrll // Having the section be named ".data", having it be writable, and 202*2a6b7db3Sskrll // giving it an alignment of 1 is because the GNU linker does it 203*2a6b7db3Sskrll // that way, and existing linker script expect it. 204*2a6b7db3Sskrll this->write_section_header<size, big_endian>(".data", &shstrtab, 205*2a6b7db3Sskrll elfcpp::SHT_PROGBITS, 206*2a6b7db3Sskrll (elfcpp::SHF_ALLOC 207*2a6b7db3Sskrll | elfcpp::SHF_WRITE), 208*2a6b7db3Sskrll data_offset, 209*2a6b7db3Sskrll filesize, 0, 0, 210*2a6b7db3Sskrll 1, 0, &pout); 211*2a6b7db3Sskrll this->write_section_header<size, big_endian>(".symtab", &shstrtab, 212*2a6b7db3Sskrll elfcpp::SHT_SYMTAB, 213*2a6b7db3Sskrll 0, symtab_offset, 4 * sym_size, 214*2a6b7db3Sskrll 3, 1, align, sym_size, &pout); 215*2a6b7db3Sskrll this->write_section_header<size, big_endian>(".strtab", &shstrtab, 216*2a6b7db3Sskrll elfcpp::SHT_STRTAB, 217*2a6b7db3Sskrll 0, strtab_offset, 218*2a6b7db3Sskrll strtab.get_strtab_size(), 219*2a6b7db3Sskrll 0, 0, 1, 0, &pout); 220*2a6b7db3Sskrll this->write_section_header<size, big_endian>(".shstrtab", &shstrtab, 221*2a6b7db3Sskrll elfcpp::SHT_STRTAB, 222*2a6b7db3Sskrll 0, shstrtab_offset, 223*2a6b7db3Sskrll shstrtab.get_strtab_size(), 224*2a6b7db3Sskrll 0, 0, 1, 0, &pout); 225*2a6b7db3Sskrll 226*2a6b7db3Sskrll memcpy(pout, fileview, filesize); 227*2a6b7db3Sskrll pout += filesize; 228*2a6b7db3Sskrll memset(pout, 0, aligned_filesize - filesize); 229*2a6b7db3Sskrll pout += aligned_filesize - filesize; 230*2a6b7db3Sskrll 231*2a6b7db3Sskrll this->write_symbol<size, big_endian>("", &strtab, 0, 0, &pout); 232*2a6b7db3Sskrll this->write_symbol<size, big_endian>(start_symbol_name, &strtab, 0, 1, 233*2a6b7db3Sskrll &pout); 234*2a6b7db3Sskrll this->write_symbol<size, big_endian>(end_symbol_name, &strtab, filesize, 1, 235*2a6b7db3Sskrll &pout); 236*2a6b7db3Sskrll this->write_symbol<size, big_endian>(size_symbol_name, &strtab, filesize, 237*2a6b7db3Sskrll elfcpp::SHN_ABS, &pout); 238*2a6b7db3Sskrll 239*2a6b7db3Sskrll strtab.write_to_buffer(pout, strtab.get_strtab_size()); 240*2a6b7db3Sskrll pout += strtab.get_strtab_size(); 241*2a6b7db3Sskrll 242*2a6b7db3Sskrll shstrtab.write_to_buffer(pout, shstrtab.get_strtab_size()); 243*2a6b7db3Sskrll pout += shstrtab.get_strtab_size(); 244*2a6b7db3Sskrll 245*2a6b7db3Sskrll gold_assert(static_cast<size_t>(pout - buffer) == output_size); 246*2a6b7db3Sskrll 247*2a6b7db3Sskrll this->data_ = buffer; 248*2a6b7db3Sskrll this->filesize_ = output_size; 249*2a6b7db3Sskrll 250*2a6b7db3Sskrll f.unlock(task); 251*2a6b7db3Sskrll 252*2a6b7db3Sskrll return true; 253*2a6b7db3Sskrll } 254*2a6b7db3Sskrll 255*2a6b7db3Sskrll // Write out the file header. 256*2a6b7db3Sskrll 257*2a6b7db3Sskrll template<int size, bool big_endian> 258*2a6b7db3Sskrll void 259*2a6b7db3Sskrll Binary_to_elf::write_file_header(unsigned char** ppout) 260*2a6b7db3Sskrll { 261*2a6b7db3Sskrll elfcpp::Ehdr_write<size, big_endian> oehdr(*ppout); 262*2a6b7db3Sskrll 263*2a6b7db3Sskrll unsigned char e_ident[elfcpp::EI_NIDENT]; 264*2a6b7db3Sskrll memset(e_ident, 0, elfcpp::EI_NIDENT); 265*2a6b7db3Sskrll e_ident[elfcpp::EI_MAG0] = elfcpp::ELFMAG0; 266*2a6b7db3Sskrll e_ident[elfcpp::EI_MAG1] = elfcpp::ELFMAG1; 267*2a6b7db3Sskrll e_ident[elfcpp::EI_MAG2] = elfcpp::ELFMAG2; 268*2a6b7db3Sskrll e_ident[elfcpp::EI_MAG3] = elfcpp::ELFMAG3; 269*2a6b7db3Sskrll if (size == 32) 270*2a6b7db3Sskrll e_ident[elfcpp::EI_CLASS] = elfcpp::ELFCLASS32; 271*2a6b7db3Sskrll else if (size == 64) 272*2a6b7db3Sskrll e_ident[elfcpp::EI_CLASS] = elfcpp::ELFCLASS64; 273*2a6b7db3Sskrll else 274*2a6b7db3Sskrll gold_unreachable(); 275*2a6b7db3Sskrll e_ident[elfcpp::EI_DATA] = (big_endian 276*2a6b7db3Sskrll ? elfcpp::ELFDATA2MSB 277*2a6b7db3Sskrll : elfcpp::ELFDATA2LSB); 278*2a6b7db3Sskrll e_ident[elfcpp::EI_VERSION] = elfcpp::EV_CURRENT; 279*2a6b7db3Sskrll oehdr.put_e_ident(e_ident); 280*2a6b7db3Sskrll 281*2a6b7db3Sskrll oehdr.put_e_type(elfcpp::ET_REL); 282*2a6b7db3Sskrll oehdr.put_e_machine(this->elf_machine_); 283*2a6b7db3Sskrll oehdr.put_e_version(elfcpp::EV_CURRENT); 284*2a6b7db3Sskrll oehdr.put_e_entry(0); 285*2a6b7db3Sskrll oehdr.put_e_phoff(0); 286*2a6b7db3Sskrll oehdr.put_e_shoff(elfcpp::Elf_sizes<size>::ehdr_size); 287*2a6b7db3Sskrll oehdr.put_e_flags(0); 288*2a6b7db3Sskrll oehdr.put_e_ehsize(elfcpp::Elf_sizes<size>::ehdr_size); 289*2a6b7db3Sskrll oehdr.put_e_phentsize(0); 290*2a6b7db3Sskrll oehdr.put_e_phnum(0); 291*2a6b7db3Sskrll oehdr.put_e_shentsize(elfcpp::Elf_sizes<size>::shdr_size); 292*2a6b7db3Sskrll oehdr.put_e_shnum(5); 293*2a6b7db3Sskrll oehdr.put_e_shstrndx(4); 294*2a6b7db3Sskrll 295*2a6b7db3Sskrll *ppout += elfcpp::Elf_sizes<size>::ehdr_size; 296*2a6b7db3Sskrll } 297*2a6b7db3Sskrll 298*2a6b7db3Sskrll // Write out a section header. 299*2a6b7db3Sskrll 300*2a6b7db3Sskrll template<int size, bool big_endian> 301*2a6b7db3Sskrll void 302*2a6b7db3Sskrll Binary_to_elf::write_section_header( 303*2a6b7db3Sskrll const char* name, 304*2a6b7db3Sskrll const Stringpool* shstrtab, 305*2a6b7db3Sskrll elfcpp::SHT type, 306*2a6b7db3Sskrll unsigned int flags, 307*2a6b7db3Sskrll section_size_type offset, 308*2a6b7db3Sskrll section_size_type section_size, 309*2a6b7db3Sskrll unsigned int link, 310*2a6b7db3Sskrll unsigned int info, 311*2a6b7db3Sskrll unsigned int addralign, 312*2a6b7db3Sskrll unsigned int entsize, 313*2a6b7db3Sskrll unsigned char** ppout) 314*2a6b7db3Sskrll { 315*2a6b7db3Sskrll elfcpp::Shdr_write<size, big_endian> oshdr(*ppout); 316*2a6b7db3Sskrll 317*2a6b7db3Sskrll oshdr.put_sh_name(*name == '\0' ? 0 : shstrtab->get_offset(name)); 318*2a6b7db3Sskrll oshdr.put_sh_type(type); 319*2a6b7db3Sskrll oshdr.put_sh_flags(flags); 320*2a6b7db3Sskrll oshdr.put_sh_addr(0); 321*2a6b7db3Sskrll oshdr.put_sh_offset(offset); 322*2a6b7db3Sskrll oshdr.put_sh_size(section_size); 323*2a6b7db3Sskrll oshdr.put_sh_link(link); 324*2a6b7db3Sskrll oshdr.put_sh_info(info); 325*2a6b7db3Sskrll oshdr.put_sh_addralign(addralign); 326*2a6b7db3Sskrll oshdr.put_sh_entsize(entsize); 327*2a6b7db3Sskrll 328*2a6b7db3Sskrll *ppout += elfcpp::Elf_sizes<size>::shdr_size; 329*2a6b7db3Sskrll } 330*2a6b7db3Sskrll 331*2a6b7db3Sskrll // Write out a symbol. 332*2a6b7db3Sskrll 333*2a6b7db3Sskrll template<int size, bool big_endian> 334*2a6b7db3Sskrll void 335*2a6b7db3Sskrll Binary_to_elf::write_symbol( 336*2a6b7db3Sskrll const std::string& name, 337*2a6b7db3Sskrll const Stringpool* strtab, 338*2a6b7db3Sskrll section_size_type value, 339*2a6b7db3Sskrll unsigned int shndx, 340*2a6b7db3Sskrll unsigned char** ppout) 341*2a6b7db3Sskrll { 342*2a6b7db3Sskrll unsigned char* pout = *ppout; 343*2a6b7db3Sskrll 344*2a6b7db3Sskrll elfcpp::Sym_write<size, big_endian> osym(pout); 345*2a6b7db3Sskrll osym.put_st_name(name.empty() ? 0 : strtab->get_offset(name.c_str())); 346*2a6b7db3Sskrll osym.put_st_value(value); 347*2a6b7db3Sskrll osym.put_st_size(0); 348*2a6b7db3Sskrll osym.put_st_info(name.empty() ? elfcpp::STB_LOCAL : elfcpp::STB_GLOBAL, 349*2a6b7db3Sskrll elfcpp::STT_NOTYPE); 350*2a6b7db3Sskrll osym.put_st_other(elfcpp::STV_DEFAULT, 0); 351*2a6b7db3Sskrll osym.put_st_shndx(shndx); 352*2a6b7db3Sskrll 353*2a6b7db3Sskrll *ppout += elfcpp::Elf_sizes<size>::sym_size; 354*2a6b7db3Sskrll } 355*2a6b7db3Sskrll 356*2a6b7db3Sskrll } // End namespace gold. 357