%if 0

Extensions for lDebug linker

Copyright (C) 2008-2024 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif

%include "lmacros3.mac"
%include "eld.mac"

	cpu 8086

%if ELDSTRICT
 %if ELDSTRICTCOUNTER
  %error Missing relocation
 %endif
%endif
	eldstrict off		; linker does some relocations

%ifn ELDCALLCALL_DUMPED
	eldcall_dump_callcall ELDCALL_CALLCALL_LIST
%endif

	numdef ELD_IDENTICALISE, 0
	numdef ELD_DEBUG, 0
	numdef ELD_LINKER_PASSES, 1
	strdef LISTING, _ELD_LISTING
	numdef ELDCALL_OPTIONAL, ELDCALL_OPTIONAL_STATUS
	numdef ELDDATA_OPTIONAL, ELDDATA_OPTIONAL_STATUS
%if _ELD_IDENTICALISE
 ;%assign _ELDCALL_OPTIONAL 1
%endif
%ifn _ELDCALL_OPTIONAL
%assign ELDCALL_OPTIONAL_STATUS 2		; not allowed
%endif
;%ifn _ELDDATA_OPTIONAL
;%assign ELDDATA_OPTIONAL_STATUS 2		; not allowed
;%endif


endresident: equ ($ + _CURRENT_SECTION %+ FIXUP + 15) & ~15

%if _ELD_LINKER_PASSES
%assign ELDLINKER 1

	struc LINKTABLE
ltCodeToCode:	resw 2
ltCodeToData:	resw 2
ltDataToCode:	resw 2
ltDataToData:	resw 2
ltLinkData:	resw 2
ltLinkCode:	resw 2
	endstruc
%endif


linker:
		; The first 15 Bytes of the linker should be
		;  the same regardless of the linker options
		;  used (debug, passes, vstart). This allows
		;  the eldcomp ELD to match even if up to 15
		;  Bytes of the linker are trailing in the
		;  resident part of the ELD.
	lframe
 %if ELDOTHER
	lvar dword, linkinfo_other
	lvar word, use_hash_other
 %endif
	lenter
	lvar dword, instance
	 push es
	 push dx
	lvar word, targetsection_low_optional_high
	 push ax
	lequ ?targetsection_low_optional_high, targetsection
	lequ ?targetsection_low_optional_high + 1, optional
	lvar dword, linkinfo
	 push ds
	 push di
	lvar dword, nextreloc
	 push es
	 push dx
	lvar dword, entry
	 push es
	 push ax		; placeholder
	xor ax, ax
	cmp word [di + eldlSignature], 0E1D1h
%if ($ - linker) < 16
 %error Expected invariant first paragraph of linker
%endif
	jne .error_j
	cmp word [di + eldlUseLinkHash], 1
	ja .error_j
	jb @F
	dec ax
@@:
	lvar word, use_hash
	 push ax
%if _ELD_IDENTICALISE && _ELD_LINKER_PASSES
	mov ax, linktable - code
	lvar word, lt
	 push ax
%endif
%if _ELD_LINKER_PASSES || ELDOTHER
	xor ax, ax
 %if _ELD_LINKER_PASSES
	lvar word, pass
	 push ax
	lvar word, amounterrors
	 push ax
	lvar word, name
	 push ax
 %endif
 %if ELDOTHER
	lvar word, other
	 push ax
 %endif
%endif
	push si
	push bx

			; simple: add instance base (dx) to code
	push es
	pop ds
%if _ELD_LINKER_PASSES
.pass:
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	mov si, word [ltCodeToCode + bx]
 %else
	mov si, word [linktable - code + ltCodeToCode + bx]
 %endif
%else
	mov si, internalcodetocoderelocations - code
%endif
	add si, dx
@@:
	lodsw
	test ax, ax		; was last ?
	jz @F			; yes -->
	xchg bx, ax		; bx = entry
	add bx, dx		; relocate the entry itself
%if _ELD_CODE_VSTART
	sub word [bx], code	; undo adjustment
