1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Set bits in the DT_FLAGS_1 member of the .dynamic section of an object. 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <stdarg.h> 34 #include <errno.h> 35 #include <libelf.h> 36 #include <gelf.h> 37 #include <string.h> 38 #include <fcntl.h> 39 #include <libgen.h> 40 #include <unistd.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <sys/link.h> 44 45 #include <util.h> 46 47 /* 48 * These are here because we can't be sure (yet) that the build machine has a 49 * sys/link.h that includes the following #defines. This tool will be executed 50 * on the build machine, so we have to use its headers (rather than the ones 51 * in $ROOT which will, by definition, be up to date). These #defines can be 52 * removed when we're sure that all build machines have recent copies of 53 * sys/link.h. 54 */ 55 #ifndef DF_1_IGNMULDEF 56 #define DF_1_IGNMULDEF 0x00040000 57 #endif 58 #ifndef DF_1_NOKSYMS 59 #define DF_1_NOKSYMS 0x00080000 60 #endif 61 62 struct dtflagval { 63 char *fv_name; 64 ulong_t fv_val; 65 }; 66 67 static struct dtflagval dtflagvals[] = { 68 { "DF_1_IGNMULDEF", DF_1_IGNMULDEF }, 69 { "DF_1_NOKSYMS", DF_1_NOKSYMS }, 70 { NULL } 71 }; 72 73 const char *progname; 74 75 static void 76 usage(void) 77 { 78 (void) fprintf(stderr, "Usage: %s -f flag_val file\n", progname); 79 exit(2); 80 } 81 82 static void 83 set_flag(char *ifile, ulong_t flval) 84 { 85 Elf *elf; 86 Elf_Scn *scn; 87 Elf_Data *data; 88 GElf_Shdr shdr; 89 GElf_Dyn dyn; 90 int fd, secidx, nent, i; 91 92 (void) elf_version(EV_CURRENT); 93 94 if ((fd = open(ifile, O_RDWR)) < 0) 95 die("Can't open %s", ifile); 96 97 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) 98 elfdie("Can't start ELF for %s", ifile); 99 100 if ((secidx = findelfsecidx(elf, ".dynamic")) == -1) 101 die("Can't find .dynamic section in %s\n", ifile); 102 103 if ((scn = elf_getscn(elf, secidx)) == NULL) 104 elfdie("elf_getscn (%d)", secidx); 105 106 if (gelf_getshdr(scn, &shdr) == NULL) 107 elfdie("gelf_shdr"); 108 109 if ((data = elf_getdata(scn, NULL)) == NULL) 110 elfdie("elf_getdata"); 111 112 nent = shdr.sh_size / shdr.sh_entsize; 113 for (i = 0; i < nent; i++) { 114 if (gelf_getdyn(data, i, &dyn) == NULL) 115 elfdie("gelf_getdyn"); 116 117 if (dyn.d_tag == DT_FLAGS_1) { 118 dyn.d_un.d_val |= (Elf64_Xword)flval; 119 120 if (gelf_update_dyn(data, i, &dyn) == 0) 121 elfdie("gelf_update_dyn"); 122 123 break; 124 } 125 } 126 127 if (i == nent) { 128 die("%s's .dynamic section doesn't have a DT_FLAGS_1 " 129 "field\n", ifile); 130 } 131 132 if (elf_update(elf, ELF_C_WRITE) == -1) 133 elfdie("Couldn't update %s with changes", ifile); 134 135 (void) elf_end(elf); 136 (void) close(fd); 137 } 138 139 static ulong_t 140 parse_flag(char *optarg) 141 { 142 ulong_t flval = 0L; 143 char *arg; 144 int i; 145 146 for (arg = strtok(optarg, ","); arg != NULL; arg = strtok(NULL, ",")) { 147 for (i = 0; dtflagvals[i].fv_name != NULL; i++) { 148 if (strcmp(dtflagvals[i].fv_name, arg) == 0) 149 flval |= dtflagvals[i].fv_val; 150 } 151 } 152 153 return (flval); 154 } 155 156 int 157 main(int argc, char **argv) 158 { 159 ulong_t flval = 0L; 160 int c; 161 162 progname = basename(argv[0]); 163 164 while ((c = getopt(argc, argv, "f:")) != EOF) { 165 switch (c) { 166 case 'f': 167 if ((flval = strtoul(optarg, NULL, 0)) == 0 && 168 (flval = parse_flag(optarg)) == 0) 169 usage(); 170 break; 171 default: 172 usage(); 173 } 174 } 175 176 if (flval == 0 || argc - optind != 1) 177 usage(); 178 179 set_flag(argv[optind], flval); 180 181 return (0); 182 } 183