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