OSDN Git Service

Doxygenコメントを追加した。
[uzume/uzume_bfin.git] / uzume_prototype / kernel / cfg / base / fc_bfd.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_bfd.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39
40 #include "base/filecontainer.h"
41
42 #include "base/message.h"
43
44 #include "bfd.h"
45 #include "libiberty.h"
46
47 #include <string>
48 #include <map>
49
50 using namespace std;
51
52
53 /*
54  *  BFDを使ったファイルコンテナクラス
55  */
56 class filecontainer_BFD : public filecontainer
57 {
58 protected:
59     bfd * object;                           //オブジェクト
60     map<string, asymbol *> symbol_table;    //検索用ハッシュもどき
61     asymbol ** symbol_container;
62
63 public:
64     filecontainer_BFD(void)  throw();
65     ~filecontainer_BFD(void) throw();
66
67     virtual bool attach_module(const char *);
68     virtual bool change_endian(void * target, unsigned int size);
69     virtual bool load_contents(void * dest, unsigned long address, unsigned int size);
70     virtual unsigned long get_symbol_address(const char *);
71     virtual const char * get_architecture(void);
72
73 } Instance_of_filecontainer_BFD;
74
75 filecontainer_BFD::filecontainer_BFD(void) throw()
76 {
77     bfd_init();
78
79     object = NULL;
80     symbol_table.clear();
81     symbol_container = NULL;
82     instance = this;
83 }
84
85 filecontainer_BFD::~filecontainer_BFD(void) throw()
86 {
87     if(object != NULL)
88         bfd_close(object);
89 }
90
91 /*
92  *  attach_module : 対象モジュールをアタッチする
93  */
94 bool filecontainer_BFD::attach_module(const char * filename)
95 {
96     char ** target_list;
97     asymbol ** symbols;
98     asymbol *  sym;
99     int num_syms;
100     boolean result;
101     int i;
102
103     if(object != NULL)
104         bfd_close(object);
105     symbol_table.clear();
106
107         //モジュールオープン (読込用)
108     object = bfd_openr(filename, "default");
109
110         //ターゲット解決
111     target_list = (char **)bfd_target_list();
112     result = bfd_check_format_matches(object, bfd_object, &target_list);
113     if(result == 0)
114         ExceptionMessage("Internel error: BFD could not recognize the target file format.","内部エラー: BFDはファイルの読み出しに失敗しました").throwException();
115
116         //シンボルのハッシュもどき作成
117     symbols = (asymbol **)xmalloc( bfd_get_symtab_upper_bound(object) );
118     num_syms = bfd_canonicalize_symtab(object, symbols);
119
120     for(i=0;i<num_syms;i++)
121     {
122         sym = *(symbols+i);
123         if(sym != NULL && sym->name != NULL && *(sym->name) != '\x0')
124             symbol_table[string(sym->name)] = sym;
125     }
126
127     symbol_container = symbols;
128     return true;
129 }
130
131 bool filecontainer_BFD::change_endian(void * target, unsigned int size)
132 {
133         //ホストはリトルと仮定
134     enum bfd_endian host_endian = BFD_ENDIAN_LITTLE;
135
136     char * top, * tail;
137
138     if(object == NULL)
139         return false;
140
141     if(object->xvec->byteorder == BFD_ENDIAN_UNKNOWN)
142         return false;
143
144 /*
145     unsigned int __work = 0x1;
146     if( *(char *)__work == 0)
147         host_endian = BFD_ENDIAN_BIG;
148 */
149
150     if(object->xvec->byteorder == host_endian)
151         return true;
152
153     /*
154      *  メインループ : bswapしないで、素直に書く
155      */
156
157     top  = (char *)target;
158     tail = (char *)target+size -1;
159
160     while(top < tail)
161     {
162         *top ^= *tail, *tail ^= *top, *top ^= *tail;
163         top ++;
164         tail --;
165     }
166
167     return true;
168 }
169
170
171 bool filecontainer_BFD::load_contents(void * dest, unsigned long address, unsigned int size)
172 {
173     struct sec * section;
174
175     if(object == 0)
176         return false;
177
178         //対象アドレスを保有するセクションを探す
179     section = object->sections;
180     while(section != 0)
181     {
182         if(address - (unsigned long)section->vma <= section->_raw_size 
183             && (section->flags & (SEC_ALLOC|SEC_HAS_CONTENTS)) == (SEC_ALLOC|SEC_HAS_CONTENTS))
184         {
185                 //読み出し
186             bfd_get_section_contents(object, section, dest, address - (unsigned long)section->vma, size);
187             return true;
188         }
189         section = section->next;
190     }
191
192         //どこにもない
193     ExceptionMessage("Internel error: Memory read with unmapped address","内部エラー; マップされてないアドレスを使ってメモリリードが行われました").throwException();
194
195     return false;
196 }
197
198
199 /*
200  * get_symbol_address : シンボル名からアドレス値を取得する
201  */
202 unsigned long filecontainer_BFD::get_symbol_address(const char * symbol)
203 {
204     map<string, asymbol *>::iterator scope;
205     string symbol_name;
206
207     if(object == 0)
208         ExceptionMessage("Not initialized","初期化されてません").throwException();
209
210         //シンボル名を生成する ("_"とかの処理)
211     if(object->xvec->symbol_leading_char != '\x0')
212         symbol_name += object->xvec->symbol_leading_char;
213     symbol_name += symbol;
214
215     scope = symbol_table.find(symbol_name);
216     if(scope == symbol_table.end())
217         return 0;
218         //Exception("Internal error: Unknown symbol [%s]","内部エラー: 不明なシンボル [%s]").format(symbol_name.c_str());
219
220         //Address = セクション内オフセット値 + セクションのVMA
221     return (*scope).second->value + (*scope).second->section->vma;
222 }
223
224 /*
225  * get_architecture : アーキテクチャ名の取得
226  */
227 const char * filecontainer_BFD::get_architecture(void)
228 {
229     if(object == NULL)
230         return "Unknown";
231
232         //とりあえずターゲット名を持ってアーキテクチャ名にしておく。
233         // #どうせバナーにしか使ってないしね 今のところ
234     return object->xvec->name;
235 }
236