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 3446 2016-05-03 01:31:17Z emaste $
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  */
39 struct 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. */
57 struct 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/... */
68 struct 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. */
105 struct sec_add {
106 	char	*name;
107 	char	*content;
108 	size_t	 size;
109 
110 	STAILQ_ENTRY(sec_add) sadd_list;
111 };
112 
113 struct segment;
114 
115 /* Internal data structure for sections. */
116 struct 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	 vma;	/* section virtual addr */
131 	uint64_t	 lma;	/* section load addr */
132 	uint64_t	 pad_sz;/* section padding size */
133 	int		 loadable; /* whether loadable */
134 	int		 pseudo;
135 	int		 nocopy;
136 
137 	TAILQ_ENTRY(section) sec_list;	/* next section */
138 };
139 
140 /* Internal data structure for segments. */
141 struct segment {
142 	uint64_t	vaddr;	/* virtual addr (VMA) */
143 	uint64_t	paddr;	/* physical addr (LMA) */
144 	uint64_t	off;	/* file offset */
145 	uint64_t	fsz;	/* file size */
146 	uint64_t	msz;	/* memory size */
147 	uint64_t	type;	/* segment type */
148 	int		remove;	/* whether remove */
149 	int		nsec;	/* number of sections contained */
150 	struct section **v_sec;	/* list of sections contained */
151 
152 	STAILQ_ENTRY(segment) seg_list; /* next segment */
153 };
154 
155 /*
156  * In-memory representation of ar(1) archive member(object).
157  */
158 struct ar_obj {
159 	char	*name;		/* member name */
160 	char	*buf;		/* member content */
161 	void	*maddr;		/* mmap start address */
162 	uid_t	 uid;		/* user id */
163 	gid_t	 gid;		/* group id */
164 	mode_t	 md;		/* octal file permissions */
165 	size_t	 size;		/* member size */
166 	time_t	 mtime;		/* modification time */
167 
168 	STAILQ_ENTRY(ar_obj) objs;
169 };
170 
171 /*
172  * Structure encapsulates the "global" data for "elfcopy" program.
173  */
174 struct elfcopy {
175 	const char	*progname; /* program name */
176 	int		 iec;	/* elfclass of input object */
177 	Elftc_Bfd_Target_Flavor itf; /* flavour of input object */
178 	Elftc_Bfd_Target_Flavor otf; /* flavour of output object */
179 	const char	*otgt;	/* output target name */
180 	int		 oec;	/* elfclass of output object */
181 	unsigned char	 oed;	/* endianness of output object */
182 	int		 oem;	/* EM_XXX of output object */
183 	int		 abi;	/* OSABI of output object */
184 	Elf		*ein;	/* ELF descriptor of input object */
185 	Elf		*eout;	/* ELF descriptor of output object */
186 	int		 iphnum; /* num. of input object phdr entries */
187 	int		 ophnum; /* num. of output object phdr entries */
188 	int		 nos;	/* num. of output object sections */
189 
190 	enum {
191 		STRIP_NONE = 0,
192 		STRIP_ALL,
193 		STRIP_DEBUG,
194 		STRIP_DWO,
195 		STRIP_NONDEBUG,
196 		STRIP_NONDWO,
197 		STRIP_UNNEEDED
198 	} strip;
199 
200 #define	EXECUTABLE	0x00000001U
201 #define	DYNAMIC		0x00000002U
202 #define	RELOCATABLE	0x00000004U
203 #define	SYMTAB_EXIST	0x00000010U
204 #define	SYMTAB_INTACT	0x00000020U
205 #define	KEEP_GLOBAL	0x00000040U
206 #define	DISCARD_LOCAL	0x00000080U
207 #define	WEAKEN_ALL	0x00000100U
208 #define	PRESERVE_DATE	0x00001000U
209 #define	SREC_FORCE_S3	0x00002000U
210 #define	SREC_FORCE_LEN	0x00004000U
211 #define	SET_START	0x00008000U
212 #define	GAP_FILL	0x00010000U
213 #define	WILDCARD	0x00020000U
214 #define	NO_CHANGE_WARN	0x00040000U
215 #define	SEC_ADD		0x00080000U
216 #define	SEC_APPEND	0x00100000U
217 #define	SEC_COMPRESS	0x00200000U
218 #define	SEC_PRINT	0x00400000U
219 #define	SEC_REMOVE	0x00800000U
220 #define	SEC_COPY	0x01000000U
221 #define	DISCARD_LLABEL	0x02000000U
222 #define	LOCALIZE_HIDDEN	0x04000000U
223 
224 	int		 flags;		/* elfcopy run control flags. */
225 	int64_t		 change_addr;	/* Section address adjustment. */
226 	int64_t		 change_start;	/* Entry point adjustment. */
227 	uint64_t	 set_start;	/* Entry point value. */
228 	unsigned long	 srec_len;	/* S-Record length. */
229 	uint64_t	 pad_to;	/* load address padding. */
230 	uint8_t		 fill;		/* gap fill value. */
231 	char		*prefix_sec;	/* section prefix. */
232 	char		*prefix_alloc;	/* alloc section prefix. */
233 	char		*prefix_sym;	/* symbol prefix. */
234 	char		*debuglink;	/* GNU debuglink file. */
235 	struct section	*symtab;	/* .symtab section. */
236 	struct section	*strtab;	/* .strtab section. */
237 	struct section	*shstrtab;	/* .shstrtab section. */
238 	uint64_t	*secndx;	/* section index map. */
239 	uint64_t	*symndx;	/* symbol index map. */
240 	unsigned char	*v_rel;		/* symbols needed by relocation. */
241 	unsigned char	*v_grp;		/* symbols referred by section group. */
242 	unsigned char	*v_secsym;	/* sections with section symbol. */
243 	STAILQ_HEAD(, segment) v_seg;	/* list of segments. */
244 	STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
245 	STAILQ_HEAD(, sec_add) v_sadd;	/* list of sections to add. */
246 	STAILQ_HEAD(, symop) v_symop;	/* list of symbols operations. */
247 	STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */
248 	TAILQ_HEAD(, section) v_sec;	/* list of sections. */
249 
250 	/*
251 	 * Fields for the ar(1) archive.
252 	 */
253 	char		*as;		/* buffer for archive string table. */
254 	size_t		 as_sz;		/* current size of as table. */
255 	size_t		 as_cap;	/* capacity of as table buffer. */
256 	uint32_t	 s_cnt;		/* current number of symbols. */
257 	uint32_t	*s_so;		/* symbol offset table. */
258 	size_t		 s_so_cap;	/* capacity of so table buffer. */
259 	char		*s_sn;		/* symbol name table */
260 	size_t		 s_sn_cap;	/* capacity of sn table buffer. */
261 	size_t		 s_sn_sz;	/* current size of sn table. */
262 	off_t		 rela_off;	/* offset relative to pseudo members. */
263 	STAILQ_HEAD(, ar_obj) v_arobj;	/* archive object(member) list. */
264 };
265 
266 void	add_section(struct elfcopy *_ecp, const char *_optarg);
267 void	add_to_shstrtab(struct elfcopy *_ecp, const char *_name);
268 void	add_to_symop_list(struct elfcopy *_ecp, const char *_name,
269     const char *_newname, unsigned int _op);
270 void	add_to_symtab(struct elfcopy *_ecp, const char *_name,
271     uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx,
272     unsigned char _st_info, unsigned char _st_other, int _ndx_known);
273 int	add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
274 void	adjust_addr(struct elfcopy *_ecp);
275 void	copy_content(struct elfcopy *_ecp);
276 void	copy_data(struct section *_s);
277 void	copy_phdr(struct elfcopy *_ecp);
278 void	copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name,
279     int _copy, int _sec_flags);
280 void	create_binary(int _ifd, int _ofd);
281 void	create_elf(struct elfcopy *_ecp);
282 void	create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn);
283 void	create_elf_from_ihex(struct elfcopy *_ecp, int _ifd);
284 void	create_elf_from_srec(struct elfcopy *_ecp, int _ifd);
285 struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
286     char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype,
287     Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma,
288     int _loadable);
289 void	create_external_symtab(struct elfcopy *_ecp);
290 void	create_ihex(int _ifd, int _ofd);
291 void	create_pe(struct elfcopy *_ecp, int _ifd, int _ofd);
292 void	create_scn(struct elfcopy *_ecp);
293 void	create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
294 void	create_symtab(struct elfcopy *_ecp);
295 void	create_symtab_data(struct elfcopy *_ecp);
296 void	create_tempfile(char **_fn, int *_fd);
297 void	finalize_external_symtab(struct elfcopy *_ecp);
298 void	free_elf(struct elfcopy *_ecp);
299 void	free_sec_act(struct elfcopy *_ecp);
300 void	free_sec_add(struct elfcopy *_ecp);
301 void	free_symtab(struct elfcopy *_ecp);
302 void	init_shstrtab(struct elfcopy *_ecp);
303 void	insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec,
304     int _tail);
305 struct section *insert_shtab(struct elfcopy *_ecp, int tail);
306 int	is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info);
307 int	is_remove_section(struct elfcopy *_ecp, const char *_name);
308 struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
309     const char *_name, int _add);
310 struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
311     unsigned int _op);
312 void	resync_sections(struct elfcopy *_ecp);
313 void	set_shstrtab(struct elfcopy *_ecp);
314 void	setup_phdr(struct elfcopy *_ecp);
315 void	update_shdr(struct elfcopy *_ecp, int _update_link);
316 
317 #ifndef LIBELF_AR
318 int	ac_detect_ar(int _ifd);
319 void	ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd);
320 #endif	/* ! LIBELF_AR */
321