MUIM_List_InsertSingle: if there's no active entry,
[AROS.git] / rom / debug / decodelocation.c
blob92f0e230b4857dd6256dc35faa3da8052997d28f
1 #define DEBUG 0
2 #define DSEGS(x)
4 #include <aros/debug.h>
5 #include <dos/bptr.h>
6 #include <libraries/debug.h>
7 #include <proto/exec.h>
8 #include <proto/kernel.h>
10 #include <inttypes.h>
12 #include "debug_intern.h"
14 static BOOL FindSymbol(module_t *mod, char **function, void **funstart, void **funend, void *addr)
16 dbg_sym_t *sym = mod->m_symbols;
17 unsigned int i;
19 if (!addr)
20 return FALSE;
22 for (i = 0; i < mod->m_symcnt; i++)
24 APTR highest = sym[i].s_highest;
26 /* Symbols with zero length have zero in s_highest */
27 if (!highest)
28 highest = sym[i].s_lowest;
30 if (sym[i].s_lowest <= addr && highest >= addr) {
31 *function = sym[i].s_name;
32 *funstart = sym[i].s_lowest;
33 *funend = sym[i].s_highest;
35 return TRUE;
39 /* Indicate that symbol not found */
40 return FALSE;
43 /*****************************************************************************
45 NAME */
46 #include <proto/debug.h>
48 AROS_LH2(int, DecodeLocationA,
50 /* SYNOPSIS */
51 AROS_LHA(void *, addr, A0),
52 AROS_LHA(struct TagItem *, tags, A1),
54 /* LOCATION */
55 struct Library *, DebugBase, 7, Debug)
57 /* FUNCTION
58 Locate the given address in the list of registered modules and return
59 information about it.
61 INPUTS
62 addr - An address to resolve
63 tags - An optional taglist. ti_Tag can be one of the following tags and
64 ti_Data is always a pointer to a storage of specified type.
65 Resulting values will be placed into specified locations if the
66 function succeeds.
68 DL_ModuleName (char *) - Module name
69 DL_SegmentName (char *) - Segment name. Can be NULL if there were
70 no segment names provided for the module.
71 DL_SegmentPointer (BPTR) - DOS pointer to the corresponding segment.
72 Note that it will be different from
73 KDL_SegmentStart value
75 DL_SegmentNumber (unsigned int) - Order number of the segment in the
76 module
77 DL_SegmentStart (void *) - Start address of actual segment contents
78 in memory.
79 DL_SegmentEnd (void *) - End address of actual segment contents
80 in memory.
82 The following tags may return NULL values if there was no corresponding
83 information provided for the module:
85 DL_SymbolName (char *) - Symbol name (function or variable name)
86 DL_SymbolStart (void *) - Start address of contents described by this
87 symbol.
88 DL_SymbolEnd (void *) - End address of contents described by this
89 symbol.
91 RESULT
92 Zero if lookup failed and no corresponding module found, nonzero
93 otherwise.
95 NOTES
96 If the function fails values pointed to by taglist will not be changed.
98 EXAMPLE
100 BUGS
102 SEE ALSO
104 INTERNALS
106 ******************************************************************************/
108 AROS_LIBFUNC_INIT
110 struct segment *seg;
111 void *dummy;
112 char **module = (char **)&dummy;
113 char **segment = (char **)&dummy;
114 char **function = (char **)&dummy;
115 void **secstart = &dummy;
116 void **secend = &dummy;
117 void **funstart = &dummy;
118 void **funend = &dummy;
119 BPTR *secptr = (BPTR *)&dummy;
120 unsigned int *secnum = (unsigned int *)&dummy;
121 struct TagItem *tag, *tstate = tags;
122 void *symaddr = NULL;
123 int ret = 0;
124 int super;
126 D(bug("[Debug] DecodeLocationA(0x%p)\n", addr));
128 /* Parse TagList */
129 while ((tag = LibNextTagItem(&tstate)))
131 switch (tag->ti_Tag)
133 case DL_ModuleName:
134 module = (char **)tag->ti_Data;
135 break;
137 case DL_SegmentName:
138 segment = (char **)tag->ti_Data;
139 break;
141 case DL_SegmentPointer:
142 secptr = (BPTR *)tag->ti_Data;
143 break;
145 case DL_SegmentNumber:
146 secnum = (unsigned int *)tag->ti_Data;
147 break;
149 case DL_SegmentStart:
150 secstart = (void **)tag->ti_Data;
151 break;
153 case DL_SegmentEnd:
154 secend = (void **)tag->ti_Data;
155 break;
157 case DL_SymbolName:
158 function = (char **)tag->ti_Data;
159 symaddr = addr;
160 break;
162 case DL_SymbolStart:
163 funstart = (void **)tag->ti_Data;
164 symaddr = addr;
165 break;
167 case DL_SymbolEnd:
168 funend = (void **)tag->ti_Data;
169 symaddr = addr;
170 break;
174 /* We can be called in supervisor mode. No semaphores in the case! */
175 super = KrnIsSuper();
176 if (!super)
177 ObtainSemaphoreShared(&DBGBASE(DebugBase)->db_ModSem);
179 ForeachNode(&DBGBASE(DebugBase)->db_Modules, seg)
181 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));
183 /* if address suits the segment bounds, you got it */
184 if ((seg->s_lowest <= addr) && (seg->s_highest >= addr))
186 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", seg->s_mod->m_name, seg->s_num,
187 seg->s_name, seg->s_lowest, seg->s_highest));
189 *module = seg->s_mod->m_name;
190 *segment = seg->s_name;
191 *secptr = seg->s_seg;
192 *secnum = seg->s_num;
193 *secstart = seg->s_lowest;
194 *secend = seg->s_highest;
196 /* Now look up the function if requested */
197 if (FindSymbol(seg->s_mod, function, funstart, funend, symaddr)) {
198 ret = 1;
199 break;
204 if (!super)
205 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
207 /* Try to search kernel debug information if found nothing */
208 if (!ret)
210 struct ELF_ModuleInfo *kmod;
212 D(bug("[Debug] Checking kernel modules...\n"));
214 for (kmod = DBGBASE(DebugBase)->db_KernelModules; kmod; kmod = kmod->Next)
216 /* We understand only ELF here */
217 if (kmod->Type == DEBUG_ELF)
219 struct elfheader *eh = kmod->eh;
220 struct sheader *sections = kmod->sh;
221 ULONG int_shnum = eh->shnum;
222 ULONG int_shstrndx = eh->shstrndx;
223 ULONG shstr;
224 unsigned int i;
226 /* Get wider versions of shnum and shstrndx from first section header if needed */
227 if (int_shnum == 0)
228 int_shnum = sections[0].size;
229 if (int_shstrndx == SHN_XINDEX)
230 int_shstrndx = sections[0].link;
232 shstr = SHINDEX(int_shstrndx);
234 D(bug("[Debug] Module %s, %d sections at 0x%p\n", kmod->Name, int_shnum, sections));
236 for (i=0; i < int_shnum; i++)
238 void *s_lowest = sections[i].addr;
240 /* Ignore all empty segments */
241 if (s_lowest && sections[i].size)
243 void *s_highest = s_lowest + sections[i].size - 1;
245 if ((s_lowest <= addr) && (s_highest >= addr))
247 char *s_name = NULL;
249 if (sections[shstr].type == SHT_STRTAB)
250 s_name = sections[shstr].addr + sections[i].name;
252 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", kmod->Name, i,
253 s_name, s_lowest, s_highest));
255 *module = (char *)kmod->Name;
256 *segment = s_name;
257 *secptr = BNULL;
258 *secnum = i;
259 *secstart = s_lowest;
260 *secend = s_highest;
262 ret = 1;
263 break;
268 /* If we are in correct module, let's try to look up the symbol */
269 if (ret)
271 char *m_str = NULL;
273 /* Find symbols name table */
274 for (i = 0; i < int_shnum; i++)
276 if ((sections[i].type == SHT_STRTAB) && (i != shstr))
278 m_str = sections[i].addr;
279 D(bug("[Debug] Symbol name table of length %d in section %d at 0x%p\n", sections[i].size, i, m_str));
283 for (i = 0; i < int_shnum; i++)
285 if (sections[i].addr && sections[i].type == SHT_SYMTAB)
287 struct symbol *st = (struct symbol *)sections[i].addr;
288 unsigned int symcnt = sections[i].size / sizeof(struct symbol);
289 unsigned int j;
291 for (j=0; j < symcnt; j++)
293 int idx = st[j].shindex;
294 void *s_lowest, *s_highest, *cmp_highest;
295 char *s_name;
297 /* Ignore these - they should not be here at all */
298 if ((idx == SHN_UNDEF) || (idx == SHN_COMMON))
299 continue;
300 /* TODO: perhaps XINDEX support is needed */
301 if (idx == SHN_XINDEX)
302 continue;
304 s_name = (m_str) ? m_str + st[j].name : NULL;
306 s_lowest = (void *)st[j].value;
307 if (idx != SHN_ABS)
308 s_lowest += (IPTR)sections[idx].addr;
310 if (st[j].size)
312 s_highest = s_lowest + st[j].size - 1;
313 cmp_highest = s_highest;
315 else
317 s_highest = NULL;
318 cmp_highest = s_lowest;
321 if ((s_lowest <= addr) && (cmp_highest >= addr))
323 *function = s_name;
324 *funstart = s_lowest;
325 *funend = s_highest;
327 return 1;
333 /* Symbol not found */
334 *function = NULL;
335 *funstart = NULL;
336 *funend = NULL;
338 break;
344 return ret;
346 AROS_LIBFUNC_EXIT