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/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
00175
00176
00177
00178
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
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
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
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
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 }