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