/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8                                     :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
│                                                                              │
│ Permission to use, copy, modify, and/or distribute this software for         │
│ any purpose with or without fee is hereby granted, provided that the         │
│ above copyright notice and this permission notice appear in all copies.      │
│                                                                              │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
│ PERFORMANCE OF THIS SOFTWARE.                                                │
╚─────────────────────────────────────────────────────────────────────────────*/
#ifndef APE_IDATA_H_
#define APE_IDATA_H_
#ifdef __ASSEMBLER__
#include "ape/relocations.h"
/* clang-format off */

//	Links function from external DLL.
//
//	This embeds a function pointer in the binary. The NT Executive
//	fills its value before control is handed off to the program.
//
//	@note	only ELF toolchains are powerful enough to use this
//	@see	libc/nt/master.sh
//	@see	ape/ape.lds
//	@see	winimp
.macro	.imp	dll:req fn:req actual:req hint
	.dll	\dll
	.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
	.type	\fn,@object
	.align	__SIZEOF_POINTER__
\fn:	.quad	RVA((\dll\().\actual))
	.size	\fn,.-\fn
	.globl	\fn
	.hidden	\fn
	.previous
	.section .idata.ro.ilt.\dll\().2.\actual,"a",@progbits
.Lidata.ilt.\dll\().\actual:
	.quad	RVA((\dll\().\actual))
	.type	.Lidata.ilt.\dll\().\actual,@object
	.size	.Lidata.ilt.\dll\().\actual,.-.Lidata.ilt.\dll\().\actual
	.previous
	.section .idata.ro.hnt.\dll\().2.\actual,"a",@progbits
\dll\().\actual:
	.ifnb	\hint			# hint i.e. guess function ordinal
	.short	\hint
	.else
	.short	0
	.endif
	.asciz	"\actual"
	.align	2			# documented requirement
	.globl	\dll\().\actual
	.hidden	\dll\().\actual
	.type	\dll\().\actual,@object
	.size	\dll\().\actual,.-\dll\().\actual
	.previous
.endm

//	Defines DLL import.
//	@note	this is an implementation detail of .imp
.macro	.dll	name:req
  .section .idata.ro.idt.2.\name,"aG",@progbits,\name,comdat
	.equ	.Lidata.idt.\name,.
	.long	RVA(idata.ilt.\name)		# ImportLookupTable
	.long	0				# TimeDateStamp
	.long	0				# ForwarderChain
	.long	RVA(.Lidata.str.\name)		# DllNameRva
	.long	RVA(idata.iat.\name)		# ImportAddressTable
	.type	.Lidata.idt.\name,@object
	.size	.Lidata.idt.\name,.-.Lidata.idt.\name
  .previous
  .section .idata.ro.ilt.\name\().1,"aG",@progbits,\name,comdat
	.align	__SIZEOF_POINTER__
	.type	idata.ilt.\name,@object
idata.ilt.\name:
	.previous/*
	...
	decentralized content
	...
	*/.section .idata.ro.ilt.\name\().3,"aG",@progbits,\name,comdat
	.quad	0
  .previous
  .section .idata.ro.hnt.\name\().1,"aG",@progbits,\name,comdat
	.align	__SIZEOF_POINTER__
	.type	idata.hnt.\name,@object
	.equ	idata.hnt.\name,.
  .previous
  .section .piro.data.sort.iat.2.\name\().1,"awG",@progbits,\name,comdat
	.align	__SIZEOF_POINTER__
	.type	idata.iat.\name,@object
idata.iat.\name:
	.previous/*
	...
	decentralized content
	...
	*/.section .piro.data.sort.iat.2.\name\().3,"awG",@progbits,\name,comdat
	.quad	0
  .previous
  .section .rodata.str1.1,"aSM",@progbits,1
.Lidata.str.\name:
	.asciz	"\name\().dll"
  .previous
.endm

/* clang-format on */
#endif /* __ASSEMBLER__ */
#endif /* APE_IDATA_H_ */
