Keep the scrollbar position in accordance of the M68K PC pointer
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / DWARFManager.cpp
CommitLineData
ebcb0f3d
JPM
1//\r
2// DWARFManager.cpp: DWARF format manager\r
3//\r
4// by Jean-Paul Mari\r
5//\r
6// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
7//\r
8// WHO WHEN WHAT\r
9// --- ---------- ------------------------------------------------------------\r
10// JPM 12/03/2016 Created this file\r
11// JPM 12/03/2016 DWARF format support\r
12\r
13\r
14#include <stdlib.h>\r
15#include <stdio.h>\r
16#include <stdint.h>\r
17#include <string.h>\r
18#include <libdwarf.h>\r
19#include <dwarf.h>\r
20\r
21\r
22// Source line internal structure\r
23struct DMIStruct_LineSrc\r
24{\r
25 size_t Tag;\r
26 size_t StartPC;\r
27 size_t NumLineSrc;\r
28 char *PtrLineSrc;\r
29}S_DMIStruct_LineSrc;\r
30\r
31// Base type internal structure\r
32struct BaseTypeStruct\r
33{\r
34 size_t Tag; // Type's Tag\r
35 size_t Offset; // Type's offset\r
36 size_t TypeOffset; // Type's offset on another type\r
37 size_t ByteSize; // Type's Byte Size\r
38 size_t Encoding; // Type's encoding\r
39 char *PtrName; // Type's name\r
40}S_BaseTypeStruct;\r
41\r
42// Variables internal structure\r
43struct VariablesStruct\r
44{\r
45 size_t Addr; // Variable memory address\r
46 char *PtrName; // Variable's name\r
47 size_t TypeOffset; // Offset pointing on the Variable's Type\r
48 size_t TypeByteSize; // Variable's Type byte size\r
49 size_t TypeTag; // Variable's Type Tag\r
50 size_t TypeEncoding; // Variable's Type encoding\r
51 char *PtrTypeName; // Variable's Type name\r
52}S_VariablesStruct;\r
53\r
54// Sub program internal structure\r
55struct SubProgStruct\r
56{\r
57 size_t Tag;\r
58 size_t NumLineSrc;\r
59 size_t StartPC;\r
60 size_t LowPC, HighPC;\r
61 char *PtrLineSrc;\r
62 char *PtrSubprogramName;\r
63 size_t NbLinesSrc;\r
64 DMIStruct_LineSrc *PtrLinesSrc;\r
65}S_SubProgStruct;\r
66\r
67// Compilation Unit internal structure\r
68struct CUStruct\r
69{\r
70 size_t Tag;\r
71 size_t LowPC, HighPC;\r
72 char *PtrProducer; // Pointer to the "Producer" information (compiler and compilation options used)\r
73 char *PtrFullFilename; // Pointer to full namefile (directory & filename)\r
74 size_t SizeLoadSrc; // Source code size\r
75 char *PtrLoadSrc; // Pointer to loaded source code\r
76 size_t NbLinesLoadSrc; // Lines source number\r
77 char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity\r
78 size_t NbSubProgs; // Number of sub programs / routines\r
79 SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines information structure\r
80 size_t NbTypes;\r
81 BaseTypeStruct *PtrTypes;\r
82 size_t NbVariables; // Variables number\r
83 VariablesStruct *PtrVariables; // Pointer to the variables list information structure\r
84}S_CUStruct;\r
85\r
86\r
87// Dwarf management\r
88uint32_t LibDwarf;\r
89uint32_t NbCU;\r
90Dwarf_Ptr errarg;\r
91Dwarf_Error error;\r
92Dwarf_Debug dbg;\r
93CUStruct *PtrCU;\r
94\r
95\r
96//\r
97Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg);\r
98void DWARFManager_InitDMI(void);\r
99void DWARFManager_CloseDMI(void);\r
100bool DWARFManager_ElfClose(void);\r
101char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine);\r
102\r
103\r
104//\r
105Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg)\r
106{\r
107 return 0;\r
108}\r
109\r
110\r
111// Dwarf manager init\r
112void DWARFManager_Init(void)\r
113{\r
114 LibDwarf = DW_DLV_NO_ENTRY;\r
115}\r
116\r
117\r
118// Dwarf manager Reset\r
119bool DWARFManager_Reset(void)\r
120{\r
121 return DWARFManager_ElfClose();\r
122}\r
123\r
124\r
125// Dwarf manager Close\r
126bool DWARFManager_Close(void)\r
127{\r
128 return(DWARFManager_Reset());\r
129}\r
130\r
131\r
132// Dwarf manager Elf init\r
133int DWARFManager_ElfInit(Elf *ElfPtr)\r
134{\r
135 if ((LibDwarf = dwarf_elf_init(ElfPtr, DW_DLC_READ, (Dwarf_Handler)DWARFManager_ErrorHandler, errarg, &dbg, &error)) == DW_DLV_OK)\r
136 {\r
137 DWARFManager_InitDMI();\r
138 }\r
139\r
140 return LibDwarf;\r
141}\r
142\r
143\r
144// Dwarf manager Elf close\r
145bool DWARFManager_ElfClose(void)\r
146{\r
147 if (LibDwarf == DW_DLV_OK)\r
148 {\r
149 DWARFManager_CloseDMI();\r
150\r
151 if (dwarf_finish(dbg, &error) == DW_DLV_OK)\r
152 {\r
153 LibDwarf = DW_DLV_NO_ENTRY;\r
154 return true;\r
155 }\r
156 else\r
157 {\r
158 return false;\r
159 }\r
160 }\r
161 else\r
162 {\r
163 return true;\r
164 }\r
165}\r
166\r
167\r
168// Dwarf manager Compilation Units close\r
169void DWARFManager_CloseDMI(void)\r
170{\r
171 while (NbCU--)\r
172 {\r
173 free(PtrCU[NbCU].PtrFullFilename);\r
174 free(PtrCU[NbCU].PtrLoadSrc);\r
175 free(PtrCU[NbCU].PtrProducer);\r
176\r
177 while (PtrCU[NbCU].NbLinesLoadSrc--)\r
178 {\r
179 free(PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].NbLinesLoadSrc]);\r
180 }\r
181 free(PtrCU[NbCU].PtrLinesLoadSrc);\r
182\r
183 while (PtrCU[NbCU].NbSubProgs--)\r
184 {\r
185 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc);\r
186 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName);\r
187 }\r
188 free(PtrCU[NbCU].PtrSubProgs);\r
189\r
190 while (PtrCU[NbCU].NbTypes--)\r
191 {\r
192 free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName);\r
193 }\r
194 free(PtrCU[NbCU].PtrTypes);\r
195\r
196 while (PtrCU[NbCU].NbVariables--)\r
197 {\r
198 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);\r
199 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrTypeName);\r
200 }\r
201 free(PtrCU[NbCU].PtrVariables);\r
202 }\r
203\r
204 free(PtrCU);\r
205}\r
206\r
207\r
208// Dwarf manager Compilation Units initialisations\r
209void DWARFManager_InitDMI(void)\r
210{\r
211 Dwarf_Unsigned next_cu_header, return_uvalue;\r
212 Dwarf_Error error;\r
213 Dwarf_Attribute *atlist;\r
214 Dwarf_Attribute return_attr1;\r
215 Dwarf_Half return_tagval, return_attr;\r
216 Dwarf_Addr return_lowpc, return_highpc, return_lineaddr;\r
217 Dwarf_Block *return_block;\r
218 Dwarf_Signed atcnt, cnt;\r
219 Dwarf_Die return_sib, return_die;\r
220 Dwarf_Off return_offset;\r
221 Dwarf_Line *linebuf;\r
222 FILE *SrcFile;\r
223 size_t i, j, k, TypeOffset;\r
224 char *return_string;\r
225 char *Ptr;\r
226 char *SourceFilename = NULL;\r
227 char *SourceFileDirectory = NULL;\r
228 char *SourceFullFilename = NULL;\r
229\r
230 // Initialisation for the Compilation Units table\r
231 NbCU = 0;\r
232 PtrCU = NULL;\r
233\r
234 // loop on the available Compilation Unit\r
235 while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &next_cu_header, &error) == DW_DLV_OK)\r
236 {\r
237 // Allocation of an additional Compilation Unit structure in the table\r
238 if (Ptr = (char *)realloc(PtrCU, ((NbCU + 1) * sizeof(CUStruct))))\r
239 {\r
240 // Compilation Unit RAZ\r
241 PtrCU = (CUStruct *)Ptr;\r
242 memset(PtrCU + NbCU, 0, sizeof(CUStruct));\r
243\r
244 // Get 1st Die from the Compilation Unit\r
245 if (dwarf_siblingof(dbg, NULL, &return_sib, &error) == DW_DLV_OK)\r
246 {\r
247 // Get Die's Tag\r
248 if ((dwarf_tag(return_sib, &return_tagval, &error) == DW_DLV_OK))\r
249 {\r
250 PtrCU[NbCU].Tag = return_tagval;\r
251\r
252 // Die type detection\r
253 switch (return_tagval)\r
254 {\r
255 case DW_TAG_compile_unit:\r
256 if (dwarf_attrlist(return_sib, &atlist, &atcnt, &error) == DW_DLV_OK)\r
257 {\r
258 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
259 {\r
260 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
261 {\r
262 switch (return_attr)\r
263 {\r
264 case DW_AT_low_pc:\r
265 if (dwarf_lowpc(return_sib, &return_lowpc, &error) == DW_DLV_OK)\r
266 {\r
267 PtrCU[NbCU].LowPC = return_lowpc;\r
268 }\r
269 break;\r
270\r
271 case DW_AT_high_pc:\r
272 if (dwarf_highpc(return_sib, &return_highpc, &error) == DW_DLV_OK)\r
273 {\r
274 PtrCU[NbCU].HighPC = return_highpc;\r
275 }\r
276 break;\r
277\r
278 case DW_AT_producer:\r
279 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
280 {\r
281 PtrCU[NbCU].PtrProducer = (char *)calloc(strlen(return_string) + 1, 1);\r
282 strcpy(PtrCU[NbCU].PtrProducer, return_string);\r
283 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
284 }\r
285 break;\r
286\r
287 case DW_AT_name:\r
288 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
289 {\r
290 SourceFilename = (char *)realloc(SourceFilename, strlen(return_string) + 1);\r
291 strcpy(SourceFilename, return_string);\r
292 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
293 }\r
294 break;\r
295\r
296 case DW_AT_comp_dir:\r
297 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
298 {\r
299 SourceFileDirectory = (char *)realloc(SourceFileDirectory, strlen(return_string) + 1);\r
300 strcpy(SourceFileDirectory, return_string);\r
301 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
302 }\r
303 break;\r
304\r
305 default:\r
306 break;\r
307 }\r
308 }\r
309 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
310 }\r
311 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
312 }\r
313\r
314 Ptr = SourceFullFilename = (char *)realloc(SourceFullFilename, strlen(SourceFilename) + strlen(SourceFileDirectory) + 2);\r
315 sprintf(SourceFullFilename, "%s\\%s", SourceFileDirectory, SourceFilename);\r
316 while (*Ptr)\r
317 {\r
318 if (*Ptr == '/')\r
319 {\r
320 *Ptr = '\\';\r
321 }\r
322 Ptr++;\r
323 }\r
324 PtrCU[NbCU].PtrFullFilename = (char *)calloc(strlen(SourceFullFilename) + 1, 1);\r
325 strcpy((char *)PtrCU[NbCU].PtrFullFilename, SourceFullFilename);\r
326\r
327#ifndef __CYGWIN__\r
328 if (!fopen_s(&SrcFile, SourceFullFilename, "rt"))\r
329#else\r
330 if (!(SrcFile = fopen(SourceFullFilename, "rt")))\r
331#endif\r
332 {\r
333 if (!fseek(SrcFile, 0, SEEK_END))\r
334 {\r
335 if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)\r
336 {\r
337 if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)calloc((PtrCU[NbCU].SizeLoadSrc + 1), 1))\r
338 {\r
339 rewind(SrcFile);\r
340 if (PtrCU[NbCU].SizeLoadSrc < fread(Ptr, 1, PtrCU[NbCU].SizeLoadSrc, SrcFile))\r
341 {\r
342 free(PtrCU[NbCU].PtrLoadSrc);\r
343 PtrCU[NbCU].PtrLoadSrc = NULL;\r
344 PtrCU[NbCU].SizeLoadSrc = 0;\r
345 }\r
346 else\r
347 {\r
348 do\r
349 {\r
350 if (*Ptr == 0xa)\r
351 {\r
352 PtrCU[NbCU].NbLinesLoadSrc++;\r
353 *Ptr = 0;\r
354 }\r
355 } while (*++Ptr);\r
356 }\r
357 }\r
358 }\r
359 }\r
360 fclose(SrcFile);\r
361 }\r
362 break;\r
363\r
364 default:\r
365 break;\r
366 }\r
367 }\r
368\r
369 // Get the source lines table located in the Compilation Unit\r
370 if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK)\r
371 {\r
372 }\r
373\r
374 if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK)\r
375 {\r
376 do\r
377 {\r
378 return_sib = return_die;\r
379 if ((dwarf_tag(return_die, &return_tagval, &error) == DW_DLV_OK))\r
380 {\r
381 switch (return_tagval)\r
382 {\r
383 case DW_TAG_lexical_block:\r
384 break;\r
385\r
386 case DW_TAG_variable:\r
387 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
388 {\r
389 PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct)));\r
390 memset(PtrCU[NbCU].PtrVariables + PtrCU[NbCU].NbVariables, 0, sizeof(VariablesStruct));\r
391\r
392 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
393 {\r
394 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
395 {\r
396 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
397 {\r
398 switch (return_attr)\r
399 {\r
400 case DW_AT_location:\r
401 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
402 {\r
403 if (return_block->bl_len == 5)\r
404 {\r
405 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr = (*((unsigned char *)(return_block->bl_data) + 1) << 24) + (*((unsigned char *)(return_block->bl_data) + 2) << 16) + (*((unsigned char *)(return_block->bl_data) + 3) << 8) + (*((unsigned char *)(return_block->bl_data) + 4));\r
406 }\r
407 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
408 }\r
409 break;\r
410\r
411 case DW_AT_type:\r
412 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
413 {\r
414 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset;\r
415 }\r
416 break;\r
417\r
418 case DW_AT_name:\r
419 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
420 {\r
421 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
422 strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);\r
423 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
424 }\r
425 break;\r
426\r
427 default:\r
428 break;\r
429 }\r
430 }\r
431 }\r
432\r
433 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
434 }\r
435\r
436 PtrCU[NbCU].NbVariables++;\r
437\r
438 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
439 }\r
440 break;\r
441\r
442 case DW_TAG_base_type:\r
443 case DW_TAG_typedef:\r
444 case DW_TAG_structure_type:\r
445 case DW_TAG_pointer_type:\r
446 case DW_TAG_const_type:\r
447 case DW_TAG_array_type:\r
448 case DW_TAG_subrange_type:\r
449 case DW_TAG_subroutine_type:\r
450 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
451 {\r
452 PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));\r
453 memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));\r
454 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;\r
455\r
456 if (dwarf_dieoffset(return_die, &return_offset, &error) == DW_DLV_OK)\r
457 {\r
458 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Offset = return_offset;\r
459 }\r
460\r
461 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
462 {\r
463 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
464 {\r
465 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
466 {\r
467 switch (return_attr)\r
468 {\r
469 case DW_AT_type:\r
470 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
471 {\r
472 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset;\r
473 }\r
474 break;\r
475\r
476 case DW_AT_byte_size:\r
477 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
478 {\r
479 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue;\r
480 }\r
481 break;\r
482\r
483 case DW_AT_encoding:\r
484 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
485 {\r
486 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue;\r
487 }\r
488 break;\r
489\r
490 case DW_AT_name:\r
491 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
492 {\r
493 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
494 strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
495 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
496 }\r
497 break;\r
498\r
499 default:\r
500 break;\r
501 }\r
502 }\r
503 }\r
504\r
505 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
506 }\r
507\r
508 PtrCU[NbCU].NbTypes++;\r
509\r
510 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
511 }\r
512 break;\r
513\r
514 case DW_TAG_subprogram:\r
515 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
516 {\r
517 PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct)));\r
518 memset((void *)(PtrCU[NbCU].PtrSubProgs + PtrCU[NbCU].NbSubProgs), 0, sizeof(SubProgStruct));\r
519 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].Tag = return_tagval;\r
520\r
521 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
522 {\r
523 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
524 {\r
525 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
526 {\r
527 switch (return_attr)\r
528 {\r
529 case DW_AT_low_pc:\r
530 if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK)\r
531 {\r
532 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc;\r
533 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].LowPC = return_lowpc;\r
534 }\r
535 break;\r
536\r
537 case DW_AT_high_pc:\r
538 if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK)\r
539 {\r
540 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc;\r
541 }\r
542 break;\r
543\r
544 case DW_AT_decl_line:\r
545 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
546 {\r
547 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue;\r
548 }\r
549 break;\r
550\r
551 case DW_AT_name:\r
552 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
553 {\r
554 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1);\r
555 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName, return_string);\r
556 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
557 }\r
558 break;\r
559\r
560 default:\r
561 break;\r
562 }\r
563 }\r
564 }\r
565 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
566 }\r
567 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
568\r
569 for (i = 0; i < (size_t)cnt; ++i)\r
570 {\r
571 if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)\r
572 {\r
573 if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)\r
574 {\r
575 if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc))\r
576 {\r
577 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc = (DMIStruct_LineSrc *)realloc(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc, (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc + 1) * sizeof(DMIStruct_LineSrc));\r
578 memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));\r
579 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = return_lineaddr;\r
580 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = return_uvalue;\r
581 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;\r
582 }\r
583 }\r
584 } \r
585 }\r
586 \r
587 PtrCU[NbCU].NbSubProgs++;\r
588 }\r
589 break;\r
590\r
591 default:\r
592 break;\r
593 }\r
594 }\r
595 }\r
596 while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);\r
597 }\r
598\r
599 // Release the memory used by the source lines\r
600 for (i = 0; i < (size_t)cnt; ++i)\r
601 dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);\r
602 dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);\r
603 }\r
604\r
605 // Set the source code lines for QT html/text conformity\r
606 if (PtrCU[NbCU].NbLinesLoadSrc)\r
607 {\r
608 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *)))\r
609 {\r
610 for (j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)\r
611 {\r
612 if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char)))\r
613 {\r
614 if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))\r
615 {\r
616 i = 0;\r
617\r
618 while (*Ptr)\r
619 {\r
620 switch (*Ptr)\r
621 {\r
622 case 9:\r
623 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&nbsp;");\r
624 i += strlen("&nbsp;");\r
625 break;\r
626\r
627 case '<':\r
628 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&lt;");\r
629 i += strlen("&lt;");\r
630 break;\r
631\r
632 case '>':\r
633 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&gt;");\r
634 i += strlen("&gt;");\r
635 break;\r
636#if 0\r
637 case '&':\r
638 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&amp;");\r
639 i += strlen("&amp;");\r
640 break;\r
641#endif\r
642#if 0\r
643 case '"':\r
644 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&quot;");\r
645 i += strlen("&quot;");\r
646 break;\r
647#endif\r
648 default:\r
649 PtrCU[NbCU].PtrLinesLoadSrc[j][i++] = *Ptr;\r
650 break;\r
651 }\r
652 Ptr++;\r
653 }\r
654 }\r
655 PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], i + 1);\r
656 }\r
657 }\r
658 }\r
659 }\r
660 else\r
661 {\r
662 // Set each source lines pointer to NULL\r
663 if (PtrCU[NbCU].NbSubProgs)\r
664 {\r
665 i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;\r
666 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))\r
667 {\r
668 for (j = 0; j < i; j++)\r
669 {\r
670 PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;\r
671 }\r
672 }\r
673 }\r
674 }\r
675\r
676 // Init lines source information based on each source code line numbers\r
677 for (j = 0; j < PtrCU[NbCU].NbSubProgs; j++)\r
678 {\r
679 PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];\r
680\r
681 for (k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)\r
682 {\r
683 PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1];\r
684 }\r
685 }\r
686\r
687 // Init variables information based on types information\r
688 for (i = 0; i < PtrCU[NbCU].NbVariables; i++)\r
689 {\r
690 PtrCU[NbCU].PtrVariables[i].PtrTypeName = (char *)calloc(1000, 1);\r
691 TypeOffset = PtrCU[NbCU].PtrVariables[i].TypeOffset;\r
692\r
693 for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
694 {\r
695 if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
696 {\r
697 switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
698 {\r
699 case DW_TAG_structure_type:\r
700 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x1;\r
701 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
702 {\r
703 j = -1;\r
704 }\r
705 else\r
706 {\r
707 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))\r
708 {\r
709 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");\r
710 }\r
711 }\r
712 break;\r
713\r
714 case DW_TAG_pointer_type:\r
715 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x2;\r
716 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
717 PtrCU[NbCU].PtrVariables[i].TypeEncoding = 0x10;\r
718 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
719 {\r
720 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "void *");\r
721 }\r
722 else\r
723 {\r
724 j = -1;\r
725 }\r
726 break;\r
727\r
728 case DW_TAG_typedef:\r
729 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x20;\r
730 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
731 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
732 {\r
733 j = -1;\r
734 }\r
735 break;\r
736\r
737 case DW_TAG_subrange_type:\r
738 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x4;\r
739 break;\r
740\r
741 case DW_TAG_array_type:\r
742 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x8;\r
743 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
744 {\r
745 j = -1;\r
746 }\r
747 break;\r
748\r
749 case DW_TAG_const_type:\r
750 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x10;\r
751 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "const ");\r
752 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
753 {\r
754 j = -1;\r
755 }\r
756 break;\r
757\r
758 case DW_TAG_base_type:\r
759 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
760 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))\r
761 {\r
762 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");\r
763 }\r
764 else\r
765 {\r
766 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
767 PtrCU[NbCU].PtrVariables[i].TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
768 }\r
769 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x8))\r
770 {\r
771 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "[]");\r
772 }\r
773 break;\r
774\r
775 default:\r
776 break;\r
777 }\r
778 }\r
779 }\r
780 }\r
781\r
782 ++NbCU;\r
783 }\r
784 } \r
785\r
786 free(SourceFilename);\r
787 free(SourceFileDirectory);\r
788 free(SourceFullFilename);\r
789}\r
790\r
791\r
792// Get symbol name based from address\r
793// Return NULL if no symbol name exists\r
794char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)\r
795{\r
796 size_t i, j;\r
797\r
798 for (i = 0; i < NbCU; i++)\r
799 {\r
800 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
801 {\r
802 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)\r
803 {\r
804 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))\r
805 {\r
806 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;\r
807 }\r
808 }\r
809 }\r
810 }\r
811\r
812 return NULL;\r
813}\r
814\r
815\r
816// Get complete source filename based from address\r
817// Return NULL if no source filename exists\r
818// Return the existence status (true or false) in Error\r
819char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)\r
820{\r
821 size_t i;\r
822\r
823 for (i = 0; i < NbCU; i++)\r
824 {\r
825 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
826 {\r
827 *Error = PtrCU[i].PtrLoadSrc ? true : false;\r
828 return PtrCU[i].PtrFullFilename;\r
829 }\r
830 }\r
831\r
832 return NULL;\r
833}\r
834\r
835\r
836// Get text line source based on line number (starting by 1)\r
837// Return NULL if no text line exists or if line number is 0\r
838char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)\r
839{\r
840 size_t i = 0;\r
841 char *PtrLineSrc = NULL;\r
842\r
843 if (PtrSrcFile)\r
844 {\r
845 while (i != NumLine)\r
846 {\r
847 PtrLineSrc = PtrSrcFile;\r
848 while (*PtrSrcFile++);\r
849 i++;\r
850 }\r
851 }\r
852\r
853 return PtrLineSrc;\r
854}\r
855\r
856\r
857// Get Compilation Unit / External variables numbers\r
858// Return variables number\r
859size_t DWARFManager_GetNbExternalVariables(void)\r
860{\r
861 size_t NbVariables = 0, i;\r
862\r
863 for (i = 0; i < NbCU; i++)\r
864 {\r
865 NbVariables += PtrCU[i].NbVariables;\r
866 }\r
867\r
868 return NbVariables;\r
869}\r
870\r
871\r
872// Get external variable type name based on his index (starting by 1)\r
873// Return NULL if not found\r
874// May return NULL if there is not type linked to the variable's index\r
875char *DWARFManager_GetExternalVariableTypeName(size_t Index)\r
876{\r
877 size_t i;\r
878\r
879 for (i = 0; i < NbCU; i++)\r
880 {\r
881 if (PtrCU[i].NbVariables)\r
882 {\r
883 if (Index <= PtrCU[i].NbVariables)\r
884 {\r
885 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;\r
886 }\r
887 else\r
888 {\r
889 Index -= PtrCU[i].NbVariables;\r
890 }\r
891 }\r
892 }\r
893\r
894 return NULL;\r
895}\r
896\r
897\r
898// Get external variable's type tag based on his index (starting by 1)\r
899// Return 0 if not found\r
900size_t DWARFManager_GetExternalVariableTypeTag(size_t Index)\r
901{\r
902 size_t i;\r
903\r
904 for (i = 0; i < NbCU; i++)\r
905 {\r
906 if (PtrCU[i].NbVariables)\r
907 {\r
908 if (Index <= PtrCU[i].NbVariables)\r
909 {\r
910 return PtrCU[i].PtrVariables[Index - 1].TypeTag;\r
911 }\r
912 else\r
913 {\r
914 Index -= PtrCU[i].NbVariables;\r
915 }\r
916 }\r
917 }\r
918\r
919 return 0;\r
920}\r
921\r
922\r
923// Get external variable byte size based on his index (starting by 1)\r
924// Return 0 if not found\r
925size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index)\r
926{\r
927 size_t i;\r
928\r
929 for (i = 0; i < NbCU; i++)\r
930 {\r
931 if (PtrCU[i].NbVariables)\r
932 {\r
933 if (Index <= PtrCU[i].NbVariables)\r
934 {\r
935 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;\r
936 }\r
937 else\r
938 {\r
939 Index -= PtrCU[i].NbVariables;\r
940 }\r
941 }\r
942 }\r
943\r
944 return 0;\r
945}\r
946\r
947\r
948// Get external variable encoding based on his index (starting by 1)\r
949// Return 0 if not found\r
950size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index)\r
951{\r
952 size_t i;\r
953\r
954 for (i = 0; i < NbCU; i++)\r
955 {\r
956 if (PtrCU[i].NbVariables)\r
957 {\r
958 if (Index <= PtrCU[i].NbVariables)\r
959 {\r
960 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;\r
961 }\r
962 else\r
963 {\r
964 Index -= PtrCU[i].NbVariables;\r
965 }\r
966 }\r
967 }\r
968\r
969 return 0;\r
970}\r
971\r
972\r
973// Get external variable address based on his index (starting by 1)\r
974// Return 0 if not found\r
975size_t DWARFManager_GetExternalVariableAdr(size_t Index)\r
976{\r
977 size_t i;\r
978\r
979 for (i = 0; i < NbCU; i++)\r
980 {\r
981 if (PtrCU[i].NbVariables)\r
982 {\r
983 if (Index <= PtrCU[i].NbVariables)\r
984 {\r
985 return PtrCU[i].PtrVariables[Index - 1].Addr;\r
986 }\r
987 else\r
988 {\r
989 Index -= PtrCU[i].NbVariables;\r
990 }\r
991 }\r
992 }\r
993\r
994 return 0;\r
995}\r
996\r
997\r
998// Get external variable memory address based on his name\r
999// Return 0 if not found\r
1000// Note: Return the first occurence found\r
1001size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName)\r
1002{\r
1003 size_t i, j;\r
1004\r
1005 for (i = 0; i < NbCU; i++)\r
1006 {\r
1007 if (PtrCU[i].NbVariables)\r
1008 {\r
1009 for (j = 0; j < PtrCU[i].NbVariables; j++)\r
1010 {\r
1011 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))\r
1012 {\r
1013 return PtrCU[i].PtrVariables[j].Addr;\r
1014 }\r
1015 }\r
1016 }\r
1017 }\r
1018\r
1019 return 0;\r
1020}\r
1021\r
1022\r
1023// Get external variable name based on his index (starting by 1)\r
1024// Return name's pointer text found\r
1025// Return NULL if not found\r
1026char *DWARFManager_GetExternalVariableName(size_t Index)\r
1027{\r
1028 size_t i;\r
1029\r
1030 for (i = 0; i < NbCU; i++)\r
1031 {\r
1032 if (PtrCU[i].NbVariables)\r
1033 {\r
1034 if (Index <= PtrCU[i].NbVariables)\r
1035 {\r
1036 return PtrCU[i].PtrVariables[Index - 1].PtrName;\r
1037 }\r
1038 else\r
1039 {\r
1040 Index -= PtrCU[i].NbVariables;\r
1041 }\r
1042 }\r
1043 }\r
1044\r
1045 return NULL;\r
1046}\r
1047\r
1048\r
1049// Get text line from source based on address and his tag\r
1050// Return NULL if no text line has been found\r
1051char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)\r
1052{\r
1053 size_t i, j, k;\r
1054\r
1055 for (i = 0; i < NbCU; i++)\r
1056 {\r
1057 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1058 {\r
1059 for (j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1060 {\r
1061 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1062 {\r
1063 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))\r
1064 {\r
1065 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;\r
1066 }\r
1067 else\r
1068 {\r
1069 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
1070 {\r
1071 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
1072 {\r
1073 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
1074 }\r
1075 }\r
1076 }\r
1077 }\r
1078 }\r
1079 }\r
1080 }\r
1081\r
1082 return NULL;\r
1083}\r
1084\r
1085\r
1086// Get line number based on the address and the tag\r
1087// Return 0 if no line number has been found\r
1088size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)\r
1089{\r
1090 size_t i, j, k;\r
1091\r
1092 for (i = 0; i < NbCU; i++)\r
1093 {\r
1094 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1095 {\r
1096 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)\r
1097 {\r
1098 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1099 {\r
1100 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))\r
1101 {\r
1102 return PtrCU[i].PtrSubProgs[j].NumLineSrc;\r
1103 }\r
1104 else\r
1105 {\r
1106 for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++)\r
1107 {\r
1108 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
1109 {\r
1110 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;\r
1111 }\r
1112 }\r
1113 }\r
1114#if 0\r
1115 if (!Tag || (Tag == DW_TAG_subprogram))\r
1116 {\r
1117 return PtrCU[i].PtrSubProgs[j].NumLineSrc;\r
1118 }\r
1119#endif\r
1120 }\r
1121 }\r
1122 }\r
1123 }\r
1124\r
1125 return 0;\r
1126}\r
1127\r
1128\r
1129// Get text line from source based on address and num line (starting by 1)\r
1130// Return NULL if no text line has been found\r
1131char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)\r
1132{\r
1133 size_t i, j, k;\r
1134\r
1135 for (i = 0; i < NbCU; i++)\r
1136 {\r
1137 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1138 {\r
1139 for (j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1140 {\r
1141 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1142 {\r
1143 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)\r
1144 {\r
1145 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;\r
1146 }\r
1147 else\r
1148 {\r
1149 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
1150 {\r
1151 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)\r
1152 {\r
1153 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
1154 }\r
1155 }\r
1156 }\r
1157 }\r
1158 }\r
1159 }\r
1160 }\r
1161\r
1162 return NULL;\r
1163}\r
1164\r
1165\r
1166// Get text line from source based on address and num line (starting by 1)\r
1167// Return NULL if no text line has been found\r
1168char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)\r
1169{\r
1170 size_t i;\r
1171\r
1172 for (i = 0; i < NbCU; i++)\r
1173 {\r
1174 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1175 {\r
1176 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];\r
1177 }\r
1178 }\r
1179\r
1180 return NULL;\r
1181}\r
1182\r