1 /////////////////////////////////////////////////////////////////////////
2 // $Id: symbols.cc,v 1.7 2006/10/11 14:54:40 akrisak Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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 /////////////////////////////////////////////////////////////////////////
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;
40 dbg_printf(BX_HAVE_HASH_MAP_ERR
);
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
);
68 Bit32u
bx_dbg_get_symbol_value(char *Symbol
)
73 char* bx_dbg_disasm_symbolic_address(Bit32u eip
, Bit32u base
)
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
86 #elif BX_HAVE_HASH_MAP_H
100 symbol_entry_t (Bit32u _start
= 0, char* _name
= 0)
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;
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
;}
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
;
145 hash_map
<int,context_t
*>* context_t::map
= new hash_map
<int,context_t
*>;
147 context_t::context_t (Bit32u _id
)
150 syms
= new set
<symbol_entry_t
*, lt_symbol_entry_t
>;
151 rsyms
= new set
<symbol_entry_t
*, lt_rsymbol_entry_t
>;
155 context_t::~context_t()
157 set
<symbol_entry_t
*>::iterator iter
;
159 for(iter
=syms
->begin();iter
!=syms
->end();++iter
)
165 for(iter
=rsyms
->begin();iter
!=rsyms
->end();++iter
)
171 context_t
* context_t::get_context(Bit32u i
)
176 symbol_entry_t
* context_t::get_symbol_entry(Bit32u ip
)
178 symbol_entry_t probe
;
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
191 symbol_entry_t
* context_t::get_symbol_entry(const char *Symbol
) const
193 symbol_entry_t probe
;
194 probe
.name
=(char *)Symbol
;
199 set
<symbol_entry_t
*>::const_iterator iter
;
200 iter
=rsyms
->find(&probe
);
201 if(iter
==rsyms
->end()) // No symbol found
206 void context_t::add_symbol(symbol_entry_t
* 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
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
229 char* bx_dbg_symbolic_address(Bit32u context
, Bit32u eip
, Bit32u base
)
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.
237 snprintf (buf
, 80, "non-zero base");
241 // Look up this context
242 context_t
* cntx
= context_t::get_context(context
);
244 // Try global context
245 cntx
= context_t::get_context(0);
247 snprintf (buf
, 80, "unk. ctxt");
251 // full linear address not only eip (for nonzero based segments)
252 symbol_entry_t
* entr
= cntx
->get_symbol_entry(base
+eip
);
254 snprintf (buf
, 80, "no symbol");
257 snprintf (buf
, 80, "%s+%x", entr
->name
, (base
+eip
) - entr
->start
);
261 char* bx_dbg_disasm_symbolic_address(Bit32u eip
, Bit32u base
)
265 // Try global context
266 context_t
* cntx
= context_t::get_context(0);
271 // full linear address not only eip (for nonzero based segments)
272 symbol_entry_t
* entr
= cntx
->get_symbol_entry(base
+eip
);
276 snprintf (buf
, 80, "%s+%x", entr
->name
, (base
+eip
) - entr
->start
);
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.
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] == '"')
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);
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
311 dbg_printf ("Could not open symbol file '%s'\n", filename
);
315 while (fgets(buf
, 200, fp
)) {
317 char* sym_name
= buf
;
319 for (int i
= 0; i
< 200 && buf
[i
]; i
++) {
322 sym_name
= buf
+ i
+ 1;
326 if (sym_name
== buf
) {
327 dbg_printf ("Syntax error '%s'\n", buf
);
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
)
344 size_t len
=strlen(s1
);
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);
356 dbg_printf ("Global context not available\n");
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");
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
;
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");
381 for(;iter
!=rsyms
->end() && bx_dbg_strprefix(Symbol
, (*iter
)->name
);++iter
) {
382 dbg_printf ("%08x: %s\n", (*iter
)->start
, (*iter
)->name
);
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");
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);
405 dbg_printf ("Global context not available\n");
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
);
414 return bx_dbg_lbreakpoint_command(bkRegular
, sym
->start
);
415 dbg_printf ("Symbol not found\n");