4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <sys/machelf.h>
39 #include <sys/elf_SPARC.h>
40 #include <sys/elf_amd64.h>
46 * This file contains utility functions that are of general use
47 * to different elfedit modules for solving common problems.
48 * The functions in this file are not ELFCLASS specific. Those
49 * functions are found in util_machelf.c
51 * NOTE: This module contains functions with names
52 * elfedit_atoi, and elfedit_atoui, that are otherwise identical.
53 * These functions are for signed, and unsigned integers, respectively.
54 * In general, I supply one comment header for each such pair,
55 * and put their implementations together.
57 * There are also functions with names elfedit_atoconst. These are
58 * convenience wrappers that use the corresponding elfedit_atoui()
59 * function to process an array of symbolic names provided by a call
60 * elfedit_const_to_atoui().
67 * Given a value and an array of elfedit_ato[u]i items, return a pointer
68 * to the symbolic name for the value.
71 * sym - NULL terminated array of name->value mappings.
72 * value - Value to be found
73 * required - If True, and value is not found, an error is issued.
74 * Callers should only set required to True when they know
75 * a priori that the value will be found --- the error
76 * is reported as an internal programming error.
79 * If the array contains an entry with the given value, the
80 * name for the first such entry will be returned.
82 * If no entry is found: If required is True (1), an error is
83 * issued and this routine does not return to the caller. If required
84 * is False (0), then NULL is returned.
87 elfedit_atoi_value_to_str(const elfedit_atoi_sym_t
*sym
, elfedit_atoi_t value
,
90 for (; sym
->sym_name
!= NULL
; sym
++)
91 if (value
== sym
->sym_value
)
92 return (sym
->sym_name
);
94 /* Value did not match any of the entries */
96 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_BADGETVAL
));
100 elfedit_atoui_value_to_str(const elfedit_atoui_sym_t
*sym
,
101 elfedit_atoui_t value
, int required
)
103 for (; sym
->sym_name
!= NULL
; sym
++)
104 if (value
== sym
->sym_value
)
105 return (sym
->sym_name
);
107 /* Value did not match any of the entries */
109 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_BADGETVAL
));
113 elfedit_atoconst_value_to_str(elfedit_const_t const_type
, elfedit_atoui_t value
,
116 return (elfedit_atoui_value_to_str(elfedit_const_to_atoui(const_type
),
122 * Process the symbolic name to value mappings passed to the
123 * atoi and atoui functions.
126 * sym - NULL terminated array of name->value mappings.
127 * value - Address of variable to recieve corresponding value.
130 * If a mapping is found, *value is set to it, and True is returned.
131 * Otherwise False is returned.
134 atoi_sym_process(const char *str
, const elfedit_atoi_sym_t
*sym
,
135 elfedit_atoi_t
*value
)
140 while (isspace(*str
))
143 tail
= str
+ strlen(str
);
144 while ((tail
> str
) && isspace(*(tail
- 1)))
147 cmp_len
= tail
- str
;
149 for (; sym
->sym_name
!= NULL
; sym
++) {
150 if ((strlen(sym
->sym_name
) == cmp_len
) &&
151 (strncasecmp(sym
->sym_name
, str
, cmp_len
) == 0)) {
152 *value
= sym
->sym_value
;
157 /* No symbolic mapping was found */
161 atoui_sym_process(const char *str
, const elfedit_atoui_sym_t
*sym
,
162 elfedit_atoui_t
*value
)
167 while (isspace(*str
))
170 tail
= str
+ strlen(str
);
171 while ((tail
> str
) && isspace(*(tail
- 1)))
174 cmp_len
= tail
- str
;
176 for (; sym
->sym_name
!= NULL
; sym
++) {
177 if ((strlen(sym
->sym_name
) == cmp_len
) &&
178 (strncasecmp(sym
->sym_name
, str
, cmp_len
) == 0)) {
179 *value
= sym
->sym_value
;
184 /* No symbolic mapping was found */
191 * A command completion function for atoi and atoui mappings.
194 elfedit_cpl_atoi(void *cpldata
, const elfedit_atoi_sym_t
*sym
)
196 for (; sym
->sym_name
!= NULL
; sym
++)
197 elfedit_cpl_match(cpldata
, sym
->sym_name
, 1);
200 elfedit_cpl_atoui(void *cpldata
, const elfedit_atoui_sym_t
*sym
)
202 for (; sym
->sym_name
!= NULL
; sym
++)
203 elfedit_cpl_match(cpldata
, sym
->sym_name
, 1);
206 elfedit_cpl_atoconst(void *cpldata
, elfedit_const_t const_type
)
208 elfedit_cpl_atoui(cpldata
, elfedit_const_to_atoui(const_type
));
216 * Convert a string to a numeric value. Strings starting with '0'
217 * are taken to be octal, those staring with '0x' are hex, and all
218 * others are decimal.
221 * str - String to be converted
222 * sym - NULL, or NULL terminated array of name/value pairs.
224 * [elfedit_atoi2() and elfedit_atoui2() only]
225 * v - Address of variable to receive resulting value.
228 * elfedit_atoi2() and elfedit_atoui2():
229 * On success, returns True (1) and *v is set to the value.
230 * On failure, returns False (0) and *v is undefined.
232 * elfedit_atoi() and elfedit_atoui():
233 * If the string is convertable, the value is returned.
234 * Otherwise an error is issued and this routine does
235 * not return to the caller.
238 elfedit_atoi2(const char *str
, const elfedit_atoi_sym_t
*sym
, elfedit_atoi_t
*v
)
242 if (sym
&& atoi_sym_process(str
, sym
, v
))
245 *v
= strtoll(str
, &endptr
, 0);
247 /* If the left over part contains anything but whitespace, fail */
248 for (; *endptr
; endptr
++)
249 if (!isspace(*endptr
))
254 elfedit_atoi(const char *str
, const elfedit_atoi_sym_t
*sym
)
257 if (elfedit_atoi2(str
, sym
, &v
) == 0)
258 elfedit_msg(ELFEDIT_MSG_ERR
,
259 MSG_INTL(MSG_ERR_BADATOISTR
), str
);
263 elfedit_atoui2(const char *str
, const elfedit_atoui_sym_t
*sym
,
268 if (sym
&& atoui_sym_process(str
, sym
, v
))
271 *v
= strtoull(str
, &endptr
, 0);
273 /* If the left over part contains anything but whitespace, fail */
274 for (; *endptr
; endptr
++)
275 if (!isspace(*endptr
))
280 elfedit_atoui(const char *str
, const elfedit_atoui_sym_t
*sym
)
283 if (elfedit_atoui2(str
, sym
, &v
) == 0)
284 elfedit_msg(ELFEDIT_MSG_ERR
,
285 MSG_INTL(MSG_ERR_BADATOISTR
), str
);
289 elfedit_atoconst2(const char *str
, elfedit_const_t const_type
,
292 return (elfedit_atoui2(str
, elfedit_const_to_atoui(const_type
), v
));
295 elfedit_atoconst(const char *str
, elfedit_const_t const_type
)
297 return (elfedit_atoui(str
, elfedit_const_to_atoui(const_type
)));
301 * Convert a string to a numeric value using elfedit_ato[u]i and
302 * ensure that the resulting value lies within a given range.
303 * elfedit_ato[u]i_range() requires values to be in the range
304 * (min <= value <= max).
307 * str - String to be converted
308 * min, max - If check_range is true, the allowed range that the
309 * resulting value must lie in.
310 * sym - NULL, or NULL terminated array of name/value pairs.
312 * entry [elfedit_atoi_range() and elfedit_atoui_range() only]:
313 * item_name - String describing item for which value is being read.
315 * entry [elfedit_atoi_range2() and elfedit_atoui_range2() only]:
316 * v - Address of variable to receive resulting value.
319 * elfedit_atoi_range2() and elfedit_atoui_range2():
320 * On success, returns True (1) and *v is set to the value.
321 * On failure, returns False (0) and *v is undefined.
323 * elfedit_atoi_range() and elfedit_atoui_range():
324 * If the string is convertable, the value is returned.
325 * Otherwise an error is issued and this routine does
326 * not return to the caller.
329 elfedit_atoi_range2(const char *str
, elfedit_atoi_t min
, elfedit_atoi_t max
,
330 const elfedit_atoi_sym_t
*sym
, elfedit_atoi_t
*v
)
332 return ((elfedit_atoi2(str
, sym
, v
) != 0) &&
333 (*v
>= min
) && (*v
<= max
));
336 elfedit_atoi_range(const char *str
, const char *item_name
,
337 elfedit_atoi_t min
, elfedit_atoi_t max
, const elfedit_atoi_sym_t
*sym
)
339 elfedit_atoi_t v
= elfedit_atoi(str
, sym
);
341 if ((v
< min
) || (v
> max
))
342 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_ATOIRANGE
),
343 item_name
, EC_XWORD(min
), EC_XWORD(max
), EC_XWORD(v
));
348 elfedit_atoui_range2(const char *str
, elfedit_atoui_t min
, elfedit_atoui_t max
,
349 const elfedit_atoui_sym_t
*sym
, elfedit_atoui_t
*v
)
351 return ((elfedit_atoui2(str
, sym
, v
) != 0) &&
352 (*v
>= min
) && (*v
<= max
));
355 elfedit_atoui_range(const char *str
, const char *item_name
,
356 elfedit_atoui_t min
, elfedit_atoui_t max
, const elfedit_atoui_sym_t
*sym
)
358 elfedit_atoui_t v
= elfedit_atoui(str
, sym
);
360 if ((v
< min
) || (v
> max
))
361 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_ATOUIRANGE
),
362 item_name
, EC_XWORD(min
), EC_XWORD(max
), EC_XWORD(v
));
367 elfedit_atoconst_range2(const char *str
, elfedit_atoui_t min
,
368 elfedit_atoui_t max
, elfedit_const_t const_type
, elfedit_atoui_t
*v
)
370 return (elfedit_atoui_range2(str
, min
, max
,
371 elfedit_const_to_atoui(const_type
), v
));
374 elfedit_atoconst_range(const char *str
, const char *item_name
,
375 elfedit_atoui_t min
, elfedit_atoui_t max
, elfedit_const_t const_type
)
377 return (elfedit_atoui_range(str
, item_name
, min
, max
,
378 elfedit_const_to_atoui(const_type
)));
383 * Convenience wrapper on elfedit_atoui_range() that expects to see
384 * boolean values. Returns 1 for true, and 0 for false.
387 elfedit_atobool(const char *str
, const char *item_name
)
390 return (elfedit_atoconst_range(str
, item_name
, 0, 1,
391 ELFEDIT_CONST_BOOL
) != 0);
397 * Convenience wrapper on elfedit_atoui() to read a section index
398 * that understands the special SHN_ names.
401 * str - String to process
402 * shnum - Number of sections in the ELF file
405 * If it is possible to convert str to a number, that value
406 * is returned. If the value is out of range for the file,
407 * a warning message to that effect is issued. On failure,
408 * an error is issued and this routine does not return to
412 elfedit_atoshndx(const char *str
, size_t shnum
)
416 ndx
= elfedit_atoconst(str
, ELFEDIT_CONST_SHN
);
417 if ((ndx
>= shnum
) && ((ndx
< SHN_LORESERVE
) || (ndx
> SHN_HIRESERVE
)))
418 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_SHNDX_RANGE
),
419 EC_WORD(ndx
), EC_WORD(shnum
-1));
427 * Convert an output style string into it's integer constant. This
428 * routine reports success/failure via the return value rather than
429 * by throwing errors so that it can be used to process command
430 * line options at program startup, before
431 * the elfedit framework is initialized.
434 elfedit_atooutstyle(const char *str
, elfedit_outstyle_t
*outstyle
)
437 elfedit_atoui_t value
;
439 ret
= atoui_sym_process(str
,
440 elfedit_const_to_atoui(ELFEDIT_CONST_OUTSTYLE
), &value
);
450 * Initialize a state block for processing by elfedit_getopt().
453 * state - State block to initialize
454 * cmd_name - NULL, or name of command for which we are processing
456 * argc, argv - Address of variables giving number of options and
457 * access to the option strings.
460 * cmd_name can only be set to NULL when this routine is called
461 * by, or below, a currently active command. Otherwise, results
462 * are undefined (crashing or corruption) if there isn't one.
465 elfedit_getopt_init(elfedit_getopt_state_t
*state
,
466 int *argc
, const char **argv
[])
468 elfeditGC_cmd_t
*cmd
= elfedit_curcmd();
470 state
->go_argc
= argc
;
471 state
->go_argv
= argv
;
472 state
->go_optarg
= cmd
->cmd_opt
;
473 state
->go_idmask
= 0;
475 state
->go_sglgrp
= NULL
;
481 * elfedit-centric version of getopt()
484 * state - Getopt state, which must have been previously initialized
485 * via a call to elfedit_getopt_init.
488 * If an option is matched, this routine returns a pointer to an
489 * elfedit_getopt_ret_t buffer (which comes from the storage used
490 * for state). If there are no more options to process, NULL is returned.
492 * Syntax errors are reported via elfedit_command_usage(), and this
493 * routine does not return to the caller.
496 * - The caller should not access the contents of state directly.
497 * Those contents are private, and subject to change.
498 * - Once a call to this routine returns NULL, the argc/argv have
499 * have been ajusted so that they reference the plain arguments.
501 elfedit_getopt_ret_t
*
502 elfedit_getopt(elfedit_getopt_state_t
*state
)
504 elfedit_cmd_optarg_t
*optarg
;
506 int argc
= *(state
->go_argc
);
507 const char **argv
= *(state
->go_argv
);
508 elfedit_optarg_item_t item
;
512 elfedit_getopt_ret_t ret
;
513 elfedit_cmd_oa_mask_t excmask
;
516 if (state
->go_sglgrp
== NULL
) {
518 * Reasons to bail out immediately:
519 * - The command does not accept options
520 * - We've already reported the final option.
521 * - There are no more arguments.
522 * - The next argument does not start with '-'
524 if ((state
->go_optarg
== NULL
) || state
->go_done
||
525 (argc
<= 0) || (*(argv
[0]) != '-')) {
532 /* A '-' by itself is a syntax error */
533 if (argstr
[1] == '\0')
534 elfedit_command_usage();
536 /* A '--' option means we should stop at this point */
537 if ((argstr
[1] == '-') && (argstr
[2] == '\0')) {
544 * We have a string that starts with a '-'.
545 * Does it match an option?
547 sgl_with_value
.valid
= 0;
548 for (optarg
= state
->go_optarg
; optarg
->oa_name
!= NULL
; ) {
550 (optarg
->oa_flags
& ELFEDIT_CMDOA_F_INHERIT
) &&
551 (optarg
->oa_name
== ELFEDIT_STDOA_OPT_O
);
554 elfedit_next_optarg(&optarg
, &item
);
555 need_value
= item
.oai_flags
& ELFEDIT_CMDOA_F_VALUE
;
558 * If the option is a single letter that accepts
559 * a value, then we allow the combined syntax
560 * -ovalue, where no space is reqired between the
561 * option flag and the value string.
563 if ((item
.oai_name
[2] == '\0') && need_value
&&
564 (argstr
[1] == item
.oai_name
[1]) &&
565 (argstr
[2] != '\0')) {
567 * We have a match. However, there may also
568 * be a straightforward match that we have
569 * not yet found. If so, we want to prefer that
570 * case over this one. So rather than return
571 * it immediately, we capture the information
572 * and keep looking. If nothing else surfaces,
573 * we'll use this later.
575 sgl_with_value
.valid
= 1;
576 sgl_with_value
.ret
.gor_idmask
= item
.oai_idmask
;
577 sgl_with_value
.excmask
= item
.oai_excmask
;
578 sgl_with_value
.ret
.gor_value
= argstr
+ 2;
579 sgl_with_value
.is_outstyle
= is_outstyle
;
583 /* Try for a straightforward match */
584 if (strcmp(argstr
, item
.oai_name
) == 0) {
585 (*state
->go_argc
) = --argc
;
586 (*state
->go_argv
) = ++argv
;
588 /* Mutually exclusive option already seen? */
589 if (item
.oai_excmask
& state
->go_idmask
)
590 elfedit_command_usage();
592 /* Return the match */
593 state
->go_idmask
|= item
.oai_idmask
;
594 state
->go_ret
.gor_idmask
= item
.oai_idmask
;
596 /* If out of args, syntax error */
598 elfedit_command_usage();
599 state
->go_ret
.gor_value
= argv
[0];
603 state
->go_ret
.gor_value
= NULL
;
606 elfedit_set_cmd_outstyle(
607 state
->go_ret
.gor_value
);
608 return (&state
->go_ret
);
613 * No straightforward matches: Did we get a match with
614 * the special single letter and combined value? If so
617 if (sgl_with_value
.valid
) {
621 /* Mutually exclusive option already seen? */
622 if (sgl_with_value
.excmask
& state
->go_idmask
)
623 elfedit_command_usage();
625 state
->go_idmask
|= sgl_with_value
.ret
.gor_idmask
;
626 state
->go_ret
= sgl_with_value
.ret
;
627 if (sgl_with_value
.is_outstyle
)
628 elfedit_set_cmd_outstyle(
629 state
->go_ret
.gor_value
);
631 return (&state
->go_ret
);
635 * If nothing above matched, make this option the single
636 * group string and see if the characters in it all match
637 * as single letter options without values.
639 state
->go_sglgrp
= argstr
+ 1; /* Skip '-' */
643 * If there is a single group string, take the first character
644 * and try to match it to an 1-letter option that does not
647 if (state
->go_sglgrp
!= NULL
) {
648 int ch
= *state
->go_sglgrp
++;
650 /* If that is the last character, clear single group mode */
651 if (*state
->go_sglgrp
== '\0') {
654 state
->go_sglgrp
= NULL
;
657 for (optarg
= state
->go_optarg
; optarg
->oa_name
!= NULL
; ) {
658 elfedit_next_optarg(&optarg
, &item
);
660 if ((item
.oai_name
[2] == '\0') &&
661 (ch
== item
.oai_name
[1])) {
663 * It matches. If the option requires a value
664 * then it cannot be in a group.
666 if (item
.oai_flags
& ELFEDIT_CMDOA_F_VALUE
)
667 elfedit_command_usage();
669 /* Mutually exclusive option already seen? */
670 if (item
.oai_excmask
& state
->go_idmask
)
671 elfedit_command_usage();
673 /* Return the match */
674 state
->go_idmask
|= item
.oai_idmask
;
675 state
->go_ret
.gor_idmask
= item
.oai_idmask
;
676 state
->go_ret
.gor_value
= NULL
;
677 return (&state
->go_ret
);
682 /* Nothing matched. We have a syntax error */
683 elfedit_command_usage();
690 * Return the count of non-zero bits in the value v.
694 * sizeof_orig_v - The result of using the sizeof operator
695 * on the original value of v. The value received
696 * by this routine has been cast to an unsigned 64-bit
697 * integer, so having the caller use sizeof allows us to
698 * avoid testing bits that were not in the original.
701 elfedit_bits_set(u_longlong_t v
, int sizeof_orig_v
)
703 int nbits
= sizeof_orig_v
* 8;
707 for (mask
= 1; (nbits
-- > 0) && (cnt
< 2); mask
*= 2)
716 * "delete" items in an array by copying the following items up
717 * over the "deleted" items and then zero filling the vacated
718 * slots at the bottom.
721 * name_str - Array identification prefix to use for debug message
722 * data_start - Address of 1st byte in array
723 * entsize - sizeof a single element of the array
724 * num_ent - # of elements in array
725 * start_ndx - Index of first item to be deleted
726 * cnt - # of items to delete
729 * Any errors are issued and control does not return to the
730 * caller. On success, the items have been removed, zero filling
731 * has been done, and debug messages issued.
734 elfedit_array_elts_delete(const char *name_str
, void *data_start
,
735 size_t entsize
, size_t num_ent
, size_t start_ndx
, size_t cnt
)
737 char *data
= data_start
;
739 /* The specified index and range must be in bounds */
740 if ((start_ndx
+ cnt
) > num_ent
)
741 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_ARRBNDS
),
742 name_str
, EC_WORD(num_ent
), EC_WORD(num_ent
- 1));
745 * Everything below the deleted items moves up.
746 * Note that bcopy() is documented to handle overlapping
747 * src/dst correctly, so we make no effort to handle this
748 * element by element, but issue a single operation.
750 * If we're doing the last element, there is nothing to
751 * move up, and we skip this step, moving on to the zeroing below.
753 if (start_ndx
< (num_ent
- 1)) {
754 size_t ncpy
= num_ent
- (start_ndx
+ cnt
);
756 bcopy(data
+ ((start_ndx
+ cnt
) * entsize
),
757 data
+ (start_ndx
* entsize
), ncpy
* entsize
);
759 elfedit_msg(ELFEDIT_MSG_DEBUG
,
760 MSG_INTL(MSG_DEBUG_ARRCPY_1
), name_str
,
761 EC_WORD(start_ndx
+ cnt
), EC_WORD(start_ndx
));
763 elfedit_msg(ELFEDIT_MSG_DEBUG
,
764 MSG_INTL(MSG_DEBUG_ARRCPY_N
), name_str
,
765 EC_WORD(start_ndx
+ cnt
),
766 EC_WORD(start_ndx
+ cnt
+ ncpy
- 1),
768 EC_WORD(start_ndx
+ ncpy
- 1));
772 /* Zero out the vacated elements at the end */
773 bzero(data
+ ((num_ent
- cnt
) * entsize
), entsize
* cnt
);
776 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_ARRZERO_1
),
777 name_str
, EC_WORD(num_ent
- 1));
779 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_ARRZERO_N
),
780 name_str
, EC_WORD(num_ent
- cnt
),
781 EC_WORD(num_ent
- 1), EC_WORD(cnt
));
787 * move the location of items in an array by shifting the surround
788 * items into the vacated hole and them putting the values into
792 * name_str - Array identification prefix to use for debug message
793 * data_start - Address of 1st byte in array
794 * entsize - sizeof a single element of the array
795 * num_ent - # of elements in array
796 * start_ndx - Index of first item to be moved
797 * dst_ndx - Index to receive the moved block
798 * cnt - # of items to move
799 * scr_item - Space allocated by the caller sufficient to hold
800 * one item from the array. Used to swap elements.
803 * Any errors are issued and control does not return to the
804 * caller. On success, the items have been moved, and debug
808 elfedit_array_elts_move(const char *name_str
, void *data_start
,
809 size_t entsize
, size_t num_ent
, size_t srcndx
,
810 size_t dstndx
, size_t cnt
, void *scr_item
)
812 char *data
= data_start
;
814 /* The specified source and destination ranges must be in bounds */
815 if (((srcndx
+ cnt
) > num_ent
) || ((dstndx
+ cnt
) > num_ent
))
816 elfedit_msg(ELFEDIT_MSG_ERR
, MSG_INTL(MSG_ERR_ARRBNDS
),
817 name_str
, EC_WORD(num_ent
), EC_WORD(num_ent
- 1));
819 /* If source and destination are same, there's nothing to do */
820 if (srcndx
== dstndx
)
824 * It is meaningless to do a move where the source and destination
825 * are overlapping, because this "move" amounts to shifting
826 * the existing items around into a new position. If there is
827 * more than one element, then overlap is possible and we need
833 if (srcndx
> dstndx
) {
840 /* Ensure that the src and dst don't overlap */
841 if ((low
+ cnt
) > hi
)
842 elfedit_msg(ELFEDIT_MSG_ERR
,
843 MSG_INTL(MSG_ERR_ARRMVOVERLAP
), name_str
,
844 EC_WORD(srcndx
), EC_WORD(srcndx
+ cnt
- 1),
845 EC_WORD(dstndx
), EC_WORD(dstndx
+ cnt
- 1));
849 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_ARRMOVE_1
),
850 name_str
, EC_WORD(srcndx
), EC_WORD(dstndx
));
852 elfedit_msg(ELFEDIT_MSG_DEBUG
, MSG_INTL(MSG_DEBUG_ARRMOVE_N
),
853 name_str
, EC_WORD(cnt
),
854 EC_WORD(srcndx
), EC_WORD(srcndx
+ cnt
- 1),
855 EC_WORD(dstndx
), EC_WORD(dstndx
+ cnt
- 1));
857 if (srcndx
< dstndx
) {
860 for (; cnt
-- > 0; srcndx
--, dstndx
--) {
862 * Copy item at srcndx to scratch location
864 * save = dyn[srcndx];
866 bcopy(data
+ (srcndx
* entsize
), scr_item
, entsize
);
869 * Shift items after source up through destination
870 * to source. bcopy() handles overlapped copies.
872 * for (i = srcndx; i < dstndx; i++)
873 * dyn[i] = dyn[i + 1];
875 bcopy(data
+ ((srcndx
+ 1) * entsize
),
876 data
+ (srcndx
* entsize
),
877 (dstndx
- srcndx
) * entsize
);
880 * Copy saved item into destination slot
882 * dyn[dstndx] = save;
884 bcopy(scr_item
, data
+ (dstndx
* entsize
), entsize
);
887 for (; cnt
-- > 0; srcndx
++, dstndx
++) {
889 * Copy item at srcndx to scratch location
891 * save = dyn[srcndx];
893 bcopy(data
+ (srcndx
* entsize
), scr_item
, entsize
);
896 * Shift items from destination through item below
897 * source up one. bcopy() handles overlapped copies.
899 * for (i = srcndx; i > dstndx; i--)
900 * dyn[i] = dyn[i - 1];
902 bcopy(data
+ (dstndx
* entsize
),
903 data
+ ((dstndx
+ 1) * entsize
),
904 (srcndx
- dstndx
) * entsize
);
907 * Copy saved item into destination slot
909 * dyn[dstndx] = save;
911 bcopy(scr_item
, data
+ (dstndx
* entsize
), entsize
);