summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/include/elfedit.h
blob: 6c5a204f1a6978f09707ecbf38cb2e2f45020039 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_ELFEDIT_H
#define	_ELFEDIT_H

#include	<stdio.h>
#include	<stdlib.h>
#include	<sys/types.h>
#include	<libelf.h>
#include	<stdarg.h>

/* The following are here to support use of elfedit_msg() */
#include	<sys/machelf.h>		/* EC_ macros */
#include	<libintl.h>

#ifdef	__cplusplus
extern "C" {
#endif


/*
 * elfedit uses elfedit_printf() to produce generic output to stdout.
 * elfedit_msg() is used to produce error message, or specific types
 * of terse informational messages:
 *
 *	ELFEDIT_MSG_ERR:
 *		Issues an error to stderr. elfedit_msg() does not return
 *		to the caller. Control returns to the outer loop in
 *		interactive use. elfedit exits in non-interactive use.
 *
 *	ELFEDIT_MSG_FATAL:
 *		Issues an error to stderr. elfedit_msg() exits the process,
 *		and does not return to the caller.
 *
 *	ELFEDIT_MSG_USAGE:
 *		Issues an elfedit usage message to stderr, and
 *		returns to the caller.
 *
 *	ELFEDIT_MSG_CMDUSAGE
 *		Issues an elfedit usage message to stderr, and
 *		does not return to the caller.
 *
 *	ELFEDIT_MSG_DEBUG
 *		If the ELFEDIT_F_DEBUG flag is set, the message
 *		is printed to stdout, otherwise no output is produced.
 *		elfedit_msg() returns to the caller.
 *
 *	ELFEDIT_MSG_QUIET
 *		This is a very special case, intended to handle the
 *		case where the pager subprocess exits before we are
 *		done producing output (the user presses 'q'). It acts
 *		just like ELFEDIT_MSG_ERR, except that no message is
 *		actually printed.
 *
 * In the cases where elfedit_msg() does not return to the caller, the
 * behavior depends on the mode of execution. If running in interactive
 * mode (reading from a tty), control is returned directly to the outer
 * elfedit control loop to read another command. If not running in interactive
 * mode, elfedit exits with a non-zero status.
 */
typedef enum {
	ELFEDIT_MSG_ERR = 0,
	ELFEDIT_MSG_FATAL = 1,
	ELFEDIT_MSG_USAGE = 2,
	ELFEDIT_MSG_CMDUSAGE = 3,
	ELFEDIT_MSG_DEBUG = 4,
	ELFEDIT_MSG_QUIET = 5
} elfedit_msg_t;


/*
 * Information for a single ELF section.
 *
 * NOTE: sec_xshndx
 *	A symbol table can have an associated SHT_SYMTAB_SHNDX section. This
 *	happens when the number of sections is too large to fit in the
 *	ELF symbol st_shndx field, which is a 16-bit value. The sec_xshndx
 *	field will be SHN_UNDEF if there is no such section, and will be
 *	the section index of the extended section index section assocated
 *	with the symbol table otherwise.
 *
 * NOTE: sec_versym
 *	Symbol table sections can have an SHT_SUNW_VERSYM section that
 *	contains its version indices. Other types of section will have
 *	this field set to SHN_UNDEF.
 */
typedef struct {
	Elf32_Word	sec_shndx;	/* Section index */
	Elf_Scn		*sec_scn;	/* Section descriptor */
	Elf32_Shdr	*sec_shdr;	/* Section header */
	Elf_Data	*sec_data;	/* Data region of section */
	const char	*sec_name;	/* Name of section */
} elfedit32_section_t;

typedef struct {
	Elf64_Word	sec_shndx;
	Elf_Scn		*sec_scn;
	Elf64_Shdr	*sec_shdr;
	Elf_Data	*sec_data;
	const char	*sec_name;
} elfedit64_section_t;

#ifdef _ELF64
#define	elfedit_section_t	elfedit64_section_t
#else
#define	elfedit_section_t	elfedit32_section_t
#endif


/*
 * We maintain extra information for symbol tables. We look them
 * up frequently, so we want to eliminate expensive linear searches
 * of the entire section header array. Also, symbol tables usually
 * have associated parallal sections (syminfo, versym, extended indexes, etc)
 * and we want to eliminate repeated linear lookups for them, as well as
 * the basic error checking that is necessary to ensure they match the
 * symbol table they're given.
 *
 * This extra information is kept in elfedit_symtab_t structs. Each field
 * is a section index, with SHN_UNDEF used for those that do not apply.
 */
typedef struct {
	Elf32_Word	symt_shndx;	/* Symbol table section index */
	Elf32_Word	symt_xshndx;	/* Index of extended index section */
	Elf32_Word	symt_syminfo;	/* Index of versym section */
	Elf32_Word	symt_versym;	/* Index of versym section */
} elfedit32_symtab_t;

typedef struct {
	Elf64_Word	symt_shndx;
	Elf64_Word	symt_xshndx;
	Elf64_Word	symt_versym;
	Elf64_Word	symt_syminfo;
} elfedit64_symtab_t;

#ifdef _ELF64
#define	elfedit_symtab_t	elfedit64_symtab_t
#else
#define	elfedit_symtab_t	elfedit32_symtab_t
#endif


/*
 * Information for a single ELF object.
 *
 * note:
 *	elfedit is intended to be an expert's tool, capable of modifying
 *	nearly everything in the file, whether or not such modifications
 *	are a good idea. At the same time, elfedit, via libelf, relies
 *	on the contents of the object to properly locate information in
 *	the file. As this is the same information that elfedit allows the
 *	user to modify, it should be obvious that the potential exists
 *	for users to corrupt the file to the degree that elfedit itself
 *	may fail, or produce spurious results. We allow such changes for
 *	several reasons:
 *
 *	1) Such corruption does not happen in the most obvious and
 *		useful operations elfedit supports, but comes as a result
 *		of modifying fields that contain size and offset information
 *		used to navigate the file. Non-ELF developers have
 *		little practical reason to change such things.
 *
 *	2) Producing a corrupt ELF file can be very useful
 *		for R&D and/or testing purposes.
 *
 *	3) ELF is sufficiently complex that no absolute guarantees can
 *		be made about "safe" operations, beyond the basic
 *		and obvious things that are of practical use.
 *
 *	One way we protect ourselves is via the information cached in
 *	the elfedit_obj_state_t structure at startup. By using this
 *	information, rather than constantly fetching it via libelf,
 *	we protect ourselves against many user changes, such as changing the
 *	program or section header offsets, or similar size/position fields.
 *
 *	Of course, we make no assurances that that we will be able to
 *	read the resulting file in a subsequent session.
 */
typedef struct {
	const char		*os_file;	/* Path to ELF file */
	int			os_fd;		/* Open file descriptor */
	Elf			*os_elf;	/* ELF descriptor */
	Elf32_Ehdr		*os_ehdr;	/* ELF header */
	Elf32_Word		os_dynndx;	/* Index of dynamic section */
	size_t			os_shstrndx;	/* Index of section header */
						/*	string table section */
	size_t			os_shnum;	/* # of sections in file */
	elfedit32_section_t	*os_secarr;	/* Section data */
	size_t			os_phnum;	/* # of program headers */
	Elf32_Phdr		*os_phdr;	/* Program header array */
	size_t			os_symtabnum;	/* # items in os_symtab[] */
	elfedit32_symtab_t	*os_symtab;	/* Array of symbol tbl info  */
} elfedit32_obj_state_t;

typedef struct {
	const char		*os_file;
	int			os_fd;
	Elf			*os_elf;
	Elf64_Ehdr		*os_ehdr;
	Elf64_Word		os_dynndx;
	size_t			os_shstrndx;
	size_t			os_shnum;
	elfedit64_section_t	*os_secarr;
	size_t			os_phnum;
	Elf64_Phdr		*os_phdr;
	size_t			os_symtabnum;
	elfedit64_symtab_t	*os_symtab;
} elfedit64_obj_state_t;

#ifdef _ELF64
#define	elfedit_obj_state_t	elfedit64_obj_state_t
#else
#define	elfedit_obj_state_t	elfedit32_obj_state_t
#endif


/*
 * Bit values for editor state.
 */
typedef enum {
	ELFEDIT_F_AUTOPRINT = 1, /* Print informational text about edits */
	ELFEDIT_F_DEBUG = 2,	/* Print informational text about operations */
	ELFEDIT_F_READONLY = 4,	/* File is processed readonly */
} elfedit_flag_t;

/*
 * Type used to represent the output style for printing ELF values.
 *
 * DEFAULT - Output is in 'elfdump' style, designed for human eyes.
 *	Headers, and additional information are shown.
 * SIMPLE - Output is simple, consisting only of the target item.
 *	Integer values are shown as symbolic constants when possible,
 *	and integers otherwise.
 * NUM - Like SIMPLE, except integer values are always shown as
 *	integer constants, and strings are shown as the integer
 *	offset into the string table.
 */
typedef enum {
	ELFEDIT_OUTSTYLE_DEFAULT = 0,
	ELFEDIT_OUTSTYLE_SIMPLE = 1,
	ELFEDIT_OUTSTYLE_NUM = 2
} elfedit_outstyle_t;


/*
 * The elfedit_module_t, and the types it references, are defined
 * by loadable elfedit modules, and used by elfedit. These structures
 * need to communicate internationalized strings for elfedit to print.
 *
 * We want to leave the choice of internationalization APIs, as well as
 * the decision about whether or not to even to it to the individual
 * modules. Hence, we do not use a simple (const char *) pointer to
 * communicate potentially internationalized strings. Instead, we define
 * elfedit_i18nhdl_t, an opaque type guaranteed to be large enough
 * to hold a pointer. Each module casts the handle needed to access the
 * string to this type. Each module also supplies a function
 * (mod_i18nhdl_to_str field of elfedit_module_t) that given one
 * of these opaque keys, will return a (const char *) pointer to the
 * actual string, for elfedit to print.
 *
 * If the underlying module doesn't want to implement i18n support,
 * all it has to do is cast the strings to elfedit_i18nhdl_t and
 * back.
 */
typedef uintptr_t elfedit_i18nhdl_t;



/*
 * Macro to handle casting international string "handles" to the
 * elfedit_i18nhdl_t opaque type.
 */
#define	ELFEDIT_I18NHDL(_i18n_str_ref) ((elfedit_i18nhdl_t)_i18n_str_ref)


/*
 * Return values from command functions
 */
typedef enum {
	ELFEDIT_CMDRET_NONE = 0,	/* Nothing to report */
	ELFEDIT_CMDRET_MOD = 1,		/* Command modified output ELF file */
	ELFEDIT_CMDRET_MOD_OS_MACH = 2, /* As per _MOD, include ELF header */
					/*	osabi or machine change */
	ELFEDIT_CMDRET_FLUSH = 3	/* Output file flushed: elf_update() */
} elfedit_cmdret_t;

/*
 * Prototype of an implementation function for an edit command. Note that
 * commands do not return a status:
 *	- Success is indicated by a normal return.
 *	- The command indicates a fatal error by calling elfedit_msg() with the
 *		ELFEDIT_MSG_ERR type, in which case execution does not return
 *		to the command, and the elfedit command loop knows that an
 *		error occurred.
 *	- The command is responsible for using the standard libelf
 *		mechanisms to indicate when changes have been made to
 *		the ELF file.
 */
typedef elfedit_cmdret_t elfedit32_cmd_func_t(elfedit32_obj_state_t *state,
    int argc, const char *argv[]);
typedef elfedit_cmdret_t elfedit64_cmd_func_t(elfedit64_obj_state_t *state,
    int argc, const char *argv[]);
#ifdef _ELF64
#define	elfedit_cmd_func_t	elfedit64_cmd_func_t
#else
#define	elfedit_cmd_func_t	elfedit32_cmd_func_t
#endif


/*
 * An elfedit command (elfedit_cmd_t) has a cmd_cpl field that
 * can be set to a command completion function. If such a function
 * is present (non-NULL), and the user presses the tab key at the
 * command line while the cursor is at a plain (non option) argument,
 * elfedit calls the function, passing it all the tokens up through
 * the one needing completion.  The function can use elfedit_cpl_match()
 * to enter possible alternatives.  Additionally, there are helper
 * functions built on top of elfedit_cpl_match() that simplify common cases.
 *
 *	elfedit_cpl_ato[iu]() - enter matches from elfedit_ato[iu]_sym_t
 *		mappings.
 *	elfedit_cpl_atoconst() - Enter matches for well known constants
 *	elfedit_cpl_command() - enter matches for all known commands
 *	elfedit_cpl_mod() - enter matches for all known modules.
 *	elfedit_cpl_ndx() - enter numeric index as a match
 *
 * The completion function is passed the following arguments:
 *
 *	obj_state - Object state. Will be NULL if elfedit session does not
 *		have an active object. The completion function must test
 *		the pointer before using it.
 *	cpldata - Completion data, to be passed to elfedit_cpl_match()
 *		or the helper functions built on it to register alternative
 *		strings.
 *	argc, argv - The tokens from the start of the line through
 *		the one needing completion, which will always
 *		be cmdcpl_argv[cmdcpl_argc - 1].
 *	num_opt - A count of the optional arguments (those starting with
 *		'-' at the beginning of argv. This means that argv[num_opt]
 *		is the first plain argument, and the 1-based positional
 *		number of the plain argument for which command completion
 *		is needed is (argc - num_opt).
 */
typedef void elfedit32_cmdcpl_func_t(elfedit32_obj_state_t *state,
    void *cpldata, int argc, const char *argv[], int num_opt);
typedef void elfedit64_cmdcpl_func_t(elfedit64_obj_state_t *state,
    void *cpldata, int argc, const char *argv[], int num_opt);
#ifdef _ELF64
#define	elfedit_cmdcpl_func_t	elfedit64_cmdcpl_func_t
#else
#define	elfedit_cmdcpl_func_t	elfedit32_cmdcpl_func_t
#endif




/*
 * Command option/argument descriptor. These structures
 * are used to represent each option and plain argument accepted
 * by a command, via the cmd_opt and cmd_args fields in the
 * command definition (elfedit_cmd_t). Each descriptor consists
 * of a name, a help string (formatted for display via sys:help),
 * and a flags field that conveys extra information about the
 * item:
 *
 *	ELFEDIT_CMDOA_F_OPT
 *	The item is optional. This flag is implicit for options
 *	and need only be set for plain arguments.
 *
 *	ELFEDIT_CMDOA_F_VALUE
 *	The item has a value, which is found in the following
 *	item. This flag only has meaning for options, and should
 *	not be set for plain arguments. The descriptor for the
 *	value is found in the next array element, and only the
 *	oa_name field is used (the other should be set t 0).
 *
 *	ELFEDIT_CMDOA_F_MULT
 *	More than one of the specified items may be specified
 *
 *	ELFEDIT_CMDOA_F_INHERIT
 *	This is an item for which a common definition exists.
 *	Elfedit will substitute the standard values for the
 *	name, help text, and flags. This enforces consistency
 *	in documentation, plus it is easier for the module author.
 *	When ELFEDIT_CMDOA_F_INHERIT is set:
 *		- oa_name should be set to one of the ELFEDIT_STDOA_
 *			values to specifiy which standard item is being
 *			inherited.
 *		- oa_help must be set to NULL.
 *		- It is an error to set any other flags with
 *			ELFEDIT_CMDOA_F_INHERIT.
 *		- oa_idmask and oa_excmask are used in the normal way.
 *
 * The oa_idmask and oa_excmask fields are used to identify options,
 * and to support mutual exclusion (when two or more options cannot be
 * used together). They are ignored for arguments, and should be set to 0.
 * oa_idmask is used to uniquely identify each item. When elfedit_getopt()
 * matches an option, it returns the value of oa_idmask to the caller to
 * indicate which option was matched. elfedit enforces the following rules
 * for oa_idmask, and will refuse to load a module that does not follow them:
 *	- The value of oa_idmask must be 0, or have a value that
 *		is a power of 2 (i.e. only has one bit set).
 *	- Each item that sets a non-0 value for oa_idmask must have
 *		a unique value.
 *	- If oa_idmask is 0, oa_excmask must be 0 also.
 *	- oa_excmask is set to 0 if an item is not mutually exclusive
 *		to any other item. Otherwise, it should set the bit
 *		values representing the items it is mutually exclusive to.
 *	- An oa_idmask value of 0 can be used for any item that
 *		the module does not need to identify, and which
 *		is not mutually exclusive to any other item.
 * As elfedit_getopt() processes items, it maintains a bitmask combining the
 * oa_idmask fields of all the options already seen. For each option, it uses
 * oa_excmask to check for conflicts.
 *
 * note: elfedit enforces the rule that options consist of a '-'
 *	character followed by at least one character when a module
 *	is loaded.
 */
typedef enum {
	ELFEDIT_CMDOA_F_OPT =	1,	/* Item is optional */
	ELFEDIT_CMDOA_F_VALUE =	2,	/* Item has a value arg following */
	ELFEDIT_CMDOA_F_MULT =	4,	/* More than one are allowed */
	ELFEDIT_CMDOA_F_INHERIT = 8,	/* Inherit definition: See above */
} elfedit_cmd_oa_flag_t;

typedef u_longlong_t elfedit_cmd_oa_mask_t;

typedef struct {
	const char		*oa_name;	/* Name of option */
	elfedit_i18nhdl_t	oa_help;	/* Help text for option */
	elfedit_cmd_oa_flag_t	oa_flags;	/* Additional attributes */
	elfedit_cmd_oa_mask_t	oa_idmask;	/* Unique id, returned by */
						/* 	elfedit_getopt */
						/*	for use by caller */
	elfedit_cmd_oa_mask_t	oa_excmask;	/* Mutual exclusion mask */
} elfedit_cmd_optarg_t;



/*
 * These values define the standard options and arguments that a module
 * can inherit using the ELFEDIT_CMDOA_F_INHERIT flag (described above).
 * New items must be added at the end --- reordering the list will
 * require all modules to be rebuilt.
 *
 * Note: 0 cannot be used as a ELFEDIT_STDOA_ value, because a NULL
 *	value of oa_name is used to terminate argument and options lists.
 *	Therefore, these values start at 1.
 */
#define	ELFEDIT_STDOA_OPT_O		((const char *) 1)	/* -o ostyle */
#define	ELFEDIT_STDOA_OPT_AND		((const char *) 2)	/* -and */
#define	ELFEDIT_STDOA_OPT_CMP		((const char *) 3)	/* -cmp */
#define	ELFEDIT_STDOA_OPT_OR		((const char *) 4)	/* -or */

#define	ELFEDIT_NUM_STDOA	4	/* # of ELFEDIT_STDOA_ definitions */



/*
 * Definition of a command
 *
 * This structure includes an elfedit_cmd_func_t pointer, which has
 * different definitions for different ELFCLASS. Rather than needlessly
 * complicate the code with three versions of this type, and any
 * type that uses it, we simply use the GenericClass type. elfedit
 * will always cast this to the correct type before calling a module.
 *
 * cmd_name is an array of pointers to the names for the command.
 * The "primary" name should always be first, followed by any alias
 * names. The final element of the array must be a NULL pointer,
 * which terminates the list. Every command is required to have at
 * least one name, so code is allowed to assume that the first element
 * of cmd_name is non-NULL, and contains the primary name.
 *
 * Many modules provide a "default" command, which is a command
 * that is run if only the module name is specified, followed
 * by a colon (i.e. "sym:"). The way this is implemented is to
 * give the desired default command an empty string as an alias.
 * Note that the primary name cannot be an empty string, only the
 * alias name.
 *
 * cmd_opts and cmd_args are each an array of elfedit_cmd_argdesc_t
 * structures, that describe the options and plain arguments accepted
 * by the command. These arrays are used to general help text for
 * the commands. The cmd_opts array is also used to provide command
 * completion for options. Both of these arrays are terminated by
 * a final NULL element (all fields zero).
 */
typedef struct {
	elfedit32_cmd_func_t	*cmd_func;	/* Implementation */
	elfedit32_cmdcpl_func_t	*cmd_cplfunc;	/* Completion function */
	const char		**cmd_name;	/* Cmd names (null term.) */
	elfedit_i18nhdl_t	cmd_desc;	/* Short desc. of cmd purpose */
	elfedit_i18nhdl_t	cmd_help;	/* Help text for the command */
	elfedit_cmd_optarg_t	*cmd_opt;	/* Options */
	elfedit_cmd_optarg_t	*cmd_args;	/* Plain arguments */
} elfedit32_cmd_t;

typedef struct {
	elfedit64_cmd_func_t	*cmd_func;
	elfedit64_cmdcpl_func_t	*cmd_cplfunc;
	const char		**cmd_name;
	elfedit_i18nhdl_t	cmd_desc;
	elfedit_i18nhdl_t	cmd_help;
	elfedit_cmd_optarg_t	*cmd_opt;
	elfedit_cmd_optarg_t	*cmd_args;
} elfedit64_cmd_t;

#ifdef _ELF64
#define	elfedit_cmd_t		elfedit64_cmd_t
#else
#define	elfedit_cmd_t		elfedit32_cmd_t
#endif



/*
 * elfedit modules version themselves so that we can alter the definition
 * of elfedit_module_t in a backward compatible way.
 */
typedef enum {
	ELFEDIT_VER_NONE = 0,
	ELFEDIT_VER_CURRENT = 1,
	ELFEDIT_VER_NUM = 2
} elfedit_module_version_t;


/*
 * Each module returns a pointer to an elfedit_module_t, describing
 * what commands the module provides.
 *
 * Note: mod_cmds is a NULL terminated array of command defs. This
 * means that the final element in the array should have all of its
 * fields set to NULL.
 *
 * The mod_i18nhdl_to_str function pointer is explained above
 * with the definition of elfedit_i18nhdl_t.
 */
typedef const char *(* elfedit_mod_i18nhdl_to_str_func_t)(elfedit_i18nhdl_t);

typedef struct {
	elfedit_module_version_t mod_version;	/* version */
	const char		*mod_name;	/* Name of module */
	elfedit_i18nhdl_t	mod_desc;	/* Short desc. of mod purpose */
	elfedit32_cmd_t		*mod_cmds;	/* Array of command defs */
						/* i18n -> (char *) fcn */
	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
} elfedit32_module_t;

typedef struct {
	elfedit_module_version_t mod_version;
	const char		*mod_name;
	elfedit_i18nhdl_t	mod_desc;
	elfedit64_cmd_t		*mod_cmds;
	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
} elfedit64_module_t;

#ifdef _ELF64
#define	elfedit_module_t	elfedit64_module_t
#else
#define	elfedit_module_t	elfedit32_module_t
#endif


/*
 * Each module is a sharable library, expected to provide a single global
 * function, named elfedit_init(), with the following prototype.
 */
typedef elfedit_module_t *elfedit_init_func_t(elfedit_module_version_t version);


/*
 * Prototype for elfedit_write(), and for outfunc argument
 * to elfedit_str_to_c_literal().
 */
typedef void elfedit_write_func_t(const void *ptr, size_t size);


/*
 * Core elfedit functions exported for use by modules
 */
extern void elfedit_command_usage(void);
extern void elfedit_cpl_command(void *cpldata);
extern void elfedit_cpl_match(void *cpldata, const char *str, int casefold);
extern void elfedit_cpl_ndx(void *cpldata, uint_t ndx);
extern void elfedit_elferr(const char *file, const char *libelf_rtn_name);
extern elfedit_flag_t elfedit_flags(void);
extern void *elfedit_malloc(const char *item_name, size_t size);
extern void elfedit_msg(elfedit_msg_t type, const char *format, ...);
extern elfedit_outstyle_t elfedit_outstyle(void);
extern void elfedit_pager_init(void);
extern void elfedit_printf(const char *format, ...);
extern void *elfedit_realloc(const char *item_name, void *ptr, size_t size);
extern void elfedit_str_to_c_literal(const char *str,
    elfedit_write_func_t *outfunc);
extern elfedit_write_func_t elfedit_write;

/*
 * Core elfedit functions exported for use by sys: module only
 */
extern void elfedit_cpl_module(void *cpldata, int load_all_modules);


/*
 * elfedit modules are expected to define two functions, one for
 * each ELFCLASS. Define a generic name for this function, based on
 * the class being supported by the including module.
 */
#ifdef _ELF64
#define	elfedit_init		elfedit64_init
#else
#define	elfedit_init		elfedit32_init
#endif



/*
 * It is common to search the dynamic section for specific elements.
 * Structures of this type are used to represent the contents of such
 * elements in a systematic way. The elfedit_dyn_elt_init() function
 * is used to prepare these strucutres for use.
 */
typedef struct {
	int		dn_seen;	/* True if this item has been seen */
	Elf32_Word	dn_ndx;		/* Index of item in dynamic array */
	Elf32_Dyn	dn_dyn;		/* Contents of dynamic item */
} elfedit32_dyn_elt_t;

typedef struct {
	int		dn_seen;
	Elf64_Word	dn_ndx;
	Elf64_Dyn	dn_dyn;
} elfedit64_dyn_elt_t;

#ifdef _ELF64
#define	elfedit_dyn_elt_t	elfedit64_dyn_elt_t
#else
#define	elfedit_dyn_elt_t	elfedit32_dyn_elt_t
#endif

/*
 * The elfedit_atoi() and elfedit_atoui() functions can optionally
 * accept an array of these structures, giving symbolic names that
 * will be accepted instead of numeric codes. If such an array is
 * present, the supplied string has it's leading and trailing whitespace
 * removed and is then compared to the list, and if there is a match,
 * the corresponding integer value is returned.
 *
 * The final array element must have its name field set to NULL.
 */
typedef u_longlong_t elfedit_atoui_t;
typedef struct {
	const char	*sym_name;
	elfedit_atoui_t	sym_value;
} elfedit_atoui_sym_t;
typedef longlong_t elfedit_atoi_t;
typedef struct {
	const char	*sym_name;
	elfedit_atoi_t	sym_value;
} elfedit_atoi_sym_t;


/*
 * The elfedit_atoconst*() functions are built on top of the atoui routines.
 * These routines accept an elfedit_const_t code instead of a
 * pointer to an elfedit_atoui_sym_t array, and use internally
 * predefined tables of elfedit_atoui_sym_t in order to do the desired
 * mappings. elfedit modules are encouraged to use these standard
 * tables instead of defining their own elfedit_atoui_sym_t arrays.
 *
 * note:
 *	- The values assigned here must be in agreement with the
 *		sym_table[] array defined in elfconst.c.
 *	- Once defined, these values must not change. Reordering the
 *		list will require all modules to be rebuilt, and will
 *		break backward compatability. New items should be
 *		added to the end.
 */
typedef enum {
	ELFEDIT_CONST_OUTSTYLE =	0,	/* elfedit output styles  */
	ELFEDIT_CONST_OUTSTYLE_MO =	1,	/* ostyles with -o prefix */
	ELFEDIT_CONST_BOOL =		2,	/* boolean names */
	ELFEDIT_CONST_SHT_STRTAB =	3,	/* ELF SHT_STRTAB */
	ELFEDIT_CONST_SHT_SYMTAB =	4,	/* ELF SHT_SYMTAB */
	ELFEDIT_CONST_SHT_DYNSYM =	5,	/* ELF SHT_DYNSYM */
	ELFEDIT_CONST_SHT_LDYNSYM =	6,	/* ELF SHT_SUNW_LDYNSYM */
	ELFEDIT_CONST_SHN =		7,	/* ELF SHN_ section indexes  */
	ELFEDIT_CONST_SHT =		8,	/* ELF SHT_ section types  */
	ELFEDIT_CONST_SHT_ALLSYMTAB =	9,	/* ELF SHT_ symbol table */
						/*	section types */
	ELFEDIT_CONST_DT =		10,	/* Dynamic tags: DT_ */
	ELFEDIT_CONST_DF =		11,	/* DT_FLAGS bits */
	ELFEDIT_CONST_DF_P1 =		12,	/* DF_POSFLAG_1 bits */
	ELFEDIT_CONST_DF_1 =		13,	/* DT_FLAGS_1 bits */
	ELFEDIT_CONST_DTF_1 =		14,	/* DT_FEATURE_1 bits */
	ELFEDIT_CONST_EI =		15,	/* ELF header e_ident indexes */
	ELFEDIT_CONST_ET =		16,	/* Ehdr obj type */
	ELFEDIT_CONST_ELFCLASS =	17,	/* Ehdr wordsize (32,64) */
	ELFEDIT_CONST_ELFDATA =		18,	/* Ehdr endian */
	ELFEDIT_CONST_EF =		19,	/* Ehdr flags */
	ELFEDIT_CONST_EV =		20,	/* Ehdr version */
	ELFEDIT_CONST_EM =		21,	/* Ehdr machine */
	ELFEDIT_CONST_ELFOSABI =	22,	/* Ehdr ABI */
	ELFEDIT_CONST_EAV =		23,	/* Ehdr ABI version */
	ELFEDIT_CONST_PT =		24,	/* Phdr type */
	ELFEDIT_CONST_PF =		25,	/* Phdr flags */
	ELFEDIT_CONST_SHF =		26,	/* Shdr flags */
	ELFEDIT_CONST_STB =		27,	/* Sym binding */
	ELFEDIT_CONST_STT =		28,	/* Sym type */
	ELFEDIT_CONST_STV =		29,	/* Sym visibility */
	ELFEDIT_CONST_SYMINFO_BT =	30,	/* Syminfo boundto */
	ELFEDIT_CONST_SYMINFO_FLG =	31,	/* Syminfo flags */
	ELFEDIT_CONST_CA =		32,	/* Capabilities tags */
	ELFEDIT_CONST_HW1_SUNW =	33,	/* hardware capabilities */
	ELFEDIT_CONST_SF1_SUNW =	34,	/* software capabilities */
	ELFEDIT_CONST_HW2_SUNW =	35,	/* hardware capabilities */

	ELFEDIT_CONST_NUM =		36,	/* # of constant types */
} elfedit_const_t;

/*
 * Given an elfedit_const_t, return the array of elfedit_atoui_sym_t
 * entries that it represents.
 */
extern elfedit_atoui_sym_t *elfedit_const_to_atoui(elfedit_const_t const_type);

/*
 * ato[u]i and const routines, used to turn strings into numeric values,
 * with support for mapping symbol names to numbers, and range checking.
 */
extern elfedit_atoi_t elfedit_atoi(const char *str,
    const elfedit_atoi_sym_t *sym);
extern elfedit_atoui_t elfedit_atoui(const char *str,
    const elfedit_atoui_sym_t *sym);
extern elfedit_atoui_t elfedit_atoconst(const char *str,
    elfedit_const_t const_type);

extern int elfedit_atoi2(const char *str, const elfedit_atoi_sym_t *sym,
    elfedit_atoi_t *v);
extern int elfedit_atoui2(const char *str, const elfedit_atoui_sym_t *sym,
    elfedit_atoui_t *);
extern int elfedit_atoconst2(const char *str, elfedit_const_t const_type,
    elfedit_atoui_t *);

extern elfedit_atoi_t elfedit_atoi_range(const char *str,
    const char *item_name, elfedit_atoi_t min, elfedit_atoi_t max,
    const elfedit_atoi_sym_t *sym);
extern elfedit_atoui_t elfedit_atoui_range(const char *str,
    const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
    const elfedit_atoui_sym_t *sym);
extern elfedit_atoui_t elfedit_atoconst_range(const char *str,
    const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
    elfedit_const_t const_type);

extern int elfedit_atoi_range2(const char *str, elfedit_atoi_t min,
    elfedit_atoi_t max, const elfedit_atoi_sym_t *sym, elfedit_atoi_t *v);
extern int elfedit_atoui_range2(const char *str, elfedit_atoui_t min,
    elfedit_atoui_t max, const elfedit_atoui_sym_t *sym, elfedit_atoui_t *v);
extern int elfedit_atoconst_range2(const char *str, elfedit_atoui_t min,
    elfedit_atoui_t max, elfedit_const_t const_type, elfedit_atoui_t *v);

extern const char *elfedit_atoi_value_to_str(const elfedit_atoi_sym_t *sym,
    elfedit_atoi_t value, int required);
extern const char *elfedit_atoui_value_to_str(const elfedit_atoui_sym_t *sym,
    elfedit_atoui_t value, int required);
extern const char *elfedit_atoconst_value_to_str(elfedit_const_t const_type,
    elfedit_atoui_t value, int required);

extern void elfedit_cpl_atoi(void *cpldata, const elfedit_atoi_sym_t *sym);
extern void elfedit_cpl_atoui(void *cpldata, const elfedit_atoui_sym_t *sym);
extern void elfedit_cpl_atoconst(void *cpldata, elfedit_const_t const_type);


/*
 * Convenience functions built on top of the ato[u]i routines.
 */
extern int elfedit_atobool(const char *str, const char *item_name);
extern elfedit_atoui_t elfedit_atoshndx(const char *str, size_t shnum);


/*
 * elfedit provides a getopt utility for use by the module commands.
 * elfedit_getopt_state_t is the state block used by elfedit_getopt().
 * elfedit_getopt_ret_t is the definition of the values returned to
 * the user by elfedit_getopt() when an option is matched. Elfedit
 * getopt processing is done as follows:
 *
 * 1) The caller initializes an elfedit_getopt_state_t struct via
 *	a call to elfedit_getopt_init(). The contents of this structure
 *	must not be accessed by the caller, as they are all private and
 *	subject to change.
 * 2) Repeated calls are made to elfedit_getopt(), as long as it returns
 *	a non-NULL pointer to an elfedit_getopt_ret_t structure. If the
 *	matched option has a value (ELFEDIT_CMDOA_F_VALUE), then the gor_value
 *	field contains the pointer to the string. Otherwise, gor_value is NULL.
 * 3) As elfedit_getopt() consumes optional arguments from the argc/argv
 *	passed to elfedit_getopt_init(), it adjusts argc/argc to skip over
 *	them. Once elfedit_getopt() returns NULL to indicate that there are no
 *	more options to match, argc/argv have been adjusted so that they
 *	reference the plain arguments.
 */
typedef struct {
	elfedit_cmd_oa_mask_t gor_idmask;	/* oa_idmask from matching */
					/*	elfedit_cmd_optarg_t. Can be */
					/*	used to quickly identify opt */
	const char	*gor_value;	/* Opt value if ELFEDIT_CMDOA_F_VALUE */
					/*	Otherwise, NULL */
} elfedit_getopt_ret_t;
typedef struct {
	int			*go_argc;	/* Pointer to # of options */
	const char		***go_argv;	/* Ptr to array of opt strs */
	elfedit_cmd_optarg_t	*go_optarg;	/* Array of allowed options */
	elfedit_cmd_oa_mask_t	go_idmask;	/* Combined id masks of all */
						/*	seen options */
	int			go_done;	/* True if last option seen */
	const char		*go_sglgrp;	/* Group of 1-letter opts */
	elfedit_getopt_ret_t	go_ret;		/* Data returned to user */
} elfedit_getopt_state_t;



/*
 * getopt related routines
 */
extern void elfedit_getopt_init(elfedit_getopt_state_t *,
    int *, const char ***);
extern elfedit_getopt_ret_t *elfedit_getopt(elfedit_getopt_state_t *);



/*
 * Additional utility functions exported for use by modules
 */
extern void elfedit_array_elts_delete(const char *name_str, void *data_start,
    size_t entsize, size_t num_ent, size_t start_ndx, size_t cnt);

extern void elfedit_array_elts_move(const char *name_str, void *data_start,
    size_t entsize, size_t num_ent, size_t srcndx,
    size_t dstndx, size_t cnt, void *scr_item);

extern int elfedit_bits_set(u_longlong_t v, int sizeof_orig_v);

extern void elfedit32_dyn_elt_init(elfedit32_dyn_elt_t *dyn_elt);
extern void elfedit64_dyn_elt_init(elfedit64_dyn_elt_t *dyn_elt);

extern void elfedit32_dyn_elt_save(elfedit32_dyn_elt_t *elt, Elf32_Word ndx,
    Elf32_Dyn *dyn);
extern void elfedit64_dyn_elt_save(elfedit64_dyn_elt_t *elt, Elf64_Word ndx,
    Elf64_Dyn *dyn);

const char *elfedit32_dyn_offset_to_str(elfedit32_section_t *strsec,
    elfedit32_dyn_elt_t *dynelt);
const char *elfedit64_dyn_offset_to_str(elfedit64_section_t *strsec,
    elfedit64_dyn_elt_t *dynelt);

extern int elfedit32_dynstr_getpad(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *dynsec, elfedit32_dyn_elt_t *dyn_strpad);
extern int elfedit64_dynstr_getpad(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *dynsec, elfedit64_dyn_elt_t *dyn_strpad);

extern Elf32_Word elfedit32_dynstr_insert(elfedit32_section_t *dynsec,
    elfedit32_section_t *strsec, elfedit32_dyn_elt_t *dyn_strpad,
    const char *str);
extern Elf64_Word elfedit64_dynstr_insert(elfedit64_section_t *dynsec,
    elfedit64_section_t *strsec, elfedit64_dyn_elt_t *dyn_strpad,
    const char *str);

extern void elfedit32_modified_data(elfedit32_section_t *s);
extern void elfedit64_modified_data(elfedit64_section_t *s);

extern void elfedit32_modified_ehdr(elfedit32_obj_state_t *obj_state);
extern void elfedit64_modified_ehdr(elfedit64_obj_state_t *obj_state);

extern void elfedit32_modified_phdr(elfedit32_obj_state_t *obj_state);
extern void elfedit64_modified_phdr(elfedit64_obj_state_t *obj_state);

extern void elfedit32_modified_shdr(elfedit32_section_t *s);
extern void elfedit64_modified_shdr(elfedit64_section_t *s);

extern Elf32_Word elfedit32_name_to_shndx(elfedit32_obj_state_t *obj_state,
    const char *shnam);
extern Elf64_Word elfedit64_name_to_shndx(elfedit64_obj_state_t *obj_state,
    const char *shnam);

extern int elfedit32_name_to_symndx(elfedit32_section_t *symsec,
    elfedit32_section_t *strsec, const char *name, elfedit_msg_t msg_type,
    Elf32_Word *ret_symndx);
extern int elfedit64_name_to_symndx(elfedit64_section_t *symsec,
    elfedit64_section_t *strsec, const char *name, elfedit_msg_t msg_type,
    Elf64_Word *ret_symndx);

extern const char *elfedit32_offset_to_str(elfedit32_section_t *strsec,
    Elf32_Word offset, elfedit_msg_t msg_type, int debug_msg);
extern const char *elfedit64_offset_to_str(elfedit64_section_t *strsec,
    Elf64_Word offset, elfedit_msg_t msg_type, int debug_msg);

extern int elfedit32_sec_findstr(elfedit32_section_t *sec, Elf32_Word tail_ign,
    const char *str, Elf32_Word *ret_offset);
extern int elfedit64_sec_findstr(elfedit64_section_t *sec, Elf64_Word tail_ign,
    const char *str, Elf64_Word *ret_offset);

extern elfedit32_section_t *elfedit32_sec_get(
    elfedit32_obj_state_t *obj_state, Elf32_Word shndx);
extern elfedit64_section_t *elfedit64_sec_get(
    elfedit64_obj_state_t *obj_state, Elf64_Word shndx);

extern elfedit32_section_t *elfedit32_sec_getcap(
    elfedit32_obj_state_t *obj_state, Elf32_Cap **cap, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getcap(
    elfedit64_obj_state_t *obj_state, Elf64_Cap **cap, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getdyn(
    elfedit32_obj_state_t *obj_state, Elf32_Dyn **dyn, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getdyn(
    elfedit64_obj_state_t *obj_state, Elf64_Dyn **dyn, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getstr(
    elfedit32_obj_state_t *obj_state, Elf32_Word shndx, int);
extern elfedit64_section_t *elfedit64_sec_getstr(
    elfedit64_obj_state_t *obj_state, Elf64_Word shndx, int);

extern elfedit32_section_t *elfedit32_sec_getsyminfo(
    elfedit32_obj_state_t *obj_state, Elf32_Syminfo **syminfo, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getsyminfo(
    elfedit64_obj_state_t *obj_state, Elf64_Syminfo **syminfo, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getsymtab(
    elfedit32_obj_state_t *obj_state, int by_index, Elf32_Word index,
    const char *name, Elf32_Sym **sym, Elf32_Word *num,
    elfedit32_symtab_t **aux_info);
extern elfedit64_section_t *elfedit64_sec_getsymtab(
    elfedit64_obj_state_t *obj_state, int by_index, Elf64_Word index,
    const char *name, Elf64_Sym **sym, Elf64_Word *num,
    elfedit64_symtab_t **aux_info);

extern elfedit32_section_t *elfedit32_sec_getversym(
    elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
    Elf32_Versym **versym, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getversym(
    elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
    Elf64_Versym **versym, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getxshndx(
    elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
    Elf32_Word **xshndx, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getxshndx(
    elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
    Elf64_Word **xshndx, Elf64_Word *num);

extern int elfedit32_sec_issymtab(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);
extern int elfedit64_sec_issymtab(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);

extern const char *elfedit32_sec_msgprefix(elfedit32_section_t *sec);
extern const char *elfedit64_sec_msgprefix(elfedit64_section_t *sec);

extern const char *elfedit32_shndx_to_name(elfedit32_obj_state_t *obj_state,
    Elf32_Word shndx);
extern const char *elfedit64_shndx_to_name(elfedit64_obj_state_t *obj_state,
    Elf64_Word shndx);

extern Elf32_Word elfedit32_strtab_insert(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
extern Elf64_Word elfedit64_strtab_insert(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);

extern void elfedit32_strtab_insert_test(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
extern void elfedit64_strtab_insert_test(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);

extern int elfedit32_test_osabi(elfedit32_obj_state_t *obj_state, uchar_t osabi,
    int issue_err);
extern int elfedit64_test_osabi(elfedit64_obj_state_t *obj_state, uchar_t osabi,
    int issue_err);

extern Elf32_Word elfedit32_type_to_shndx(elfedit32_obj_state_t *obj_state,
    Elf32_Word shtype);
extern Elf64_Word elfedit64_type_to_shndx(elfedit64_obj_state_t *obj_state,
    Elf64_Word shtype);



/*
 * Map the generic names for each of the ELFCLASS specific routines
 * above to reference the proper routine for the current compilation.
 */
#ifdef _ELF64
#define	elfedit_dyn_elt_init		elfedit64_dyn_elt_init
#define	elfedit_dyn_elt_save		elfedit64_dyn_elt_save
#define	elfedit_dyn_offset_to_str	elfedit64_dyn_offset_to_str
#define	elfedit_dynstr_getpad		elfedit64_dynstr_getpad
#define	elfedit_dynstr_insert		elfedit64_dynstr_insert
#define	elfedit_modified_data		elfedit64_modified_data
#define	elfedit_modified_ehdr		elfedit64_modified_ehdr
#define	elfedit_modified_phdr		elfedit64_modified_phdr
#define	elfedit_modified_shdr		elfedit64_modified_shdr
#define	elfedit_name_to_shndx		elfedit64_name_to_shndx
#define	elfedit_name_to_symndx		elfedit64_name_to_symndx
#define	elfedit_offset_to_str		elfedit64_offset_to_str
#define	elfedit_sec_findstr		elfedit64_sec_findstr
#define	elfedit_sec_get			elfedit64_sec_get
#define	elfedit_sec_getcap		elfedit64_sec_getcap
#define	elfedit_sec_getdyn		elfedit64_sec_getdyn
#define	elfedit_sec_getstr		elfedit64_sec_getstr
#define	elfedit_sec_getsyminfo		elfedit64_sec_getsyminfo
#define	elfedit_sec_getsymtab		elfedit64_sec_getsymtab
#define	elfedit_sec_getversym		elfedit64_sec_getversym
#define	elfedit_sec_getxshndx		elfedit64_sec_getxshndx
#define	elfedit_sec_issymtab		elfedit64_sec_issymtab
#define	elfedit_shndx_to_name		elfedit64_shndx_to_name
#define	elfedit_sec_msgprefix		elfedit64_sec_msgprefix
#define	elfedit_strtab_insert		elfedit64_strtab_insert
#define	elfedit_strtab_insert_test	elfedit64_strtab_insert_test
#define	elfedit_test_osabi		elfedit64_test_osabi
#define	elfedit_type_to_shndx		elfedit64_type_to_shndx
#else
#define	elfedit_dyn_elt_init		elfedit32_dyn_elt_init
#define	elfedit_dyn_elt_save		elfedit32_dyn_elt_save
#define	elfedit_dyn_offset_to_str	elfedit32_dyn_offset_to_str
#define	elfedit_dynstr_getpad		elfedit32_dynstr_getpad
#define	elfedit_dynstr_insert		elfedit32_dynstr_insert
#define	elfedit_modified_data		elfedit32_modified_data
#define	elfedit_modified_ehdr		elfedit32_modified_ehdr
#define	elfedit_modified_phdr		elfedit32_modified_phdr
#define	elfedit_modified_shdr		elfedit32_modified_shdr
#define	elfedit_name_to_shndx		elfedit32_name_to_shndx
#define	elfedit_name_to_symndx		elfedit32_name_to_symndx
#define	elfedit_offset_to_str		elfedit32_offset_to_str
#define	elfedit_sec_findstr		elfedit32_sec_findstr
#define	elfedit_sec_get			elfedit32_sec_get
#define	elfedit_sec_getcap		elfedit32_sec_getcap
#define	elfedit_sec_getdyn		elfedit32_sec_getdyn
#define	elfedit_sec_getstr		elfedit32_sec_getstr
#define	elfedit_sec_getsyminfo		elfedit32_sec_getsyminfo
#define	elfedit_sec_getsymtab		elfedit32_sec_getsymtab
#define	elfedit_sec_getversym		elfedit32_sec_getversym
#define	elfedit_sec_getxshndx		elfedit32_sec_getxshndx
#define	elfedit_sec_issymtab		elfedit32_sec_issymtab
#define	elfedit_shndx_to_name		elfedit32_shndx_to_name
#define	elfedit_sec_msgprefix		elfedit32_sec_msgprefix
#define	elfedit_strtab_insert		elfedit32_strtab_insert
#define	elfedit_strtab_insert_test	elfedit32_strtab_insert_test
#define	elfedit_test_osabi		elfedit32_test_osabi
#define	elfedit_type_to_shndx		elfedit32_type_to_shndx
#endif


#ifdef	__cplusplus
}
#endif

#endif	/* _ELFEDIT_H */