%endif
	add word [bx], dx	; relocate word referenced by entry
	jmp @B

@@:
			; next, add heap data base (on stack) to code
%if _ELD_LINKER_PASSES
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	mov si, word [ltCodeToData + bx]
 %else
	mov si, word [linktable - code + ltCodeToData + bx]
 %endif
%else
	mov si, internalcodetodatarelocations - code
%endif
	add si, dx
@@:
	lodsw
	test ax, ax		; was last ?
	jz @F			; yes -->
	xchg bx, ax		; bx = entry
	add bx, dx		; relocate the entry itself
	pop ax			; ax -> heap data
	push ax
%if _ELD_DATA_VSTART
	sub ax, datastart	; undo adjustment
%endif
	add word [bx], ax	; relocate word referenced by entry
	jmp @B

@@:

			; add instance base (dx) to data
%if _ELD_LINKER_PASSES
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	mov si, word [ltDataToCode + bx]
 %else
	mov si, word [linktable - code + ltDataToCode + bx]
 %endif
%else
	mov si, internaldatatocoderelocations - code
%endif
	add si, dx
@@:
	lodsw
	cmp ax, -1		; was last ?
	je @F			; yes -->
	xchg bx, ax		; bx = entry
	pop ax
	push ax
	add bx, ax		; relocate the entry itself
%if _ELD_CODE_VSTART
	sub word [ss:bx], code	; undo adjustment
%endif
	add word [ss:bx], dx	; relocate word referenced by entry
	jmp @B

@@:
			; next, add heap data base (on stack) to data
%if _ELD_LINKER_PASSES
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	mov si, word [ltDataToData + bx]
 %else
	mov si, word [linktable - code + ltDataToData + bx]
 %endif
%else
	mov si, internaldatatodatarelocations - code
%endif
	add si, dx
@@:
	lodsw
	cmp ax, -1		; was last ?
	je @F			; yes -->
	xchg bx, ax		; bx = entry
	pop ax			; ax -> heap data
	push ax
	add bx, ax		; relocate the entry itself
%if _ELD_DATA_VSTART
	sub ax, datastart	; undo adjustment
%endif
	add word [ss:bx], ax	; relocate word referenced by entry
	jmp @B

@@:
	mov dx, word [bp + ?instance]
%if _ELD_LINKER_PASSES
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	add dx, word [ltLinkData + bx]
 %else
	add dx, word [linktable - code + ltLinkData + bx]
 %endif
%else
	add dx, linkerdatarelocations - code
%endif
.otherloop:
	mov word [bp + ?nextreloc], dx

.datarelocloop:		; must be done before further relocs
	lds si, [bp + ?nextreloc]
	lodsw			; ax = section indicator
	test ax, ax		; end of table ?
	jz .donedatareloc
	dec ax			; al = 1 if data, 0 if code
	pop bx
	push bx			; bx -> ELD data block
	mov word [bp + ?targetsection_low_optional_high], ax
	test al, al		; data ?
	lodsw
	jnz @F			; yes -->
	add ax, word [bp + ?instance]
				; relocate entry into code
	db __TEST_IMM16		; (skip add)
@@:
	add ax, bx		; relocate entry into data
	mov word [bp + ?entry], ax
	lodsw
	mov word [bp + ?nextreloc], si
	call .build_match
%if _ELD_LINKER_PASSES
	jnc .datarelocloop
%endif
	les bx, [bp + ?linkinfo]
%if ELDOTHER
	rol byte [bp + ?other], 1
	jnc @F
	les bx, [bp + ?linkinfo_other]
@@:
%endif
	mov cx, word [es:bx + eldlDataAmount]	; amount data link info
	mov di, word [es:bx + eldlDataPrefixes]	; -> prefixes or hashes
