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>
14 #include "debug_intern.h"
16 static inline char *getstrtab(struct sheader
*sh
)
20 str
= AllocVec(sh
->size
, MEMF_PUBLIC
);
22 CopyMem(sh
->addr
, str
, sh
->size
);
27 static void addsymbol(module_t
*mod
, dbg_sym_t
*sym
, struct symbol
*st
, APTR value
)
30 sym
->s_name
= &mod
->m_str
[st
->name
];
34 sym
->s_lowest
= value
;
36 sym
->s_highest
= value
+ st
->size
- 1;
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 */
45 /*****************************************************************************
48 #include <proto/debug.h>
50 AROS_LH4(void, RegisterModule
,
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
),
59 struct Library
*, DebugBase
, 5, Debug
)
62 Add information about the loaded executable module to the
63 debug information database
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.
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 ******************************************************************************/
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
);
104 ULONG int_shnum
= eh
->shnum
;
105 ULONG int_shstrndx
= eh
->shstrndx
;
109 /* Get wider versions of shnum and shstrndx from first section header if needed */
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(§ions
[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(§ions
[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
);
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 */
147 seg
->s_name
= &mod
->m_shstr
[sections
[i
].name
];
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)
173 FreeVec(mod
->m_shstr
);
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
);
189 mod
->m_symbols
= 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
))
199 /* TODO: perhaps XINDEX support is needed */
200 if (idx
== SHN_XINDEX
)
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
));
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
));
218 } else if (debugType
== DEBUG_PARTHENOPE
) {
219 const struct Parthenope_ModuleInfo
*pm
;
221 ForeachNode(debugInfo
, pm
) {
224 seg
= AllocVec(sizeof(struct segment
) + sizeof(module_t
) + strlen(pm
->m_name
), MEMF_PUBLIC
|MEMF_CLEAR
);
227 unsigned int symbols
;
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
);
239 seg
->s_name
= mod
->m_name
;
246 /* Determine the size of the string table */
248 ForeachNode(&pm
->m_symbols
, sym
) {
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
;
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
;
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
);
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
;
285 ObtainSemaphore(&DBGBASE(DebugBase
)->db_ModSem
);
286 AddTail((struct List
*)&DBGBASE(DebugBase
)->db_Modules
, (struct Node
*)seg
);
287 ReleaseSemaphore(&DBGBASE(DebugBase
)->db_ModSem
);