source: trunk/src/win32k/kKrnlLib/tools/libconv.c

Last change on this file was 8066, checked in by bird, 24 years ago

Made it compile.

File size: 13.4 KB
Line 
1/* $Id: libconv.c,v 1.3 2002-03-10 04:56:46 bird Exp $
2 *
3 * Very simple OMF/LIB dumper.
4 *
5 * Copyright (c) 1999 knut st. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14/**
15 * Upcases a char.
16 */
17#define upcase(ch) ((ch) >= 'a' && (ch) <= 'z' ? (char)((ch) - ('a' - 'A')) : (ch))
18
19
20/**
21 * Access macro for reading index value.
22 * @return index value. 0 - 32768.
23 * @param pch Pointer to the first byte of the index.
24 */
25#define INDEX_VALUE(pch) ( *(char*)(pch) & 0x80 \
26 ? (*(char *)(pch) & 0x7f) * 0x100 + *((char*)(pch)+1) \
27 : *((char*)(pch)) )
28
29/**
30 * Access macro for determin the size of an index.
31 * @return index size in bytes. 1 or 2.
32 * @param pch Pointer to the first byte of the index.
33 */
34#define INDEX_SIZE(pch) ( *(char*)(pch) & 0x80 ? 2 : 1 )
35
36
37/**
38 * Get a byte at a given offset.
39 * @return byte at given offset.
40 * @param pch Pointer to address relativ to.
41 * @param off Byte offset from pch.
42 */
43#define OMF_BYTE(pch, off) ( *((char*)(pch) + (int)(off)) )
44
45
46/**
47 * Get a word (unsigned short) at a given offset.
48 * @return word (unsigned short) at given offset.
49 * @param pch Pointer to address relativ to.
50 * @param off Byte offset from pch.
51 */
52#define OMF_WORD(pch, off) ( *(unsigned short*)((char*)(pch) + (int)(off)) )
53
54
55/**
56 * Get a dword (unsigned long) at a given offset.
57 * @return dword (unsigned long) at given offset.
58 * @param pch Pointer to address relativ to.
59 * @param off Byte offset from pch.
60 */
61#define OMF_DWORD(pch, off) ( *(unsigned long*)((char*)(pch) + (int)(off)) )
62
63
64/*@Header***********************************************************************
65* Header Files *
66*******************************************************************************/
67#include <stdio.h>
68#include <string.h>
69#include <malloc.h>
70
71
72#include "omf.h"
73
74int fUpcase = 0;
75int fRemoveExtra = 0;
76
77/*@IntFunc**********************************************************************
78* Internal Functions *
79*******************************************************************************/
80int processFile(const char *pszFilename, const char *pszFilenameOut);
81void *processRecord(void *pvRecord, void *pvBase, FILE *phNew, unsigned short *ausTrans);
82
83
84
85int main(int argc, char **argv)
86{
87 int rc = 0;
88 int argi = 1;
89
90 if (argc >= 4)
91 {
92 argi = 2;
93 fRemoveExtra = 1;
94 }
95 if (argc != 3)
96 printf("syntax error - requires two filename, in.lib and out.lib\n");
97
98 rc = processFile(argv[argi], argv[argi+1]);
99
100 return rc;
101}
102
103
104
105
106int processFile(const char *pszFilename, const char *pszFilenameOut)
107{
108 FILE *phFile;
109 FILE *phNew;
110 char *psz;
111 int rc = 0;
112
113 psz = strrchr(pszFilename, '\\');
114 if (psz)
115 fUpcase = stricmp(psz, "\\dhcalls.lib") == 0;
116
117 phFile = fopen(pszFilename, "rb");
118 phNew = fopen(pszFilenameOut, "wb");
119 if (phFile != NULL && phNew != NULL)
120 {
121 int cbFile;
122
123 /* get size of file */
124 if (!fseek(phFile, 0, SEEK_END)
125 && (cbFile = ftell(phFile) ) != -1
126 && !fseek(phFile, 0, SEEK_SET)
127 )
128 {
129 void *pvFile;
130
131 /* allocater memory */
132 pvFile = malloc(cbFile);
133 if (pvFile != NULL)
134 {
135 /* read the whole file */
136 if (fread(pvFile, cbFile, 1, phFile) == 1)
137 {
138 unsigned short * ausTrans = calloc(sizeof(unsigned short), cbFile / 16 ); /* Assumes page size of 16 FIXME! */
139 void *pvNew = pvFile;
140
141
142 /* main loop */
143 while (pvNew < (void*)(cbFile + (int)pvFile))
144 pvNew = processRecord(pvNew, pvFile, phNew, ausTrans);
145 }
146 else
147 rc = 4;
148 }
149 else
150 rc = 3;
151 }
152 else
153 rc = 2;
154 fclose(phFile);
155 fclose(phNew);
156 }
157 else
158 rc = 1;
159
160 return rc;
161}
162
163
164
165void *processRecord(void *pvRecord, void *pvBase, FILE *phNew, unsigned short *ausTrans)
166{
167 static char *apszLNames[256];
168 static int cpszLNames = 0;
169 static int iCode16 = 0;
170 static int cbPage = 16; /* fixme todo TODO FIXME ASSUMES: pagesize = 16 */
171 void *pvRet = pvRecord;
172 int cbRecord;
173 int i;
174 int fChanged = 0;
175
176 switch (*(unsigned char*)pvRecord)
177 {
178 case LIBHDR:
179 if (*(unsigned short*)((int)pvRecord+1) < 6)
180 fprintf(stderr, "error: not supported LIBHDR\n");
181 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
182 break;
183
184 case THEADR:
185 /* Add entry to the translation table - used to translate block numbers in the dictionary */
186 ausTrans[((char*)pvRecord - (char*)pvBase) / cbPage] = (unsigned short)(ftell(phNew) / cbPage);
187 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
188 break;
189
190 case SEGDEF: /* 16-bit segdef */
191 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
192 *((char*)pvRecord + 9) = 0;
193 i = *(char*)((int)pvRecord + 6);
194 if (cbRecord == 10 && i <= cpszLNames && strcmp(apszLNames[i-1], "CODE") == 0)
195 {
196 *(char*)((int)pvRecord + 6) = iCode16+1;
197 }
198 i = *(char*)((int)pvRecord + 6);
199 if (cbRecord == 10 && (*((char *)pvRecord + 3) & 0xE0) == 0x20 && i <= cpszLNames && strcmp(apszLNames[i-1], "CODE16_IOSEG") == 0)
200 { /* change alignment of this segment... */
201 /* fprintf(stderr, "debug %s 0x%02x\n", apszLNames[*(char*)((int)pvRecord + 6) - 1], (*((char *)pvRecord + 3) & 0xFF)); */
202 *((char*)pvRecord + 3) = 0x40 | (*((char*)pvRecord + 3) & 0x1F);
203 }
204 break;
205
206 case MODEND:
207 case MODEND2:
208 {
209 unsigned long ul = (unsigned long)pvRecord - (unsigned long)pvBase;
210
211 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
212 /* it seems to be somthing funny here! - lets try aligning it to on a 16 bytes boundrary... */
213 /* PS. I know this I have a wrong approch to the lib files, not using the directory... */
214 /* Aug 13 2000 4:24am: The alignment of modules are found in the library header.
215 * It's the size of the library header.
216 * Not implemented yet. TODO FIXME BUGBUG ASSUMES
217 */
218 fChanged = 1;
219 fwrite(pvRecord, 1, cbRecord, phNew);
220 ul += cbRecord;
221 if (*((unsigned char*)((int)pvRecord+cbRecord)) == 0x00)
222 {
223 if ((ul % cbPage) > 0)
224 cbRecord += cbPage - (ul % cbPage);
225 }
226 /*if (*((unsigned char*)pvRecord + cbRecord) != LIBEND)*/
227 {
228 ul = ftell(phNew);
229 while (ul++ % cbPage != 0)
230 fputc(0, phNew);
231 }
232 while (cpszLNames-- > 0)
233 free(apszLNames[cpszLNames]);
234 } break;
235
236 case PUBDEF:
237 {
238 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
239 *((char*)pvRecord + cbRecord - 1) = 0;
240 if (fUpcase)
241 {
242 char *pch = (char*)pvRecord;
243 char *pch1, *pch2, *pchEnd;
244 pch1 = pch + 3 + INDEX_SIZE(pch + 3);
245 pch2 = pch1 + INDEX_SIZE(pch1);
246 if (!*pch1)
247 pch2 += 2;
248
249 for (pchEnd = pch + pch[1]; pch2 + 1 < pchEnd; )
250 {
251 int i;
252 for (i = 1; i <= *pch2; i++)
253 pch2[i] = upcase(pch2[i]);
254 pch2 += *pch2 + 1 + (pch[0] & 0x1 ? 4 : 2);
255 pch2 += INDEX_SIZE(pch2);
256 }
257 }
258 break;
259 }
260
261 case LNAMES:
262 {
263 char *apszConv[] =
264 {
265 /* classes */
266 "CODE", "CODE",
267 "IOSEG_CODE", "CODE",
268 "DATA", "FAR_DATA",
269 "BSS", "DATA16BSS",
270 "CONST", "DATA16CONST",
271 /* segment names */
272 "_TEXT", "CODE16",
273 "_IOSEG", "CODE16_IOSEG",
274 "_CODE", "CODE16", /* dhcalls */
275 "_DATA", "DATA16",
276 "_BSS", "DATA16BSS",
277 "_CONST", "DATA16CONST",
278 /* groups */
279 "DGROUP", "DATA16_GROUP",
280 NULL, NULL
281 };
282
283 int cb;
284 int cbNew; /* record size */
285 char *psz;
286 iCode16 = -1;
287
288 cpszLNames = 0;
289 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
290 cb = 3;
291 cbNew = 1;
292 psz = (char*)pvRecord + 3;
293 while (cb < cbRecord-1)
294 {
295 int j = 0;
296 char szName[256];
297
298 strncpy(szName, psz+1, *psz);
299 szName[*psz] = '\0';
300
301 while (apszConv[j] != NULL && stricmp(szName, apszConv[j]) != 0)
302 j += 2;
303
304 if (apszConv[j] == NULL)
305 {
306 cbNew += *psz + 1;
307 if (*psz != 0)
308 printf("LNAMES: %.*s was not converted\n", *psz, psz+1);
309 apszLNames[cpszLNames++] = strdup(&szName[0]);
310 }
311 else
312 {
313 cbNew += strlen(apszConv[j+1]) + 1;
314 if (strcmp(apszConv[j+1], "CODE16") == 0)
315 iCode16 = cpszLNames;
316 apszLNames[cpszLNames++] = strdup(apszConv[j+1]);
317 }
318 cb += *psz + 1;
319 psz += 1 + *psz;
320 }
321
322 if (iCode16 == -1)
323 {
324 iCode16 = cpszLNames;
325 apszLNames[cpszLNames++] = strdup("CODE16");
326 cbNew += 1 + 6;
327 }
328
329 fChanged = 1;
330 fputc(LNAMES, phNew);
331 fwrite(&cbNew, 1, 2, phNew);
332
333 for (i = 0; i < cpszLNames; i++)
334 {
335 fputc(strlen(apszLNames[i]), phNew);
336 fwrite(apszLNames[i], 1, strlen(apszLNames[i]), phNew);
337 }
338
339 fputc(0, phNew);
340 break;
341 }
342
343 case LIBEND:
344 {
345 /* align dictionary at 512 byte (3 is min size of this record) */
346 int cBlocks;
347 unsigned short int cbSize = (((ftell(phNew) + 3 + 0x1ff) & ~0x1ff) - ftell(phNew)) - 3;
348 unsigned long int offDict = ftell(phNew) + cbSize + 3;
349 cbRecord = cbSize + 3;
350 fwrite(pvRecord, 1, 1, phNew);
351 fwrite(&cbSize, 1, sizeof(cbSize), phNew);
352 while (cbSize-- > 0)
353 fwrite("\0", 1, 1, phNew);
354
355 /* update header record. */
356 fseek(phNew, 3, SEEK_SET);
357 fwrite(&offDict, 1, sizeof(offDict), phNew);
358 fseek(phNew, offDict, SEEK_SET);
359
360 /* Translate the dictionary */
361 pvRecord = (void*)((char*)pvRecord + *(unsigned short*)((char*)pvRecord + 1) + 3);
362 cBlocks = *(unsigned short *)((char*)pvBase + 7);
363 for (i = 0; i < cBlocks; i++)
364 {
365 int j;
366 char *pchBlock = (char*)pvRecord + i * 512;
367 for (j = 0; j < 37; j++)
368 {
369 if (pchBlock[j] > 19 && pchBlock[j] < 0xff)
370 {
371 unsigned short *pusBlock = (unsigned short*)&pchBlock[pchBlock[j] * 2];
372 pusBlock = (unsigned short *) ((char*)pusBlock + *(char*)pusBlock + 1);
373 if (ausTrans[*pusBlock] == 0)
374 fprintf(stderr, "error: dictionary entry don't point to a THEADR page!\n");
375 else
376 *pusBlock = ausTrans[*pusBlock];
377 }
378 }
379
380 }
381
382 /* Write the dictionary */
383 fwrite(pvRecord, 512, cBlocks, phNew);
384 return (void*)0xffffffff; /* FINE */
385 }
386
387 case COMENT:
388 {
389 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
390 switch (*((unsigned char*)((int)pvRecord+4)))
391 {
392 /* remove "Link Pass Separator" */
393 case 0xA2:
394 /* remove "LIBMOD" - The VAC 3.6.5 Linker don't like these! */
395 case 0xA3:
396 fChanged = fRemoveExtra;
397 break;
398 }
399 break;
400 }
401
402 /*
403 * Remove checksum
404 */
405 /*
406 case GRPDEF:
407 case FIXUPP:
408 case FIXUPP2:
409 case LEDATA:
410 {
411 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
412 *((char*)pvRecord + cbRecord - 1) = 0;
413 break;
414 }
415 */
416
417 default:
418 cbRecord = *((unsigned short*)((int)pvRecord+1)) + 3;
419 break;
420 }
421
422 if (!fChanged)
423 fwrite(pvRet, 1, cbRecord, phNew);
424
425
426 return (void*)((int)pvRet + cbRecord);
427}
428
429
Note: See TracBrowser for help on using the repository browser.