EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

reloc.htm
Classes
RELOC
Relocation types
I386 (32bit)
X86_64 (64bit)
Encodings
RelocEnc
Procedures
RelocCombine
RelocPurge
RelocRelocInBuffer
RelocReportUnresolved
RelocResolve

Structure RELOC describes relocation in storage unit, which is a word, dword or qword memory variable in emitted code|data. The address, which the instruction refers to, is called target.

Relocations loaded at link-time from object files in formats OMF, COFF, ELF are converted by PfformatLoad to this united internal structure RELOC, which does not depend on CPU architecture (AMD64, x86, v86) neither on object-file format.

RELOC objects are kept in SSS.RelocBuffer. Their properties are:
RELOC.Status specifies the type of relocation and the size of relocated storage unit.
RELOC.Org represents the offset of the storage unit from the beginning of its section|segment, which is identified by RELOC.Section (P).
RELOC.Symbol specifies the target. It points to SYM representing the bottom of (perhaps external) segment or group (frame).
RELOC.Addend represents addend (A) to the value (R) in storage unit, which was left in instruction encoding by the assembler at asm-time (and which is pointed to by RELOC.Org ). Addend will be added to the storage unit when the relocation is resolved.
Frame of absolute relocation is the target's segment|group bottom, addend is zero.
Frame of relative relocation is RIP, i.e. address of the following instruction. Addend is the difference between the address of storage unit and RIP, for instance -2 when a word unit is relocated and this word is the last field of JMPN in 16bit mode.

Example of absolute relocation
|[CODE] |[CODE] SEGMENT WIDTH=16 | ... |0021:BA[0000] | MOV DX,Label ; Load DX with the offset of external symbol Label.
RELOC.Section=[CODE], RELOC.Org=0x0022, RELOC.Addend=0, RELOC.Symbol=Label, RELOC.Status=relocWidth16+relocAbsVA
Example of relative relocation
|[.text] |[.text] SEGMENT WIDTH=64 | ... |00000012:48C705(00000000)23010000 | MOV [QData],0x123,DATA=QWORD,ADDR=REL ; Store immeditate constant to an external variable QData.
RELOC.Section=[.text], RELOC.Org=0x00000015, RELOC.Addend=-8, RELOC.Symbol=QData, RELOC.Status=relocWidth64+relocRel

Addend is 0 in absolute relocations. In relative relocations it is the negative distance between RELOC.Org and the start of the next instruction (rIP). Addend may be modified later in RelocResolve

Relocation of FAR pointers uses two RELOC records (one for the offset, other for the paragraph address of target).

For the relation between symbols and segments in €ASM see SymSssBinding.

RELOC records are created by €ASM at asm-time by IiFlush when a machine instruction is assembled, and by ExpEvalData or ExpStoreInstr when a data definition is assembled.
RELOC record are also created at link-time when OMF|COFF|ELF object files are loaded.

Relative intrasection relocations (iiRelocDispRIP and iiRelocImmRIP) are resolved immediately in IiFlush.
Relative intrasegment relocations and absolute relocations of scalars are resolved in RelocResolve when sections are marshaled to their segment.
Other relocations between segments and external symbols are resolved by the linker of executable formats (PfformatCompile) or they are converted and stored in object output files.


 

Evolution of RELOC.Org in multiple data definition (e.g. DD 2*DWORD aPointer) at assembly time:
Example
aData D D 5, 2*D aBssSymbol ; EuroAssembler creates two RELOC records with origins 4 and 8 in Stm.RelocBuffer. ; Origins will be elevated to OFFSET#aData+4, OFFSET#aData+8 in StmFlush. ; RELOC.Symbol points to symbol .bss representing the bottom of target segment [.bss].
Evolution of RELOC.Org at marshal time: Evolution of RELOC.Org at combine time: Evolution of RELOC.Org at link time:

Calculation method shortcuts:

A represents the value left by the compiler in relocated storage unit (word|dword|qword). It is visible in the dump column of program listing.
The process of resolving a relocation will replace A with the new relocated value R.

B represents the base address at which a shared object has been loaded into memory during execution. Generally, a shared object is built with a zero-base virtual address, but the execution address will be different. In €ASM it is specified by PROGRAM ImageBase=.

G represents the offset into the global offset table at which the relocation entry’s symbol will reside during execution.

