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. INCLUDEHEAD \ ; Include headers of another modules used in this module. ea.htm, \ eaopt.htm, \ exp.htm, \ msg.htm, \ pf.htm, \ pfelf.htm, \ pgm.htm, \ pgmopt.htm, \ reloc.htm, \ sss.htm, \ stm.htm, \ sym.htm, \ syswin.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],EBX ; Group alignment = highest alignment of its segments. mov [EDX+SSS.Alignment],%LinPageSize .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 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 ; [.dynstr]. .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