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