muimaster.library: support Listview_List in List
[AROS.git] / rom / debug / decodelocation.c
blob1a47f289b2b71a14b13d2c85b22df8d32737eb32
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 /* Binary search over sorted array of segments */
22 static struct segment * FindSegmentInModule(void *addr, module_t *mod)
24 LONG idx, minidx = 0, maxidx = mod->m_segcnt - 1;
26 while(TRUE)
28 idx = (maxidx + minidx) / 2;
30 if (mod->m_segments[idx]->s_lowest <= addr)
32 if (mod->m_segments[idx]->s_highest >= addr)
34 return mod->m_segments[idx];
36 else
38 /* cut off segments with lower addresses */
39 minidx = idx + 1;
42 else
44 /* cut off segments with higher addresses */
45 maxidx = idx - 1;
48 /* Not found, aborting */
49 if (maxidx < minidx)
50 return NULL;
53 return NULL;
56 static struct segment * FindSegment(void *addr, struct Library *DebugBase)
58 module_t * mod;
60 ForeachNode(&DBGBASE(DebugBase)->db_Modules, mod)
62 DSEGS(bug("[Debug] Checking module 0x%p - 0x%p, %s\n", mod->m_lowest, mod->m_highest, mod->m_name));
64 /* if address suits the module bounds, you got a candidate */
65 if (!((mod->m_gaplowest <= addr) && (mod->m_gaphighest >= addr)) &&
66 ((mod->m_lowest <= addr) && (mod->m_highest >= addr)))
68 struct segment *seg = FindSegmentInModule(addr, mod);
69 if (seg)
70 return seg;
74 return NULL;
77 static BOOL FindSymbol(module_t *mod, char **function, void **funstart, void **funend, void *addr)
79 dbg_sym_t *sym = mod->m_symbols;
80 unsigned int i;
82 /* Caller didn't care about symbols? */
83 if (!addr)
84 return TRUE;
86 *function = NULL;
87 *funstart = NULL;
88 *funend = NULL;
90 for (i = 0; i < mod->m_symcnt; i++)
92 APTR highest = sym[i].s_highest;
94 /* Symbols with zero length have zero in s_highest */
95 if (!highest)
96 highest = sym[i].s_lowest;
98 if (sym[i].s_lowest <= addr && highest >= addr) {
99 *function = sym[i].s_name;
100 *funstart = sym[i].s_lowest;
101 *funend = sym[i].s_highest;
103 return TRUE;
107 /* Indicate that symbol not found */
108 return FALSE;
111 /*****************************************************************************
113 NAME */
114 #include <proto/debug.h>
116 AROS_LH2(int, DecodeLocationA,
118 /* SYNOPSIS */
119 AROS_LHA(void *, addr, A0),
120 AROS_LHA(struct TagItem *, tags, A1),
122 /* LOCATION */
123 struct Library *, DebugBase, 7, Debug)
125 /* FUNCTION
126 Locate the given address in the list of registered modules and return
127 information about it.
129 INPUTS
130 addr - An address to resolve
131 tags - An optional taglist. ti_Tag can be one of the following tags and
132 ti_Data is always a pointer to a storage of specified type.
133 Resulting values will be placed into specified locations if the
134 function succeeds.
136 DL_ModuleName (char *) - Module name
137 DL_SegmentName (char *) - Segment name. Can be NULL if there were
138 no segment names provided for the module.
139 DL_SegmentPointer (BPTR) - DOS pointer to the corresponding segment.
140 Note that it will be different from
141 KDL_SegmentStart value
143 DL_SegmentNumber (unsigned int) - Order number of the segment in the
144 module
145 DL_SegmentStart (void *) - Start address of actual segment contents
146 in memory.
147 DL_SegmentEnd (void *) - End address of actual segment contents
148 in memory.
149 DL_FirstSegment (BPTR) - DOS pointer to the first segment.
151 The following tags may return NULL values if there was no corresponding
152 information provided for the module:
154 DL_SymbolName (char *) - Symbol name (function or variable name)
155 DL_SymbolStart (void *) - Start address of contents described by this
156 symbol.
157 DL_SymbolEnd (void *) - End address of contents described by this
158 symbol.
160 RESULT
161 Zero if lookup failed and no corresponding module found, nonzero
162 otherwise.
164 NOTES
165 If the function fails values pointed to by taglist will not be changed.
167 EXAMPLE
169 BUGS
171 SEE ALSO
173 INTERNALS
175 ******************************************************************************/
177 AROS_LIBFUNC_INIT
179 struct segment *seg;
180 void *dummy;
181 char **module = (char **)&dummy;
182 char **segment = (char **)&dummy;
183 char **function = (char **)&dummy;
184 void **secstart = &dummy;
185 void **secend = &dummy;
186 void **funstart = &dummy;
187 void **funend = &dummy;
188 BPTR *secptr = (BPTR *)&dummy;
189 BPTR *secfirst = (BPTR *)&dummy;
190 unsigned int *secnum = (unsigned int *)&dummy;
191 struct TagItem *tag, *tstate = tags;
192 void *symaddr = NULL;
193 int ret = 0;
194 int super;
196 D(bug("[Debug] DecodeLocationA(0x%p)\n", addr));
198 /* Parse TagList */
199 while ((tag = LibNextTagItem(&tstate)))
201 switch (tag->ti_Tag)
203 case DL_ModuleName:
204 module = (char **)tag->ti_Data;
205 break;
207 case DL_SegmentName:
208 segment = (char **)tag->ti_Data;
209 break;
211 case DL_SegmentPointer:
212 secptr = (BPTR *)tag->ti_Data;
213 break;
215 case DL_SegmentNumber:
216 secnum = (unsigned int *)tag->ti_Data;
217 break;
219 case DL_SegmentStart:
220 secstart = (void **)tag->ti_Data;
221 break;
223 case DL_SegmentEnd:
224 secend = (void **)tag->ti_Data;
225 break;
227 case DL_FirstSegment:
228 secfirst = (BPTR *)tag->ti_Data;
229 break;
231 case DL_SymbolName:
232 function = (char **)tag->ti_Data;
233 symaddr = addr;
234 break;
236 case DL_SymbolStart:
237 funstart = (void **)tag->ti_Data;
238 symaddr = addr;
239 break;
241 case DL_SymbolEnd:
242 funend = (void **)tag->ti_Data;
243 symaddr = addr;
244 break;
248 /* We can be called in supervisor mode. No semaphores in the case! */
249 super = KrnIsSuper();
250 if (!super)
251 ObtainSemaphoreShared(&DBGBASE(DebugBase)->db_ModSem);
253 seg = FindSegment(addr, DebugBase);
254 if (seg)
256 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", seg->s_mod->m_name, seg->s_num,
257 seg->s_name, seg->s_lowest, seg->s_highest));
259 *module = seg->s_mod->m_name;
260 *segment = seg->s_name;
261 *secptr = seg->s_seg;
262 *secnum = seg->s_num;
263 *secstart = seg->s_lowest;
264 *secend = seg->s_highest;
265 *secfirst = seg->s_mod->m_seg;
267 /* Now look up the function if requested */
268 FindSymbol(seg->s_mod, function, funstart, funend, symaddr);
269 ret = 1;
272 if (!super)
273 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
275 return ret;
277 AROS_LIBFUNC_EXIT