1/*-
2 * Copyright (c) 2007-2013 Kai Wang
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: elfcopy.h 3615 2018-05-17 04:12:24Z kaiwang27 $
27 */
28
29#include <sys/queue.h>
30#include <gelf.h>
31#include <libelftc.h>
32
33#include "_elftc.h"
34
35/*
36 * User specified symbol operation (strip, keep, localize, globalize,
37 * weaken, rename, etc).
38 */
39struct symop {
40	const char	*name;
41	const char	*newname;
42
43#define SYMOP_KEEP	0x0001U
44#define SYMOP_STRIP	0x0002U
45#define SYMOP_GLOBALIZE	0x0004U
46#define SYMOP_LOCALIZE	0x0008U
47#define SYMOP_KEEPG	0x0010U
48#define SYMOP_WEAKEN	0x0020U
49#define SYMOP_REDEF	0x0040U
50
51	unsigned int	op;
52
53	STAILQ_ENTRY(symop) symop_list;
54};
55
56/* File containing symbol list. */
57struct symfile {
58	dev_t		 dev;
59	ino_t		 ino;
60	size_t		 size;
61	char		*data;
62	unsigned int	 op;
63
64	STAILQ_ENTRY(symfile) symfile_list;
65};
66
67/* Sections to copy/remove/rename/... */
68struct sec_action {
69	const char	*name;
70	const char	*addopt;
71	const char	*newname;
72	const char	*string;
73	uint64_t	 lma;
74	uint64_t	 vma;
75	int64_t		 lma_adjust;
76	int64_t		 vma_adjust;
77
78#define	SF_ALLOC	0x0001U
79#define	SF_LOAD		0x0002U
80#define	SF_NOLOAD	0x0004U
81#define	SF_READONLY	0x0008U
82#define	SF_DEBUG	0x0010U
83#define	SF_CODE		0x0020U
84#define	SF_DATA		0x0040U
85#define	SF_ROM		0x0080U
86#define	SF_SHARED	0X0100U
87#define	SF_CONTENTS	0x0200U
88
89	int	flags;
90	int	add;
91	int	append;
92	int	compress;
93	int	copy;
94	int	print;
95	int	remove;
96	int	rename;
97	int	setflags;
98	int	setlma;
99	int	setvma;
100
101	STAILQ_ENTRY(sec_action) sac_list;
102};
103
104/* Sections to add from file. */
105struct sec_add {
106	char	*name;
107	char	*content;
108	size_t	 size;
109
110	STAILQ_ENTRY(sec_add) sadd_list;
111};
112
113struct segment;
114
115/* Internal data structure for sections. */
116struct section {
117	struct segment	*seg;	/* containing segment */
118	struct segment	*seg_tls; /* tls segment */
119	const char	*name;	/* section name */
120	char		*newname; /* new section name */
121	Elf_Scn		*is;	/* input scn */
122	Elf_Scn		*os;	/* output scn */
123	void		*buf;	/* section content */
124	uint8_t		*pad;	/* section padding */
125	uint64_t	 off;	/* section offset */
126	uint64_t	 sz;	/* section size */
127	uint64_t	 cap;	/* section capacity */
128	uint64_t	 align;	/* section alignment */
129	uint64_t	 type;	/* section type */
130	uint64_t	 flags;	/* section flags */
131	uint64_t	 vma;	/* section virtual addr */
132	uint64_t	 lma;	/* section load addr */
133	uint64_t	 pad_sz;/* section padding size */
134	int		 loadable; /* whether loadable */
135	int		 pseudo;
136	int		 nocopy;
137
138	Elftc_String_Table *strtab;
139
140	TAILQ_ENTRY(section) sec_list;	/* next section */
141};
142
143TAILQ_HEAD(sectionlist, section);
144
145/* Internal data structure for segments. */
146struct segment {
147	uint64_t	vaddr;	/* virtual addr (VMA) */
148	uint64_t	paddr;	/* physical addr (LMA) */
149	uint64_t	off;	/* file offset */
150	uint64_t	fsz;	/* file size */
151	uint64_t	msz;	/* memory size */
152	uint64_t	type;	/* segment type */
153	int		remove;	/* whether remove */
154	int		nsec;	/* number of sections contained */
155	struct section **v_sec;	/* list of sections contained */
156
157	STAILQ_ENTRY(segment) seg_list; /* next segment */
158};
159
160/*
161 * In-memory representation of ar(1) archive member(object).
162 */
163struct ar_obj {
164	char	*name;		/* member name */
165	char	*buf;		/* member content */
166	void	*maddr;		/* mmap start address */
167	uid_t	 uid;		/* user id */
168	gid_t	 gid;		/* group id */
169	mode_t	 md;		/* octal file permissions */
170	size_t	 size;		/* member size */
171	time_t	 mtime;		/* modification time */
172
173	STAILQ_ENTRY(ar_obj) objs;
174};
175
176/*
177 * Structure encapsulates the "global" data for "elfcopy" program.
178 */
179struct elfcopy {
180	const char	*progname; /* program name */
181	int		 iec;	/* elfclass of input object */
182	Elftc_Bfd_Target_Flavor itf; /* flavour of input object */
183	Elftc_Bfd_Target_Flavor otf; /* flavour of output object */
184	const char	*otgt;	/* output target name */
185	int		 oec;	/* elfclass of output object */
186	unsigned char	 oed;	/* endianness of output object */
187	int		 oem;	/* EM_XXX of output object */
188	int		 abi;	/* OSABI of output object */
189	Elf		*ein;	/* ELF descriptor of input object */
190	Elf		*eout;	/* ELF descriptor of output object */
191	int		 iphnum; /* num. of input object phdr entries */
192	int		 ophnum; /* num. of output object phdr entries */
193	int		 nos;	/* num. of output object sections */
194
195	enum {
196		STRIP_NONE = 0,
197		STRIP_ALL,
198		STRIP_DEBUG,
199		STRIP_DWO,
200		STRIP_NONDEBUG,
201		STRIP_NONDWO,
202		STRIP_UNNEEDED
203	} strip;
204
205#define	EXECUTABLE	0x00000001U
206#define	DYNAMIC		0x00000002U
207#define	RELOCATABLE	0x00000004U
208#define	SYMTAB_EXIST	0x00000010U
209#define	SYMTAB_INTACT	0x00000020U
210#define	KEEP_GLOBAL	0x00000040U
211#define	DISCARD_LOCAL	0x00000080U
212#define	WEAKEN_ALL	0x00000100U
213#define	PRESERVE_DATE	0x00001000U
214#define	SREC_FORCE_S3	0x00002000U
215#define	SREC_FORCE_LEN	0x00004000U
216#define	SET_START	0x00008000U
217#define	GAP_FILL	0x00010000U
218#define	WILDCARD	0x00020000U
219#define	NO_CHANGE_WARN	0x00040000U
220#define	SEC_ADD		0x00080000U
221#define	SEC_APPEND	0x00100000U
222#define	SEC_COMPRESS	0x00200000U
223#define	SEC_PRINT	0x00400000U
224#define	SEC_REMOVE	0x00800000U
225#define	SEC_COPY	0x01000000U
226#define	DISCARD_LLABEL	0x02000000U
227#define	LOCALIZE_HIDDEN	0x04000000U
228
229	int		 flags;		/* elfcopy run control flags. */
230	int64_t		 change_addr;	/* Section address adjustment. */
231	int64_t		 change_start;	/* Entry point adjustment. */
232	uint64_t	 set_start;	/* Entry point value. */
233	unsigned long	 srec_len;	/* S-Record length. */
234	uint64_t	 pad_to;	/* load address padding. */
235	uint8_t		 fill;		/* gap fill value. */
236	char		*prefix_sec;	/* section prefix. */
237	char		*prefix_alloc;	/* alloc section prefix. */
238	char		*prefix_sym;	/* symbol prefix. */
239	char		*debuglink;	/* GNU debuglink file. */
240	struct section	*symtab;	/* .symtab section. */
241	struct section	*strtab;	/* .strtab section. */
242	struct section	*shstrtab;	/* .shstrtab section. */
243	uint64_t	*secndx;	/* section index map. */
244	uint64_t	*symndx;	/* symbol index map. */
245	unsigned char	*v_rel;		/* symbols needed by relocation. */
246	unsigned char	*v_grp;		/* symbols referred by section group. */
247	unsigned char	*v_secsym;	/* sections with section symbol. */
248	STAILQ_HEAD(, segment) v_seg;	/* list of segments. */
249	STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
250	STAILQ_HEAD(, sec_add) v_sadd;	/* list of sections to add. */
251	STAILQ_HEAD(, symop) v_symop;	/* list of symbols operations. */
252	STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */
253	TAILQ_HEAD(, section) v_sec;	/* list of sections. */
254
255	/*
256	 * Fields for the ar(1) archive.
257	 */
258	char		*as;		/* buffer for archive string table. */
259	size_t		 as_sz;		/* current size of as table. */
260	size_t		 as_cap;	/* capacity of as table buffer. */
261	uint32_t	 s_cnt;		/* current number of symbols. */
262	uint32_t	*s_so;		/* symbol offset table. */
263	size_t		 s_so_cap;	/* capacity of so table buffer. */
264	char		*s_sn;		/* symbol name table */
265	size_t		 s_sn_cap;	/* capacity of sn table buffer. */
266	size_t		 s_sn_sz;	/* current size of sn table. */
267	off_t		 rela_off;	/* offset relative to pseudo members. */
268	STAILQ_HEAD(, ar_obj) v_arobj;	/* archive object(member) list. */
269};
270
271void	add_section(struct elfcopy *_ecp, const char *_optarg);
272void	add_to_shstrtab(struct elfcopy *_ecp, const char *_name);
273void	add_to_symop_list(struct elfcopy *_ecp, const char *_name,
274    const char *_newname, unsigned int _op);
275void	add_to_symtab(struct elfcopy *_ecp, const char *_name,
276    uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx,
277    unsigned char _st_info, unsigned char _st_other, int _ndx_known);
278int	add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
279void	adjust_addr(struct elfcopy *_ecp);
280void	copy_content(struct elfcopy *_ecp);
281void	copy_data(struct section *_s);
282void	copy_phdr(struct elfcopy *_ecp);
283void	copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name,
284    int _copy, int _sec_flags);
285void	create_binary(int _ifd, int _ofd);
286void	create_elf(struct elfcopy *_ecp);
287void	create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn);
288void	create_elf_from_ihex(struct elfcopy *_ecp, int _ifd);
289void	create_elf_from_srec(struct elfcopy *_ecp, int _ifd);
290struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
291    char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype,
292    Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma,
293    int _loadable);
294void	create_external_symtab(struct elfcopy *_ecp);
295void	create_ihex(int _ifd, int _ofd);
296void	create_pe(struct elfcopy *_ecp, int _ifd, int _ofd);
297void	create_scn(struct elfcopy *_ecp);
298void	create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
299void	create_symtab(struct elfcopy *_ecp);
300void	create_symtab_data(struct elfcopy *_ecp);
301void	create_tempfile(char **_fn, int *_fd);
302void	finalize_external_symtab(struct elfcopy *_ecp);
303void	free_elf(struct elfcopy *_ecp);
304void	free_sec_act(struct elfcopy *_ecp);
305void	free_sec_add(struct elfcopy *_ecp);
306void	free_symtab(struct elfcopy *_ecp);
307void	init_shstrtab(struct elfcopy *_ecp);
308void	insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec,
309    int _tail);
310struct section *insert_shtab(struct elfcopy *_ecp, int tail);
311int	is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info);
312int	is_remove_section(struct elfcopy *_ecp, const char *_name);
313struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
314    const char *_name, int _add);
315struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
316    unsigned int _op);
317void	resync_sections(struct elfcopy *_ecp);
318void	setup_phdr(struct elfcopy *_ecp);
319void	update_shdr(struct elfcopy *_ecp, int _update_link);
320
321#ifndef LIBELF_AR
322int	ac_detect_ar(int _ifd);
323void	ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd);
324#endif	/* ! LIBELF_AR */
325