xref: /reactos/sdk/lib/rossym/fromfile.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS kernel
4  * FILE:            lib/rossym/fromfile.c
5  * PURPOSE:         Creating rossym info from a file
6  *
7  * PROGRAMMERS:     Ge van Geldorp (gvg@reactos.com)
8  */
9 
10 #define NTOSAPI
11 #include <ntdef.h>
12 #include <reactos/rossym.h>
13 #include "rossympriv.h"
14 #include <ntimage.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 BOOLEAN
20 RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
21 {
22   IMAGE_DOS_HEADER DosHeader;
23   IMAGE_NT_HEADERS NtHeaders;
24   PIMAGE_SECTION_HEADER SectionHeaders, SectionHeader;
25   unsigned SectionIndex;
26   char SectionName[IMAGE_SIZEOF_SHORT_NAME];
27   ROSSYM_HEADER RosSymHeader;
28 
29   /* Load DOS header */
30   if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
31     {
32       DPRINT1("Failed to read DOS header\n");
33       return FALSE;
34     }
35   if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader))
36     {
37       DPRINT1("Image doesn't have a valid DOS header\n");
38       return FALSE;
39     }
40 
41   /* Load NT headers */
42   if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew))
43     {
44       DPRINT1("Failed seeking to NT headers\n");
45       return FALSE;
46     }
47   if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS)))
48     {
49       DPRINT1("Failed to read NT headers\n");
50       return FALSE;
51     }
52   if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders))
53     {
54       DPRINT1("Image doesn't have a valid PE header\n");
55       return FALSE;
56     }
57 
58   /* Load section headers */
59   if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
60                                     (char *) &NtHeaders + DosHeader.e_lfanew))
61     {
62       DPRINT1("Failed seeking to section headers\n");
63       return FALSE;
64     }
65   SectionHeaders = RosSymAllocMem(NtHeaders.FileHeader.NumberOfSections
66                                   * sizeof(IMAGE_SECTION_HEADER));
67   if (NULL == SectionHeaders)
68     {
69       DPRINT1("Failed to allocate memory for %u section headers\n",
70               NtHeaders.FileHeader.NumberOfSections);
71       return FALSE;
72     }
73   if (! RosSymReadFile(FileContext, SectionHeaders,
74                        NtHeaders.FileHeader.NumberOfSections
75                        * sizeof(IMAGE_SECTION_HEADER)))
76     {
77       RosSymFreeMem(SectionHeaders);
78       DPRINT1("Failed to read section headers\n");
79       return FALSE;
80     }
81 
82   /* Search for the section header */
83   strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME);
84   SectionHeader = SectionHeaders;
85   for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections; SectionIndex++)
86     {
87       if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME))
88         {
89           break;
90         }
91       SectionHeader++;
92     }
93   if (NtHeaders.FileHeader.NumberOfSections <= SectionIndex)
94     {
95       RosSymFreeMem(SectionHeaders);
96       DPRINT("No %s section found\n", ROSSYM_SECTION_NAME);
97       return FALSE;
98     }
99 
100   /* Load rossym header */
101   if (! RosSymSeekFile(FileContext, SectionHeader->PointerToRawData))
102     {
103       RosSymFreeMem(SectionHeaders);
104       DPRINT1("Failed seeking to section data\n");
105       return FALSE;
106     }
107   RosSymFreeMem(SectionHeaders);
108   if (! RosSymReadFile(FileContext, &RosSymHeader, sizeof(ROSSYM_HEADER)))
109     {
110       DPRINT1("Failed to read rossym header\n");
111       return FALSE;
112     }
113   if (RosSymHeader.SymbolsOffset < sizeof(ROSSYM_HEADER)
114       || RosSymHeader.StringsOffset < RosSymHeader.SymbolsOffset + RosSymHeader.SymbolsLength
115       || 0 != (RosSymHeader.SymbolsLength % sizeof(ROSSYM_ENTRY)))
116     {
117       DPRINT1("Invalid ROSSYM_HEADER\n");
118       return FALSE;
119     }
120 
121   *RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
122                                + RosSymHeader.StringsOffset + RosSymHeader.StringsLength + 1);
123   if (NULL == *RosSymInfo)
124     {
125       DPRINT1("Failed to allocate memory for rossym\n");
126       return FALSE;
127     }
128   (*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO)
129                                            - sizeof(ROSSYM_HEADER) + RosSymHeader.SymbolsOffset);
130   (*RosSymInfo)->SymbolsCount = RosSymHeader.SymbolsLength / sizeof(ROSSYM_ENTRY);
131   (*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
132                            + RosSymHeader.StringsOffset;
133   (*RosSymInfo)->StringsLength = RosSymHeader.StringsLength;
134   if (! RosSymReadFile(FileContext, *RosSymInfo + 1,
135                        RosSymHeader.StringsOffset + RosSymHeader.StringsLength
136                        - sizeof(ROSSYM_HEADER)))
137     {
138       DPRINT1("Failed to read rossym headers\n");
139       return FALSE;
140     }
141   /* Make sure the last string is null terminated, we allocated an extra byte for that */
142   (*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0';
143 
144   return TRUE;
145 }
146 
147 /* EOF */
148