.datarelocfind:
	repne scasw			; scan initial
	jne .datarelocnotfound
	push di
	push cx
	push si
	sub di, word [es:bx + eldlDataPrefixes]	; = double index, 1-based
	dec di
	dec di				; 0-based
	add di, word [es:bx + eldlDataEntries]	; -> entry
	mov di, [es:di]			; -> counted suffix/string
	mov ch, 0
	mov cl, byte [si]		; cx = length
	inc cx
	; cmp al, al			; ZR if length is zero
	repe cmpsb			; match ?
	pop si
	pop cx
	pop di
	jne .datarelocfind
	mov byte [si], dl
	sub di, word [es:bx + eldlDataPrefixes]	; = double index, 1-based
	dec di
	dec di				; 0-based
	add di, word [es:bx + eldlDataAddresses]	; -> address (offset)
	mov ax, word [es:di]
	call .address_data_reloc
%if _ELD_RELOC_VSTART
	sub ax, relocateddata		; *not* a relocation
%endif
	add word [si], ax		; relocate
	jmp .datarelocloop

.address_data_reloc:
	lds si, [bp + ?entry]		; -> entry if in ELD code instance
	cmp byte [bp + ?targetsection], 0
					; relocation in code ?
	je @F				; yes -->
	push ss
	pop ds				; => our ELD data block
@@:
	retn

.datarelocnotfound:
	mov byte [si], dl
	cmp byte [bp + ?optional], 0
%if _ELD_DEBUG
	jne @F
 %ifn _ELD_LINKER_PASSES
	mov si, 0			; (invalid link)
linkdatarelocation internalflags6
	test si, si
	jz .datanotfound
	mov si, 0			; (invalid link)
linkdatarelocation options7
	test si, si
	jz .datanotfound
 %else
	cmp byte [bp + ?pass], 0
	je .datanotfound
 %endif
	houdini
	jmp .datanotfound
@@:
%else
	je .datanotfound
%endif

%if ELDDATA_PMREQUIRED_STATUS
	mov si, relocateddata
linkdatarelocation build_option_PM
	test si, si
	jz @F
	test byte [bp + ?optional], 2
	jnz .datanotfound
@@:
%endif

%if _ELD_LINKER_PASSES
	testopt [ss:relocateddata], 2
linkdatarelocation options7, -3
	jz @F
	mov si, lmsg.warning_data_optional
internalcoderelocation
	call .notfound
@@:
%endif
	call .address_data_reloc
	and word [si], 0		; indicate optional data link failed
	jmp .datarelocloop


%if _ELDCALL_OPTIONAL
.coderelocnotfound:
	mov byte [si], dl
	cmp byte [bp + ?optional], 0
%if _ELD_DEBUG
	jne @F
 %ifn _ELD_LINKER_PASSES
	mov si, 0			; (invalid link)
linkdatarelocation internalflags6
	test si, si
	jz .codenotfound
	mov si, 0			; (invalid link)
linkdatarelocation options7
	test si, si
	jz .codenotfound
 %else
	cmp byte [bp + ?pass], 0
	je .codenotfound
 %endif
	houdini
	jmp .codenotfound
@@:
%else
	je .codenotfound
%endif

%if ELDCALL_PMREQUIRED_STATUS
 %if _ELD_LINKER_PASSES
  %assign ELDLINKER 0
 %endif
	mov si, relocateddata
linkdatarelocation build_option_PM
 %if _ELD_LINKER_PASSES
  %assign ELDLINKER 1
 %endif
	test si, si
	jz @F
	test byte [bp + ?optional], 2
	jnz .codenotfound
@@:
%endif

%if _ELD_LINKER_PASSES
	testopt [ss:relocateddata], 2
linkdatarelocation options7, -3
	jz @F
	mov si, lmsg.warning_code_optional
internalcoderelocation
	call .notfound
@@:
%endif
	lds si, [bp + ?entry]
	mov word [si], 9090h
	mov byte [si + 2], 90h		; indicate optional code link failed
	jmp .coderelocloop
%endif


%if _ELD_LINKER_PASSES
.datanotfound:
	mov si, lmsg.error_data
internalcoderelocation
	call .notfound
	jnc .error_j
	inc word [bp + ?amounterrors]
	jmp .datarelocloop

.codenotfound:
	mov si, lmsg.error_code
