1*d29b2c44Sab196087 /* 2*d29b2c44Sab196087 * CDDL HEADER START 3*d29b2c44Sab196087 * 4*d29b2c44Sab196087 * The contents of this file are subject to the terms of the 5*d29b2c44Sab196087 * Common Development and Distribution License (the "License"). 6*d29b2c44Sab196087 * You may not use this file except in compliance with the License. 7*d29b2c44Sab196087 * 8*d29b2c44Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d29b2c44Sab196087 * or http://www.opensolaris.org/os/licensing. 10*d29b2c44Sab196087 * See the License for the specific language governing permissions 11*d29b2c44Sab196087 * and limitations under the License. 12*d29b2c44Sab196087 * 13*d29b2c44Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 14*d29b2c44Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d29b2c44Sab196087 * If applicable, add the following below this CDDL HEADER, with the 16*d29b2c44Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 17*d29b2c44Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 18*d29b2c44Sab196087 * 19*d29b2c44Sab196087 * CDDL HEADER END 20*d29b2c44Sab196087 */ 21*d29b2c44Sab196087 22*d29b2c44Sab196087 /* 23*d29b2c44Sab196087 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*d29b2c44Sab196087 * Use is subject to license terms. 25*d29b2c44Sab196087 */ 26*d29b2c44Sab196087 #pragma ident "%Z%%M% %I% %E% SMI" 27*d29b2c44Sab196087 28*d29b2c44Sab196087 #include <stdlib.h> 29*d29b2c44Sab196087 #include <stdio.h> 30*d29b2c44Sab196087 #include <unistd.h> 31*d29b2c44Sab196087 #include <libintl.h> 32*d29b2c44Sab196087 #include <libelf.h> 33*d29b2c44Sab196087 #include <sys/machelf.h> 34*d29b2c44Sab196087 #include <link.h> 35*d29b2c44Sab196087 #include <strings.h> 36*d29b2c44Sab196087 #include <ctype.h> 37*d29b2c44Sab196087 #include <elfedit.h> 38*d29b2c44Sab196087 #include <_elfedit.h> 39*d29b2c44Sab196087 #include <sys/elf_SPARC.h> 40*d29b2c44Sab196087 #include <sys/elf_amd64.h> 41*d29b2c44Sab196087 #include <msg.h> 42*d29b2c44Sab196087 43*d29b2c44Sab196087 44*d29b2c44Sab196087 45*d29b2c44Sab196087 /* 46*d29b2c44Sab196087 * This file contains utility functions that are of general use 47*d29b2c44Sab196087 * to different elfedit modules for solving common problems. 48*d29b2c44Sab196087 * The functions in this file are not ELFCLASS specific. Those 49*d29b2c44Sab196087 * functions are found in util_machelf.c 50*d29b2c44Sab196087 * 51*d29b2c44Sab196087 * NOTE: This module contains functions with names 52*d29b2c44Sab196087 * elfedit_atoi, and elfedit_atoui, that are otherwise identical. 53*d29b2c44Sab196087 * These functions are for signed, and unsigned integers, respectively. 54*d29b2c44Sab196087 * In general, I supply one comment header for each such pair, 55*d29b2c44Sab196087 * and put their implementations together. 56*d29b2c44Sab196087 * 57*d29b2c44Sab196087 * There are also functions with names elfedit_atoconst. These are 58*d29b2c44Sab196087 * convenience wrappers that use the corresponding elfedit_atoui() 59*d29b2c44Sab196087 * function to process an array of symbolic names provided by a call 60*d29b2c44Sab196087 * elfedit_const_to_atoui(). 61*d29b2c44Sab196087 */ 62*d29b2c44Sab196087 63*d29b2c44Sab196087 64*d29b2c44Sab196087 65*d29b2c44Sab196087 66*d29b2c44Sab196087 /* 67*d29b2c44Sab196087 * Given a value and an array of elfedit_ato[u]i items, return a pointer 68*d29b2c44Sab196087 * to the symbolic name for the value. 69*d29b2c44Sab196087 * 70*d29b2c44Sab196087 * entry: 71*d29b2c44Sab196087 * sym - NULL terminated array of name->value mappings. 72*d29b2c44Sab196087 * value - Value to be found 73*d29b2c44Sab196087 * required - If True, and value is not found, an error is issued. 74*d29b2c44Sab196087 * Callers should only set required to True when they know 75*d29b2c44Sab196087 * a priori that the value will be found --- the error 76*d29b2c44Sab196087 * is reported as an internal programming error. 77*d29b2c44Sab196087 * 78*d29b2c44Sab196087 * exit: 79*d29b2c44Sab196087 * If the array contains an entry with the given value, the 80*d29b2c44Sab196087 * name for the first such entry will be returned. 81*d29b2c44Sab196087 * 82*d29b2c44Sab196087 * If no entry is found: If required is True (1), an error is 83*d29b2c44Sab196087 * issued and this routine does not return to the caller. If required 84*d29b2c44Sab196087 * is False (0), then NULL is returned. 85*d29b2c44Sab196087 */ 86*d29b2c44Sab196087 const char * 87*d29b2c44Sab196087 elfedit_atoi_value_to_str(const elfedit_atoi_sym_t *sym, elfedit_atoi_t value, 88*d29b2c44Sab196087 int required) 89*d29b2c44Sab196087 { 90*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) 91*d29b2c44Sab196087 if (value == sym->sym_value) 92*d29b2c44Sab196087 return (sym->sym_name); 93*d29b2c44Sab196087 94*d29b2c44Sab196087 /* Value did not match any of the entries */ 95*d29b2c44Sab196087 if (required) 96*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADGETVAL)); 97*d29b2c44Sab196087 return (NULL); 98*d29b2c44Sab196087 } 99*d29b2c44Sab196087 const char * 100*d29b2c44Sab196087 elfedit_atoui_value_to_str(const elfedit_atoui_sym_t *sym, 101*d29b2c44Sab196087 elfedit_atoui_t value, int required) 102*d29b2c44Sab196087 { 103*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) 104*d29b2c44Sab196087 if (value == sym->sym_value) 105*d29b2c44Sab196087 return (sym->sym_name); 106*d29b2c44Sab196087 107*d29b2c44Sab196087 /* Value did not match any of the entries */ 108*d29b2c44Sab196087 if (required) 109*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADGETVAL)); 110*d29b2c44Sab196087 return (NULL); 111*d29b2c44Sab196087 } 112*d29b2c44Sab196087 const char * 113*d29b2c44Sab196087 elfedit_atoconst_value_to_str(elfedit_const_t const_type, elfedit_atoui_t value, 114*d29b2c44Sab196087 int required) 115*d29b2c44Sab196087 { 116*d29b2c44Sab196087 return (elfedit_atoui_value_to_str(elfedit_const_to_atoui(const_type), 117*d29b2c44Sab196087 value, required)); 118*d29b2c44Sab196087 } 119*d29b2c44Sab196087 120*d29b2c44Sab196087 121*d29b2c44Sab196087 /* 122*d29b2c44Sab196087 * Process the symbolic name to value mappings passed to the 123*d29b2c44Sab196087 * atoi and atoui functions. 124*d29b2c44Sab196087 * 125*d29b2c44Sab196087 * entry: 126*d29b2c44Sab196087 * sym - NULL terminated array of name->value mappings. 127*d29b2c44Sab196087 * value - Address of variable to recieve corresponding value. 128*d29b2c44Sab196087 * 129*d29b2c44Sab196087 * exit: 130*d29b2c44Sab196087 * If a mapping is found, *value is set to it, and True is returned. 131*d29b2c44Sab196087 * Otherwise False is returned. 132*d29b2c44Sab196087 */ 133*d29b2c44Sab196087 static int 134*d29b2c44Sab196087 atoi_sym_process(const char *str, const elfedit_atoi_sym_t *sym, 135*d29b2c44Sab196087 elfedit_atoi_t *value) 136*d29b2c44Sab196087 { 137*d29b2c44Sab196087 size_t cmp_len; 138*d29b2c44Sab196087 const char *tail; 139*d29b2c44Sab196087 140*d29b2c44Sab196087 while (isspace(*str)) 141*d29b2c44Sab196087 str++; 142*d29b2c44Sab196087 143*d29b2c44Sab196087 tail = str + strlen(str); 144*d29b2c44Sab196087 while ((tail > str) && isspace(*(tail - 1))) 145*d29b2c44Sab196087 tail--; 146*d29b2c44Sab196087 147*d29b2c44Sab196087 cmp_len = tail - str; 148*d29b2c44Sab196087 149*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) { 150*d29b2c44Sab196087 if ((strlen(sym->sym_name) == cmp_len) && 151*d29b2c44Sab196087 (strncasecmp(sym->sym_name, str, cmp_len) == 0)) { 152*d29b2c44Sab196087 *value = sym->sym_value; 153*d29b2c44Sab196087 return (1); 154*d29b2c44Sab196087 } 155*d29b2c44Sab196087 } 156*d29b2c44Sab196087 157*d29b2c44Sab196087 /* No symbolic mapping was found */ 158*d29b2c44Sab196087 return (0); 159*d29b2c44Sab196087 } 160*d29b2c44Sab196087 static int 161*d29b2c44Sab196087 atoui_sym_process(const char *str, const elfedit_atoui_sym_t *sym, 162*d29b2c44Sab196087 elfedit_atoui_t *value) 163*d29b2c44Sab196087 { 164*d29b2c44Sab196087 size_t cmp_len; 165*d29b2c44Sab196087 const char *tail; 166*d29b2c44Sab196087 167*d29b2c44Sab196087 while (isspace(*str)) 168*d29b2c44Sab196087 str++; 169*d29b2c44Sab196087 170*d29b2c44Sab196087 tail = str + strlen(str); 171*d29b2c44Sab196087 while ((tail > str) && isspace(*(tail - 1))) 172*d29b2c44Sab196087 tail--; 173*d29b2c44Sab196087 174*d29b2c44Sab196087 cmp_len = tail - str; 175*d29b2c44Sab196087 176*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) { 177*d29b2c44Sab196087 if ((strlen(sym->sym_name) == cmp_len) && 178*d29b2c44Sab196087 (strncasecmp(sym->sym_name, str, cmp_len) == 0)) { 179*d29b2c44Sab196087 *value = sym->sym_value; 180*d29b2c44Sab196087 return (1); 181*d29b2c44Sab196087 } 182*d29b2c44Sab196087 } 183*d29b2c44Sab196087 184*d29b2c44Sab196087 /* No symbolic mapping was found */ 185*d29b2c44Sab196087 return (0); 186*d29b2c44Sab196087 } 187*d29b2c44Sab196087 188*d29b2c44Sab196087 189*d29b2c44Sab196087 190*d29b2c44Sab196087 /* 191*d29b2c44Sab196087 * A command completion function for atoi and atoui mappings. 192*d29b2c44Sab196087 */ 193*d29b2c44Sab196087 void 194*d29b2c44Sab196087 elfedit_cpl_atoi(void *cpldata, const elfedit_atoi_sym_t *sym) 195*d29b2c44Sab196087 { 196*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) 197*d29b2c44Sab196087 elfedit_cpl_match(cpldata, sym->sym_name, 1); 198*d29b2c44Sab196087 } 199*d29b2c44Sab196087 void 200*d29b2c44Sab196087 elfedit_cpl_atoui(void *cpldata, const elfedit_atoui_sym_t *sym) 201*d29b2c44Sab196087 { 202*d29b2c44Sab196087 for (; sym->sym_name != NULL; sym++) 203*d29b2c44Sab196087 elfedit_cpl_match(cpldata, sym->sym_name, 1); 204*d29b2c44Sab196087 } 205*d29b2c44Sab196087 void 206*d29b2c44Sab196087 elfedit_cpl_atoconst(void *cpldata, elfedit_const_t const_type) 207*d29b2c44Sab196087 { 208*d29b2c44Sab196087 elfedit_cpl_atoui(cpldata, elfedit_const_to_atoui(const_type)); 209*d29b2c44Sab196087 } 210*d29b2c44Sab196087 211*d29b2c44Sab196087 212*d29b2c44Sab196087 213*d29b2c44Sab196087 214*d29b2c44Sab196087 215*d29b2c44Sab196087 /* 216*d29b2c44Sab196087 * Convert a string to a numeric value. Strings starting with '0' 217*d29b2c44Sab196087 * are taken to be octal, those staring with '0x' are hex, and all 218*d29b2c44Sab196087 * others are decimal. 219*d29b2c44Sab196087 * 220*d29b2c44Sab196087 * entry: 221*d29b2c44Sab196087 * str - String to be converted 222*d29b2c44Sab196087 * sym - NULL, or NULL terminated array of name/value pairs. 223*d29b2c44Sab196087 * 224*d29b2c44Sab196087 * [elfedit_atoi2() and elfedit_atoui2() only] 225*d29b2c44Sab196087 * v - Address of variable to receive resulting value. 226*d29b2c44Sab196087 * 227*d29b2c44Sab196087 * exit: 228*d29b2c44Sab196087 * elfedit_atoi2() and elfedit_atoui2(): 229*d29b2c44Sab196087 * On success, returns True (1) and *v is set to the value. 230*d29b2c44Sab196087 * On failure, returns False (0) and *v is undefined. 231*d29b2c44Sab196087 * 232*d29b2c44Sab196087 * elfedit_atoi() and elfedit_atoui(): 233*d29b2c44Sab196087 * If the string is convertable, the value is returned. 234*d29b2c44Sab196087 * Otherwise an error is issued and this routine does 235*d29b2c44Sab196087 * not return to the caller. 236*d29b2c44Sab196087 */ 237*d29b2c44Sab196087 int 238*d29b2c44Sab196087 elfedit_atoi2(const char *str, const elfedit_atoi_sym_t *sym, elfedit_atoi_t *v) 239*d29b2c44Sab196087 { 240*d29b2c44Sab196087 char *endptr; 241*d29b2c44Sab196087 242*d29b2c44Sab196087 if (sym && atoi_sym_process(str, sym, v)) 243*d29b2c44Sab196087 return (1); 244*d29b2c44Sab196087 245*d29b2c44Sab196087 *v = strtoll(str, &endptr, 0); 246*d29b2c44Sab196087 247*d29b2c44Sab196087 /* If the left over part contains anything but whitespace, fail */ 248*d29b2c44Sab196087 for (; *endptr; endptr++) 249*d29b2c44Sab196087 if (!isspace(*endptr)) 250*d29b2c44Sab196087 return (0); 251*d29b2c44Sab196087 return (1); 252*d29b2c44Sab196087 } 253*d29b2c44Sab196087 elfedit_atoi_t 254*d29b2c44Sab196087 elfedit_atoi(const char *str, const elfedit_atoi_sym_t *sym) 255*d29b2c44Sab196087 { 256*d29b2c44Sab196087 elfedit_atoi_t v; 257*d29b2c44Sab196087 if (elfedit_atoi2(str, sym, &v) == 0) 258*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 259*d29b2c44Sab196087 MSG_INTL(MSG_ERR_BADATOISTR), str); 260*d29b2c44Sab196087 return (v); 261*d29b2c44Sab196087 } 262*d29b2c44Sab196087 int 263*d29b2c44Sab196087 elfedit_atoui2(const char *str, const elfedit_atoui_sym_t *sym, 264*d29b2c44Sab196087 elfedit_atoui_t *v) 265*d29b2c44Sab196087 { 266*d29b2c44Sab196087 char *endptr; 267*d29b2c44Sab196087 268*d29b2c44Sab196087 if (sym && atoui_sym_process(str, sym, v)) 269*d29b2c44Sab196087 return (1); 270*d29b2c44Sab196087 271*d29b2c44Sab196087 *v = strtoull(str, &endptr, 0); 272*d29b2c44Sab196087 273*d29b2c44Sab196087 /* If the left over part contains anything but whitespace, fail */ 274*d29b2c44Sab196087 for (; *endptr; endptr++) 275*d29b2c44Sab196087 if (!isspace(*endptr)) 276*d29b2c44Sab196087 return (0); 277*d29b2c44Sab196087 return (1); 278*d29b2c44Sab196087 } 279*d29b2c44Sab196087 elfedit_atoui_t 280*d29b2c44Sab196087 elfedit_atoui(const char *str, const elfedit_atoui_sym_t *sym) 281*d29b2c44Sab196087 { 282*d29b2c44Sab196087 elfedit_atoui_t v; 283*d29b2c44Sab196087 if (elfedit_atoui2(str, sym, &v) == 0) 284*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 285*d29b2c44Sab196087 MSG_INTL(MSG_ERR_BADATOISTR), str); 286*d29b2c44Sab196087 return (v); 287*d29b2c44Sab196087 } 288*d29b2c44Sab196087 int 289*d29b2c44Sab196087 elfedit_atoconst2(const char *str, elfedit_const_t const_type, 290*d29b2c44Sab196087 elfedit_atoui_t *v) 291*d29b2c44Sab196087 { 292*d29b2c44Sab196087 return (elfedit_atoui2(str, elfedit_const_to_atoui(const_type), v)); 293*d29b2c44Sab196087 } 294*d29b2c44Sab196087 elfedit_atoui_t 295*d29b2c44Sab196087 elfedit_atoconst(const char *str, elfedit_const_t const_type) 296*d29b2c44Sab196087 { 297*d29b2c44Sab196087 return (elfedit_atoui(str, elfedit_const_to_atoui(const_type))); 298*d29b2c44Sab196087 } 299*d29b2c44Sab196087 300*d29b2c44Sab196087 /* 301*d29b2c44Sab196087 * Convert a string to a numeric value using elfedit_ato[u]i and 302*d29b2c44Sab196087 * ensure that the resulting value lies within a given range. 303*d29b2c44Sab196087 * elfedit_ato[u]i_range() requires values to be in the range 304*d29b2c44Sab196087 * (min <= value <= max). 305*d29b2c44Sab196087 * 306*d29b2c44Sab196087 * entry: 307*d29b2c44Sab196087 * str - String to be converted 308*d29b2c44Sab196087 * min, max - If check_range is true, the allowed range that the 309*d29b2c44Sab196087 * resulting value must lie in. 310*d29b2c44Sab196087 * sym - NULL, or NULL terminated array of name/value pairs. 311*d29b2c44Sab196087 * 312*d29b2c44Sab196087 * entry [elfedit_atoi_range() and elfedit_atoui_range() only]: 313*d29b2c44Sab196087 * item_name - String describing item for which value is being read. 314*d29b2c44Sab196087 * 315*d29b2c44Sab196087 * entry [elfedit_atoi_range2() and elfedit_atoui_range2() only]: 316*d29b2c44Sab196087 * v - Address of variable to receive resulting value. 317*d29b2c44Sab196087 * 318*d29b2c44Sab196087 * exit: 319*d29b2c44Sab196087 * elfedit_atoi_range2() and elfedit_atoui_range2(): 320*d29b2c44Sab196087 * On success, returns True (1) and *v is set to the value. 321*d29b2c44Sab196087 * On failure, returns False (0) and *v is undefined. 322*d29b2c44Sab196087 * 323*d29b2c44Sab196087 * elfedit_atoi_range() and elfedit_atoui_range(): 324*d29b2c44Sab196087 * If the string is convertable, the value is returned. 325*d29b2c44Sab196087 * Otherwise an error is issued and this routine does 326*d29b2c44Sab196087 * not return to the caller. 327*d29b2c44Sab196087 */ 328*d29b2c44Sab196087 int 329*d29b2c44Sab196087 elfedit_atoi_range2(const char *str, elfedit_atoi_t min, elfedit_atoi_t max, 330*d29b2c44Sab196087 const elfedit_atoi_sym_t *sym, elfedit_atoi_t *v) 331*d29b2c44Sab196087 { 332*d29b2c44Sab196087 return ((elfedit_atoi2(str, sym, v) != 0) && 333*d29b2c44Sab196087 (*v >= min) && (*v <= max)); 334*d29b2c44Sab196087 } 335*d29b2c44Sab196087 elfedit_atoi_t 336*d29b2c44Sab196087 elfedit_atoi_range(const char *str, const char *item_name, 337*d29b2c44Sab196087 elfedit_atoi_t min, elfedit_atoi_t max, const elfedit_atoi_sym_t *sym) 338*d29b2c44Sab196087 { 339*d29b2c44Sab196087 elfedit_atoi_t v = elfedit_atoi(str, sym); 340*d29b2c44Sab196087 341*d29b2c44Sab196087 if ((v < min) || (v > max)) 342*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_ATOIRANGE), 343*d29b2c44Sab196087 item_name, EC_XWORD(min), EC_XWORD(max), EC_XWORD(v)); 344*d29b2c44Sab196087 345*d29b2c44Sab196087 return (v); 346*d29b2c44Sab196087 } 347*d29b2c44Sab196087 int 348*d29b2c44Sab196087 elfedit_atoui_range2(const char *str, elfedit_atoui_t min, elfedit_atoui_t max, 349*d29b2c44Sab196087 const elfedit_atoui_sym_t *sym, elfedit_atoui_t *v) 350*d29b2c44Sab196087 { 351*d29b2c44Sab196087 return ((elfedit_atoui2(str, sym, v) != 0) && 352*d29b2c44Sab196087 (*v >= min) && (*v <= max)); 353*d29b2c44Sab196087 } 354*d29b2c44Sab196087 elfedit_atoui_t 355*d29b2c44Sab196087 elfedit_atoui_range(const char *str, const char *item_name, 356*d29b2c44Sab196087 elfedit_atoui_t min, elfedit_atoui_t max, const elfedit_atoui_sym_t *sym) 357*d29b2c44Sab196087 { 358*d29b2c44Sab196087 elfedit_atoui_t v = elfedit_atoui(str, sym); 359*d29b2c44Sab196087 360*d29b2c44Sab196087 if ((v < min) || (v > max)) 361*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_ATOUIRANGE), 362*d29b2c44Sab196087 item_name, EC_XWORD(min), EC_XWORD(max), EC_XWORD(v)); 363*d29b2c44Sab196087 364*d29b2c44Sab196087 return (v); 365*d29b2c44Sab196087 } 366*d29b2c44Sab196087 int 367*d29b2c44Sab196087 elfedit_atoconst_range2(const char *str, elfedit_atoui_t min, 368*d29b2c44Sab196087 elfedit_atoui_t max, elfedit_const_t const_type, elfedit_atoui_t *v) 369*d29b2c44Sab196087 { 370*d29b2c44Sab196087 return (elfedit_atoui_range2(str, min, max, 371*d29b2c44Sab196087 elfedit_const_to_atoui(const_type), v)); 372*d29b2c44Sab196087 } 373*d29b2c44Sab196087 elfedit_atoui_t 374*d29b2c44Sab196087 elfedit_atoconst_range(const char *str, const char *item_name, 375*d29b2c44Sab196087 elfedit_atoui_t min, elfedit_atoui_t max, elfedit_const_t const_type) 376*d29b2c44Sab196087 { 377*d29b2c44Sab196087 return (elfedit_atoui_range(str, item_name, min, max, 378*d29b2c44Sab196087 elfedit_const_to_atoui(const_type))); 379*d29b2c44Sab196087 } 380*d29b2c44Sab196087 381*d29b2c44Sab196087 382*d29b2c44Sab196087 /* 383*d29b2c44Sab196087 * Convenience wrapper on elfedit_atoui_range() that expects to see 384*d29b2c44Sab196087 * boolean values. Returns 1 for true, and 0 for false. 385*d29b2c44Sab196087 */ 386*d29b2c44Sab196087 int 387*d29b2c44Sab196087 elfedit_atobool(const char *str, const char *item_name) 388*d29b2c44Sab196087 { 389*d29b2c44Sab196087 390*d29b2c44Sab196087 return (elfedit_atoconst_range(str, item_name, 0, 1, 391*d29b2c44Sab196087 ELFEDIT_CONST_BOOL) != 0); 392*d29b2c44Sab196087 } 393*d29b2c44Sab196087 394*d29b2c44Sab196087 395*d29b2c44Sab196087 396*d29b2c44Sab196087 /* 397*d29b2c44Sab196087 * Convenience wrapper on elfedit_atoui() to read a section index 398*d29b2c44Sab196087 * that understands the special SHN_ names. 399*d29b2c44Sab196087 * 400*d29b2c44Sab196087 * entry: 401*d29b2c44Sab196087 * str - String to process 402*d29b2c44Sab196087 * shnum - Number of sections in the ELF file 403*d29b2c44Sab196087 * 404*d29b2c44Sab196087 * exit: 405*d29b2c44Sab196087 * If it is possible to convert str to a number, that value 406*d29b2c44Sab196087 * is returned. If the value is out of range for the file, 407*d29b2c44Sab196087 * a warning message to that effect is issued. On failure, 408*d29b2c44Sab196087 * an error is issued and this routine does not return to 409*d29b2c44Sab196087 * the caller. 410*d29b2c44Sab196087 */ 411*d29b2c44Sab196087 elfedit_atoui_t 412*d29b2c44Sab196087 elfedit_atoshndx(const char *str, size_t shnum) 413*d29b2c44Sab196087 { 414*d29b2c44Sab196087 elfedit_atoui_t ndx; 415*d29b2c44Sab196087 416*d29b2c44Sab196087 ndx = elfedit_atoconst(str, ELFEDIT_CONST_SHN); 417*d29b2c44Sab196087 if ((ndx >= shnum) && ((ndx < SHN_LORESERVE) || (ndx > SHN_HIRESERVE))) 418*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_SHNDX_RANGE), 419*d29b2c44Sab196087 EC_WORD(ndx), EC_WORD(shnum-1)); 420*d29b2c44Sab196087 421*d29b2c44Sab196087 return (ndx); 422*d29b2c44Sab196087 } 423*d29b2c44Sab196087 424*d29b2c44Sab196087 425*d29b2c44Sab196087 426*d29b2c44Sab196087 /* 427*d29b2c44Sab196087 * Convert an output style string into it's integer constant. This 428*d29b2c44Sab196087 * routine reports success/failure via the return value rather than 429*d29b2c44Sab196087 * by throwing errors so that it can be used to process command 430*d29b2c44Sab196087 * line options at program startup, before 431*d29b2c44Sab196087 * the elfedit framework is initialized. 432*d29b2c44Sab196087 */ 433*d29b2c44Sab196087 int 434*d29b2c44Sab196087 elfedit_atooutstyle(const char *str, elfedit_outstyle_t *outstyle) 435*d29b2c44Sab196087 { 436*d29b2c44Sab196087 int ret; 437*d29b2c44Sab196087 elfedit_atoui_t value; 438*d29b2c44Sab196087 439*d29b2c44Sab196087 ret = atoui_sym_process(str, 440*d29b2c44Sab196087 elfedit_const_to_atoui(ELFEDIT_CONST_OUTSTYLE), &value); 441*d29b2c44Sab196087 if (ret != 0) 442*d29b2c44Sab196087 *outstyle = value; 443*d29b2c44Sab196087 return (ret); 444*d29b2c44Sab196087 } 445*d29b2c44Sab196087 446*d29b2c44Sab196087 447*d29b2c44Sab196087 448*d29b2c44Sab196087 449*d29b2c44Sab196087 /* 450*d29b2c44Sab196087 * Initialize a state block for processing by elfedit_getopt(). 451*d29b2c44Sab196087 * 452*d29b2c44Sab196087 * entry: 453*d29b2c44Sab196087 * state - State block to initialize 454*d29b2c44Sab196087 * cmd_name - NULL, or name of command for which we are processing 455*d29b2c44Sab196087 * options. 456*d29b2c44Sab196087 * argc, argv - Address of variables giving number of options and 457*d29b2c44Sab196087 * access to the option strings. 458*d29b2c44Sab196087 * 459*d29b2c44Sab196087 * note: 460*d29b2c44Sab196087 * cmd_name can only be set to NULL when this routine is called 461*d29b2c44Sab196087 * by, or below, a currently active command. Otherwise, results 462*d29b2c44Sab196087 * are undefined (crashing or corruption) if there isn't one. 463*d29b2c44Sab196087 */ 464*d29b2c44Sab196087 void 465*d29b2c44Sab196087 elfedit_getopt_init(elfedit_getopt_state_t *state, 466*d29b2c44Sab196087 int *argc, const char **argv[]) 467*d29b2c44Sab196087 { 468*d29b2c44Sab196087 elfeditGC_cmd_t *cmd = elfedit_curcmd(); 469*d29b2c44Sab196087 470*d29b2c44Sab196087 state->go_argc = argc; 471*d29b2c44Sab196087 state->go_argv = argv; 472*d29b2c44Sab196087 state->go_optarg = cmd->cmd_opt; 473*d29b2c44Sab196087 state->go_idmask = 0; 474*d29b2c44Sab196087 state->go_done = 0; 475*d29b2c44Sab196087 state->go_sglgrp = NULL; 476*d29b2c44Sab196087 } 477*d29b2c44Sab196087 478*d29b2c44Sab196087 479*d29b2c44Sab196087 480*d29b2c44Sab196087 /* 481*d29b2c44Sab196087 * elfedit-centric version of getopt() 482*d29b2c44Sab196087 * 483*d29b2c44Sab196087 * entry: 484*d29b2c44Sab196087 * state - Getopt state, which must have been previously initialized 485*d29b2c44Sab196087 * via a call to elfedit_getopt_init. 486*d29b2c44Sab196087 * 487*d29b2c44Sab196087 * exit: 488*d29b2c44Sab196087 * If an option is matched, this routine returns a pointer to an 489*d29b2c44Sab196087 * elfedit_getopt_ret_t buffer (which comes from the storage used 490*d29b2c44Sab196087 * for state). If there are no more options to process, NULL is returned. 491*d29b2c44Sab196087 * 492*d29b2c44Sab196087 * Syntax errors are reported via elfedit_command_usage(), and this 493*d29b2c44Sab196087 * routine does not return to the caller. 494*d29b2c44Sab196087 * 495*d29b2c44Sab196087 * note: 496*d29b2c44Sab196087 * - The caller should not access the contents of state directly. 497*d29b2c44Sab196087 * Those contents are private, and subject to change. 498*d29b2c44Sab196087 * - Once a call to this routine returns NULL, the argc/argv have 499*d29b2c44Sab196087 * have been ajusted so that they reference the plain arguments. 500*d29b2c44Sab196087 */ 501*d29b2c44Sab196087 elfedit_getopt_ret_t * 502*d29b2c44Sab196087 elfedit_getopt(elfedit_getopt_state_t *state) 503*d29b2c44Sab196087 { 504*d29b2c44Sab196087 elfedit_cmd_optarg_t *optarg; 505*d29b2c44Sab196087 const char *argstr; 506*d29b2c44Sab196087 int argc = *(state->go_argc); 507*d29b2c44Sab196087 const char **argv = *(state->go_argv); 508*d29b2c44Sab196087 elfedit_optarg_item_t item; 509*d29b2c44Sab196087 struct { 510*d29b2c44Sab196087 int valid; 511*d29b2c44Sab196087 int is_outstyle; 512*d29b2c44Sab196087 elfedit_getopt_ret_t ret; 513*d29b2c44Sab196087 elfedit_cmd_oa_mask_t excmask; 514*d29b2c44Sab196087 } sgl_with_value; 515*d29b2c44Sab196087 516*d29b2c44Sab196087 if (state->go_sglgrp == NULL) { 517*d29b2c44Sab196087 /* 518*d29b2c44Sab196087 * Reasons to bail out immediately: 519*d29b2c44Sab196087 * - The command does not accept options 520*d29b2c44Sab196087 * - We've already reported the final option. 521*d29b2c44Sab196087 * - There are no more arguments. 522*d29b2c44Sab196087 * - The next argument does not start with '-' 523*d29b2c44Sab196087 */ 524*d29b2c44Sab196087 if ((state->go_optarg == NULL) || state->go_done || 525*d29b2c44Sab196087 (argc <= 0) || (*(argv[0]) != '-')) { 526*d29b2c44Sab196087 state->go_done = 1; 527*d29b2c44Sab196087 return (NULL); 528*d29b2c44Sab196087 } 529*d29b2c44Sab196087 530*d29b2c44Sab196087 argstr = argv[0]; 531*d29b2c44Sab196087 532*d29b2c44Sab196087 /* A '-' by itself is a syntax error */ 533*d29b2c44Sab196087 if (argstr[1] == '\0') 534*d29b2c44Sab196087 elfedit_command_usage(); 535*d29b2c44Sab196087 536*d29b2c44Sab196087 /* A '--' option means we should stop at this point */ 537*d29b2c44Sab196087 if ((argstr[1] == '-') && (argstr[2] == '\0')) { 538*d29b2c44Sab196087 (*state->go_argc)--; 539*d29b2c44Sab196087 (*state->go_argv)++; 540*d29b2c44Sab196087 return (NULL); 541*d29b2c44Sab196087 } 542*d29b2c44Sab196087 543*d29b2c44Sab196087 /* 544*d29b2c44Sab196087 * We have a string that starts with a '-'. 545*d29b2c44Sab196087 * Does it match an option? 546*d29b2c44Sab196087 */ 547*d29b2c44Sab196087 sgl_with_value.valid = 0; 548*d29b2c44Sab196087 for (optarg = state->go_optarg; optarg->oa_name != NULL; ) { 549*d29b2c44Sab196087 int is_outstyle = 550*d29b2c44Sab196087 (optarg->oa_flags & ELFEDIT_CMDOA_F_INHERIT) && 551*d29b2c44Sab196087 (optarg->oa_name == ELFEDIT_STDOA_OPT_O); 552*d29b2c44Sab196087 int need_value; 553*d29b2c44Sab196087 554*d29b2c44Sab196087 elfedit_next_optarg(&optarg, &item); 555*d29b2c44Sab196087 need_value = item.oai_flags & ELFEDIT_CMDOA_F_VALUE; 556*d29b2c44Sab196087 557*d29b2c44Sab196087 /* 558*d29b2c44Sab196087 * If the option is a single letter that accepts 559*d29b2c44Sab196087 * a value, then we allow the combined syntax 560*d29b2c44Sab196087 * -ovalue, where no space is reqired between the 561*d29b2c44Sab196087 * option flag and the value string. 562*d29b2c44Sab196087 */ 563*d29b2c44Sab196087 if ((item.oai_name[2] == '\0') && need_value && 564*d29b2c44Sab196087 (argstr[1] == item.oai_name[1]) && 565*d29b2c44Sab196087 (argstr[2] != '\0')) { 566*d29b2c44Sab196087 /* 567*d29b2c44Sab196087 * We have a match. However, there may also 568*d29b2c44Sab196087 * be a straightforward match that we have 569*d29b2c44Sab196087 * not yet found. If so, we want to prefer that 570*d29b2c44Sab196087 * case over this one. So rather than return 571*d29b2c44Sab196087 * it immediately, we capture the information 572*d29b2c44Sab196087 * and keep looking. If nothing else surfaces, 573*d29b2c44Sab196087 * we'll use this later. 574*d29b2c44Sab196087 */ 575*d29b2c44Sab196087 sgl_with_value.valid = 1; 576*d29b2c44Sab196087 sgl_with_value.ret.gor_idmask = item.oai_idmask; 577*d29b2c44Sab196087 sgl_with_value.excmask = item.oai_excmask; 578*d29b2c44Sab196087 sgl_with_value.ret.gor_value = argstr + 2; 579*d29b2c44Sab196087 sgl_with_value.is_outstyle = is_outstyle; 580*d29b2c44Sab196087 continue; 581*d29b2c44Sab196087 } 582*d29b2c44Sab196087 583*d29b2c44Sab196087 /* Try for a straightforward match */ 584*d29b2c44Sab196087 if (strcmp(argstr, item.oai_name) == 0) { 585*d29b2c44Sab196087 (*state->go_argc) = --argc; 586*d29b2c44Sab196087 (*state->go_argv) = ++argv; 587*d29b2c44Sab196087 588*d29b2c44Sab196087 /* Mutually exclusive option already seen? */ 589*d29b2c44Sab196087 if (item.oai_excmask & state->go_idmask) 590*d29b2c44Sab196087 elfedit_command_usage(); 591*d29b2c44Sab196087 592*d29b2c44Sab196087 /* Return the match */ 593*d29b2c44Sab196087 state->go_idmask |= item.oai_idmask; 594*d29b2c44Sab196087 state->go_ret.gor_idmask = item.oai_idmask; 595*d29b2c44Sab196087 if (need_value) { 596*d29b2c44Sab196087 /* If out of args, syntax error */ 597*d29b2c44Sab196087 if (argc <= 0) 598*d29b2c44Sab196087 elfedit_command_usage(); 599*d29b2c44Sab196087 state->go_ret.gor_value = argv[0]; 600*d29b2c44Sab196087 (*state->go_argc)--; 601*d29b2c44Sab196087 (*state->go_argv)++; 602*d29b2c44Sab196087 } else { 603*d29b2c44Sab196087 state->go_ret.gor_value = NULL; 604*d29b2c44Sab196087 } 605*d29b2c44Sab196087 if (is_outstyle) 606*d29b2c44Sab196087 elfedit_set_cmd_outstyle( 607*d29b2c44Sab196087 state->go_ret.gor_value); 608*d29b2c44Sab196087 return (&state->go_ret); 609*d29b2c44Sab196087 } 610*d29b2c44Sab196087 } 611*d29b2c44Sab196087 612*d29b2c44Sab196087 /* 613*d29b2c44Sab196087 * No straightforward matches: Did we get a match with 614*d29b2c44Sab196087 * the special single letter and combined value? If so 615*d29b2c44Sab196087 * return that now. 616*d29b2c44Sab196087 */ 617*d29b2c44Sab196087 if (sgl_with_value.valid) { 618*d29b2c44Sab196087 (*state->go_argc)--; 619*d29b2c44Sab196087 (*state->go_argv)++; 620*d29b2c44Sab196087 621*d29b2c44Sab196087 /* Mutually exclusive option already seen? */ 622*d29b2c44Sab196087 if (sgl_with_value.excmask & state->go_idmask) 623*d29b2c44Sab196087 elfedit_command_usage(); 624*d29b2c44Sab196087 625*d29b2c44Sab196087 state->go_idmask |= sgl_with_value.ret.gor_idmask; 626*d29b2c44Sab196087 state->go_ret = sgl_with_value.ret; 627*d29b2c44Sab196087 if (sgl_with_value.is_outstyle) 628*d29b2c44Sab196087 elfedit_set_cmd_outstyle( 629*d29b2c44Sab196087 state->go_ret.gor_value); 630*d29b2c44Sab196087 631*d29b2c44Sab196087 return (&state->go_ret); 632*d29b2c44Sab196087 } 633*d29b2c44Sab196087 634*d29b2c44Sab196087 /* 635*d29b2c44Sab196087 * If nothing above matched, make this option the single 636*d29b2c44Sab196087 * group string and see if the characters in it all match 637*d29b2c44Sab196087 * as single letter options without values. 638*d29b2c44Sab196087 */ 639*d29b2c44Sab196087 state->go_sglgrp = argstr + 1; /* Skip '-' */ 640*d29b2c44Sab196087 } 641*d29b2c44Sab196087 642*d29b2c44Sab196087 /* 643*d29b2c44Sab196087 * If there is a single group string, take the first character 644*d29b2c44Sab196087 * and try to match it to an 1-letter option that does not 645*d29b2c44Sab196087 * require a value. 646*d29b2c44Sab196087 */ 647*d29b2c44Sab196087 if (state->go_sglgrp != NULL) { 648*d29b2c44Sab196087 int ch = *state->go_sglgrp++; 649*d29b2c44Sab196087 650*d29b2c44Sab196087 /* If that is the last character, clear single group mode */ 651*d29b2c44Sab196087 if (*state->go_sglgrp == '\0') { 652*d29b2c44Sab196087 (*state->go_argc)--; 653*d29b2c44Sab196087 (*state->go_argv)++; 654*d29b2c44Sab196087 state->go_sglgrp = NULL; 655*d29b2c44Sab196087 } 656*d29b2c44Sab196087 657*d29b2c44Sab196087 for (optarg = state->go_optarg; optarg->oa_name != NULL; ) { 658*d29b2c44Sab196087 elfedit_next_optarg(&optarg, &item); 659*d29b2c44Sab196087 660*d29b2c44Sab196087 if ((item.oai_name[2] == '\0') && 661*d29b2c44Sab196087 (ch == item.oai_name[1])) { 662*d29b2c44Sab196087 /* 663*d29b2c44Sab196087 * It matches. If the option requires a value 664*d29b2c44Sab196087 * then it cannot be in a group. 665*d29b2c44Sab196087 */ 666*d29b2c44Sab196087 if (item.oai_flags & ELFEDIT_CMDOA_F_VALUE) 667*d29b2c44Sab196087 elfedit_command_usage(); 668*d29b2c44Sab196087 669*d29b2c44Sab196087 /* Mutually exclusive option already seen? */ 670*d29b2c44Sab196087 if (item.oai_excmask & state->go_idmask) 671*d29b2c44Sab196087 elfedit_command_usage(); 672*d29b2c44Sab196087 673*d29b2c44Sab196087 /* Return the match */ 674*d29b2c44Sab196087 state->go_idmask |= item.oai_idmask; 675*d29b2c44Sab196087 state->go_ret.gor_idmask = item.oai_idmask; 676*d29b2c44Sab196087 state->go_ret.gor_value = NULL; 677*d29b2c44Sab196087 return (&state->go_ret); 678*d29b2c44Sab196087 } 679*d29b2c44Sab196087 } 680*d29b2c44Sab196087 } 681*d29b2c44Sab196087 682*d29b2c44Sab196087 /* Nothing matched. We have a syntax error */ 683*d29b2c44Sab196087 elfedit_command_usage(); 684*d29b2c44Sab196087 /*NOTREACHED*/ 685*d29b2c44Sab196087 return (NULL); 686*d29b2c44Sab196087 } 687*d29b2c44Sab196087 688*d29b2c44Sab196087 689*d29b2c44Sab196087 /* 690*d29b2c44Sab196087 * Return the count of non-zero bits in the value v. 691*d29b2c44Sab196087 * 692*d29b2c44Sab196087 * entry: 693*d29b2c44Sab196087 * v - Value to test 694*d29b2c44Sab196087 * sizeof_orig_v - The result of using the sizeof operator 695*d29b2c44Sab196087 * on the original value of v. The value received 696*d29b2c44Sab196087 * by this routine has been cast to an unsigned 64-bit 697*d29b2c44Sab196087 * integer, so having the caller use sizeof allows us to 698*d29b2c44Sab196087 * avoid testing bits that were not in the original. 699*d29b2c44Sab196087 */ 700*d29b2c44Sab196087 int 701*d29b2c44Sab196087 elfedit_bits_set(u_longlong_t v, int sizeof_orig_v) 702*d29b2c44Sab196087 { 703*d29b2c44Sab196087 int nbits = sizeof_orig_v * 8; 704*d29b2c44Sab196087 int mask; 705*d29b2c44Sab196087 int cnt = 0; 706*d29b2c44Sab196087 707*d29b2c44Sab196087 for (mask = 1; (nbits-- > 0) && (cnt < 2); mask *= 2) 708*d29b2c44Sab196087 if (v & mask) 709*d29b2c44Sab196087 cnt++; 710*d29b2c44Sab196087 711*d29b2c44Sab196087 return (cnt); 712*d29b2c44Sab196087 } 713*d29b2c44Sab196087 714*d29b2c44Sab196087 715*d29b2c44Sab196087 /* 716*d29b2c44Sab196087 * "delete" items in an array by copying the following items up 717*d29b2c44Sab196087 * over the "deleted" items and then zero filling the vacated 718*d29b2c44Sab196087 * slots at the bottom. 719*d29b2c44Sab196087 * 720*d29b2c44Sab196087 * entry: 721*d29b2c44Sab196087 * name_str - Array identification prefix to use for debug message 722*d29b2c44Sab196087 * data_start - Address of 1st byte in array 723*d29b2c44Sab196087 * entsize - sizeof a single element of the array 724*d29b2c44Sab196087 * num_ent - # of elements in array 725*d29b2c44Sab196087 * start_ndx - Index of first item to be deleted 726*d29b2c44Sab196087 * cnt - # of items to delete 727*d29b2c44Sab196087 * 728*d29b2c44Sab196087 * exit: 729*d29b2c44Sab196087 * Any errors are issued and control does not return to the 730*d29b2c44Sab196087 * caller. On success, the items have been removed, zero filling 731*d29b2c44Sab196087 * has been done, and debug messages issued. 732*d29b2c44Sab196087 */ 733*d29b2c44Sab196087 void 734*d29b2c44Sab196087 elfedit_array_elts_delete(const char *name_str, void *data_start, 735*d29b2c44Sab196087 size_t entsize, size_t num_ent, size_t start_ndx, size_t cnt) 736*d29b2c44Sab196087 { 737*d29b2c44Sab196087 char *data = data_start; 738*d29b2c44Sab196087 739*d29b2c44Sab196087 /* The specified index and range must be in bounds */ 740*d29b2c44Sab196087 if ((start_ndx + cnt) > num_ent) 741*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_ARRBNDS), 742*d29b2c44Sab196087 name_str, EC_WORD(num_ent), EC_WORD(num_ent - 1)); 743*d29b2c44Sab196087 744*d29b2c44Sab196087 /* 745*d29b2c44Sab196087 * Everything below the deleted items moves up. 746*d29b2c44Sab196087 * Note that bcopy() is documented to handle overlapping 747*d29b2c44Sab196087 * src/dst correctly, so we make no effort to handle this 748*d29b2c44Sab196087 * element by element, but issue a single operation. 749*d29b2c44Sab196087 * 750*d29b2c44Sab196087 * If we're doing the last element, there is nothing to 751*d29b2c44Sab196087 * move up, and we skip this step, moving on to the zeroing below. 752*d29b2c44Sab196087 */ 753*d29b2c44Sab196087 if (start_ndx < (num_ent - 1)) { 754*d29b2c44Sab196087 size_t ncpy = num_ent - (start_ndx + cnt); 755*d29b2c44Sab196087 756*d29b2c44Sab196087 bcopy(data + ((start_ndx + cnt) * entsize), 757*d29b2c44Sab196087 data + (start_ndx * entsize), ncpy * entsize); 758*d29b2c44Sab196087 if (ncpy == 1) { 759*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 760*d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_ARRCPY_1), name_str, 761*d29b2c44Sab196087 EC_WORD(start_ndx + cnt), EC_WORD(start_ndx)); 762*d29b2c44Sab196087 } else { 763*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 764*d29b2c44Sab196087 MSG_INTL(MSG_DEBUG_ARRCPY_N), name_str, 765*d29b2c44Sab196087 EC_WORD(start_ndx + cnt), 766*d29b2c44Sab196087 EC_WORD(start_ndx + cnt + ncpy - 1), 767*d29b2c44Sab196087 EC_WORD(start_ndx), 768*d29b2c44Sab196087 EC_WORD(start_ndx + ncpy - 1)); 769*d29b2c44Sab196087 } 770*d29b2c44Sab196087 } 771*d29b2c44Sab196087 772*d29b2c44Sab196087 /* Zero out the vacated elements at the end */ 773*d29b2c44Sab196087 bzero(data + ((num_ent - cnt) * entsize), entsize * cnt); 774*d29b2c44Sab196087 775*d29b2c44Sab196087 if (cnt == 1) { 776*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ARRZERO_1), 777*d29b2c44Sab196087 name_str, EC_WORD(num_ent - 1)); 778*d29b2c44Sab196087 } else { 779*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ARRZERO_N), 780*d29b2c44Sab196087 name_str, EC_WORD(num_ent - cnt), 781*d29b2c44Sab196087 EC_WORD(num_ent - 1), EC_WORD(cnt)); 782*d29b2c44Sab196087 } 783*d29b2c44Sab196087 } 784*d29b2c44Sab196087 785*d29b2c44Sab196087 786*d29b2c44Sab196087 /* 787*d29b2c44Sab196087 * move the location of items in an array by shifting the surround 788*d29b2c44Sab196087 * items into the vacated hole and them putting the values into 789*d29b2c44Sab196087 * the new location. 790*d29b2c44Sab196087 * 791*d29b2c44Sab196087 * entry: 792*d29b2c44Sab196087 * name_str - Array identification prefix to use for debug message 793*d29b2c44Sab196087 * data_start - Address of 1st byte in array 794*d29b2c44Sab196087 * entsize - sizeof a single element of the array 795*d29b2c44Sab196087 * num_ent - # of elements in array 796*d29b2c44Sab196087 * start_ndx - Index of first item to be moved 797*d29b2c44Sab196087 * dst_ndx - Index to receive the moved block 798*d29b2c44Sab196087 * cnt - # of items to move 799*d29b2c44Sab196087 * scr_item - Space allocated by the caller sufficient to hold 800*d29b2c44Sab196087 * one item from the array. Used to swap elements. 801*d29b2c44Sab196087 * 802*d29b2c44Sab196087 * exit: 803*d29b2c44Sab196087 * Any errors are issued and control does not return to the 804*d29b2c44Sab196087 * caller. On success, the items have been moved, and debug 805*d29b2c44Sab196087 * messages issued. 806*d29b2c44Sab196087 */ 807*d29b2c44Sab196087 void 808*d29b2c44Sab196087 elfedit_array_elts_move(const char *name_str, void *data_start, 809*d29b2c44Sab196087 size_t entsize, size_t num_ent, size_t srcndx, 810*d29b2c44Sab196087 size_t dstndx, size_t cnt, void *scr_item) 811*d29b2c44Sab196087 { 812*d29b2c44Sab196087 char *data = data_start; 813*d29b2c44Sab196087 814*d29b2c44Sab196087 /* The specified source and destination ranges must be in bounds */ 815*d29b2c44Sab196087 if (((srcndx + cnt) > num_ent) || ((dstndx + cnt) > num_ent)) 816*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_ARRBNDS), 817*d29b2c44Sab196087 name_str, EC_WORD(num_ent), EC_WORD(num_ent - 1)); 818*d29b2c44Sab196087 819*d29b2c44Sab196087 /* If source and destination are same, there's nothing to do */ 820*d29b2c44Sab196087 if (srcndx == dstndx) 821*d29b2c44Sab196087 return; 822*d29b2c44Sab196087 823*d29b2c44Sab196087 /* 824*d29b2c44Sab196087 * It is meaningless to do a move where the source and destination 825*d29b2c44Sab196087 * are overlapping, because this "move" amounts to shifting 826*d29b2c44Sab196087 * the existing items around into a new position. If there is 827*d29b2c44Sab196087 * more than one element, then overlap is possible and we need 828*d29b2c44Sab196087 * to test for it. 829*d29b2c44Sab196087 */ 830*d29b2c44Sab196087 if (cnt > 1) { 831*d29b2c44Sab196087 size_t low, hi; 832*d29b2c44Sab196087 833*d29b2c44Sab196087 if (srcndx > dstndx) { 834*d29b2c44Sab196087 low = dstndx; 835*d29b2c44Sab196087 hi = srcndx; 836*d29b2c44Sab196087 } else { 837*d29b2c44Sab196087 low = srcndx; 838*d29b2c44Sab196087 hi = dstndx; 839*d29b2c44Sab196087 } 840*d29b2c44Sab196087 /* Ensure that the src and dst don't overlap */ 841*d29b2c44Sab196087 if ((low + cnt) > hi) 842*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 843*d29b2c44Sab196087 MSG_INTL(MSG_ERR_ARRMVOVERLAP), name_str, 844*d29b2c44Sab196087 EC_WORD(srcndx), EC_WORD(srcndx + cnt - 1), 845*d29b2c44Sab196087 EC_WORD(dstndx), EC_WORD(dstndx + cnt - 1)); 846*d29b2c44Sab196087 } 847*d29b2c44Sab196087 848*d29b2c44Sab196087 if (cnt == 1) 849*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ARRMOVE_1), 850*d29b2c44Sab196087 name_str, EC_WORD(srcndx), EC_WORD(dstndx)); 851*d29b2c44Sab196087 else 852*d29b2c44Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ARRMOVE_N), 853*d29b2c44Sab196087 name_str, EC_WORD(cnt), 854*d29b2c44Sab196087 EC_WORD(srcndx), EC_WORD(srcndx + cnt - 1), 855*d29b2c44Sab196087 EC_WORD(dstndx), EC_WORD(dstndx + cnt - 1)); 856*d29b2c44Sab196087 857*d29b2c44Sab196087 if (srcndx < dstndx) { 858*d29b2c44Sab196087 srcndx += cnt - 1; 859*d29b2c44Sab196087 dstndx += cnt - 1; 860*d29b2c44Sab196087 for (; cnt-- > 0; srcndx--, dstndx--) { 861*d29b2c44Sab196087 /* 862*d29b2c44Sab196087 * Copy item at srcndx to scratch location 863*d29b2c44Sab196087 * 864*d29b2c44Sab196087 * save = dyn[srcndx]; 865*d29b2c44Sab196087 */ 866*d29b2c44Sab196087 bcopy(data + (srcndx * entsize), scr_item, entsize); 867*d29b2c44Sab196087 868*d29b2c44Sab196087 /* 869*d29b2c44Sab196087 * Shift items after source up through destination 870*d29b2c44Sab196087 * to source. bcopy() handles overlapped copies. 871*d29b2c44Sab196087 * 872*d29b2c44Sab196087 * for (i = srcndx; i < dstndx; i++) 873*d29b2c44Sab196087 * dyn[i] = dyn[i + 1]; 874*d29b2c44Sab196087 */ 875*d29b2c44Sab196087 bcopy(data + ((srcndx + 1) * entsize), 876*d29b2c44Sab196087 data + (srcndx * entsize), 877*d29b2c44Sab196087 (dstndx - srcndx) * entsize); 878*d29b2c44Sab196087 879*d29b2c44Sab196087 /* 880*d29b2c44Sab196087 * Copy saved item into destination slot 881*d29b2c44Sab196087 * 882*d29b2c44Sab196087 * dyn[dstndx] = save; 883*d29b2c44Sab196087 */ 884*d29b2c44Sab196087 bcopy(scr_item, data + (dstndx * entsize), entsize); 885*d29b2c44Sab196087 } 886*d29b2c44Sab196087 } else { 887*d29b2c44Sab196087 for (; cnt-- > 0; srcndx++, dstndx++) { 888*d29b2c44Sab196087 /* 889*d29b2c44Sab196087 * Copy item at srcndx to scratch location 890*d29b2c44Sab196087 * 891*d29b2c44Sab196087 * save = dyn[srcndx]; 892*d29b2c44Sab196087 */ 893*d29b2c44Sab196087 bcopy(data + (srcndx * entsize), scr_item, entsize); 894*d29b2c44Sab196087 895*d29b2c44Sab196087 /* 896*d29b2c44Sab196087 * Shift items from destination through item below 897*d29b2c44Sab196087 * source up one. bcopy() handles overlapped copies. 898*d29b2c44Sab196087 * 899*d29b2c44Sab196087 * for (i = srcndx; i > dstndx; i--) 900*d29b2c44Sab196087 * dyn[i] = dyn[i - 1]; 901*d29b2c44Sab196087 */ 902*d29b2c44Sab196087 bcopy(data + (dstndx * entsize), 903*d29b2c44Sab196087 data + ((dstndx + 1) * entsize), 904*d29b2c44Sab196087 (srcndx - dstndx) * entsize); 905*d29b2c44Sab196087 906*d29b2c44Sab196087 /* 907*d29b2c44Sab196087 * Copy saved item into destination slot 908*d29b2c44Sab196087 * 909*d29b2c44Sab196087 * dyn[dstndx] = save; 910*d29b2c44Sab196087 */ 911*d29b2c44Sab196087 bcopy(scr_item, data + (dstndx * entsize), entsize); 912*d29b2c44Sab196087 } 913*d29b2c44Sab196087 } 914*d29b2c44Sab196087 } 915