xref: /reactos/sdk/tools/log2lines/image.c (revision 321bcc05)
1 /*
2  * ReactOS log2lines
3  * Written by Jan Roeloffzen
4  *
5  * - Image functions for symbol info
6  */
7 
8 #include <errno.h>
9 #include <string.h>
10 #include <rsym.h>
11 
12 #include "compat.h"
13 #include "util.h"
14 #include "options.h"
15 #include "log2lines.h"
16 
17 static PIMAGE_SECTION_HEADER
18 find_rossym_section(PIMAGE_FILE_HEADER PEFileHeader, PIMAGE_SECTION_HEADER PESectionHeaders)
19 {
20     size_t i;
21     for (i = 0; i < PEFileHeader->NumberOfSections; i++)
22     {
23         if (0 == strcmp((char *)PESectionHeaders[i].Name, ".rossym"))
24             return &PESectionHeaders[i];
25     }
26     return NULL;
27 }
28 
29 size_t
30 fixup_offset(size_t ImageBase, size_t offset)
31 {
32     if (offset > ABS_TRESHOLD)
33         offset -= ImageBase;
34     return offset;
35 }
36 
37 PROSSYM_ENTRY
38 find_offset(void *data, size_t offset)
39 {
40     PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data;
41     PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset);
42     size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY);
43     size_t i;
44 
45     for (i = 0; i < symbols; i++)
46     {
47         if (Entries[i].Address > offset)
48         {
49             if (!i--)
50                 return NULL;
51             else
52                 return &Entries[i];
53         }
54     }
55     return NULL;
56 }
57 
58 PIMAGE_SECTION_HEADER
59 get_sectionheader(const void *FileData)
60 {
61     PIMAGE_DOS_HEADER PEDosHeader;
62     PIMAGE_FILE_HEADER PEFileHeader;
63     PIMAGE_OPTIONAL_HEADER PEOptHeader;
64     PIMAGE_SECTION_HEADER PESectionHeaders;
65     PIMAGE_SECTION_HEADER PERosSymSectionHeader;
66     size_t ImageBase;
67 
68     /* Check if MZ header exists */
69     PEDosHeader = (PIMAGE_DOS_HEADER)FileData;
70     if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L)
71     {
72         l2l_dbg(0, "Input file is not a PE image.\n");
73         summ.offset_errors++;
74         return NULL;
75     }
76 
77     /* Locate PE file header */
78     /* sizeof(ULONG) = sizeof(MAGIC) */
79     PEFileHeader = (PIMAGE_FILE_HEADER)((char *)FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
80 
81     /* Locate optional header */
82     PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
83     ImageBase = PEOptHeader->ImageBase;
84 
85     /* Locate PE section headers */
86     PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
87 
88     /* find rossym section */
89     PERosSymSectionHeader = find_rossym_section(PEFileHeader, PESectionHeaders);
90     if (!PERosSymSectionHeader)
91     {
92         l2l_dbg(0, "Couldn't find rossym section in executable\n");
93         summ.offset_errors++;
94         return NULL;
95     }
96 
97     return PERosSymSectionHeader;
98 }
99 
100 int
101 get_ImageBase(char *fname, size_t *ImageBase)
102 {
103     IMAGE_DOS_HEADER PEDosHeader;
104     IMAGE_FILE_HEADER PEFileHeader;
105     IMAGE_OPTIONAL_HEADER PEOptHeader;
106 
107     FILE *fr;
108     off_t readLen;
109     int res;
110 
111     *ImageBase = INVALID_BASE;
112     fr = fopen(fname, "rb");
113     if (!fr)
114     {
115         l2l_dbg(3, "get_ImageBase, cannot open '%s' (%s)\n", fname, strerror(errno));
116         return 1;
117     }
118 
119     readLen = fread(&PEDosHeader, sizeof(IMAGE_DOS_HEADER), 1, fr);
120     if (1 != readLen)
121     {
122         l2l_dbg(1, "get_ImageBase %s, read error IMAGE_DOS_HEADER (%s)\n", fname, strerror(errno));
123         fclose(fr);
124         return 2;
125     }
126 
127     /* Check if MZ header exists */
128     if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC || PEDosHeader.e_lfanew == 0L)
129     {
130         l2l_dbg(2, "get_ImageBase %s, MZ header missing\n", fname);
131         fclose(fr);
132         return 3;
133     }
134 
135     /* Locate PE file header */
136     res = fseek(fr, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
137     readLen = fread(&PEFileHeader, sizeof(IMAGE_FILE_HEADER), 1, fr);
138     if (1 != readLen)
139     {
140         l2l_dbg(1, "get_ImageBase %s, read error IMAGE_FILE_HEADER (%s)\n", fname, strerror(errno));
141         fclose(fr);
142         return 4;
143     }
144 
145     /* Locate optional header */
146     readLen = fread(&PEOptHeader, sizeof(IMAGE_OPTIONAL_HEADER), 1, fr);
147     if (1 != readLen)
148     {
149         l2l_dbg(1, "get_ImageBase %s, read error IMAGE_OPTIONAL_HEADER (%s)\n", fname, strerror(errno));
150         fclose(fr);
151         return 5;
152     }
153 
154     /* Check if it's really an IMAGE_OPTIONAL_HEADER we are interested in */
155     if (PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
156         PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
157     {
158         l2l_dbg(2, "get_ImageBase %s, not an IMAGE_NT_OPTIONAL_HDR 32/64 bit\n", fname);
159         fclose(fr);
160         return 6;
161     }
162 
163     *ImageBase = PEOptHeader.ImageBase;
164     fclose(fr);
165     return 0;
166 }
167 
168 /* EOF */
169