PAGE ,132 TITLE LDRELOC - SegReloc procedure .xlist include gpfix.inc include kernel.inc include newexe.inc include protect.inc .list ;externFP FatalExit externFP GlobalLock externFP GlobalUnLock externFP Int21Handler externFP IFatalAppExit DataBegin if PMODE32 and ROM externW gdtdsc endif externW f8087 externB fastFP ;externW WinFlags ifndef WINDEBUG externB szUndefDyn endif DataEnd sBegin CODE assumes CS,CODE externNP GetStringPtr externNP FindOrdinal externNP EntProcAddress externNP LoadSegment externNP GetOwner ife ROM and PMODE32 externW gdtdsc endif externNP GetAccessWord externNP DPMIProc DPMICALL MACRO callno mov ax, callno call DPMIProc ENDM ifdef WOW_x86 externNP get_physical_address endif ;-----------------------------------------------------------------------; ; UndefDynlink ; ; If an application has a dynamic link to a loaded library that ; we can't find we fix up to this think. This way the app ; will blow up only if it tries to call the entry point. ; ; Entry: ; ; Returns: ; ; Registers Destroyed: ; ; History: ; Wed 10-May-1989 19:28:50 -by- David N. Weise [davidw] ; Added this nifty comment block! ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc UndefDynlink,, localW foo ; force stack frame cBegin SetKernelDS if KDEBUG cCall GetOwner,<[bp].savedCS> mov es,[bp].savedCS mov bx,[bp].savedIP sub bx,5 krDebugOut DEB_FERROR, "%AX1 #ES:#BX called undefined dynalink" ; kerror ERR_LDNAME,,es,bx else push 0 push ds push dataOffset szUndefDyn cCall IFatalAppExit ;,<0, ds, dataOffset szUndefDyn> endif cEnd ;-----------------------------------------------------------------------; ; SegReloc ; ; ; Entry: ; ; Returns: ; ; Registers Destroyed: ; ; History: ; Thu 25-May-1989 20:16:09 -by- David N. Weise [davidw] ; Removed the special case code for version 1.01 (linker or windows?) that ; If BASE fixup for moveable code segment within a DATA segment (V1.01 only) ; Then force to be PTR fixup. ; ; Wed 10-May-1989 19:28:50 -by- David N. Weise [davidw] ; Added this nifty comment block! ;-----------------------------------------------------------------------; assumes ds, nothing assumes es, nothing ifdef WOW_x86 .386 cProc SegReloc,, else cProc SegReloc,, endif parmW hexe parmD prleinfo parmW creloc parmD pseginfo parmW fdataseg parmW fh localW himpexe localW hseg localW pseg localW hifileoff localW lofileoff localV rlerec, localW fOsfixup ;bool set if a floating-pt osfixup. localW old_access ifdef WOW_x86 localD rover_2 endif cBegin les si, pseginfo mov dx, es:[si].ns_handle ; Get handle to segment mov hseg, dx test dl, GA_FIXED jnz sr_nolock cCall GlobalLock, sr_nolock: mov pseg, dx ;; WOW - refer to original win 3.1 code on \\pucus, there were too many ifdefs ;; in the code. It would have become unreadable to add any more. mattfe ;; mar 29 93 ;;; Restored the "too many ifdef's" because this code doesn't just ;;; assemble right for all our platform permutations. I also tried to make it ;;; readable by adding comments. -neilsa ;; For 386 version of WOW we use selector 23h to write to vdm memory without ;; worrying about setting up a selector. ifndef WOW ;------------------Original win31 source-------------------------------- ife PMODE32 cCall GetAccessWord, else .386p lar eax, edx shr eax, 8 .286 endif mov old_access, ax test al, DSC_CODE_BIT jz short access_ok mov al, DSC_PRESENT+DSC_DATA mov bx, dx push ds if ROM and PMODE32 SetKernelDS mov ds, gdtdsc UnsetKernelDS else mov ds, gdtdsc endif and bl, not 7 mov word ptr ds:[bx].dsc_access, ax if 0 ;;ROM and KDEBUG call CheckROMSelector endif pop ds else ; ******** WOW ADDED SOURCE ifdef WOW_x86 ;------------------WOW source for X86 platforms------------------------- ife PMODE32 cCall GetAccessWord, mov old_access, ax test al, DSC_CODE_BIT jz short access_ok mov al, DSC_PRESENT+DSC_DATA mov bx, dx mov cx,ax DPMICALL 0009h endif; PMODE32 else; WOW_x86 ;------------------WOW source for NON-X86 platforms--------------------- ife PMODE32 cCall GetAccessWord, else .386p lar eax, edx shr eax, 8 .286 endif mov old_access, ax test al, DSC_CODE_BIT jz short access_ok mov al, DSC_PRESENT+DSC_DATA mov bx, dx ife PMODE32 mov cx,ax DPMICALL 0009h else push ds mov ds, gdtdsc and bl, not 7 mov word ptr ds:[bx].dsc_access, ax pop ds endif; PMODE32 endif; WOW_x86 endif; ******** WOW ADDED SOURCE ;----------------------End of WOW changes------------------------------- access_ok: mov fOsfixup,0 ; set flag initially to false. mov si,OFF_prleinfo mov ax,SEG_prleinfo or ax,ax jz @F jmp srloop1 @@: xor dx,dx xor cx,cx mov bx,fh mov ax,4201h DOSCALL ; Get current file offset jnc @F krDebugOut , "Get file offset failed" ; Debug_Out "Get file offset failed." jmps srbadrle1 @@: mov hifileoff,dx mov lofileoff,ax srloop: mov ax,SEG_prleinfo or ax,ax ; Did we get a handle to RLE? jnz srloop1 ; No, continue mov cx,hifileoff ; OPTIMIZE this to read in more mov dx,lofileoff ; than one record at a time!! mov bx,fh mov ax,4200h DOSCALL ; Seek to current offset jnc @F krDebugOut DEB_ERROR, "Seek failed." ; Debug_Out "Seek failed." srbadrle1: jmp srbadrle @@: push ss pop ds lea dx,rlerec mov cx,SIZE NEW_RLC add lofileoff,cx adc hifileoff,0 mov ah,3Fh DOSCALL ; Read next record jnc @F krDebugOut DEB_ERROR, "Read record failed" ; Debug_Out "Read record failed" jmps srbadrle1 @@: cmp ax,cx je @F krDebugOut DEB_ERROR, "Read #AX bytes, expecting #CX." jmp srbadrle srosfijmp: jmp srosfixup @@: mov ax,ss mov si,dx srloop1: mov ds,ax mov ax,ds:[si].nr_proc mov cx,NRRTYP and cl,ds:[si].nr_flags or cx,cx jz srint ; Internal Reference cmp cl,OSFIXUP je srosfijmp .errnz NRRINT mov bx,ds:[si].nr_mod ; Here if Import Ordinal/Name sub bx,1 jnc @F krDebugOut DEB_ERROR, "Zero import module." jmps srbadrle @@: shl bx,1 mov es,hexe add bx,es:[ne_modtab] mov bx,es:[bx] mov himpexe,bx or bx,bx jz srbadimp dec cx ; (sleaze) if cx == 2, then Import Name jz srrord ; else Import Ordinal .errnz NRRORD - 1 .errnz NRRNAM - 2 srrnam: ; Convert name to ordinal cCall GetStringPtr, cCall FindOrdinal, mov bx,himpexe or ax,ax jz srbadimp srrord: if KDEBUG cCall EntProcAddress,; we do want to RIP for failure else cCall EntProcAddress, endif jcxz srbadimp jmp dorle srbadimp: if kdebug mov dx, hExe mov ax, himpexe krDebugOut , "%dx1 failed implicit link to %ax0" endif mov dx,cs mov ax,codeOFFSET UndefDynlink jmp dorle srbadrle: jmp srfail srdone1: jmp srdone srint: mov dl,NRSTYP ; DL = fixup type and dl,ds:[si].nr_stype mov cl,ds:[si].nr_segno or cx,cx jnz @F krDebugOut DEB_ERROR, "NULL segment in fixup." jmp srbadrle @@: mov bx,hexe cmp cl,ENT_MOVEABLE je srrord mov es,bx mov bx,cx dec bx cmp es:[ne_cseg],bx jnbe @F krDebugOut DEB_ERROR, "Invalid segment in fixup." jmp srbadrle ; Error if invalid segno @@: push ax ; Save offset shl bx,1 mov ax,bx shl bx,1 shl bx,1 add bx,ax ; BX *= 10 .errnz 10 - SIZE NEW_SEG1 add bx,es:[ne_segtab] cmp dl,NRSOFF ; Offset only fixup? je srint2 ; Yes, go do it then (DX ignored then) if ROM test byte ptr es:[bx].ns_flags, NSALLOCED OR NSLOADED else test byte ptr es:[bx].ns_flags, NSALLOCED endif jz srint1 mov ax, es:[bx].ns_handle or ax,ax jnz @F krDebugOut DEB_ERROR, "NULL handle." jmp srbadrle @@: test al,GA_FIXED jnz srint2 HtoS ax mov cx,ax ; for the jcxz below jmps srint2 srbadrlej: jmp srbadrle srint1: int 3 int 3 cCall LoadSegment, srint2: mov dx,ax pop ax or cx,cx jnz @F krDebugOut DEB_ERROR, "Can't load segment." jmp srbadrlej @@: dorle: push ax push dx mov ax,SEG_prleinfo or ax,ax ; Did we get a handle to RLE? jnz @F ; No, continue mov ax,ss ; Assume reading from stack @@: mov ds,ax mov bl,NRSTYP and bl,ds:[si].nr_stype mov cx,NRADD and cl,ds:[si].nr_flags mov di,ds:[si].nr_soff ifdef WOW_x86 .386 ;; WOW selector optimiaztion cCall get_physical_address, shl edx,16 mov dx,ax mov rover_2,edx mov ax,FLAT_SEL mov ds,ax movzx edi,di add edi,edx ; es:edi -> pseg:0 else mov ds, pseg endif pop dx pop ax cmp bl,NRSSEG je srsseg cmp bl,NRSPTR je srsptr cmp bl,NRSOFF je srsoff cmp bl,NRSBYTE je srsbyte krDebugOut DEB_ERROR, "Unknown fixup #BX" ife KDEBUG jmps nextrle endif nextrlenz: ; if NZ at this point, something broke jz nextrle ; jnz srfail jmp srfail nextrle: mov ax,1 add si,SIZE NEW_RLC dec creloc jle srdone2 jmp srloop srdone2:jmp srdone ; Lo-byte fixup chain (always additive) beg_fault_trap srfailGP srsbyte: ifdef WOW_x86 add ds:[edi],al else add ds:[di],al endif jmp nextrle ; Offset fixup chain srsoff: cmp fOsfixup,0 ; is it a floating-pt. osfixup? jnz srsosfixup ; yes, goto special case code. mov dx, ax ; fall through into segment fixup ; Segment fixup chain srsseg: jcxz srsseg1 ifdef WOW_x86 add ds:[edi],dx else add ds:[di],dx endif jmp nextrle srsseg1: or cx, -1 srsseg2: mov bx,dx ifdef WOW_x86 xchg word ptr ds:[edi],bx movzx edi,bx add edi,rover_2 else xchg ds:[di],bx mov di,bx endif inc bx loopnz srsseg2 ; if CX == 0, we're broken jmp nextrlenz ; Segment:Offset fixup chain srsptr: jcxz srsptr1 ifdef WOW_x86 add word ptr ds:[edi],ax add word ptr ds:[edi+2],dx else add ds:[di],ax add ds:[di+2],dx endif jmp nextrle srsptr1: or cx, -1 srsptr2: mov bx,ax ifdef WOW_x86 xchg word ptr ds:[edi],bx mov word ptr ds:[edi+2],dx movzx edi,bx add edi,rover_2 else xchg ds:[di],bx mov ds:[di+2],dx mov di,bx endif inc bx loopnz srsptr2 jmp nextrlenz ; osfixup for floating-point instructions fINT EQU 0CDH fFWAIT EQU 09BH fESCAPE EQU 0D8H fFNOP EQU 090H fES EQU 026H fCS EQU 02Eh fSS EQU 036h fDS EQU 03Eh BEGINT EQU 034h FIARQQ EQU (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fDS) FISRQQ EQU (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fSS) FICRQQ EQU (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fCS) FIERQQ EQU (fINT + 256*(BEGINT + 8)) - (fFWAIT + 256*fES) FIDRQQ EQU (fINT + 256*(BEGINT + 0)) - (fFWAIT + 256*fESCAPE) FIWRQQ EQU (fINT + 256*(BEGINT + 9)) - (fFNOP + 256*fFWAIT) FJARQQ EQU 256*(((0 shl 6) or (fESCAPE and 03Fh)) - fESCAPE) FJSRQQ EQU 256*(((1 shl 6) or (fESCAPE and 03Fh)) - fESCAPE) FJCRQQ EQU 256*(((2 shl 6) or (fESCAPE and 03Fh)) - fESCAPE) osfixuptbl label word ; table has 12 entries - six for int DW FIARQQ, FJARQQ DW FISRQQ, FJSRQQ DW FICRQQ, FJCRQQ DW FIERQQ, 0h DW FIDRQQ, 0h DW FIWRQQ, 0h osfixuptbllen = $-osfixuptbl ; six to convert FWAIT to NOP DW fFNOP - fFWAIT, 0 DW fFNOP - fFWAIT, 0 DW fFNOP - fFWAIT, 0 DW fFNOP - fFWAIT, 0 DW fFNOP - fFWAIT, 0 DW FIWRQQ, 0h ; leave this one in for emulator srsosfixup: ifdef WOW_x86 add word ptr ds:[edi][0],ax add word ptr ds:[edi][1],dx else add ds:[di][0],ax add ds:[di][1],dx endif mov fOsfixup,0 ; clear flag for next record. jmp nextrle end_fault_trap srfailGP: ; fault_fix_stack pop ax pop dx krDebugOut DEB_ERROR, "Fault in SegReloc #AX #DX" srfail: if KDEBUG mov bx,hexe ; xor bx,bx krDebugOut DEB_ERROR, "%BX1 has invalid relocation record" ; kerror ERR_LDRELOC,,es,bx endif xor ax,ax jmps srdone ; OSFIXUPs for floating-point instructions. ; ; The fixup is applied by adding the first word (ax) to the ; coprocessor intruction, and for fixups 1-3 also adding the ; second word (dx) to the instruction+1. Generalize, by having ; dx=0 for fixups 4-6 and always adding dx to instruction+1. ; ; Note: the relocation type is marked NRSOFF by the linker, ; but we must apply these fixups differently. Here we know ; it is an osfixup, so set the flag fOsfixup so that later ; when we test the type, we can apply the fixup correctly. ; ; 06-Oct-1987. davidhab. ; Wed 10-May-1989 19:28:50 -by- David N. Weise [davidw] ; ; Actually, due to the way the emulator does fwait polling ; of exceptions we must send the NOP FWAIT pairs to the ; emulator even if a math coprocessor is available. srosfixup: mov es,hexe test es:[ne_flags],NEPROT ; OS/2 app jnz srosf_skip ; then never fix up! SetKernelDS es mov bx,ds:[si].nr_mod ; get OSFIXUP id cmp bx,6 ; is it NOP, FWAIT? jz srosfixup1 ; if so always fix up! cmp f8087,94 ; 8087 installed? jnz srosfixup1 ; No, do OSFIXUP processing cmp fastFP,0 je srosf_skip dec bx shl bx, 2 cmp bx, osfixuptbllen jae srosfixup2 add bx, osfixuptbllen jmps fast srosf_skip: jmp nextrle ; Yes, skip OSFIXUP processing srosfixup1: dec bx ; offset into table is (n-1) * 4 shl bx,1 shl bx,1 cmp bx,osfixuptbllen ; Make sure it is within table bounds jae srosfixup2 ; No, bad relocation fast: mov ax,osfixuptbl[bx+0] ; Yes, get relocation value from table mov dx,osfixuptbl[bx+2] ; get second part of fixup mov fOsfixup,1 ; set flag to mark our special type. jmp dorle ; Go apply relocation srosfixup2: jmp srbadrle UnSetKernelDS es srdone: push ax ifndef WOW ;------------------Original win31 source-------------------------------- mov cx, old_access test cl, DSC_CODE_BIT jz short no_reset_access mov bx, pseg push ds if ROM and PMODE32 SetKernelDS mov ds, gdtdsc UnsetKernelDS else mov ds, gdtdsc endif and bl, not 7 mov word ptr ds:[bx].dsc_access, cx if 0 ;;ROM and KDEBUG call CheckROMSelector endif pop ds else ; ******** WOW ADDED SOURCE ifdef WOW_x86 ;------------------WOW source for X86 platforms------------------------- ife PMODE32 mov cx, old_access test cl, DSC_CODE_BIT jz short no_reset_access mov bx, pseg DPMICALL 0009h endif; PMODE32 else; WOW_x86 ;------------------WOW source for NON-X86 platforms--------------------- mov cx, old_access test cl, DSC_CODE_BIT jz short no_reset_access mov bx, pseg ife PMODE32 DPMICALL 0009h else push ds mov ds, gdtdsc and bl, not 7 mov word ptr ds:[bx].dsc_access, cx pop ds endif; PMODE32 endif; WOW_x86 endif; ******** WOW ADDED SOURCE ;----------------------End of WOW changes------------------------------- no_reset_access: mov ax, hseg test al, 1 jnz srdone_nounlock cCall GlobalUnLock, srdone_nounlock: pop ax cEnd sEnd CODE end