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