source: trunk/src/odinprof/symfile.cpp@ 7423

Last change on this file since 7423 was 7423, checked in by phaller, 24 years ago

.

File size: 12.8 KB
Line 
1/* $Id: symfile.cpp,v 1.2 2001-11-22 11:34:43 phaller Exp $ */
2/*
3 * Project Odin Software License can be found in LICENSE.TXT
4 * Execution Trace Profiler
5 *
6 * Copyright 2001 Patrick Haller <patrick.haller@innotek.de>
7 *
8 */
9
10
11/****************************************************************************
12 * To Do
13 ****************************************************************************
14
15 - find and load symbolic debug information file
16 (SYM2IDA)
17 => verify against kernel32\exceptionstack.cpp
18 (KERNEL32.SYM is not interpreted correctly)
19 */
20
21
22/****************************************************************************
23 * includes
24 ****************************************************************************/
25
26#define INCL_DOSERRORS
27#define INCL_DOSPROCESS
28#define INCL_DOSMISC
29#define INCL_DOSFILEMGR
30#include <os2.h>
31
32#include <os2sel.h>
33#include <stdlib.h>
34#include <string.h>
35#include <stdio.h>
36#include <demangle.h>
37
38#include "profcollection.h"
39#include "symfile.h"
40
41
42/****************************************************************************
43 * implementation
44 ****************************************************************************/
45
46/*****************************************************************************
47 * Name : APIRET ReadFileToBuffer
48 * Funktion : Reads a single file completely into a memory buffer
49 * Parameter : PSZ pszFile, PPVOID ppBuffer, PULONG pulBuffer
50 * Variablen :
51 * Ergebnis : API-Returncode
52 * Bemerkung :
53 *
54 * Autor : Patrick Haller [Samstag, 07.10.1995 03.22.44]
55 *****************************************************************************/
56
57APIRET ToolsReadFileToBuffer (PSZ pszFile,
58 PPVOID ppBuffer,
59 PULONG pulBuffer)
60{
61 APIRET rc; /* API-Returncode */
62 FILESTATUS3 fs3Status; /* Dateiinformationen */
63 HFILE hFileInput; /* input file handle */
64 ULONG ulAction; /* dummy parameter for DosOpen */
65 ULONG ulReadSize; /* number of bytes to read per call */
66 ULONG ulReadTotal = 0; /* total number of bytes read */
67
68 if ( (pszFile == NULL) || /* check parameters */
69 (ppBuffer == NULL) ||
70 (pulBuffer == NULL) )
71 return (ERROR_INVALID_PARAMETER); /* signal error */
72
73
74 rc = DosQueryPathInfo (pszFile, /* Infos einholen */
75 FIL_STANDARD,
76 &fs3Status,
77 sizeof(fs3Status));
78 if (rc != NO_ERROR) /* check if an error occured */
79 return (rc); /* signal error */
80
81 /* allocate buffer RAM for the file */
82 *pulBuffer = fs3Status.cbFile; /* return the size of the file */
83 rc = DosAllocMem(ppBuffer, /* allocate the buffer */
84 fs3Status.cbFile,
85 PAG_WRITE |
86 PAG_READ |
87 PAG_COMMIT);
88 if (rc != NO_ERROR) /* check if the allocation failed */
89 return (rc); /* signal error */
90
91 ulReadSize = fs3Status.cbFile;
92
93 rc = DosOpen(pszFile, /* File path name */
94 &hFileInput, /* File handle */
95 &ulAction, /* Action taken */
96 0L, /* File primary allocation */
97 FILE_ARCHIVED |
98 FILE_NORMAL, /* File attribute */
99 OPEN_ACTION_FAIL_IF_NEW |
100 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
101 OPEN_FLAGS_NOINHERIT |
102 OPEN_FLAGS_SEQUENTIAL|
103 OPEN_SHARE_DENYNONE |
104 OPEN_ACCESS_READONLY, /* Open mode of the file */
105 0L); /* No extended attribute */
106 if (rc == NO_ERROR) /* check for errors */
107 {
108 ULONG ulRead; /* number of read bytes */
109
110 rc = DosRead (hFileInput,
111 *ppBuffer,
112 ulReadSize,
113 &ulRead);
114
115 DosClose (hFileInput); /* close the filehandle in any case */
116 }
117
118 if (rc != NO_ERROR) /* check for errors */
119 {
120 DosFreeMem (*ppBuffer); /* free the allocated memory */
121 *ppBuffer = NULL; /* reset the passed back values */
122 *pulBuffer = 0;
123 }
124
125 return (rc); /* return code */
126}
127
128
129
130
131LXSymbolFile::LXSymbolFile(PSZ _pszName, PSZ _pszFileName)
132{
133 pszName = strdup(_pszName); // copy lookup name
134 pszFileName = strdup(_pszFileName);
135 pszErrorMessage = NULL;
136}
137
138
139LXSymbolFile::~LXSymbolFile()
140{
141 if (pszName)
142 free(pszName);
143
144 if (pszErrorMessage)
145 free(pszErrorMessage);
146
147 if (pszFileName)
148 free(pszFileName);
149
150 if (pSymbolRawData)
151 DosFreeMem (pSymbolRawData);
152}
153
154
155void LXSymbolFile::setErrorMessage(PSZ _pszErrorMessage)
156{
157 if (pszErrorMessage)
158 free(pszErrorMessage);
159
160 if (NULL != _pszErrorMessage)
161 pszErrorMessage = strdup(_pszErrorMessage);
162 else
163 pszErrorMessage = NULL;
164}
165
166
167APIRET LXSymbolFile::parseFile()
168{
169 APIRET rc;
170 ULONG ulBufferSize;
171
172 // 1 - read file to buffer
173 rc = ToolsReadFileToBuffer(pszFileName,
174 (PPVOID)&pSymbolRawData,
175 &ulBufferSize);
176 if (NO_ERROR != rc)
177 {
178 setErrorMessage("unable to read file");
179 return rc;
180 }
181
182 return NO_ERROR;
183}
184
185
186BOOL LXSymbolFile::isAvailable()
187{
188 return pszErrorMessage == NULL;
189}
190
191
192PSZ LXSymbolFile::getErrorMessage()
193{
194 return pszErrorMessage;
195}
196
197
198PSZ LXSymbolFile::getFileName()
199{
200 return pszFileName;
201}
202
203
204BOOL LXSymbolFile::getSymbolName(ULONG objNr,
205 ULONG offset,
206 PSZ pszNameBuffer,
207 ULONG ulNameBufferLength,
208 PULONG pulSymbolOffset)
209{
210 PUCHAR p = (PUCHAR)pSymbolRawData;
211 ULONG ulMapDefs;
212 PMAPDEF pMapDef;
213 ULONG SegOffset;
214 ULONG SymOffset;
215 ULONG ulSegNum;
216 ULONG ulSymNum;
217 SEGDEF* pSegDef;
218 SYMDEF32* pSymDef32;
219
220 // scan through the maps
221 pMapDef = (PMAPDEF)p;
222 for (ulMapDefs = 0;
223 pMapDef->ppNextMap != 0;
224 ulMapDefs++)
225 {
226 SegOffset = pMapDef->ppSegDef * 16;
227
228 for (ulSegNum = 0;
229 ulSegNum < pMapDef->cSegs;
230 ulSegNum++)
231 {
232 pSegDef = (PSEGDEF)(p + SegOffset);
233
234 // check for the segment number
235 if (ulSegNum == objNr)
236 {
237 PSYMDEF32 pSymClosest = NULL;
238
239 // lookup the symbol
240 for (ulSymNum = 0;
241 ulSymNum < pSegDef->cSymbols;
242 ulSymNum++)
243 {
244 /* calculate symbol offset */
245 PUCHAR pucTemp = ( (PUCHAR)pSegDef +
246 pSegDef->pSymDef +
247 ulSymNum * sizeof(USHORT) );
248 SymOffset = *(PUSHORT)pucTemp;
249 pucTemp = (PUCHAR)pSegDef + SymOffset;
250
251 if (pSegDef->bFlags & 0x01)
252 {
253 // 32-bit segment
254 pSymDef32 = (PSYMDEF32)pucTemp;
255
256 if (NULL == pSymClosest)
257 pSymClosest = pSymDef32;
258 else
259 {
260 int iClosest = offset - pSymClosest->wSymVal;
261 int iCurrent = offset - pSymDef32->wSymVal;
262
263 // find nearest symbol to the given offset
264 if (iCurrent > 0)
265 if (iClosest > iCurrent)
266 pSymClosest = pSymDef32;
267 }
268
269 // check if we've found it (or get the closest symbol)
270 if (offset == pSymDef32->wSymVal)
271 {
272 int iLen = min(pSymDef32->cbSymName, ulNameBufferLength);
273 memcpy(pszNameBuffer,
274 pSymDef32->achSymName,
275 iLen);
276
277 // terminate the string in any case
278 pszNameBuffer[iLen] = 0;
279 *pulSymbolOffset = 0;
280
281 // OK, found
282 return TRUE;
283 }
284 }
285 else
286 {
287 // 16-bit segment
288 // @@@PH not supported
289 }
290 } /* symbol lookup */
291
292 if (NULL != pSymClosest)
293 {
294 CHAR szBuf[128];
295 int iLen;
296
297 // proper symbol name found?
298 if ( (pSymClosest->achSymName[0] > 32) &&
299 (pSymClosest->cbSymName < 255) )
300 {
301 memcpy(szBuf, pSymClosest->achSymName, sizeof(szBuf));
302 szBuf[ min(sizeof(szBuf), pSymClosest->cbSymName) ] = 0;
303 iLen = min(strlen(szBuf), ulNameBufferLength);
304 }
305 else
306 {
307 sprintf(szBuf, "%s:obj%d:%08xh", getName(), objNr, offset);
308 iLen = min(strlen(szBuf), ulNameBufferLength);
309 }
310
311 memcpy(pszNameBuffer, szBuf, iLen);
312 pszNameBuffer[iLen] = 0; // terminate the string in any case
313 *pulSymbolOffset = offset - pSymClosest->wSymVal;
314 return TRUE; // at least something usable has been found!
315 }
316 else
317 {
318 // nothing usable was found
319 return FALSE;
320 }
321 }
322
323 SegOffset = (pSegDef->ppNextSeg * 16);
324 } /* segment loop */
325
326 p += (pMapDef->ppNextMap * 16);
327 pMapDef = (PMAPDEF)p;
328 } /* map loop */
329
330 // not found
331 return FALSE;
332}
333
334
335
336
337
338SymbolFilePool::SymbolFilePool()
339{
340 pHashModules = new CHashtableLookup(67);
341}
342
343
344SymbolFilePool::~SymbolFilePool()
345{
346 if (pHashModules)
347 delete pHashModules;
348}
349
350
351APIRET SymbolFilePool::searchModule(PSZ pszModule, PBYTE pBuffer, ULONG ulBufferLength)
352{
353 // 1 - build symbol filename
354 CHAR szSymFile[260];
355
356 strcpy(szSymFile, pszModule);
357 PSZ pszDot = strrchr(szSymFile, '.');
358 if (NULL == pszDot)
359 pszDot = szSymFile + strlen(szSymFile);
360
361 strcpy(pszDot, ".sym");
362
363 // 2 - search path for symbol files
364 // and copy result to pszFilename
365 APIRET rc = DosSearchPath(SEARCH_IGNORENETERRS |
366 SEARCH_ENVIRONMENT |
367 SEARCH_CUR_DIRECTORY,
368 "PATH",
369 szSymFile,
370 pBuffer,
371 ulBufferLength);
372 if ( (rc == ERROR_FILE_NOT_FOUND) ||
373 (rc == ERROR_ENVVAR_NOT_FOUND) )
374 rc = DosSearchPath(SEARCH_IGNORENETERRS |
375 SEARCH_ENVIRONMENT |
376 SEARCH_CUR_DIRECTORY,
377 "DPATH",
378 szSymFile,
379 pBuffer,
380 ulBufferLength);
381
382 return rc;
383}
384
385
386
387BOOL SymbolFilePool::getSymbolName(PSZ pszModule,
388 ULONG objNr,
389 ULONG offset,
390 PSZ pszNameBuffer,
391 ULONG ulNameBufferLength,
392 PULONG pulSymbolOffset)
393{
394 LXSymbolFile* pSym = (LXSymbolFile*)pHashModules->getElement(pszModule);
395 if (NULL == pSym)
396 {
397 CHAR szFilename[260];
398
399 // 1 - locate the file
400 APIRET rc = searchModule(pszModule, szFilename, sizeof(szFilename));
401
402 // create new entry
403 pSym = new LXSymbolFile(pszModule, szFilename);
404
405 // parse the file
406 if (rc == NO_ERROR)
407 pSym->parseFile();
408 else
409 pSym->setErrorMessage("file not found");
410
411 // add to the hashtable
412 pHashModules->addElement(pszModule, pSym);
413 }
414
415 BOOL rc;
416
417 // if the parsed symbol table is correct, lookup the symbol
418 if (pSym->isAvailable())
419 {
420 rc = pSym->getSymbolName(objNr,
421 offset,
422 pszNameBuffer,
423 ulNameBufferLength,
424 pulSymbolOffset);
425
426 if (rc == TRUE)
427 {
428 // check if we can demangle a C++ name
429 char* rest;
430 Name* name = Demangle(pszNameBuffer, rest);
431 if (name != NULL)
432 {
433 strncpy(pszNameBuffer,
434 name->Text(),
435 ulNameBufferLength);
436 delete name;
437 }
438
439 // append symbol offsets
440 if (*pulSymbolOffset != 0)
441 {
442 CHAR szBuf[256];
443 sprintf(szBuf,
444 "%s+%xh",
445 pszNameBuffer,
446 *pulSymbolOffset);
447 strncpy(pszNameBuffer,
448 szBuf,
449 ulNameBufferLength);
450 }
451 }
452 }
453 else
454 rc = FALSE;
455
456 return rc;
457}
458
Note: See TracBrowser for help on using the repository browser.