grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / debug / decodelocation.c
blob8a6d6c0965ecb45fd64223126786add0a1364a82
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 struct DebugBase *debugBase = DBGBASE(DebugBase);
59 module_t * mod;
61 ForeachNode(&debugBase->db_Modules, mod)
63 DSEGS(bug("[Debug] Checking module 0x%p - 0x%p, %s\n", mod->m_lowest, mod->m_highest, mod->m_name));
65 /* if address suits the module bounds, you got a candidate */
66 if (!((mod->m_gaplowest <= addr) && (mod->m_gaphighest >= addr)) &&
67 ((mod->m_lowest <= addr) && (mod->m_highest >= addr)))
69 struct segment *seg = FindSegmentInModule(addr, mod);
70 if (seg)
71 return seg;
75 return NULL;
78 static BOOL FindSymbol(module_t *mod, char **function, void **funstart, void **funend, void *addr)
80 dbg_sym_t *sym = mod->m_symbols;
81 unsigned int i;
83 /* Caller didn't care about symbols? */
84 if (!addr)
85 return TRUE;
87 *function = NULL;
88 *funstart = NULL;
89 *funend = NULL;
91 for (i = 0; i < mod->m_symcnt; i++)
93 APTR highest = sym[i].s_highest;
95 /* Symbols with zero length have zero in s_highest */
96 if (!highest)
97 highest = sym[i].s_lowest;
99 if (sym[i].s_lowest <= addr && highest >= addr) {
100 *function = sym[i].s_name;
101 *funstart = sym[i].s_lowest;
102 *funend = sym[i].s_highest;
104 return TRUE;
108 /* Indicate that symbol not found */
109 return FALSE;
112 /*****************************************************************************
114 NAME */
115 #include <proto/debug.h>
117 AROS_LH2(int, DecodeLocationA,
119 /* SYNOPSIS */
120 AROS_LHA(void *, addr, A0),
121 AROS_LHA(struct TagItem *, tags, A1),
123 /* LOCATION */
124 struct Library *, DebugBase, 7, Debug)
126 /* FUNCTION
127 Locate the given address in the list of registered modules and return
128 information about it.
130 INPUTS
131 addr - An address to resolve
132 tags - An optional taglist. ti_Tag can be one of the following tags and
133 ti_Data is always a pointer to a storage of specified type.
134 Resulting values will be placed into specified locations if the
135 function succeeds.
137 DL_ModuleName (char *) - Module name
138 DL_SegmentName (char *) - Segment name. Can be NULL if there were
139 no segment names provided for the module.
140 DL_SegmentPointer (BPTR) - DOS pointer to the corresponding segment.
141 Note that it will be different from
142 KDL_SegmentStart value
144 DL_SegmentNumber (unsigned int) - Order number of the segment in the
145 module
146 DL_SegmentStart (void *) - Start address of actual segment contents
147 in memory.
148 DL_SegmentEnd (void *) - End address of actual segment contents
149 in memory.
150 DL_FirstSegment (BPTR) - DOS pointer to the first segment.
152 The following tags may return NULL values if there was no corresponding
153 information provided for the module:
155 DL_SymbolName (char *) - Symbol name (function or variable name)
156 DL_SymbolStart (void *) - Start address of contents described by this
157 symbol.
158 DL_SymbolEnd (void *) - End address of contents described by this
159 symbol.
161 RESULT
162 Zero if lookup failed and no corresponding module found, nonzero
163 otherwise.
165 NOTES
166 If the function fails values pointed to by taglist will not be changed.
168 EXAMPLE
170 BUGS
172 SEE ALSO
174 INTERNALS
176 ******************************************************************************/
178 AROS_LIBFUNC_INIT
180 struct segment *seg;
181 void *dummy;
182 char **module = (char **)&dummy;
183 char **segment = (char **)&dummy;
184 char **function = (char **)&dummy;
185 void **secstart = &dummy;
186 void **secend = &dummy;
187 void **funstart = &dummy;
188 void **funend = &dummy;
189 BPTR *secptr = (BPTR *)&dummy;
190 BPTR *secfirst = (BPTR *)&dummy;
191 unsigned int *secnum = (unsigned int *)&dummy;
192 struct TagItem *tag, *tstate = tags;
193 void *symaddr = NULL;
194 int ret = 0;
195 int super;
197 D(bug("[Debug] DecodeLocationA(0x%p)\n", addr));
199 /* Parse TagList */
200 while ((tag = LibNextTagItem(&tstate)))
202 switch (tag->ti_Tag)
204 case DL_ModuleName:
205 module = (char **)tag->ti_Data;
206 break;
208 case DL_SegmentName:
209 segment = (char **)tag->ti_Data;
210 break;
212 case DL_SegmentPointer:
213 secptr = (BPTR *)tag->ti_Data;
214 break;
216 case DL_SegmentNumber:
217 secnum = (unsigned int *)tag->ti_Data;
218 break;
220 case DL_SegmentStart:
221 secstart = (void **)tag->ti_Data;
222 break;
224 case DL_SegmentEnd:
225 secend = (void **)tag->ti_Data;
226 break;
228 case DL_FirstSegment:
229 secfirst = (BPTR *)tag->ti_Data;
230 break;
232 case DL_SymbolName:
233 function = (char **)tag->ti_Data;
234 symaddr = addr;
235 break;
237 case DL_SymbolStart:
238 funstart = (void **)tag->ti_Data;
239 symaddr = addr;
240 break;
242 case DL_SymbolEnd:
243 funend = (void **)tag->ti_Data;
244 symaddr = addr;
245 break;
249 /* We can be called in supervisor mode. No semaphores in the case! */
250 super = KrnIsSuper();
251 if (!super)
252 ObtainSemaphoreShared(&DBGBASE(DebugBase)->db_ModSem);
254 seg = FindSegment(addr, DebugBase);
255 if (seg)
257 D(bug("[Debug] Found module %s, Segment %u (%s, 0x%p - 0x%p)\n", seg->s_mod->m_name, seg->s_num,
258 seg->s_name, seg->s_lowest, seg->s_highest));
260 *module = seg->s_mod->m_name;
261 *segment = seg->s_name;
262 *secptr = seg->s_seg;
263 *secnum = seg->s_num;
264 *secstart = seg->s_lowest;
265 *secend = seg->s_highest;
266 *secfirst = seg->s_mod->m_seg;
268 /* Now look up the function if requested */
269 FindSymbol(seg->s_mod, function, funstart, funend, symaddr);
270 ret = 1;
273 if (!super)
274 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
276 return ret;
278 AROS_LIBFUNC_EXIT