12a6b7db3Sskrll // binary.cc -- binary input files for gold
22a6b7db3Sskrll 
3*f22f0ef4Schristos // Copyright (C) 2008-2022 Free Software Foundation, Inc.
42a6b7db3Sskrll // Written by Ian Lance Taylor <iant@google.com>.
52a6b7db3Sskrll 
62a6b7db3Sskrll // This file is part of gold.
72a6b7db3Sskrll 
82a6b7db3Sskrll // This program is free software; you can redistribute it and/or modify
92a6b7db3Sskrll // it under the terms of the GNU General Public License as published by
102a6b7db3Sskrll // the Free Software Foundation; either version 3 of the License, or
112a6b7db3Sskrll // (at your option) any later version.
122a6b7db3Sskrll 
132a6b7db3Sskrll // This program is distributed in the hope that it will be useful,
142a6b7db3Sskrll // but WITHOUT ANY WARRANTY; without even the implied warranty of
152a6b7db3Sskrll // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162a6b7db3Sskrll // GNU General Public License for more details.
172a6b7db3Sskrll 
182a6b7db3Sskrll // You should have received a copy of the GNU General Public License
192a6b7db3Sskrll // along with this program; if not, write to the Free Software
202a6b7db3Sskrll // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
212a6b7db3Sskrll // MA 02110-1301, USA.
222a6b7db3Sskrll 
232a6b7db3Sskrll #include "gold.h"
242a6b7db3Sskrll 
252a6b7db3Sskrll #include <cerrno>
262a6b7db3Sskrll #include <cstring>
272a6b7db3Sskrll 
282a6b7db3Sskrll #include "elfcpp.h"
292a6b7db3Sskrll #include "stringpool.h"
302a6b7db3Sskrll #include "fileread.h"
312a6b7db3Sskrll #include "output.h"
322a6b7db3Sskrll #include "binary.h"
332a6b7db3Sskrll 
345ba6b03cSchristos // safe-ctype.h interferes with macros defined by the system <ctype.h>.
355ba6b03cSchristos // Some C++ system headers might include <ctype.h> and rely on its macro
365ba6b03cSchristos // definitions being intact.  So make sure that safe-ctype.h is included
375ba6b03cSchristos // only after any C++ system headers, whether directly here (above) or via
385ba6b03cSchristos // other local header files (e.g. #include <string> in "binary.h").
395ba6b03cSchristos #include "safe-ctype.h"
405ba6b03cSchristos 
412a6b7db3Sskrll // Support for reading binary files as input.  These become blobs in
422a6b7db3Sskrll // the final output.  These files are treated as though they have a
432a6b7db3Sskrll // single .data section and define three symbols:
44b578a859Schristos // _binary_FILENAME_start, _binary_FILENAME_end, _binary_FILENAME_size.
452a6b7db3Sskrll // The FILENAME is the name of the input file, with any
462a6b7db3Sskrll // non-alphanumeric character changed to an underscore.
472a6b7db3Sskrll 
482a6b7db3Sskrll // We implement this by creating an ELF file in memory.
492a6b7db3Sskrll 
502a6b7db3Sskrll namespace gold
512a6b7db3Sskrll {
522a6b7db3Sskrll 
532a6b7db3Sskrll // class Binary_to_elf.
542a6b7db3Sskrll 
Binary_to_elf(elfcpp::EM machine,int size,bool big_endian,const std::string & filename)552a6b7db3Sskrll Binary_to_elf::Binary_to_elf(elfcpp::EM machine, int size, bool big_endian,
562a6b7db3Sskrll 			     const std::string& filename)
572a6b7db3Sskrll   : elf_machine_(machine), size_(size), big_endian_(big_endian),
582a6b7db3Sskrll     filename_(filename), data_(NULL), filesize_(0)
592a6b7db3Sskrll {
602a6b7db3Sskrll }
612a6b7db3Sskrll 
~Binary_to_elf()622a6b7db3Sskrll Binary_to_elf::~Binary_to_elf()
632a6b7db3Sskrll {
642a6b7db3Sskrll   if (this->data_ != NULL)
652a6b7db3Sskrll     delete[] this->data_;
662a6b7db3Sskrll }
672a6b7db3Sskrll 
682a6b7db3Sskrll // Given FILENAME, create a buffer which looks like an ELF file with
692a6b7db3Sskrll // the contents of FILENAME as the contents of the only section.  The
702a6b7db3Sskrll // TASK parameters is mainly for debugging, and records who holds
712a6b7db3Sskrll // locks.
722a6b7db3Sskrll 
732a6b7db3Sskrll bool
convert(const Task * task)742a6b7db3Sskrll Binary_to_elf::convert(const Task* task)
752a6b7db3Sskrll {
762a6b7db3Sskrll   if (this->size_ == 32)
772a6b7db3Sskrll     {
782a6b7db3Sskrll       if (!this->big_endian_)
792a6b7db3Sskrll 	{
802a6b7db3Sskrll #ifdef HAVE_TARGET_32_LITTLE
812a6b7db3Sskrll 	  return this->sized_convert<32, false>(task);
822a6b7db3Sskrll #else
832a6b7db3Sskrll 	  gold_unreachable();
842a6b7db3Sskrll #endif
852a6b7db3Sskrll 	}
862a6b7db3Sskrll       else
872a6b7db3Sskrll 	{
882a6b7db3Sskrll #ifdef HAVE_TARGET_32_BIG
892a6b7db3Sskrll 	  return this->sized_convert<32, true>(task);
902a6b7db3Sskrll #else
912a6b7db3Sskrll 	  gold_unreachable();
922a6b7db3Sskrll #endif
932a6b7db3Sskrll 	}
942a6b7db3Sskrll     }
952a6b7db3Sskrll   else if (this->size_ == 64)
962a6b7db3Sskrll     {
972a6b7db3Sskrll       if (!this->big_endian_)
982a6b7db3Sskrll 	{
992a6b7db3Sskrll #ifdef HAVE_TARGET_64_LITTLE
1002a6b7db3Sskrll 	  return this->sized_convert<64, false>(task);
1012a6b7db3Sskrll #else
1022a6b7db3Sskrll 	  gold_unreachable();
1032a6b7db3Sskrll #endif
1042a6b7db3Sskrll 	}
1052a6b7db3Sskrll       else
1062a6b7db3Sskrll 	{
1072a6b7db3Sskrll #ifdef HAVE_TARGET_64_BIG
1082a6b7db3Sskrll 	  return this->sized_convert<64, true>(task);
1092a6b7db3Sskrll #else
1102a6b7db3Sskrll 	  gold_unreachable();
1112a6b7db3Sskrll #endif
1122a6b7db3Sskrll 	}
1132a6b7db3Sskrll     }
1142a6b7db3Sskrll   else
1152a6b7db3Sskrll     gold_unreachable();
1162a6b7db3Sskrll }
1172a6b7db3Sskrll 
1182a6b7db3Sskrll // We are going to create:
1192a6b7db3Sskrll // * The ELF file header.
1202a6b7db3Sskrll // * Five sections: null section, .data, .symtab, .strtab, .shstrtab
1212a6b7db3Sskrll // * The contents of the file.
1222a6b7db3Sskrll // * Four symbols: null, begin, end, size.
1232a6b7db3Sskrll // * Three symbol names.
1242a6b7db3Sskrll // * Four section names.
1252a6b7db3Sskrll 
1262a6b7db3Sskrll template<int size, bool big_endian>
1272a6b7db3Sskrll bool
sized_convert(const Task * task)1282a6b7db3Sskrll Binary_to_elf::sized_convert(const Task* task)
1292a6b7db3Sskrll {
1302a6b7db3Sskrll   // Read the input file.
1312a6b7db3Sskrll 
1322a6b7db3Sskrll   File_read f;
1332a6b7db3Sskrll   if (!f.open(task, this->filename_))
1342a6b7db3Sskrll     {
1352a6b7db3Sskrll       gold_error(_("cannot open %s: %s:"), this->filename_.c_str(),
1362a6b7db3Sskrll 		 strerror(errno));
1372a6b7db3Sskrll       return false;
1382a6b7db3Sskrll     }
1392a6b7db3Sskrll 
1402a6b7db3Sskrll   section_size_type filesize = convert_to_section_size_type(f.filesize());
141b578a859Schristos   const unsigned char* fileview;
142b578a859Schristos   if (filesize == 0)
143b578a859Schristos     fileview = NULL;
144b578a859Schristos   else
145b578a859Schristos     fileview = f.get_view(0, 0, filesize, false, false);
1462a6b7db3Sskrll 
1472a6b7db3Sskrll   unsigned int align;
1482a6b7db3Sskrll   if (size == 32)
1492a6b7db3Sskrll     align = 4;
1502a6b7db3Sskrll   else if (size == 64)
1512a6b7db3Sskrll     align = 8;
1522a6b7db3Sskrll   else
1532a6b7db3Sskrll     gold_unreachable();
1542a6b7db3Sskrll   section_size_type aligned_filesize = align_address(filesize, align);
1552a6b7db3Sskrll 
1562a6b7db3Sskrll   // Build the stringpool for the symbol table.
1572a6b7db3Sskrll 
1582a6b7db3Sskrll   std::string mangled_name = this->filename_;
1592a6b7db3Sskrll   for (std::string::iterator p = mangled_name.begin();
1602a6b7db3Sskrll        p != mangled_name.end();
1612a6b7db3Sskrll        ++p)
1622a6b7db3Sskrll     if (!ISALNUM(*p))
1632a6b7db3Sskrll       *p = '_';
1642a6b7db3Sskrll   mangled_name = "_binary_" + mangled_name;
1652a6b7db3Sskrll   std::string start_symbol_name = mangled_name + "_start";
1662a6b7db3Sskrll   std::string end_symbol_name = mangled_name + "_end";
1672a6b7db3Sskrll   std::string size_symbol_name = mangled_name + "_size";
1682a6b7db3Sskrll 
1692a6b7db3Sskrll   Stringpool strtab;
1702a6b7db3Sskrll   strtab.add(start_symbol_name.c_str(), false, NULL);
1712a6b7db3Sskrll   strtab.add(end_symbol_name.c_str(), false, NULL);
1722a6b7db3Sskrll   strtab.add(size_symbol_name.c_str(), false, NULL);
1732a6b7db3Sskrll   strtab.set_string_offsets();
1742a6b7db3Sskrll 
1752a6b7db3Sskrll   // Build the stringpool for the section name table.
1762a6b7db3Sskrll 
1772a6b7db3Sskrll   Stringpool shstrtab;
1782a6b7db3Sskrll   shstrtab.add(".data", false, NULL);
1792a6b7db3Sskrll   shstrtab.add(".symtab", false, NULL);
1802a6b7db3Sskrll   shstrtab.add(".strtab", false, NULL);
1812a6b7db3Sskrll   shstrtab.add(".shstrtab", false, NULL);
1822a6b7db3Sskrll   shstrtab.set_string_offsets();
1832a6b7db3Sskrll 
1842a6b7db3Sskrll   // Work out the size of the generated file, and the offsets of the
1852a6b7db3Sskrll   // various sections, and allocate a buffer.
1862a6b7db3Sskrll 
1872a6b7db3Sskrll   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
1882a6b7db3Sskrll 
1892a6b7db3Sskrll   size_t output_size = (elfcpp::Elf_sizes<size>::ehdr_size
1902a6b7db3Sskrll 			+ 5 * elfcpp::Elf_sizes<size>::shdr_size);
1912a6b7db3Sskrll   size_t data_offset = output_size;
1922a6b7db3Sskrll   output_size += aligned_filesize;
1932a6b7db3Sskrll   size_t symtab_offset = output_size;
1942a6b7db3Sskrll   output_size += 4 * sym_size;
1952a6b7db3Sskrll   size_t strtab_offset = output_size;
1962a6b7db3Sskrll   output_size += strtab.get_strtab_size();
1972a6b7db3Sskrll   size_t shstrtab_offset = output_size;
1982a6b7db3Sskrll   output_size += shstrtab.get_strtab_size();
1992a6b7db3Sskrll 
2002a6b7db3Sskrll   unsigned char* buffer = new unsigned char[output_size];
2012a6b7db3Sskrll 
2022a6b7db3Sskrll   // Write out the data.
2032a6b7db3Sskrll 
2042a6b7db3Sskrll   unsigned char* pout = buffer;
2052a6b7db3Sskrll 
2062a6b7db3Sskrll   this->write_file_header<size, big_endian>(&pout);
2072a6b7db3Sskrll 
2082a6b7db3Sskrll   this->write_section_header<size, big_endian>("", &shstrtab, elfcpp::SHT_NULL,
2092a6b7db3Sskrll 					       0, 0, 0, 0, 0,
2102a6b7db3Sskrll 					       0, 0, &pout);
2112a6b7db3Sskrll   // Having the section be named ".data", having it be writable, and
2122a6b7db3Sskrll   // giving it an alignment of 1 is because the GNU linker does it
2132a6b7db3Sskrll   // that way, and existing linker script expect it.
2142a6b7db3Sskrll   this->write_section_header<size, big_endian>(".data", &shstrtab,
2152a6b7db3Sskrll 					       elfcpp::SHT_PROGBITS,
2162a6b7db3Sskrll 					       (elfcpp::SHF_ALLOC
2172a6b7db3Sskrll 						| elfcpp::SHF_WRITE),
2182a6b7db3Sskrll 					       data_offset,
2192a6b7db3Sskrll 					       filesize, 0, 0,
2202a6b7db3Sskrll 					       1, 0, &pout);
2212a6b7db3Sskrll   this->write_section_header<size, big_endian>(".symtab", &shstrtab,
2222a6b7db3Sskrll 					       elfcpp::SHT_SYMTAB,
2232a6b7db3Sskrll 					       0, symtab_offset, 4 * sym_size,
2242a6b7db3Sskrll 					       3, 1, align, sym_size, &pout);
2252a6b7db3Sskrll   this->write_section_header<size, big_endian>(".strtab", &shstrtab,
2262a6b7db3Sskrll 					       elfcpp::SHT_STRTAB,
2272a6b7db3Sskrll 					       0, strtab_offset,
2282a6b7db3Sskrll 					       strtab.get_strtab_size(),
2292a6b7db3Sskrll 					       0, 0, 1, 0, &pout);
2302a6b7db3Sskrll   this->write_section_header<size, big_endian>(".shstrtab", &shstrtab,
2312a6b7db3Sskrll 					       elfcpp::SHT_STRTAB,
2322a6b7db3Sskrll 					       0, shstrtab_offset,
2332a6b7db3Sskrll 					       shstrtab.get_strtab_size(),
2342a6b7db3Sskrll 					       0, 0, 1, 0, &pout);
2352a6b7db3Sskrll 
236b578a859Schristos   if (filesize > 0)
237b578a859Schristos     {
2382a6b7db3Sskrll       memcpy(pout, fileview, filesize);
2392a6b7db3Sskrll       pout += filesize;
2402a6b7db3Sskrll       memset(pout, 0, aligned_filesize - filesize);
2412a6b7db3Sskrll       pout += aligned_filesize - filesize;
242b578a859Schristos     }
2432a6b7db3Sskrll 
2445ba6b03cSchristos   this->write_symbol<size, big_endian>("", &strtab, 0, 0, 0, &pout);
2455ba6b03cSchristos   this->write_symbol<size, big_endian>(start_symbol_name, &strtab, 0, filesize,
2465ba6b03cSchristos 				       1, &pout);
2475ba6b03cSchristos   this->write_symbol<size, big_endian>(end_symbol_name, &strtab, filesize, 0,
2485ba6b03cSchristos 				       1, &pout);
2495ba6b03cSchristos   this->write_symbol<size, big_endian>(size_symbol_name, &strtab, filesize, 0,
2502a6b7db3Sskrll 				       elfcpp::SHN_ABS, &pout);
2512a6b7db3Sskrll 
2522a6b7db3Sskrll   strtab.write_to_buffer(pout, strtab.get_strtab_size());
2532a6b7db3Sskrll   pout += strtab.get_strtab_size();
2542a6b7db3Sskrll 
2552a6b7db3Sskrll   shstrtab.write_to_buffer(pout, shstrtab.get_strtab_size());
2562a6b7db3Sskrll   pout += shstrtab.get_strtab_size();
2572a6b7db3Sskrll 
2582a6b7db3Sskrll   gold_assert(static_cast<size_t>(pout - buffer) == output_size);
2592a6b7db3Sskrll 
2602a6b7db3Sskrll   this->data_ = buffer;
2612a6b7db3Sskrll   this->filesize_ = output_size;
2622a6b7db3Sskrll 
2632a6b7db3Sskrll   f.unlock(task);
2642a6b7db3Sskrll 
2652a6b7db3Sskrll   return true;
2662a6b7db3Sskrll }
2672a6b7db3Sskrll 
2682a6b7db3Sskrll // Write out the file header.
2692a6b7db3Sskrll 
2702a6b7db3Sskrll template<int size, bool big_endian>
2712a6b7db3Sskrll void
write_file_header(unsigned char ** ppout)2722a6b7db3Sskrll Binary_to_elf::write_file_header(unsigned char** ppout)
2732a6b7db3Sskrll {
2742a6b7db3Sskrll   elfcpp::Ehdr_write<size, big_endian> oehdr(*ppout);
2752a6b7db3Sskrll 
2762a6b7db3Sskrll   unsigned char e_ident[elfcpp::EI_NIDENT];
2772a6b7db3Sskrll   memset(e_ident, 0, elfcpp::EI_NIDENT);
2782a6b7db3Sskrll   e_ident[elfcpp::EI_MAG0] = elfcpp::ELFMAG0;
2792a6b7db3Sskrll   e_ident[elfcpp::EI_MAG1] = elfcpp::ELFMAG1;
2802a6b7db3Sskrll   e_ident[elfcpp::EI_MAG2] = elfcpp::ELFMAG2;
2812a6b7db3Sskrll   e_ident[elfcpp::EI_MAG3] = elfcpp::ELFMAG3;
2822a6b7db3Sskrll   if (size == 32)
2832a6b7db3Sskrll     e_ident[elfcpp::EI_CLASS] = elfcpp::ELFCLASS32;
2842a6b7db3Sskrll   else if (size == 64)
2852a6b7db3Sskrll     e_ident[elfcpp::EI_CLASS] = elfcpp::ELFCLASS64;
2862a6b7db3Sskrll   else
2872a6b7db3Sskrll     gold_unreachable();
2882a6b7db3Sskrll   e_ident[elfcpp::EI_DATA] = (big_endian
2892a6b7db3Sskrll 			      ? elfcpp::ELFDATA2MSB
2902a6b7db3Sskrll 			      : elfcpp::ELFDATA2LSB);
2912a6b7db3Sskrll   e_ident[elfcpp::EI_VERSION] = elfcpp::EV_CURRENT;
2922a6b7db3Sskrll   oehdr.put_e_ident(e_ident);
2932a6b7db3Sskrll 
2942a6b7db3Sskrll   oehdr.put_e_type(elfcpp::ET_REL);
2952a6b7db3Sskrll   oehdr.put_e_machine(this->elf_machine_);
2962a6b7db3Sskrll   oehdr.put_e_version(elfcpp::EV_CURRENT);
2972a6b7db3Sskrll   oehdr.put_e_entry(0);
2982a6b7db3Sskrll   oehdr.put_e_phoff(0);
2992a6b7db3Sskrll   oehdr.put_e_shoff(elfcpp::Elf_sizes<size>::ehdr_size);
3002a6b7db3Sskrll   oehdr.put_e_flags(0);
3012a6b7db3Sskrll   oehdr.put_e_ehsize(elfcpp::Elf_sizes<size>::ehdr_size);
3022a6b7db3Sskrll   oehdr.put_e_phentsize(0);
3032a6b7db3Sskrll   oehdr.put_e_phnum(0);
3042a6b7db3Sskrll   oehdr.put_e_shentsize(elfcpp::Elf_sizes<size>::shdr_size);
3052a6b7db3Sskrll   oehdr.put_e_shnum(5);
3062a6b7db3Sskrll   oehdr.put_e_shstrndx(4);
3072a6b7db3Sskrll 
3082a6b7db3Sskrll   *ppout += elfcpp::Elf_sizes<size>::ehdr_size;
3092a6b7db3Sskrll }
3102a6b7db3Sskrll 
3112a6b7db3Sskrll // Write out a section header.
3122a6b7db3Sskrll 
3132a6b7db3Sskrll template<int size, bool big_endian>
3142a6b7db3Sskrll void
write_section_header(const char * name,const Stringpool * shstrtab,elfcpp::SHT type,unsigned int flags,section_size_type offset,section_size_type section_size,unsigned int link,unsigned int info,unsigned int addralign,unsigned int entsize,unsigned char ** ppout)3152a6b7db3Sskrll Binary_to_elf::write_section_header(
3162a6b7db3Sskrll     const char* name,
3172a6b7db3Sskrll     const Stringpool* shstrtab,
3182a6b7db3Sskrll     elfcpp::SHT type,
3192a6b7db3Sskrll     unsigned int flags,
3202a6b7db3Sskrll     section_size_type offset,
3212a6b7db3Sskrll     section_size_type section_size,
3222a6b7db3Sskrll     unsigned int link,
3232a6b7db3Sskrll     unsigned int info,
3242a6b7db3Sskrll     unsigned int addralign,
3252a6b7db3Sskrll     unsigned int entsize,
3262a6b7db3Sskrll     unsigned char** ppout)
3272a6b7db3Sskrll {
3282a6b7db3Sskrll   elfcpp::Shdr_write<size, big_endian> oshdr(*ppout);
3292a6b7db3Sskrll 
3302a6b7db3Sskrll   oshdr.put_sh_name(*name == '\0' ? 0 : shstrtab->get_offset(name));
3312a6b7db3Sskrll   oshdr.put_sh_type(type);
3322a6b7db3Sskrll   oshdr.put_sh_flags(flags);
3332a6b7db3Sskrll   oshdr.put_sh_addr(0);
3342a6b7db3Sskrll   oshdr.put_sh_offset(offset);
3352a6b7db3Sskrll   oshdr.put_sh_size(section_size);
3362a6b7db3Sskrll   oshdr.put_sh_link(link);
3372a6b7db3Sskrll   oshdr.put_sh_info(info);
3382a6b7db3Sskrll   oshdr.put_sh_addralign(addralign);
3392a6b7db3Sskrll   oshdr.put_sh_entsize(entsize);
3402a6b7db3Sskrll 
3412a6b7db3Sskrll   *ppout += elfcpp::Elf_sizes<size>::shdr_size;
3422a6b7db3Sskrll }
3432a6b7db3Sskrll 
3442a6b7db3Sskrll // Write out a symbol.
3452a6b7db3Sskrll 
3462a6b7db3Sskrll template<int size, bool big_endian>
3472a6b7db3Sskrll void
write_symbol(const std::string & name,const Stringpool * strtab,section_size_type value,typename elfcpp::Elf_types<32>::Elf_WXword st_size,unsigned int shndx,unsigned char ** ppout)3482a6b7db3Sskrll Binary_to_elf::write_symbol(
3492a6b7db3Sskrll     const std::string& name,
3502a6b7db3Sskrll     const Stringpool* strtab,
3512a6b7db3Sskrll     section_size_type value,
3525ba6b03cSchristos     typename elfcpp::Elf_types<32>::Elf_WXword st_size,
3532a6b7db3Sskrll     unsigned int shndx,
3542a6b7db3Sskrll     unsigned char** ppout)
3552a6b7db3Sskrll {
3562a6b7db3Sskrll   unsigned char* pout = *ppout;
3572a6b7db3Sskrll 
3582a6b7db3Sskrll   elfcpp::Sym_write<size, big_endian> osym(pout);
3592a6b7db3Sskrll   osym.put_st_name(name.empty() ? 0 : strtab->get_offset(name.c_str()));
3602a6b7db3Sskrll   osym.put_st_value(value);
3615ba6b03cSchristos   osym.put_st_size(st_size);
3622a6b7db3Sskrll   osym.put_st_info(name.empty() ? elfcpp::STB_LOCAL : elfcpp::STB_GLOBAL,
3632a6b7db3Sskrll 		   elfcpp::STT_NOTYPE);
3642a6b7db3Sskrll   osym.put_st_other(elfcpp::STV_DEFAULT, 0);
3652a6b7db3Sskrll   osym.put_st_shndx(shndx);
3662a6b7db3Sskrll 
3672a6b7db3Sskrll   *ppout += elfcpp::Elf_sizes<size>::sym_size;
3682a6b7db3Sskrll }
3692a6b7db3Sskrll 
3702a6b7db3Sskrll } // End namespace gold.
371