3 * kProfiler Mark 2 - Core Module Segment Code Template.
7 * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
33 * Adds a module segment.
35 * @returns Offset to the module if existing or successfully added
36 * @returns 0 if not found.
38 * @param pHdr The profiler header.
39 * @param pModSeg Pointer to the module segment to insert (it's copied of course).
40 * @param off The offset into the modseg area which has been searched.
41 * (This is relative to the first moddule segment record (at pHdr->offModSegs).)
43 static KU32
KPRF_NAME(InsertModSeg
)(KPRF_TYPE(P
,HDR
) pHdr
, KPRF_TYPE(PC
,MODSEG
) pModSeg
, KU32 off
)
46 * Lookup the module segment, inserting it if not found (and there is room).
50 if (off
>= pHdr
->cbModSegs
)
53 * It was the end, let's try insert it.
55 * This is where we lock the modseg stuff. The deal is that we
56 * serialize the actual inserting without blocking lookups. This
57 * means that we may end up with potential racing inserts, but
58 * unless there is a large amount of modules being profiled that's
59 * probably not going to be much of a problem. Anyway if we race,
60 * we'll simply have to search the new additions before we add our
64 if (off
>= pHdr
->cbModSegs
)
66 KU32 cbModSeg
= KPRF_OFFSETOF(MODSEG
, szPath
[pModSeg
->cchPath
+ 1]);
67 cbModSeg
= KPRF_ALIGN(cbModSeg
, KPRF_SIZEOF(UPTR
));
68 if (off
+ cbModSeg
<= pHdr
->cbMaxModSegs
)
70 KPRF_TYPE(P
,MODSEG
) pNew
= KPRF_OFF2PTR(P
,MODSEG
, off
+ pHdr
->offModSegs
, pHdr
);
71 pNew
->uBasePtr
= pModSeg
->uBasePtr
;
72 pNew
->cbSegmentMinusOne
= pModSeg
->cbSegmentMinusOne
;
73 pNew
->iSegment
= pModSeg
->iSegment
;
74 pNew
->fLoaded
= pModSeg
->fLoaded
;
75 pNew
->cchPath
= pModSeg
->cchPath
;
77 KI32 iPath
= pModSeg
->cchPath
;
78 do pNew
->szPath
[iPath
] = pModSeg
->szPath
[iPath
];
82 KPRF_ATOMIC_SET32(&pHdr
->cbModSegs
, off
+ cbModSeg
);
83 off
+= pHdr
->offModSegs
;
87 KPRF_MODSEGS_UNLOCK();
90 KPRF_MODSEGS_UNLOCK();
91 /* someone raced us, check the new entries. */
97 KPRF_TYPE(PC
,MODSEG
) pCur
= KPRF_OFF2PTR(P
,MODSEG
, off
+ pHdr
->offModSegs
, pHdr
);
98 if ( pCur
->uBasePtr
== pModSeg
->uBasePtr
99 && pCur
->fLoaded
== pModSeg
->fLoaded
100 && pCur
->cchPath
== pModSeg
->cchPath
101 && pCur
->iSegment
== pModSeg
->iSegment
102 && pCur
->cbSegmentMinusOne
== pModSeg
->cbSegmentMinusOne
105 KI32 iPath
= pModSeg
->cchPath
;
109 return off
+ pHdr
->offModSegs
;
110 if (pModSeg
->szPath
[iPath
] != pCur
->szPath
[iPath
])
113 /* didn't match, continue searching */
115 KU32 cbCur
= KPRF_OFFSETOF(MODSEG
, szPath
[pCur
->cchPath
+ 1]);
116 off
+= KPRF_ALIGN(cbCur
, KPRF_SIZEOF(UPTR
));
122 * Queries data for and inserts a new module segment.
125 * @returns Offset to the module if existing or successfully added
126 * @returns 0 if not found.
128 * @param pHdr The profiler header.
129 * @param uPC Address within the module.
130 * @param off The offset into the modseg area which has been searched.
131 * (This is relative to the first moddule segment record (at pHdr->offModSegs).)
133 static KU32
KPRF_NAME(NewModSeg
)(KPRF_TYPE(P
,HDR
) pHdr
, KPRF_TYPE(,UPTR
) uPC
, KU32 off
)
136 * Query the module name and object of the function.
141 KPRF_TYPE(,MODSEG
) ModSeg
;
142 char szMorePath
[260];
145 if (KPRF_GET_MODSEG(uPC
+ pHdr
->uBasePtr
, s
.ModSeg
.szPath
, sizeof(s
.ModSeg
.szPath
) + sizeof(s
.szMorePath
),
146 &s
.ModSeg
.iSegment
, &s
.ModSeg
.uBasePtr
, &s
.ModSeg
.cbSegmentMinusOne
))
148 s
.ModSeg
.uBasePtr
-= pHdr
->uBasePtr
;
149 s
.ModSeg
.fLoaded
= 1;
150 s
.ModSeg
.cchPath
= 0;
151 while (s
.ModSeg
.szPath
[s
.ModSeg
.cchPath
])
154 return KPRF_NAME(InsertModSeg
)(pHdr
, &s
.ModSeg
, off
);
159 * Record a module segment.
161 * This is an internal worker for recording a module segment when adding
164 * @returns Offset to the module if existing or successfully added
165 * @returns 0 if not found.
167 * @param pHdr The profiler header.
168 * @param uPC Address within the module.
170 static KU32
KPRF_NAME(RecordModSeg
)(KPRF_TYPE(P
,HDR
) pHdr
, KPRF_TYPE(,UPTR
) uPC
)
173 * Lookup the module segment, inserting it if not found (and there is room).
176 KPRF_TYPE(PC
,MODSEG
) pCur
= KPRF_OFF2PTR(P
,MODSEG
, pHdr
->offModSegs
, pHdr
);
177 const KU32 cbModSegs
= pHdr
->cbModSegs
;
180 /* done and not found? */
181 if (off
>= cbModSegs
)
182 return KPRF_NAME(NewModSeg
)(pHdr
, uPC
, off
);
188 && uPC
- pCur
->uBasePtr
<= pCur
->cbSegmentMinusOne
)
189 return off
+ pHdr
->offModSegs
;
191 KU32 cbCur
= KPRF_OFFSETOF(MODSEG
, szPath
[pCur
->cchPath
+ 1]);
192 cbCur
= KPRF_ALIGN(cbCur
, KPRF_SIZEOF(UPTR
));
194 pCur
= (KPRF_TYPE(PC
,MODSEG
))((KU8
*)pCur
+ cbCur
);