internalcoderelocation
	call .notfound
	jnc .error_j
	inc word [bp + ?amounterrors]
	jmp .coderelocloop

.notfound:
	cmp byte [bp + ?pass], 0
	je @F				; --> (NC)
	 push ss
	 pop es
	mov di, relocateddata
linkdatarelocation line_out
	call .copy
	mov si, word [bp + ?name]
	lodsw
	extcall hexword
	push si
	mov si, lmsg.error.2
internalcoderelocation
	call .copy
	pop si
%if _ELD_LINKER_PASSES
	push si
	call .copy
	pop si
	mov byte [si], 0		; mark as failed
%else
	call .copy
%endif
	mov al, '"'
	stosb
	 push ss
	 pop ds
	extcall putsline_crlf
	mov ax, 0E35h
	extcall setrc
	stc				; CY, diagnostic displayed
@@:
	retn

.copy:
	extcall copy_single_counted_string
	retn
%else
.datanotfound: equ .error_j
.codenotfound: equ .error_j
%endif

.build_match:
%if _ELD_CODE_VSTART
	sub ax, code
%endif
	add ax, word [bp + ?instance]
	xchg si, ax
%if _ELD_LINKER_PASSES
	mov word [bp + ?name], si
%endif
	lodsw			; = hash, si -> counted string
	mov dl, byte [si]
%if _ELD_LINKER_PASSES
	test dl, dl		; marked as already failed ?
	jnz @F
	cmp word [bp + ?amounterrors], 0
	je .error_j
	retn			; (NC)

@@:
%endif
%if ELDOTHER
	rol byte [bp + ?other], 1
	jnc @F
	rol byte [bp + ?use_hash_other], 1
	jmp @FF

@@:
%endif
	rol byte [bp + ?use_hash], 1
@@:
	jc @F
	lodsb
	xchg cx, ax		; cl = length
	lodsw			; ax = prefix
	dec cx
	dec cx
	dec si
	mov dl, byte [si]
	mov byte [si], cl	; si -> counted string suffix
@@:
%if _ELD_LINKER_PASSES
	stc			; CY
%endif
	retn


.donedatareloc:
%if ELDOTHER
	rol byte [bp + ?other], 1
	jc .otherdone
%endif

	mov dx, word [bp + ?instance]
%if _ELD_LINKER_PASSES
	mov bx, word [bp + ?pass]
	add bx, dx
 %if _ELD_IDENTICALISE
	add bx, word [bp + ?lt]
	add dx, word [ltLinkCode + bx]
 %else
	add dx, word [linktable - code + ltLinkCode + bx]
 %endif
%else
	add dx, linkercoderelocations - code
%endif
	mov word [bp + ?nextreloc], dx

.coderelocloop:
	lds si, [bp + ?nextreloc]
	lodsw
%if _ELDCALL_OPTIONAL
	dec ax
	js .donecodereloc
	mov word [bp + ?targetsection_low_optional_high], ax
	lodsw
%endif
	add ax, word [bp + ?instance]
	mov word [bp + ?entry], ax
	lodsw
	mov word [bp + ?nextreloc], si
%ifn _ELDCALL_OPTIONAL
	test ax, ax
	jz .donecodereloc
%endif
	call .build_match
%if _ELD_LINKER_PASSES
	jnc .coderelocloop
%endif
	les bx, [bp + ?linkinfo]
	mov cx, word [es:bx + eldlCodeAmount]	; amount code link info
	mov di, word [es:bx + eldlCodePrefixes]	; -> prefixes or hashes
.coderelocfind:
	repne scasw			; scan initial
%if _ELDCALL_OPTIONAL
	jne .coderelocnotfound
%else
 %if _ELD_DEBUG
	je @F
	houdini
	jmp .codenotfound
@@:
 %else
	jne .codenotfound
 %endif
