EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

reloc.htm
Classes
RELOC
Encodings
RelocEnc
Procedures
RelocCombine
RelocFixup
RelocRelocInBuffer
RelocFixup
RelocResolveImage
RelocResolveObject
RelocSort
RelocUniq

Object RELOC describes one relocation of word, dword or qword memory variable in emitted code.


reloc PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
 INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
 reloc HEAD  ; Start of module interface.
↑ RELOC

Reloc record used internally by EuroAssembler describes one relocation, i.e. a WORD, DWORD or QWORD in emitted code/data which needs to be patched at link-time or at load-time.
RELOC objects are kept in Section.RelocBuffer. Important property of fixup is its .Org which represents offset of the patched word/dword/qword from the beginning of segment.
The member .Section points to section or segment in whose .RelocBuffer are the relocations kept at assembly time. It will be employed at link time for fixing up .Org.

Evolution of reloc origin at assembly time:

Evolution of reloc origin at combine time:

Evolution of reloc origin at link time:

Special reloc type relocDisp8 does not represent a real relocation but only a hint how to decorate the scaled disp8*N in listing.

Example
aData D D 5, 2*D aBssSymbol ; Creates two relocations with origins 4 and 8 in Stm.RelocBuffer. ; They will be patched to OFFSET#aData+4, OFFSET#aData+8 in StmFlush. ; RELOC.Target points to (BSS) segment of aBssSymbol.
RELOC STRUC  ; Relocation record.
.OrgLow   D D ; Origin, i.e. offset of fixed memory object (word/dword/qword)
.OrgHigh  D D ;   relative from the beginning of the segment where the fixed object lies.
.Section  D D ; ^SSS section or segment whose .EmitBuffer contains the fixed object.
.Status   D D ; Relocation properties, see below.
.DispLow  D D ; Target displacement to be added to the fixed object.
.DispHigh D D
.Target   D D ; ^SSS representing section/segment which the target belongs to.
.Frame    D D ; ^SSS representing assumed group/segment address used for addressing the target. 0=use .Target.
        ENDSTRUC RELOC
↑ RelocEnc
Encoding of flags used in RELOC.Status.
relocTypeMask identifies the fundamental, format-independent relocation type.
relocWidthMask specifies if the relocated object is WORD|DWORD|QWORD.
relocExtAttr is used when attribute is applied to an external object, and its evaluation needs to be postponed to the link-time.
relocRelDist specifies an additional distance of the relocated object in 64bit mode. It is nonzero when the relocated DWORD displacement in instruction encoding is followed by immediate value, for instance MOV [MemoryVar],ImmConstant. In this case RIP is not only an address of relocated DWORD displacement+4, but it is must be enlarged by the value in relocRelDist (usually 1,4,5). The corresponding PFCOFF_RELOCATION.Type is then 0x0005,0x0008,0x0009.
Some other linkers keep PFCOFF_RELOCATION.Type at fixed value 0x0004 (IMAGE_REL_AMD64_REL32) and decrement the relocated object in COFF text by 1,4,5 instead.
€ASM could also achieve this with decrementing RELOC.Disp by 1,4,5 and having the type fixed at 0x0004, but I preferred keeping the relocated DWORD unchanged.
                             ; Fundamental relocation types.
relocPara      = 0x0000_0001 ; Base relocation of paragraph address related to ImageBase.
relocAbsVA     = 0x0000_0002 ; Absolute relocation of  VA related to .Frame segment/group.
relocAbsRVA    = 0x0000_0004 ; Absolute relocation of RVA related to .Frame segment.
relocRel       = 0x0000_0008 ; Relative relocation of  VA related to rIP.
relocFar       = 0x0000_0010 ; Far absolute relocation (16+16 or 16+32).
relocTypeMask  = 0x0000_0FFF ; Relocation type. Only one flag should be set.
                             ; Correction of RIP-relative relocation.
relocRelDist   = 0x0000_7000 ; Additional distance of RIP-relative relocation in 64bit mode (0..5).
                             ; Evaluation of external symbol attributes postponed to the link time.
relocExtAttr   = 0x000F_0000 ; DictAttr* (0..9) <<16. Synchronized  with sssExtAttr.
                             ; Width of relocated object.
relocWidth16   = 0x0010_0000 ;  WORD in memory is relocated.
relocWidth32   = 0x0020_0000 ; DWORD in memory is relocated.
relocWidth64   = 0x0040_0000 ; QWORD in memory is relocated.
relocWidthMask = relocWidth16|relocWidth32|relocWidth64
                             ; Miscellaneous properties.
relocResolved  = 0x0080_0000 ; This relocation has been already resolved and should be ignored.
relocDisp8N    = 0x7000_0000 ; Disp8*N shift factor 0..6. Valid only when relocDisp8 is set.
relocDisp8     = 0x8000_0000 ; Pseudorelocation, used to decorate dumped listing of Disp8*N (AVX instruction).
  ENDHEAD reloc ; End of module interface.