GOT represents the VA (virtual address) of the global offset table.

L represents the place (section offset or address) of the Procedure Linkage Table entry for a symbol.

O represents the offset of the target symbol, whose index resides in the relocation entry, from the bottom of its segment. It becomes VA when the segment is finally linked to executable image.

P represents VA of the storage unit (word|dword|qword) which is being relocated (computed using PFELF_REL.r_offset alias RELOC.Org+SEGMENT#RELOC.Section.

R is the final value which will be written to the storage unit instead of A as the result of resolving the relocation. This value is visible in debugger and in hexadecimal dump of output file.

S represents the value (VA) of the target symbol, whose index resides in the relocation entry, i.e. RELOC.Symbol (its offset + bottom of its segment). When the symbol is scalar, its segment is NULL and S is its absolute value.

V is number of bytes (0..5) betweeen the end of relocated word|dword|qword and start of the next instruction (rIP). It is nonzero only when the relocated storage unit is not the last field in instruction encoding, e.g. in ADCD [Symbol],0x11 assembled as 8315[00000000]11 is V=1, W=4.

W represents the width of the relocated storage unit (word|dword|qword) in bytes, i.e. 2|4|8.

Z represents the size of the symbol whose index resides in the relocation entry (SIZE# of RELOC.Symbol).

Calculation of A by compilers

If the relocation is absolute:
    A=O, i.e. offset of target or its absolute value.

If the relocation is relative, compilers compute this value according to the output format:
    A=0 in COFF Microsoft format,
    A=B-P-W-V in COFFD DJ GPP format,
    A=-W-V in ELF format.

Calculation of R by linkers

The following tables show transformation of relocation types to RELOC.Status and back, together with their calculation methods:

Relocation types for machine i386 (PROGRAM WIDTH=32)
Internal €ASM formatCOFF, COFFDELF, ELFX, ELFSO
RELOC.Status
reloc*
Calculation
method
PFCOFF_RELOCATION.Type
IMAGE_REL_I386_*
PFELF_REL32.r_type
pfelfR_386_*
NoneR=A0 ABSOLUTE0|5 NONE|COPY
Width16+AbsVAR=S+A1 DIR16
Width16+RelR=S-P+A2 REL16
Width32+AbsVAR=S+A6 DIR321 32
Width32+AbsRVAR=S-B+A7 DIR32NB
Width32+RelR=S-P20 REL32
Width32+Rel+COFFDR=S+A20 REL32
Width32+Rel+ELFR=S-P+A2 PC32
Width32+GOTR=G-P+A3 GOT32
Width32+PLTR=L-P+A4 PLT32
Width32+SymR=S6|7 GLOB_DAT|JMP_SLOT
Width32+DynR=B+A8 RELATIVE
Width32+GOToffR=S-GOT+A9 GOTOFF
Width32+GOTrelR=GOT-P+A10 GOTPC
Relocation types for machine x86-64 (PROGRAM WIDTH=64)
Internal €ASM formatCOFF, COFFDELF, ELFX, ELFSO
RELOC.Status
reloc*
Calculation
method
PFCOFF_RELOCATION.Type
IMAGE_REL_AMD64_*
PFELF_REL64.r_type
pfelfR_X86_64_*
NoneR=A0 ABSOLUTE0|5 NONE|COPY
Width64+AbsVAR=S+A1 ADDR641 64
Width32+AbsVAR=S+A2 ADDR3210 32
Width32+AbsRVAR=S-B+A3 ADDR32NB
Width32+RelR=S-P+A4 REL322 PC32
Width32+Rel+RelDist1R=S-P+V+A5 REL32_1
Width32+Rel+RelDist2R=S-P+V+A6 REL32_2
Width32+Rel+RelDist3R=S-P+V+A7 REL32_3
Width32+Rel+RelDist4R=S-P+V+A8 REL32_4
Width32+Rel+RelDist5R=S-P+V+A9 REL32_5
Width32+GOTR=G+A3 GOT32
Width32+PLTR=L-P+A4 PLT32
Width64+SymR=S6|7 GLOB_DAT|JMP_SLOT
Width64+DynR=B+A8 RELATIVE
Width64+GOToffR=S-GOT+A25 GOTOFF64
Width32+GOTrelR=GOT-P+A26 GOTPC32

      euroasm nowarn=2101
reloc PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
INCLUDEHEAD "euroasm.htm" ; Interface (structures, symbols and macros) of other modules.
INCLUDEHEAD  \  ; Include headers of another modules used in this module.
dict.htm,    \
ea.htm,      \
eaopt.htm,   \
exp.htm,     \
msg.htm,     \
pf.htm,      \
pgm.htm,     \
pgmopt.htm,  \
sss.htm,     \
sym.htm,     \
syswin.htm,  \
;;
 reloc HEAD  ; Start of module interface.
↑ RELOC

Relocation 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.

Special reloc type relocDisp8 does not represent a real relocation but only a hint how to decorate the scaled disp8*N in listing, if nonzero. Other bits in RELOC.Status should be zero when disp8*N is used.

RELOC STRUC  ; Relocation record.
.OrgLow     D D ; P: Origin, i.e. offset of fixed memory object (word|dword|qword)
.OrgHigh    D D ;   relative from the beginning of the section which hosts the fixed object.
.Section    D D ; ^SSS section or segment whose .EmitBuffer contains the fixed object.
.Status     D D ; Relocation properties, see below.

.AddendLow  D D ; A: Value to be added to the relocated word|dword|qword.
.AddendHigh D D
.Symbol     D D ; ^SYM representing the bottom of target's segment or an external symbol.
            D D ; not used
        ENDSTRUC RELOC ; SIZE# RELOC = 32 = 20h
↑ 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 (W).
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 (V). 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.Addend by 1,4,5 and having the type fixed at 0x0004, but I preferred keeping the relocated DWORD unchanged in COFF object code.
                             ; Fundamental relocation types.
relocNone      = 0x0000_0000 ; No relocation, same as relocResolved.
relocPara      = 0x0000_0001 ; Base relocation of paragraph address related to ImageBase.
relocAbsVA     = 0x0000_0002 ; Absolute relocation of  VA of the target RELOC.Symbol.
relocAbsRVA    = 0x0000_0004 ; Absolute relocation of RVA of the target RELOC.Symbol.
relocRel       = 0x0000_0008 ; Relative relocation of  VA related to rIP. May be set together with relocELF,relocCOFFD.
relocFar       = 0x0000_0010 ; Far absolute relocation (16+16 or 16+32).
               ; 0x0000_0020 ; Reserved.
relocSym       = 0x0000_0040 ; Related to the symbol.
relocDyn       = 0x0000_0080 ; Related to the runtime ImageBase of shared object.
relocPLT       = 0x0000_0100 ; Adressed via Procedure Linkage Table.
relocGOT       = 0x0000_0200 ; Related to the Global Offset Table.
relocGOToff    = 0x0000_0400 ; Adressed via entry in Global Offset Table.
relocGOTrel    = 0x0000_0800 ; Relative relocation addressed via GOT.
               ; 0x0000_1000 ; Reserved.
               ; 0x0000_2000 ; Reserved.
relocTypeMask  = 0x0000_3FFF ; Relocation type. Only one flag may be set.
relocCOFFD     = 0x0000_4000 ; Relocation was loaded from COFFD (DJ GPP) module.
relocELF       = 0x0000_8000 ; Relocation was loaded from ELF module.
                             ; Evaluation of external symbol attributes postponed to the link time.
relocExtAttr   = 0x000F_0000 ; DictAttr* (0..9) synchronized with expExtAttr.
                             ; W: 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
                             ; V: correction of RIP-relative relocation.
relocRelDist   = 0x0700_0000 ; Additional distance of RIP-relative relocation in 64bit mode (0..5).
                             ; Miscellaneous properties.
relocDisp8N    = 0x7000_0000 ; Disp8*N shift factor 1..6. Pseudorelocation used to decorate dumped listing.
relocResolved  = 0x8000_0000 ; This relocation has been already resolved and should be ignored.
relocIgnore    = relocResolved | relocDisp8N ; Do not relocate anything.
  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 32bit 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
↑ RelocPurge Pgm
RelocPurge sorts relocations in all segments of a given Pgm by their RELOC.Org ascending and then removes resolved and duplicated records.
It is invoked at link time, after PgmCombine and SssCreateImplicit.
Input
Pgm is pointer to the linked PGM.
Output
Relocations in all segments are purged and sorted.
Error
-
Expands
ShellSort
Invoked by
PfOutput
Invokes
EaBufferRelease EaBufferReserve
RelocPurge    Procedure Pgm
TopOrig LocalVar                          ; Pointer to the original top of RelocBuffer (behind the last RELOC record).
Top     LocalVar                          ; Pointer to the current top of RelocBuffer (behind the last RELOC record).
TempBuf LocalVar                          ; ^Temporary buffer for relocations.
    Invoke EaBufferReserve::,%^PROC
    MOV [%TempBuf],EAX
    MOV EBX,[%Pgm]
    MOV EDX,SIZE# RELOC
    ListGetFirst [EBX+PGM.SssList]
    JZ .90:
.10:JNSt [EAX+SSS.Status],sssSegment,.80:
    XOR EBX,EBX                           ; Counter of RELOC records in %TempBuf.
    BufferClear [%TempBuf]
    BufferRetrieve [EAX+SSS.RelocBuffer]
    ADD ECX,ESI
.20:CMP ESI,ECX
    JNB .40:                              ; If there are no more relocations in segment EAX.
    JSt [ESI+RELOC.Status],relocIgnore,.30:
    BufferStore [%TempBuf],ESI,EDX
    INC EBX
.30:ADD ESI,EDX
    JMP .20:
.40:BufferClear [EAX+SSS.RelocBuffer]
    BufferRetrieve [%TempBuf]             ; Sort the array of EBX records.
;;    ShellSort ESI,EBX,EDX,MemberUpdate.SortByOrg::
    ShellSort ESI,EBX,EDX,SortByOrg::

    BufferRetrieve [%TempBuf]             ; Omit duplicated relocations.
    ADD ECX,ESI                           ; ESI..ECX is an array of sorted RELOC records.
.50:CMP ESI,ECX
    JNB .80:
    BufferStore [EAX+SSS.RelocBuffer],ESI,EDX
.60:LEA EDI,[ESI+EDX]                     ; The next records following ESI.
    CMP EDI,ECX
    JNB .80:
    Compare ESI,EDX,EDI,EDX               ; Compare, preserving all GPR.
    MOV ESI,EDI
    JE .60:
    JMP .50:
.80:ListGetNext EAX ; The next segment.
    JNZ .10:
.90:Invoke EaBufferRelease::,[%TempBuf]
    EndProcedure RelocPurge
↑ RelocCombine Relocation, BaseProg
RelocCombine will update the Relocation in BasePgm when segments and symbols have already been combined to the base program.
Intrasegment relative relocation between public homonymous segments is finally resolved here.
Input
Relocation points to RELOC object in the base program, as it was copied from linked module.
BaseProg is pointer to a PGM which it is linked to.
Output
Relocation members .Org, .Section, .Addend, .Symbol are updated.
Error
-
Invoked by
PgmCombine
RelocCombine Procedure Relocation, BaseProg
    MOV EBX,[%Relocation]
    MOV ECX,[EBX+RELOC.Status]
    JSt ECX,relocIgnore,.90:
    ; Update RELOC.Section:RELOC.Org, i.e. position of the relocated storage unit (word|dword).
    MOV ESI,[EBX+RELOC.Section]                  ; ^SSS where the relocated object is located.
    MOV EAX,[ESI+SSS.BottomLow]                  ; Bottom of its combined segment might have been elevated.
    MOV EDX,[ESI+SSS.BottomHigh]
    MOV EDI,[ESI+SSS.SegmPtr]
    SUB EAX,[EDI+SSS.BottomLow]
    SBB EDX,[EDI+SSS.BottomHigh]
    ADD [EBX+RELOC.OrgLow],EAX
    ADC [EBX+RELOC.OrgHigh],EDX
    MOV [EBX+RELOC.Section],EDI
    AND ECX,relocTypeMask
    Dispatch ECX,relocAbsVA,relocAbsRVA,relocRel
    JMP .90:

.relocRel:
    MOV EDI,[EBX+RELOC.Symbol]
    TEST EDI
    JZ .90:
    MOV ECX,[EDI+SYM.Section]
    JECXZ .90:
    MOV EAX,[ECX+SSS.BottomLow]
    MOV EDX,[ECX+SSS.BottomHigh]
    MOV EDI,[EDI+SYM.SymbPtr]
    TEST EDI
    JZ .90:
    MOV ECX,[EDI+SYM.Section]
    JECXZ .90:
    SUB EAX,[ECX+SSS.BottomLow]
    SBB EDX,[ECX+SSS.BottomHigh]
    ADD [EBX+RELOC.AddendLow],EAX
    ADC [EBX+RELOC.AddendHigh],EDX
    MOV [EBX+RELOC.Symbol],EDI
    JMP .90:

.relocAbsRVA:
.relocAbsVA:
    MOV ECX,[EBX+RELOC.Symbol]
    JECXZ .90:
    MOV EDI,[ECX+SYM.Section]
    TEST EDI
    JZ .90:
    MOV EAX,[EDI+SSS.BottomLow]
    MOV EDX,[EDI+SSS.BottomHigh]
    ADD [EBX+RELOC.AddendLow],EAX
    ADC [EBX+RELOC.AddendHigh],EDX
.90:
   EndProcedure RelocCombine
↑ RelocReportUnresolved Pgm
Procedure reports warning W3835 Relocation at [!1S]:!2H is not resolvable in this program format for each unresolved relocation left in program %Pgm.
Input
Pgm points to a linked PGM
Output
-
Error
W3835 if any relocation if left unresolved.
Invoked by
PfbinCompile PfbootCompile PfcomCompile PfmzCompile
RelocReportUnresolved Procedure Pgm
    MOV EBX,[%Pgm]
    BufferRetrieve [EBX+PGM.SegOrdBuffer]               ; ESI,ECX is now an array of pointers to SSS.
    SAR ECX,2
    JZ .90:
.10:LODSD
    JNSt [EAX+SSS.Status],sssSegment,.80:
    PUSH ECX,ESI
      BufferRetrieve [EAX+SSS.RelocBuffer]
      JECXZ .70:
.20:  MOV EAX,[ESI+RELOC.Status]
      JSt EAX,relocResolved|relocIgnore,.60:
      JSt EAX,relocAbsVA,.E7733:
      JSt EAX,relocRel  ,.E7734:
.E7735: Msg '7735',EAX,[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Relocation type 0x!1W at [!2S]:!3H is not resolvable in this program format.
      JMPS .60:
.E7733: Msg '7733',[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Absolute relocation at [!2S]:!3H is not resolvable in this program format.
      JMPS .60:
.E7734: Msg '7734',[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Relative relocation at [!2S]:!3H is not resolvable in this program format.
.60:  ADD ESI,SIZE# RELOC
      SUB ECX,SIZE# RELOC
      JA .20:
.70:POP ESI,ECX
.80:LOOP .10:
.90:EndProcedure RelocReportUnresolved
↑ RelocResolve Relocation, BaseProgram
RelocResolve will try to resolve one relocation.
It is invoked when an executable program is combined and linked, external symbols resolved and virtual segment addresses fixed in image.
Input
Relocation = ^RELOC.
BaseProgram is pointer to PGM.
Output
Data or code in SSS.EmitBuffer is modified: emited relocable Word/Dword/Fword pointed to by Relocation.Org is fixed up according to the relocation type.
Resolved relocation in is then marked as relocResolved.
Error
-
Invoked by
SssRelocResolve
RelocResolve Procedure Relocation, BaseProgram
EmittedBottom      LocalVar ; Pointer to the bottom of emitted data (withing the contents of SSS.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.
Pgmopt             LocalVar ; Program format and model (cache copy of Program.Pgmopt.Status).
     MOV EBX,[%BaseProgram]
     MOV EAX,[EBX+PGM.Pgmopt.Status]
     MOV [%Pgmopt],EAX
     MOV ESI,[%Relocation]
     MOV EAX,[ESI+RELOC.Section]
     BufferRetrieve [EAX+SSS.EmitBuffer]         ; Mark borders of emitted contents.
     ADD ECX,ESI
     MOV [%EmittedBottom],ESI
     MOV [%EmittedTop],ECX
     MOV ESI,[%Relocation]
.20: MOV EDI,[ESI+RELOC.Status]
     JSt EDI,relocIgnore,.90:                    ; If relocation ESI is already resolved or if its a Disp8*N decoration.
     JNSt EDI,relocWidthMask,.E7920:             ; Invalid fixup at [!1S]:!2Hh.
     MOV EBX,[ESI+RELOC.Symbol]                  ; Target symbol of the relocation ESI.
     TEST EBX
     JNZ .30:
     MOV EAX,pgmoptFormatMask
     AND EAX,[%Pgmopt]
     Dispatch AL,pgmoptBIN,pgmoptBOOT
     JMP .90:
.pgmoptBIN:
.pgmoptBOOT:                                     ; Formats which allow absolute scalar target.
     SetSt [ESI+RELOC.Status],relocResolved
     JMP .50:
.30: MOV ECX,[EBX+SYM.SymbPtr]                   ; Is the external symbol EBX really resolved to public symbol ECX?
     JECXZ .40:
     MOV [ESI+RELOC.Symbol],ECX                  ; Replace external target EBX with its resolved public/PLT symbol ECX.
     MOV EBX,ECX
.40: MOV ECX,[EBX+SYM.Section]
     MOV EAX,relocExtAttr
     MOV EDX,ECX                                 ; Prepare registers for handlers of postponed attribute evaluation.
     AND EAX,EDI
     JZ .dictAttrNONE:
     SHR EAX,16                                  ; Convert relocExtAttr to dictAttr* (1..9).
     Dispatch AL,dictAttrOFFSET,dictAttrSECTION,dictAttrSEGMENT,dictAttrGROUP,dictAttrPARA,dictAttrSIZE,dictAttrTYPE
     JMP .dictAttrNONE:                          ; Target symbol is not attributed.
     ; Attribute dispatching: EBX=^SYM target (never 0), ECX=EDX=^SSS of target symbol (0 when scalar), ESI=^RELOC.
.Scalar:
     XOR EBX,EBX
     JMP .50:
.dictAttrSECTION:
     JECXZ .Scalar:
     JSt [EBX+SYM.Status],symSe,.dictAttrNONE:
.D2: MOV EAX,[EDX+SSS.SymPtr]                     ; Replace the target symbol with section's bottom symbol (symSe).
     MOV [ESI+RELOC.Symbol],EAX
     JMP .dictAttrNONE:
.dictAttrSEGMENT:
     JECXZ .Scalar:
     MOV ECX,[EDX+SSS.SegmPtr]
     JECXZ .D2:
     MOV EDX,ECX
     JMP .D2:                                     ; Replace the target symbol with segment's bottom symbol (symSe).
.dictAttrGROUP:
     JECXZ .Scalar:
     MOV ECX,[EDX+SSS.SegmPtr]
     JECXZ .D2:
     MOV EDX,ECX
     MOV ECX,[EDX+SSS.GroupPtr]
     JECXZ .D2:
     MOV EDX,ECX
     JMP .D2:                                     ; Replace the target symbol with group's bottom symbol (symSe).
.dictAttrPARA:
     RstSt [ESI+RELOC.Status],relocTypeMask
     SetSt [ESI+RELOC.Status],relocPara
     JMP .dictAttrGROUP:                          ; Replace the target symbol with group's bottom symbol (symSe).
.dictAttrOFFSET:
     MOV EAX,[EBX+SYM.OffsetLow]
     JMP .D4:

.dictAttrTYPE:
     MOV EAX,[EBX+SYM.Status]
     AND EAX,symTypeMask
     JMP .D4:
.dictAttrSIZE:
     MOV EAX,[EBX+SYM.Size]
.D4: XOR EDX,EDX
     ADD [ESI+RELOC.AddendLow],EAX
     ADC [ESI+RELOC.AddendHigh],EDX
     MOV [ESI+RELOC.Symbol],EDX
.dictAttrNONE:
     MOV EDI,[ESI+RELOC.Status]
     MOV EBX,[ESI+RELOC.Symbol]
     XOR ECX,ECX
     TEST EBX                                    ; EBX=0 when the target is scalar.
     JZ .50:
     MOV ECX,[EBX+SYM.Section]
     ; EBX=^SYM of target (0 when ExtAttr resolved to scalar), ECX=^SSS of target symbol (0 when scalar),  ESI=^RELOC, EDI=RELOC.Status
.50: MOV EAX,[ESI+RELOC.AddendLow]
     MOV EDX,[ESI+RELOC.AddendHigh]
     AND EDI,relocTypeMask
     Dispatch EDI,relocRel,relocAbsVA,relocFar,relocPara,relocAbsRVA
.E7735:Msg '7735',EDI,[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Relocation type 0x!1W at [!2S]:!3H is not resolvable in this program format.
     JMP .90::
.E7925: Msg '7925',EBX,[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Unresolved relocation of symbol "!1S" at [!2S]:!3Hh.
     JMP .90::
.E7920: Msg '7920',[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Invalid fixup at [!1S]:!2Hh.
     JMP .90::
.E7927: Msg '7927',[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Relocation offset out of 4GB range at [!1S]:!2Hh.
     JMP .90::

.relocRel: ; Relative relocation is resolvable if target segment ECX=[ESI+RELOC.Section] or if both are sssLinked.
    MOV EDI,[ESI+RELOC.Section]
    CMP ECX,EDI
    JE .R2:                                              ; Resolve if intrasegment relative relocation.
    JNSt [%Pgmopt],pgmoptImage,.90:                ; Do not resolve when this format may be combined and linked into image later.
    TEST EBX
    JZ .R4:
    JNSt [EDI+SSS.Status],sssLinked,.90::          ; Ignore when this segment is not linked yet.
    JECXZ .R2:                                           ; Scalar target segment is treated as sssLinked.
    JNSt [ECX+SSS.Status],sssLinked,.90::          ; Ignore when target segment is not linked yet.
.R2:SetSt [ESI+RELOC.Status],relocResolved
    ADD EAX,[EBX+SYM.OffsetLow]
    ADC EDX,[EBX+SYM.OffsetHigh]
    JECXZ .R4:
    ADD EAX,[ECX+SSS.BottomLow]
    ADC EDX,[ECX+SSS.BottomHigh]
.R4:SUB EAX,[ESI+RELOC.OrgLow]
    SBB EDX,[ESI+RELOC.OrgHigh]
    MOV ECX,[ESI+RELOC.Section]
    SUB EAX,[ECX+SSS.BottomLow]
    SBB EDX,[ECX+SSS.BottomHigh]
    JMP .Apply:

.relocAbsRVA:  ; ImageBase absolute relocation is resolvable only if target segment is sssLinked.
     MOV EDI,[%BaseProgram]
     SUB EAX,[EDI+PGM.Pgmopt.ImageBaseLow]
     SBB EDX,[EDI+PGM.Pgmopt.ImageBaseHigh]
.relocAbsVA:   ; Absolute relocation is resolvable only if target segment ECX is sssLinked or none (scalar).
     CALL .Abs:
     JC .90::
     SetSt [ESI+RELOC.Status],relocResolved
     JMP .Apply:

.relocFar:  ; Far relocation is resolvable only if target segment is sssLinked.
            ; It is resolved in two parts: as relocAbsVA (relocWidth16|relocWidth32) and then as relocPara (relocWidth16).
     CALL .Abs:
     JC .90::
     JMP .Apply:                                 ; Apply the relocation of offset portion, then continue with relocPara.

.relocPara:  ; Frame of paragraph relocation is the group (if exists) or the segment of target.
     JECXZ .P2:
     JNSt [ECX+SSS.Status],sssLinked,.90:: ; Ignore when the target segment ECX is not linked yet.
     MOV EBX,[ECX+SSS.SymPtr]
     MOV ECX,[ECX+SSS.GroupPtr]
     JECXZ .P2:
     MOV EBX,[ECX+SSS.SymPtr]
.P2: MOV [ESI+RELOC.Symbol],EBX
     TEST EBX
     JZ .P3:
     MOV ECX,[EBX+SYM.Section]
     CMPB [%Pgmopt],pgmoptMZ                     ; Paragraph relocation in MZ executable will be fixed-up by the DOS loader.
     JE .P4:                                     ; relocPara will be finally resolved in PfmzCompile.
.P3: SetSt [ESI+RELOC.Status],relocResolved      ; Formats BIN, BOOT, COM are fixed-up here to the absolute paragraph address.
.P4: JECXZ .Apply:
     JSt [%Pgmopt],pgmoptFLAT,.Apply:            ; Let segment part 0 in FLAT model.
     ADD EAX,[ECX+SSS.BottomLow]
     ADC EDX,[ECX+SSS.BottomHigh]
     JNZ .E7927:                                 ; Relocation offset out of 4GB range at [!1S]:!2Hh.
;.P6: ;TEST AL,0x0F
     ;Msg cc=NZ,'7928',ECX,[ESI+RELOC.Section],[ESI+RELOC.OrgLow] ; Unaligned target segment [!1S] of relocation at [!2S]:!3Hh.
     SHR EAX,4                                   ; Convert linear address to the paragraph address.
     ;JMP .Apply:

.Apply:                                          ; Add EDX:EAX to the relocated object identified at ESI+RELOC.Org.
     MOV EDI,[ESI+RELOC.OrgLow]
     MOV ECX,[ESI+RELOC.OrgHigh]
     ADD EDI,[%EmittedBottom]                    ; EDI=pointer to the relocated object in emitted code.
     ADC ECX,0
     JNZ .E7927:                                 ; Relocation offset out of 4GB range at [!1S]:!2Hh.
     MOV ECX,[ESI+RELOC.Status]
     MOV EBX,ECX
     AND ECX,relocWidthMask
     SHR ECX,19                                  ; Convert relocWidth to the object size 2,4,8.
     ADD ECX,EDI
     CMP ECX,[%EmittedTop]                       ; Check if RELOC.Org is within the emitted code.
     JA .E7920:                                  ; Invalid fixup at [!1S]:!2Hh.
     JNSt EBX,relocWidth64,.W32:
     ADD [EDI+0],EAX
     ADC [EDI+4],EDX
     JMP .60:
.W32:JNSt EBX,relocWidth32,.W16:
     ADD [EDI],EAX
     JMP .60:
.W16:JNSt EBX,relocWidth16,.60:                  ; Ignore relocations with undefined width.
     ADD [EDI],AX
.60: JNSt [ESI+RELOC.Status],relocFar,.90::
     ADD [ESI+RELOC.OrgLow],2                    ; Offset part of FAR relocation was resolved. Change relocFar to unresolved 16bit relocPara.
     JNSt [ESI+RELOC.Status],relocWidth32,.70:
     ADD [ESI+RELOC.OrgLow],2                    ; Only when relocFar is 16:32 bits.
.70: RstSt [ESI+RELOC.Status],relocFar+relocWidth32+relocWidth64
     SetSt [ESI+RELOC.Status],relocPara+relocWidth16 ; Change relocFar to relocPara.
     JMP .20:                                    ; Resolve the same relocFar record once again, this time as relocPara.

.Abs:PROC1  ; Input: ESI=^RELOC; EBX=^SYM; ECX=^SSS; EDX:EAX=addend. Output: CF=not resolvable; EDX:EAX updated, ready to apply; EDI clobbered.
     JECXZ .A5:                                  ; Resolvable if EBX is a scalar symbol.
     JSt [ECX+SSS.Status],sssLinked,.A1:
     STC                                         ; Do not resolve when target segment is not linked yet.
     JMP .A9:
.A1: JSt [%Pgmopt],pgmoptFLAT,.A3:               ; Use VA (segment bottom) instead of SVA in FLAT model.
     MOV EDI,[ECX+SSS.GroupPtr]                  ; Frame whose PARA# is assumed in segment register.
     TEST EDI
     JNZ .A2:
     MOV EDI,[ECX+SSS.BottomLow]                 ; Bottom of segment ECX is used as the addressing frame.
     AND EDI,0x0000_000F
     ADD EAX,EDI
     ADC EDX,0
     JMP .A5:
.A2: SUB EAX,[EDI+SSS.BottomLow]
     SBB EDX,[EDI+SSS.BottomHigh]
     MOV EDI,[EDI+SSS.BottomLow]                 ; Bottom of group EDI is used as the addressing frame.
     AND EDI,0x0000_000F                         ; Correction when the relocation frame assumed in segment register was not OWORD aligned.
     ADD EAX,EDI
     ADC EDX,0
.A3: ADD EAX,[ECX+SSS.BottomLow]
     ADC EDX,[ECX+SSS.BottomHigh]
.A5: TEST EBX
   ;  STC
     JZ .A9:
     ADD EAX,[EBX+SYM.OffsetLow]
     ADC EDX,[EBX+SYM.OffsetHigh]
   ;  CLC
.A9: RET
     ENDP1 .Abs:

.90:EndProcedure RelocResolve
 ENDPROGRAM reloc

▲Back to the top▲