2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
11 #include <aros/debug.h>
13 #include <libraries/debug.h>
14 #include <proto/exec.h>
15 #include <proto/kernel.h>
19 #include "debug_intern.h"
21 static BOOL
FindSymbol(module_t
*mod
, char **function
, void **funstart
, void **funend
, void *addr
)
23 dbg_sym_t
*sym
= mod
->m_symbols
;
29 for (i
= 0; i
< mod
->m_symcnt
; i
++)
31 APTR highest
= sym
[i
].s_highest
;
33 /* Symbols with zero length have zero in s_highest */
35 highest
= sym
[i
].s_lowest
;
37 if (sym
[i
].s_lowest
<= addr
&& highest
>= addr
) {
38 *function
= sym
[i
].s_name
;
39 *funstart
= sym
[i
].s_lowest
;
40 *funend
= sym
[i
].s_highest
;
46 /* Indicate that symbol not found */
50 /*****************************************************************************
53 #include <proto/debug.h>
55 AROS_LH2(int, DecodeLocationA
,
58 AROS_LHA(void *, addr
, A0
),
59 AROS_LHA(struct TagItem
*, tags
, A1
),
62 struct Library
*, DebugBase
, 7, Debug
)
65 Locate the given address in the list of registered modules and return
69 addr - An address to resolve
70 tags - An optional taglist. ti_Tag can be one of the following tags and
71 ti_Data is always a pointer to a storage of specified type.
72 Resulting values will be placed into specified locations if the
75 DL_ModuleName (char *) - Module name
76 DL_SegmentName (char *) - Segment name. Can be NULL if there were
77 no segment names provided for the module.
78 DL_SegmentPointer (BPTR) - DOS pointer to the corresponding segment.
79 Note that it will be different from
80 KDL_SegmentStart value
82 DL_SegmentNumber (unsigned int) - Order number of the segment in the
84 DL_SegmentStart (void *) - Start address of actual segment contents
86 DL_SegmentEnd (void *) - End address of actual segment contents
89 The following tags may return NULL values if there was no corresponding
90 information provided for the module:
92 DL_SymbolName (char *) - Symbol name (function or variable name)
93 DL_SymbolStart (void *) - Start address of contents described by this
95 DL_SymbolEnd (void *) - End address of contents described by this
99 Zero if lookup failed and no corresponding module found, nonzero
103 If the function fails values pointed to by taglist will not be changed.
113 ******************************************************************************/
119 char **module
= (char **)&dummy
;
120 char **segment
= (char **)&dummy
;
121 char **function
= (char **)&dummy
;
122 void **secstart
= &dummy
;
123 void **secend
= &dummy
;
124 void **funstart
= &dummy
;
125 void **funend
= &dummy
;
126 BPTR
*secptr
= (BPTR
*)&dummy
;
127 unsigned int *secnum
= (unsigned int *)&dummy
;
128 struct TagItem
*tag
, *tstate
= tags
;
129 void *symaddr
= NULL
;
133 D(bug("[Debug] DecodeLocationA(0x%p)\n", addr
));
136 while ((tag
= LibNextTagItem(&tstate
)))
141 module
= (char **)tag
->ti_Data
;
145 segment
= (char **)tag
->ti_Data
;
148 case DL_SegmentPointer
:
149 secptr
= (BPTR
*)tag
->ti_Data
;
152 case DL_SegmentNumber
:
153 secnum
= (unsigned int *)tag
->ti_Data
;
156 case DL_SegmentStart
:
157 secstart
= (void **)tag
->ti_Data
;
161 secend
= (void **)tag
->ti_Data
;
165 function
= (char **)tag
->ti_Data
;
170 funstart
= (void **)tag
->ti_Data
;
175 funend
= (void **)tag
->ti_Data
;
181 /* We can be called in supervisor mode. No semaphores in the case! */
182 super
= KrnIsSuper();
184 ObtainSemaphoreShared(&DBGBASE(DebugBase
)->db_ModSem
);
186 ForeachNode(&DBGBASE(DebugBase
)->db_Modules
, seg
)
188 DSEGS(bug("[Debug] Checking segment 0x%p - 0x%p, num %u, module %s\n", seg
->s_lowest
, seg
->s_highest
, seg
->s_num
, seg
->s_mod
->m_name
));
190 /* if address suits the segment bounds, you got it */
191 if ((seg
->s_lowest
<= addr
) && (seg
->s_highest
>= addr
))
193 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", seg
->s_mod
->m_name
, seg
->s_num
,
194 seg
->s_name
, seg
->s_lowest
, seg
->s_highest
));
196 *module
= seg
->s_mod
->m_name
;
197 *segment
= seg
->s_name
;
198 *secptr
= seg
->s_seg
;
199 *secnum
= seg
->s_num
;
200 *secstart
= seg
->s_lowest
;
201 *secend
= seg
->s_highest
;
203 /* Now look up the function if requested */
204 if (FindSymbol(seg
->s_mod
, function
, funstart
, funend
, symaddr
)) {
212 ReleaseSemaphore(&DBGBASE(DebugBase
)->db_ModSem
);
214 /* Try to search kernel debug information if found nothing */
217 struct ELF_ModuleInfo
*kmod
;
219 D(bug("[Debug] Checking kernel modules...\n"));
221 for (kmod
= DBGBASE(DebugBase
)->db_KernelModules
; kmod
; kmod
= kmod
->Next
)
223 /* We understand only ELF here */
224 if (kmod
->Type
== DEBUG_ELF
)
226 struct elfheader
*eh
= kmod
->eh
;
227 struct sheader
*sections
= kmod
->sh
;
228 ULONG int_shnum
= eh
->shnum
;
229 ULONG int_shstrndx
= eh
->shstrndx
;
233 /* Get wider versions of shnum and shstrndx from first section header if needed */
235 int_shnum
= sections
[0].size
;
236 if (int_shstrndx
== SHN_XINDEX
)
237 int_shstrndx
= sections
[0].link
;
239 shstr
= SHINDEX(int_shstrndx
);
241 D(bug("[Debug] Module %s, %d sections at 0x%p\n", kmod
->Name
, int_shnum
, sections
));
243 for (i
=0; i
< int_shnum
; i
++)
245 void *s_lowest
= sections
[i
].addr
;
247 /* Ignore all empty segments */
248 if (s_lowest
&& sections
[i
].size
)
250 void *s_highest
= s_lowest
+ sections
[i
].size
- 1;
252 if ((s_lowest
<= addr
) && (s_highest
>= addr
))
256 if (sections
[shstr
].type
== SHT_STRTAB
)
257 s_name
= sections
[shstr
].addr
+ sections
[i
].name
;
259 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", kmod
->Name
, i
,
260 s_name
, s_lowest
, s_highest
));
262 *module
= (char *)kmod
->Name
;
266 *secstart
= s_lowest
;
275 /* If we are in correct module, let's try to look up the symbol */
280 /* Find symbols name table */
281 for (i
= 0; i
< int_shnum
; i
++)
283 if ((sections
[i
].type
== SHT_STRTAB
) && (i
!= shstr
))
285 m_str
= sections
[i
].addr
;
286 D(bug("[Debug] Symbol name table of length %d in section %d at 0x%p\n", sections
[i
].size
, i
, m_str
));
290 for (i
= 0; i
< int_shnum
; i
++)
292 if (sections
[i
].addr
&& sections
[i
].type
== SHT_SYMTAB
)
294 struct symbol
*st
= (struct symbol
*)sections
[i
].addr
;
295 unsigned int symcnt
= sections
[i
].size
/ sizeof(struct symbol
);
298 for (j
=0; j
< symcnt
; j
++)
300 int idx
= st
[j
].shindex
;
301 void *s_lowest
, *s_highest
, *cmp_highest
;
304 /* Ignore these - they should not be here at all */
305 if ((idx
== SHN_UNDEF
) || (idx
== SHN_COMMON
))
307 /* TODO: perhaps XINDEX support is needed */
308 if (idx
== SHN_XINDEX
)
311 s_name
= (m_str
) ? m_str
+ st
[j
].name
: NULL
;
313 s_lowest
= (void *)st
[j
].value
;
315 s_lowest
+= (IPTR
)sections
[idx
].addr
;
319 s_highest
= s_lowest
+ st
[j
].size
- 1;
320 cmp_highest
= s_highest
;
325 cmp_highest
= s_lowest
;
328 if ((s_lowest
<= addr
) && (cmp_highest
>= addr
))
331 *funstart
= s_lowest
;
340 /* Symbol not found */