src/Emu/Utility/System/Loader/ElfReader.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
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     // ELF64`FbN
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     // GfBAo
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     // wb_TCYzlvG[
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     // ZNVwb_
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     // vOwb_
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     // XElf32_Half = 16bit
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 }

Onikiri2に対してTue Jun 18 14:34:20 2013に生成されました。  doxygen 1.4.7