%endif
	push di
	push cx
	push si
	sub di, word [es:bx + eldlCodePrefixes]	; = double index, 1-based
	dec di
	dec di				; 0-based
	add di, word [es:bx + eldlCodeEntries]	; -> entry
	mov di, [es:di]			; -> counted suffix/string
	mov ch, 0
	mov cl, byte [si]		; cx = length
	inc cx
	; cmp al, al			; ZR if length is zero
	repe cmpsb			; match ?
	pop si
	pop cx
	pop di
	jne .coderelocfind
	mov byte [si], dl
	sub di, word [es:bx + eldlCodePrefixes]	; = double index, 1-based
	dec di
	dec di				; 0-based
	add di, di			; quadruple index
	add di, word [es:bx + eldlCodeAddresses]	; -> address (offset, segment)
	push word [es:di]
	lds si, [bp + ?entry]
	pop word [si + 3 + 2]		; call near imm (3), jmp short (2)
					;  patch the destination address
	cmp byte [si], 0E8h		; is it as expected ?
	jne .error_j
	mov di, word [es:di + 2]
	mov bx, relocateddata
linkdatarelocation linkcall_table	; ss:bx -> link call table
	cmp word [ss:bx], 1		; is it initialised to format 1 ?
	jne .error_j			; no -->
	mov cx, word [ss:bx + 2]	; get amount of segments
	jcxz .error_j			; none -->
@@:
	add bx, 4			; -> next segment
	cmp word [ss:bx], di		; value matches ?
	je @F				; yes, found -->
	loop @B				; try remaining segments
.error_j:
	jmp .error

@@:
	mov bx, word [ss:bx + 2]	; -> call destination offset
		; si + 3 + delta = bx
		; delta = bx - si - 3
	sub bx, si
	sub bx, 3
	mov word [si + 1], bx		; patch the call instruction
	jmp .coderelocloop

.donecodereloc:
%if _ELD_LINKER_PASSES
	mov ax, word [bp + ?amounterrors]
	test ax, ax
	jnz .error_j
	mov bx, word [bp + ?pass]
	test bx, bx
	jnz @F
	inc bx
	inc bx
	mov word [bp + ?pass], bx
	mov dx, word [bp + ?instance]
	jmp .pass

@@:
%endif

%ifnidni _LISTING, ""
%assign ELDLINKER 0
.hint:
	push ss
	pop ds
	mov al, 2Dh
	extcall intchk			; ZR if offset = -1 or segment = 0
					; CHG: ax, dx, bx
	jz .no_hint

	mov ah, byte [relocateddata]
linkdatarelocation try_debugger_amis_multiplex_number
	call plex_check
	jnc @F

	mov ah, 0FFh		; start with multiplex number 0FFh
.loop_hint:
	call plex_check
@@:
	jnc .end_hint		; if found --> (NC)
	sub ah, 1		; search is backward (to find latest installed first), from 0FFh to 00h including
	jnc .loop_hint		; try next if we didn't check all yet -->
	jmp .no_hint

.end_hint:
	push ax
	les ax, [bp + ?instance]
	mov di, listmsg.hint.offset
internalcoderelocation
	extcall hexword
	mov bx, listmsg.hint
internalcoderelocation
	mov dx, [ss:relocateddata]
linkdatarelocation extseg	; must be 86 Mode segment even in PM
	pop ax
	mov al, 40h		; AMIS message display service
	extcall call_int2D
.no_hint:
%endif

%if ELDOTHER
%assign ELDLINKER 0
	not byte [bp + ?other]

	push ss
	pop ds
	mov al, 2Dh
	extcall intchk			; ZR if offset = -1 or segment = 0
					; CHG: ax, dx, bx
	jz .no_other

	mov ah, byte [relocateddata]
linkdatarelocation try_debugger_amis_multiplex_number
	call plex_check
	jnc @F

	mov ah, 0FFh		; start with multiplex number 0FFh
.loop_other:
	call plex_check
@@:
	jnc .end_other		; if found --> (NC)
	sub ah, 1		; search is backward (to find latest installed first), from 0FFh to 00h including
	jnc .loop_other		; try next if we didn't check all yet -->
	jmp .no_other

