Added our usual copyright header.
[AROS.git] / rom / debug / decodelocation.c
blobfa20dae0df1cc3671280360e87b08ed918297ae4
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 */
8 #define DEBUG 0
9 #define DSEGS(x)
11 #include <aros/debug.h>
12 #include <dos/bptr.h>
13 #include <libraries/debug.h>
14 #include <proto/exec.h>
15 #include <proto/kernel.h>
17 #include <inttypes.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;
24 unsigned int i;
26 if (!addr)
27 return FALSE;
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 */
34 if (!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;
42 return TRUE;
46 /* Indicate that symbol not found */
47 return FALSE;
50 /*****************************************************************************
52 NAME */
53 #include <proto/debug.h>
55 AROS_LH2(int, DecodeLocationA,
57 /* SYNOPSIS */
58 AROS_LHA(void *, addr, A0),
59 AROS_LHA(struct TagItem *, tags, A1),
61 /* LOCATION */
62 struct Library *, DebugBase, 7, Debug)
64 /* FUNCTION
65 Locate the given address in the list of registered modules and return
66 information about it.
68 INPUTS
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
73 function succeeds.
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
83 module
84 DL_SegmentStart (void *) - Start address of actual segment contents
85 in memory.
86 DL_SegmentEnd (void *) - End address of actual segment contents
87 in memory.
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
94 symbol.
95 DL_SymbolEnd (void *) - End address of contents described by this
96 symbol.
98 RESULT
99 Zero if lookup failed and no corresponding module found, nonzero
100 otherwise.
102 NOTES
103 If the function fails values pointed to by taglist will not be changed.
105 EXAMPLE
107 BUGS
109 SEE ALSO
111 INTERNALS
113 ******************************************************************************/
115 AROS_LIBFUNC_INIT
117 struct segment *seg;
118 void *dummy;
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;
130 int ret = 0;
131 int super;
133 D(bug("[Debug] DecodeLocationA(0x%p)\n", addr));
135 /* Parse TagList */
136 while ((tag = LibNextTagItem(&tstate)))
138 switch (tag->ti_Tag)
140 case DL_ModuleName:
141 module = (char **)tag->ti_Data;
142 break;
144 case DL_SegmentName:
145 segment = (char **)tag->ti_Data;
146 break;
148 case DL_SegmentPointer:
149 secptr = (BPTR *)tag->ti_Data;
150 break;
152 case DL_SegmentNumber:
153 secnum = (unsigned int *)tag->ti_Data;
154 break;
156 case DL_SegmentStart:
157 secstart = (void **)tag->ti_Data;
158 break;
160 case DL_SegmentEnd:
161 secend = (void **)tag->ti_Data;
162 break;
164 case DL_SymbolName:
165 function = (char **)tag->ti_Data;
166 symaddr = addr;
167 break;
169 case DL_SymbolStart:
170 funstart = (void **)tag->ti_Data;
171 symaddr = addr;
172 break;
174 case DL_SymbolEnd:
175 funend = (void **)tag->ti_Data;
176 symaddr = addr;
177 break;
181 /* We can be called in supervisor mode. No semaphores in the case! */
182 super = KrnIsSuper();
183 if (!super)
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)) {
205 ret = 1;
206 break;
211 if (!super)
212 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
214 /* Try to search kernel debug information if found nothing */
215 if (!ret)
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;
230 ULONG shstr;
231 unsigned int i;
233 /* Get wider versions of shnum and shstrndx from first section header if needed */
234 if (int_shnum == 0)
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))
254 char *s_name = NULL;
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;
263 *segment = s_name;
264 *secptr = BNULL;
265 *secnum = i;
266 *secstart = s_lowest;
267 *secend = s_highest;
269 ret = 1;
270 break;
275 /* If we are in correct module, let's try to look up the symbol */
276 if (ret)
278 char *m_str = NULL;
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);
296 unsigned int j;
298 for (j=0; j < symcnt; j++)
300 int idx = st[j].shindex;
301 void *s_lowest, *s_highest, *cmp_highest;
302 char *s_name;
304 /* Ignore these - they should not be here at all */
305 if ((idx == SHN_UNDEF) || (idx == SHN_COMMON))
306 continue;
307 /* TODO: perhaps XINDEX support is needed */
308 if (idx == SHN_XINDEX)
309 continue;
311 s_name = (m_str) ? m_str + st[j].name : NULL;
313 s_lowest = (void *)st[j].value;
314 if (idx != SHN_ABS)
315 s_lowest += (IPTR)sections[idx].addr;
317 if (st[j].size)
319 s_highest = s_lowest + st[j].size - 1;
320 cmp_highest = s_highest;
322 else
324 s_highest = NULL;
325 cmp_highest = s_lowest;
328 if ((s_lowest <= addr) && (cmp_highest >= addr))
330 *function = s_name;
331 *funstart = s_lowest;
332 *funend = s_highest;
334 return 1;
340 /* Symbol not found */
341 *function = NULL;
342 *funstart = NULL;
343 *funend = NULL;
345 break;
351 return ret;
353 AROS_LIBFUNC_EXIT