This EuroAssembler source pfelfx.htm
generates output executable file in program format ELF as described in
[ELF32] and
[ELF64].
Section in ELF documentation is equivalent to €ASM SEGMENT.
Program in ELF documentation is equivalent to €ASM GROUP.
pfelfx PROGRAM FORMAT=COFF,MODEL=FLAT,WIDTH=32
INCLUDEHEAD euroasm.htm, \ Interface (structures, symbols and macros) of other modules used in this source.
ea.htm,eaopt.htm,exp.htm,msg.htm,pf.htm,pfelf.htm,pgm.htm,pgmopt.htm,reloc.htm,sss.htm,stm.htm,sym.htm
pfelfx HEAD ; Start module interface. %LinPageSize %SETA 4K ; Memory page size fixed at 1000h in 32bit Linux.
ENDHEAD pfelfx
PfelfxLoadPgm reads the contents of one ELF file
and converts it to structures of a fresh new program, which then will be stored on
BasePgm.ModulePgmList.
This procedure works with ELF types Relocatable, Executable and SharedObject in both 32bit and 64bit mode.
BasePgm.ModulePgmList as a new
PGM structure.
PfelfxLoadPgm Procedure BasePgm, ObjBegin, ObjSize, FileNamePtr
Msg '8534',Dict_FormatELFX::,[%FileNamePtr] ; Format !1S of file "!2$" is not linkable.
EndProcedure PfelfxLoadPgm
PfelfxLink calculates size, alignment, virtual and file address of every program segment.
It does not change the contents of SSS.EmitBuffer, SSS.RelocBuffer;
the actual raw contents of segments is not concatenated into image here because relocations are not resolved yet.
PfelfxLink Procedure Pfelf
ArrayPtr LocalVar ; Pointer into the array of DWORD pointers to SSS groups and segments (ELF programs and sections).
ArrayEnd LocalVar ; Behind the last pointer of the array.
Size LocalVar ; Virtual (emitted or reserved) segment size.
FA LocalVar ; Current file address when linked.
VALow LocalVar ; Current virtual address when linked, including ImageBase.
VAHigh LocalVar
FileAlign LocalVar ; PGMOPT.FileAlign.
SectionAlign LocalVar ; PGMOPT.SectionAlign.
MOV EDI,[%Pfelf]
MOV EBX,[EDI+PFELF.Pgm]
MOV EAX,[EBX+PGM.Pgmopt.FileAlign]
MOV EDX,[EBX+PGM.Pgmopt.SectionAlign]
MOV [%FileAlign],EAX
MOV [%SectionAlign],EDX
MOV ECX,[EDI+PFELF.HDRsEnd]
MOV [%FA],ECX
MOV EAX,[EBX+PGM.Pgmopt.ImageBaseLow]
MOV EDX,[EBX+PGM.Pgmopt.ImageBaseHigh]
MOV [%VALow],EAX
MOV [%VAHigh],EDX
BufferRetrieve [EBX+PGM.SegOrdBuffer] ; Array of DWORD pointers to SSS.
ADD ECX,ESI
MOV [%ArrayPtr],ESI ; Prepare the main loop for all SSS objects.
MOV [%ArrayEnd],ECX
.10:MOV ESI,[%ArrayPtr] ; The main loop: Adjust FA and VA of all segments.
CMP ESI,[%ArrayEnd]
JNB .35: ; End when all segments were linked.
LODSD
MOV [%ArrayPtr],ESI
MOV EBX,EAX ; EBX is the linked group or segment.
CMPD [EBX+SSS.NameSize],0
JZ .10: ; Ignore the empty segment [] (ELF NULL section).
; Fork groups (ELF program headers) and segments (ELF sections).
JSt [EBX+SSS.Status],sssSegment,.20:
JNSt [EBX+SSS.Status],sssGroup,.10:
; Link the €ASM group EBX, also called "ELF program header".
MOV EAX,[%VALow] ; A new [LOAD.*] group has different access flags, %VA rounds up by %LinPageSize.
MOV EDX,[%VAHigh]
Invoke ExpAlign::,EAX,%LinPageSize,0
ADD EAX,ECX
ADC EDX,0
MOV [%VALow],EAX
MOV [%VAHigh],EDX
JMP .10:
.20:; Link the €ASM segment EBX, also called "ELF section".
SetSt [EBX+SSS.Status],sssLinked ; This will tell relocation resolver that its VA is already fixed.
MOV EAX,[EBX+SSS.TopLow] ; Compute segment size in memory.
MOV EDX,[EBX+SSS.TopHigh]
SUB EAX,[EBX+SSS.BottomLow]
SBB EDX,[EBX+SSS.BottomHigh]
Msg cc=NZ,'8525',EBX ; Size of segment [!1S] exceeded 4 GB.
MOV [%Size],EAX
; Compute segment's file address.
MOV EAX,[%FA] ; Top FA of previous segment.
MOV ECX,[EBX+SSS.Alignment] ; Segment's own alignment.
JNSt [EBX+SSS.Purpose],sssPurposeDYNAMIC,.25:
mov ecx,%LinPageSize
.25:JSt [EBX+SSS.Purpose],sssPurposeElfMask,.30: ; PROGRAM FileAlign= is ignored for ELF-special sections .symtab, .strtab etc.
CMP ECX,[%FileAlign]
JAE .30:
MOV ECX,[%FileAlign] ; PROGRAM FileAlign= applies to regular sections .text, .data etc.
.30:Invoke ExpAlign::,EAX,ECX,0
ADD EAX,ECX
MOV [EBX+SSS.BottomFA],EAX
BufferRetrieve [EBX+SSS.EmitBuffer]
ADD EAX,ECX
MOV [EBX+SSS.TopFA],EAX
MOV [%FA],EAX
; Compute segment's memory address.
MOV ECX,%LinPageSize-1 ; 0x0000_0FFF
AND ECX,[EBX+SSS.BottomFA]
MOV EAX,[%VALow]
MOV EDX,[%VAHigh]
AND EAX,~(%LinPageSize-1)
OR EAX,ECX ; Make FA and VA congruent.
MOV [EBX+SSS.BottomLow],EAX
MOV [EBX+SSS.BottomHigh],EDX
ADD EAX,[%Size]
ADC EDX,0
MOV [EBX+SSS.TopLow],EAX
MOV [EBX+SSS.TopHigh],EDX
MOV [%VALow],EAX
MOV [%VAHigh],EDX
JMP .10:
.35:MOV EBX,[EDI+PFELF.Pgm]
Invoke PgmResizeGroups::,EBX ; Update VA of groups by their segments.
; Special adjustment of group [LOAD.HDR]
MOV ECX,[EDI+PFELF.Sss.LOAD.HDR]
JECXZ .40:
MOV EAX,[EBX+PGM.Pgmopt.ImageBaseLow]
MOV EDX,[EBX+PGM.Pgmopt.ImageBaseHigh]
MOV [ECX+SSS.BottomLow],EAX
MOV [ECX+SSS.BottomHigh],EDX
MOVD [ECX+SSS.BottomFA],0
.40:
; Special adjustment of group [DYNAMIC] - copies FA and VA from segment [.dynamic].
MOV ECX,[EDI+PFELF.Sss.dynamic]
JECXZ .45:
MOV ESI,[EDI+PFELF.Sss.DYNAMIC]
MOV EAX,[ECX+SSS.BottomLow]
MOV EDX,[ECX+SSS.BottomHigh]
MOV [ESI+SSS.BottomLow],EAX
MOV [ESI+SSS.BottomHigh],EDX
MOV EAX,[ECX+SSS.TopLow]
MOV EDX,[ECX+SSS.TopHigh]
MOV [ESI+SSS.TopLow],EAX
MOV [ESI+SSS.TopHigh],EDX
MOV EAX,[ECX+SSS.BottomFA]
MOV EDX,[ECX+SSS.TopFA]
MOV [ESI+SSS.BottomFA],EAX
MOV [ESI+SSS.TopFA],EDX
.45:MOV ECX,16
JSt [EDI+PFELF.Status],pfelfWidth64,.50:
MOV CL,8
.50:MOV [ESI+SSS.Alignment],ECX
; Special adjustment of group [PHDR] which covers PT_PHDR records only, FA starts at 40h (fixed), VA at ImageBase+40h. Size=%PHDRsize.
MOV ESI,[EDI+PFELF.Sss.PHDR]
TEST ESI
JZ .70:
MOV EAX,40h ; SIZE# PFELF_EHDR rounded up to 16.
XOR EDX,EDX
MOV [ESI+SSS.BottomFA],EAX
MOV [ESI+SSS.TopFA],EAX
ADD EAX,[EBX+PGM.Pgmopt.ImageBaseLow]
ADC EDX,0
MOV [ESI+SSS.BottomLow],EAX
MOV [ESI+SSS.BottomHigh],EDX
MOV [ESI+SSS.TopLow],EAX
MOV [ESI+SSS.TopHigh],EDX
PUSH ESI
BufferRetrieve [EBX+PGM.SegOrdBuffer]
SUB EDX,EDX
SHR ECX,2
JZ .65:
.55: LODSD
JNSt [EAX+SSS.Status],sssGroup,.60:
ADD EDX,[EDI+PFELF.PHDRSize]
.60: LOOP .55:
.65:POP ESI ; EDX is SIZE#[PHDR].
ADD [ESI+SSS.TopFA],EDX
ADD [ESI+SSS.TopLow],EDX
ADCD [ESI+SSS.TopHigh],0
.70: ; Special adjustment of group [INTERP] - copies FA and VA from segment [.interp].
MOV ECX,[EDI+PFELF.Sss.interp]
JECXZ .90:
MOV ESI,[EDI+PFELF.Sss.INTERP]
MOV EAX,[ECX+SSS.BottomLow]
MOV EDX,[ECX+SSS.BottomHigh]
MOV [ESI+SSS.BottomLow],EAX
MOV [ESI+SSS.BottomHigh],EDX
MOV EAX,[ECX+SSS.TopLow]
MOV EDX,[ECX+SSS.TopHigh]
MOV [ESI+SSS.TopLow],EAX
MOV [ESI+SSS.TopHigh],EDX
MOV EAX,[ECX+SSS.BottomFA]
MOV EDX,[ECX+SSS.TopFA]
MOV [ESI+SSS.BottomFA],EAX
MOV [ESI+SSS.TopFA],EDX
MOVD [ESI+SSS.Alignment],1
.90:EndProcedure PfelfxLink
PfelfxCompile Procedure OutputStream, Pgm
Pfelf LocalVar Size=SIZE# PFELF ; PFELF object.
MOV EBX,[%Pgm]
LEA EDI,[%Pfelf]
Invoke PfelfCreate::,EDI,EBX
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"LOAD.HDR",8,0,sssPurposeRODATA
MOV [EDI+PFELF.Sss.LOAD.HDR],EAX
MOV [EAX+SSS.Alignment],%LinPageSize
Invoke PfelfSssTab::,EDI,EAX ; Create ELF-special empty SSS segments [], [.symtab], [.strtab], [.shstrtab].
JNSt [EDI+PFELF.Status],pfelfDynamic,.11: ; Skip when none of linked modules is ELFSO (ELFX is being statically linked).
Invoke PfelfsoSssDynTab::,EDI,EAX ; Create ELFSO-special SSS segments: [.dynamic], [.dynsym], [.hash], [.dynstr], [.rel(a).dyn]. [.interp].
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"INTERP",6,0,sssPurposeINTERP
MOV [EDI+PFELF.Sss.INTERP],EAX
MOV [EAX+SSS.Alignment],1
.11: ; Create groups of regular segments.
Invoke PfelfSssSeg::,EDI ; Fill PFELF.Buffer.CODE/RODATA/DATA with pointers to segments.
BufferRetrieve [EDI+PFELF.Buffer.CODE]
SHR ECX,2
JZ .17: ; Do not create [LOAD.CODE] group when no CODE/PLT segment exists.
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"LOAD.CODE",9,0,0
MOV EDX,EAX
MOV [EDX+SSS.Alignment],%LinPageSize
MOV [EDI+PFELF.Sss.LOAD.CODE],EDX ; EDX is the just created SSS group, i.e. ELF program segment.
.13:LODSD ; EAX is one of SSS segments which belongs to the group EDX.
MOV [EAX+SSS.GroupPtr],EDX
MOV EBX,[EAX+SSS.Alignment]
CMP EBX,[EDX+SSS.Alignment]
JBE .15:
MOV [EDX+SSS.Alignment],EBX ; Group alignment = highest alignment of its segments.
.15:LOOP .13:
.17:BufferRetrieve [EDI+PFELF.Buffer.RODATA]
SHR ECX,2
JZ .23: ; Do not create [LOAD.RODATA] group when no RODATA segment exists.
MOV EBX,[EDI+PFELF.Pgm]
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"LOAD.RODATA",11,0,0
MOV EDX,EAX
MOV [EDX+SSS.Alignment],%LinPageSize
MOV [EDI+PFELF.Sss.LOAD.RODATA],EDX
.19:LODSD
MOV [EAX+SSS.GroupPtr],EDX
MOV EBX,[EAX+SSS.Alignment]
CMP EBX,[EDX+SSS.Alignment]
JBE .21:
MOV [EDX+SSS.Alignment],%LinPageSize ; Group alignment = highest alignment of its segments.
.21:LOOP .19:
.23:BufferRetrieve [EDI+PFELF.Buffer.DATA]
SHR ECX,2
JZ .29: ; Do not create [LOAD.DATA] group when no DATA/GOT/BSS segment exists.
MOV EBX,[EDI+PFELF.Pgm]
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"LOAD.DATA",9,0,0
MOV EDX,EAX
MOV [EDX+SSS.Alignment],%LinPageSize
MOV [EDI+PFELF.Sss.LOAD.DATA],EDX
.25:LODSD
MOV [EAX+SSS.GroupPtr],EDX
MOV EBX,[EAX+SSS.Alignment]
CMP EBX,[EDX+SSS.Alignment]
JBE .27:
MOV [EDX+SSS.Alignment],EBX ; Group alignment = highest alignment of its segments.
.27:LOOP .25:
.29:MOV EBX,[EDI+PFELF.Pgm]
JNSt [EDI+PFELF.Status],pfelfDynamic,.33: ; Skip when none of linked modules is ELFSO (ELFX is being statically linked).
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"PHDR",4,0,sssPurposePHDR
MOV [EDI+PFELF.Sss.PHDR],EAX
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"LOAD.DYNAMIC",12,0,sssPurposeDATA
MOV [EDI+PFELF.Sss.LOAD.DYNAMIC],EAX
MOV [EAX+SSS.Alignment],%LinPageSize
Invoke SssCreateGroup::,[EBX+PGM.CurrentStm],=B"DYNAMIC",7,0,sssPurposeDYNAMIC
MOV [EDI+PFELF.Sss.DYNAMIC],EAX
mov [EAX+SSS.Alignment],%LinPageSize
MOV ECX,16
JSt [EDI+PFELF.Status],pfelfWidth64,.31:
MOV CL,8
.31:MOV ESI,[EDI+PFELF.Sss.dynamic]
MOV [ESI+SSS.GroupPtr],EAX
MOV [ESI+SSS.Alignment],ECX
.33:MOV EBX,[EDI+PFELF.Pgm]
; All groups and segments are created now (but not their contents yet).
; Set the order of ELF special groups and segments into PGM.SegOrdBuffer.
MOV ECX,[EDI+PFELF.Sss.PHDR]
JECXZ .35:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [PHDR].
.35:MOV ECX,[EDI+PFELF.Sss.INTERP]
JECXZ .37:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [INTERP].
.37:BufferStoreDword [EBX+PGM.SegOrdBuffer],[EDI+PFELF.Sss.LOAD.HDR] ; [LOAD.HDR].
BufferStoreDword [EBX+PGM.SegOrdBuffer],[EDI+PFELF.Sss] ; [] (NULL section).
BufferStoreDword [EBX+PGM.SegOrdBuffer],[EDI+PFELF.Sss.symtab] ; [.symtab].
MOV ECX,[EDI+PFELF.Sss.dynsym]
JECXZ .39:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.dynsym].
.39:MOV ECX,[EDI+PFELF.Sss.rela.dyn]
JECXZ .41:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.rela.dyn].
.41:MOV ECX,[EDI+PFELF.Sss.rela.plt]
JECXZ .43:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.rela.plt].
.43:MOV ECX,[EDI+PFELF.Sss.hash]
JECXZ .45:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.hash].
.45:MOV ECX,[EDI+PFELF.Sss.dynstr]
JECXZ .47:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.dynstr].
.47:MOV ECX,[EDI+PFELF.Sss.interp]
JECXZ .49:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [.interp].
.49:BufferStoreDword [EBX+PGM.SegOrdBuffer],[EDI+PFELF.Sss.strtab] ; [.strtab].
BufferStoreDword [EBX+PGM.SegOrdBuffer],[EDI+PFELF.Sss.shstrtab] ; [.shstrtab].
MOV ECX,[EDI+PFELF.Sss.LOAD.CODE]
JECXZ .51:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [LOAD.CODE].
BufferRetrieve [EDI+PFELF.Buffer.CODE]
BufferStore [EBX+PGM.SegOrdBuffer],ESI,ECX ; [.text], [.plt] (all code sections).
.51:MOV ECX,[EDI+PFELF.Sss.LOAD.RODATA]
JECXZ .53:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [LOAD.RODATA].
BufferRetrieve [EDI+PFELF.Buffer.RODATA]
BufferStore [EBX+PGM.SegOrdBuffer],ESI,ECX ; [.rodata] (all read-only data sections).
.53:MOV ECX,[EDI+PFELF.Sss.LOAD.DATA]
JECXZ .55:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [LOAD.DATA].
BufferRetrieve [EDI+PFELF.Buffer.DATA]
BufferStore [EBX+PGM.SegOrdBuffer],ESI,ECX ; [.data], [.got], [.bss] (all data+bss sections).
.55:MOV ECX,[EDI+PFELF.Sss.LOAD.DYNAMIC]
JECXZ .57:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [LOAD.DYNAMIC].
MOV EAX,[EDI+PFELF.Sss.dynamic]
MOV [EAX+SSS.GroupPtr],ECX
BufferStoreDword [EBX+PGM.SegOrdBuffer],EAX ; [.dynamic].
.57:MOV ECX,[EDI+PFELF.Sss.DYNAMIC]
JECXZ .59:
BufferStoreDword [EBX+PGM.SegOrdBuffer],ECX ; [DYNAMIC].
.59:BufferRetrieve [EBX+PGM.SegOrdBuffer] ; Enumerate and specify SSS.Segmindex of all ordered segments.
SUB EDX,EDX ; EDX keeps SSS.SegmIndex.
ADD ECX,ESI
.61:CMP ESI,ECX
JNB .63:
LODSD
JNSt [EAX+SSS.Status],sssSegment,.61:
MOV [EAX+SSS.SegmIndex],EDX
INC EDX
JMP .61:
.63:MOV ESI,[EDI+PFELF.Sss.rela.plt]
MOV EDX,[EDI+PFELF.Sss.dynsym]
TEST EDX
JZ .65:
MOV EAX,[EDX+SSS.SegmIndex]
MOV [ESI+SSS.sh_link],EAX
.65:MOV EDX,[EDI+PFELF.Sss.got]
TEST EDX
JZ .67:
MOV EAX,[EDX+SSS.SegmIndex]
MOV [ESI+SSS.sh_info],EAX
.67:Invoke PgmOrderSymbols::,EBX ; Put ^SYM dwords to Pgm.SymOrdBuffer. SYM.NameIndex and SYM.NameDynIndex are not set yet.
; Enumerate and specify SYM.NameIndex and SYM.NameDynIndex for symbols in PGM.SegOrdBuffer.
BufferRetrieve [EBX+PGM.SymOrdBuffer]
ADD ECX,ESI
SUB EDX,EDX ; EDX keeps SYM.NameIndex.
SUB EBX,EBX ; EBX keeps SYM.NameDynIndex.
.69:CMP ESI,ECX
JNB .71:
LODSD
MOV [EAX+SYM.NameIndex],EDX
INC EDX
JNSt [EAX+SYM.Status],symImport,.69:
INC EBX
MOV [EAX+SYM.NameDynIndex],EBX
JMP .69:
.71:; All SSS and SYM are indexed now.
MOV EBX,[EDI+PFELF.Pgm]
JNSt [EDI+PFELF.Status],pfelfDynamic,.73: ; Skip when none of linked modules is ELFSO (ELFX is being statically linked).
Invoke PfelfxPltGot,EDI ; Emit the contens of [.plt],[.got],[.rel(a).plt].
.73:Invoke PfelfConvertSymbols,EDI,0 ; Convert €ASM symbols to PFELF_SYM in [.symtab], write their names to [.strtab]. Set SYM.NameIndex.
JNSt [EDI+PFELF.Status],pfelfDynamic,.75: ; Skip when none of linked modules is ELFSO (ELFX is being statically linked).
Invoke PfelfConvertSymbols::,EDI,pfelfDyn ; Convert €ASM symbols to PFELF_SYM in [.dynsym], write their names to [.dynstr]. Set SYM.NameDynIndex.
Invoke PfelfsoHashTable::,EDI ; Fill [.hash] SSS.EmitBuffer.
Invoke PfelfsoDynamic::,EDI ; Fill [.dynamic] SSS.EmitBuffer.
; All SYM and SSS are indexed.
.75:Invoke PfelfShdr::,EDI ; Create ELF section headers, pass 1.
Invoke PfelfHdrsLink::,EDI ; Calculate PFELF.HDRsEnd.
Invoke PfelfxLink,EDI ; Set VA, FA, sizes of all ELF "program segments" and "sections".
JNSt [EDI+PFELF.Status],pfelfDynamic,.77: ; Skip when none of linked modules is ELFSO (ELFX is being statically linked).
.77:Invoke PgmRelocResolve::,[EDI+PFELF.Pgm]
Invoke PfelfPhdr::,EDI
Invoke PfelfEhdr::,EDI,pfelfExec ; Create ELF file header.
Invoke PfelfShdr::,EDI ; Create ELF section headers, pass 2.
MOV EDX,[%OutputStream]
Invoke PfelfHdrsStream::,EDI,EDX
Invoke PgmStreamImage::,EBX,EDX
Invoke PfelfDestroy::,EDI
EndProcedure PfelfxCompile
PfelfxPltGot Procedure Pfelf
SymPtr LocalVar
SymEnd LocalVar
Sym@impPtr LocalVar ; Original imported symbol in [sssImport]
Sym@pltPtr LocalVar ; Homonymous copy in [.plt].
Sym@gotPtr LocalVar ; Homonymous copy in [.got].
DynIndex LocalVar
ClearLocalVar
MOV EDI,[%Pfelf]
MOV EBX,[EDI+PFELF.Pgm]
BufferRetrieve [EBX+PGM.SymOrdBuffer]
ADD ECX,ESI
MOV [%SymPtr],ESI
MOV [%SymEnd],ECX
.10:MOV ESI,[%SymPtr]
CMP ESI,[%SymEnd]
JNB .90:
LODSD
MOV [%SymPtr],ESI
JNSt [EAX+SYM.Status],symImport,.10:
MOV [%Sym@impPtr],EAX
MOV EBX,[EDI+PFELF.Pgm]
ListStore [EBX+PGM.SymList],EAX ; Create a homonymous symbol in [.got] as a copy of symbol EAX.
MOV [%Sym@gotPtr],EAX
MOV [EAX+SYM.Status],symPrivate ; Rewrite some properties of both homonymous symbols.
MOV [EAX+SYM.OffsetHigh],0
ListStore [EBX+PGM.SymList],EAX ; Create a homonymous symbol in [.plt].
MOV [%Sym@pltPtr],EAX
MOV EDX,[%Sym@impPtr]
MOV [EDX+SYM.SymbPtr],EAX ; Redirect Sym@imp to Sym@plt to be relocated later.
MOV ESI,[EDI+PFELF.Sss.plt]
MOV [EAX+SYM.Section],ESI ; ESI=^SSS [.plt]
BufferRetrieve [ESI+SSS.EmitBuffer]
ADD ECX,6 ; Skip the size of "JMP symbol@got" emited it .plt
MOV [EAX+SYM.OffsetLow],ECX ; Symbol@plt is ready.
MOV EAX,[%Sym@gotPtr]
MOV EDX,[EDI+PFELF.Sss.got]
MOV [EAX+SYM.Section],EDX
BufferRetrieve [EDX+SSS.EmitBuffer] ; ECX=offset of symbol@got
MOV [EAX+SYM.OffsetLow],ECX ; Symbol@got is ready.
; Create emited contents of [.plt] ; EAX=^Sym@got
MOV ESI,[EDI+PFELF.Sss.plt]
BufferStoreWord [ESI+SSS.EmitBuffer],0x25FF ; JMP sym@got,ADDR=REL
BufferStoreDword [ESI+SSS.EmitBuffer],-4 ; This will be relocated to symbol@got
BufferStoreByte [ESI+SSS.EmitBuffer],0x68 ; PUSHQ imm
MOV ECX,[EAX+SYM.NameDynIndex]
DEC ECX
BufferStoreDword [ESI+SSS.EmitBuffer],ECX
BufferStoreByte [ESI+SSS.EmitBuffer],0xE9 ; JMP .plt,ADDR=REL
BufferStoreDword [ESI+SSS.EmitBuffer],-4 ; This will be relocated to the start of .plt
; Create relocation in .plt for JMP sym@got
BufferNew [ESI+SSS.RelocBuffer],SIZE#RELOC,Zeroed=Yes
MOV EBX,EAX ; EBX=^RELOC
MOV [EBX+RELOC.Section],ESI ; ESI=^SSS [.plt]
BufferRetrieve [ESI+SSS.EmitBuffer]
SUB ECX,14
MOV [EBX+RELOC.OrgLow],ECX
MOV [EBX+RELOC.Status],relocWidth32+relocRel
MOV EDX,[EDI+PFELF.Sss.got]
MOV EAX,[%Sym@gotPtr]
MOV [EBX+RELOC.Symbol],EAX
; Create relocation in .plt for JMP .plt
MOV ESI,[EDI+PFELF.Sss.plt]
BufferNew [ESI+SSS.RelocBuffer],SIZE#RELOC,Zeroed=Yes
MOV EBX,EAX ; EBX=^RELOC
MOV [EBX+RELOC.Section],ESI ; ESI=^SSS [.plt]
ADD ECX,10
MOV [EBX+RELOC.OrgLow],ECX
MOV [EBX+RELOC.Status],relocWidth32+relocRel
;;MOV EAX,[%Sym@pltPtr]
MOV ECX,[EDI+PFELF.Sss.plt]
MOV EAX,[ECX+SSS.SymPtr]
MOV [EBX+RELOC.Symbol],EAX
; Create emited contents of [.got]
MOV ESI,[EDI+PFELF.Sss.got]
BufferStoreQword [ESI+SSS.EmitBuffer],0
; Create relocation of address stored in .got
BufferNew [ESI+SSS.RelocBuffer],SIZE#RELOC,Zeroed=Yes
MOV EBX,EAX ; EBX=^RELOC
MOV [EBX+RELOC.Section],ESI ; ESI=^SSS [.got]
MOV [EBX+RELOC.Status],relocWidth64+relocAbsVA
BufferRetrieve [ESI+SSS.EmitBuffer] ; ECX=offset of symbol@got
SUB ECX,8
MOV [EBX+RELOC.OrgLow],ECX
MOV EAX,[%Sym@pltPtr]
MOV [EBX+RELOC.Symbol],EAX
; Emit dynamic relocation PFELF_RELA* into [.rel(a).plt]
MOV EDX,[EDI+PFELF.Sss.rela.plt]
BufferRetrieve [EDX+SSS.EmitBuffer] ; ECX=offset of PFELF_REL* record in .rel(a).plt
BufferStoreQword [EDX+SSS.EmitBuffer],0 ; PFELF_RELA64.r_offset, will be relocated to symbol@got
BufferStoreDword [EDX+SSS.EmitBuffer],pfelfR_X86_64_JUMP_SLOT ; PFELF_RELA64.r_info.low
MOV EAX,[%Sym@gotPtr]
BufferStoreDword [EDX+SSS.EmitBuffer],[EAX+SYM.NameDynIndex] ; PFELF_RELA64.r_info.high
BufferStoreQword [EDX+SSS.EmitBuffer],0 ; PFELF_RELA64.r_addend
; Create relocation of address in PFELF_RELA64.r_offset pointed to by ECX.
BufferNew [EDX+SSS.RelocBuffer],SIZE# RELOC,Zeroed=Yes
MOV EBX,EAX
MOV [EBX+RELOC.OrgLow],ECX
MOV [EBX+RELOC.Section],EDX
MOV [EBX+RELOC.Status],relocWidth64+relocAbsVA
MOV ECX,[%Sym@gotPtr]
MOV [EBX+RELOC.Symbol],ECX
JMP .10:
.90:Invoke SssUpdateByEmit::,[EDI+PFELF.Sss.plt]
Invoke SssUpdateByEmit::,[EDI+PFELF.Sss.got]
Invoke SssUpdateByEmit::,[EDI+PFELF.Sss.rela.plt]
EndProcedure PfelfxPltGot
ENDPROGRAM pfelfx