.end_other:
	mov al, 42h		; AMIS get other link info service
	extcall call_int2D
	cmp al, 0FFh
	jne .no_other

	mov ax, si		; selector => PSP
	extcall ispm
	jz @F
	mov ax, dx		; segment => PSP
@@:
	 push ss
	 pop ds
	mov word [otherds], ax
internaldatarelocation		; current mode sel/seg
	mov word [otherseg], dx
internaldatarelocation		; remember segment

	mov ax, cx		; selector => link info
	extcall ispm
	jz @F
	mov ax, bx		; segment => link info
@@:
	mov word [bp + ?linkinfo_other], di
	mov word [bp + ?linkinfo_other + 2], ax

	mov ds, ax		; => link info
	xor ax, ax
	cmp word [di + eldlSignature], 0E1D1h
	jne .error_other
	cmp word [di + eldlUseLinkHash], 1
	ja .error_other
	jb @F
	dec ax
@@:
	mov word [bp + ?use_hash_other], ax

	mov dx, word [bp + ?instance]
	add dx, linkerotherdatarelocations - code
	jmp .otherloop

.error_other:
	push cs
	pop ds
	mov ax, 0E33h
	extcall setrc
	mov dx, lmsg.error_other
internalcoderelocation
	jmp @F

.no_other:
	push cs
	pop ds
	mov ax, 0E34h
	extcall setrc
	mov dx, lmsg.no_other
internalcoderelocation
@@:
	extcall putsz
	jmp .error

.otherdone:
%endif

	pop bx				; -> our heap data
	pop si				; -> our command line tail
	 push ss
	 pop ds
	les di, [bp + ?instance]
	mov ax, word [es:di + eldiEndCode]
houdini
	sub ax, strict word endresident + code
internalcoderelocation
	mov word [es:di + eldiEndCode], endresident + code
internalcoderelocation
	sub word [relocateddata], ax
linkdatarelocation extseg_used
%if _DATA_SIZE == 0
	xor ax, ax
	mov word [es:di + eldiStartData], ax
	mov word [es:di + eldiEndData], ax
%endif
	lleave code
		; INP:	es => ELD code segment
		;	ds:si -> command line tail
		;	ds:bx -> ELD data block
		;	ss:sp -> far return address for current mode
		; STT:	ds = ss, UP, EI
	jmp start

.error:
	lleave
	mov ax, -1
	retf


%ifnidni _LISTING, ""
 %assign ELDHINT 1
%else
 %assign ELDHINT 0
%endif

%if ELDOTHER || ELDHINT
		; INP:	ah = multiplex number to check
		; OUT:	CY if multiplex number unused or no signature match,
		;	 bp, ah, ds unmodified
		;	NC if match found,
		;	 ah = multiplex number (unmodified)
		; CHG:	si, di, es, cx, dx
plex_check:
	push ss
	pop ds
	testopt [relocateddata], 8
linkdatarelocation internalflags4, -3
	jz @F
	mov si, relocateddata
linkdatarelocation amis_multiplex_number, -2, optional
	test si, si
	jz @F
	cmp ah, byte [si]
	je .notfound		; do not use our own multiplexer -->
@@:
	mov al, 00h		; AMIS installation check
	extcall call_int2D	; AMIS (or "DOS reserved" = iret if no AMIS present)
	cmp al, 0FFh
	jne .notfound
	push cs
	pop ds
	mov si, debuggeramissig	; ds:si -> our AMIS name strings
internalcoderelocation
	extcall setes2dx	; es:di -> name strings of AMIS multiplexer that just answered
	mov cx, 8		; Ignore description, only compare vendor and program name
	repe cmpsw
	je .checkret		; ZR, NC = match -->
.notfound:
	stc			; CY no match
.checkret:
	retn
%endif


	align 4, db 0
linkercoderelocations:
%if _ELDCALL_OPTIONAL
	dw ELDCALL_CODE_RELOCATIONS_OPTIONAL, 0
%else
	dw ELDCALL_CODE_RELOCATIONS, 0, 0
%endif

