ReactOS 0.4.16-dev-336-gb667d82
rsym64.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "rsym.h"
6#include "rsym64.h"
7#include "dwarf2.h"
8
9char DoPrint = 0;
11
12#define DPRINT if(DoPrint) printf
13
14struct {char *name; char regnt;} regs[] =
15{ {"rax", REG_RAX}, {"rdx", REG_RDX}, {"rcx", REG_RCX}, {"rbx", REG_RBX},
16 {"rsi", REG_RSI}, {"rdi", REG_RDI}, {"rbp", REG_RBP}, {"rsp", REG_RSP},
17 {"r8", REG_R8}, {"r9", REG_R9}, {"r10", REG_R10}, {"r11", REG_R11},
18 {"r12", REG_R12}, {"r13", REG_R13}, {"r14", REG_R14}, {"r15", REG_R15},
19 {"xmm0", REG_XMM0}, {"xmm1", REG_XMM1}, {"xmm2", REG_XMM2}, {"xmm3", REG_XMM3},
20 {"xmm4", REG_XMM4}, {"xmm5", REG_XMM5}, {"xmm6", REG_XMM6}, {"xmm7", REG_XMM7},
21 {"xmm8", REG_XMM8}, {"xmm9", REG_XMM9}, {"xmm10",REG_XMM10},{"xmm11",REG_XMM11},
22 {"xmm12",REG_XMM12},{"xmm13",REG_XMM13},{"xmm14",REG_XMM14},{"xmm15",REG_XMM15},
23// "st0", "st1", "st2", "st3",
24// "st4", "st5", "st6", "st7",
25// "mm0", "mm1", "mm2", "mm3",
26// "mm4", "mm5", "mm6", "mm7"
27};
28
31unsigned long
32DwDecodeUleb128(unsigned long *pResult, char *pc)
33{
34 unsigned long ulResult = 0;
35 unsigned long ulShift = 0;
36 unsigned char current;
37 unsigned long ulSize = 0;
38
39 do
40 {
41 current = pc[ulSize];
42 ulSize++;
43 ulResult |= (current & 0x7f) << ulShift;
44 ulShift += 7;
45 }
46 while (current & 0x80);
47
48 *pResult = ulResult;
49 return ulSize;
50}
51
52unsigned long
53DwDecodeSleb128(long *pResult, char *pc)
54{
55 long lResult = 0;
56 unsigned long ulShift = 0;
57 unsigned char current;
58 unsigned long ulSize = 0;
59
60 do
61 {
62 current = pc[ulSize];
63 ulSize++;
64 lResult |= (current & 0x7f) << ulShift;
65 ulShift += 7;
66 }
67 while (current & 0x80);
68
69 if (current & 0x40)
70 lResult |= - (1 << (ulShift));
71
72 *pResult = lResult;
73
74 return ulSize;
75}
76
77unsigned long
78DwDecodeCie(PDW2CIE Cie, char *pc)
79{
80 Cie->Length = *(ULONG*)pc;
81 Cie->Next = pc + 4 + Cie->Length;
82 Cie->CieId = *(ULONG*)(pc + 4);
83 Cie->Version = pc[8];
84 Cie->AugString = pc + 9;
85 Cie->AugStringLength = strlen(Cie->AugString);
86 pc = Cie->AugString + Cie->AugStringLength + 1;
87 pc += DwDecodeUleb128(&Cie->CodeAlign, pc);
88 pc += DwDecodeSleb128(&Cie->DataAlign, pc);
90 pc += DwDecodeUleb128(&Cie->AugLength, pc);
91 Cie->AugData = pc;
92 pc += Cie->AugLength;
93 Cie->Instructions = pc;
94
95 return Cie->Length + 4;
96}
97
98unsigned long
99DwDecodeFde(PDW2FDE Fde, char *pc)
100{
101 Fde->Length = *(ULONG*)pc;
102 Fde->Next = pc + 4 + Fde->Length;
103 Fde->CiePointer = pc + 4 - *(ULONG*)(pc + 4);
104 Fde->PcBegin = *(ULONG*)(pc + 8);
105 Fde->PcRange = *(ULONG*)(pc + 12);
106 pc += 16;
107 pc += DwDecodeUleb128(&Fde->AugLength, pc);
108 Fde->AugData = pc;
109 Fde->Instructions = Fde->AugData + Fde->AugLength;
110
111 return Fde->Length + 4;
112}
113
114unsigned long
116{
117 unsigned char Code;
118 unsigned long Length;
119 unsigned long PrevFramePtr = State->FramePtr;
120
121 State->Scope = 0;
122 State->IsUwop = 0;
123 State->Code = Code = *pc;
124 Length = 1;
125 if ((Code & 0xc0) == DW_CFA_advance_loc)
126 {
128 State->Location += Code & 0x3f;
129 }
130 else if ((Code & 0xc0) == DW_CFA_offset)
131 {
132 State->Code = DW_CFA_offset;
133 State->Reg = Code & 0x3f;
134 Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + 1);
135 State->Offset *= 8; // fixme data alignment
136 State->IsUwop = 1;
137 }
138 else if ((Code & 0xc0) == DW_CFA_restore)
139 {
140 State->Code = DW_CFA_restore;
141 State->Reg = Code & 0x3f;
142 }
143 else switch (Code)
144 {
145 case DW_CFA_nop:
146 break;
147 case DW_CFA_set_loc:
148 Length = 9; // address
149 State->Location = *(DWORD*)(pc + 1);
150 break;
152 Length = 2;
153 State->Location += pc[1];
154 break;
156 Length = 3;
157// printf("Found a DW_CFA_advance_loc2 : 0x%lx ->", *(WORD*)(pc + 1));
158 State->Location += *(WORD*)(pc + 1);
159// printf(" 0x%lx\n", State->Location);
160 break;
162 Length = 5;
163// printf("Found a DW_CFA_advance_loc4 : 0x%lx ->", *(DWORD*)(pc + 1));
164 State->Location += *(DWORD*)(pc + 1);
165// printf(" 0x%lx\n", State->Location);
166 break;
168 Length += DwDecodeUleb128(&State->Reg, pc + Length);
169 Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + Length);
170 State->IsUwop = 1;
171 break;
173 Length += DwDecodeUleb128(&State->Reg, pc + Length);
174 Length += DwDecodeSleb128(&State->Offset, pc + Length);
175 State->IsUwop = 1;
176 break;
178 Length += DwDecodeUleb128(&State->Reg, pc + Length);
179 break;
180 case DW_CFA_undefined:
181 Length += DwDecodeUleb128(&State->Reg, pc + Length);
182 break;
184 Length += DwDecodeUleb128(&State->Reg, pc + Length);
185 break;
186 case DW_CFA_register:
187 Length += DwDecodeUleb128(&State->Reg, pc + Length);
188 Length += DwDecodeUleb128(&State->Reg2, pc + Length);
189 break;
191 break;
193 break;
194 case DW_CFA_def_cfa:
195 Length += DwDecodeUleb128(&State->Reg, pc + Length);
196 Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length);
197 State->IsUwop = 1;
198 break;
200 Length += DwDecodeUleb128(&State->Reg, pc + Length);
201 break;
203 Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length);
204 State->IsUwop = 1;
205 break;
207 Length += DwDecodeUleb128(&State->Reg, pc + Length);
208 Length += DwDecodeSleb128(&State->FramePtr, pc + Length);
209 State->FramePtr *= 8; // data alignment
210 State->IsUwop = 1;
211 break;
213 {
214 unsigned long argsize;
215 printf("Warning, DW_CFA_GNU_args_size is unimplemented\n");
216 Length += DwDecodeUleb128(&argsize, pc + Length);
217 break;
218 }
219 /* PSEH */
220 case 0x21:
221 {
222 unsigned long SehType;
223
224// printf("found 0x21 at %lx\n", State->Location);
225 Length += DwDecodeUleb128(&SehType, pc + Length);
226 switch (SehType)
227 {
228 case 1: /* Begin Try */
229 State->TryLevel++;
230 if (State->TryLevel >= 20)
231 {
232 printf("WTF? Trylevel of 20 exceeded...\n");
233 exit(1);
234 }
235 State->SehBlock[State->TryLevel-1].BeginTry = State->Location;
236// printf("Found begintry at 0x%lx\n", State->Location);
237 State->Scope = 1;
238 break;
239
240 case 2: /* End Try */
241 State->SehBlock[State->TryLevel-1].EndTry = State->Location;
242 State->Scope = 2;
243 break;
244
245 case 3: /* Jump target */
246 State->SehBlock[State->TryLevel-1].Target = State->Location;
247 State->Scope = 3;
248 break;
249
250 case 4: /* SEH End */
251 if (State->TryLevel == 20)
252 {
253 printf("Ooops, end of SEH with trylevel at 0!\n");
254 exit(1);
255 }
256 State->SehBlock[State->TryLevel-1].End = State->Location;
257 State->TryLevel--;
258 State->cScopes++;
259 State->Scope = 0;
260 break;
261
262 case 5: /* Constant filter */
263 {
264 unsigned long value;
266 State->SehBlock[State->TryLevel-1].Handler = value;
267// printf("Found a constant filter at 0x%lx\n", State->Location);
268 break;
269 }
270
271 /* These work differently. We are in a new function.
272 * We have to parse a lea opcode to find the address of
273 * the jump target. This is the reference to find the
274 * appropriate C_SCOPE_TABLE. */
275 case 6: /* Filter func */
276// printf("Found a filter func at 0x%lx\n", State->Location);
277 break;
278
279 case 7: /* Finally func */
280 {
281// printf("Found a finally func at 0x%lx\n", State->Location);
282 break;
283 }
284
285 default:
286 printf("Found unknow PSEH code 0x%lx\n", SehType);
287 exit(1);
288 }
289 break;
290 }
291 default:
292 fprintf(stderr, "unknown instruction 0x%x at 0x%p\n", Code, pc);
293 exit(1);
294 }
295
296 State->FramePtrDiff = State->FramePtr - PrevFramePtr;
297 DPRINT("@%p: code=%x, Loc=%lx, offset=%lx, reg=0x%lx:%s\n",
298 (void*)((ULONG)pc - g_ehframep), Code, State->Location, State->Offset, State->Reg, regs[State->Reg].name);
299 return Length;
300}
301
304ULONG
306{
307 ULONG cCodes = 0;
308 ULONG AllocSize;
309 UNWIND_CODE Code[3];
310 int i;
311
312 Code[0].CodeOffset = State->Location - FunctionStart;
313
314 switch (State->Code)
315 {
316 case DW_CFA_offset:
318 // save register at offset
319 Code[0].OpInfo = regs[State->Reg].regnt;
320 if (State->Offset <= 0x7FFF8)
321 {
322 Code[0].UnwindOp = UWOP_SAVE_NONVOL;
323 Code[1].FrameOffset = State->Offset / 8;
324 cCodes = 2;
325 }
326 else
327 {
328 Code[0].UnwindOp = UWOP_SAVE_NONVOL_FAR;
329 Code[1].FrameOffset = (State->Offset / 8);
330 Code[2].FrameOffset = (State->Offset / 8) >> 16;
331 cCodes = 3;
332 }
333 break;
334
335 case DW_CFA_def_cfa:
336 //case DW_CFA_def_cfa_register:
339 AllocSize = State->FramePtrDiff;
340 if (AllocSize <= 128)
341 {
342 Code[0].UnwindOp = UWOP_ALLOC_SMALL;
343 Code[0].OpInfo = (AllocSize / 8) - 1;
344 cCodes = 1;
345 }
346 else if (AllocSize <= 0x7FFF8)
347 {
348 Code[0].UnwindOp = UWOP_ALLOC_LARGE;
349 Code[0].OpInfo = 0;
350 Code[1].FrameOffset = AllocSize / 8;
351 cCodes = 2;
352 }
353 else // if (AllocSize > 0x7FFF8)
354 {
355 Code[0].UnwindOp = UWOP_ALLOC_LARGE;
356 Code[0].OpInfo = 1;
357 Code[1].FrameOffset = (USHORT)AllocSize;
358 Code[2].FrameOffset = (USHORT)(AllocSize >> 16);
359 cCodes = 3;
360 }
361 break;
362 }
363
364 if (Info)
365 {
366 /* Move old codes */
367 for (i = Info->CountOfCodes - 1; i >= 0; i--)
368 {
369 Info->UnwindCode[i + cCodes] = Info->UnwindCode[i];
370 }
371
372 /* Copy new codes */
373 for (i = 0; i < cCodes; i++)
374 {
375 Info->UnwindCode[i] = Code[i];
376 }
377
378 Info->CountOfCodes += cCodes;
379 }
380
381 return cCodes;
382}
383
384#define GetxdataSize(cFuncs, cUWOP, cScopes) \
385 ( cFuncs * (sizeof(UNWIND_INFO) + 2 + 4 + 4) \
386 + cUWOP * sizeof(UNWIND_CODE) \
387 + cScopes * sizeof(C_SCOPE_TABLE_ENTRY) )
388
389ULONG
391{
392 ULONG cbSize;
394 char *pInst;
395 ULONG c;
396 DW2CIE Cie;
397
398 cbSize = 4; // sizeof(UNWIND_INFO);
399 Info->Version = 1;
400 Info->Flags = 0;
401 Info->SizeOfProlog = 0;
402 Info->CountOfCodes = 0;
403 Info->FrameRegister = 0;
404 Info->FrameOffset = 0;
405
406 /* Decode the CIE */
407 DwDecodeCie(&Cie, pFde->CiePointer);
408
409 /* Initialize state */
410 State.Location = FunctionStart;
411 State.FramePtr = 0;
412 State.TryLevel = 0;
413 State.cScopes = 0;
414
415 /* Parse the CIE's initial instructions */
416 pInst = Cie.Instructions;
417 while (pInst < Cie.Next)
418 {
419 pInst += DwExecIntruction(&State, pInst);
420 }
421
422 /* Parse the FDE instructions */
423 pInst = pFde->Instructions;
424 while (pInst < pFde->Next)
425 {
426 pInst += DwExecIntruction(&State, pInst);
427
428 if (State.IsUwop)
429 {
430 c = StoreUnwindCodes(Info, &State, FunctionStart);
431 cbSize += c * sizeof(UNWIND_CODE);
432 Info->SizeOfProlog = State.Location - FunctionStart;
433 }
434 }
435 cbSize = ROUND_UP(cbSize, 4);
436
437 /* Do we have scope table to write? */
438 if (State.cScopes > 0)
439 {
440 unsigned long i;
441 ULONG *pExceptionHandler;
442 PC_SCOPE_TABLE pScopeTable;
443
444 /* Set flag for exception handler */
445 Info->Flags |= UNW_FLAG_EHANDLER;
446
447 /* Store address of handler and number of scope tables */
448 pExceptionHandler = (ULONG*)((char*)Info + cbSize);
449 // HACK for testing purpose
450 *pExceptionHandler = FunctionStart; // _C_specific_handler
451
452 pScopeTable = (PC_SCOPE_TABLE)(pExceptionHandler + 1);
453 pScopeTable->NumEntries = State.cScopes;
454
455 /* Store the scope table entries */
456 for (i = 0; i < State.cScopes; i++)
457 {
458 pScopeTable->Entry[i].Begin = State.SehBlock[i].BeginTry;
459 pScopeTable->Entry[i].End = State.SehBlock[i].EndTry;
460 pScopeTable->Entry[i].Handler = 1;//State.SehBlock[i].Handler;
461 pScopeTable->Entry[i].Target = State.SehBlock[i].Target;
462 }
463
464 /* Update size */
465 cbSize += 8 + State.cScopes * sizeof(C_SCOPE_TABLE_ENTRY);
466 }
467
468 return cbSize;
469}
470
471void
473{
474 DW2CIEFDE *p;
475 DW2FDE Fde;
476 char *pInst, *pmax;
478
479 File->cFuncs = 0;
480 File->cScopes = 0;
481 File->cUWOP = 0;
482 State.FramePtr = 0;
483 State.TryLevel = 0;
484
485 p = File->eh_frame.p;
486 pmax = (char*)p + File->eh_frame.psh->Misc.VirtualSize;
487 for (; p->Length && (char*)p < pmax; p = NextCIE(p))
488 {
489 /* Is this an FDE? */
490 if (p->CiePointer != 0)
491 {
492 File->cFuncs++;
493 DwDecodeFde(&Fde, (char*)p);
494
495 pInst = Fde.Instructions;
496 while (pInst < Fde.Next)
497 {
498 pInst += DwExecIntruction(&State, pInst);
499 File->cUWOP += StoreUnwindCodes(NULL, &State, 0);
500 File->cScopes += State.Scope ? 1 : 0;
501 }
502 }
503 }
504
505 return;
506}
507
508int CompFunc(const void *p1, const void *p2)
509{
510 PRUNTIME_FUNCTION prf1 = (void*)p1, prf2 = (void*)p2;
511 return (prf1->FunctionStart > prf2->FunctionStart ? 1 : -1);
512}
513
514void
516{
517 DW2CIEFDE *p;
518 DW2FDE Fde;
520 ULONG i, Offset;
521 void * eh_frame;
523 ULONG xdata_va;
524 char *xdata_p;
525 ULONG cbSize;
526 PIMAGE_SECTION_HEADER pshp, pshx;
527 ULONG FileAlignment;
528 char *pmax;
529
530 FileAlignment = File->OptionalHeader->FileAlignment;
531
532 /* Get pointer to eh_frame section */
533 eh_frame = File->eh_frame.p;
534 g_ehframep = (ULONG)eh_frame;
535
536 /* Get sizes */
538// printf("cFuncs = %ld, cUWOPS = %ld, cScopes = %ld\n",
539// File->cFuncs, File->cUWOP, File->cScopes);
540
541 /* Initialize section header for .pdata */
542 i = File->pdata.idx = File->UsedSections;
543 pshp = File->pdata.psh = &File->NewSectionHeaders[i];
544 memcpy(pshp->Name, ".pdata", 7);
545 pshp->Misc.VirtualSize = (File->cFuncs + 1) * sizeof(RUNTIME_FUNCTION);
546 pshp->VirtualAddress = File->NewSectionHeaders[i - 1].VirtualAddress +
547 File->NewSectionHeaders[i - 1].SizeOfRawData;
548 pshp->SizeOfRawData = ROUND_UP(pshp->Misc.VirtualSize, FileAlignment);
549 pshp->PointerToRawData = File->NewSectionHeaders[i - 1].PointerToRawData +
550 File->NewSectionHeaders[i - 1].SizeOfRawData;
551 pshp->PointerToRelocations = 0;
552 pshp->PointerToLinenumbers = 0;
553 pshp->NumberOfRelocations = 0;
554 pshp->NumberOfLinenumbers = 0;
557
558 /* Allocate .pdata buffer */
559 pdata = File->pdata.p = malloc(pshp->SizeOfRawData);
560 memset(File->pdata.p, 0, pshp->SizeOfRawData);
561
562 /* Init exception data dir */
563 Dir = &File->OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
564 Dir->VirtualAddress = pshp->VirtualAddress;
565 Dir->Size = pshp->Misc.VirtualSize;
566
567 /* Initialize section header for .xdata */
568 File->xdata.idx = File->pdata.idx + 1;
569 pshx = File->xdata.psh = &File->NewSectionHeaders[File->xdata.idx];
570 memcpy(pshx->Name, ".xdata", 7);
571 pshx->Misc.VirtualSize = GetxdataSize(File->cFuncs, File->cUWOP, File->cScopes);
572 pshx->VirtualAddress = pshp->VirtualAddress + pshp->SizeOfRawData;
573 pshx->SizeOfRawData = ROUND_UP(pshx->Misc.VirtualSize, FileAlignment);
574 pshx->PointerToRawData = pshp->PointerToRawData + pshp->SizeOfRawData;
575 pshx->PointerToRelocations = 0;
576 pshx->PointerToLinenumbers = 0;
577 pshx->NumberOfRelocations = 0;
578 pshx->NumberOfLinenumbers = 0;
581
582 /* Allocate .xdata buffer */
583 File->xdata.p = malloc(pshx->SizeOfRawData);
584 memset(File->xdata.p, 0, pshx->SizeOfRawData);
585
586 i = 0;
587 Offset = File->eh_frame.psh->VirtualAddress;
588 xdata_va = pshx->VirtualAddress;
589 xdata_p = File->xdata.p;
590 pmax = (char*)eh_frame + File->eh_frame.psh->Misc.VirtualSize - 100;
591
592 for (p = eh_frame; p->Length && (char*)p < pmax; p = NextCIE(p))
593 {
594 /* Is this an FDE? */
595 if (p->CiePointer != 0)
596 {
597 DwDecodeFde(&Fde, (char*)p);
598 pdata[i].FunctionStart = Offset + 8 + Fde.PcBegin;
599 pdata[i].FunctionEnd = pdata[i].FunctionStart + Fde.PcRange;
600 pdata[i].UnwindInfo = xdata_va;
601
602// printf("%ld: RUNTIME_FUNCTION: {0x%lx, 0x%lx, 0x%lx}\n", i, pdata[i].FunctionStart, pdata[i].FunctionEnd, pdata[i].UnwindInfo);
603
604 cbSize = StoreUnwindInfo((void*)xdata_p, &Fde, pdata[i].FunctionStart);
605 xdata_va += cbSize;
606 xdata_p += cbSize;
607 i++;
608 }
609 Offset += 4 + p->Length;
610 }
611
612 /* Sort the RUNTIME_FUNCTIONS */
614
615}
616
620WORD
622{
623 WORD *Ptr = pFile;
624 DWORD i;
626
627 for (i = 0; i < (cbSize + 1) / sizeof(WORD); i++)
628 {
629 checksum += Ptr[i];
630 checksum = (checksum + (checksum >> 16)) & 0xffff;
631 }
632
633 return checksum ;
634}
635
636void
638{
639 int ret, Size, Pos = 0;
640 DWORD CheckSum;
642
643 Alignment = File->OptionalHeader->FileAlignment;
644
645 /* Update section count */
646 File->FileHeader->NumberOfSections = File->UsedSections + 2; // FIXME!!!
647
648 /* Update SizeOfImage */
649 Size = File->xdata.psh->VirtualAddress
650 + File->xdata.psh->SizeOfRawData;
651 File->OptionalHeader->SizeOfImage = Size;
652
653 /* Recalculate checksum */
654 CheckSum = CalculateChecksum(0, File->FilePtr, File->HeaderSize);
655 for (i = 0; i < File->AllSections; i++)
656 {
657 if (File->UseSection[i])
658 {
659 Size = File->SectionHeaders[i].SizeOfRawData;
660 if (Size)
661 {
662 void *p;
663 p = File->FilePtr + File->SectionHeaders[i].PointerToRawData;
664 CheckSum = CalculateChecksum(CheckSum, p, Size);
665 }
666 }
667 }
668 Size = File->pdata.psh->Misc.VirtualSize;
669 CheckSum = CalculateChecksum(CheckSum, File->pdata.p, Size);
670 Size = File->xdata.psh->Misc.VirtualSize;
671 CheckSum = CalculateChecksum(CheckSum, File->xdata.p, Size);
672 CheckSum += File->HeaderSize;
673 CheckSum += File->pdata.psh->Misc.VirtualSize;
674 CheckSum += File->xdata.psh->Misc.VirtualSize;
675 File->OptionalHeader->CheckSum = CheckSum;
676
677 /* Write file header */
678 Size = File->HeaderSize;
679 ret = fwrite(File->DosHeader, 1, Size, handle);
680 Pos = Size;
681
682 /* Write Section headers */
683 Size = File->NewSectionHeaderSize;
684 ret = fwrite(File->NewSectionHeaders, 1, Size, handle);
685 Pos += Size;
686
687 /* Fill up to next alignement */
689 ret = fwrite(File->AlignBuf, 1, Size, handle);
690 Pos += Size;
691
692 /* Write sections */
693 for (i = 0; i < File->AllSections; i++)
694 {
695 if (File->UseSection[i])
696 {
697 void *p;
698 Size = File->SectionHeaders[i].SizeOfRawData;
699 if (Size)
700 {
701 p = File->FilePtr + File->SectionHeaders[i].PointerToRawData;
702 ret = fwrite(p, 1, Size, handle);
703 Pos += Size;
704 }
705 }
706 }
707
708 /* Write .pdata section */
709 Size = File->pdata.psh->SizeOfRawData;
710 ret = fwrite(File->pdata.p, 1, Size, handle);
711 Pos += Size;
712
713 /* Write .xdata section */
714 Size = File->xdata.psh->SizeOfRawData;
715 ret = fwrite(File->xdata.p, 1, Size, handle);
716 Pos += Size;
717
718}
719
720
721int
723{
724 DWORD OldChecksum, Checksum;
725 ULONG Alignment, CurrentPos;
726 int i, j;
727
728 /* Check if MZ header exists */
729 File->DosHeader = (PIMAGE_DOS_HEADER)File->FilePtr;
730 if ((File->DosHeader->e_magic != IMAGE_DOS_MAGIC) ||
731 (File->DosHeader->e_lfanew == 0L))
732 {
733 perror("Input file is not a PE image.\n");
734 return -1;
735 }
736
737 /* Locate PE file header */
738 File->FileHeader = (PIMAGE_FILE_HEADER)(File->FilePtr +
739 File->DosHeader->e_lfanew + sizeof(ULONG));
740
741 /* Check for x64 image */
742 if (File->FileHeader->Machine != IMAGE_FILE_MACHINE_AMD64)
743 {
744 perror("Input file is not an x64 image.\n");
745 return -1;
746 }
747
748 /* Locate optional header */
749 File->OptionalHeader = (PIMAGE_OPTIONAL_HEADER64)(File->FileHeader + 1);
750
751 /* Check if checksum is correct */
752 OldChecksum = File->OptionalHeader->CheckSum;
753 File->OptionalHeader->CheckSum = 0;
754 Checksum = CalculateChecksum(0, File->FilePtr, File->cbInFileSize);
755 Checksum += File->cbInFileSize;
756 if ((Checksum & 0xffff) != (OldChecksum & 0xffff))
757 {
758 fprintf(stderr, "Input file has incorrect PE checksum: 0x%lx (calculated: 0x%lx)\n",
759 OldChecksum, Checksum);
760// return 0;
761 }
762
763 /* Locate PE section headers */
764 File->SectionHeaders = (PIMAGE_SECTION_HEADER)((char*)File->OptionalHeader
765 + File->FileHeader->SizeOfOptionalHeader);
766
767 File->HeaderSize = File->DosHeader->e_lfanew
768 + sizeof(ULONG)
769 + sizeof(IMAGE_FILE_HEADER)
770 + File->FileHeader->SizeOfOptionalHeader;
771
772 /* Create some shortcuts */
773 File->ImageBase = File->OptionalHeader->ImageBase;
774 File->Symbols = File->FilePtr + File->FileHeader->PointerToSymbolTable;
775 File->Strings = (char*)File->Symbols + File->FileHeader->NumberOfSymbols * 18;
776
777 /* Check section names */
778 File->AllSections = File->FileHeader->NumberOfSections;
779 Alignment = File->OptionalHeader->FileAlignment;
780 File->NewSectionHeaders = malloc((File->AllSections+2) * sizeof(IMAGE_SECTION_HEADER));
781 File->UsedSections = 0;
782 File->eh_frame.idx = -1;
783
784 /* Allocate array of chars, specifying whether to copy the section */
785 File->UseSection = malloc(File->AllSections);
786
787 for (i = 0; i < File->AllSections; i++)
788 {
789 char *pName = (char*)File->SectionHeaders[i].Name;
790 File->UseSection[i] = 1;
791
792 /* Check for long name */
793 if (pName[0] == '/')
794 {
795 unsigned long index = strtoul(pName+1, 0, 10);
796 pName = File->Strings + index;
797
798 // Hack, simply remove all sections with long names
799 File->UseSection[i] = 0;
800 }
801
802 /* Chek if we have the eh_frame section */
803 if (strcmp(pName, ".eh_frame") == 0)
804 {
805 File->eh_frame.psh = &File->SectionHeaders[i];
806 File->eh_frame.idx = i;
807 File->eh_frame.p = File->FilePtr + File->eh_frame.psh->PointerToRawData;
808 }
809
810 /* Increase number of used sections */
811 if (File->UseSection[i])
812 File->UsedSections = i+1;
813
814 }
815
816 /* This is the actual size of the new section headers */
817 File->NewSectionHeaderSize =
818 (File->UsedSections+2) * sizeof(IMAGE_SECTION_HEADER);
819
820 /* Calculate the position to start writing the sections to */
821 CurrentPos = File->HeaderSize + File->NewSectionHeaderSize;
822 CurrentPos = ROUND_UP(CurrentPos, Alignment);
823
824 /* Create new section headers */
825 for (i = 0, j = 0; i < File->UsedSections; i++)
826 {
827 /* Copy section header */
828 File->NewSectionHeaders[j] = File->SectionHeaders[i];
829
830 /* Shall we strip the section? */
831 if (File->UseSection[i] == 0)
832 {
833 /* Make it a bss section */
834 File->NewSectionHeaders[j].PointerToRawData = 0;
835 File->NewSectionHeaders[j].SizeOfRawData = 0;
836 File->NewSectionHeaders[j].Characteristics = 0xC0500080;
837 }
838
839 /* Fix Offset into File */
840 File->NewSectionHeaders[j].PointerToRawData =
841 File->NewSectionHeaders[j].PointerToRawData ? CurrentPos : 0;
842 CurrentPos += File->NewSectionHeaders[j].SizeOfRawData;
843 j++;
844 }
845
846 if (File->eh_frame.idx == -1)
847 {
848 //fprintf(stderr, "No .eh_frame section found\n");
849 return 0;
850 }
851
852 return 1;
853}
854
855int main(int argc, char* argv[])
856{
857 char* pszInFile;
858 char* pszOutFile;
860 FILE* outfile;
861 int ret;
862 int arg, argstate = 0;
863 char *SourcePath = NULL;
864
865 for (arg = 1; arg < argc; arg++)
866 {
867 switch (argstate)
868 {
869 default:
870 argstate = -1;
871 break;
872
873 case 0:
874 if (!strcmp(argv[arg], "-s"))
875 {
876 argstate = 1;
877 }
878 else
879 {
880 argstate = 2;
881 pszInFile = convert_path(argv[arg]);
882 }
883 break;
884
885 case 1:
886 free(SourcePath);
887 SourcePath = strdup(argv[arg]);
888 argstate = 0;
889 break;
890
891 case 2:
892 pszOutFile = convert_path(argv[arg]);
893 argstate = 3;
894 break;
895 }
896 }
897
898 if (argstate != 3)
899 {
900 fprintf(stderr, "Usage: rsym [-s <sources>] <input> <output>\n");
901 exit(1);
902 }
903
904 File.FilePtr = load_file(pszInFile, &File.cbInFileSize);
905 if (!File.FilePtr)
906 {
907 fprintf(stderr, "An error occured loading '%s'\n", pszInFile);
908 exit(1);
909 }
910
912 if (ret != 1)
913 {
914 free(File.FilePtr);
915 exit(ret == -1 ? 1 : 0);
916 }
917
918 File.AlignBuf = malloc(File.OptionalHeader->FileAlignment);
919 memset(File.AlignBuf, 0, File.OptionalHeader->FileAlignment);
920
922
923 outfile = fopen(pszOutFile, "wb");
924 if (outfile == NULL)
925 {
926 perror("Cannot open output file");
927 free(File.FilePtr);
928 exit(1);
929 }
930
932
934
935 return 0;
936}
static int argc
Definition: ServiceArgs.c:12
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define index(s, c)
Definition: various.h:29
Definition: File.h:16
union _UNWIND_CODE UNWIND_CODE
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define Code
Definition: deflate.h:80
ush Pos
Definition: deflate.h:92
#define NULL
Definition: types.h:112
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
@ DW_CFA_offset_extended
Definition: dwarf.h:515
@ DW_CFA_restore
Definition: dwarf.h:509
@ DW_CFA_def_cfa_sf
Definition: dwarf.h:528
@ DW_CFA_remember_state
Definition: dwarf.h:520
@ DW_CFA_offset_extended_sf
Definition: dwarf.h:527
@ DW_CFA_nop
Definition: dwarf.h:510
@ DW_CFA_register
Definition: dwarf.h:519
@ DW_CFA_advance_loc1
Definition: dwarf.h:512
@ DW_CFA_restore_state
Definition: dwarf.h:521
@ DW_CFA_def_cfa
Definition: dwarf.h:522
@ DW_CFA_undefined
Definition: dwarf.h:517
@ DW_CFA_offset
Definition: dwarf.h:508
@ DW_CFA_def_cfa_register
Definition: dwarf.h:523
@ DW_CFA_GNU_args_size
Definition: dwarf.h:535
@ DW_CFA_restore_extended
Definition: dwarf.h:516
@ DW_CFA_set_loc
Definition: dwarf.h:511
@ DW_CFA_def_cfa_offset
Definition: dwarf.h:524
@ DW_CFA_advance_loc2
Definition: dwarf.h:513
@ DW_CFA_same_value
Definition: dwarf.h:518
@ DW_CFA_advance_loc4
Definition: dwarf.h:514
@ DW_CFA_advance_loc
Definition: dwarf.h:507
static UINT load_file(MSIRECORD *row, LPVOID param)
Definition: action.c:1031
int main()
Definition: test.c:6
#define NextCIE(p)
Definition: dwarf2.h:839
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
struct _IMAGE_FILE_HEADER * PIMAGE_FILE_HEADER
unsigned short WORD
Definition: ntddk_ex.h:93
#define printf
Definition: freeldr.h:97
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
union Alignment_ Alignment
return pTarget Start()
MdFileObject pFile
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
#define c
Definition: ke_i.h:80
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
#define for
Definition: utility.h:88
static LPSTR pName
Definition: security.c:75
static PROTOCOLDATA * pdata
Definition: protocol.c:158
#define argv
Definition: mplay32.c:18
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
struct _IMAGE_OPTIONAL_HEADER64 * PIMAGE_OPTIONAL_HEADER64
#define IMAGE_SCN_MEM_NOT_PAGED
Definition: ntimage.h:237
#define IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: ntimage.h:231
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
#define IMAGE_SCN_MEM_READ
Definition: ntimage.h:240
#define L(x)
Definition: ntvdm.h:50
#define IMAGE_DOS_MAGIC
Definition: pecoff.h:6
struct _IMAGE_SECTION_HEADER * PIMAGE_SECTION_HEADER
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262
unsigned short USHORT
Definition: pedump.c:61
struct _IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER
char * convert_path(char *origpath)
Definition: rcopy.c:11
ULONG StoreUnwindInfo(PUNWIND_INFO Info, PDW2FDE pFde, ULONG FunctionStart)
Definition: rsym64.c:390
void WriteOutFile(FILE *handle, PFILE_INFO File)
Definition: rsym64.c:637
char regnt
Definition: rsym64.c:14
#define DPRINT
Definition: rsym64.c:12
ULONG g_ehframep
Definition: rsym64.c:10
int ParsePEHeaders(PFILE_INFO File)
Definition: rsym64.c:722
void GeneratePData(PFILE_INFO File)
Definition: rsym64.c:515
unsigned long DwExecIntruction(PDW2CFSTATE State, char *pc)
Definition: rsym64.c:115
char DoPrint
Definition: rsym64.c:9
char * name
Definition: rsym64.c:14
unsigned long DwDecodeFde(PDW2FDE Fde, char *pc)
Definition: rsym64.c:99
unsigned long DwDecodeSleb128(long *pResult, char *pc)
Definition: rsym64.c:53
ULONG StoreUnwindCodes(PUNWIND_INFO Info, PDW2CFSTATE State, ULONG FunctionStart)
Definition: rsym64.c:305
void CountUnwindData(PFILE_INFO File)
Definition: rsym64.c:472
unsigned long DwDecodeCie(PDW2CIE Cie, char *pc)
Definition: rsym64.c:78
unsigned long DwDecodeUleb128(unsigned long *pResult, char *pc)
Definition: rsym64.c:32
#define GetxdataSize(cFuncs, cUWOP, cScopes)
Definition: rsym64.c:384
struct @5017 regs[]
int CompFunc(const void *p1, const void *p2)
Definition: rsym64.c:508
WORD CalculateChecksum(DWORD Start, void *pFile, ULONG cbSize)
Definition: rsym64.c:621
#define REG_RAX
Definition: rsym64.h:31
#define REG_XMM15
Definition: rsym64.h:63
#define REG_R8
Definition: rsym64.h:39
#define REG_XMM5
Definition: rsym64.h:53
#define REG_XMM13
Definition: rsym64.h:61
#define REG_XMM0
Definition: rsym64.h:48
#define REG_XMM11
Definition: rsym64.h:59
#define REG_XMM3
Definition: rsym64.h:51
#define REG_R10
Definition: rsym64.h:41
#define REG_XMM2
Definition: rsym64.h:50
#define REG_RSI
Definition: rsym64.h:37
#define REG_XMM9
Definition: rsym64.h:57
@ UNW_FLAG_EHANDLER
Definition: rsym64.h:109
#define REG_XMM7
Definition: rsym64.h:55
#define REG_RCX
Definition: rsym64.h:32
#define REG_R15
Definition: rsym64.h:46
#define REG_R13
Definition: rsym64.h:44
struct _C_SCOPE_TABLE * PC_SCOPE_TABLE
#define REG_XMM6
Definition: rsym64.h:54
#define REG_RDI
Definition: rsym64.h:38
#define REG_XMM12
Definition: rsym64.h:60
#define REG_RSP
Definition: rsym64.h:35
#define REG_XMM10
Definition: rsym64.h:58
#define REG_R11
Definition: rsym64.h:42
#define REG_R9
Definition: rsym64.h:40
#define REG_RBX
Definition: rsym64.h:34
#define REG_RBP
Definition: rsym64.h:36
#define REG_R14
Definition: rsym64.h:45
#define REG_RDX
Definition: rsym64.h:33
#define REG_XMM14
Definition: rsym64.h:62
#define REG_XMM8
Definition: rsym64.h:56
#define REG_XMM4
Definition: rsym64.h:52
struct _C_SCOPE_TABLE_ENTRY C_SCOPE_TABLE_ENTRY
#define REG_XMM1
Definition: rsym64.h:49
#define REG_R12
Definition: rsym64.h:43
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
Definition: dwarf2.h:787
char * Instructions
Definition: dwarf2.h:799
char * Next
Definition: dwarf2.h:789
char * AugData
Definition: dwarf2.h:796
ULONG CieId
Definition: dwarf2.h:790
ULONG AugStringLength
Definition: dwarf2.h:793
char * AugString
Definition: dwarf2.h:794
char Version
Definition: dwarf2.h:791
ULONG CodeAlign
Definition: dwarf2.h:797
ULONG AugLength
Definition: dwarf2.h:795
LONG DataAlign
Definition: dwarf2.h:798
ULONG ReturnAddressRegister
Definition: dwarf2.h:792
ULONG Length
Definition: dwarf2.h:788
Definition: dwarf2.h:803
char * Instructions
Definition: dwarf2.h:811
char * Next
Definition: dwarf2.h:805
char * CiePointer
Definition: dwarf2.h:806
unsigned long PcBegin
Definition: dwarf2.h:807
unsigned long PcRange
Definition: dwarf2.h:808
unsigned long Length
Definition: dwarf2.h:804
char * AugData
Definition: dwarf2.h:810
unsigned long AugLength
Definition: dwarf2.h:809
ULONG Target
Definition: rsym64.h:136
ULONG Handler
Definition: rsym64.h:135
ULONG Begin
Definition: rsym64.h:133
ULONG End
Definition: rsym64.h:134
ULONG NumEntries
Definition: rsym64.h:141
C_SCOPE_TABLE_ENTRY Entry[1]
Definition: rsym64.h:142
DWORD PointerToLinenumbers
Definition: pedump.c:292
DWORD PointerToRelocations
Definition: pedump.c:291
DWORD PointerToRawData
Definition: pedump.c:290
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: pedump.c:281
WORD NumberOfLinenumbers
Definition: pedump.c:294
WORD NumberOfRelocations
Definition: pedump.c:293
union _IMAGE_SECTION_HEADER::@1573 Misc
ULONG FunctionStart
Definition: rsym64.h:90
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:94
#define UWOP_SAVE_NONVOL
Definition: unwind.c:23
#define UWOP_SAVE_NONVOL_FAR
Definition: unwind.c:24
#define UWOP_ALLOC_LARGE
Definition: unwind.c:20
#define UWOP_ALLOC_SMALL
Definition: unwind.c:21
int ret
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1701
void * arg
Definition: msvc.h:10
static FILE * outfile
Definition: wrjpgcom.c:81