- compare disk size with the size calculated from geometry to avoid image
[bochs-mirror.git] / bx_debug / symbols.cc
blobc40d1ff057e096695ffd5dde83c95297e6aa15a3
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: symbols.cc,v 1.7 2006/10/11 14:54:40 akrisak Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #include "bochs.h"
29 #include "cpu/cpu.h"
31 #if BX_DEBUGGER
32 #if !((BX_HAVE_HASH_MAP || BX_HAVE_HASH_MAP_H) && (BX_HAVE_SET || BX_HAVE_SET_H))
34 static char *BX_HAVE_HASH_MAP_ERR = "context not implemented because BX_HAVE_HASH_MAP=0\n";
36 char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
38 static bx_bool first = true;
39 if (first) {
40 dbg_printf(BX_HAVE_HASH_MAP_ERR);
41 first = false;
43 return "unk. ctxt";
46 char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
48 // just prints an error anyway
49 return bx_dbg_symbolic_address (0,0,0);
52 void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
54 dbg_printf(BX_HAVE_HASH_MAP_ERR);
57 void bx_dbg_info_symbols_command(char *Symbol)
59 dbg_printf(BX_HAVE_HASH_MAP_ERR);
62 int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
64 dbg_printf(BX_HAVE_HASH_MAP_ERR);
65 return -1;
68 Bit32u bx_dbg_get_symbol_value(char *Symbol)
70 return 0;
73 char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
75 return 0;
78 #else /* if BX_HAVE_HASH_MAP == 1 */
80 /* Haven't figured out how to port this code to OSF1 cxx compiler.
81 Until a more portable solution is found, at least make it easy
82 to disable the template code: just set BX_HAVE_HASH_MAP=0
83 in config.h */
84 #if BX_HAVE_HASH_MAP
85 #include <hash_map>
86 #elif BX_HAVE_HASH_MAP_H
87 #include <hash_map.h>
88 #endif
90 #if BX_HAVE_SET
91 #include <set>
92 #elif BX_HAVE_SET_H
93 #include <set.h>
94 #endif
96 using namespace std;
98 struct symbol_entry_t
100 symbol_entry_t (Bit32u _start = 0, char* _name = 0)
102 start = _start;
103 name = _name;
106 char* name;
107 Bit32u start;
110 struct lt_symbol_entry_t
112 bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
114 return s1->start < s2->start;
118 struct lt_rsymbol_entry_t
120 bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const
122 return strcoll(s1->name, s2->name) < 0;
126 struct context_t
128 context_t (Bit32u);
129 ~context_t();
130 static context_t* get_context(Bit32u);
131 symbol_entry_t* get_symbol_entry(Bit32u);
132 symbol_entry_t* get_symbol_entry(const char *Symbol) const;
133 void add_symbol(symbol_entry_t*);
134 const set<symbol_entry_t*,lt_symbol_entry_t>* get_all_symbols() const {return syms;}
135 const set<symbol_entry_t*,lt_rsymbol_entry_t>* get_all_rsymbols() const {return rsyms;}
136 private:
137 static hash_map<int,context_t*>* map;
138 // Forvard references (find name by address)
139 set<symbol_entry_t*,lt_symbol_entry_t>* syms;
140 // Reverse references (find address by name)
141 set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;
142 Bit32u id;
145 hash_map<int,context_t*>* context_t::map = new hash_map<int,context_t*>;
147 context_t::context_t (Bit32u _id)
149 id = _id;
150 syms = new set<symbol_entry_t*, lt_symbol_entry_t>;
151 rsyms = new set<symbol_entry_t*, lt_rsymbol_entry_t>;
152 (*map)[id] = this;
155 context_t::~context_t()
157 set<symbol_entry_t*>::iterator iter;
158 if(syms) {
159 for(iter=syms->begin();iter!=syms->end();++iter)
160 if(*iter)
161 delete *iter;
164 if(rsyms) {
165 for(iter=rsyms->begin();iter!=rsyms->end();++iter)
166 if(*iter)
167 delete *iter;
171 context_t* context_t::get_context(Bit32u i)
173 return (*map)[i];
176 symbol_entry_t* context_t::get_symbol_entry(Bit32u ip)
178 symbol_entry_t probe;
179 probe.start = ip;
180 // find the first symbol whose address is greater than ip.
181 if (syms->empty ()) return 0;
182 set<symbol_entry_t*>::iterator iter = syms->upper_bound(&probe);
184 if (iter == syms->end()) { // No symbol found
185 return 0;
188 return *(--iter);
191 symbol_entry_t* context_t::get_symbol_entry(const char *Symbol) const
193 symbol_entry_t probe;
194 probe.name=(char *)Symbol;
196 if (rsyms->empty ())
197 return 0;
199 set<symbol_entry_t*>::const_iterator iter;
200 iter=rsyms->find(&probe);
201 if(iter==rsyms->end()) // No symbol found
202 return 0;
203 return *iter;
206 void context_t::add_symbol(symbol_entry_t* sym)
208 syms->insert(sym);
209 rsyms->insert(sym);
212 Bit32u bx_dbg_get_symbol_value(char *Symbol)
214 context_t* cntx = context_t::get_context(0);
215 if(!cntx) // Context not found
216 return 0;
218 if (Symbol[0]=='\"') Symbol++;
219 int len = strlen(Symbol);
220 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';
222 symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
223 if(!sym) // Symbol not found
224 return 0;
226 return sym->start;
229 char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base)
231 static char buf[80];
232 #if 0
233 // bbd: I don't see why we shouldn't allow symbol lookups on
234 // segments with a nonzero base. I need to trace user
235 // processes in Linux, which have a base of 0xc0000000.
236 if (base != 0) {
237 snprintf (buf, 80, "non-zero base");
238 return buf;
240 #endif
241 // Look up this context
242 context_t* cntx = context_t::get_context(context);
243 if (!cntx) {
244 // Try global context
245 cntx = context_t::get_context(0);
246 if (!cntx) {
247 snprintf (buf, 80, "unk. ctxt");
248 return buf;
251 // full linear address not only eip (for nonzero based segments)
252 symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
253 if (!entr) {
254 snprintf (buf, 80, "no symbol");
255 return buf;
257 snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
258 return buf;
261 char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base)
263 static char buf[80];
265 // Try global context
266 context_t* cntx = context_t::get_context(0);
267 if (!cntx) {
268 return 0;
271 // full linear address not only eip (for nonzero based segments)
272 symbol_entry_t* entr = cntx->get_symbol_entry(base+eip);
273 if (!entr) {
274 return 0;
276 snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start);
277 return buf;
280 char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs)
282 // in 16-bit code, the segment selector and offset are combined into a
283 // 20-bit linear address = (segment selector<<4) + offset.
284 eip &= 0xffff;
285 cs &= 0xffff;
286 return bx_dbg_symbolic_address (0, eip+(cs<<4), 0);
289 void bx_dbg_symbol_command(char* filename, bx_bool global, Bit32u offset)
291 if (filename[0] == '"')
292 filename++;
293 int len = strlen(filename);
294 if (filename[len - 1] == '"')
295 filename[len - 1] = '\0';
297 // Install symbols in correct context (page table)
298 // The file format should be
299 // address symbol (example '00002afe _StartLoseNT')
301 context_t* cntx = (global) ? context_t::get_context(0)
302 : context_t::get_context((BX_CPU(dbg_cpu)->cr3) >> 12);
304 if (!cntx) {
305 cntx = (global) ? new context_t(0)
306 : new context_t((BX_CPU(dbg_cpu)->cr3) >> 12);
309 FILE* fp = fopen(filename, "rt"); // 't' is need for win32, unixes simply ignore it
310 if (!fp) {
311 dbg_printf ("Could not open symbol file '%s'\n", filename);
312 return;
314 char buf[200];
315 while (fgets(buf, 200, fp)) {
316 // Parse
317 char* sym_name = buf;
319 for (int i = 0; i < 200 && buf[i]; i++) {
320 if (buf[i] == ' ') {
321 buf[i] = '\0';
322 sym_name = buf + i + 1;
323 break;
326 if (sym_name == buf) {
327 dbg_printf ("Syntax error '%s'\n", buf);
328 break;
330 Bit32u addr = strtoul(buf, 0, 16);
331 if (sym_name[strlen(sym_name)-1] == '\n')
332 sym_name[strlen(sym_name)-1] = '\0';
333 symbol_entry_t* sym = new symbol_entry_t(addr + offset, strdup(sym_name));
334 cntx->add_symbol(sym);
338 // chack if s1 is prefix of s2
339 static bool bx_dbg_strprefix(const char *s1, const char *s2)
341 if(!s1 || !s2)
342 return false;
344 size_t len=strlen(s1);
346 if(len>strlen(s2))
347 return false;
348 return strncmp(s1, s2, len)==0;
351 void bx_dbg_info_symbols_command(char *Symbol)
353 context_t* cntx = context_t::get_context(0);
355 if(!cntx) {
356 dbg_printf ("Global context not available\n");
357 return;
360 if(Symbol) {
361 const set<symbol_entry_t*,lt_rsymbol_entry_t>* rsyms;
363 rsyms=cntx->get_all_rsymbols();
364 if (rsyms->empty ()) {
365 dbg_printf ("Symbols not loaded\n");
366 return;
368 // remove leading and trailing quotas
369 if (Symbol[0]=='\"') Symbol++;
370 int len = strlen(Symbol);
371 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';
373 symbol_entry_t probe;
374 probe.name=Symbol;
375 set<symbol_entry_t*>::const_iterator iter;
376 iter=rsyms->lower_bound(&probe);
378 if(iter==rsyms->end() || !bx_dbg_strprefix(Symbol, (*iter)->name))
379 dbg_printf ("No symbols found\n");
380 else
381 for(;iter!=rsyms->end() && bx_dbg_strprefix(Symbol, (*iter)->name);++iter) {
382 dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
385 else {
386 const set<symbol_entry_t*,lt_symbol_entry_t>* syms;
388 syms=cntx->get_all_symbols();
389 if (syms->empty ()) {
390 dbg_printf ("Symbols not loaded\n");
391 return;
394 set<symbol_entry_t*>::const_iterator iter;
395 for(iter = syms->begin();iter!=syms->end();++iter) {
396 dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name);
401 int bx_dbg_lbreakpoint_symbol_command(char *Symbol)
403 context_t* cntx = context_t::get_context(0);
404 if(!cntx) {
405 dbg_printf ("Global context not available\n");
406 return -1;
408 if (Symbol[0]=='\"') Symbol++;
409 int len = strlen(Symbol);
410 if (Symbol[len - 1] == '\"') Symbol[len - 1] = '\0';
412 const symbol_entry_t* sym=cntx->get_symbol_entry(Symbol);
413 if(sym)
414 return bx_dbg_lbreakpoint_command(bkRegular, sym->start);
415 dbg_printf ("Symbol not found\n");
416 return -1;
418 #endif
419 #endif