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 64struct dtflagval { 65 char *fv_name; 66 ulong_t fv_val; 67}; 68 69static struct dtflagval dtflagvals[] = { 70 { "DF_1_IGNMULDEF", DF_1_IGNMULDEF }, 71 { "DF_1_NOKSYMS", DF_1_NOKSYMS }, 72 { NULL } 73}; 74 75const char *progname; 76 77static void 78usage(void) 79{ 80 (void) fprintf(stderr, "Usage: %s -f flag_val file\n", progname); 81 exit(2); 82} 83 84static void 85set_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 141static ulong_t 142parse_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 158int 159main(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