4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1988 AT&T
26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Copyright 2011, Richard Lowe.
32 * This file contains the functions responsible for opening the output file
33 * image, associating the appropriate input elf structures with the new image,
34 * and obtaining new elf structures to define the new image.
49 * Determine a least common multiplier. Input sections contain an alignment
50 * requirement, which elf_update() uses to insure that the section is aligned
51 * correctly off of the base of the elf image. We must also insure that the
52 * sections mapping is congruent with this alignment requirement. For each
53 * input section associated with a loadable segment determine whether the
54 * segments alignment must be adjusted to compensate for a sections alignment
58 ld_lcm(Xword a
, Xword b
)
69 while ((_r
= _b
% _a
) != 0)
71 return ((a
/ _a
) * b
);
75 * Open the output file and insure the correct access modes.
78 ld_open_outfile(Ofl_desc
* ofl
)
84 * Determine the required file mode from the type of output file we
87 mode
= (ofl
->ofl_flags
& (FLG_OF_EXEC
| FLG_OF_SHAROBJ
))
90 /* Determine if the output file already exists */
91 if (stat(ofl
->ofl_name
, &status
) == 0) {
92 if ((status
.st_mode
& S_IFMT
) != S_IFREG
) {
94 * It is not a regular file, so don't delete it
95 * or allow it to be deleted. This allows root
96 * users to specify /dev/null output file for
99 ofl
->ofl_flags1
|= FLG_OF1_NONREG
;
102 * It's a regular file, so unlink it. In standard
103 * Unix fashion, the old file will continue to
104 * exist until its link count drops to 0 and no
105 * process has the file open. In the meantime, we
106 * create a new file (inode) under the same name,
107 * available for new use.
109 * The advantage of this policy is that creating
110 * a new executable or sharable library does not
111 * corrupt existing processes using the old file.
112 * A possible disadvantage is that if the existing
113 * file has a (link_count > 1), the other names will
114 * continue to reference the old inode, thus
117 * A subtlety here is that POSIX says we are not
118 * supposed to replace a non-writable file, which
119 * is something that unlink() is happy to do. The
120 * only 100% reliable test against this is to open
121 * the file for non-destructive write access. If the
122 * open succeeds, we are clear to unlink it, and if
123 * not, then the error generated is the error we
126 if ((ofl
->ofl_fd
= open(ofl
->ofl_name
, O_RDWR
,
131 ld_eprintf(ofl
, ERR_FATAL
,
132 MSG_INTL(MSG_SYS_OPEN
),
133 ofl
->ofl_name
, strerror(err
));
137 (void) close(ofl
->ofl_fd
);
140 if ((unlink(ofl
->ofl_name
) == -1) &&
144 ld_eprintf(ofl
, ERR_FATAL
,
145 MSG_INTL(MSG_SYS_UNLINK
),
146 ofl
->ofl_name
, strerror(err
));
153 * Open (or create) the output file name (ofl_fd acts as a global
154 * flag to ldexit() signifying whether the output file should be
155 * removed or not on error).
157 if ((ofl
->ofl_fd
= open(ofl
->ofl_name
, O_RDWR
| O_CREAT
| O_TRUNC
,
161 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_SYS_OPEN
),
162 ofl
->ofl_name
, strerror(err
));
171 * If we are creating a memory model we need to update the present memory image.
172 * Use elf_update(ELF_C_NULL) to calculate the offset of each section and their
173 * associated data buffers. From this information determine what padding is
176 * Two actions are necessary to convert the present disc image into a memory
179 * - Loadable segments must be padded so that the next segment virtual
180 * address and file offset are the same.
182 * - NOBITS sections must be converted into allocated, null filled sections.
185 pad_outfile(Ofl_desc
*ofl
)
194 * Update all the elf structures. This will assign offsets to the
195 * section headers and data buffers as they relate to the new image.
197 if (elf_update(ofl
->ofl_welf
, ELF_C_NULL
) == -1) {
198 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_UPDATE
),
202 if ((ehdr
= elf_getehdr(ofl
->ofl_welf
)) == NULL
) {
203 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_GETEHDR
),
209 * Initialize the offset by skipping the Elf header and program
212 offset
= ehdr
->e_phoff
+ (ehdr
->e_phnum
* ehdr
->e_phentsize
);
215 * Traverse the segment list looking for loadable segments.
217 for (APLIST_TRAVERSE(ofl
->ofl_segs
, idx1
, sgp
)) {
218 Phdr
*phdr
= &(sgp
->sg_phdr
);
223 * If we've already processed a loadable segment, the `scn'
224 * variable will be initialized to the last section that was
225 * part of that segment. Add sufficient padding to this section
226 * to cause the next segments virtual address and file offset to
229 if (oscn
&& (phdr
->p_type
== PT_LOAD
)) {
233 size
= (size_t)(S_ROUND(offset
, phdr
->p_align
) -
236 if ((data
= elf_newdata(oscn
)) == NULL
) {
237 ld_eprintf(ofl
, ERR_ELF
,
238 MSG_INTL(MSG_ELF_NEWDATA
), ofl
->ofl_name
);
241 if ((data
->d_buf
= libld_calloc(size
, 1)) == 0)
244 data
->d_type
= ELF_T_BYTE
;
247 data
->d_version
= ofl
->ofl_dehdr
->e_version
;
251 * Traverse the output sections for this segment calculating the
252 * offset of each section. Retain the final section descriptor
253 * as this will be where any padding buffer will be added.
255 for (APLIST_TRAVERSE(sgp
->sg_osdescs
, idx2
, osp
)) {
256 Shdr
*shdr
= osp
->os_shdr
;
258 offset
= (off_t
)S_ROUND(offset
, shdr
->sh_addralign
);
259 offset
+= shdr
->sh_size
;
262 * If this is a NOBITS output section convert all of
263 * its associated input sections into real, null filled,
264 * data buffers, and change the section to PROGBITS.
266 if (shdr
->sh_type
== SHT_NOBITS
)
267 shdr
->sh_type
= SHT_PROGBITS
;
271 * If this is a loadable segment retain the last output section
272 * descriptor. This acts both as a flag that a loadable
273 * segment has been seen, and as the segment to which a padding
274 * buffer will be added.
276 if (phdr
->p_type
== PT_LOAD
)
283 * Create an output section. The first instance of an input section triggers
284 * the creation of a new output section.
287 create_outsec(Ofl_desc
*ofl
, Sg_desc
*sgp
, Os_desc
*osp
, Word ptype
, int shidx
,
294 * Get a section descriptor for the section.
296 if ((scn
= elf_newscn(ofl
->ofl_welf
)) == NULL
) {
297 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_NEWSCN
),
304 * Get a new section header table entry and copy the pertinent
305 * information from the in-core descriptor.
307 if ((shdr
= elf_getshdr(scn
)) == NULL
) {
308 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_GETSHDR
),
312 *shdr
= *(osp
->os_shdr
);
316 * If this is the first section within a loadable segment, and the
317 * alignment needs to be updated, record this section.
319 if ((fixalign
== TRUE
) && (ptype
== PT_LOAD
) && (shidx
== 1))
323 * If not building a relocatable object, remove any of the
324 * following flags, as they have been acted upon and are not
325 * meaningful in the output:
326 * SHF_ORDERED, SHF_LINK_ORDER, SHF_GROUP
327 * For relocatable objects, we allow them to propagate to
328 * the output object to be handled by the next linker that
331 if ((ofl
->ofl_flags
& FLG_OF_RELOBJ
) == 0)
332 osp
->os_shdr
->sh_flags
&= ~(ALL_SHF_ORDER
|SHF_GROUP
);
335 * If this is a TLS section, save it so that the PT_TLS program header
336 * information can be established after the output image has been
337 * initially created. At this point, all TLS input sections are ordered
338 * as they will appear in the output image.
340 if ((ofl
->ofl_flags
& FLG_OF_TLSPHDR
) &&
341 (osp
->os_shdr
->sh_flags
& SHF_TLS
) &&
342 (aplist_append(&ofl
->ofl_ostlsseg
, osp
,
343 AL_CNT_OFL_OSTLSSEG
) == NULL
))
350 * Create the elf structures that allow the input data to be associated with the
353 * - define the new elf image using elf_begin(),
355 * - obtain an elf header for the image,
357 * - traverse the input segments and create a program header array to define
358 * the required segments,
360 * - traverse the output sections for each segment assigning a new section
361 * descriptor and section header for each,
363 * - traverse the input sections associated with each output section and
364 * assign a new data descriptor to each (each output section becomes a
365 * linked list of input data buffers).
368 ld_create_outfile(Ofl_desc
*ofl
)
373 Elf_Data
*tlsdata
= 0;
375 ofl_flag_t flags
= ofl
->ofl_flags
;
376 ofl_flag_t flags1
= ofl
->ofl_flags1
;
379 Boolean fixalign
= FALSE
;
380 int fd
, nseg
= 0, shidx
, dataidx
, ptloadidx
= 0;
382 DBG_CALL(Dbg_basic_create(ofl
->ofl_lml
));
385 * If DF_1_NOHDR or FLG_OF1_VADDR were set,
386 * we need to do alignment adjustment.
388 if ((flags1
& FLG_OF1_VADDR
) ||
389 (ofl
->ofl_dtflags_1
& DF_1_NOHDR
)) {
393 if (flags1
& FLG_OF1_MEMORY
) {
402 * If there are any ordered sections, handle them here.
404 if ((ofl
->ofl_ordered
!= NULL
) &&
405 (ld_sort_ordered(ofl
) == S_ERROR
))
409 * Tell the access library about our new temporary file.
411 if ((ofl
->ofl_welf
= elf_begin(fd
, cmd
, 0)) == NULL
) {
412 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_BEGIN
),
418 * Obtain a new Elf header.
420 if ((ofl
->ofl_nehdr
= elf_newehdr(ofl
->ofl_welf
)) == NULL
) {
421 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_NEWEHDR
),
425 ofl
->ofl_nehdr
->e_machine
= ofl
->ofl_dehdr
->e_machine
;
427 DBG_CALL(Dbg_util_nl(ofl
->ofl_lml
, DBG_NL_STD
));
428 for (APLIST_TRAVERSE(ofl
->ofl_segs
, idx1
, sgp
)) {
430 Phdr
*phdr
= &(sgp
->sg_phdr
);
431 Word ptype
= phdr
->p_type
;
433 Os_desc
*nonempty
= NULL
; /* First non-empty section */
436 * Count the number of segments that will go in the program
437 * header table. If a segment is empty, ignore it.
439 if (!(flags
& FLG_OF_RELOBJ
)) {
441 * If the program header type belongs to the os range,
442 * the resulting object is ELFOSABI_SOLARIS.
444 if ((ptype
>= PT_LOOS
) && (ptype
<= PT_HIOS
))
445 ofl
->ofl_flags
|= FLG_OF_OSABI
;
447 if (ptype
== PT_PHDR
) {
449 * If we are generating an interp section (and
450 * thus an associated PT_INTERP program header
451 * entry) also generate a PT_PHDR program header
452 * entry. This allows the kernel to generate
453 * the appropriate aux vector entries to pass to
454 * the interpreter (refer to exec/elf/elf.c).
455 * Note that if an image was generated with an
456 * interp section, but no associated PT_PHDR
457 * program header entry, the kernel will simply
458 * pass the interpreter an open file descriptor
459 * when the image is executed).
461 if (ofl
->ofl_osinterp
)
463 } else if (ptype
== PT_INTERP
) {
464 if (ofl
->ofl_osinterp
)
466 } else if (ptype
== PT_DYNAMIC
) {
467 if (flags
& FLG_OF_DYNAMIC
)
469 } else if (ptype
== PT_TLS
) {
470 if (flags
& FLG_OF_TLSPHDR
)
472 } else if (ptype
== PT_SUNW_UNWIND
) {
473 if (ofl
->ofl_unwindhdr
)
475 } else if (ptype
== PT_SUNWDTRACE
) {
476 if (ofl
->ofl_dtracesym
)
478 } else if (ptype
== PT_SUNWCAP
) {
481 } else if (ptype
== PT_SUNWSTACK
) {
482 if ((sgp
->sg_flags
& FLG_SG_DISABLED
) == 0)
484 } else if (sgp
->sg_flags
& FLG_SG_EMPTY
) {
486 } else if (sgp
->sg_osdescs
!= NULL
) {
487 if ((sgp
->sg_flags
& FLG_SG_PHREQ
) == 0) {
489 * If this is a segment for which
490 * we are not making a program header,
491 * don't increment nseg
493 ptype
= (sgp
->sg_phdr
).p_type
= PT_NULL
;
494 } else if (ptype
!= PT_NULL
)
500 * Establish any processing unique to the first loadable
503 if ((ptype
== PT_LOAD
) && (ptloadidx
== 0)) {
507 * If the first loadable segment is not supposed to
508 * include the ELF or program headers, alignments
509 * of the following segments need to be fixed,
510 * plus a .dynamic FLAGS1 setting is required.
512 if (ofl
->ofl_dtflags_1
& DF_1_NOHDR
)
517 for (APLIST_TRAVERSE(sgp
->sg_osdescs
, idx2
, osp
)) {
523 OS_ISDESCS_TRAVERSE(os_isdescs_idx
, osp
, idx3
, isp
) {
525 Ifl_desc
*ifl
= isp
->is_file
;
528 * An input section in the list that has
529 * been previously marked to be discarded
530 * should be completely ignored.
532 if (isp
->is_flags
& FLG_IS_DISCARD
)
536 * At this point we know whether a section has
537 * been referenced. If it hasn't, and the whole
538 * file hasn't been referenced (which would have
539 * been caught in ignore_section_processing()),
540 * give a diagnostic (-D unused,detail) or
541 * discard the section if -zignore is in effect.
544 (((ifl
->ifl_flags
& FLG_IF_FILEREF
) == 0) ||
545 ((ptype
== PT_LOAD
) &&
546 ((isp
->is_flags
& FLG_IS_SECTREF
) == 0) &&
547 (isp
->is_shdr
->sh_size
> 0)))) {
548 Lm_list
*lml
= ofl
->ofl_lml
;
550 if (ifl
->ifl_flags
& FLG_IF_IGNORE
) {
551 isp
->is_flags
|= FLG_IS_DISCARD
;
552 DBG_CALL(Dbg_unused_sec(lml
,
556 DBG_CALL(Dbg_unused_sec(lml
,
562 * If this section provides no data, and isn't
563 * referenced, then it can be discarded as well.
564 * Note, if this is the first input section
565 * associated to an output section, let it
566 * through, there may be a legitimate reason why
567 * the user wants a null section. Discarding
568 * additional sections is intended to remove the
569 * empty clutter the compilers have a habit of
570 * creating. Don't provide an unused diagnostic
571 * as these sections aren't typically the users
574 if (ifl
&& dataidx
&&
575 ((isp
->is_flags
& FLG_IS_SECTREF
) == 0) &&
576 (isp
->is_shdr
->sh_size
== 0)) {
577 isp
->is_flags
|= FLG_IS_DISCARD
;
582 * The first input section triggers the creation
583 * of the associated output section.
585 if (osp
->os_scn
== NULL
) {
588 if (create_outsec(ofl
, sgp
, osp
, ptype
,
589 shidx
, fixalign
) == S_ERROR
)
596 * Create a new output data buffer for each
597 * input data buffer, thus linking the new
598 * buffers to the new elf output structures.
599 * Simply make the new data buffers point to
602 if ((data
= elf_newdata(osp
->os_scn
)) == NULL
) {
603 ld_eprintf(ofl
, ERR_ELF
,
604 MSG_INTL(MSG_ELF_NEWDATA
),
608 *data
= *(isp
->is_indata
);
609 isp
->is_indata
= data
;
611 if ((fixalign
== TRUE
) && (ptype
== PT_LOAD
) &&
612 (shidx
== 1) && (dataidx
== 1))
613 data
->d_align
= sgp
->sg_align
;
616 * Save the first TLS data buffer, as this is
617 * the start of the TLS segment. Realign this
618 * buffer based on the alignment requirements
619 * of all the TLS input sections.
621 if ((flags
& FLG_OF_TLSPHDR
) &&
622 (isp
->is_shdr
->sh_flags
& SHF_TLS
)) {
626 ld_lcm(tlsdata
->d_align
,
627 isp
->is_shdr
->sh_addralign
);
630 #if defined(_ELF64) && defined(_ILP32)
632 * 4106312, the 32-bit ELF64 version of ld
633 * needs to be able to create large .bss
634 * sections. The d_size member of Elf_Data
635 * only allows 32-bits in _ILP32, so we build
636 * multiple data-items that each fit into 32-
637 * bits. libelf (4106398) can summ these up
638 * into a 64-bit quantity. This only works
639 * for NOBITS sections which don't have any
640 * real data to maintain and don't require
641 * large file support.
643 if (isp
->is_shdr
->sh_type
== SHT_NOBITS
) {
644 Xword sz
= isp
->is_shdr
->sh_size
;
647 data
->d_size
= SIZE_MAX
;
648 sz
-= (Xword
)SIZE_MAX
;
650 data
= elf_newdata(osp
->os_scn
);
654 data
->d_size
= (size_t)sz
;
659 * If this segment requires rounding realign the
660 * first data buffer associated with the first
664 (sgp
->sg_flags
& FLG_SG_ROUND
)) {
669 S_ROUND(data
->d_align
,
672 align
= sgp
->sg_round
;
674 data
->d_align
= (size_t)align
;
677 if ((data
->d_size
!= 0) && (nonempty
== NULL
)) {
683 * Clear the szoutrels counter so that it can be used
684 * again in the building of relocs. See machrel.c.
686 osp
->os_szoutrels
= 0;
690 * We need to raise the alignment of any empty sections at the
691 * start of a segment to be at least as aligned as the first
692 * non-empty section, such that the empty and first non-empty
693 * sections are placed at the same offset.
695 if (nonempty
!= NULL
) {
699 ne
= elf_getdata(nonempty
->os_scn
, NULL
);
703 pad_align
= ld_lcm(pad_align
, ne
->d_align
);
704 ne
= elf_getdata(nonempty
->os_scn
, ne
);
705 } while (ne
!= NULL
);
707 for (APLIST_TRAVERSE(sgp
->sg_osdescs
, idx2
, osp
)) {
710 /* Stop at the first non-empty section */
714 d
= elf_getdata(osp
->os_scn
, NULL
);
717 d
->d_align
= pad_align
;
723 * Did we use ELF features from the osabi range? If so,
724 * update the ELF header osabi fields. If this doesn't happen,
725 * those fields remain 0, reflecting a generic System V ELF ABI.
727 if (ofl
->ofl_flags
& FLG_OF_OSABI
) {
728 ofl
->ofl_nehdr
->e_ident
[EI_OSABI
] = ELFOSABI_SOLARIS
;
729 ofl
->ofl_nehdr
->e_ident
[EI_ABIVERSION
] = EAV_SUNW_CURRENT
;
733 * Build an empty PHDR.
736 if ((ofl
->ofl_phdr
= elf_newphdr(ofl
->ofl_welf
,
738 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_NEWPHDR
),
745 * If we need to generate a memory model, pad the image.
747 if (flags1
& FLG_OF1_MEMORY
) {
748 if (pad_outfile(ofl
) == S_ERROR
)
753 * After all the basic input file processing, all data pointers are
754 * referencing two types of memory:
756 * - allocated memory, ie. elf structures, internal link editor
757 * structures, and any new sections that have been created.
759 * - original input file mmap'ed memory, ie. the actual data
760 * sections of the input file images.
762 * Up until now, the only memory modifications have been carried out on
763 * the allocated memory. Before carrying out any relocations, write the
764 * new output file image and reassign any necessary data pointers to the
765 * output files memory image. This insures that any relocation
766 * modifications are made to the output file image and not to the input
767 * file image, thus preventing the creation of dirty pages and reducing
768 * the overall swap space requirement.
770 * Write out the elf structure so as to create the new file image.
772 if ((ofl
->ofl_size
= (size_t)elf_update(ofl
->ofl_welf
,
773 ELF_C_WRIMAGE
)) == (size_t)-1) {
774 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_UPDATE
),
780 * Initialize the true `ofl' information with the memory images address
781 * and size. This will be used to write() out the image once any
782 * relocation processing has been completed. We also use this image
783 * information to setup a new Elf descriptor, which is used to obtain
784 * all the necessary elf pointers within the new output image.
786 if ((ofl
->ofl_elf
= elf_begin(0, ELF_C_IMAGE
,
787 ofl
->ofl_welf
)) == NULL
) {
788 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_BEGIN
),
792 if ((ofl
->ofl_nehdr
= elf_getehdr(ofl
->ofl_elf
)) == NULL
) {
793 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_GETEHDR
),
797 if (!(flags
& FLG_OF_RELOBJ
))
798 if ((ofl
->ofl_phdr
= elf_getphdr(ofl
->ofl_elf
)) == NULL
) {
799 ld_eprintf(ofl
, ERR_ELF
, MSG_INTL(MSG_ELF_GETPHDR
),
805 * Reinitialize the section descriptors, section headers and obtain new
806 * output data buffer pointers (these will be used to perform any
810 for (APLIST_TRAVERSE(ofl
->ofl_segs
, idx1
, sgp
)) {
811 Phdr
*_phdr
= &(sgp
->sg_phdr
);
814 Boolean recorded
= FALSE
;
816 for (APLIST_TRAVERSE(sgp
->sg_osdescs
, idx2
, osp
)) {
818 * Make sure that an output section was originally
819 * created. Input sections that had been marked as
820 * discarded may have made an output section
821 * unnecessary. Remove this alist entry so that
822 * future output section descriptor processing doesn't
823 * have to compensate for this empty section.
825 if (osp
->os_scn
== NULL
) {
826 aplist_delete(sgp
->sg_osdescs
, &idx2
);
830 elf_getscn(ofl
->ofl_elf
, ++ndx
)) == NULL
) {
831 ld_eprintf(ofl
, ERR_ELF
,
832 MSG_INTL(MSG_ELF_GETSCN
), ofl
->ofl_name
,
837 elf_getshdr(osp
->os_scn
)) == NULL
) {
838 ld_eprintf(ofl
, ERR_ELF
,
839 MSG_INTL(MSG_ELF_GETSHDR
), ofl
->ofl_name
);
842 if ((fixalign
== TRUE
) && sgp
->sg_fscn
&&
843 (recorded
== FALSE
)) {
848 if ((fndx
= elf_ndxscn(scn
)) == SHN_UNDEF
) {
849 ld_eprintf(ofl
, ERR_ELF
,
850 MSG_INTL(MSG_ELF_NDXSCN
),
855 sgp
->sg_fscn
= osp
->os_scn
;
860 if ((osp
->os_outdata
=
861 elf_getdata(osp
->os_scn
, NULL
)) == NULL
) {
862 ld_eprintf(ofl
, ERR_ELF
,
863 MSG_INTL(MSG_ELF_GETDATA
), ofl
->ofl_name
);
868 * If this section is part of a loadable segment insure
869 * that the segments alignment is appropriate.
871 if (_phdr
->p_type
== PT_LOAD
) {
872 _phdr
->p_align
= ld_lcm(_phdr
->p_align
,
873 osp
->os_shdr
->sh_addralign
);