OSDN Git Service

Sメーター周りを修正
[trx-305dsp/dsp.git] / trx305 / kernel / cfg / base / fc_windows.cpp
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
13  *  利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  * 
31  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: fc_windows.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 #if (defined(FILECONTAINER_WINDOWS) || defined(TESTSUITE)) && defined(_MSC_VER)
40
41 #pragma warning(disable:4786)
42
43 #include "base/filecontainer.h"
44 #include <windows.h>
45 #include <imagehlp.h>
46 #include <string>
47
48 using namespace std;
49
50 namespace {
51
52     class FileContainerWindowsImpl : public FileContainer
53     {
54     protected:
55         HANDLE          process;
56         LOADED_IMAGE    image;
57         DWORD           base;
58
59         inline bool isLoaded(void) const
60         {   return base != 0;   }
61
62     public:
63         FileContainerWindowsImpl(void) throw();
64         virtual ~FileContainerWindowsImpl(void) throw();
65
66             /* インタフェース部 */
67         virtual void        attachModule(const string & filename) throw(Exception);
68         virtual void        loadContents(void * dest, address_t address, size_t size) throw(Exception);
69         virtual address_t   getSymbolAddress(const string & symbol) throw(Exception);
70         virtual std::string getArchitecture(void) throw();
71
72         TESTSUITE_PROTOTYPE(main)
73     };
74
75     FileContainerWindowsImpl instance_of_FileContaienrWindowsImpl;
76
77         /* コンストラクタ */
78     FileContainerWindowsImpl::FileContainerWindowsImpl(void) throw()
79         : process(NULL), image(), base(0)
80     {}
81
82         /* デストラクタ */
83     FileContainerWindowsImpl::~FileContainerWindowsImpl(void) throw()
84     {
85         if(isLoaded()) {
86             ::UnMapAndLoad(&image);
87             ::SymUnloadModule(process, base);
88             process = NULL;
89             base    = 0;
90         }
91     }
92
93         /* 対象モジュールの割付 */
94     void FileContainerWindowsImpl::attachModule(const std::string & _filename) throw(Exception)
95     {
96         string filename(_filename);
97
98         process = ::GetCurrentProcess();
99         if(::SymInitialize( process , NULL, FALSE) == FALSE)
100             ExceptionMessage("[Internal Error] ImageHelper API initialization failure","[内部エラー] 初期化に失敗しました (ImageHlp)").throwException();
101
102         base = ::SymLoadModule(process, NULL, (PSTR)filename.c_str(), NULL, 0, 0);
103
104         image.SizeOfImage = sizeof(LOADED_IMAGE);
105         if(::MapAndLoad((PSTR)filename.c_str(), NULL, &image, FALSE, TRUE) == FALSE)
106             ExceptionMessage("[Internel error] Module loading failure [%]","[内部エラー] モジュールの読み込みに失敗しました [%]") << filename << throwException;
107     }
108
109         /* 内容の取得 */
110     void FileContainerWindowsImpl::loadContents(void * dest, address_t address, size_t size) throw(Exception)
111     {
112         PIMAGE_SECTION_HEADER header;
113         unsigned int i;
114
115         address -= base;
116         for(i=0;i<image.NumberOfSections;i++) {
117             header = image.Sections+i;
118             if(address >= header->VirtualAddress && address < header->VirtualAddress + header->SizeOfRawData) {
119                 address -= header->VirtualAddress - header->PointerToRawData;
120                 ::CopyMemory(dest,image.MappedAddress + address,size);
121                 break;
122             }
123         }
124
125         if(i == image.NumberOfSections)
126             ExceptionMessage("[Internel error] Memory read with unmapped address","[内部エラー] マップされてないアドレスを使ってメモリリードが行われました").throwException();
127     }
128
129         /* シンボルアドレスの解決 */
130     FileContainer::address_t FileContainerWindowsImpl::getSymbolAddress(const string & _symbol) throw(Exception)
131     {
132         FileContainer::address_t result = 0;
133         string symbol(_symbol);
134         IMAGEHLP_SYMBOL sym;
135
136         if(process == NULL || base == 0)
137             ExceptionMessage("Not initialized","初期化されてません").throwException();
138
139         sym.SizeOfStruct = sizeof(sym);
140         sym.MaxNameLength = 0;
141
142         if(::SymGetSymFromName(process, (PSTR)symbol.c_str(), &sym) == TRUE)
143             result = static_cast<FileContainer::address_t>(sym.Address);
144      
145         if(result == 0)
146             ExceptionMessage("Unknown symbol [%]","不正なシンボル名 [%]") << symbol << throwException;
147
148         return static_cast<FileContainer::address_t>(sym.Address);
149     }
150
151     string FileContainerWindowsImpl::getArchitecture(void) throw()
152     {   return "Windows (Win32)";   }
153
154 }
155
156 //---------------------------------------------
157
158 #ifdef TESTSUITE
159 #include "base/coverage_undefs.h"
160
161 #pragma warning(disable:4311) //'reinterpret_cast' : ポインタを 'const int *__w64 ' から 'FileContainer::address_t' へ切り詰めます。
162
163 extern "C" const int FileContainerWindowsImplTestVariable = 0x01234567;
164 extern "C" const int _FileContainerWindowsImplTestVariableWithUnderbar = 0x89abcdef;
165
166 TESTSUITE(main, FileContainerWindowsImpl)
167 {
168     PREDECESSOR("TFileContainer");
169
170     SingletonBase::ContextChain chain;
171     chain.saveContext<RuntimeObjectTable>();
172     chain.renewInstance();
173
174     BEGIN_CASE("attachModule","attachModule") {
175         BEGIN_CASE("1","実行しているプログラムが開けるか") {
176             FileContainerWindowsImpl fcwi;
177             bool result = true;
178             try { fcwi.attachModule(TestSuite::getProgName()); } catch(...) { result = false; }
179             
180             TEST_CASE("1", "例外は起きない", result);
181         } END_CASE;
182
183         BEGIN_CASE("2","存在しないファイル名で例外") {
184             FileContainerWindowsImpl fcwi;
185             bool result = false;
186             try { fcwi.attachModule("..."); } catch(...) { result = true; }
187             
188             TEST_CASE("1", "例外が起きる", result);
189         } END_CASE;
190     } END_CASE;
191
192     BEGIN_CASE("getSymbolAddress","getSymbolAddress") {
193         FileContainerWindowsImpl fcwi;
194
195         BEGIN_CASE("1","初期化していない状態で検索する") {
196             bool result = false;
197             try { fcwi.getSymbolAddress("FileContainerWindowsImplTestVariable"); } catch(...) { result = true; }
198             TEST_CASE("1","例外がおきる", result);
199         } END_CASE;
200
201         fcwi.attachModule(TestSuite::getProgName());
202
203         BEGIN_CASE("2","存在するシンボルを検索する") {
204             FileContainer::address_t addr = 0;
205             bool result = true;
206
207             try { addr = fcwi.getSymbolAddress("FileContainerWindowsImplTestVariable"); } catch(...) { result = false; }
208
209             TEST_CASE("1","例外は起きない", result);
210             TEST_CASE("2","アドレスが正しい", addr == reinterpret_cast<FileContainer::address_t>(&FileContainerWindowsImplTestVariable));
211         } END_CASE;
212
213         BEGIN_CASE("3","余計な_を勝手に付加しない") {
214             FileContainer::address_t addr = 0;
215             bool result = false;
216
217             try { addr = fcwi.getSymbolAddress("FileContainerWindowsImplTestVariableWithUnderbar"); } catch(...) { result = true; }
218
219             TEST_CASE("1","例外が起きる", result);
220             TEST_CASE("2","アドレスは0のまま", addr == 0);
221         } END_CASE;
222
223         BEGIN_CASE("4","存在しないシンボルを検索する") {
224             FileContainer::address_t addr = 0;
225             bool result = false;
226
227             try { addr = fcwi.getSymbolAddress("____unknown____"); } catch(...) { result = true; }
228
229             TEST_CASE("1","例外がおきる", result);
230         } END_CASE;
231     } END_CASE;
232
233     BEGIN_CASE("loadContents","loadContents") {
234         FileContainerWindowsImpl fcwi;
235         fcwi.attachModule(TestSuite::getProgName());
236
237         BEGIN_CASE("1","存在する変数を読み出す") {
238             FileContainer::address_t addr;
239             int i;
240
241             addr = fcwi.getSymbolAddress("FileContainerWindowsImplTestVariable");
242             bool result = true;
243             try { fcwi.loadContents(&i, addr, sizeof(i)); } catch(...) { result = false; }
244
245             TEST_CASE("1","例外は起きない", result);
246             TEST_CASE("2","読み出された内容は正しい", i == FileContainerWindowsImplTestVariable);
247         } END_CASE;
248
249         BEGIN_CASE("2","存在しない変数を読み出す") {
250             FileContainer::address_t addr;
251             int i;
252
253             addr = ~0;
254             bool result = false;
255             try { fcwi.loadContents(&i, addr, sizeof(i)); } catch(Exception &) { result = true; }
256
257             TEST_CASE("1","例外が起こる", result);
258         } END_CASE;
259
260     } END_CASE;
261
262     chain.restoreContext();
263 }
264
265 #endif /* TESTSUITE */
266
267 #endif /* FILECONTAINER_WINDOWS || TESTSUITE */
268