00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pch.h>
00033
00034 #include "Emu/Utility/System/Loader/ElfReader.h"
00035
00036 #include <ios>
00037 #include <algorithm>
00038 #include <cstring>
00039 #include <limits>
00040
00041 #include "SysDeps/Endian.h"
00042
00043 using namespace std;
00044 using namespace Onikiri;
00045 using namespace Onikiri::EmulatorUtility;
00046
00047 ElfReader::ElfReader()
00048 {
00049 m_sectionNameTable = 0;
00050 m_bigEndian = false;
00051 }
00052
00053 ElfReader::~ElfReader()
00054 {
00055 delete[] m_sectionNameTable;
00056 }
00057
00058 void ElfReader::Open(const char *name)
00059 {
00060 m_file.open(name, ios_base::in | ios_base::binary);
00061 if (m_file.fail()) {
00062 stringstream ss;
00063 ss << "'" << name << "' : cannot open file";
00064 throw runtime_error(ss.str());
00065 }
00066
00067 try {
00068 ReadELFHeader();
00069 ReadSectionHeaders();
00070 ReadProgramHeaders();
00071 ReadSectionNameTable();
00072 }
00073 catch (runtime_error& e) {
00074 m_file.close();
00075
00076 stringstream ss;
00077 ss << "'" << name << "' : " << e.what();
00078 throw runtime_error(ss.str());
00079 }
00080 }
00081
00082 void ElfReader::ReadELFHeader()
00083 {
00084 m_file.read((char *)&m_elfHeader, sizeof(m_elfHeader));
00085 if (m_file.fail())
00086 throw runtime_error("cannot read ELF header");
00087
00088
00089 static const int CLASS_ELF64 = 2;
00090 if (!equal(&m_elfHeader.e_ident[0], &m_elfHeader.e_ident[3], "\177ELF") && m_elfHeader.e_ident[4] != CLASS_ELF64)
00091 throw runtime_error("not a valid ELF file");
00092
00093
00094 static const int DATA_LE = 1;
00095 static const int DATA_BE = 2;
00096 switch (m_elfHeader.e_ident[5]) {
00097 case DATA_LE:
00098 m_bigEndian = false;
00099 break;
00100 case DATA_BE:
00101 m_bigEndian = true;
00102 break;
00103 default:
00104 throw runtime_error("unknown endian type");
00105 }
00106
00107 EndianSpecifiedToHostInPlace(m_elfHeader, m_bigEndian);
00108
00109
00110 if (m_elfHeader.e_ehsize != sizeof(m_elfHeader) ||
00111 m_elfHeader.e_shentsize != sizeof(Elf_Shdr) ||
00112 m_elfHeader.e_phentsize != sizeof(Elf_Phdr))
00113 {
00114 throw runtime_error("invalid header size");
00115 }
00116 }
00117
00118 void ElfReader::ReadSectionHeaders()
00119 {
00120 const char* readError = "cannot read section headers";
00121
00122
00123 if (m_elfHeader.e_shoff == 0)
00124 return;
00125
00126 m_file.seekg(static_cast<istream::off_type>(m_elfHeader.e_shoff), ios_base::beg);
00127 if (m_file.fail())
00128 throw runtime_error(readError);
00129
00130
00131 m_elfSectionHeaders.clear();
00132 for (int i = 0; i < m_elfHeader.e_shnum; i ++) {
00133 Elf_Shdr sh;
00134
00135 m_file.read((char*)&sh, sizeof(sh));
00136 EndianSpecifiedToHostInPlace(sh, m_bigEndian);
00137 m_elfSectionHeaders.push_back(sh);
00138 }
00139
00140 if (m_file.fail())
00141 throw runtime_error(readError);
00142 }
00143
00144 void ElfReader::ReadProgramHeaders()
00145 {
00146 const char* readError = "cannot read program headers";
00147
00148
00149 if (m_elfHeader.e_phoff == 0)
00150 return;
00151
00152 m_file.seekg(static_cast<istream::off_type>(m_elfHeader.e_phoff), ios_base::beg);
00153 if (m_file.fail())
00154 throw runtime_error(readError);
00155
00156 m_elfProgramHeaders.clear();
00157 for (int i = 0; i < m_elfHeader.e_phnum; i ++) {
00158 Elf_Phdr ph;
00159
00160 m_file.read((char*)&ph, sizeof(ph));
00161 EndianSpecifiedToHostInPlace(ph, m_bigEndian);
00162 m_elfProgramHeaders.push_back(ph);
00163 }
00164
00165 if (m_file.fail())
00166 throw runtime_error(readError);
00167 }
00168
00169
00170 void ElfReader::ReadSectionNameTable()
00171 {
00172 if (m_elfHeader.e_shstrndx >= GetSectionHeaderCount())
00173 throw runtime_error("no section name table found");
00174
00175 int shstrndx = m_elfHeader.e_shstrndx;
00176 int shstrsize = static_cast<int>( GetSectionHeader(shstrndx).sh_size );
00177
00178 delete[] m_sectionNameTable;
00179 m_sectionNameTable = new char[ shstrsize ];
00180 ReadSectionBody(shstrndx, m_sectionNameTable, shstrsize);
00181 }
00182
00183 void ElfReader::Close()
00184 {
00185 m_file.close();
00186 }
00187
00188 void ElfReader::ReadSectionBody(int index, char *buf, size_t buf_size) const
00189 {
00190 const Elf_Shdr &sh = GetSectionHeader(index);
00191 if (buf_size != sh.sh_size)
00192 throw runtime_error("not enough buffer");
00193
00194 ReadRange((size_t)sh.sh_offset, buf, (size_t)sh.sh_size);
00195 }
00196
00197 void ElfReader::ReadRange(size_t offset, char *buf, size_t buf_size) const
00198 {
00199 m_file.seekg(static_cast<istream::off_type>(offset), ios_base::beg);
00200 m_file.read(buf, static_cast<std::streamsize>(buf_size));
00201
00202 if (m_file.fail())
00203 throw runtime_error("read error");
00204 }
00205
00206 const char *ElfReader::GetSectionName(int index) const
00207 {
00208 const Elf_Shdr &sh = GetSectionHeader(index);
00209
00210 return m_sectionNameTable + sh.sh_name;
00211 }
00212
00213 int ElfReader::FindSection(const char *name) const
00214 {
00215 for (int i = 0; i < GetSectionHeaderCount(); i++) {
00216 if (strcmp(GetSectionName(i), name) == 0)
00217 return i;
00218 }
00219
00220 return -1;
00221 }
00222
00223 streamsize ElfReader::GetImageSize() const
00224 {
00225 m_file.seekg(0, ios_base::end);
00226 return m_file.tellg();
00227 }
00228
00229 void ElfReader::ReadImage(char *buf, size_t buf_size) const
00230 {
00231 streamsize size = GetImageSize();
00232 if ((streamsize)buf_size < size)
00233 throw runtime_error("read error");
00234
00235 m_file.seekg(0, ios_base::beg);
00236 m_file.read(buf, static_cast<std::streamoff>(size));
00237
00238 if (m_file.fail())
00239 throw runtime_error("read error");
00240 }
00241
00242
00243 int ElfReader::GetClass() const
00244 {
00245 return m_elfHeader.e_ident[EI_CLASS];
00246 }
00247
00248 int ElfReader::GetDataEncoding() const
00249 {
00250 return m_elfHeader.e_ident[EI_DATA];
00251 }
00252
00253 int ElfReader::GetVersion() const
00254 {
00255 return m_elfHeader.e_ident[EI_VERSION];
00256 }
00257
00258 u16 ElfReader::GetMachine() const
00259 {
00260 return m_elfHeader.e_machine;
00261 }
00262
00263 bool ElfReader::IsBigEndian() const
00264 {
00265 return m_bigEndian;
00266 }
00267
00268 ElfReader::Elf_Addr ElfReader::GetEntryPoint() const
00269 {
00270 return m_elfHeader.e_entry;
00271 }
00272
00273 ElfReader::Elf_Off ElfReader::GetSectionHeaderOffset() const
00274 {
00275 return m_elfHeader.e_shoff;
00276 }
00277
00278 ElfReader::Elf_Off ElfReader::GetProgramHeaderOffset() const
00279 {
00280 return m_elfHeader.e_phoff;
00281 }
00282
00283 int ElfReader::GetSectionHeaderCount() const
00284 {
00285
00286 return (int)m_elfSectionHeaders.size();
00287 }
00288
00289 int ElfReader::GetProgramHeaderCount() const
00290 {
00291 return (int)m_elfProgramHeaders.size();
00292 }
00293
00294 const ElfReader::Elf_Shdr &ElfReader::GetSectionHeader(int index) const
00295 {
00296 return m_elfSectionHeaders[index];
00297 }
00298
00299 const ElfReader::Elf_Phdr &ElfReader::GetProgramHeader(int index) const
00300 {
00301 return m_elfProgramHeaders[index];
00302 }