↑ RelocRelocInBuffer Buffer, Delta
RelocRelocInBuffer will relocate origin of each RELOC record in Buffer by Delta.
Input
Buffer is pointer to BUFFER which should contain zero or more RELOC objects.
Delta is signed integer which will be added to .Org of each RELOC object in the buffer.
Output
The contents of buffer is changed.
Error
-
Invoked by
PfomfLoadDataBlock PfomfLoadModule
RelocRelocInBuffer Procedure Buffer,Delta
    BufferRetrieve [%Buffer]
    JECXZ .90:
    MOV EAX,[%Delta]
    MOV EBX,SIZE#RELOC
    CDQ
.10:ADD [ESI+RELOC.OrgLow],EAX
    ADC [ESI+RELOC.OrgHigh],EDX
    ADD ESI,EBX
    SUB ECX,EBX
    JA .10:
.90:EndProcedure RelocRelocInBuffer
↑ RelocCombine Relocation
RelocCombine will update RELOC members .Target and .Frame which may refer to segments and groups from the abandoned linked program.
This procedure will update .Seg and .Frame according to their SSS.SegmPtr and SSS.GroupPtr, which should refer to combined segment in the base program.
Input
Relocation is pointer to a combined RELOC object.
Output
Relocation members .Org, .Seg, .Frame are updated.
Error
-
Tested by
t7940 t7943
RelocCombine Procedure Relocation
    MOV EBX,[%Relocation]
    MOV ESI,[EBX+RELOC.Target]   ; Segment in linked program.
    TEST ESI
    Msg cc=Z,'7727',0,[EBX+RELOC.OrgLow] ; Unresolved extern relocation at [!1S]:!2Hh.
    JZ .90:
    MOV EAX,[ESI+SSS.SegmPtr]
    MOV [EBX+RELOC.Target],EAX
    MOV ESI,[EBX+RELOC.Frame]   ; Segment or group in linked program.
    TEST ESI
    JZ .80:
    MOV EAX,[ESI+SSS.GroupPtr]
.80:MOV [EBX+RELOC.Target],EAX
.90:EndProcedure RelocCombine
↑ RelocFixup Relocation
RelocFixup updates the relocation when its segment was reallocated due to combine or link.
Input
Relocation is pointer to RELOC object.
Output
Contents of Relocation is updated.
Error
Errors are reported with macro Msg.
Invoked by
PgmCombine
RelocFixup Procedure Relocation
    MOV ESI,[%Relocation]
    JMP .10:
