2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
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>
21 #include "debug_intern.h"
23 static inline char *getstrtab(struct sheader
*sh
)
27 str
= AllocVec(sh
->size
, MEMF_PUBLIC
);
29 CopyMem(sh
->addr
, str
, sh
->size
);
34 static void addsymbol(module_t
*mod
, dbg_sym_t
*sym
, struct symbol
*st
, APTR value
)
37 sym
->s_name
= &mod
->m_str
[st
->name
];
41 sym
->s_lowest
= value
;
43 sym
->s_highest
= value
+ st
->size
- 1;
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 */
52 static void RegisterModule_Hunk(const char *name
, BPTR segList
, ULONG DebugType
, APTR DebugInfo
, struct Library
*DebugBase
)
57 mod
= AllocVec(sizeof(module_t
) + strlen(name
), MEMF_PUBLIC
|MEMF_CLEAR
);
60 strcpy(mod
->m_name
, name
);
63 ULONG
*segPtr
= BADDR(segList
);
64 struct segment
*seg
= AllocMem(sizeof(struct segment
), MEMF_PUBLIC
| MEMF_CLEAR
);
66 seg
->s_lowest
= (UBYTE
*)segPtr
- 4;
67 seg
->s_highest
= (UBYTE
*)segPtr
+ segPtr
[-1];
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
);
83 /*****************************************************************************
86 #include <proto/debug.h>
88 AROS_LH4(void, RegisterModule
,
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
),
97 struct Library
*, DebugBase
, 5, Debug
)
100 Add information about the loaded executable module to the
101 debug information database
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.
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 ******************************************************************************/
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
);
142 ULONG int_shnum
= eh
->shnum
;
143 ULONG int_shstrndx
= eh
->shstrndx
;
147 /* Get wider versions of shnum and shstrndx from first section header if needed */
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(§ions
[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(§ions
[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
);
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 */
186 seg
->s_name
= &mod
->m_shstr
[sections
[i
].name
];
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)
212 FreeVec(mod
->m_shstr
);
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
);
228 mod
->m_symbols
= 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
))
238 /* TODO: perhaps XINDEX support is needed */
239 if (idx
== SHN_XINDEX
)
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
));
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
));
257 } else if (debugType
== DEBUG_PARTHENOPE
) {
258 const struct Parthenope_ModuleInfo
*pm
;
260 ForeachNode(debugInfo
, pm
) {
263 seg
= AllocVec(sizeof(struct segment
) + sizeof(module_t
) + strlen(pm
->m_name
), MEMF_PUBLIC
|MEMF_CLEAR
);
266 unsigned int symbols
;
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
);
278 seg
->s_name
= mod
->m_name
;
285 /* Determine the size of the string table */
287 ForeachNode(&pm
->m_symbols
, sym
) {
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
;
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
;
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
);
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
;
324 ObtainSemaphore(&DBGBASE(DebugBase
)->db_ModSem
);
325 AddTail((struct List
*)&DBGBASE(DebugBase
)->db_Modules
, (struct Node
*)seg
);
326 ReleaseSemaphore(&DBGBASE(DebugBase
)->db_ModSem
);
337 } else if (debugType
== DEBUG_HUNK
) {
338 RegisterModule_Hunk(name
, segList
, debugType
, debugInfo
, DebugBase
);