src/Emu/Utility/System/Loader/Linux64Loader.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/Linux64Loader.h"
00035 
00036 #include "SysDeps/posix.h"
00037 #include "Emu/Utility/System/Memory/MemorySystem.h"
00038 #include "Emu/Utility/System/Memory/MemoryUtility.h"
00039 #include "Emu/Utility/System/Loader/ElfReader.h"
00040 
00041 using namespace std;
00042 using namespace boost;
00043 using namespace Onikiri;
00044 using namespace Onikiri::POSIX;
00045 using namespace Onikiri::EmulatorUtility;
00046 
00047 Linux64Loader::Linux64Loader(u16 machine)
00048     : m_imageBase(0), m_entryPoint(0), m_initialSp(0), m_machine(machine)
00049 {
00050 
00051 }
00052 
00053 Linux64Loader::~Linux64Loader()
00054 {
00055 }
00056 
00057 void Linux64Loader::LoadBinary(MemorySystem* memory, const String& command)
00058 {
00059     ElfReader elfReader;
00060 
00061     try {
00062         elfReader.Open(command.c_str());
00063 
00064         if (elfReader.GetMachine() != m_machine)
00065             throw runtime_error((command + " : machine type does not match").c_str());
00066 
00067         m_bigEndian = elfReader.IsBigEndian();
00068 
00069         u64 initialBrk = 0;
00070         for (int i = 0; i < elfReader.GetProgramHeaderCount(); i ++) {
00071             const ElfReader::Elf_Phdr &ph = elfReader.GetProgramHeader(i);
00072 
00073             VIRTUAL_MEMORY_ATTR_TYPE pageAttr =
00074                 VIRTUAL_MEMORY_ATTR_READ | VIRTUAL_MEMORY_ATTR_WRITE;
00075 
00076             // Do not add a writable attribute to a code page.
00077             if(ph.p_flags & PF_X){
00078                 pageAttr = VIRTUAL_MEMORY_ATTR_READ | VIRTUAL_MEMORY_ATTR_EXEC;
00079             }
00080 
00081             // ZOgAhXCZOg
00082             if (ph.p_type == PT_LOAD) {
00083                 if (ph.p_offset == 0)
00084                     m_imageBase = ph.p_vaddr;
00085                 memory->AssignPhysicalMemory(ph.p_vaddr, ph.p_memsz, pageAttr);
00086                 TargetBuffer buf(memory, ph.p_vaddr, static_cast<size_t>(ph.p_filesz));
00087                 elfReader.ReadRange(static_cast<size_t>(ph.p_offset), (char*)buf.Get(), static_cast<size_t>(ph.p_filesz));
00088 
00089                 initialBrk = max(initialBrk, ph.p_vaddr+ph.p_memsz);
00090 
00091                 if( memory->GetReservedAddressRange() >= ph.p_vaddr ){
00092                     THROW_RUNTIME_ERROR( "Reserved address region is too large.");
00093                 }
00094             }
00095             //if (ph.p_flags & PF_W && writable_base == 0) {
00096             //}
00097 
00098             // タsZOg1
00099             if (ph.p_flags & PF_X) {
00100                 m_codeRange.first = ph.p_vaddr;
00101                 m_codeRange.second = static_cast<size_t>(ph.p_memsz);
00102             }
00103         }
00104         ASSERT(m_imageBase != 0);
00105 
00106         memory->SetInitialBrk(initialBrk);
00107 
00108         m_elfProgramHeaderOffset = elfReader.GetProgramHeaderOffset();
00109         m_elfProgramHeaderCount = elfReader.GetProgramHeaderCount();
00110 
00111         // Gg|CgvZ
00112         m_entryPoint = CalculateEntryPoint(memory, elfReader);
00113         CalculateOthers(memory, elfReader);
00114     }
00115     catch (runtime_error& e) {
00116         THROW_RUNTIME_ERROR(e.what());
00117     }
00118 }
00119 
00120 void Linux64Loader::InitArgs(MemorySystem* memory, u64 stackHead, u64 stackSize, const String& command, const String& commandArgs)
00121 {
00122     u64 sp = stackHead+stackSize;
00123 
00124     // 
00125     std::vector<String> stringArgs = commandArgs.split(" ");
00126     int argc = (int)stringArgs.size()+1;
00127     scoped_array<const char *> argv(new const char*[argc+1]);
00128 
00129     argv[0] = command.c_str();
00130     for (int i = 1; i < argc; i ++) {
00131         argv[i] = stringArgs[i-1].c_str();
00132     }
00133     argv[argc] = NULL;
00134 
00135     // X^bNRs[
00136     scoped_array<u64> target_argv ( new u64 [argc+1] );
00137     for (int i = 0; i <= argc; i ++) {
00138         if (argv[i]) {
00139             size_t len = strlen(argv[i]);
00140             sp -= len+1;
00141             memory->MemCopyToTarget(sp, argv[i], len+1);
00142             target_argv[i] = sp;
00143         }
00144         else {
00145             target_argv[i] = 0;
00146         }
00147     }
00148     sp -= sp % sizeof(u64);
00149 
00150     // <Linux>
00151     // stack : argc, argv[argc-1], NULL, environ[], NULL, auxv[], NULL
00152 
00153     // Auxiliary Vector 
00154     ELF64_AUXV auxv;
00155 
00156     const int uid = posix_getuid(), gid = posix_getgid(), euid = posix_geteuid(), egid = posix_getegid();
00157 
00158     sp -= sizeof(ELF64_AUXV);
00159     auxv.a_type = EndianHostToSpecified((u64)AT_NULL, m_bigEndian);
00160     auxv.a_un.a_val = 0;
00161     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00162 
00163     sp -= sizeof(ELF64_AUXV);
00164     auxv.a_type = EndianHostToSpecified((u64)AT_PHDR, m_bigEndian);
00165     auxv.a_un.a_val = EndianHostToSpecified((u64)(m_imageBase + m_elfProgramHeaderOffset), m_bigEndian);
00166     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00167 
00168     sp -= sizeof(ELF64_AUXV);
00169     auxv.a_type = EndianHostToSpecified((u64)AT_PHNUM, m_bigEndian);
00170     auxv.a_un.a_val = EndianHostToSpecified((u64)m_elfProgramHeaderCount, m_bigEndian);
00171     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00172 
00173     sp -= sizeof(ELF64_AUXV);
00174     auxv.a_type = EndianHostToSpecified((u64)AT_PHENT, m_bigEndian);
00175     auxv.a_un.a_val = EndianHostToSpecified((u64)sizeof(ElfReader::Elf_Phdr), m_bigEndian);
00176     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00177 
00178     sp -= sizeof(ELF64_AUXV);
00179     auxv.a_type = EndianHostToSpecified((u64)AT_PAGESZ, m_bigEndian);
00180     auxv.a_un.a_val = EndianHostToSpecified((u64)memory->GetPageSize(), m_bigEndian);
00181     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00182 
00183     sp -= sizeof(ELF64_AUXV);
00184     auxv.a_type = EndianHostToSpecified((u64)AT_BASE, m_bigEndian);
00185     auxv.a_un.a_val = 0;
00186     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00187 
00188     sp -= sizeof(ELF64_AUXV);
00189     auxv.a_type = EndianHostToSpecified((u64)AT_UID, m_bigEndian);
00190     auxv.a_un.a_val = EndianHostToSpecified((u64)uid, m_bigEndian);
00191     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00192 
00193     sp -= sizeof(ELF64_AUXV);
00194     auxv.a_type = EndianHostToSpecified((u64)AT_EUID, m_bigEndian);
00195     auxv.a_un.a_val = EndianHostToSpecified((u64)euid, m_bigEndian);
00196     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00197 
00198     sp -= sizeof(ELF64_AUXV);
00199     auxv.a_type = EndianHostToSpecified((u64)AT_GID, m_bigEndian);
00200     auxv.a_un.a_val = EndianHostToSpecified((u64)gid, m_bigEndian);
00201     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00202 
00203     sp -= sizeof(ELF64_AUXV);
00204     auxv.a_type = EndianHostToSpecified((u64)AT_EGID, m_bigEndian);
00205     auxv.a_un.a_val = EndianHostToSpecified((u64)egid, m_bigEndian);
00206     memory->MemCopyToTarget(sp, &auxv, sizeof(ELF64_AUXV));
00207 
00208     sp -= sizeof(u64); // NULL
00209     // environ
00210     sp -= sizeof(u64);
00211     WriteMemory( memory, sp, sizeof(u64), sp-8);    // argv[argc] (== NULL) w
00212 
00213     sp -= sizeof(u64); // NULL
00214     // argv
00215     for (int i = 0; i <= argc; i ++) {
00216         sp -= sizeof(u64);
00217         WriteMemory( memory, sp, sizeof(u64), target_argv[argc-i]);
00218     }
00219 
00220     // argc
00221     sp -= sizeof(u64);
00222     WriteMemory( memory, sp, sizeof(u64), argc);
00223 
00224     m_initialSp = sp;
00225 }
00226 
00227 // Memory write
00228 void Linux64Loader::WriteMemory( MemorySystem* memory, u64 address, int size, u64 value )
00229 {
00230     EmuMemAccess access( address, size, value );
00231     memory->WriteMemory( &access );
00232 }
00233 
00234 u64 Linux64Loader::GetImageBase() const
00235 {
00236     return m_imageBase;
00237 }
00238 
00239 u64 Linux64Loader::GetEntryPoint() const
00240 {
00241     return m_entryPoint;
00242 }
00243 
00244 std::pair<u64, size_t> Linux64Loader::GetCodeRange() const
00245 {
00246     return m_codeRange;
00247 }
00248 
00249 u64 Linux64Loader::GetInitialSp() const
00250 {
00251     return m_initialSp;
00252 }
00253 
00254 bool Linux64Loader::IsBigEndian() const
00255 {
00256     return m_bigEndian;
00257 }
00258 
00259 u64 Linux64Loader::CalculateEntryPoint(EmulatorUtility::MemorySystem* memory, const ElfReader& elfReader)
00260 {
00261     return elfReader.GetEntryPoint();
00262 }
00263 
00264 // ElfReader gvZ
00265 void Linux64Loader::CalculateOthers(EmulatorUtility::MemorySystem* memory, const ElfReader& elfReader)
00266 {
00267     // ftHg
00268 }

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