ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rsym64.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 
00005 #include "rsym.h"
00006 #include "rsym64.h"
00007 #include "dwarf2.h"
00008 
00009 char DoPrint = 0;
00010 ULONG g_ehframep;
00011 
00012 #define DPRINT if(DoPrint) printf
00013 
00014 struct {char *name; char regnt;} regs[] =
00015 { {"rax", REG_RAX}, {"rdx", REG_RDX}, {"rcx", REG_RCX}, {"rbx", REG_RBX},
00016   {"rsi", REG_RSI}, {"rdi", REG_RDI}, {"rbp", REG_RBP}, {"rsp", REG_RSP},
00017   {"r8",  REG_R8},  {"r9",  REG_R9},  {"r10", REG_R10}, {"r11", REG_R11},
00018   {"r12", REG_R12}, {"r13", REG_R13}, {"r14", REG_R14}, {"r15", REG_R15},
00019   {"xmm0", REG_XMM0}, {"xmm1", REG_XMM1}, {"xmm2", REG_XMM2}, {"xmm3", REG_XMM3},
00020   {"xmm4", REG_XMM4}, {"xmm5", REG_XMM5}, {"xmm6", REG_XMM6}, {"xmm7", REG_XMM7},
00021   {"xmm8", REG_XMM8}, {"xmm9", REG_XMM9}, {"xmm10",REG_XMM10},{"xmm11",REG_XMM11},
00022   {"xmm12",REG_XMM12},{"xmm13",REG_XMM13},{"xmm14",REG_XMM14},{"xmm15",REG_XMM15},
00023 //      "st0", "st1", "st2", "st3",
00024 //      "st4", "st5", "st6", "st7",
00025 //      "mm0", "mm1", "mm2", "mm3",
00026 //      "mm4", "mm5", "mm6", "mm7"
00027 };
00028 
00031 unsigned long
00032 DwDecodeUleb128(unsigned long *pResult, char *pc)
00033 {
00034     unsigned long ulResult = 0;
00035     unsigned long ulShift = 0;
00036     unsigned char current;
00037     unsigned long ulSize = 0;
00038 
00039     do
00040     {
00041         current = pc[ulSize];
00042         ulSize++;
00043         ulResult |= (current & 0x7f) << ulShift;
00044         ulShift += 7;
00045     }
00046     while (current & 0x80);
00047 
00048     *pResult = ulResult;
00049     return ulSize;
00050 }
00051 
00052 unsigned long
00053 DwDecodeSleb128(long *pResult, char *pc)
00054 {
00055     long lResult = 0;
00056     unsigned long ulShift = 0;
00057     unsigned char current;
00058     unsigned long ulSize = 0;
00059 
00060     do
00061     {
00062         current = pc[ulSize];
00063         ulSize++;
00064         lResult |= (current & 0x7f) << ulShift;
00065         ulShift += 7;
00066     }
00067     while (current & 0x80);
00068 
00069     if (current & 0x40)
00070         lResult |= - (1 << (ulShift));
00071 
00072     *pResult = lResult;
00073 
00074     return ulSize;
00075 }
00076 
00077 unsigned long
00078 DwDecodeCie(PDW2CIE Cie, char *pc)
00079 {
00080     Cie->Length = *(ULONG*)pc;
00081     Cie->Next = pc + 4 + Cie->Length;
00082     Cie->CieId = *(ULONG*)(pc + 4);
00083     Cie->Version = pc[8];
00084     Cie->AugString = pc + 9;
00085     Cie->AugStringLength = strlen(Cie->AugString);
00086     pc = Cie->AugString + Cie->AugStringLength + 1;
00087     pc += DwDecodeUleb128(&Cie->CodeAlign, pc);
00088     pc += DwDecodeSleb128(&Cie->DataAlign, pc);
00089     pc += DwDecodeUleb128(&Cie->ReturnAddressRegister, pc);
00090     pc += DwDecodeUleb128(&Cie->AugLength, pc);
00091     Cie->AugData = pc;
00092     pc += Cie->AugLength;
00093     Cie->Instructions = pc;
00094 
00095     return Cie->Length + 4;
00096 }
00097 
00098 unsigned long
00099 DwDecodeFde(PDW2FDE Fde, char *pc)
00100 {
00101     Fde->Length = *(ULONG*)pc;
00102     Fde->Next = pc + 4 + Fde->Length;
00103     Fde->CiePointer = pc + 4 - *(ULONG*)(pc + 4);
00104     Fde->PcBegin = *(ULONG*)(pc + 8);
00105     Fde->PcRange = *(ULONG*)(pc + 12);
00106     pc += 16;
00107     pc += DwDecodeUleb128(&Fde->AugLength, pc);
00108     Fde->AugData = pc;
00109     Fde->Instructions = Fde->AugData + Fde->AugLength;
00110 
00111     return Fde->Length + 4;
00112 }
00113 
00114 unsigned long
00115 DwExecIntruction(PDW2CFSTATE State, char *pc)
00116 {
00117     unsigned char Code;
00118     unsigned long Length;
00119     unsigned long PrevFramePtr = State->FramePtr;
00120 
00121     State->Scope = 0;
00122     State->IsUwop = 0;
00123     State->Code = Code = *pc;
00124     Length = 1;
00125     if ((Code & 0xc0) == DW_CFA_advance_loc)
00126     {
00127         State->Code = DW_CFA_advance_loc;
00128         State->Location += Code & 0x3f;
00129     }
00130     else if ((Code & 0xc0) == DW_CFA_offset)
00131     {
00132         State->Code = DW_CFA_offset;
00133         State->Reg = Code & 0x3f;
00134         Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + 1);
00135         State->Offset *= 8; // fixme data alignment
00136         State->IsUwop = 1;
00137     }
00138     else if ((Code & 0xc0) == DW_CFA_restore)
00139     {
00140         State->Code = DW_CFA_restore;
00141         State->Reg = Code & 0x3f;
00142     }
00143     else switch (Code)
00144     {
00145         case DW_CFA_nop:
00146             break;
00147         case DW_CFA_set_loc:
00148             Length = 9; // address
00149             State->Location = *(DWORD*)(pc + 1);
00150             break;
00151         case DW_CFA_advance_loc1:
00152             Length = 2;
00153             State->Location += pc[1];
00154             break;
00155         case DW_CFA_advance_loc2:
00156             Length = 3;
00157 //            printf("Found a DW_CFA_advance_loc2 : 0x%lx ->", *(WORD*)(pc + 1));
00158             State->Location += *(WORD*)(pc + 1);
00159 //            printf(" 0x%lx\n", State->Location);
00160             break;
00161         case DW_CFA_advance_loc4:
00162             Length = 5;
00163 //            printf("Found a DW_CFA_advance_loc4 : 0x%lx ->", *(DWORD*)(pc + 1));
00164             State->Location += *(DWORD*)(pc + 1);
00165 //            printf(" 0x%lx\n", State->Location);
00166             break;
00167         case DW_CFA_offset_extended:
00168             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00169             Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + Length);
00170             State->IsUwop = 1;
00171             break;
00172         case DW_CFA_offset_extended_sf:
00173             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00174             Length += DwDecodeSleb128(&State->Offset, pc + Length);
00175             State->IsUwop = 1;
00176             break;
00177         case DW_CFA_restore_extended:
00178             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00179             break;
00180         case DW_CFA_undefined:
00181             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00182             break;
00183         case DW_CFA_same_value:
00184             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00185             break;
00186         case DW_CFA_register:
00187             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00188             Length += DwDecodeUleb128(&State->Reg2, pc + Length);
00189             break;
00190         case DW_CFA_remember_state:
00191             break;
00192         case DW_CFA_restore_state:
00193             break;
00194         case DW_CFA_def_cfa:
00195             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00196             Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length);
00197             State->IsUwop = 1;
00198             break;
00199         case DW_CFA_def_cfa_register:
00200             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00201             break;
00202         case DW_CFA_def_cfa_offset:
00203             Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length);
00204             State->IsUwop = 1;
00205             break;
00206         case DW_CFA_def_cfa_sf:
00207             Length += DwDecodeUleb128(&State->Reg, pc + Length);
00208             Length += DwDecodeSleb128(&State->FramePtr, pc + Length);
00209             State->FramePtr *= 8; // data alignment
00210             State->IsUwop = 1;
00211             break;
00212         case DW_CFA_GNU_args_size:
00213         {
00214             unsigned long argsize;
00215             printf("Warning, DW_CFA_GNU_args_size is unimplemented\n");
00216             Length += DwDecodeUleb128(&argsize, pc + Length);
00217             break;
00218         }
00219         /* PSEH */
00220         case 0x21:
00221         {
00222             unsigned long SehType;
00223 
00224 //            printf("found 0x21 at %lx\n", State->Location);
00225             Length += DwDecodeUleb128(&SehType, pc + Length);
00226             switch (SehType)
00227             {
00228                 case 1: /* Begin Try */
00229                     State->TryLevel++;
00230                     if (State->TryLevel >= 20)
00231                     {
00232                         printf("WTF? Trylevel of 20 exceeded...\n");
00233                         exit(1);
00234                     }
00235                     State->SehBlock[State->TryLevel-1].BeginTry = State->Location;
00236 //                    printf("Found begintry at 0x%lx\n", State->Location);
00237                     State->Scope = 1;
00238                     break;
00239 
00240                 case 2: /* End Try */
00241                     State->SehBlock[State->TryLevel-1].EndTry = State->Location;
00242                     State->Scope = 2;
00243                     break;
00244 
00245                 case 3: /* Jump target */
00246                     State->SehBlock[State->TryLevel-1].Target = State->Location;
00247                     State->Scope = 3;
00248                     break;
00249 
00250                 case 4: /* SEH End */
00251                     if (State->TryLevel == 20)
00252                     {
00253                         printf("Ooops, end of SEH with trylevel at 0!\n");
00254                         exit(1);
00255                     }
00256                     State->SehBlock[State->TryLevel-1].End = State->Location;
00257                     State->TryLevel--;
00258                     State->cScopes++;
00259                     State->Scope = 0;
00260                     break;
00261 
00262                 case 5: /* Constant filter */
00263                 {
00264                     unsigned long value;
00265                     Length += DwDecodeUleb128(&value, pc + Length);
00266                     State->SehBlock[State->TryLevel-1].Handler = value;
00267 //                     printf("Found a constant filter at 0x%lx\n", State->Location);
00268                     break;
00269                 }
00270 
00271                /* These work differently. We are in a new function.
00272                  * We have to parse a lea opcode to find the adress of
00273                  * the jump target. This is the reference to find the 
00274                  * appropriate C_SCOPE_TABLE. */
00275                 case 6: /* Filter func */
00276 //                    printf("Found a filter func at 0x%lx\n", State->Location);
00277                     break;
00278 
00279                 case 7: /* Finally func */
00280                 {
00281 //                     printf("Found a finally func at 0x%lx\n", State->Location);
00282                     break;
00283                 }
00284 
00285                 default:
00286                     printf("Found unknow PSEH code 0x%lx\n", SehType);
00287                     exit(1);
00288             }
00289             break;
00290         }
00291         default:
00292             fprintf(stderr, "unknown instruction 0x%x at 0x%p\n", Code, pc);
00293             exit(1);
00294     }
00295     
00296     State->FramePtrDiff = State->FramePtr - PrevFramePtr;
00297     DPRINT("@%p: code=%x, Loc=%lx, offset=%lx, reg=0x%lx:%s\n", 
00298         (void*)((ULONG)pc - g_ehframep), Code, State->Location, State->Offset, State->Reg, regs[State->Reg].name);
00299     return Length;
00300 }
00301 
00304 ULONG
00305 StoreUnwindCodes(PUNWIND_INFO Info, PDW2CFSTATE State, ULONG FunctionStart)
00306 {
00307     ULONG cCodes = 0;
00308     ULONG AllocSize;
00309     UNWIND_CODE Code[3];
00310     int i;
00311 
00312     Code[0].CodeOffset = State->Location - FunctionStart;
00313 
00314     switch (State->Code)
00315     {
00316         case DW_CFA_offset:
00317         case DW_CFA_offset_extended:
00318             // save register at offset
00319             Code[0].OpInfo = regs[State->Reg].regnt;
00320             if (State->Offset <= 0x7FFF8)
00321             {
00322                 Code[0].UnwindOp = UWOP_SAVE_NONVOL;
00323                 Code[1].FrameOffset = State->Offset / 8;
00324                 cCodes = 2;
00325             }
00326             else
00327             {
00328                 Code[0].UnwindOp = UWOP_SAVE_NONVOL_FAR;
00329                 Code[1].FrameOffset = (State->Offset / 8);
00330                 Code[2].FrameOffset = (State->Offset / 8) >> 16;
00331                 cCodes = 3;
00332             }
00333             break;
00334 
00335         case DW_CFA_def_cfa:
00336         //case DW_CFA_def_cfa_register:
00337         case DW_CFA_def_cfa_offset:
00338         case DW_CFA_def_cfa_sf:
00339             AllocSize = State->FramePtrDiff;
00340             if (AllocSize <= 128)
00341             {
00342                 Code[0].UnwindOp = UWOP_ALLOC_SMALL;
00343                 Code[0].OpInfo = (AllocSize / 8) - 1;
00344                 cCodes = 1;
00345             }
00346             else if (AllocSize <= 0x7FFF8)
00347             {
00348                 Code[0].UnwindOp = UWOP_ALLOC_LARGE;
00349                 Code[0].OpInfo = 0;
00350                 Code[1].FrameOffset = AllocSize / 8;
00351                 cCodes = 2;
00352             }
00353             else // if (AllocSize > 0x7FFF8)
00354             {
00355                 Code[0].UnwindOp = UWOP_ALLOC_LARGE;
00356                 Code[0].OpInfo = 1;
00357                 Code[1].FrameOffset = (USHORT)AllocSize;
00358                 Code[2].FrameOffset = (USHORT)(AllocSize >> 16);
00359                 cCodes = 3;
00360             }
00361             break;
00362     }
00363 
00364     if (Info)
00365     {
00366         /* Move old codes */
00367         for (i = Info->CountOfCodes - 1; i >= 0; i--)
00368         {
00369             Info->UnwindCode[i + cCodes] = Info->UnwindCode[i];
00370         }
00371 
00372         /* Copy new codes */
00373         for (i = 0; i < cCodes; i++)
00374         {
00375             Info->UnwindCode[i] = Code[i];
00376         }
00377 
00378         Info->CountOfCodes += cCodes;
00379     }
00380 
00381     return cCodes;
00382 }
00383 
00384 #define GetxdataSize(cFuncs, cUWOP, cScopes) \
00385     ( cFuncs * (sizeof(UNWIND_INFO) + 2 + 4 + 4) \
00386     + cUWOP * sizeof(UNWIND_CODE) \
00387     + cScopes * sizeof(C_SCOPE_TABLE_ENTRY) )
00388 
00389 ULONG
00390 StoreUnwindInfo(PUNWIND_INFO Info, PDW2FDE pFde, ULONG FunctionStart)
00391 {
00392     ULONG cbSize;
00393     DW2CFSTATE State;
00394     char *pInst;
00395     ULONG c;
00396     DW2CIE Cie;
00397 
00398     cbSize = 4; // sizeof(UNWIND_INFO);
00399     Info->Version = 1;
00400     Info->Flags = 0;
00401     Info->SizeOfProlog = 0;
00402     Info->CountOfCodes = 0;
00403     Info->FrameRegister = 0;
00404     Info->FrameOffset = 0;
00405 
00406     /* Decode the CIE */
00407     DwDecodeCie(&Cie, pFde->CiePointer);
00408 
00409     /* Initialize state */
00410     State.Location = FunctionStart;
00411     State.FramePtr = 0;
00412     State.TryLevel = 0;
00413     State.cScopes = 0;
00414 
00415     /* Parse the CIE's initial instructions */
00416     pInst = Cie.Instructions;
00417     while (pInst < Cie.Next)
00418     {
00419         pInst += DwExecIntruction(&State, pInst);
00420     }
00421 
00422     /* Parse the FDE instructions */
00423     pInst = pFde->Instructions;
00424     while (pInst < pFde->Next)
00425     {
00426         pInst += DwExecIntruction(&State, pInst);
00427 
00428         if (State.IsUwop)
00429         {
00430             c = StoreUnwindCodes(Info, &State, FunctionStart);
00431             cbSize += c * sizeof(UNWIND_CODE);
00432             Info->SizeOfProlog = State.Location - FunctionStart;
00433         }
00434     }
00435     cbSize = ROUND_UP(cbSize, 4);
00436 
00437     /* Do we have scope table to write? */
00438     if (State.cScopes > 0)
00439     {
00440         unsigned long i;
00441         ULONG *pExceptionHandler;
00442         PC_SCOPE_TABLE pScopeTable;
00443 
00444         /* Set flag for exception handler */ 
00445         Info->Flags |= UNW_FLAG_EHANDLER;
00446 
00447         /* Store address of handler and number of scope tables */
00448         pExceptionHandler = (ULONG*)((char*)Info + cbSize);
00449         // HACK for testing purpose
00450         *pExceptionHandler = FunctionStart; // _C_specific_handler
00451 
00452         pScopeTable = (PC_SCOPE_TABLE)(pExceptionHandler + 1);
00453         pScopeTable->NumEntries = State.cScopes;
00454 
00455         /* Store the scope table entries */
00456         for (i = 0; i < State.cScopes; i++)
00457         {
00458             pScopeTable->Entry[i].Begin = State.SehBlock[i].BeginTry;
00459             pScopeTable->Entry[i].End = State.SehBlock[i].EndTry;
00460             pScopeTable->Entry[i].Handler = 1;//State.SehBlock[i].Handler;
00461             pScopeTable->Entry[i].Target = State.SehBlock[i].Target;
00462         }
00463         
00464         /* Update size */
00465         cbSize += 8 + State.cScopes * sizeof(C_SCOPE_TABLE_ENTRY);
00466     }
00467 
00468     return cbSize;
00469 }
00470 
00471 void
00472 CountUnwindData(PFILE_INFO File)
00473 {
00474     DW2CIEFDE *p;
00475     DW2FDE Fde;
00476     char *pInst, *pmax;
00477     DW2CFSTATE State;
00478 
00479     File->cFuncs = 0;
00480     File->cScopes = 0;
00481     File->cUWOP = 0;
00482     State.FramePtr = 0;
00483     State.TryLevel = 0;
00484 
00485     p = File->eh_frame.p;
00486     pmax = (char*)p + File->eh_frame.psh->Misc.VirtualSize;
00487     for (; p->Length && (char*)p < pmax; p = NextCIE(p))
00488     {
00489         /* Is this an FDE? */
00490         if (p->CiePointer != 0)
00491         {
00492             File->cFuncs++;
00493             DwDecodeFde(&Fde, (char*)p);
00494 
00495             pInst = Fde.Instructions;
00496             while (pInst < Fde.Next)
00497             {
00498                 pInst += DwExecIntruction(&State, pInst);
00499                 File->cUWOP += StoreUnwindCodes(NULL, &State, 0);
00500                 File->cScopes += State.Scope ? 1 : 0;
00501             }
00502         }
00503     }
00504 
00505     return;
00506 }
00507 
00508 int CompFunc(const void *p1, const void *p2)
00509 {
00510     PRUNTIME_FUNCTION prf1 = (void*)p1, prf2 = (void*)p2;
00511     return (prf1->FunctionStart > prf2->FunctionStart ? 1 : -1);
00512 }
00513 
00514 void
00515 GeneratePData(PFILE_INFO File)
00516 {
00517     DW2CIEFDE *p;
00518     DW2FDE Fde;
00519     PIMAGE_DATA_DIRECTORY Dir;
00520     ULONG i, Offset;
00521     void * eh_frame;
00522     PRUNTIME_FUNCTION pdata;
00523     ULONG xdata_va;
00524     char *xdata_p;
00525     ULONG cbSize;
00526     PIMAGE_SECTION_HEADER pshp, pshx;
00527     ULONG FileAlignment;
00528     char *pmax;
00529 
00530     FileAlignment = File->OptionalHeader->FileAlignment;
00531 
00532     /* Get pointer to eh_frame section */
00533     eh_frame = File->eh_frame.p;
00534     g_ehframep = (ULONG)eh_frame;
00535 
00536     /* Get sizes */
00537     CountUnwindData(File);
00538 //    printf("cFuncs = %ld, cUWOPS = %ld, cScopes = %ld\n", 
00539 //        File->cFuncs, File->cUWOP, File->cScopes);
00540 
00541     /* Initialize section header for .pdata */
00542     i = File->pdata.idx = File->UsedSections;
00543     pshp = File->pdata.psh = &File->NewSectionHeaders[i];
00544     memcpy(pshp->Name, ".pdata", 7);
00545     pshp->Misc.VirtualSize = (File->cFuncs + 1) * sizeof(RUNTIME_FUNCTION);
00546     pshp->VirtualAddress = File->NewSectionHeaders[i - 1].VirtualAddress +
00547                            File->NewSectionHeaders[i - 1].SizeOfRawData;
00548     pshp->SizeOfRawData = ROUND_UP(pshp->Misc.VirtualSize, FileAlignment);
00549     pshp->PointerToRawData = File->NewSectionHeaders[i - 1].PointerToRawData +
00550                            File->NewSectionHeaders[i - 1].SizeOfRawData;
00551     pshp->PointerToRelocations = 0;
00552     pshp->PointerToLinenumbers = 0;
00553     pshp->NumberOfRelocations = 0;
00554     pshp->NumberOfLinenumbers = 0;
00555     pshp->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_NOT_PAGED |
00556                             IMAGE_SCN_CNT_INITIALIZED_DATA;
00557 
00558     /* Allocate .pdata buffer */
00559     pdata = File->pdata.p = malloc(pshp->SizeOfRawData);
00560     memset(File->pdata.p, 0, pshp->SizeOfRawData);
00561 
00562     /* Init exception data dir */
00563     Dir = &File->OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
00564     Dir->VirtualAddress = pshp->VirtualAddress;
00565     Dir->Size = pshp->Misc.VirtualSize;
00566 
00567     /* Initialize section header for .xdata */
00568     File->xdata.idx = File->pdata.idx + 1;
00569     pshx = File->xdata.psh = &File->NewSectionHeaders[File->xdata.idx];
00570     memcpy(pshx->Name, ".xdata", 7);
00571     pshx->Misc.VirtualSize = GetxdataSize(File->cFuncs, File->cUWOP, File->cScopes);
00572     pshx->VirtualAddress = pshp->VirtualAddress + pshp->SizeOfRawData;
00573     pshx->SizeOfRawData = ROUND_UP(pshx->Misc.VirtualSize, FileAlignment);
00574     pshx->PointerToRawData = pshp->PointerToRawData + pshp->SizeOfRawData;
00575     pshx->PointerToRelocations = 0;
00576     pshx->PointerToLinenumbers = 0;
00577     pshx->NumberOfRelocations = 0;
00578     pshx->NumberOfLinenumbers = 0;
00579     pshx->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_NOT_PAGED |
00580                             IMAGE_SCN_CNT_INITIALIZED_DATA;
00581 
00582     /* Allocate .xdata buffer */
00583     File->xdata.p = malloc(pshx->SizeOfRawData);
00584     memset(File->xdata.p, 0, pshx->SizeOfRawData);
00585 
00586     i = 0;
00587     Offset = File->eh_frame.psh->VirtualAddress;
00588     xdata_va = pshx->VirtualAddress;
00589     xdata_p = File->xdata.p;
00590     pmax = (char*)eh_frame + File->eh_frame.psh->Misc.VirtualSize - 100;
00591 
00592     for (p = eh_frame; p->Length && (char*)p < pmax; p = NextCIE(p))
00593     {
00594         /* Is this an FDE? */
00595         if (p->CiePointer != 0)
00596         {
00597             DwDecodeFde(&Fde, (char*)p);
00598             pdata[i].FunctionStart = Offset + 8 + Fde.PcBegin;
00599             pdata[i].FunctionEnd = pdata[i].FunctionStart + Fde.PcRange;
00600             pdata[i].UnwindInfo = xdata_va;
00601 
00602 //            printf("%ld: RUNTIME_FUNCTION: {0x%lx, 0x%lx, 0x%lx}\n", i, pdata[i].FunctionStart, pdata[i].FunctionEnd, pdata[i].UnwindInfo);
00603 
00604             cbSize = StoreUnwindInfo((void*)xdata_p, &Fde, pdata[i].FunctionStart);
00605             xdata_va += cbSize;
00606             xdata_p += cbSize;
00607             i++;
00608         }
00609         Offset += 4 + p->Length;
00610     }
00611 
00612     /* Sort the RUNTIME_FUNCTIONS */
00613     qsort(pdata, i, sizeof(RUNTIME_FUNCTION), CompFunc);
00614 
00615 }
00616 
00620 WORD
00621 CalculateChecksum(DWORD Start, void *pFile, ULONG cbSize)
00622 {
00623     WORD *Ptr = pFile;
00624     DWORD i;
00625     DWORD checksum = Start;
00626 
00627     for (i = 0; i < (cbSize + 1) / sizeof(WORD); i++)
00628     {
00629         checksum += Ptr[i];
00630         checksum = (checksum + (checksum >> 16)) & 0xffff;
00631     }
00632 
00633     return checksum ;
00634 }
00635 
00636 void
00637 WriteOutFile(FILE *handle, PFILE_INFO File)
00638 {
00639     int ret, Size, Pos = 0;
00640     DWORD CheckSum;
00641     ULONG i, Alignment;
00642 
00643     Alignment = File->OptionalHeader->FileAlignment;
00644 
00645     /* Update section count */
00646     File->FileHeader->NumberOfSections = File->UsedSections + 2; // FIXME!!!
00647 
00648     /* Update SizeOfImage */
00649     Size = File->xdata.psh->VirtualAddress
00650            + File->xdata.psh->SizeOfRawData;
00651     File->OptionalHeader->SizeOfImage = Size;
00652 
00653     /* Recalculate checksum */
00654     CheckSum = CalculateChecksum(0, File->FilePtr, File->HeaderSize);
00655     for (i = 0; i < File->AllSections; i++)
00656     {
00657         if (File->UseSection[i])
00658         {
00659             Size = File->SectionHeaders[i].SizeOfRawData;
00660             if (Size)
00661             {
00662                 void *p;
00663                 p = File->FilePtr + File->SectionHeaders[i].PointerToRawData;
00664                 CheckSum = CalculateChecksum(CheckSum, p, Size);
00665             }
00666         }
00667     }
00668     Size = File->pdata.psh->Misc.VirtualSize;
00669     CheckSum = CalculateChecksum(CheckSum, File->pdata.p, Size);
00670     Size = File->xdata.psh->Misc.VirtualSize;
00671     CheckSum = CalculateChecksum(CheckSum, File->xdata.p, Size);
00672     CheckSum += File->HeaderSize;
00673     CheckSum += File->pdata.psh->Misc.VirtualSize;
00674     CheckSum += File->xdata.psh->Misc.VirtualSize;
00675     File->OptionalHeader->CheckSum = CheckSum;
00676 
00677     /* Write file header */
00678     Size = File->HeaderSize;
00679     ret = fwrite(File->DosHeader, 1, Size, handle);
00680     Pos = Size;
00681 
00682     /* Write Section headers */
00683     Size = File->NewSectionHeaderSize;
00684     ret = fwrite(File->NewSectionHeaders, 1, Size, handle);
00685     Pos += Size;
00686 
00687     /* Fill up to next alignement */
00688     Size = ROUND_UP(Pos, Alignment) - Pos;
00689     ret = fwrite(File->AlignBuf, 1, Size, handle);
00690     Pos += Size;
00691 
00692     /* Write sections */
00693     for (i = 0; i < File->AllSections; i++)
00694     {
00695         if (File->UseSection[i])
00696         {
00697             void *p;
00698             Size = File->SectionHeaders[i].SizeOfRawData;
00699             if (Size)
00700             {
00701                 p = File->FilePtr + File->SectionHeaders[i].PointerToRawData;
00702                 ret = fwrite(p, 1, Size, handle);
00703                 Pos += Size;
00704             }
00705         }
00706     }
00707 
00708     /* Write .pdata section */
00709     Size = File->pdata.psh->SizeOfRawData;
00710     ret = fwrite(File->pdata.p, 1, Size, handle);
00711     Pos += Size;
00712 
00713     /* Write .xdata section */
00714     Size = File->xdata.psh->SizeOfRawData;
00715     ret = fwrite(File->xdata.p, 1, Size, handle);
00716     Pos += Size;
00717 
00718 }
00719 
00720 
00721 int
00722 ParsePEHeaders(PFILE_INFO File)
00723 {
00724     DWORD OldChecksum, Checksum;
00725     ULONG Alignment, CurrentPos;
00726     int i, j;
00727 
00728     /* Check if MZ header exists  */
00729     File->DosHeader = (PIMAGE_DOS_HEADER)File->FilePtr;
00730     if ((File->DosHeader->e_magic != IMAGE_DOS_MAGIC) || 
00731         (File->DosHeader->e_lfanew == 0L))
00732     {
00733         perror("Input file is not a PE image.\n");
00734         return -1;
00735     }
00736 
00737     /* Locate PE file header  */
00738     File->FileHeader = (PIMAGE_FILE_HEADER)(File->FilePtr + 
00739                                File->DosHeader->e_lfanew + sizeof(ULONG));
00740 
00741     /* Check for x64 image */
00742     if (File->FileHeader->Machine != IMAGE_FILE_MACHINE_AMD64)
00743     {
00744         perror("Input file is not an x64 image.\n");
00745         return -1;
00746     }
00747 
00748     /* Locate optional header */
00749     File->OptionalHeader = (PIMAGE_OPTIONAL_HEADER64)(File->FileHeader + 1);
00750 
00751     /* Check if checksum is correct */
00752     OldChecksum = File->OptionalHeader->CheckSum;
00753     File->OptionalHeader->CheckSum = 0;
00754     Checksum = CalculateChecksum(0, File->FilePtr, File->cbInFileSize);
00755     Checksum += File->cbInFileSize;
00756     if ((Checksum & 0xffff) != (OldChecksum & 0xffff))
00757     {
00758         fprintf(stderr, "Input file has incorrect PE checksum: 0x%lx (calculated: 0x%lx)\n",
00759             OldChecksum, Checksum);
00760 //        return 0;
00761     }
00762 
00763     /* Locate PE section headers  */
00764     File->SectionHeaders = (PIMAGE_SECTION_HEADER)((char*)File->OptionalHeader
00765                            + File->FileHeader->SizeOfOptionalHeader);
00766 
00767     File->HeaderSize = File->DosHeader->e_lfanew
00768                        + sizeof(ULONG)
00769                        + sizeof(IMAGE_FILE_HEADER)
00770                        + File->FileHeader->SizeOfOptionalHeader;
00771 
00772     if (!File->FileHeader->PointerToSymbolTable)
00773     {
00774         fprintf(stderr, "No symbol table.\n");
00775         return -1;
00776     }
00777 
00778     /* Create some shortcuts */
00779     File->ImageBase = File->OptionalHeader->ImageBase;
00780     File->Symbols = File->FilePtr + File->FileHeader->PointerToSymbolTable;
00781     File->Strings = (char*)File->Symbols + File->FileHeader->NumberOfSymbols * 18;
00782 
00783     /* Check section names */
00784     File->AllSections = File->FileHeader->NumberOfSections;
00785     Alignment = File->OptionalHeader->FileAlignment;
00786     File->NewSectionHeaders = malloc((File->AllSections+2) * sizeof(IMAGE_SECTION_HEADER));
00787     File->UsedSections = 0;
00788     File->eh_frame.idx = -1;
00789 
00790     /* Allocate array of chars, specifiying wheter to copy the section */
00791     File->UseSection = malloc(File->AllSections);
00792 
00793     for (i = 0; i < File->AllSections; i++)
00794     {
00795         char *pName = (char*)File->SectionHeaders[i].Name;
00796         File->UseSection[i] = 1;
00797 
00798         /* Check for long name */
00799         if (pName[0] == '/')
00800         {
00801             unsigned long index = strtoul(pName+1, 0, 10);
00802             pName = File->Strings + index;
00803             
00804             // Hack, simply remove all sections with long names
00805             File->UseSection[i] = 0;
00806         }
00807 
00808         /* Chek if we have the eh_frame section */
00809         if (strcmp(pName, ".eh_frame") == 0)
00810         {
00811             File->eh_frame.psh = &File->SectionHeaders[i];
00812             File->eh_frame.idx = i;
00813             File->eh_frame.p = File->FilePtr + File->eh_frame.psh->PointerToRawData;
00814         }
00815         
00816         /* Increase number of used sections */
00817         if (File->UseSection[i])
00818             File->UsedSections = i+1;
00819 
00820     }
00821 
00822     /* This is the actual size of the new section headers */
00823     File->NewSectionHeaderSize = 
00824         (File->UsedSections+2) * sizeof(IMAGE_SECTION_HEADER);
00825 
00826     /* Calculate the position to start writing the sections to */
00827     CurrentPos = File->HeaderSize + File->NewSectionHeaderSize;
00828     CurrentPos = ROUND_UP(CurrentPos, Alignment);
00829 
00830     /* Create new section headers */
00831     for (i = 0, j = 0; i < File->UsedSections; i++)
00832     {
00833         /* Copy section header */
00834         File->NewSectionHeaders[j] = File->SectionHeaders[i];
00835 
00836         /* Shall we strip the section? */
00837         if (File->UseSection[i] == 0)
00838         {
00839             /* Make it a bss section */
00840             File->NewSectionHeaders[j].PointerToRawData = 0;
00841             File->NewSectionHeaders[j].SizeOfRawData = 0;
00842             File->NewSectionHeaders[j].Characteristics = 0xC0500080;
00843         }
00844 
00845         /* Fix Offset into File */
00846         File->NewSectionHeaders[j].PointerToRawData =
00847               File->NewSectionHeaders[j].PointerToRawData ? CurrentPos : 0;
00848         CurrentPos += File->NewSectionHeaders[j].SizeOfRawData;
00849         j++;
00850     }
00851 
00852     if (File->eh_frame.idx == -1)
00853     {
00854         //fprintf(stderr, "No .eh_frame section found\n");
00855         return 0;
00856     }
00857 
00858     return 1;
00859 }
00860 
00861 int main(int argc, char* argv[])
00862 {
00863     char* pszInFile;
00864     char* pszOutFile;
00865     FILE_INFO File;
00866     FILE* outfile;
00867     int ret;
00868 
00869     if (argc != 3)
00870     {
00871         fprintf(stderr, "Usage: rsym <exefile> <symfile>\n");
00872         exit(1);
00873     }
00874 
00875     pszInFile = convert_path(argv[1]);
00876     pszOutFile = convert_path(argv[2]);
00877 
00878     File.FilePtr = load_file(pszInFile, &File.cbInFileSize);
00879     if (!File.FilePtr)
00880     {
00881         fprintf(stderr, "An error occured loading '%s'\n", pszInFile);
00882         exit(1);
00883     }
00884 
00885     ret = ParsePEHeaders(&File);
00886     if (ret != 1)
00887     {
00888         free(File.FilePtr);
00889         exit(ret == -1 ? 1 : 0);
00890     }
00891 
00892     File.AlignBuf = malloc(File.OptionalHeader->FileAlignment);
00893     memset(File.AlignBuf, 0, File.OptionalHeader->FileAlignment);
00894 
00895     GeneratePData(&File);
00896 
00897     outfile = fopen(pszOutFile, "wb");
00898     if (outfile == NULL)
00899     {
00900         perror("Cannot open output file");
00901         free(File.FilePtr);
00902         exit(1);
00903     }
00904 
00905     WriteOutFile(outfile, &File);
00906 
00907     fclose(outfile);
00908 
00909     return 0;
00910 }

Generated on Sun May 27 2012 04:37:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.