oops .. forgot to offset from objects bounds
[AROS.git] / rom / debug / registermodule.c
blob578be612b6196cd5076e73d033965f0d32453274
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 */
8 #define DEBUG 0
9 #define DSYMS(x)
11 #include <aros/debug.h>
12 #include <aros/libcall.h>
13 #include <dos/dosextens.h>
14 #include <exec/lists.h>
15 #include <libraries/debug.h>
16 #include <proto/exec.h>
18 #include <stdint.h>
19 #include <string.h>
21 #include "debug_intern.h"
23 static inline char *getstrtab(struct sheader *sh)
25 char *str;
27 str = AllocVec(sh->size, MEMF_PUBLIC);
28 if (str)
29 CopyMem(sh->addr, str, sh->size);
31 return str;
34 static void addsymbol(module_t *mod, dbg_sym_t *sym, struct symbol *st, APTR value)
36 if (mod->m_str)
37 sym->s_name = &mod->m_str[st->name];
38 else
39 sym->s_name = NULL;
41 sym->s_lowest = value;
42 if (st->size)
43 sym->s_highest = value + st->size - 1;
44 else
45 /* For symbols with zero size KDL_SymbolEnd will give NULL */
46 sym->s_highest = NULL;
48 /* We count symbols here because not all of them can be added */
49 mod->m_symcnt++;
52 static void RegisterModule_Hunk(const char *name, BPTR segList, ULONG DebugType, APTR DebugInfo, struct Library *DebugBase)
54 module_t *mod;
55 int i = 0;
57 mod = AllocVec(sizeof(module_t) + strlen(name), MEMF_PUBLIC|MEMF_CLEAR);
58 if (!mod)
59 return;
60 strcpy(mod->m_name, name);
61 mod->m_seg = segList;
62 while (segList) {
63 ULONG *segPtr = BADDR(segList);
64 struct segment *seg = AllocMem(sizeof(struct segment), MEMF_PUBLIC | MEMF_CLEAR);
65 if (seg) {
66 seg->s_lowest = (UBYTE*)segPtr - 4;
67 seg->s_highest = (UBYTE*)segPtr + segPtr[-1];
68 seg->s_seg = segList;
69 seg->s_num = i;
70 seg->s_mod = mod;
71 mod->m_segcnt++;
72 ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem);
73 AddTail((struct List *)&DBGBASE(DebugBase)->db_Modules, (struct Node *)seg);
74 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
75 D(bug("[Debug] Adding segment %d 0x%p (%p-%p)\n", i, segList, seg->s_lowest, seg->s_highest));
77 segList = *(BPTR *)BADDR(segList);
78 i++;
83 /*****************************************************************************
85 NAME */
86 #include <proto/debug.h>
88 AROS_LH4(void, RegisterModule,
90 /* SYNOPSIS */
91 AROS_LHA(const char *, name, A0),
92 AROS_LHA(BPTR, segList, A1),
93 AROS_LHA(ULONG, debugType, D0),
94 AROS_LHA(APTR, debugInfo, A2),
96 /* LOCATION */
97 struct Library *, DebugBase, 5, Debug)
99 /* FUNCTION
100 Add information about the loaded executable module to the
101 debug information database
103 INPUTS
104 name - Module name
105 segList - DOS segment list for the module
106 debugType - Type of supplied debug information. The only currently
107 supported type is DEBUG_ELF.
108 debugInfo - Debug information data. For DEBUG_ELF type this should be
109 a pointer to struct ELF_DebugInfo, filled in as follows:
110 eh - a pointer to ELF file header.
111 sh - a pointer to an array of ELF section headers.
113 RESULT
114 None
116 NOTES
118 EXAMPLE
120 BUGS
122 SEE ALSO
124 INTERNALS
125 The function supposes that segments in DOS list are linked in the same
126 order in which corresponding sections are placed in the file
128 ******************************************************************************/
130 AROS_LIBFUNC_INIT
132 D(bug("[Debug] RegisterModule(%s, 0x%p, %d)\n", name, segList, debugType));
134 if (debugType == DEBUG_ELF)
136 struct elfheader *eh = ((struct ELF_DebugInfo *)debugInfo)->eh;
137 struct sheader *sections = ((struct ELF_DebugInfo *)debugInfo)->sh;
138 module_t *mod = AllocVec(sizeof(module_t) + strlen(name), MEMF_PUBLIC|MEMF_CLEAR);
140 if (mod)
142 ULONG int_shnum = eh->shnum;
143 ULONG int_shstrndx = eh->shstrndx;
144 ULONG shstr;
145 ULONG i;
147 /* Get wider versions of shnum and shstrndx from first section header if needed */
148 if (int_shnum == 0)
149 int_shnum = sections[0].size;
150 if (int_shstrndx == SHN_XINDEX)
151 int_shstrndx = sections[0].link;
153 D(bug("[Debug] %d sections at 0x%p\n", int_shnum, sections));
154 shstr = SHINDEX(int_shstrndx);
156 strcpy(mod->m_name, name);
157 mod->m_seg = segList;
158 if (sections[shstr].type == SHT_STRTAB)
159 mod->m_shstr = getstrtab(&sections[shstr]);
161 for (i=0; i < int_shnum; i++)
163 /* Ignore all empty segments */
164 if (sections[i].size)
166 /* If we have string table, copy it */
167 if ((sections[i].type == SHT_STRTAB) && (i != shstr) && (!mod->m_str)) {
168 D(bug("[Debug] Symbol name table of length %d in section %d\n", sections[i].size, i));
169 mod->m_str = getstrtab(&sections[i]);
172 /* Every loadable section with nonzero size got a corresponding DOS segment */
173 if (segList && (sections[i].flags & SHF_ALLOC))
175 struct segment *seg = AllocMem(sizeof(struct segment), MEMF_PUBLIC);
177 if (seg) {
178 D(bug("[Debug] Adding segment 0x%p\n", segList));
180 seg->s_lowest = sections[i].addr;
181 seg->s_highest = sections[i].addr + sections[i].size - 1;
182 seg->s_seg = segList; /* Note that this will differ from s_lowest */
183 seg->s_mod = mod;
184 seg->s_num = i;
185 if (mod->m_shstr)
186 seg->s_name = &mod->m_shstr[sections[i].name];
187 else
188 seg->s_name = NULL;
190 mod->m_segcnt++;
192 ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem);
193 AddTail((struct List *)&DBGBASE(DebugBase)->db_Modules, (struct Node *)seg);
194 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
197 /* Advance to next DOS segment */
198 segList = *(BPTR *)BADDR(segList);
203 /* If the module contains no loadable segments (hm, weird),
204 we actually got nothing linked in our base list. This means
205 that module handle is actually a garbage and we can deallocate
206 it right now, and do nothing more */
207 if (mod->m_segcnt == 0)
209 if (mod->m_str)
210 FreeVec(mod->m_str);
211 if (mod->m_shstr)
212 FreeVec(mod->m_shstr);
213 FreeVec(mod);
215 return;
218 /* Parse module's symbol table */
219 for (i=0; i < int_shnum; i++)
221 if (sections[i].addr && sections[i].type == SHT_SYMTAB)
223 struct symbol *st = (struct symbol *)sections[i].addr;
224 unsigned int symcnt = sections[i].size / sizeof(struct symbol);
225 dbg_sym_t *sym = AllocVec(sizeof(dbg_sym_t) * symcnt, MEMF_PUBLIC);
226 unsigned int j;
228 mod->m_symbols = sym;
230 if (sym) {
231 for (j=0; j < symcnt; j++)
233 int idx = st[j].shindex;
235 /* Ignore these - they should not be here at all */
236 if ((idx == SHN_UNDEF) || (idx == SHN_COMMON))
237 continue;
238 /* TODO: perhaps XINDEX support is needed */
239 if (idx == SHN_XINDEX)
240 continue;
242 if (idx == SHN_ABS) {
243 addsymbol(mod, sym, &st[j], (APTR)st[j].value);
244 DSYMS(bug("[Debug] Added ABS symbol '%s' %08x-%08x\n", sym->s_name, sym->s_lowest, sym->s_highest));
245 sym++;
246 } else if (sections[idx].addr && (sections[idx].flags & SHF_ALLOC)) {
247 addsymbol(mod, sym, &st[j], sections[idx].addr + st[j].value);
248 DSYMS(bug("[Debug] Added symbol '%s' %08x-%08x\n", sym->s_name, sym->s_lowest, sym->s_highest));
249 sym++;
253 break;
257 } else if (debugType == DEBUG_PARTHENOPE) {
258 const struct Parthenope_ModuleInfo *pm;
260 ForeachNode(debugInfo, pm) {
261 struct segment *seg;
263 seg = AllocVec(sizeof(struct segment) + sizeof(module_t) + strlen(pm->m_name), MEMF_PUBLIC|MEMF_CLEAR);
265 if (seg) {
266 unsigned int symbols;
267 dbg_sym_t *dsym;
268 const struct Parthenope_Symbol *sym;
269 APTR str_l = (APTR)~(uintptr_t)0, str_h = (APTR)(uintptr_t)0;
270 APTR seg_l = (APTR)~(uintptr_t)0, seg_h = (APTR)(uintptr_t)0;
271 module_t *mod = (module_t *)(&seg[1]);
273 DSYMS(bug("[Debug] Adding module @%p: %s\n", pm, pm->m_name));
274 strcpy(mod->m_name, pm->m_name);
276 seg->s_seg = BNULL;
277 seg->s_mod = mod;
278 seg->s_name = mod->m_name;
279 seg->s_num = 0;
281 mod->m_shstr = NULL;
282 mod->m_str = NULL;
283 mod->m_segcnt = 0;
285 /* Determine the size of the string table */
286 symbols = 0;
287 ForeachNode(&pm->m_symbols, sym) {
288 symbols++;
289 if (sym->s_name) {
290 APTR end = (APTR)sym->s_name + strlen(sym->s_name) + 1 + 1;
291 if ((APTR)sym->s_name < str_l)
292 str_l = (APTR)sym->s_name;
293 if (end > str_h)
294 str_h = end;
296 if ((APTR)(uintptr_t)sym->s_lowest < seg_l)
297 seg_l = (APTR)(uintptr_t)sym->s_lowest;
298 if ((APTR)(uintptr_t)sym->s_highest > seg_h)
299 seg_h = (APTR)(uintptr_t)sym->s_highest;
302 if (symbols) {
303 DSYMS(bug("[Debug] String table %p-%p (%u bytes)\n", str_l, str_h, (unsigned int)(str_h - str_l)));
304 DSYMS(bug("[Debug] Symbols for %p-%p (%u symbols)\n", seg_l, seg_h, symbols));
306 seg->s_lowest = (APTR)seg_l;
307 seg->s_highest = (APTR)seg_h;
309 mod->m_symcnt = symbols;
310 mod->m_str = AllocVec(str_h - str_l, MEMF_PUBLIC);
312 if (mod->m_str) {
313 CopyMem(str_l, mod->m_str, str_h - str_l);
315 mod->m_symbols = AllocVec(sizeof(*mod->m_symbols) * symbols, MEMF_PUBLIC);
316 if (mod->m_symbols) {
317 dsym = mod->m_symbols;
318 ForeachNode(&pm->m_symbols, sym) {
319 dsym->s_name = ((APTR)sym->s_name - str_l) + mod->m_str;
320 dsym->s_lowest = (APTR)(uintptr_t)sym->s_lowest;
321 dsym->s_highest= (APTR)(uintptr_t)sym->s_highest;
322 dsym++;
324 ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem);
325 AddTail((struct List *)&DBGBASE(DebugBase)->db_Modules, (struct Node *)seg);
326 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
327 continue;
330 FreeVec(mod->m_str);
333 FreeVec(seg);
337 } else if (debugType == DEBUG_HUNK) {
338 RegisterModule_Hunk(name, segList, debugType, debugInfo, DebugBase);
340 AROS_LIBFUNC_EXIT