src/Emu/Utility/System/ProcessState.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/ProcessState.h"
00035 
00036 #include "Env/Env.h"
00037 #include "SysDeps/posix.h"
00038 
00039 #include "Emu/Utility/System/VirtualSystem.h"
00040 #include "Emu/Utility/System/Syscall/SyscallConvIF.h"
00041 #include "Emu/Utility/System/Memory/MemorySystem.h"
00042 #include "Emu/Utility/System/Loader/LoaderIF.h"
00043 
00044 using namespace std;
00045 using namespace boost;
00046 using namespace Onikiri;
00047 using namespace Onikiri::EmulatorUtility;
00048 using namespace Onikiri::POSIX;
00049 
00050 static string CompletePath(string relative, const string& base)
00051 {
00052     if(relative.empty())
00053         relative = ".";
00054 
00055     return
00056         filesystem::absolute(
00057             filesystem::path( relative ),
00058             filesystem::path( base ) 
00059         ).string();
00060 
00061 }
00062 
00063 
00064 ProcessCreateParam::ProcessCreateParam(int processNumber) : 
00065     m_processNumber(processNumber), 
00066     m_stackMegaBytes(0)
00067 {
00068     LoadParam();
00069 }
00070 
00071 ProcessCreateParam::~ProcessCreateParam()
00072 {
00073     ReleaseParam();
00074 }
00075 
00076 const String ProcessCreateParam::GetTargetBasePath() const
00077 {
00078     ParamXMLPath xPath;
00079     xPath.AddArray( 
00080         "/Session/Emulator/Processes/Process",
00081         m_processNumber 
00082     );
00083     xPath.AddAttribute( "TargetBasePath" );
00084     String xmlFilePath;
00085 
00086     bool found = g_paramDB.GetSourceXMLFile( xPath, xmlFilePath );
00087     if( !found ){
00088         THROW_RUNTIME_ERROR(
00089             "'TargetBasePath' ('%s') is not set. 'TargetBasePath' must be set in each 'Process' node.",
00090             xPath.ToString().c_str()
00091         );
00092     }
00093 
00094     filesystem::path xmlDirPath( xmlFilePath.c_str() );
00095     xmlDirPath.remove_filename();
00096 
00097     return CompletePath( 
00098         m_targetBasePath, 
00099         xmlDirPath.string()
00100     );
00101 }
00102 
00103 ProcessState::ProcessState(int pid)
00104     : m_pid(pid), m_threadUniqueValue(0)
00105 {
00106     m_loader = 0;
00107     m_syscallConv = 0;
00108 }
00109 
00110 ProcessState::~ProcessState()
00111 {
00112     for_each(
00113         m_autoCloseFile.begin(), 
00114         m_autoCloseFile.end(),
00115         fclose 
00116     );
00117 
00118     delete m_loader;
00119     delete m_syscallConv;
00120     delete m_virtualSystem;
00121     delete m_memorySystem;
00122 }
00123 
00124 u64 ProcessState::GetEntryPoint() const
00125 {
00126     return m_loader->GetEntryPoint();
00127 }
00128 
00129 u64 ProcessState::GetInitialRegValue(int index) const
00130 {
00131     return m_loader->GetInitialRegValue(index);
00132 }
00133 
00134 void ProcessState::SetThreadUniqueValue(u64 value)
00135 {
00136     m_threadUniqueValue = value;
00137 }
00138 
00139 u64 ProcessState::GetThreadUniqueValue()
00140 {
00141     return m_threadUniqueValue;
00142 }
00143 
00144 
00145 
00146 void ProcessState::Init(
00147     const ProcessCreateParam& pcp, 
00148     SystemIF* simSystem,
00149     SyscallConvIF* syscallConv, 
00150     LoaderIF* loader, 
00151     bool bigEndian )
00152 {
00153     try {
00154         m_memorySystem  = new MemorySystem( m_pid, bigEndian, simSystem );
00155         m_virtualSystem = new VirtualSystem();
00156 
00157         m_syscallConv = syscallConv;
00158         m_syscallConv->SetSystem( simSystem );
00159         m_loader = loader;
00160 
00161         string targetBase = pcp.GetTargetBasePath();
00162 
00163         m_virtualSystem->SetInitialWorkingDir(
00164             CompletePath( pcp.GetTargetWorkPath(), targetBase )
00165         );
00166 
00167         m_loader->LoadBinary(
00168             m_memorySystem,
00169             CompletePath( pcp.GetCommand(), targetBase )
00170         );
00171 
00172         m_codeRange = m_loader->GetCodeRange();
00173 
00174         // mmapgq[vCAhX0oCiC[W
00175         // Om (AhX0}bvP)
00176         //u64 heapBase = m_memorySystem->GetPageSize();
00177 
00178         // Sa\
00179         u64 heapBase = m_memorySystem->GetReservedAddressRange() + 1;
00180         m_memorySystem->AddHeapBlock(heapBase, m_loader->GetImageBase()-heapBase);
00181 
00182         InitStack(pcp);
00183 
00184         InitTargetStdIO(pcp);
00185     }
00186     catch (...) {
00187         delete m_loader;
00188         m_loader = 0;
00189         delete m_syscallConv;
00190         m_syscallConv = 0;
00191         delete m_virtualSystem;
00192         m_virtualSystem = 0;
00193         delete m_memorySystem;
00194         m_memorySystem = 0;
00195 
00196         throw;
00197     }
00198 }
00199 
00200 
00201 void ProcessState::InitStack(const ProcessCreateParam& pcp)
00202 {
00203     // X^bNm
00204     u64 stackMegaBytes = pcp.GetStackMegaBytes();
00205     if(stackMegaBytes <= 1){
00206         THROW_RUNTIME_ERROR("Stack size(%d MB) is too small.", stackMegaBytes);
00207     }
00208 
00209     u64 stackBytes = stackMegaBytes*1024*1024;
00210     u64 stack = m_memorySystem->MMap(0, stackBytes);
00211 
00212     // 
00213     string targetBase = pcp.GetTargetBasePath();
00214     m_loader->InitArgs(
00215         m_memorySystem,
00216         stack, 
00217         stackBytes, 
00218         CompletePath( pcp.GetCommand(), targetBase ),
00219         pcp.GetCommandArguments() );
00220 }
00221 
00222 void ProcessState::InitTargetStdIO(const ProcessCreateParam& pcp)
00223 {
00224     string targetBase = pcp.GetTargetBasePath();
00225     string targetWork = 
00226         CompletePath( pcp.GetTargetWorkPath(), targetBase );
00227 
00228 
00229     // stdin stdout stderr 
00230     String omode[3] = {"rt", "wt", "wt"};
00231     int std_fd[3] = 
00232     {
00233         posix_fileno(stdin), 
00234         posix_fileno(stdout), 
00235         posix_fileno(stderr)
00236     };
00237     String std_filename[3] = 
00238     {
00239         pcp.GetStdinFilename(),
00240         pcp.GetStdoutFilename(), 
00241         pcp.GetStderrFilename()
00242     };
00243 
00244     // STDIN t@CI[v[h
00245     if( pcp.GetStdinFileOpenMode() == "Text" ){
00246         omode[0] = "rt";
00247     }
00248     else if( pcp.GetStdinFileOpenMode() == "Binary" ){
00249         omode[0] = "rb";
00250     }
00251     else{
00252         THROW_RUNTIME_ERROR( "The file open mode of STDIN must be one of the following strings: 'Text', 'Binary'");
00253     }
00254 
00255     for (int i = 0; i < 3; i ++) {
00256         if (std_filename[i].empty()) {
00257             // owt@CzXgogp
00258             m_virtualSystem->AddFDMap(std_fd[i], std_fd[i], false);
00259             m_virtualSystem->GetDelayUnlinker()->AddMap(std_fd[i], "HostIO");
00260         }
00261         else {
00262             string filename = CompletePath(std_filename[i], targetWork );
00263             FILE *fp = fopen( filename.c_str(), omode[i].c_str() );
00264             if (fp == NULL) {
00265                 THROW_RUNTIME_ERROR("Cannot open file '%s'.", filename.c_str());
00266             }
00267             m_autoCloseFile.push_back(fp);
00268             m_virtualSystem->AddFDMap(std_fd[i], posix_fileno(fp), false);
00269             m_virtualSystem->GetDelayUnlinker()->AddMap(std_fd[i], filename);
00270         }
00271     }
00272 }

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