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
usage(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
set_flag(char * ifile,ulong_t flval)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
parse_flag(char * optarg)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
main(int argc,char ** argv)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