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 3757 2019-06-28 01:15:28Z 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	 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 
143 TAILQ_HEAD(sectionlist, section);
144 
145 /* Internal data structure for segments. */
146 struct 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  */
163 struct 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  */
179 struct 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 
271 void	add_section(struct elfcopy *_ecp, const char *_optarg);
272 void	add_to_shstrtab(struct elfcopy *_ecp, const char *_name);
273 void	add_to_symop_list(struct elfcopy *_ecp, const char *_name,
274     const char *_newname, unsigned int _op);
275 void	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);
278 int	add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec);
279 void	adjust_addr(struct elfcopy *_ecp);
280 int	cleanup_tempfile(char *_fn);
281 void	copy_content(struct elfcopy *_ecp);
282 void	copy_data(struct section *_s);
283 void	copy_phdr(struct elfcopy *_ecp);
284 void	copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name,
285     int _copy, int _sec_flags);
286 void	create_binary(int _ifd, int _ofd);
287 void	create_elf(struct elfcopy *_ecp);
288 void	create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn);
289 void	create_elf_from_ihex(struct elfcopy *_ecp, int _ifd);
290 void	create_elf_from_srec(struct elfcopy *_ecp, int _ifd);
291 struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
292     char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype,
293     Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma,
294     int _loadable);
295 void	create_external_symtab(struct elfcopy *_ecp);
296 void	create_ihex(int _ifd, int _ofd);
297 void	create_pe(struct elfcopy *_ecp, int _ifd, int _ofd);
298 void	create_scn(struct elfcopy *_ecp);
299 void	create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
300 void	create_symtab(struct elfcopy *_ecp);
301 void	create_symtab_data(struct elfcopy *_ecp);
302 void	create_tempfile(const char *_src, char **_fn, int *_fd);
303 void	finalize_external_symtab(struct elfcopy *_ecp);
304 void	free_elf(struct elfcopy *_ecp);
305 void	free_sec_act(struct elfcopy *_ecp);
306 void	free_sec_add(struct elfcopy *_ecp);
307 void	free_symtab(struct elfcopy *_ecp);
308 void	init_shstrtab(struct elfcopy *_ecp);
309 void	insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec,
310     int _tail);
311 struct section *insert_shtab(struct elfcopy *_ecp, int tail);
312 int	is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info);
313 int	is_remove_section(struct elfcopy *_ecp, const char *_name);
314 struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
315     const char *_name, int _add);
316 struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
317     unsigned int _op);
318 void	resync_sections(struct elfcopy *_ecp);
319 void	setup_phdr(struct elfcopy *_ecp);
320 void	update_shdr(struct elfcopy *_ecp, int _update_link);
321 
322 #ifndef LIBELF_AR
323 int	ac_detect_ar(int _ifd);
324 void	ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd);
325 #endif	/* ! LIBELF_AR */
326