%if _ELD_LINKER_PASSES
linkerlinkercoderelocations:
%if _ELDCALL_OPTIONAL
	dw ELDCALL_LINKER_CODE_RELOCATIONS_OPTIONAL, 0
%else
	dw ELDCALL_LINKER_CODE_RELOCATIONS, 0, 0
%endif

	align 2, db 0
linktable:
	istruc LINKTABLE
at ltCodeToCode
	dw internallinkercodetocoderelocations - code
	dw internalcodetocoderelocations - code
at ltCodeToData
	dw internallinkercodetodatarelocations - code
	dw internalcodetodatarelocations - code
at ltDataToCode
	dw internallinkerdatatocoderelocations - code
	dw internaldatatocoderelocations - code
at ltDataToData
	dw internallinkerdatatodatarelocations - code
	dw internaldatatodatarelocations - code
at ltLinkData
	dw linkerlinkerdatarelocations - code
	dw linkerdatarelocations - code
at ltLinkCode
	dw linkerlinkercoderelocations - code
	dw linkercoderelocations - code
	iend
%endif

	align 2, db 0
linkerdatarelocations:
	dw LINK_DATA_RELOCATIONS, 0

	align 2, db 0
internalcodetocoderelocations:
	dw INTERNAL_CODE_TO_CODE_RELOCATIONS, 0

	align 2, db 0
internalcodetodatarelocations:
	dw INTERNAL_CODE_TO_DATA_RELOCATIONS, 0

	align 2, db 0
internaldatatocoderelocations:
	dw INTERNAL_DATA_TO_CODE_RELOCATIONS, -1

	align 2, db 0
internaldatatodatarelocations:
	dw INTERNAL_DATA_TO_DATA_RELOCATIONS, -1

%if _ELD_LINKER_PASSES
	align 2, db 0
linkerlinkerdatarelocations:
	dw LINK_LINKER_DATA_RELOCATIONS, 0

	align 2, db 0
internallinkercodetocoderelocations:
	dw INTERNAL_LINKER_CODE_TO_CODE_RELOCATIONS, 0

	align 2, db 0
internallinkercodetodatarelocations:
	dw INTERNAL_LINKER_CODE_TO_DATA_RELOCATIONS, 0

	align 2, db 0
internallinkerdatatocoderelocations:
	dw INTERNAL_LINKER_DATA_TO_CODE_RELOCATIONS, -1

	align 2, db 0
internallinkerdatatodatarelocations:
	dw INTERNAL_LINKER_DATA_TO_DATA_RELOCATIONS, -1
%endif

%if ELDOTHER
	align 2, db 0
linkerotherdatarelocations:
	dw LINK_OTHER_DATA_RELOCATIONS, 0

 %ifnidn LINK_OTHER_LINKER_DATA_RELOCATIONS, ""
  %error Other linker data links not supported
 %endif
%endif

%if ELDOTHER || ELDHINT
	align 2, db 0
debuggeramissig:
		fill 8, 32, db "ecm"
		fill 8, 32, db "lDebug"
%endif

%ifnidni _LISTING, ""
listmsg:
.hint:		db "TracList-add-offset=",_LISTING,"::"
.hint.offset:	asciz "----h",13,10
%endif

	eldcall_dump_names ELDCALL_CODE_NAMES
	link_data_dump_names LINK_DATA_NAMES
%if ELDOTHER
	link_data_dump_names LINK_OTHER_DATA_NAMES
%endif

lmsg:
%if _ELD_LINKER_PASSES
%if _ELDCALL_OPTIONAL
.warning_code_optional:		counted "Optional code link missing, hash="
%endif
.warning_data_optional:		counted "Optional data link missing, hash="
.error_data:			counted "Data link missing, hash="
.error_code:			counted "Code link missing, hash="
.error.2:			counted "h, label ",'"'
%endif
%if ELDOTHER
.no_other:		asciz "ELD linker: No other link info found!",13,10
.error_other:		asciz "ELD linker: Other link info unknown format!",13,10
%endif

	align 16, db 0
