// --- ---------- ------------------------------------------------------------\r
// JPM 12/03/2016 Created this file\r
// JPM 12/03/2016 DWARF format support\r
+// JPM 09/12/2018 Added LEB128 decoding features\r
+// JPM 09/14/2018 Improve the DWARF parsing information\r
+//\r
+\r
+// To Do\r
+// To use pointers instead of arrays usage\r
+// \r
\r
\r
#include <stdlib.h>\r
#include <string.h>\r
#include <libdwarf.h>\r
#include <dwarf.h>\r
+#include "LEB128.h"\r
\r
\r
//\r
-//#define DEBUG_NumCU 0x6 // CU number to debug or undefine it\r
-//#define DEBUG_VariableName "argc" // Variable name to look for or undefine it\r
+//#define DEBUG_NumCU 0x9 // CU number to debug or undefine it\r
+//#define DEBUG_VariableName "alloc" // Variable name to look for or undefine it\r
+//#define DEBUG_TypeName "Cbuf_Execute" // Type name to look for or undefine it\r
+//#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not supported)\r
+//#define DEBUG_Filename "cmd.c" // Filename to look for or undefine it\r
\r
\r
// Source line internal structure\r
-struct DMIStruct_LineSrc\r
+typedef struct DMIStruct_LineSrc\r
{\r
size_t Tag;\r
size_t StartPC;\r
char *PtrLineSrc;\r
}S_DMIStruct_LineSrc;\r
\r
+// Enumeration structure\r
+typedef struct EnumerationStruct\r
+{\r
+ char *PtrName; // Enumeration's name\r
+ size_t value; // Enumeration's value\r
+}S_EnumerationStruct;\r
+\r
+// Structure members structure\r
+//typedef struct StructureMembersStruct\r
+//{\r
+//}S_StructureMembersStruct;\r
+\r
// Base type internal structure\r
-struct BaseTypeStruct\r
+typedef struct BaseTypeStruct\r
{\r
- size_t Tag; // Type's Tag\r
- size_t Offset; // Type's offset\r
- size_t TypeOffset; // Type's offset on another type\r
- size_t ByteSize; // Type's Byte Size\r
- size_t Encoding; // Type's encoding\r
- char *PtrName; // Type's name\r
+ size_t Tag; // Type's Tag\r
+ size_t Offset; // Type's offset\r
+ size_t TypeOffset; // Type's offset on another type\r
+ size_t ByteSize; // Type's Byte Size\r
+ size_t Encoding; // Type's encoding\r
+ char *PtrName; // Type's name\r
+ size_t NbEnumeration; // Type's enumeration numbers\r
+ EnumerationStruct *PtrEnumeration; // Type's enumeration\r
+// StructureMembersStruct *PtrStructureMembers; // Type's structure members\r
}S_BaseTypeStruct;\r
\r
// Definitions for the variables's typetag\r
-#define TypeTag_structure 0x01 // structure\r
-#define TypeTag_pointer 0x02 // pointer\r
-#define TypeTag_0x04 0x04\r
-#define TypeTag_arraytype 0x08 // array type\r
-#define TypeTag_consttype 0x10 // const type\r
-#define TypeTag_typedef 0x20 // typedef\r
+#define TypeTag_structure 0x01 // structure\r
+#define TypeTag_pointer 0x02 // pointer\r
+#define TypeTag_subrange 0x04 // (subrange_type?)\r
+#define TypeTag_arraytype 0x08 // array type\r
+#define TypeTag_consttype 0x10 // const type\r
+#define TypeTag_typedef 0x20 // typedef\r
+#define TypeTag_enumeration_type 0x40 // enumeration\r
+#define TypeTag_subroutine_type 0x80 // subroutine\r
\r
// Variables internal structure\r
-struct VariablesStruct\r
+typedef struct VariablesStruct\r
{\r
size_t Op; // Variable's DW_OP\r
union\r
}S_VariablesStruct;\r
\r
// Sub program internal structure\r
-struct SubProgStruct\r
+typedef struct SubProgStruct\r
{\r
size_t Tag;\r
size_t NumLineSrc;\r
}S_SubProgStruct;\r
\r
// Compilation Unit internal structure\r
-struct CUStruct\r
+typedef struct CUStruct\r
{\r
size_t Tag;\r
size_t LowPC, HighPC;\r
- char *PtrProducer; // Pointer to the "Producer" information (compiler and compilation options used)\r
+ char *PtrProducer; // Pointer to the "Producer" text information (mostly compiler and compilation options used)\r
+ char *PtrSourceFilename; // Source file name\r
+ char *PtrSourceFileDirectory; // Directory of the source file\r
char *PtrFullFilename; // Pointer to full namefile (directory & filename)\r
size_t SizeLoadSrc; // Source code size\r
char *PtrLoadSrc; // Pointer to loaded source code\r
char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity\r
size_t NbSubProgs; // Number of sub programs / routines\r
SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines information structure\r
- size_t NbTypes;\r
- BaseTypeStruct *PtrTypes;\r
+ size_t NbTypes; // Number of types\r
+ BaseTypeStruct *PtrTypes; // Pointer to types\r
size_t NbVariables; // Variables number\r
VariablesStruct *PtrVariables; // Pointer to the global variables list information structure\r
size_t NbFrames; // Frames number\r
free(PtrCU[NbCU].PtrFullFilename);\r
free(PtrCU[NbCU].PtrLoadSrc);\r
free(PtrCU[NbCU].PtrProducer);\r
+ free(PtrCU[NbCU].PtrSourceFilename);\r
+ free(PtrCU[NbCU].PtrSourceFileDirectory);\r
\r
while (PtrCU[NbCU].NbLinesLoadSrc--)\r
{\r
size_t i, j, k;\r
char *return_string;\r
char *Ptr;\r
- char *SourceFilename = NULL;\r
- char *SourceFileDirectory = NULL;\r
- char *SourceFullFilename = NULL;\r
\r
// Initialisation for the Compilation Units table\r
NbCU = 0;\r
case DW_AT_name:\r
if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
{\r
- SourceFilename = (char *)realloc(SourceFilename, strlen(return_string) + 1);\r
- strcpy(SourceFilename, return_string);\r
+#ifdef DEBUG_Filename\r
+ if (strstr(return_string, DEBUG_Filename))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrSourceFilename = (char *)calloc((strlen(return_string) + 1), 1);\r
+ strcpy(PtrCU[NbCU].PtrSourceFilename, return_string);\r
+ }\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
case DW_AT_comp_dir:\r
if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
{\r
- SourceFileDirectory = (char *)realloc(SourceFileDirectory, strlen(return_string) + 1);\r
- strcpy(SourceFileDirectory, return_string);\r
+ PtrCU[NbCU].PtrSourceFileDirectory = (char *)calloc((strlen(return_string) + 1), 1);\r
+ strcpy(PtrCU[NbCU].PtrSourceFileDirectory, return_string);\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
}\r
\r
- Ptr = SourceFullFilename = (char *)realloc(SourceFullFilename, strlen(SourceFilename) + strlen(SourceFileDirectory) + 2);\r
-#if defined(_WIN32)\r
- sprintf(SourceFullFilename, "%s\\%s", SourceFileDirectory, SourceFilename);\r
-#else\r
- sprintf(SourceFullFilename, "%s/%s", SourceFileDirectory, SourceFilename);\r
-#endif\r
+ // Check filename validity\r
+ if (!PtrCU[NbCU].PtrSourceFilename)\r
+ {\r
+ PtrCU[NbCU].PtrSourceFilename = (char *)calloc(1, 1);\r
+ }\r
+\r
+ // Check directory validity\r
+ if (!PtrCU[NbCU].PtrSourceFileDirectory)\r
+ {\r
+ PtrCU[NbCU].PtrSourceFileDirectory = (char *)calloc(2, 1);\r
+ PtrCU[NbCU].PtrSourceFileDirectory[0] = '.';\r
+ }\r
+\r
+ // Create full filename\r
+ Ptr = PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen(PtrCU[NbCU].PtrSourceFileDirectory) + 2);\r
+ sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename);\r
+\r
+ // Conform slashes and backslashes\r
while (*Ptr)\r
{\r
#if defined(_WIN32)\r
#endif\r
Ptr++;\r
}\r
- PtrCU[NbCU].PtrFullFilename = (char *)calloc(strlen(SourceFullFilename) + 1, 1);\r
- strcpy((char *)PtrCU[NbCU].PtrFullFilename, SourceFullFilename);\r
\r
+ // Read the file as text\r
#ifndef __CYGWIN__\r
- if (!fopen_s(&SrcFile, SourceFullFilename, "rt"))\r
+ if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rt"))\r
#else\r
if (!(SrcFile = fopen(SourceFullFilename, "rt")))\r
#endif\r
{\r
PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);\r
- dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
+ dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
case DW_TAG_array_type:\r
case DW_TAG_subrange_type:\r
case DW_TAG_subroutine_type:\r
+ case DW_TAG_enumeration_type:\r
if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
{\r
+ // Allocate memory for this type\r
PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));\r
memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));\r
PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;\r
{\r
switch (return_attr)\r
{\r
+ // \r
+ case DW_AT_sibling:\r
+ break;\r
+\r
+ // Type's type offset\r
case DW_AT_type:\r
if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
{\r
}\r
break;\r
\r
+ // Type's byte size\r
case DW_AT_byte_size:\r
if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
{\r
}\r
break;\r
\r
+ // Type's encoding\r
case DW_AT_encoding:\r
if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
{\r
}\r
break;\r
\r
+ // Type's name\r
case DW_AT_name:\r
if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
{\r
- PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
- strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
+#ifdef DEBUG_TypeName\r
+ if (!strcmp(return_string, DEBUG_TypeName))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
+ strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
+ }\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
- default:\r
+ // Type's file number\r
+ case DW_AT_decl_file:\r
+ break;\r
+\r
+ // Type's line number\r
+ case DW_AT_decl_line:\r
+ break;\r
+\r
+ default:\r
break;\r
}\r
}\r
}\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
\r
+ // Get source line number and associated block of address\r
for (i = 0; i < (size_t)cnt; ++i)\r
{\r
if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)\r
break;\r
\r
case 2:\r
- PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = *((char *)(return_block->bl_data) + 1);\r
-\r
+ case 3:\r
switch (return_tagval)\r
{\r
case DW_TAG_variable:\r
- PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset -= 0x80;\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadLEB128((char *)return_block->bl_data + 1);\r
break;\r
\r
case DW_TAG_formal_parameter:\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadULEB128((char *)return_block->bl_data + 1);\r
break;\r
\r
default:\r
break;\r
}\r
+ break;\r
\r
default:\r
break;\r
{\r
PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName, return_string);\r
- dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
+ dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
++NbCU;\r
}\r
} \r
-\r
- free(SourceFilename);\r
- free(SourceFileDirectory);\r
- free(SourceFullFilename);\r
}\r
\r
\r
{\r
size_t j, TypeOffset;\r
\r
- PtrVariables->PtrTypeName = (char *)calloc(1000, 1);\r
- TypeOffset = PtrVariables->TypeOffset;\r
-\r
- for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
+#ifdef DEBUG_VariableName\r
+ if (PtrVariables->PtrName && !strcmp(PtrVariables->PtrName, DEBUG_VariableName))\r
+#endif\r
{\r
- if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
+ PtrVariables->PtrTypeName = (char *)calloc(1000, 1);\r
+ TypeOffset = PtrVariables->TypeOffset;\r
+\r
+ for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
{\r
- switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
+ if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
{\r
- // Structure type tag\r
- case DW_TAG_structure_type:\r
- PtrVariables->TypeTag |= TypeTag_structure;\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
{\r
- j = -1;\r
- }\r
- else\r
- {\r
- if ((PtrVariables->TypeTag & TypeTag_pointer))\r
+ case DW_TAG_subroutine_type:\r
+ PtrVariables->TypeTag |= TypeTag_subroutine_type;\r
+ strcat(PtrVariables->PtrTypeName, " (* ) ()");\r
+ break;\r
+\r
+ // Structure type tag\r
+ case DW_TAG_structure_type:\r
+ PtrVariables->TypeTag |= TypeTag_structure;\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
{\r
- strcat(PtrVariables->PtrTypeName, " *");\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
}\r
- }\r
- break;\r
-\r
- // Pointer type tag\r
- case DW_TAG_pointer_type:\r
- PtrVariables->TypeTag |= TypeTag_pointer;\r
- PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
- PtrVariables->TypeEncoding = 0x10;\r
- if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- strcat(PtrVariables->PtrTypeName, "void *");\r
- }\r
- else\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ else\r
+ {\r
+ if ((PtrVariables->TypeTag & TypeTag_pointer))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, " *");\r
+ }\r
+ }\r
+ break;\r
\r
- // Typedef type tag\r
- case DW_TAG_typedef:\r
- if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
- {\r
- PtrVariables->TypeTag |= TypeTag_typedef;\r
- strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
- }\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ // Pointer type tag\r
+ case DW_TAG_pointer_type:\r
+ PtrVariables->TypeTag |= TypeTag_pointer;\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ PtrVariables->TypeEncoding = 0x10;\r
+ if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, "void *");\r
+ }\r
+ else\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
\r
- // ? type tag\r
- case DW_TAG_subrange_type:\r
- PtrVariables->TypeTag |= TypeTag_0x04;\r
- break;\r
+ case DW_TAG_enumeration_type:\r
+ PtrVariables->TypeTag |= TypeTag_enumeration_type;\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding))\r
+ {\r
+ // Try to determine the possible size\r
+ switch (PtrVariables->TypeByteSize)\r
+ {\r
+ case 4:\r
+ PtrVariables->TypeEncoding = 0x7;\r
+ break;\r
\r
- // Array type tag\r
- case DW_TAG_array_type:\r
- PtrVariables->TypeTag |= TypeTag_arraytype;\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ break;\r
\r
- // Const type tag\r
- case DW_TAG_const_type:\r
- PtrVariables->TypeTag |= TypeTag_consttype;\r
- strcat(PtrVariables->PtrTypeName, "const ");\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ // Typedef type tag\r
+ case DW_TAG_typedef:\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
+ {\r
+ PtrVariables->TypeTag |= TypeTag_typedef;\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
+ }\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
\r
- // Base type tag\r
- case DW_TAG_base_type:\r
- if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
- {\r
- strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
- }\r
- if ((PtrVariables->TypeTag & TypeTag_pointer))\r
- {\r
- strcat(PtrVariables->PtrTypeName, " *");\r
- }\r
- else\r
- {\r
- PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
- PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
- }\r
- if ((PtrVariables->TypeTag & TypeTag_arraytype))\r
- {\r
- strcat(PtrVariables->PtrTypeName, "[]");\r
- }\r
- break;\r
+ // ? type tag\r
+ case DW_TAG_subrange_type:\r
+ PtrVariables->TypeTag |= TypeTag_subrange;\r
+ break;\r
\r
- default:\r
- break;\r
+ // Array type tag\r
+ case DW_TAG_array_type:\r
+ PtrVariables->TypeTag |= TypeTag_arraytype;\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ // Const type tag\r
+ case DW_TAG_const_type:\r
+ PtrVariables->TypeTag |= TypeTag_consttype;\r
+ strcat(PtrVariables->PtrTypeName, "const ");\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ // Base type tag\r
+ case DW_TAG_base_type:\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
+ }\r
+ if ((PtrVariables->TypeTag & TypeTag_pointer))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, " *");\r
+ }\r
+ else\r
+ {\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
+ }\r
+ if ((PtrVariables->TypeTag & TypeTag_arraytype))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, "[]");\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
}\r
}\r
}\r
{\r
for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
{\r
- if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)\r
{\r
- return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
+ if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;\r
}\r
}\r
}\r