Minor fixes to comments.
[AROS.git] / rom / debug / registermodule.c
blob024f33b07c72d23b87d341bb923c5febf70b2c38
1 #define DEBUG 0
2 #define DSYMS(x)
4 #include <aros/debug.h>
5 #include <aros/libcall.h>
6 #include <dos/dosextens.h>
7 #include <exec/lists.h>
8 #include <libraries/debug.h>
9 #include <proto/exec.h>
11 #include <stdint.h>
12 #include <string.h>
14 #include "debug_intern.h"
16 static inline char *getstrtab(struct sheader *sh)
18 char *str;
20 str = AllocVec(sh->size, MEMF_PUBLIC);
21 if (str)
22 CopyMem(sh->addr, str, sh->size);
24 return str;
27 static void addsymbol(module_t *mod, dbg_sym_t *sym, struct symbol *st, APTR value)
29 if (mod->m_str)
30 sym->s_name = &mod->m_str[st->name];
31 else
32 sym->s_name = NULL;
34 sym->s_lowest = value;
35 if (st->size)
36 sym->s_highest = value + st->size - 1;
37 else
38 /* For symbols with zero size KDL_SymbolEnd will give NULL */
39 sym->s_highest = NULL;
41 /* We count symbols here because not all of them can be added */
42 mod->m_symcnt++;
45 /*****************************************************************************
47 NAME */
48 #include <proto/debug.h>
50 AROS_LH4(void, RegisterModule,
52 /* SYNOPSIS */
53 AROS_LHA(const char *, name, A0),
54 AROS_LHA(BPTR, segList, A1),
55 AROS_LHA(ULONG, debugType, D0),
56 AROS_LHA(APTR, debugInfo, A2),
58 /* LOCATION */
59 struct Library *, DebugBase, 5, Debug)
61 /* FUNCTION
62 Add information about the loaded executable module to the
63 debug information database
65 INPUTS
66 name - Module name
67 segList - DOS segment list for the module
68 debugType - Type of supplied debug information. The only currently
69 supported type is DEBUG_ELF.
70 debugInfo - Debug information data. For DEBUG_ELF type this should be
71 a pointer to struct ELF_DebugInfo, filled in as follows:
72 eh - a pointer to ELF file header.
73 sh - a pointer to an array of ELF section headers.
75 RESULT
76 None
78 NOTES
80 EXAMPLE
82 BUGS
84 SEE ALSO
86 INTERNALS
87 The function supposes that segments in DOS list are linked in the same
88 order in which corresponding sections are placed in the file
90 ******************************************************************************/
92 AROS_LIBFUNC_INIT
94 D(bug("[Debug] RegisterModule(%s, 0x%p, %d)\n", name, segList, debugType));
96 if (debugType == DEBUG_ELF)
98 struct elfheader *eh = ((struct ELF_DebugInfo *)debugInfo)->eh;
99 struct sheader *sections = ((struct ELF_DebugInfo *)debugInfo)->sh;
100 module_t *mod = AllocVec(sizeof(module_t) + strlen(name), MEMF_PUBLIC|MEMF_CLEAR);
102 if (mod)
104 ULONG int_shnum = eh->shnum;
105 ULONG int_shstrndx = eh->shstrndx;
106 ULONG shstr;
107 ULONG i;
109 /* Get wider versions of shnum and shstrndx from first section header if needed */
110 if (int_shnum == 0)
111 int_shnum = sections[0].size;
112 if (int_shstrndx == SHN_XINDEX)
113 int_shstrndx = sections[0].link;
115 D(bug("[Debug] %d sections at 0x%p\n", int_shnum, sections));
116 shstr = SHINDEX(int_shstrndx);
118 strcpy(mod->m_name, name);
119 if (sections[shstr].type == SHT_STRTAB)
120 mod->m_shstr = getstrtab(&sections[shstr]);
122 for (i=0; i < int_shnum; i++)
124 /* Ignore all empty segments */
125 if (sections[i].size)
127 /* If we have string table, copy it */
128 if ((sections[i].type == SHT_STRTAB) && (i != shstr) && (!mod->m_str)) {
129 D(bug("[Debug] Symbol name table of length %d in section %d\n", sections[i].size, i));
130 mod->m_str = getstrtab(&sections[i]);
133 /* Every loadable section with nonzero size got a corresponding DOS segment */
134 if (segList && (sections[i].flags & SHF_ALLOC))
136 struct segment *seg = AllocMem(sizeof(struct segment), MEMF_PUBLIC);
138 if (seg) {
139 D(bug("[Debug] Adding segment 0x%p\n", segList));
141 seg->s_lowest = sections[i].addr;
142 seg->s_highest = sections[i].addr + sections[i].size - 1;
143 seg->s_seg = segList; /* Note that this will differ from s_lowest */
144 seg->s_mod = mod;
145 seg->s_num = i;
146 if (mod->m_shstr)
147 seg->s_name = &mod->m_shstr[sections[i].name];
148 else
149 seg->s_name = NULL;
151 mod->m_segcnt++;
153 ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem);
154 AddTail((struct List *)&DBGBASE(DebugBase)->db_Modules, (struct Node *)seg);
155 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
158 /* Advance to next DOS segment */
159 segList = *(BPTR *)BADDR(segList);
164 /* If the module contains no loadable segments (hm, weird),
165 we actually got nothing linked in our base list. This means
166 that module handle is actually a garbage and we can deallocate
167 it right now, and do nothing more */
168 if (mod->m_segcnt == 0)
170 if (mod->m_str)
171 FreeVec(mod->m_str);
172 if (mod->m_shstr)
173 FreeVec(mod->m_shstr);
174 FreeVec(mod);
176 return;
179 /* Parse module's symbol table */
180 for (i=0; i < int_shnum; i++)
182 if (sections[i].addr && sections[i].type == SHT_SYMTAB)
184 struct symbol *st = (struct symbol *)sections[i].addr;
185 unsigned int symcnt = sections[i].size / sizeof(struct symbol);
186 dbg_sym_t *sym = AllocVec(sizeof(dbg_sym_t) * symcnt, MEMF_PUBLIC);
187 unsigned int j;
189 mod->m_symbols = sym;
191 if (sym) {
192 for (j=0; j < symcnt; j++)
194 int idx = st[j].shindex;
196 /* Ignore these - they should not be here at all */
197 if ((idx == SHN_UNDEF) || (idx == SHN_COMMON))
198 continue;
199 /* TODO: perhaps XINDEX support is needed */
200 if (idx == SHN_XINDEX)
201 continue;
203 if (idx == SHN_ABS) {
204 addsymbol(mod, sym, &st[j], (APTR)st[j].value);
205 DSYMS(bug("[Debug] Added ABS symbol '%s' %08x-%08x\n", sym->s_name, sym->s_lowest, sym->s_highest));
206 sym++;
207 } else if (sections[idx].addr && (sections[idx].flags & SHF_ALLOC)) {
208 addsymbol(mod, sym, &st[j], sections[idx].addr + st[j].value);
209 DSYMS(bug("[Debug] Added symbol '%s' %08x-%08x\n", sym->s_name, sym->s_lowest, sym->s_highest));
210 sym++;
214 break;
218 } else if (debugType == DEBUG_PARTHENOPE) {
219 const struct Parthenope_ModuleInfo *pm;
221 ForeachNode(debugInfo, pm) {
222 struct segment *seg;
224 seg = AllocVec(sizeof(struct segment) + sizeof(module_t) + strlen(pm->m_name), MEMF_PUBLIC|MEMF_CLEAR);
226 if (seg) {
227 unsigned int symbols;
228 dbg_sym_t *dsym;
229 const struct Parthenope_Symbol *sym;
230 APTR str_l = (APTR)~(uintptr_t)0, str_h = (APTR)(uintptr_t)0;
231 APTR seg_l = (APTR)~(uintptr_t)0, seg_h = (APTR)(uintptr_t)0;
232 module_t *mod = (module_t *)(&seg[1]);
234 DSYMS(bug("[Debug] Adding module @%p: %s\n", pm, pm->m_name));
235 strcpy(mod->m_name, pm->m_name);
237 seg->s_seg = BNULL;
238 seg->s_mod = mod;
239 seg->s_name = mod->m_name;
240 seg->s_num = 0;
242 mod->m_shstr = NULL;
243 mod->m_str = NULL;
244 mod->m_segcnt = 0;
246 /* Determine the size of the string table */
247 symbols = 0;
248 ForeachNode(&pm->m_symbols, sym) {
249 symbols++;
250 if (sym->s_name) {
251 APTR end = (APTR)sym->s_name + strlen(sym->s_name) + 1 + 1;
252 if ((APTR)sym->s_name < str_l)
253 str_l = (APTR)sym->s_name;
254 if (end > str_h)
255 str_h = end;
257 if ((APTR)(uintptr_t)sym->s_lowest < seg_l)
258 seg_l = (APTR)(uintptr_t)sym->s_lowest;
259 if ((APTR)(uintptr_t)sym->s_highest > seg_h)
260 seg_h = (APTR)(uintptr_t)sym->s_highest;
263 if (symbols) {
264 DSYMS(bug("[Debug] String table %p-%p (%u bytes)\n", str_l, str_h, (unsigned int)(str_h - str_l)));
265 DSYMS(bug("[Debug] Symbols for %p-%p (%u symbols)\n", seg_l, seg_h, symbols));
267 seg->s_lowest = (APTR)seg_l;
268 seg->s_highest = (APTR)seg_h;
270 mod->m_symcnt = symbols;
271 mod->m_str = AllocVec(str_h - str_l, MEMF_PUBLIC);
273 if (mod->m_str) {
274 CopyMem(str_l, mod->m_str, str_h - str_l);
276 mod->m_symbols = AllocVec(sizeof(*mod->m_symbols) * symbols, MEMF_PUBLIC);
277 if (mod->m_symbols) {
278 dsym = mod->m_symbols;
279 ForeachNode(&pm->m_symbols, sym) {
280 dsym->s_name = ((APTR)sym->s_name - str_l) + mod->m_str;
281 dsym->s_lowest = (APTR)(uintptr_t)sym->s_lowest;
282 dsym->s_highest= (APTR)(uintptr_t)sym->s_highest;
283 dsym++;
285 ObtainSemaphore(&DBGBASE(DebugBase)->db_ModSem);
286 AddTail((struct List *)&DBGBASE(DebugBase)->db_Modules, (struct Node *)seg);
287 ReleaseSemaphore(&DBGBASE(DebugBase)->db_ModSem);
288 continue;
291 FreeVec(mod->m_str);
294 FreeVec(seg);
300 AROS_LIBFUNC_EXIT