Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrsym64.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
1.7.6.1
|