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