1 // binary.cc -- binary input files for gold 2 3 // Copyright (C) 2008-2014 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant (at) 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 44 namespace gold 45 { 46 47 // class Binary_to_elf. 48 49 Binary_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 56 Binary_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 67 bool 68 Binary_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 120 template<int size, bool big_endian> 121 bool 122 Binary_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, 0, &pout); 239 this->write_symbol<size, big_endian>(start_symbol_name, &strtab, 0, filesize, 240 1, &pout); 241 this->write_symbol<size, big_endian>(end_symbol_name, &strtab, filesize, 0, 242 1, &pout); 243 this->write_symbol<size, big_endian>(size_symbol_name, &strtab, filesize, 0, 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 264 template<int size, bool big_endian> 265 void 266 Binary_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 307 template<int size, bool big_endian> 308 void 309 Binary_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 340 template<int size, bool big_endian> 341 void 342 Binary_to_elf::write_symbol( 343 const std::string& name, 344 const Stringpool* strtab, 345 section_size_type value, 346 typename elfcpp::Elf_types<32>::Elf_WXword st_size, 347 unsigned int shndx, 348 unsigned char** ppout) 349 { 350 unsigned char* pout = *ppout; 351 352 elfcpp::Sym_write<size, big_endian> osym(pout); 353 osym.put_st_name(name.empty() ? 0 : strtab->get_offset(name.c_str())); 354 osym.put_st_value(value); 355 osym.put_st_size(st_size); 356 osym.put_st_info(name.empty() ? elfcpp::STB_LOCAL : elfcpp::STB_GLOBAL, 357 elfcpp::STT_NOTYPE); 358 osym.put_st_other(elfcpp::STV_DEFAULT, 0); 359 osym.put_st_shndx(shndx); 360 361 *ppout += elfcpp::Elf_sizes<size>::sym_size; 362 } 363 364 } // End namespace gold. 365