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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Set bits in the DT_FLAGS_1 member of the .dynamic section of an object. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <stdarg.h> 36 #include <errno.h> 37 #include <libelf.h> 38 #include <gelf.h> 39 #include <string.h> 40 #include <fcntl.h> 41 #include <libgen.h> 42 #include <unistd.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <sys/link.h> 46 47 #include <util.h> 48 49 /* 50 * These are here because we can't be sure (yet) that the build machine has a 51 * sys/link.h that includes the following #defines. This tool will be executed 52 * on the build machine, so we have to use its headers (rather than the ones 53 * in $ROOT which will, by definition, be up to date). These #defines can be 54 * removed when we're sure that all build machines have recent copies of 55 * sys/link.h. 56 */ 57 #ifndef DF_1_IGNMULDEF 58 #define DF_1_IGNMULDEF 0x00040000 59 #endif 60 #ifndef DF_1_NOKSYMS 61 #define DF_1_NOKSYMS 0x00080000 62 #endif 63 64 struct dtflagval { 65 char *fv_name; 66 ulong_t fv_val; 67 }; 68 69 static struct dtflagval dtflagvals[] = { 70 { "DF_1_IGNMULDEF", DF_1_IGNMULDEF }, 71 { "DF_1_NOKSYMS", DF_1_NOKSYMS }, 72 { NULL } 73 }; 74 75 const char *progname; 76 77 static void 78 usage(void) 79 { 80 (void) fprintf(stderr, "Usage: %s -f flag_val file\n", progname); 81 exit(2); 82 } 83 84 static void 85 set_flag(char *ifile, ulong_t flval) 86 { 87 Elf *elf; 88 Elf_Scn *scn; 89 Elf_Data *data; 90 GElf_Shdr shdr; 91 GElf_Dyn dyn; 92 int fd, secidx, nent, i; 93 94 (void) elf_version(EV_CURRENT); 95 96 if ((fd = open(ifile, O_RDWR)) < 0) 97 die("Can't open %s", ifile); 98 99 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) 100 elfdie("Can't start ELF for %s", ifile); 101 102 if ((secidx = findelfsecidx(elf, ".dynamic")) == -1) 103 die("Can't find .dynamic section in %s\n", ifile); 104 105 if ((scn = elf_getscn(elf, secidx)) == NULL) 106 elfdie("elf_getscn (%d)", secidx); 107 108 if (gelf_getshdr(scn, &shdr) == NULL) 109 elfdie("gelf_shdr"); 110 111 if ((data = elf_getdata(scn, NULL)) == NULL) 112 elfdie("elf_getdata"); 113 114 nent = shdr.sh_size / shdr.sh_entsize; 115 for (i = 0; i < nent; i++) { 116 if (gelf_getdyn(data, i, &dyn) == NULL) 117 elfdie("gelf_getdyn"); 118 119 if (dyn.d_tag == DT_FLAGS_1) { 120 dyn.d_un.d_val |= (Elf64_Xword)flval; 121 122 if (gelf_update_dyn(data, i, &dyn) == 0) 123 elfdie("gelf_update_dyn"); 124 125 break; 126 } 127 } 128 129 if (i == nent) { 130 die("%s's .dynamic section doesn't have a DT_FLAGS_1 " 131 "field\n", ifile); 132 } 133 134 if (elf_update(elf, ELF_C_WRITE) == -1) 135 elfdie("Couldn't update %s with changes", ifile); 136 137 (void) elf_end(elf); 138 (void) close(fd); 139 } 140 141 static ulong_t 142 parse_flag(char *optarg) 143 { 144 ulong_t flval = 0L; 145 char *arg; 146 int i; 147 148 for (arg = strtok(optarg, ","); arg != NULL; arg = strtok(NULL, ",")) { 149 for (i = 0; dtflagvals[i].fv_name != NULL; i++) { 150 if (strcmp(dtflagvals[i].fv_name, arg) == 0) 151 flval |= dtflagvals[i].fv_val; 152 } 153 } 154 155 return (flval); 156 } 157 158 int 159 main(int argc, char **argv) 160 { 161 ulong_t flval = 0L; 162 int c; 163 164 progname = basename(argv[0]); 165 166 while ((c = getopt(argc, argv, "f:")) != EOF) { 167 switch (c) { 168 case 'f': 169 if ((flval = strtoul(optarg, NULL, 0)) == 0 && 170 (flval = parse_flag(optarg)) == 0) 171 usage(); 172 break; 173 default: 174 usage(); 175 } 176 } 177 178 if (flval == 0 || argc - optind != 1) 179 usage(); 180 181 set_flag(argv[optind], flval); 182 183 return (0); 184 } 185