.E7924:Msg '7924',[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Invalid relocation [!1S]:!2Hh.
    JMP .90:
.10:; Fixup .Section and .Org of relocation ESI.
    MOV ECX,[ESI+RELOC.Section]
    JECXZ .E7924:
    ; Relocation ESI may belong to base program and then its .Section
    ;  may refer to a sssSection rather than to a sssSegment.
    ; However, its offset is already related to the segment bottom.
    JNSt [ECX+SSS.Status],sssSection,.30:
    MOV ECX,[ECX+SSS.SegmPtr]
    JECXZ .E7924:
.30:MOV EAX,[ECX+SSS.BottomLow]  ; Bottom of old linked segment.
    MOV EDX,[ECX+SSS.BottomHigh]
    MOV ECX,[ECX+SSS.SegmPtr]    ; Pointer to new base segment.
    JECXZ .E7924:
    SUB EAX,[ECX+SSS.BottomLow]
    SBB EDX,[ECX+SSS.BottomHigh] ; EDX:EAX is now delta of relocated word/dword.
    ADD [ESI+RELOC.OrgLow],EAX
    ADC [ESI+RELOC.OrgHigh],EDX
    MOV [ESI+RELOC.Section],ECX
    ; Fixup .Target and .Disp of relocation ESI.
    MOV ECX,[ESI+RELOC.Target]
    JECXZ .50: ; If the target is scalar.
    JNSt [ECX+SSS.Status],sssSection,.40:
    MOV ECX,[ECX+SSS.SegmPtr]
    JECXZ .50:
.40:MOV EAX,[ECX+SSS.BottomLow]
    MOV EDX,[ECX+SSS.BottomHigh]
    MOV ECX,[ECX+SSS.SegmPtr]
    JECXZ .50:
    SUB EAX,[ECX+SSS.BottomLow]
    SBB EDX,[ECX+SSS.BottomHigh]
    ADD [ESI+RELOC.DispLow],EAX
    ADC [ESI+RELOC.DispHigh],EDX
    MOV [ESI+RELOC.Target],ECX
.50:; Fixup .Frame of relocation ESI.
    MOV ECX,[ESI+RELOC.Frame]
    JECXZ .90:
    MOV ECX,[ECX+SSS.GroupPtr]
    JECXZ .90:
    MOV [ESI+RELOC.Frame],ECX
.90:EndProcedure RelocFixup
↑ RelocSort Pgm
RelocSort will update RELOC.Frame and sort all relocations in all segments of a given Pgm by their RELOC.Org ascending.
It is invoked after PgmCombine and PgmCreateImplicitGroups.
Input
Pgm is pointer to PGM.
Output
Relocations in all segments are sorted.
Error
-
Expands
ShellSort
Invoked by
PfbinCompile PfcoffCompile PfcomCompile PfmzCompile PfomfStoreModule PfpeCompile
RelocSort Procedure Pgm
    MOV EBX,[%Pgm]
    ListGetFirst [EBX+PGM.SssList]
    JZ .90:
.10:JNSt [EAX+SSS.Status],sssSegment,.80:
    BufferRetrieve [EAX+SSS.RelocBuffer]
    JECXZ .80: ; If there are no relocations in segment EAX.
    PUSH EAX
      LEA EDX,[ESI+ECX] ; End of RELOC array.
      MOV EBX,ESI ; Temporary save ptr  to RELOC block to EBX.
      MOV EAX,ECX ; Temporary save size of RELOC block to EAX.
      MOV EDI,SIZE#RELOC
 .30: CMP ESI,EDX
      JAE .70:
      ; Update frame of each relocation ESI.
      MOV ECX,[ESI+RELOC.Target]
      JECXZ .50:
      MOV ECX,[ECX+SSS.GroupPtr]
      JECXZ .50:
      MOV ECX,[ECX+SSS.GroupPtr]
 .50: MOV [ESI+RELOC.Frame],ECX
      ADD ESI,EDI
      JMP .30: ; The next relocation.
 .70: CDQ ; EDX:EAX is now the size of RELOC array.
      DIV EDI ; Get the number of RELOC records to EAX.
      ; Sort the RELOC array.
      ShellSort EBX,EAX,EDI,MemberUpdate.SortByOrg::
    POP EAX
.80:ListGetNext EAX ; The next segment.
    JNZ .10:
.90:EndProcedure RelocSort
↑ RelocUniq RelocBuffer
RelocUniq will sort RELOC records in RelocBuffer by their origin and remove identical records, which may have been created by recursive literal reference.
Input
RelocBuffer is pointer to input/output BUFFER with RELOC records.
Output
Duplicated relocations in RelocBuffer are removed.
Error
-
Expands
ShellSort
Invokes
EaBufferRelease EaBufferReserve
Invoked by
ExpEval SssEmit
RelocUniq Procedure RelocBuffer
TempBuffer LocalVar
    BufferRetrieve [%RelocBuffer]
    JECXZ .90:                        ; Do nothing when it's empty.
    Invoke EaBufferReserve::,RelocUniq
    MOV [%TempBuffer],EAX
    MOV EAX,ECX
    MOV EBX,SIZE# RELOC
    CDQ                               ; EDX:EAX is now the size of RELOC array.
    DIV EBX                           ; Get the number of RELOC records to EAX.
    LEA EDX,[ESI+ECX]                 ; EDX is now pointer to the end of array.
    ; Sort the RELOC array.
    ShellSort ESI,EAX,EBX,MemberUpdate.SortByOrg::
    ; Copy unique records to TempBuffer.
.30:BufferStore [%TempBuffer],ESI,EBX ; Copy one unique record.
    MOV EDI,ESI                       ; Remember in EDI the pointer to just stored record.
.40:ADD ESI,EBX                       ; The next record.
    CMP ESI,EDX
    JNB .80:                          ; If end of array was reached.
    MOV ECX,EBX
    PUSH ESI,EDI
      REPE CMPSB
    POP EDI,ESI
    JE .40:                           ; Skip the record if it's duplicated.
    JMP .30:
.80:;Copy TempBuffer to output.
    BufferClear [%RelocBuffer]
    BufferRetrieve [%TempBuffer]
    BufferStore [%RelocBuffer],ESI,ECX
    Invoke EaBufferRelease::,[%TempBuffer]
.90:EndProcedure RelocUniq
↑ RelocResolveImage Segment, Program

RelocResolveImage is invoked from PgmLinkImage when an executable program image is linked.
RelocResolveImage will read all relocations (RELOC records) stored in Segment.RelocBuffer and fixup their target in the emitted code, if possible.
The relocation is then marked as relocResolved.

If the image is in MZ format, unresolved paragraph relocations will be incorporated to the MZ executable image format later by PfmzCompile.

If the image is in PE|DLL format, absolute relocations will be incorporated to [.reloc] section later by PfpeBaserelocCreate.

In other executable formats any unresolved relocation reports E7727.

Input
Segment is pointer to SSS - segment with .Bottom set to the final VA within image.
Program is pointer to PGM with the linked image.
Output
Contents of Segment.EmitBuffer is modified: each emitted relocable Word/Dword/Fword pointed to by RELOC.Org is fixed up according to relocation type.
Resolved relocations in Segment.RelocBuffer are then marked as relocResolved.
Error
Errors are reported with macro Msg.
See also
RelocResolveObject
Invokes
ExpWidthSigned
Invoked by
PgmLinkImage
RelocResolveImage Procedure Segment, Program
SegmentBottomLow   LocalVar ; RVA of target segment bottom.
SegmentBottomHigh  LocalVar
FrameBottomLow     LocalVar ; RVA of target group/segment bottom
FrameBottomHigh    LocalVar ;   which is assumed to be loaded at run time in segment register.
EmittedBottom      LocalVar ; Pointer to bottom of emitted data (withing the contents of Segment.EmitBuffer).
EmittedPtr         LocalVar ; Pointer to the relocated word/dword in emitted data. Always between EmittedBottom and EmittedTop.
EmittedTop         LocalVar ; Pointer to the top of emitted data.
    MOV EBX,[%Segment]
    ; Mark borders of emitted contents.
    BufferRetrieve [EBX+SSS.EmitBuffer]
    LEA EAX,[ESI+ECX]
    MOV [%EmittedBottom],ESI
    MOV [%EmittedTop],EAX
    ; Walk through relocations.
    BufferRetrieve [EBX+SSS.RelocBuffer]
    TEST ECX
    JZ .99:                       ; If there are no relocations in the segment, done.
    ; Resolve each relocation ESI  in the loop .10: .. .90:.
.10:PUSH ECX
      JSt [ESI+RELOC.Status],relocResolved|relocDisp8,.90: ; Skip if it's a decorating RELOC record only.
      ; First calculate %EmittedPtr to relocated word/dword/qword. It's width is specified by Reloc.Status.
      MOV EAX,[ESI+RELOC.OrgLow]  ; Offset of the fixed word/dword/qword relative to segment.Bottom.
      MOV EDX,[ESI+RELOC.OrgHigh]
      ADD EAX,[%EmittedBottom]
      ADC EDX,0 ; Check if the relocated object lies inside emitted contents.
      JNZ .E7920: ; Invalid fixup at [!1S]:!2Hh.
      CMP EAX,[%EmittedTop]
      JAE .E7920: ; Invalid fixup at [!1S]:!2Hh.
      MOV [%EmittedPtr],EAX ; Pointer to relocated word/dword/qword within .EmitBuffer contents.
      ; Resolve relocation of target symbol.
      MOV ECX,[ESI+RELOC.Target]
      TEST ECX
      JZ .30:                     ; If the target is scalar.
      JNSt [ECX+SSS.Status],sssExtern,.30:
      ; Update relocation of external/imported symbol.
      ; Extern pseudosection ECX should refer with its .SymPtr to the corresponding public symbol.
      MOV EDI,[ECX+SSS.SymPtr] ; Symbol of extern pseudosegment. It was put there in PgmLinkImage.
      TEST EDI ; Properties of the matched public symbol EDI will be used instead of the external/imported one.
      JZ .E7727:                  ; Unresolved extern relocation at [!1S]:!2Hh.
      MOV EAX,[ESI+RELOC.Status]
      AND EAX,relocExtAttr        ; Postponed evaluation of attributes applied on external symbol.
      JNZ .12:
      MOV ECX,[EDI+SYM.Section]
      JECXZ .12:
      MOV EAX,[ECX+SSS.Status]
      AND EAX,relocExtAttr
.12:  SHR EAX,16 ; Convert relocDictAttr* to dictAttr*.
      Dispatch EAX,dictAttrNONE,dictAttrPARA,dictAttrGROUP,dictAttrSEGMENT,dictAttrSECTION,dictAttrOFFSET
      JMP .dictAttrNONE: ; Other attributes are ignored.

.dictAttrGROUP:
.dictAttrPARA:
      MOV ECX,[EDI+SYM.Section]   ; Segment or section of public symbol in base program.
      SUB EAX,EAX
      SUB EDX,EDX
      MOV EDI,ECX
      JECXZ .20:                  ; If external symbol is scalar.
      MOV ECX,[ECX+SSS.SegmPtr]
      JECXZ .20:
      MOV EDI,[ECX+SSS.GroupPtr]
      JMP .20:
.dictAttrSEGMENT:
.dictAttrSECTION:
      MOV ECX,[EDI+SYM.Section]   ; Segment or section of public symbol in base program.
      SUB EAX,EAX
      SUB EDX,EDX
      MOV EDI,ECX
      JMP .20:
.dictAttrOFFSET:
      SUB ECX,ECX
      JMP .18:
.dictAttrNONE:
      MOV ECX,[EDI+SYM.Section]    ; Segment or section of public symbol in base program.
      JECXZ .18:
      MOV ECX,[ECX+SSS.SegmPtr]    ; Segment.Bottom is already elevated to the new VA in image.
.18:  MOV EAX,[EDI+SYM.OffsetLow]
      MOV EDX,[EDI+SYM.OffsetHigh]
      MOV EDI,ECX                  ; Default frame of public symbol if it is in nongrouped segment.
      JECXZ .20:
      MOV EDI,[ECX+SSS.GroupPtr]
.20:  MOV [ESI+RELOC.Target],ECX   ; Update Target segment.
      MOV [ESI+RELOC.Frame],EDI    ; Update Frame group.
      ADD [ESI+RELOC.DispLow],EAX  ; Update Target displacement.
      ADC [ESI+RELOC.DispHigh],EDX ; Update Target displacement.
.30:  ; Common continuation of extern and standard symbols.
      ; Calculate %SegmentBottom of target segment.
      MOV ECX,[ESI+RELOC.Target]   ; Target segment. Zero when the target is absolute scalar address.
      SUB EAX,EAX
      CDQ
      JECXZ .40: ; If scalar.
      MOV ECX,[ECX+SSS.SegmPtr]
      JECXZ .40:
      MOV EAX,[ECX+SSS.BottomLow]  ; SEGMENT#.
      MOV EDX,[ECX+SSS.BottomHigh]
.40:  MOV [%SegmentBottomLow],EAX
      MOV [%SegmentBottomHigh],EDX
      MOV [%FrameBottomLow],EAX    ; Prepare frame for the case when equal to segment.
      MOV [%FrameBottomHigh],EDX
      ; Calculate %FrameBottom of the group of target segment ECX. It equals to %SegmentBottom if no group.
      JECXZ .50:
      MOV ECX,[ECX+SSS.GroupPtr]
      JECXZ .50:
      JSt [ESI+RELOC.Status],relocPara,.43:
      MOV EBX,[%Program]
      XOR EDX,EDX
      MOV EAX,[EBX+PGM.Pgmopt.Status]
      CMP AL,pgmoptBIN             ; When program format is BIN and relocation type not PARA#,
      MOV EAX,EDX                  ;   no base relocation is available, so FrameBottom will be 0.
      JE .45:
.43:  MOV EAX,[ECX+SSS.BottomLow]
      MOV EDX,[ECX+SSS.BottomHigh]
.45:  MOV [%FrameBottomLow],EAX
      MOV [%FrameBottomHigh],EDX
.50:  MOV EAX,[ESI+RELOC.Status]   ; Perform the actual relocation ESI method.
      MOV EDX,relocTypeMask
      MOV EDI,[%EmittedPtr]
      AND EDX,EAX                  ; EDX is now the relocation type.
      ; Select the relocation type.
      Dispatch EDX,relocRel,relocAbsVA,relocAbsRVA,relocPara,relocFar
.relocResolved:
      SetSt [ESI+RELOC.Status],relocResolved
      JMP .90:
.relocPara:                        ; Absolute paragraph relocation.
      ; Relocated target word is increased by delta = (GROUP#Target)/16.
      MOV EAX,[%FrameBottomLow]
      MOV EDX,[%FrameBottomHigh]
      SHRD EAX,EDX,4
      ADD [EDI],AX ; The actual fixup with paragraph RVA.
      MOV EBX,[%Program]
      MOV EAX,[EBX+PGM.Pgmopt.Status]
      CMP AL,pgmoptBIN
      JE .relocResolved: ; This kind of relocation is resolved only if format=BIN.
      JMP .90:

.relocFar:                         ; Far pointer relocation.
      ; Segment fixup delta value = (SEGMENT#Target) / 16.
      ; Offset  fixup delta value = (SEGMENT#Target) \ 16 + RELOC.Disp
      MOV EDX,[%SegmentBottomLow]  ; RVA of the target segment.
      MOV EAX,0x0000_000F
      MOV ECX,2
      AND EAX,EDX ; EAX is now RVA modulo 16.
      ADD EAX,[ESI+RELOC.DispLow]  ; If segment is unaligned, the remainder will be added to target displacement.
      JSt [ESI+RELOC.Status],relocWidth16,.far16:
.far32:ADD [EDI],EAX               ; The actual fixup of far dword offset.
      MOV CL,4
      JMP .farSeg:
.far16:ADD [EDI],AX                ; The actual fixup of far word offset.
.farSeg:ADD EDI,ECX                ; Make EDI point to the segment part of far address (add 2 or 4).
      SHR EDX,4                    ; EDX is now RVA/16.
      ADD [EDI],DX                 ; The actual fixup of far segment paragraph address.
      ; Far relocation is not completely resolved yet, the segment part will be fixed up at load time.
      ; The reloc record ESI will be restructuralized from relocFar to relocPara.
      SUB EAX,EAX
      ADD [ESI+RELOC.OrgLow],ECX   ; Make the origin point to paragraph address.
      ADC [ESI+RELOC.OrgHigh],EAX
      MOV [ESI+RELOC.DispLow],EAX
      MOV [ESI+RELOC.DispHigh],EAX
      MOVD [ESI+RELOC.Status],relocPara+relocWidth16
      JMP .90:

.relocAbsRVA:                      ; Relocation of RVA.
      MOV EBX,[%Program]
      MOV ECX,[EBX+PGM.Pgmopt.ImageBaseLow]
      MOV EDX,[EBX+PGM.Pgmopt.ImageBaseHigh]
      NOT ECX
      NOT EDX
      ADD ECX,1
      ADC EDX,0
      JMP .relocAbs:
.relocAbsVA:                       ; Relocation of VA.
      MOV EBX,[%Program]
      SUB ECX,ECX
      SUB EDX,EDX
.relocAbs:                         ; Absolute relocation.
      ; Fixup delta value = SEGMENT#Target - GROUP#Target + RELOC.Disp.
      ; GROUP#Target is 0 when MODEL=FLAT. EDX:ECX is -ImageBase if AbsRVA or 0 if AbsVA.
      PUSH ECX,EDX
        ADD ECX,[%FrameBottomLow]
        ; If the target frame is not paragraph-aligned, add the remainder to the target displacement.
        AND ECX,0x0000_000F
        ADD [ESI+RELOC.DispLow],ECX
        ADC [ESI+RELOC.DispHigh],EDX
      POP EDX,EAX
      ADD EAX,[%SegmentBottomLow]
      ADC EDX,[%SegmentBottomHigh]
      JSt [EBX+PGM.Pgmopt.Status],pgmoptFLAT,.Frame0:
      SUB EAX,[%FrameBottomLow]
      SBB EDX,[%FrameBottomHigh]
.Frame0:
      ADD EAX,[ESI+RELOC.DispLow]
      ADC EDX,[ESI+RELOC.DispHigh] ; EDX:EAX is now fixup delta value.
      JSt [ESI+RELOC.Status],relocWidth32,.Abs32:
      JSt [ESI+RELOC.Status],relocWidth64,.Abs64:
.Abs16:                            ; Absolute word relocation.
      ADD [EDI],AX ; The actual fixup.
      JMP .relocResolved:
.Abs32:                            ; Absolute dword relocation.
      ADD [EDI],EAX ; The actual fixup.
      JMP .relocResolved:
.Abs64:                            ; Absolute qword relocation..
      ADD [EDI+0],EAX ; The actual fixup.
      ADC [EDI+4],EDX
      JMP .relocResolved:

.relocRel: ; Self-relative relocation.
; Emitted relocated word/dword (Object) contains OFFSET#Target, or 0 if it was extern.
; Fixup delta value = SEGMENT#target - SEGMENT#Object - OFFSET#Object - SIZE#Object + RELOC.Disp.
      MOV EBX,[%Segment]
      MOV EAX,[%SegmentBottomLow]
      MOV EDX,[%SegmentBottomHigh]
      SUB EAX,[EBX+SSS.BottomLow]
      SBB EDX,[EBX+SSS.BottomHigh]
      SUB EAX,[ESI+RELOC.OrgLow]
      SBB EDX,[ESI+RELOC.OrgHigh]
      ADD EAX,[ESI+RELOC.DispLow]
      ADC EDX,[ESI+RELOC.DispHigh]
      MOV ECX,[ESI+RELOC.Status]
      AND ECX,relocRelDist
      SHR ECX,12                   ; ECX is the size of imm+imm2 encoded in the instruction.
      SUB EAX,ECX
      SBB EDX,0                    ; EDX:EAX is now the fixup delta value.
      JSt [ESI+RELOC.Status],relocWidth16,.Rel16:
.Rel32:SUB EAX,4 ; SIZE#Object.    ; Self-relative dword relocation.
      SBB EDX,0
      Invoke ExpWidthSigned::
      CMP CL,expWidth4B
      JA .E7922:                   ; Fixup increment out of 4GB range at [!1S]:!2Hh.
      ADD [EDI],EAX                ; The actual fixup.
      JMP .relocResolved:
.Rel16:SUB EAX,2 ; SIZE#Object.    ; Self-relative word relocation.
      SBB EDX,0
      Invoke ExpWidthSigned::
      CMP CL,expWidth2B
      JA .E7921:                   ; Fixup increment out of 64KB range at [!1S]:!2Hh.
      ADD [EDI],AX                 ; The actual fixup.
      JMP .relocResolved:
.E7727:Msg '7727',[%Segment],[ESI+RELOC.OrgLow] ; Unresolved extern relocation at [!1S]:!2Hh.
       JMP .90:
.E7920:Msg '7920',[%Segment],[ESI+RELOC.OrgLow] ; Invalid fixup at [!1S]:!2Hh.
       JMP .90:
.E7921:Msg '7921',[%Segment],[ESI+RELOC.OrgLow] ; Fixup increment out of 64KB range at [!1S]:!2Hh.
       JMP .90:
.E7922:Msg '7922',[%Segment],[ESI+RELOC.OrgLow] ; Fixup increment out of 4GB range at [!1S]:!2Hh.
       JMP .90:
.E7926:Msg '7926',[%Segment],[ESI+RELOC.OrgLow] ; Relocation offset out of 64KB range at [!1S]:!2Hh.
       JMP .90:
.E7927:Msg '7927',[%Segment],[ESI+RELOC.OrgLow] ; Relocation offset out of 4GB range at [!1S]:!2Hh.
       JMP .90:
.E7928:Msg '7928',[%Segment],[ESI+RELOC.OrgLow] ; Unaligned segment of relocation [!1S]:!2Hh.
      ; JMP .90:
.90:POP ECX
    ADD ESI,SIZE#RELOC
    SUB ECX,SIZE#RELOC
    JA .10:                        ; The next relocation.
.99:EndProcedure RelocResolveImage
↑ RelocResolveObject Segment, Program
RelocResolveObject is invoked when a linkable object file is linked.
RelocResolveObject will read all relocations (RELOC records) stored in Segment.RelocBuffer and fixup their target in the emitted code only if the relocation is relative to the same segment (relocRel).
The relocation is then marked as relocResolved.
Input
Segment is pointer to SSS - segment with .Bottom set to the final VA within image.
Program is pointer to PGM with the linked image.
Output
Contents of Segment.EmitBuffer is modified: each emited relocable Word/Dword/Fword pointed to by RELOC.Org is fixed up according to relocation type.
Resolved relocations in Segment.RelocBuffer are then marked as relocResolved.
Error
-
See also
RelocResolveImage
Invokes
ExpWidthSigned
Invoked by
PfcoffCompile
RelocResolveObject Procedure Segment, Program
SegmentBottomLow   LocalVar ; RVA of target segment bottom.
SegmentBottomHigh  LocalVar
FrameBottomLow     LocalVar ; RVA of target group/segment bottom
FrameBottomHigh    LocalVar ;   which is assumed to be loaded at run time in segment register.
EmittedBottom      LocalVar ; Pointer to bottom of emitted data (withing the contents of Segment.EmitBuffer).
EmittedPtr         LocalVar ; Relocated word/dword in emitted data. Always between EmittedBottom and EmittedTop.
EmittedTop         LocalVar ; Pointer to top of emitted data.
    MOV EBX,[%Segment]
    ; Mark borders of emitted contents.
    BufferRetrieve [EBX+SSS.EmitBuffer]
    LEA EAX,[ESI+ECX]
    MOV [%EmittedBottom],ESI
    MOV [%EmittedTop],EAX
    ; Walk through relocations.
    BufferRetrieve [EBX+SSS.RelocBuffer]
    TEST ECX
    JZ .99: ; If there are no relocations in the segment, done.
    ; Resolve each relocation ESI  in the loop .10: .. .90:.
.10:PUSH ECX
      JSt [ESI+RELOC.Status],relocResolved|relocDisp8,.90: ; Skip if it's a decorating RELOC record only.
      JNSt [EDI+RELOC.Status],relocRel,.90: ; Other than relative relocation are not resolvable yet,
                    ; because final segments VA are not set when an linkable object file is compiled.
      CMP [ESI+RELOC.Target],EBX
      JNE .90: ; Only relative relocations within the same segment are resolvable here.
      ; First calculate %EmittedPtr to relocated word/dword/qword. It's width is specified by Reloc.Status.
      MOV EAX,[ESI+RELOC.OrgLow]            ; Offset of fixed word/dword/qword relative to segment.Bottom.
      MOV EDX,[ESI+RELOC.OrgHigh]
      ADD EAX,[%EmittedBottom]
      ADC EDX,0
      JNZ .E7920: ; Invalid fixup at [!1S]:!2Hh.
      CMP EAX,[%EmittedTop]
      JAE .E7920: ; Invalid fixup at [!1S]:!2Hh.
      MOV [%EmittedPtr],EAX                 ; Pointer to relocated word/dword/qword within .EmitBuffer contents.
      MOV ECX,[ESI+RELOC.Target]            ; Resolve relocation of target symbol.
      TEST ECX
      JZ .30:                               ; If the target is scalar.
      JNSt [ECX+SSS.Status],sssExtern,.30:
      ; Update relocation of external symbol.
      ; Extern pseudosection ECX should refer with its .SymPtr to the corresponding public symbol.
      MOV EDI,[ECX+SSS.SymPtr]              ; Symbol of extern pseudosegment. It was put there in PgmLinkImage.
      TEST EDI ; Properties of the matched public symbol EDI will be used instead of the external/imported one.
      JZ .E7727:                            ; Unresolved extern relocation at [!1S]:!2Hh.
      MOV EAX,[ESI+RELOC.Status]
      AND EAX,relocExtAttr                  ; Postponed evaluation of attributes applied on external symbol.
      JNZ .12:
      MOV ECX,[EDI+SYM.Section]
      JECXZ .12:
      MOV EAX,[ECX+SSS.Status]
      AND EAX,relocExtAttr
.12:  SHR EAX,16                            ; Convert relocDictAttr* to dictAttr*.
      Dispatch EAX,dictAttrNONE,dictAttrPARA,dictAttrGROUP,dictAttrSEGMENT,dictAttrSECTION,dictAttrOFFSET
      JMP .dictAttrNONE:                    ; Other attributes are ignored.
.dictAttrGROUP:
.dictAttrPARA:
      MOV ECX,[EDI+SYM.Section]             ; Segment or section of public symbol in base program.
      SUB EAX,EAX
      SUB EDX,EDX
      MOV EDI,ECX
      JECXZ .20:                            ; If external symbol is scalar.
      MOV ECX,[ECX+SSS.SegmPtr]
      JECXZ .20:
      MOV EDI,[ECX+SSS.GroupPtr]
      JMP .20:
.dictAttrSEGMENT:
.dictAttrSECTION:
      MOV ECX,[EDI+SYM.Section]             ; Segment or section of public symbol in base program.
      SUB EAX,EAX
      SUB EDX,EDX
      MOV EDI,ECX
      JMP .20:
.dictAttrOFFSET:
      SUB ECX,ECX
      JMP .18:
.dictAttrNONE:
      MOV ECX,[EDI+SYM.Section]             ; Segment or section of public symbol in base program.
      JECXZ .dictAttrOFFSET:
      MOV ECX,[ECX+SSS.SegmPtr]             ; Segment.Bottom is already elevated to the new VA in image.
.18:  MOV EAX,[EDI+SYM.OffsetLow]
      MOV EDX,[EDI+SYM.OffsetHigh]
      MOV EDI,ECX                           ; Default frame of public symbol if it is in nongrouped segment.
      JECXZ .20:
      MOV EDI,[ECX+SSS.GroupPtr]
.20:  MOV [ESI+RELOC.Target],ECX            ; Update Target segment.
      MOV [ESI+RELOC.Frame],EDI             ; Update Frame group.
      ADD [ESI+RELOC.DispLow],EAX           ; Update Target displacement.
      ADC [ESI+RELOC.DispHigh],EDX
.30:  ; Common continuation of extern and standard symbols.
      ; Calculate %SegmentBottom of target segment.
      MOV ECX,[ESI+RELOC.Target]            ; Target segment. Zero when the target is absolute scalar address.
      SUB EAX,EAX
      CDQ
      JECXZ .40: ; If scalar.
      MOV ECX,[ECX+SSS.SegmPtr]
      JECXZ .40:
      MOV EAX,[ECX+SSS.BottomLow]           ; SEGMENT#.
      MOV EDX,[ECX+SSS.BottomHigh]
.40:  MOV [%SegmentBottomLow],EAX
      MOV [%SegmentBottomHigh],EDX
      MOV [%FrameBottomLow],EAX             ; Prepare frame for the case when equal to segment.
      MOV [%FrameBottomHigh],EDX
      ; Calculate %FrameBottom of the group of target segment ECX. It equals to %SegmentBottom if no group.
      JECXZ .50:
      MOV ECX,[ECX+SSS.GroupPtr]
      JECXZ .50:
      JSt [ESI+RELOC.Status],relocPara,.43:
      MOV EBX,[%Program]
      XOR EDX,EDX
      MOV EAX,[EBX+PGM.Pgmopt.Status]
      CMP AL,pgmoptBIN                       ; When program format is BIN and relocation type not PARA#,
      MOV EAX,EDX                            ;   no base relocation is available, so FrameBottom will be 0.
      JE .45:
.43:  MOV EAX,[ECX+SSS.BottomLow]
      MOV EDX,[ECX+SSS.BottomHigh]
.45:  MOV [%FrameBottomLow],EAX
      MOV [%FrameBottomHigh],EDX
.50:  MOV EDI,[%EmittedPtr]                  ; Perform the actual relocation ESI method.
      ; Emitted relocated word/dword (Object) contains OFFSET#Target, or 0 if it was extern.
      ; Fixup delta value = SEGMENT#target - SEGMENT#Object - OFFSET#Object - SIZE#Object + RELOC.Disp.
      MOV EBX,[%Segment]
      MOV EAX,[%SegmentBottomLow]
      MOV EDX,[%SegmentBottomHigh]
      SUB EAX,[EBX+SSS.BottomLow]
      SBB EDX,[EBX+SSS.BottomHigh]
      SUB EAX,[ESI+RELOC.OrgLow]
      SBB EDX,[ESI+RELOC.OrgHigh]
      ADD EAX,[ESI+RELOC.DispLow]
      ADC EDX,[ESI+RELOC.DispHigh]
      MOV ECX,[ESI+RELOC.Status]
      AND ECX,relocRelDist
      SHR ECX,12                            ; ECX is the size of imm+imm2 encoded in the instruction.
      SUB EAX,ECX
      SBB EDX,0                             ; EDX:EAX is now the fixup delta value.
      JSt [ESI+RELOC.Status],relocWidth16,.Rel16:
.Rel32:; Self-relative relocation of DWORD object.
      SUB EAX,4                             ; Size of disp32 (the relocated object).
      SBB EDX,0
      Invoke ExpWidthSigned::
      CMP CL,expWidth4B
      JA .E7922:                            ; Fixup increment out of 4GB range at [!1S]:!2Hh.
      ADD [EDI],EAX                         ; The actual fixup.
      JMP .relocResolved:
.Rel16: ; Self-relative relocation of WORD object.
      SUB EAX,2                             ; Size of disp16 (the relocated object).
      SBB EDX,0
      Invoke ExpWidthSigned::
      CMP CL,expWidth2B
      JA .E7921:                            ; Fixup increment out of 64KB range at [!1S]:!2Hh.
      ADD [EDI],AX                          ; The actual fixup.
      JMP .relocResolved:
.E7727:Msg '7727',[%Segment],[ESI+RELOC.OrgLow] ; Unresolved extern relocation at [!1S]:!2Hh.
       JMP .90:
.E7920:Msg '7920',[%Segment],[ESI+RELOC.OrgLow] ; Invalid fixup at [!1S]:!2Hh.
       JMP .90:
.E7921:Msg '7921',[%Segment],[ESI+RELOC.OrgLow] ; Fixup increment out of 64KB range at [!1S]:!2Hh.
       JMP .90:
.E7922:Msg '7922',[%Segment],[ESI+RELOC.OrgLow] ; Fixup increment out of 4GB range at [!1S]:!2Hh.
       JMP .90:
.E7926:Msg '7926',[%Segment],[ESI+RELOC.OrgLow] ; Relocation offset out of 64KB range at [!1S]:!2Hh.
       JMP .90:
.E7927:Msg '7927',[%Segment],[ESI+RELOC.OrgLow] ; Relocation offset out of 4GB range at [!1S]:!2Hh.
       JMP .90:
.E7928:Msg '7928',[%Segment],[ESI+RELOC.OrgLow] ; Unaligned segment of relocation [!1S]:!2Hh.
      ; JMP .90:
.relocResolved:
      SetSt [ESI+RELOC.Status],relocResolved
.90:POP ECX
    ADD ESI,SIZE#RELOC
    SUB ECX,SIZE#RELOC
    JA .10:                                     ; The next relocation.
.99:EndProcedure RelocResolveObject
 ENDPROGRAM reloc

▲Back to the top▲