Commit 5b9d9a0c by Michael Meissner

Solaris, shared lib, aix broken compatibiliy

From-SVN: r12439
parent 821581e4
......@@ -21,6 +21,14 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Enable AIX XL compiler calling convention breakage compatibility. */
#define MASK_XL_CALL 0x40000000
#define TARGET_XL_CALL (target_flags & MASK_XL_CALL)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{"xl-call", MASK_XL_CALL}, \
{"no-xl-call", - MASK_XL_CALL},
#include "rs6000/rs6000.h"
/* Tell the assembler to assume that all undefined names are external. */
......
......@@ -21,6 +21,14 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Enable AIX XL compiler calling convention breakage compatibility. */
#define MASK_XL_CALL 0x40000000
#define TARGET_XL_CALL (target_flags & MASK_XL_CALL)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{"xl-call", MASK_XL_CALL}, \
{"no-xl-call", - MASK_XL_CALL},
#include "rs6000/rs6000.h"
#undef ASM_SPEC
......
......@@ -66,6 +66,19 @@
.Lsda2e = .-.LCTOC1
.long __SBSS2_END__ /* end of .sdata2/.sbss2 section */
#ifdef _RELOCATABLE
.Lgots = .-.LCTOC1
.long __GOT_START__ /* Global offset table start */
.Lgotm1 = .-.LCTOC1
.long _GLOBAL_OFFSET_TABLE_-4 /* end of GOT ptrs before BLCL + 3 reserved words */
.Lgotm2 = .-.LCTOC1
.long _GLOBAL_OFFSET_TABLE_+12 /* start of GOT ptrs after BLCL + 3 reserved words */
.Lgote = .-.LCTOC1
.long __GOT_END__ /* Global offset table end */
.Lgot2s = .-.LCTOC1
.long __GOT2_START__ /* -mrelocatable GOT pointers start */
......@@ -99,16 +112,18 @@
.Linit = .-.LCTOC1
.long .Linit_p /* address of variable to say we've been called */
.text
.align 2
.Lptr:
.long .LCTOC1-.Laddr /* PC relative pointer to .got2 */
#endif
.data
.align 2
.Linit_p:
.long 0
.text
#ifdef _RELOCATABLE
.Lptr:
.long .LCTOC1-.Laddr /* PC relative pointer to .got2 */
#endif
FUNC_START(__eabi)
......@@ -116,7 +131,16 @@ FUNC_START(__eabi)
be assembled with other assemblers than GAS, such as the Solaris PowerPC
assembler. */
#ifdef _RELOCATABLE
#ifndef _RELOCATABLE
addis 10,0,.Linit_p@ha /* init flag */
addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */
lwz 9,.Linit_p@l(10) /* init flag */
addi 11,11,.LCTOC1@l
cmplwi 2,9,0 /* init flag != 0? */
bnelr 2 /* return now, if we've been called already */
stw 1,.Linit_p@l(10) /* store a non-zero value in the done flag */
#else /* -mrelocatable */
mflr 0
bl .Laddr /* get current address */
.Laddr:
......@@ -127,116 +151,48 @@ FUNC_START(__eabi)
lwz 10,.Linit(11) /* address of init flag */
subf. 12,12,11 /* calculate difference */
lwzx 9,10,12 /* done flag */
mtlr 0 /* restore link register */
cmplwi 2,9,0 /* init flag != 0? */
bnelr 2 /* return now, if we've been called already */
stwx 1,10,12 /* store a non-zero value in the done flag */
bne- 0,.Lreloc /* skip if we need to relocate */
#else /* !-mrelocatable */
addis 10,0,.Linit_p@ha /* init flag */
addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */
lwz 9,.Linit_p@l(10) /* init flag */
addi 11,11,.LCTOC1@l
cmplwi 2,9,0 /* init flag != 0? */
bnelr 2 /* return now, if we've been called already */
stw 1,.Linit_p@l(10) /* store a non-zero value in the done flag */
#endif /* !-mrelocatable */
/* Only load up register 13 if there is a .sdata and/or .sbss section */
lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */
lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */
cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
beq- 1,.Lsda2l /* skip loading r13 */
lwz 13,.Lsda(11) /* load r13 with _SDA_BASE address */
/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
.Lsda2l:
lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */
lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */
cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
beq+ 1,.Ldone /* skip loading r2 */
lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE address */
b FUNC_NAME(__do_global_ctors) /* do any C++ global constructors (which returns to caller) */
beq+ 0,.Lsdata /* skip if we don't need to relocate */
/* We need to relocate the .got2 pointers. */
#ifdef _RELOCATABLE
.Lreloc:
/* We need to relocate the .got2 pointers. Don't load registers 2 or 13 */
lwz 3,.Lgot2s(11) /* GOT pointers start */
lwz 4,.Lgot2e(11) /* GOT pointers end */
lwz 3,.Lgot2s(11) /* GOT2 pointers start */
lwz 4,.Lgot2e(11) /* GOT2 pointers end */
add 3,12,3 /* adjust pointers */
add 4,12,4
cmpw 1,3,4 /* any pointers to adjust */
bc 12,6,.Lctor
.Lloop:
lwz 5,0(3) /* next pointer */
add 5,5,12 /* adjust */
stw 5,0(3)
addi 3,3,4 /* bump to next word */
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Lloop
bl FUNC_NAME(__eabi_convert) /* convert pointers in .got2 section */
/* Fixup the .ctor section for static constructors */
.Lctor:
lwz 3,.Lctors(11) /* constructors pointers start */
lwz 4,.Lctore(11) /* constructors pointers end */
cmpw 1,3,4 /* any pointers to adjust */
bc 12,6,.Ldtor
.Lcloop:
lwz 5,0(3) /* next pointer */
add 5,5,12 /* adjust */
stw 5,0(3)
addi 3,3,4 /* bump to next word */
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Lcloop
bl FUNC_NAME(__eabi_convert) /* convert constructors */
/* Fixup the .dtor section for static destructors */
.Ldtor:
lwz 3,.Ldtors(11) /* destructors pointers start */
lwz 4,.Ldtore(11) /* destructors pointers end */
cmpw 1,3,4 /* any pointers to adjust */
bc 12,6,.Lexcept
.Ldloop:
lwz 5,0(3) /* next pointer */
add 5,5,12 /* adjust */
stw 5,0(3)
addi 3,3,4 /* bump to next word */
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Ldloop
bl FUNC_NAME(__eabi_convert) /* convert destructors */
/* Fixup the .gcc_except_table section for G++ exceptions */
.Lexcept:
lwz 3,.Lexcepts(11) /* exception table pointers start */
lwz 4,.Lexcepte(11) /* exception table pointers end */
bl FUNC_NAME(__eabi_convert) /* convert exceptions */
cmpw 1,3,4 /* any pointers to adjust */
bc 12,6,.Lfix
/* Fixup the the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
.Leloop:
lwz 5,0(3) /* next pointer */
addi 3,3,4 /* bump to next word */
cmpi 1,5,0
beq 1,.Leloop /* if NULL pointer, don't adjust */
add 5,5,12 /* adjust */
stw 5,-4(3)
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Leloop
lwz 3,.Lgots(11) /* GOT table pointers start */
lwz 4,.Lgotm1(11) /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */
bl FUNC_NAME(__eabi_convert) /* convert lower GOT */
/* Fixup the the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
lwz 3,.Lgotm2(11) /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */
lwz 4,.Lgote(11) /* GOT table pointers end */
bl FUNC_NAME(__eabi_convert) /* convert lower GOT */
/* Fixup any user initialized pointers now (the compiler drops pointers to */
/* each of the relocs that it does in the .fixup section). */
......@@ -244,28 +200,100 @@ FUNC_START(__eabi)
.Lfix:
lwz 3,.Lfixups(11) /* fixup pointers start */
lwz 4,.Lfixupe(11) /* fixup pointers end */
bl FUNC_NAME(__eabi_uconvert) /* convert user initialized pointers */
cmpw 1,3,4 /* any user pointers to adjust */
bc 12,6,.Ldone
.Lfloop:
lwz 5,0(3) /* next pointer */
add 5,5,12 /* adjust pointer */
lwz 6,0(5) /* get the pointer it points to */
stw 5,0(3) /* store adjusted pointer */
add 6,6,12 /* adjust */
stw 6,0(5)
addi 3,3,4 /* bump to next word */
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Lfloop
.Lsdata:
mtlr 0 /* restore link register */
#endif /* _RELOCATABLE */
/* Done adjusting pointers, return */
/* Only load up register 13 if there is a .sdata and/or .sbss section */
lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */
lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */
cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
beq- 1,.Lsda2l /* skip loading r13 */
lwz 13,.Lsda(11) /* load r13 with _SDA_BASE_ address */
/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
.Lsda2l:
lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */
lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */
cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
beq+ 1,.Ldone /* skip loading r2 */
lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE_ address */
/* Done adjusting pointers, return by way of doing the C++ global constructors. */
.Ldone:
b FUNC_NAME(__do_global_ctors) /* do any C++ global constructors (which returns to caller) */
FUNC_END(__eabi)
/* Special subroutine to convert a bunch of pointers directly.
r0 has original link register
r3 has low pointer to convert
r4 has high pointer to convert
r5 .. r10 are scratch registers
r11 has the address of .LCTOC1 in it.
r12 has the value to add to each pointer
r13 .. r31 are unchanged */
FUNC_START(__eabi_convert)
cmplw 1,3,4 /* any pointers to convert? */
subf 5,3,4 /* calculate number of words to convert */
bclr 4,4 /* return if no pointers */
srawi 5,5,2
addi 3,3,-4 /* start-4 for use with lwzu */
mtctr 5
.Lcvt:
lwzu 6,4(3) /* pointer to convert */
cmpi 0,6,0
beq- .Lcvt2 /* if pointer is null, don't convert */
add 6,6,12 /* convert pointer */
stw 6,0(3)
.Lcvt2:
bdnz+ .Lcvt
blr
FUNC_END(__eabi_convert)
/* Special subroutine to convert the pointers the user has initialized. The
compiler has placed the address of the initialized pointer into the .fixup
section.
r0 has original link register
r3 has low pointer to convert
r4 has high pointer to convert
r5 .. r10 are scratch registers
r11 has the address of .LCTOC1 in it.
r12 has the value to add to each pointer
r13 .. r31 are unchanged */
FUNC_START(__eabi_uconvert)
cmplw 1,3,4 /* any pointers to convert? */
subf 5,3,4 /* calculate number of words to convert */
bclr 4,4 /* return if no pointers */
srawi 5,5,2
addi 3,3,-4 /* start-4 for use with lwzu */
mtctr 5
.Lucvt:
lwzu 6,4(3) /* next pointer to pointer to convert */
add 6,6,12 /* adjust pointer */
lwz 7,0(6) /* get the pointer it points to */
stw 6,0(3) /* store adjusted pointer */
add 7,7,12 /* adjust */
stw 7,0(6)
bdnz+ .Lucvt
blr
FUNC_END(__eabi_uconvert)
/* Routines for saving floating point registers, called by the compiler. */
/* Called with r11 pointing to the stack header word of the caller of the */
/* function, just beyond the end of the floating point save area. */
......
......@@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN | MASK_EABI)
#undef CPP_ENDIAN_DEFAULT_SPEC
#define CPP_ENDIAN_DEFAULT_SPEC "-D_LITTLE_ENDIAN -Amachine(littleendian)"
#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_little)"
#undef LINK_TARGET_SPEC
#define LINK_TARGET_SPEC "\
......
......@@ -1013,7 +1013,7 @@ small_data_operand (op, mode)
if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
return 0;
if (DEFAULT_ABI != ABI_V4 /* && DEFAULT_ABI != ABI_SOLARIS */)
if (DEFAULT_ABI != ABI_V4 && DEFAULT_ABI != ABI_SOLARIS)
return 0;
if (GET_CODE (op) == SYMBOL_REF)
......@@ -1262,10 +1262,15 @@ function_arg (cum, mode, type, named)
if (USE_FP_FOR_ARG_P (*cum, mode, type))
{
if ((cum->nargs_prototype > 0)
|| DEFAULT_ABI == ABI_V4 /* V.4 never passes FP values in GP registers */
if (DEFAULT_ABI == ABI_V4 /* V.4 never passes FP values in GP registers */
|| DEFAULT_ABI == ABI_SOLARIS
|| !type)
|| ! type
|| ((cum->nargs_prototype > 0)
/* IBM AIX extended its linkage convention definition always to
require FP args after register save area hole on the stack. */
&& (DEFAULT_ABI != ABI_AIX
|| ! TARGET_XL_CALL
|| (align_words < GP_ARG_NUM_REG))))
return gen_rtx (REG, mode, cum->fregno);
return gen_rtx (PARALLEL, mode,
......
......@@ -54,6 +54,8 @@ extern char _ex_text0[], _ex_text1[];
extern char _ex_range0[], _ex_range1[];
extern void _ex_register (struct ex_shared1 *);
extern void _ex_deregister (struct ex_shared1 *);
extern char _SDA_BASE_[];
extern char _SDA2_BASE_[];
struct ex_shared shared __attribute__((section(".ex_shared"))) = {
_ex_register,
......@@ -80,11 +82,14 @@ void
_start(int argc, char *argv[], char *envp[], void *auxp, void (*termfunc)())
{
int ret;
int dummy = 0;
/* Load up r13 before we do anything else. */
__asm__ volatile ("mr %%r13,%0;mr %%r2,%1" : "=r" (dummy) : "r" (&_SDA_BASE_[0]), "r" (&_SDA2_BASE_[0]));
_environ = envp;
/* Register loader termination function */
if (termfunc)
if (termfunc || dummy)
atexit (termfunc);
/* Register exception handler if needed */
......
......@@ -68,12 +68,12 @@ __DTOR_LIST__:
.type __init,@function
__init: stwu %r1,-16(%r1)
mflr %r0
# stw %r31,12(%r1)
stw %r31,12(%r1)
stw %r0,16(%r1)
# bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address
# mflr %r31
#
bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address
mflr %r31
# lwz %r3,_ex_shared0@got(%r31)
# lwz %r4,-8(%r3) # _ex_register or 0
# cmpi %cr0,%r4,0
......@@ -92,8 +92,8 @@ __fini: stwu %r1,-16(%r1)
stw %r31,12(%r1)
stw %r0,16(%r1)
# bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address
# mflr %r31
bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address
mflr %r31
# _environ and its evil twin environ, pointing to the environment
.comm _environ,4,4
......
......@@ -68,6 +68,7 @@ _ex_range1:
# Tail of __init used for static constructors in Solaris
.section ".init","ax"
lwz %r0,16(%r1)
lwz %r31,12(%r1)
mtlr %r0
addi %r1,%r1,16
blr
......@@ -75,6 +76,7 @@ _ex_range1:
# Tail of __fini used for static destructors in Solaris
.section ".fini","ax"
lwz %r0,16(%r1)
lwz %r31,12(%r1)
mtlr %r0
addi %r1,%r1,16
blr
......@@ -52,6 +52,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef LINK_OS_DEFAULT_SPEC
#define LINK_OS_DEFAULT_SPEC "%(link_os_solaris)"
#undef CPP_ENDIAN_LITTLE_SPEC
#define CPP_ENDIAN_LITTLE_SPEC CPP_ENDIAN_SOLARIS_SPEC
/* Don't turn -B into -L if the argument specifies a relative file name. */
#undef RELATIVE_PREFIX_NOT_LINKDIR
......
......@@ -187,7 +187,7 @@ do { \
} \
else if (TARGET_SDATA) \
rs6000_sdata = (TARGET_EABI) ? SDATA_EABI : SDATA_SYSV; \
else if (!TARGET_RELOCATABLE && !flag_pic && DEFAULT_ABI == ABI_V4) \
else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
{ \
rs6000_sdata = SDATA_DATA; \
target_flags |= MASK_SDATA; \
......@@ -198,22 +198,15 @@ do { \
if (TARGET_RELOCATABLE && \
(rs6000_sdata == SDATA_EABI || rs6000_sdata == SDATA_SYSV)) \
{ \
target_flags &= ~MASK_SDATA; \
rs6000_sdata = SDATA_NONE; \
rs6000_sdata = SDATA_DATA; \
error ("-mrelocatable and -msdata are incompatible."); \
} \
\
if (TARGET_RELOCATABLE && !TARGET_EABI) \
{ \
target_flags |= ~MASK_EABI; \
error ("-mrelocatable and -mno-eabi are incompatible."); \
} \
\
if (TARGET_SDATA && DEFAULT_ABI != ABI_V4 \
&& DEFAULT_ABI != ABI_SOLARIS) \
{ \
target_flags &= ~MASK_SDATA; \
error ("-msdata and -mcall-aix are incompatible."); \
error ("-msdata and -mcall-%s are incompatible.", rs6000_abi_name); \
} \
\
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
......@@ -1039,6 +1032,8 @@ do { \
#undef CPP_SYSV_SPEC
#define CPP_SYSV_SPEC \
"%{mrelocatable*: -D_RELOCATABLE} \
%{fpic: -D__PIC__=1 -D__pic__=1} \
%{fPIC: -D__PIC__=2 -D__pic__=2} \
%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: %(cpp_sysv_default) }}}} \
......@@ -1047,22 +1042,34 @@ do { \
#undef CPP_SYSV_DEFAULT_SPEC
#define CPP_SYSV_DEFAULT_SPEC "-D_CALL_SYSV"
#ifndef CPP_ENDIAN_BIG_SPEC
#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Amachine(bigendian)"
#endif
#ifndef CPP_ENDIAN_LITTLE_SPEC
#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Amachine(littleendian)"
#endif
#ifndef CPP_ENDIAN_SOLARIS_SPEC
#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Amachine(littleendian)"
#endif
/* For solaris, don't define _LITTLE_ENDIAN, it conflicts with a header file. */
#undef CPP_ENDIAN_SPEC
#define CPP_ENDIAN_SPEC \
"%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
%{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
%{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
"%{mlittle: %(cpp_endian_little) } \
%{mlittle-endian: %(cpp_endian_little) } \
%{mbig: %(cpp_endian_big) } \
%{mbig-endian: %(cpp_endian_big) } \
%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
%{mcall-solaris: -Amachine(littleendian)} \
%{mcall-nt: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
%{mcall-linux: -D_BIG_ENDIAN -Amachine(bigendian)} \
%{mcall-aixdesc: -D_BIG_ENDIAN -Amachine(bigendian)} \
%{mcall-solaris: %(cpp_endian_solaris) } \
%{mcall-nt: %(cpp_endian_little) } \
%{mcall-linux: %(cpp_endian_big) } \
%{mcall-aixdesc: %(cpp_endian_big) } \
%{!mcall-solaris: %{!mcall-linux: %{!mcall-nt: %{!mcall-aixdesc: %(cpp_endian_default) }}}}}}}}"
#undef CPP_ENDIAN_DEFAULT_SPEC
#define CPP_ENDIAN_DEFAULT_SPEC "-D_BIG_ENDIAN -Amachine(bigendian)"
#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_big)"
#undef CPP_SPEC
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) %(cpp_endian) %(cpp_cpu) \
......@@ -1287,6 +1294,9 @@ do { \
{ "link_os_linux", LINK_OS_LINUX_SPEC }, \
{ "link_os_solaris", LINK_OS_SOLARIS_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
{ "cpp_endian_big", CPP_ENDIAN_BIG_SPEC }, \
{ "cpp_endian_little", CPP_ENDIAN_LITTLE_SPEC }, \
{ "cpp_endian_solaris", CPP_ENDIAN_SOLARIS_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
{ "cpp_os_sim", CPP_OS_SIM_SPEC }, \
{ "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
......
......@@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN)
#undef CPP_ENDIAN_DEFAULT_SPEC
#define CPP_ENDIAN_DEFAULT_SPEC "-D_LITTLE_ENDIAN -Amachine(littleendian)"
#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_little)"
#undef LINK_TARGET_SPEC
#define LINK_TARGET_SPEC "\
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment