xref: /onnv-gate/usr/src/cmd/sgs/include/elfedit.h (revision 11827:d7ef53deac3f)
15088Sab196087 /*
25088Sab196087  * CDDL HEADER START
35088Sab196087  *
45088Sab196087  * The contents of this file are subject to the terms of the
55088Sab196087  * Common Development and Distribution License (the "License").
65088Sab196087  * You may not use this file except in compliance with the License.
75088Sab196087  *
85088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95088Sab196087  * or http://www.opensolaris.org/os/licensing.
105088Sab196087  * See the License for the specific language governing permissions
115088Sab196087  * and limitations under the License.
125088Sab196087  *
135088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185088Sab196087  *
195088Sab196087  * CDDL HEADER END
205088Sab196087  */
215088Sab196087 
225088Sab196087 /*
2311734SAli.Bahrami@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 
275088Sab196087 #ifndef	_ELFEDIT_H
285088Sab196087 #define	_ELFEDIT_H
295088Sab196087 
305088Sab196087 #include	<stdio.h>
315088Sab196087 #include	<stdlib.h>
325088Sab196087 #include	<sys/types.h>
335088Sab196087 #include	<libelf.h>
345088Sab196087 #include	<stdarg.h>
355088Sab196087 
365088Sab196087 /* The following are here to support use of elfedit_msg() */
375088Sab196087 #include	<sys/machelf.h>		/* EC_ macros */
385088Sab196087 #include	<libintl.h>
395088Sab196087 
405088Sab196087 #ifdef	__cplusplus
415088Sab196087 extern "C" {
425088Sab196087 #endif
435088Sab196087 
445088Sab196087 
455088Sab196087 /*
465088Sab196087  * elfedit uses elfedit_printf() to produce generic output to stdout.
475088Sab196087  * elfedit_msg() is used to produce error message, or specific types
485088Sab196087  * of terse informational messages:
495088Sab196087  *
505088Sab196087  *	ELFEDIT_MSG_ERR:
515088Sab196087  *		Issues an error to stderr. elfedit_msg() does not return
525088Sab196087  *		to the caller. Control returns to the outer loop in
535088Sab196087  *		interactive use. elfedit exits in non-interactive use.
545088Sab196087  *
555088Sab196087  *	ELFEDIT_MSG_FATAL:
565088Sab196087  *		Issues an error to stderr. elfedit_msg() exits the process,
575088Sab196087  *		and does not return to the caller.
585088Sab196087  *
595088Sab196087  *	ELFEDIT_MSG_USAGE:
605088Sab196087  *		Issues an elfedit usage message to stderr, and
615088Sab196087  *		returns to the caller.
625088Sab196087  *
635088Sab196087  *	ELFEDIT_MSG_CMDUSAGE
645088Sab196087  *		Issues an elfedit usage message to stderr, and
655088Sab196087  *		does not return to the caller.
665088Sab196087  *
675088Sab196087  *	ELFEDIT_MSG_DEBUG
685088Sab196087  *		If the ELFEDIT_F_DEBUG flag is set, the message
695088Sab196087  *		is printed to stdout, otherwise no output is produced.
705088Sab196087  *		elfedit_msg() returns to the caller.
715088Sab196087  *
725088Sab196087  *	ELFEDIT_MSG_QUIET
735088Sab196087  *		This is a very special case, intended to handle the
745088Sab196087  *		case where the pager subprocess exits before we are
755088Sab196087  *		done producing output (the user presses 'q'). It acts
765088Sab196087  *		just like ELFEDIT_MSG_ERR, except that no message is
775088Sab196087  *		actually printed.
785088Sab196087  *
795088Sab196087  * In the cases where elfedit_msg() does not return to the caller, the
805088Sab196087  * behavior depends on the mode of execution. If running in interactive
815088Sab196087  * mode (reading from a tty), control is returned directly to the outer
825088Sab196087  * elfedit control loop to read another command. If not running in interactive
835088Sab196087  * mode, elfedit exits with a non-zero status.
845088Sab196087  */
855088Sab196087 typedef enum {
865088Sab196087 	ELFEDIT_MSG_ERR = 0,
875088Sab196087 	ELFEDIT_MSG_FATAL = 1,
885088Sab196087 	ELFEDIT_MSG_USAGE = 2,
895088Sab196087 	ELFEDIT_MSG_CMDUSAGE = 3,
905088Sab196087 	ELFEDIT_MSG_DEBUG = 4,
915088Sab196087 	ELFEDIT_MSG_QUIET = 5
925088Sab196087 } elfedit_msg_t;
935088Sab196087 
945088Sab196087 
955088Sab196087 /*
965088Sab196087  * Information for a single ELF section.
975088Sab196087  *
985088Sab196087  * NOTE: sec_xshndx
995088Sab196087  *	A symbol table can have an associated SHT_SYMTAB_SHNDX section. This
1005088Sab196087  *	happens when the number of sections is too large to fit in the
1015088Sab196087  *	ELF symbol st_shndx field, which is a 16-bit value. The sec_xshndx
1025088Sab196087  *	field will be SHN_UNDEF if there is no such section, and will be
1035088Sab196087  *	the section index of the extended section index section assocated
1045088Sab196087  *	with the symbol table otherwise.
1055088Sab196087  *
1065088Sab196087  * NOTE: sec_versym
1075088Sab196087  *	Symbol table sections can have an SHT_SUNW_VERSYM section that
1085088Sab196087  *	contains its version indices. Other types of section will have
1095088Sab196087  *	this field set to SHN_UNDEF.
1105088Sab196087  */
1115088Sab196087 typedef struct {
1125088Sab196087 	Elf32_Word	sec_shndx;	/* Section index */
1135088Sab196087 	Elf_Scn		*sec_scn;	/* Section descriptor */
1145088Sab196087 	Elf32_Shdr	*sec_shdr;	/* Section header */
1155088Sab196087 	Elf_Data	*sec_data;	/* Data region of section */
1165088Sab196087 	const char	*sec_name;	/* Name of section */
1175088Sab196087 } elfedit32_section_t;
1185088Sab196087 
1195088Sab196087 typedef struct {
1205088Sab196087 	Elf64_Word	sec_shndx;
1215088Sab196087 	Elf_Scn		*sec_scn;
1225088Sab196087 	Elf64_Shdr	*sec_shdr;
1235088Sab196087 	Elf_Data	*sec_data;
1245088Sab196087 	const char	*sec_name;
1255088Sab196087 } elfedit64_section_t;
1265088Sab196087 
1275088Sab196087 #ifdef _ELF64
1285088Sab196087 #define	elfedit_section_t	elfedit64_section_t
1295088Sab196087 #else
1305088Sab196087 #define	elfedit_section_t	elfedit32_section_t
1315088Sab196087 #endif
1325088Sab196087 
1335088Sab196087 
1345088Sab196087 /*
1355088Sab196087  * We maintain extra information for symbol tables. We look them
1365088Sab196087  * up frequently, so we want to eliminate expensive linear searches
1375088Sab196087  * of the entire section header array. Also, symbol tables usually
1385088Sab196087  * have associated parallal sections (syminfo, versym, extended indexes, etc)
1395088Sab196087  * and we want to eliminate repeated linear lookups for them, as well as
1405088Sab196087  * the basic error checking that is necessary to ensure they match the
1415088Sab196087  * symbol table they're given.
1425088Sab196087  *
1435088Sab196087  * This extra information is kept in elfedit_symtab_t structs. Each field
1445088Sab196087  * is a section index, with SHN_UNDEF used for those that do not apply.
1455088Sab196087  */
1465088Sab196087 typedef struct {
1475088Sab196087 	Elf32_Word	symt_shndx;	/* Symbol table section index */
1485088Sab196087 	Elf32_Word	symt_xshndx;	/* Index of extended index section */
1495088Sab196087 	Elf32_Word	symt_syminfo;	/* Index of versym section */
1505088Sab196087 	Elf32_Word	symt_versym;	/* Index of versym section */
1515088Sab196087 } elfedit32_symtab_t;
1525088Sab196087 
1535088Sab196087 typedef struct {
1545088Sab196087 	Elf64_Word	symt_shndx;
1555088Sab196087 	Elf64_Word	symt_xshndx;
1565088Sab196087 	Elf64_Word	symt_versym;
1575088Sab196087 	Elf64_Word	symt_syminfo;
1585088Sab196087 } elfedit64_symtab_t;
1595088Sab196087 
1605088Sab196087 #ifdef _ELF64
1615088Sab196087 #define	elfedit_symtab_t	elfedit64_symtab_t
1625088Sab196087 #else
1635088Sab196087 #define	elfedit_symtab_t	elfedit32_symtab_t
1645088Sab196087 #endif
1655088Sab196087 
1665088Sab196087 
1675088Sab196087 /*
1685088Sab196087  * Information for a single ELF object.
1695088Sab196087  *
1705088Sab196087  * note:
1715088Sab196087  *	elfedit is intended to be an expert's tool, capable of modifying
1725088Sab196087  *	nearly everything in the file, whether or not such modifications
1735088Sab196087  *	are a good idea. At the same time, elfedit, via libelf, relies
1745088Sab196087  *	on the contents of the object to properly locate information in
1755088Sab196087  *	the file. As this is the same information that elfedit allows the
1765088Sab196087  *	user to modify, it should be obvious that the potential exists
1775088Sab196087  *	for users to corrupt the file to the degree that elfedit itself
1785088Sab196087  *	may fail, or produce spurious results. We allow such changes for
1795088Sab196087  *	several reasons:
1805088Sab196087  *
1815088Sab196087  *	1) Such corruption does not happen in the most obvious and
1825088Sab196087  *		useful operations elfedit supports, but comes as a result
1835088Sab196087  *		of modifying fields that contain size and offset information
1845088Sab196087  *		used to navigate the file. Non-ELF developers have
1855088Sab196087  *		little practical reason to change such things.
1865088Sab196087  *
1875088Sab196087  *	2) Producing a corrupt ELF file can be very useful
1885088Sab196087  *		for R&D and/or testing purposes.
1895088Sab196087  *
1905088Sab196087  *	3) ELF is sufficiently complex that no absolute guarantees can
1915088Sab196087  *		be made about "safe" operations, beyond the basic
1925088Sab196087  *		and obvious things that are of practical use.
1935088Sab196087  *
1945088Sab196087  *	One way we protect ourselves is via the information cached in
1955088Sab196087  *	the elfedit_obj_state_t structure at startup. By using this
1965088Sab196087  *	information, rather than constantly fetching it via libelf,
1975088Sab196087  *	we protect ourselves against many user changes, such as changing the
1985088Sab196087  *	program or section header offsets, or similar size/position fields.
1995088Sab196087  *
2005088Sab196087  *	Of course, we make no assurances that that we will be able to
2015088Sab196087  *	read the resulting file in a subsequent session.
2025088Sab196087  */
2035088Sab196087 typedef struct {
2045088Sab196087 	const char		*os_file;	/* Path to ELF file */
2055088Sab196087 	int			os_fd;		/* Open file descriptor */
2065088Sab196087 	Elf			*os_elf;	/* ELF descriptor */
2075088Sab196087 	Elf32_Ehdr		*os_ehdr;	/* ELF header */
2085088Sab196087 	Elf32_Word		os_dynndx;	/* Index of dynamic section */
2095088Sab196087 	size_t			os_shstrndx;	/* Index of section header */
2105088Sab196087 						/*	string table section */
2115088Sab196087 	size_t			os_shnum;	/* # of sections in file */
2125088Sab196087 	elfedit32_section_t	*os_secarr;	/* Section data */
2135088Sab196087 	size_t			os_phnum;	/* # of program headers */
2145088Sab196087 	Elf32_Phdr		*os_phdr;	/* Program header array */
2155088Sab196087 	size_t			os_symtabnum;	/* # items in os_symtab[] */
2165088Sab196087 	elfedit32_symtab_t	*os_symtab;	/* Array of symbol tbl info  */
2175088Sab196087 } elfedit32_obj_state_t;
2185088Sab196087 
2195088Sab196087 typedef struct {
2205088Sab196087 	const char		*os_file;
2215088Sab196087 	int			os_fd;
2225088Sab196087 	Elf			*os_elf;
2235088Sab196087 	Elf64_Ehdr		*os_ehdr;
2245088Sab196087 	Elf64_Word		os_dynndx;
2255088Sab196087 	size_t			os_shstrndx;
2265088Sab196087 	size_t			os_shnum;
2275088Sab196087 	elfedit64_section_t	*os_secarr;
2285088Sab196087 	size_t			os_phnum;
2295088Sab196087 	Elf64_Phdr		*os_phdr;
2305088Sab196087 	size_t			os_symtabnum;
2315088Sab196087 	elfedit64_symtab_t	*os_symtab;
2325088Sab196087 } elfedit64_obj_state_t;
2335088Sab196087 
2345088Sab196087 #ifdef _ELF64
2355088Sab196087 #define	elfedit_obj_state_t	elfedit64_obj_state_t
2365088Sab196087 #else
2375088Sab196087 #define	elfedit_obj_state_t	elfedit32_obj_state_t
2385088Sab196087 #endif
2395088Sab196087 
2405088Sab196087 
2415088Sab196087 /*
2425088Sab196087  * Bit values for editor state.
2435088Sab196087  */
2445088Sab196087 typedef enum {
2455088Sab196087 	ELFEDIT_F_AUTOPRINT = 1, /* Print informational text about edits */
2465088Sab196087 	ELFEDIT_F_DEBUG = 2,	/* Print informational text about operations */
2475088Sab196087 	ELFEDIT_F_READONLY = 4,	/* File is processed readonly */
2485088Sab196087 } elfedit_flag_t;
2495088Sab196087 
2505088Sab196087 /*
2515088Sab196087  * Type used to represent the output style for printing ELF values.
2525088Sab196087  *
2535088Sab196087  * DEFAULT - Output is in 'elfdump' style, designed for human eyes.
2545088Sab196087  *	Headers, and additional information are shown.
2555088Sab196087  * SIMPLE - Output is simple, consisting only of the target item.
2565088Sab196087  *	Integer values are shown as symbolic constants when possible,
2575088Sab196087  *	and integers otherwise.
2585088Sab196087  * NUM - Like SIMPLE, except integer values are always shown as
2595088Sab196087  *	integer constants, and strings are shown as the integer
2605088Sab196087  *	offset into the string table.
2615088Sab196087  */
2625088Sab196087 typedef enum {
2635088Sab196087 	ELFEDIT_OUTSTYLE_DEFAULT = 0,
2645088Sab196087 	ELFEDIT_OUTSTYLE_SIMPLE = 1,
2655088Sab196087 	ELFEDIT_OUTSTYLE_NUM = 2
2665088Sab196087 } elfedit_outstyle_t;
2675088Sab196087 
2685088Sab196087 
2695088Sab196087 /*
2705088Sab196087  * The elfedit_module_t, and the types it references, are defined
2715088Sab196087  * by loadable elfedit modules, and used by elfedit. These structures
2725088Sab196087  * need to communicate internationalized strings for elfedit to print.
2735088Sab196087  *
2745088Sab196087  * We want to leave the choice of internationalization APIs, as well as
2755088Sab196087  * the decision about whether or not to even to it to the individual
2765088Sab196087  * modules. Hence, we do not use a simple (const char *) pointer to
2775088Sab196087  * communicate potentially internationalized strings. Instead, we define
2785088Sab196087  * elfedit_i18nhdl_t, an opaque type guaranteed to be large enough
2795088Sab196087  * to hold a pointer. Each module casts the handle needed to access the
2805088Sab196087  * string to this type. Each module also supplies a function
2815088Sab196087  * (mod_i18nhdl_to_str field of elfedit_module_t) that given one
2825088Sab196087  * of these opaque keys, will return a (const char *) pointer to the
2835088Sab196087  * actual string, for elfedit to print.
2845088Sab196087  *
2855088Sab196087  * If the underlying module doesn't want to implement i18n support,
2865088Sab196087  * all it has to do is cast the strings to elfedit_i18nhdl_t and
2875088Sab196087  * back.
2885088Sab196087  */
2895088Sab196087 typedef uintptr_t elfedit_i18nhdl_t;
2905088Sab196087 
2915088Sab196087 
2925088Sab196087 
2935088Sab196087 /*
2945088Sab196087  * Macro to handle casting international string "handles" to the
2955088Sab196087  * elfedit_i18nhdl_t opaque type.
2965088Sab196087  */
2975088Sab196087 #define	ELFEDIT_I18NHDL(_i18n_str_ref) ((elfedit_i18nhdl_t)_i18n_str_ref)
2985088Sab196087 
2995088Sab196087 
3005088Sab196087 /*
3015088Sab196087  * Return values from command functions
3025088Sab196087  */
3035088Sab196087 typedef enum {
3045088Sab196087 	ELFEDIT_CMDRET_NONE = 0,	/* Nothing to report */
3055088Sab196087 	ELFEDIT_CMDRET_MOD = 1,		/* Command modified output ELF file */
3069273SAli.Bahrami@Sun.COM 	ELFEDIT_CMDRET_MOD_OS_MACH = 2, /* As per _MOD, include ELF header */
3079273SAli.Bahrami@Sun.COM 					/*	osabi or machine change */
3089273SAli.Bahrami@Sun.COM 	ELFEDIT_CMDRET_FLUSH = 3	/* Output file flushed: elf_update() */
3095088Sab196087 } elfedit_cmdret_t;
3105088Sab196087 
3115088Sab196087 /*
3125088Sab196087  * Prototype of an implementation function for an edit command. Note that
3135088Sab196087  * commands do not return a status:
3145088Sab196087  *	- Success is indicated by a normal return.
3155088Sab196087  *	- The command indicates a fatal error by calling elfedit_msg() with the
3165088Sab196087  *		ELFEDIT_MSG_ERR type, in which case execution does not return
3175088Sab196087  *		to the command, and the elfedit command loop knows that an
3185088Sab196087  *		error occurred.
3195088Sab196087  *	- The command is responsible for using the standard libelf
3205088Sab196087  *		mechanisms to indicate when changes have been made to
3215088Sab196087  *		the ELF file.
3225088Sab196087  */
3235088Sab196087 typedef elfedit_cmdret_t elfedit32_cmd_func_t(elfedit32_obj_state_t *state,
3245088Sab196087     int argc, const char *argv[]);
3255088Sab196087 typedef elfedit_cmdret_t elfedit64_cmd_func_t(elfedit64_obj_state_t *state,
3265088Sab196087     int argc, const char *argv[]);
3275088Sab196087 #ifdef _ELF64
3285088Sab196087 #define	elfedit_cmd_func_t	elfedit64_cmd_func_t
3295088Sab196087 #else
3305088Sab196087 #define	elfedit_cmd_func_t	elfedit32_cmd_func_t
3315088Sab196087 #endif
3325088Sab196087 
3335088Sab196087 
3345088Sab196087 /*
3355088Sab196087  * An elfedit command (elfedit_cmd_t) has a cmd_cpl field that
3365088Sab196087  * can be set to a command completion function. If such a function
3375088Sab196087  * is present (non-NULL), and the user presses the tab key at the
3385088Sab196087  * command line while the cursor is at a plain (non option) argument,
3395088Sab196087  * elfedit calls the function, passing it all the tokens up through
3405088Sab196087  * the one needing completion.  The function can use elfedit_cpl_match()
3415088Sab196087  * to enter possible alternatives.  Additionally, there are helper
3425088Sab196087  * functions built on top of elfedit_cpl_match() that simplify common cases.
3435088Sab196087  *
3445088Sab196087  *	elfedit_cpl_ato[iu]() - enter matches from elfedit_ato[iu]_sym_t
3455088Sab196087  *		mappings.
3465088Sab196087  *	elfedit_cpl_atoconst() - Enter matches for well known constants
3475088Sab196087  *	elfedit_cpl_command() - enter matches for all known commands
3485088Sab196087  *	elfedit_cpl_mod() - enter matches for all known modules.
3496225Sab196087  *	elfedit_cpl_ndx() - enter numeric index as a match
3505088Sab196087  *
3515088Sab196087  * The completion function is passed the following arguments:
3525088Sab196087  *
3535088Sab196087  *	obj_state - Object state. Will be NULL if elfedit session does not
3545088Sab196087  *		have an active object. The completion function must test
3555088Sab196087  *		the pointer before using it.
3565088Sab196087  *	cpldata - Completion data, to be passed to elfedit_cpl_match()
3575088Sab196087  *		or the helper functions built on it to register alternative
3585088Sab196087  *		strings.
35911734SAli.Bahrami@Sun.COM  *	argc, argv - The tokens from the start of the line through
3605088Sab196087  *		the one needing completion, which will always
3615088Sab196087  *		be cmdcpl_argv[cmdcpl_argc - 1].
3625088Sab196087  *	num_opt - A count of the optional arguments (those starting with
3635088Sab196087  *		'-' at the beginning of argv. This means that argv[num_opt]
3645088Sab196087  *		is the first plain argument, and the 1-based positional
3655088Sab196087  *		number of the plain argument for which command completion
3665088Sab196087  *		is needed is (argc - num_opt).
3675088Sab196087  */
3685088Sab196087 typedef void elfedit32_cmdcpl_func_t(elfedit32_obj_state_t *state,
3695088Sab196087     void *cpldata, int argc, const char *argv[], int num_opt);
3705088Sab196087 typedef void elfedit64_cmdcpl_func_t(elfedit64_obj_state_t *state,
3715088Sab196087     void *cpldata, int argc, const char *argv[], int num_opt);
3725088Sab196087 #ifdef _ELF64
3735088Sab196087 #define	elfedit_cmdcpl_func_t	elfedit64_cmdcpl_func_t
3745088Sab196087 #else
3755088Sab196087 #define	elfedit_cmdcpl_func_t	elfedit32_cmdcpl_func_t
3765088Sab196087 #endif
3775088Sab196087 
3785088Sab196087 
3795088Sab196087 
3805088Sab196087 
3815088Sab196087 /*
3825088Sab196087  * Command option/argument descriptor. These structures
3835088Sab196087  * are used to represent each option and plain argument accepted
3845088Sab196087  * by a command, via the cmd_opt and cmd_args fields in the
3855088Sab196087  * command definition (elfedit_cmd_t). Each descriptor consists
3865088Sab196087  * of a name, a help string (formatted for display via sys:help),
3875088Sab196087  * and a flags field that conveys extra information about the
3885088Sab196087  * item:
3895088Sab196087  *
3905088Sab196087  *	ELFEDIT_CMDOA_F_OPT
3915088Sab196087  *	The item is optional. This flag is implicit for options
3925088Sab196087  *	and need only be set for plain arguments.
3935088Sab196087  *
3945088Sab196087  *	ELFEDIT_CMDOA_F_VALUE
3955088Sab196087  *	The item has a value, which is found in the following
3965088Sab196087  *	item. This flag only has meaning for options, and should
3975088Sab196087  *	not be set for plain arguments. The descriptor for the
3985088Sab196087  *	value is found in the next array element, and only the
3995088Sab196087  *	oa_name field is used (the other should be set t 0).
4005088Sab196087  *
4015088Sab196087  *	ELFEDIT_CMDOA_F_MULT
4025088Sab196087  *	More than one of the specified items may be specified
4035088Sab196087  *
4045088Sab196087  *	ELFEDIT_CMDOA_F_INHERIT
4055088Sab196087  *	This is an item for which a common definition exists.
4065088Sab196087  *	Elfedit will substitute the standard values for the
4075088Sab196087  *	name, help text, and flags. This enforces consistency
4085088Sab196087  *	in documentation, plus it is easier for the module author.
4095088Sab196087  *	When ELFEDIT_CMDOA_F_INHERIT is set:
4105088Sab196087  *		- oa_name should be set to one of the ELFEDIT_STDOA_
4115088Sab196087  *			values to specifiy which standard item is being
4125088Sab196087  *			inherited.
4135088Sab196087  *		- oa_help must be set to NULL.
4145088Sab196087  *		- It is an error to set any other flags with
4155088Sab196087  *			ELFEDIT_CMDOA_F_INHERIT.
4165088Sab196087  *		- oa_idmask and oa_excmask are used in the normal way.
4175088Sab196087  *
4185088Sab196087  * The oa_idmask and oa_excmask fields are used to identify options,
4195088Sab196087  * and to support mutual exclusion (when two or more options cannot be
4205088Sab196087  * used together). They are ignored for arguments, and should be set to 0.
4215088Sab196087  * oa_idmask is used to uniquely identify each item. When elfedit_getopt()
4225088Sab196087  * matches an option, it returns the value of oa_idmask to the caller to
4235088Sab196087  * indicate which option was matched. elfedit enforces the following rules
4245088Sab196087  * for oa_idmask, and will refuse to load a module that does not follow them:
4255088Sab196087  *	- The value of oa_idmask must be 0, or have a value that
4265088Sab196087  *		is a power of 2 (i.e. only has one bit set).
4275088Sab196087  *	- Each item that sets a non-0 value for oa_idmask must have
4285088Sab196087  *		a unique value.
4295088Sab196087  *	- If oa_idmask is 0, oa_excmask must be 0 also.
4305088Sab196087  *	- oa_excmask is set to 0 if an item is not mutually exclusive
4315088Sab196087  *		to any other item. Otherwise, it should set the bit
4325088Sab196087  *		values representing the items it is mutually exclusive to.
4335088Sab196087  *	- An oa_idmask value of 0 can be used for any item that
4345088Sab196087  *		the module does not need to identify, and which
4355088Sab196087  *		is not mutually exclusive to any other item.
4365088Sab196087  * As elfedit_getopt() processes items, it maintains a bitmask combining the
4375088Sab196087  * oa_idmask fields of all the options already seen. For each option, it uses
4385088Sab196087  * oa_excmask to check for conflicts.
4395088Sab196087  *
4405088Sab196087  * note: elfedit enforces the rule that options consist of a '-'
4415088Sab196087  *	character followed by at least one character when a module
4425088Sab196087  *	is loaded.
4435088Sab196087  */
4445088Sab196087 typedef enum {
4455088Sab196087 	ELFEDIT_CMDOA_F_OPT =	1,	/* Item is optional */
4465088Sab196087 	ELFEDIT_CMDOA_F_VALUE =	2,	/* Item has a value arg following */
4475088Sab196087 	ELFEDIT_CMDOA_F_MULT =	4,	/* More than one are allowed */
4485088Sab196087 	ELFEDIT_CMDOA_F_INHERIT = 8,	/* Inherit definition: See above */
4495088Sab196087 } elfedit_cmd_oa_flag_t;
4505088Sab196087 
4515088Sab196087 typedef u_longlong_t elfedit_cmd_oa_mask_t;
4525088Sab196087 
4535088Sab196087 typedef struct {
4545088Sab196087 	const char		*oa_name;	/* Name of option */
4555088Sab196087 	elfedit_i18nhdl_t	oa_help;	/* Help text for option */
4565088Sab196087 	elfedit_cmd_oa_flag_t	oa_flags;	/* Additional attributes */
4575088Sab196087 	elfedit_cmd_oa_mask_t	oa_idmask;	/* Unique id, returned by */
4585088Sab196087 						/* 	elfedit_getopt */
4595088Sab196087 						/*	for use by caller */
4605088Sab196087 	elfedit_cmd_oa_mask_t	oa_excmask;	/* Mutual exclusion mask */
4615088Sab196087 } elfedit_cmd_optarg_t;
4625088Sab196087 
4635088Sab196087 
4645088Sab196087 
4655088Sab196087 /*
4665088Sab196087  * These values define the standard options and arguments that a module
4675088Sab196087  * can inherit using the ELFEDIT_CMDOA_F_INHERIT flag (described above).
4685088Sab196087  * New items must be added at the end --- reordering the list will
4695088Sab196087  * require all modules to be rebuilt.
4705088Sab196087  *
4715088Sab196087  * Note: 0 cannot be used as a ELFEDIT_STDOA_ value, because a NULL
4725088Sab196087  *	value of oa_name is used to terminate argument and options lists.
4735088Sab196087  *	Therefore, these values start at 1.
4745088Sab196087  */
4755088Sab196087 #define	ELFEDIT_STDOA_OPT_O		((const char *) 1)	/* -o ostyle */
4765088Sab196087 #define	ELFEDIT_STDOA_OPT_AND		((const char *) 2)	/* -and */
4775088Sab196087 #define	ELFEDIT_STDOA_OPT_CMP		((const char *) 3)	/* -cmp */
4785088Sab196087 #define	ELFEDIT_STDOA_OPT_OR		((const char *) 4)	/* -or */
4795088Sab196087 
4805088Sab196087 #define	ELFEDIT_NUM_STDOA	4	/* # of ELFEDIT_STDOA_ definitions */
4815088Sab196087 
4825088Sab196087 
4835088Sab196087 
4845088Sab196087 /*
4855088Sab196087  * Definition of a command
4865088Sab196087  *
4875088Sab196087  * This structure includes an elfedit_cmd_func_t pointer, which has
4885088Sab196087  * different definitions for different ELFCLASS. Rather than needlessly
4895088Sab196087  * complicate the code with three versions of this type, and any
4905088Sab196087  * type that uses it, we simply use the GenericClass type. elfedit
4915088Sab196087  * will always cast this to the correct type before calling a module.
4925088Sab196087  *
4935088Sab196087  * cmd_name is an array of pointers to the names for the command.
4945088Sab196087  * The "primary" name should always be first, followed by any alias
4955088Sab196087  * names. The final element of the array must be a NULL pointer,
4965088Sab196087  * which terminates the list. Every command is required to have at
4975088Sab196087  * least one name, so code is allowed to assume that the first element
4985088Sab196087  * of cmd_name is non-NULL, and contains the primary name.
4995088Sab196087  *
5005088Sab196087  * Many modules provide a "default" command, which is a command
5015088Sab196087  * that is run if only the module name is specified, followed
5025088Sab196087  * by a colon (i.e. "sym:"). The way this is implemented is to
5035088Sab196087  * give the desired default command an empty string as an alias.
5045088Sab196087  * Note that the primary name cannot be an empty string, only the
5055088Sab196087  * alias name.
5065088Sab196087  *
5075088Sab196087  * cmd_opts and cmd_args are each an array of elfedit_cmd_argdesc_t
5085088Sab196087  * structures, that describe the options and plain arguments accepted
5095088Sab196087  * by the command. These arrays are used to general help text for
5105088Sab196087  * the commands. The cmd_opts array is also used to provide command
5115088Sab196087  * completion for options. Both of these arrays are terminated by
5125088Sab196087  * a final NULL element (all fields zero).
5135088Sab196087  */
5145088Sab196087 typedef struct {
5155088Sab196087 	elfedit32_cmd_func_t	*cmd_func;	/* Implementation */
5165088Sab196087 	elfedit32_cmdcpl_func_t	*cmd_cplfunc;	/* Completion function */
5175088Sab196087 	const char		**cmd_name;	/* Cmd names (null term.) */
5185088Sab196087 	elfedit_i18nhdl_t	cmd_desc;	/* Short desc. of cmd purpose */
5195088Sab196087 	elfedit_i18nhdl_t	cmd_help;	/* Help text for the command */
5205088Sab196087 	elfedit_cmd_optarg_t	*cmd_opt;	/* Options */
5215088Sab196087 	elfedit_cmd_optarg_t	*cmd_args;	/* Plain arguments */
5225088Sab196087 } elfedit32_cmd_t;
5235088Sab196087 
5245088Sab196087 typedef struct {
5255088Sab196087 	elfedit64_cmd_func_t	*cmd_func;
5265088Sab196087 	elfedit64_cmdcpl_func_t	*cmd_cplfunc;
5275088Sab196087 	const char		**cmd_name;
5285088Sab196087 	elfedit_i18nhdl_t	cmd_desc;
5295088Sab196087 	elfedit_i18nhdl_t	cmd_help;
5305088Sab196087 	elfedit_cmd_optarg_t	*cmd_opt;
5315088Sab196087 	elfedit_cmd_optarg_t	*cmd_args;
5325088Sab196087 } elfedit64_cmd_t;
5335088Sab196087 
5345088Sab196087 #ifdef _ELF64
5355088Sab196087 #define	elfedit_cmd_t		elfedit64_cmd_t
5365088Sab196087 #else
5375088Sab196087 #define	elfedit_cmd_t		elfedit32_cmd_t
5385088Sab196087 #endif
5395088Sab196087 
5405088Sab196087 
5415088Sab196087 
5425088Sab196087 /*
5435088Sab196087  * elfedit modules version themselves so that we can alter the definition
5445088Sab196087  * of elfedit_module_t in a backward compatible way.
5455088Sab196087  */
5465088Sab196087 typedef enum {
5475088Sab196087 	ELFEDIT_VER_NONE = 0,
5485088Sab196087 	ELFEDIT_VER_CURRENT = 1,
5495088Sab196087 	ELFEDIT_VER_NUM = 2
5505088Sab196087 } elfedit_module_version_t;
5515088Sab196087 
5525088Sab196087 
5535088Sab196087 /*
5545088Sab196087  * Each module returns a pointer to an elfedit_module_t, describing
5555088Sab196087  * what commands the module provides.
5565088Sab196087  *
5575088Sab196087  * Note: mod_cmds is a NULL terminated array of command defs. This
5585088Sab196087  * means that the final element in the array should have all of its
5595088Sab196087  * fields set to NULL.
5605088Sab196087  *
5615088Sab196087  * The mod_i18nhdl_to_str function pointer is explained above
5625088Sab196087  * with the definition of elfedit_i18nhdl_t.
5635088Sab196087  */
5645088Sab196087 typedef const char *(* elfedit_mod_i18nhdl_to_str_func_t)(elfedit_i18nhdl_t);
5655088Sab196087 
5665088Sab196087 typedef struct {
5675088Sab196087 	elfedit_module_version_t mod_version;	/* version */
5685088Sab196087 	const char		*mod_name;	/* Name of module */
5695088Sab196087 	elfedit_i18nhdl_t	mod_desc;	/* Short desc. of mod purpose */
5705088Sab196087 	elfedit32_cmd_t		*mod_cmds;	/* Array of command defs */
5715088Sab196087 						/* i18n -> (char *) fcn */
5725088Sab196087 	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
5735088Sab196087 } elfedit32_module_t;
5745088Sab196087 
5755088Sab196087 typedef struct {
5765088Sab196087 	elfedit_module_version_t mod_version;
5775088Sab196087 	const char		*mod_name;
5785088Sab196087 	elfedit_i18nhdl_t	mod_desc;
5795088Sab196087 	elfedit64_cmd_t		*mod_cmds;
5805088Sab196087 	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
5815088Sab196087 } elfedit64_module_t;
5825088Sab196087 
5835088Sab196087 #ifdef _ELF64
5845088Sab196087 #define	elfedit_module_t	elfedit64_module_t
5855088Sab196087 #else
5865088Sab196087 #define	elfedit_module_t	elfedit32_module_t
5875088Sab196087 #endif
5885088Sab196087 
5895088Sab196087 
5905088Sab196087 /*
5915088Sab196087  * Each module is a sharable library, expected to provide a single global
5925088Sab196087  * function, named elfedit_init(), with the following prototype.
5935088Sab196087  */
5945088Sab196087 typedef elfedit_module_t *elfedit_init_func_t(elfedit_module_version_t version);
5955088Sab196087 
5965088Sab196087 
5975892Sab196087 /*
5985892Sab196087  * Prototype for elfedit_write(), and for outfunc argument
5995892Sab196087  * to elfedit_str_to_c_literal().
6005892Sab196087  */
6015892Sab196087 typedef void elfedit_write_func_t(const void *ptr, size_t size);
6025088Sab196087 
6035088Sab196087 
6045088Sab196087 /*
6055088Sab196087  * Core elfedit functions exported for use by modules
6065088Sab196087  */
6075088Sab196087 extern void elfedit_command_usage(void);
6085088Sab196087 extern void elfedit_cpl_command(void *cpldata);
6095088Sab196087 extern void elfedit_cpl_match(void *cpldata, const char *str, int casefold);
6106225Sab196087 extern void elfedit_cpl_ndx(void *cpldata, uint_t ndx);
6115088Sab196087 extern void elfedit_elferr(const char *file, const char *libelf_rtn_name);
6125088Sab196087 extern elfedit_flag_t elfedit_flags(void);
6135088Sab196087 extern void *elfedit_malloc(const char *item_name, size_t size);
6145088Sab196087 extern void elfedit_msg(elfedit_msg_t type, const char *format, ...);
6155088Sab196087 extern elfedit_outstyle_t elfedit_outstyle(void);
6165088Sab196087 extern void elfedit_pager_init(void);
6175088Sab196087 extern void elfedit_printf(const char *format, ...);
6185088Sab196087 extern void *elfedit_realloc(const char *item_name, void *ptr, size_t size);
6195892Sab196087 extern void elfedit_str_to_c_literal(const char *str,
6205892Sab196087     elfedit_write_func_t *outfunc);
6215892Sab196087 extern elfedit_write_func_t elfedit_write;
6225088Sab196087 
6235088Sab196087 /*
6245088Sab196087  * Core elfedit functions exported for use by sys: module only
6255088Sab196087  */
6265088Sab196087 extern void elfedit_cpl_module(void *cpldata, int load_all_modules);
6275088Sab196087 
6285088Sab196087 
6295088Sab196087 /*
6305088Sab196087  * elfedit modules are expected to define two functions, one for
6315088Sab196087  * each ELFCLASS. Define a generic name for this function, based on
6325088Sab196087  * the class being supported by the including module.
6335088Sab196087  */
6345088Sab196087 #ifdef _ELF64
6355088Sab196087 #define	elfedit_init		elfedit64_init
6365088Sab196087 #else
6375088Sab196087 #define	elfedit_init		elfedit32_init
6385088Sab196087 #endif
6395088Sab196087 
6405088Sab196087 
6415088Sab196087 
6425088Sab196087 /*
6435088Sab196087  * It is common to search the dynamic section for specific elements.
6445088Sab196087  * Structures of this type are used to represent the contents of such
6455088Sab196087  * elements in a systematic way. The elfedit_dyn_elt_init() function
6465088Sab196087  * is used to prepare these strucutres for use.
6475088Sab196087  */
6485088Sab196087 typedef struct {
6495088Sab196087 	int		dn_seen;	/* True if this item has been seen */
6505088Sab196087 	Elf32_Word	dn_ndx;		/* Index of item in dynamic array */
6515088Sab196087 	Elf32_Dyn	dn_dyn;		/* Contents of dynamic item */
6525088Sab196087 } elfedit32_dyn_elt_t;
6535088Sab196087 
6545088Sab196087 typedef struct {
6555088Sab196087 	int		dn_seen;
6565088Sab196087 	Elf64_Word	dn_ndx;
6575088Sab196087 	Elf64_Dyn	dn_dyn;
6585088Sab196087 } elfedit64_dyn_elt_t;
6595088Sab196087 
6605088Sab196087 #ifdef _ELF64
6615088Sab196087 #define	elfedit_dyn_elt_t	elfedit64_dyn_elt_t
6625088Sab196087 #else
6635088Sab196087 #define	elfedit_dyn_elt_t	elfedit32_dyn_elt_t
6645088Sab196087 #endif
6655088Sab196087 
6665088Sab196087 /*
6675088Sab196087  * The elfedit_atoi() and elfedit_atoui() functions can optionally
6685088Sab196087  * accept an array of these structures, giving symbolic names that
6695088Sab196087  * will be accepted instead of numeric codes. If such an array is
6705088Sab196087  * present, the supplied string has it's leading and trailing whitespace
6715088Sab196087  * removed and is then compared to the list, and if there is a match,
6725088Sab196087  * the corresponding integer value is returned.
6735088Sab196087  *
6745088Sab196087  * The final array element must have its name field set to NULL.
6755088Sab196087  */
6765088Sab196087 typedef u_longlong_t elfedit_atoui_t;
6775088Sab196087 typedef struct {
6785088Sab196087 	const char	*sym_name;
6795088Sab196087 	elfedit_atoui_t	sym_value;
6805088Sab196087 } elfedit_atoui_sym_t;
6815088Sab196087 typedef longlong_t elfedit_atoi_t;
6825088Sab196087 typedef struct {
6835088Sab196087 	const char	*sym_name;
6845088Sab196087 	elfedit_atoi_t	sym_value;
6855088Sab196087 } elfedit_atoi_sym_t;
6865088Sab196087 
6875088Sab196087 
6885088Sab196087 /*
6895088Sab196087  * The elfedit_atoconst*() functions are built on top of the atoui routines.
6905088Sab196087  * These routines accept an elfedit_const_t code instead of a
6915088Sab196087  * pointer to an elfedit_atoui_sym_t array, and use internally
6925088Sab196087  * predefined tables of elfedit_atoui_sym_t in order to do the desired
6935088Sab196087  * mappings. elfedit modules are encouraged to use these standard
6945088Sab196087  * tables instead of defining their own elfedit_atoui_sym_t arrays.
6955088Sab196087  *
6965088Sab196087  * note:
6975088Sab196087  *	- The values assigned here must be in agreement with the
6985088Sab196087  *		sym_table[] array defined in elfconst.c.
6995088Sab196087  *	- Once defined, these values must not change. Reordering the
7005088Sab196087  *		list will require all modules to be rebuilt, and will
7015088Sab196087  *		break backward compatability. New items should be
7025088Sab196087  *		added to the end.
7035088Sab196087  */
7045088Sab196087 typedef enum {
7055088Sab196087 	ELFEDIT_CONST_OUTSTYLE =	0,	/* elfedit output styles  */
7065088Sab196087 	ELFEDIT_CONST_OUTSTYLE_MO =	1,	/* ostyles with -o prefix */
7075088Sab196087 	ELFEDIT_CONST_BOOL =		2,	/* boolean names */
7089273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT_STRTAB =	3,	/* ELF SHT_STRTAB */
7099273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT_SYMTAB =	4,	/* ELF SHT_SYMTAB */
7109273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT_DYNSYM =	5,	/* ELF SHT_DYNSYM */
7119273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT_LDYNSYM =	6,	/* ELF SHT_SUNW_LDYNSYM */
7129273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHN =		7,	/* ELF SHN_ section indexes  */
7139273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT =		8,	/* ELF SHT_ section types  */
7149273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHT_ALLSYMTAB =	9,	/* ELF SHT_ symbol table */
7155088Sab196087 						/*	section types */
7165088Sab196087 	ELFEDIT_CONST_DT =		10,	/* Dynamic tags: DT_ */
7175088Sab196087 	ELFEDIT_CONST_DF =		11,	/* DT_FLAGS bits */
7185088Sab196087 	ELFEDIT_CONST_DF_P1 =		12,	/* DF_POSFLAG_1 bits */
7195088Sab196087 	ELFEDIT_CONST_DF_1 =		13,	/* DT_FLAGS_1 bits */
7205088Sab196087 	ELFEDIT_CONST_DTF_1 =		14,	/* DT_FEATURE_1 bits */
7215088Sab196087 	ELFEDIT_CONST_EI =		15,	/* ELF header e_ident indexes */
7225088Sab196087 	ELFEDIT_CONST_ET =		16,	/* Ehdr obj type */
7235088Sab196087 	ELFEDIT_CONST_ELFCLASS =	17,	/* Ehdr wordsize (32,64) */
7245088Sab196087 	ELFEDIT_CONST_ELFDATA =		18,	/* Ehdr endian */
7255088Sab196087 	ELFEDIT_CONST_EF =		19,	/* Ehdr flags */
7265088Sab196087 	ELFEDIT_CONST_EV =		20,	/* Ehdr version */
7275088Sab196087 	ELFEDIT_CONST_EM =		21,	/* Ehdr machine */
7285088Sab196087 	ELFEDIT_CONST_ELFOSABI =	22,	/* Ehdr ABI */
7299273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_EAV =		23,	/* Ehdr ABI version */
7309273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_PT =		24,	/* Phdr type */
7319273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_PF =		25,	/* Phdr flags */
7329273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SHF =		26,	/* Shdr flags */
7339273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_STB =		27,	/* Sym binding */
7349273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_STT =		28,	/* Sym type */
7359273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_STV =		29,	/* Sym visibility */
7369273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SYMINFO_BT =	30,	/* Syminfo boundto */
7379273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_SYMINFO_FLG =	31,	/* Syminfo flags */
7389273SAli.Bahrami@Sun.COM 	ELFEDIT_CONST_CA =		32,	/* Capabilities tags */
739*11827SRod.Evans@Sun.COM 	ELFEDIT_CONST_HW1_SUNW =	33,	/* hardware capabilities */
7405088Sab196087 	ELFEDIT_CONST_SF1_SUNW =	34,	/* software capabilities */
741*11827SRod.Evans@Sun.COM 	ELFEDIT_CONST_HW2_SUNW =	35,	/* hardware capabilities */
7429273SAli.Bahrami@Sun.COM 
743*11827SRod.Evans@Sun.COM 	ELFEDIT_CONST_NUM =		36,	/* # of constant types */
7445088Sab196087 } elfedit_const_t;
7455088Sab196087 
7465088Sab196087 /*
7475088Sab196087  * Given an elfedit_const_t, return the array of elfedit_atoui_sym_t
7485088Sab196087  * entries that it represents.
7495088Sab196087  */
7505088Sab196087 extern elfedit_atoui_sym_t *elfedit_const_to_atoui(elfedit_const_t const_type);
7515088Sab196087 
7525088Sab196087 /*
7535088Sab196087  * ato[u]i and const routines, used to turn strings into numeric values,
7545088Sab196087  * with support for mapping symbol names to numbers, and range checking.
7555088Sab196087  */
7565088Sab196087 extern elfedit_atoi_t elfedit_atoi(const char *str,
7575088Sab196087     const elfedit_atoi_sym_t *sym);
7585088Sab196087 extern elfedit_atoui_t elfedit_atoui(const char *str,
7595088Sab196087     const elfedit_atoui_sym_t *sym);
7605088Sab196087 extern elfedit_atoui_t elfedit_atoconst(const char *str,
7615088Sab196087     elfedit_const_t const_type);
7625088Sab196087 
7635088Sab196087 extern int elfedit_atoi2(const char *str, const elfedit_atoi_sym_t *sym,
7645088Sab196087     elfedit_atoi_t *v);
7655088Sab196087 extern int elfedit_atoui2(const char *str, const elfedit_atoui_sym_t *sym,
7665088Sab196087     elfedit_atoui_t *);
7675088Sab196087 extern int elfedit_atoconst2(const char *str, elfedit_const_t const_type,
7685088Sab196087     elfedit_atoui_t *);
7695088Sab196087 
7705088Sab196087 extern elfedit_atoi_t elfedit_atoi_range(const char *str,
7715088Sab196087     const char *item_name, elfedit_atoi_t min, elfedit_atoi_t max,
7725088Sab196087     const elfedit_atoi_sym_t *sym);
7735088Sab196087 extern elfedit_atoui_t elfedit_atoui_range(const char *str,
7745088Sab196087     const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
7755088Sab196087     const elfedit_atoui_sym_t *sym);
7765088Sab196087 extern elfedit_atoui_t elfedit_atoconst_range(const char *str,
7775088Sab196087     const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
7785088Sab196087     elfedit_const_t const_type);
7795088Sab196087 
7805088Sab196087 extern int elfedit_atoi_range2(const char *str, elfedit_atoi_t min,
7815088Sab196087     elfedit_atoi_t max, const elfedit_atoi_sym_t *sym, elfedit_atoi_t *v);
7825088Sab196087 extern int elfedit_atoui_range2(const char *str, elfedit_atoui_t min,
7835088Sab196087     elfedit_atoui_t max, const elfedit_atoui_sym_t *sym, elfedit_atoui_t *v);
7845088Sab196087 extern int elfedit_atoconst_range2(const char *str, elfedit_atoui_t min,
7855088Sab196087     elfedit_atoui_t max, elfedit_const_t const_type, elfedit_atoui_t *v);
7865088Sab196087 
7875088Sab196087 extern const char *elfedit_atoi_value_to_str(const elfedit_atoi_sym_t *sym,
7885088Sab196087     elfedit_atoi_t value, int required);
7895088Sab196087 extern const char *elfedit_atoui_value_to_str(const elfedit_atoui_sym_t *sym,
7905088Sab196087     elfedit_atoui_t value, int required);
7915088Sab196087 extern const char *elfedit_atoconst_value_to_str(elfedit_const_t const_type,
7925088Sab196087     elfedit_atoui_t value, int required);
7935088Sab196087 
7945088Sab196087 extern void elfedit_cpl_atoi(void *cpldata, const elfedit_atoi_sym_t *sym);
7955088Sab196087 extern void elfedit_cpl_atoui(void *cpldata, const elfedit_atoui_sym_t *sym);
7965088Sab196087 extern void elfedit_cpl_atoconst(void *cpldata, elfedit_const_t const_type);
7975088Sab196087 
7985088Sab196087 
7995088Sab196087 /*
8005088Sab196087  * Convenience functions built on top of the ato[u]i routines.
8015088Sab196087  */
8025088Sab196087 extern int elfedit_atobool(const char *str, const char *item_name);
8035088Sab196087 extern elfedit_atoui_t elfedit_atoshndx(const char *str, size_t shnum);
8045088Sab196087 
8055088Sab196087 
8065088Sab196087 /*
8075088Sab196087  * elfedit provides a getopt utility for use by the module commands.
8085088Sab196087  * elfedit_getopt_state_t is the state block used by elfedit_getopt().
8095088Sab196087  * elfedit_getopt_ret_t is the definition of the values returned to
8105088Sab196087  * the user by elfedit_getopt() when an option is matched. Elfedit
8115088Sab196087  * getopt processing is done as follows:
8125088Sab196087  *
8135088Sab196087  * 1) The caller initializes an elfedit_getopt_state_t struct via
8145088Sab196087  *	a call to elfedit_getopt_init(). The contents of this structure
8155088Sab196087  *	must not be accessed by the caller, as they are all private and
8165088Sab196087  *	subject to change.
8175088Sab196087  * 2) Repeated calls are made to elfedit_getopt(), as long as it returns
8185088Sab196087  *	a non-NULL pointer to an elfedit_getopt_ret_t structure. If the
8195088Sab196087  *	matched option has a value (ELFEDIT_CMDOA_F_VALUE), then the gor_value
8205088Sab196087  *	field contains the pointer to the string. Otherwise, gor_value is NULL.
8215088Sab196087  * 3) As elfedit_getopt() consumes optional arguments from the argc/argv
8225088Sab196087  *	passed to elfedit_getopt_init(), it adjusts argc/argc to skip over
8235088Sab196087  *	them. Once elfedit_getopt() returns NULL to indicate that there are no
8245088Sab196087  *	more options to match, argc/argv have been adjusted so that they
8255088Sab196087  *	reference the plain arguments.
8265088Sab196087  */
8275088Sab196087 typedef struct {
8285088Sab196087 	elfedit_cmd_oa_mask_t gor_idmask;	/* oa_idmask from matching */
8295088Sab196087 					/*	elfedit_cmd_optarg_t. Can be */
8305088Sab196087 					/*	used to quickly identify opt */
8315088Sab196087 	const char	*gor_value;	/* Opt value if ELFEDIT_CMDOA_F_VALUE */
8325088Sab196087 					/*	Otherwise, NULL */
8335088Sab196087 } elfedit_getopt_ret_t;
8345088Sab196087 typedef struct {
8355088Sab196087 	int			*go_argc;	/* Pointer to # of options */
8365088Sab196087 	const char		***go_argv;	/* Ptr to array of opt strs */
8375088Sab196087 	elfedit_cmd_optarg_t	*go_optarg;	/* Array of allowed options */
8385088Sab196087 	elfedit_cmd_oa_mask_t	go_idmask;	/* Combined id masks of all */
8395088Sab196087 						/*	seen options */
8405088Sab196087 	int			go_done;	/* True if last option seen */
8415088Sab196087 	const char		*go_sglgrp;	/* Group of 1-letter opts */
8425088Sab196087 	elfedit_getopt_ret_t	go_ret;		/* Data returned to user */
8435088Sab196087 } elfedit_getopt_state_t;
8445088Sab196087 
8455088Sab196087 
8465088Sab196087 
8475088Sab196087 /*
8485088Sab196087  * getopt related routines
8495088Sab196087  */
8505088Sab196087 extern void elfedit_getopt_init(elfedit_getopt_state_t *,
8515088Sab196087     int *, const char ***);
8525088Sab196087 extern elfedit_getopt_ret_t *elfedit_getopt(elfedit_getopt_state_t *);
8535088Sab196087 
8545088Sab196087 
8555088Sab196087 
8565088Sab196087 /*
8575088Sab196087  * Additional utility functions exported for use by modules
8585088Sab196087  */
8595088Sab196087 extern void elfedit_array_elts_delete(const char *name_str, void *data_start,
8605088Sab196087     size_t entsize, size_t num_ent, size_t start_ndx, size_t cnt);
8615088Sab196087 
8625088Sab196087 extern void elfedit_array_elts_move(const char *name_str, void *data_start,
8635088Sab196087     size_t entsize, size_t num_ent, size_t srcndx,
8645088Sab196087     size_t dstndx, size_t cnt, void *scr_item);
8655088Sab196087 
8665088Sab196087 extern int elfedit_bits_set(u_longlong_t v, int sizeof_orig_v);
8675088Sab196087 
8685088Sab196087 extern void elfedit32_dyn_elt_init(elfedit32_dyn_elt_t *dyn_elt);
8695088Sab196087 extern void elfedit64_dyn_elt_init(elfedit64_dyn_elt_t *dyn_elt);
8705088Sab196087 
8715088Sab196087 extern void elfedit32_dyn_elt_save(elfedit32_dyn_elt_t *elt, Elf32_Word ndx,
8725088Sab196087     Elf32_Dyn *dyn);
8735088Sab196087 extern void elfedit64_dyn_elt_save(elfedit64_dyn_elt_t *elt, Elf64_Word ndx,
8745088Sab196087     Elf64_Dyn *dyn);
8755088Sab196087 
8765088Sab196087 const char *elfedit32_dyn_offset_to_str(elfedit32_section_t *strsec,
8775088Sab196087     elfedit32_dyn_elt_t *dynelt);
8785088Sab196087 const char *elfedit64_dyn_offset_to_str(elfedit64_section_t *strsec,
8795088Sab196087     elfedit64_dyn_elt_t *dynelt);
8805088Sab196087 
8819273SAli.Bahrami@Sun.COM extern int elfedit32_dynstr_getpad(elfedit32_obj_state_t *obj_state,
8829273SAli.Bahrami@Sun.COM     elfedit32_section_t *dynsec, elfedit32_dyn_elt_t *dyn_strpad);
8839273SAli.Bahrami@Sun.COM extern int elfedit64_dynstr_getpad(elfedit64_obj_state_t *obj_state,
8849273SAli.Bahrami@Sun.COM     elfedit64_section_t *dynsec, elfedit64_dyn_elt_t *dyn_strpad);
8855088Sab196087 
8865088Sab196087 extern Elf32_Word elfedit32_dynstr_insert(elfedit32_section_t *dynsec,
8875088Sab196087     elfedit32_section_t *strsec, elfedit32_dyn_elt_t *dyn_strpad,
8885088Sab196087     const char *str);
8895088Sab196087 extern Elf64_Word elfedit64_dynstr_insert(elfedit64_section_t *dynsec,
8905088Sab196087     elfedit64_section_t *strsec, elfedit64_dyn_elt_t *dyn_strpad,
8915088Sab196087     const char *str);
8925088Sab196087 
8935088Sab196087 extern void elfedit32_modified_data(elfedit32_section_t *s);
8945088Sab196087 extern void elfedit64_modified_data(elfedit64_section_t *s);
8955088Sab196087 
8965088Sab196087 extern void elfedit32_modified_ehdr(elfedit32_obj_state_t *obj_state);
8975088Sab196087 extern void elfedit64_modified_ehdr(elfedit64_obj_state_t *obj_state);
8985088Sab196087 
8995088Sab196087 extern void elfedit32_modified_phdr(elfedit32_obj_state_t *obj_state);
9005088Sab196087 extern void elfedit64_modified_phdr(elfedit64_obj_state_t *obj_state);
9015088Sab196087 
9025088Sab196087 extern void elfedit32_modified_shdr(elfedit32_section_t *s);
9035088Sab196087 extern void elfedit64_modified_shdr(elfedit64_section_t *s);
9045088Sab196087 
9055088Sab196087 extern Elf32_Word elfedit32_name_to_shndx(elfedit32_obj_state_t *obj_state,
9065088Sab196087     const char *shnam);
9075088Sab196087 extern Elf64_Word elfedit64_name_to_shndx(elfedit64_obj_state_t *obj_state,
9085088Sab196087     const char *shnam);
9095088Sab196087 
9105088Sab196087 extern int elfedit32_name_to_symndx(elfedit32_section_t *symsec,
9115088Sab196087     elfedit32_section_t *strsec, const char *name, elfedit_msg_t msg_type,
9125088Sab196087     Elf32_Word *ret_symndx);
9135088Sab196087 extern int elfedit64_name_to_symndx(elfedit64_section_t *symsec,
9145088Sab196087     elfedit64_section_t *strsec, const char *name, elfedit_msg_t msg_type,
9155088Sab196087     Elf64_Word *ret_symndx);
9165088Sab196087 
9175088Sab196087 extern const char *elfedit32_offset_to_str(elfedit32_section_t *strsec,
9185088Sab196087     Elf32_Word offset, elfedit_msg_t msg_type, int debug_msg);
9195088Sab196087 extern const char *elfedit64_offset_to_str(elfedit64_section_t *strsec,
9205088Sab196087     Elf64_Word offset, elfedit_msg_t msg_type, int debug_msg);
9215088Sab196087 
9225088Sab196087 extern int elfedit32_sec_findstr(elfedit32_section_t *sec, Elf32_Word tail_ign,
9235088Sab196087     const char *str, Elf32_Word *ret_offset);
9245088Sab196087 extern int elfedit64_sec_findstr(elfedit64_section_t *sec, Elf64_Word tail_ign,
9255088Sab196087     const char *str, Elf64_Word *ret_offset);
9265088Sab196087 
9275892Sab196087 extern elfedit32_section_t *elfedit32_sec_get(
9285892Sab196087     elfedit32_obj_state_t *obj_state, Elf32_Word shndx);
9295892Sab196087 extern elfedit64_section_t *elfedit64_sec_get(
9305892Sab196087     elfedit64_obj_state_t *obj_state, Elf64_Word shndx);
9315892Sab196087 
9325088Sab196087 extern elfedit32_section_t *elfedit32_sec_getcap(
9335088Sab196087     elfedit32_obj_state_t *obj_state, Elf32_Cap **cap, Elf32_Word *num);
9345088Sab196087 extern elfedit64_section_t *elfedit64_sec_getcap(
9355088Sab196087     elfedit64_obj_state_t *obj_state, Elf64_Cap **cap, Elf64_Word *num);
9365088Sab196087 
9375088Sab196087 extern elfedit32_section_t *elfedit32_sec_getdyn(
9385088Sab196087     elfedit32_obj_state_t *obj_state, Elf32_Dyn **dyn, Elf32_Word *num);
9395088Sab196087 extern elfedit64_section_t *elfedit64_sec_getdyn(
9405088Sab196087     elfedit64_obj_state_t *obj_state, Elf64_Dyn **dyn, Elf64_Word *num);
9415088Sab196087 
9425088Sab196087 extern elfedit32_section_t *elfedit32_sec_getstr(
9436225Sab196087     elfedit32_obj_state_t *obj_state, Elf32_Word shndx, int);
9445088Sab196087 extern elfedit64_section_t *elfedit64_sec_getstr(
9456225Sab196087     elfedit64_obj_state_t *obj_state, Elf64_Word shndx, int);
9465088Sab196087 
9475088Sab196087 extern elfedit32_section_t *elfedit32_sec_getsyminfo(
9485088Sab196087     elfedit32_obj_state_t *obj_state, Elf32_Syminfo **syminfo, Elf32_Word *num);
9495088Sab196087 extern elfedit64_section_t *elfedit64_sec_getsyminfo(
9505088Sab196087     elfedit64_obj_state_t *obj_state, Elf64_Syminfo **syminfo, Elf64_Word *num);
9515088Sab196087 
9525088Sab196087 extern elfedit32_section_t *elfedit32_sec_getsymtab(
9535088Sab196087     elfedit32_obj_state_t *obj_state, int by_index, Elf32_Word index,
9545088Sab196087     const char *name, Elf32_Sym **sym, Elf32_Word *num,
9555088Sab196087     elfedit32_symtab_t **aux_info);
9565088Sab196087 extern elfedit64_section_t *elfedit64_sec_getsymtab(
9575088Sab196087     elfedit64_obj_state_t *obj_state, int by_index, Elf64_Word index,
9585088Sab196087     const char *name, Elf64_Sym **sym, Elf64_Word *num,
9595088Sab196087     elfedit64_symtab_t **aux_info);
9605088Sab196087 
9615088Sab196087 extern elfedit32_section_t *elfedit32_sec_getversym(
9625088Sab196087     elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
9635088Sab196087     Elf32_Versym **versym, Elf32_Word *num);
9645088Sab196087 extern elfedit64_section_t *elfedit64_sec_getversym(
9655088Sab196087     elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
9665088Sab196087     Elf64_Versym **versym, Elf64_Word *num);
9675088Sab196087 
9685088Sab196087 extern elfedit32_section_t *elfedit32_sec_getxshndx(
9695088Sab196087     elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
9705088Sab196087     Elf32_Word **xshndx, Elf32_Word *num);
9715088Sab196087 extern elfedit64_section_t *elfedit64_sec_getxshndx(
9725088Sab196087     elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
9735088Sab196087     Elf64_Word **xshndx, Elf64_Word *num);
9745088Sab196087 
9759273SAli.Bahrami@Sun.COM extern int elfedit32_sec_issymtab(elfedit32_obj_state_t *obj_state,
9769273SAli.Bahrami@Sun.COM     elfedit32_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);
9779273SAli.Bahrami@Sun.COM extern int elfedit64_sec_issymtab(elfedit64_obj_state_t *obj_state,
9789273SAli.Bahrami@Sun.COM     elfedit64_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);
9795088Sab196087 
9805088Sab196087 extern const char *elfedit32_sec_msgprefix(elfedit32_section_t *sec);
9815088Sab196087 extern const char *elfedit64_sec_msgprefix(elfedit64_section_t *sec);
9825088Sab196087 
9835088Sab196087 extern const char *elfedit32_shndx_to_name(elfedit32_obj_state_t *obj_state,
9845088Sab196087     Elf32_Word shndx);
9855088Sab196087 extern const char *elfedit64_shndx_to_name(elfedit64_obj_state_t *obj_state,
9865088Sab196087     Elf64_Word shndx);
9875088Sab196087 
9885088Sab196087 extern Elf32_Word elfedit32_strtab_insert(elfedit32_obj_state_t *obj_state,
9895088Sab196087     elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
9905088Sab196087 extern Elf64_Word elfedit64_strtab_insert(elfedit64_obj_state_t *obj_state,
9915088Sab196087     elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);
9925088Sab196087 
9935088Sab196087 extern void elfedit32_strtab_insert_test(elfedit32_obj_state_t *obj_state,
9945088Sab196087     elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
9955088Sab196087 extern void elfedit64_strtab_insert_test(elfedit64_obj_state_t *obj_state,
9965088Sab196087     elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);
9975088Sab196087 
9989273SAli.Bahrami@Sun.COM extern int elfedit32_test_osabi(elfedit32_obj_state_t *obj_state, uchar_t osabi,
9999273SAli.Bahrami@Sun.COM     int issue_err);
10009273SAli.Bahrami@Sun.COM extern int elfedit64_test_osabi(elfedit64_obj_state_t *obj_state, uchar_t osabi,
10019273SAli.Bahrami@Sun.COM     int issue_err);
10029273SAli.Bahrami@Sun.COM 
10035088Sab196087 extern Elf32_Word elfedit32_type_to_shndx(elfedit32_obj_state_t *obj_state,
10045088Sab196087     Elf32_Word shtype);
10055088Sab196087 extern Elf64_Word elfedit64_type_to_shndx(elfedit64_obj_state_t *obj_state,
10065088Sab196087     Elf64_Word shtype);
10075088Sab196087 
10085088Sab196087 
10095088Sab196087 
10105088Sab196087 /*
10115088Sab196087  * Map the generic names for each of the ELFCLASS specific routines
10125088Sab196087  * above to reference the proper routine for the current compilation.
10135088Sab196087  */
10145088Sab196087 #ifdef _ELF64
10155088Sab196087 #define	elfedit_dyn_elt_init		elfedit64_dyn_elt_init
10165088Sab196087 #define	elfedit_dyn_elt_save		elfedit64_dyn_elt_save
10175088Sab196087 #define	elfedit_dyn_offset_to_str	elfedit64_dyn_offset_to_str
10185088Sab196087 #define	elfedit_dynstr_getpad		elfedit64_dynstr_getpad
10195088Sab196087 #define	elfedit_dynstr_insert		elfedit64_dynstr_insert
10205088Sab196087 #define	elfedit_modified_data		elfedit64_modified_data
10215088Sab196087 #define	elfedit_modified_ehdr		elfedit64_modified_ehdr
10225088Sab196087 #define	elfedit_modified_phdr		elfedit64_modified_phdr
10235088Sab196087 #define	elfedit_modified_shdr		elfedit64_modified_shdr
10245088Sab196087 #define	elfedit_name_to_shndx		elfedit64_name_to_shndx
10255088Sab196087 #define	elfedit_name_to_symndx		elfedit64_name_to_symndx
10265088Sab196087 #define	elfedit_offset_to_str		elfedit64_offset_to_str
10275088Sab196087 #define	elfedit_sec_findstr		elfedit64_sec_findstr
10285892Sab196087 #define	elfedit_sec_get			elfedit64_sec_get
10295088Sab196087 #define	elfedit_sec_getcap		elfedit64_sec_getcap
10305088Sab196087 #define	elfedit_sec_getdyn		elfedit64_sec_getdyn
10315088Sab196087 #define	elfedit_sec_getstr		elfedit64_sec_getstr
10325088Sab196087 #define	elfedit_sec_getsyminfo		elfedit64_sec_getsyminfo
10335088Sab196087 #define	elfedit_sec_getsymtab		elfedit64_sec_getsymtab
10345088Sab196087 #define	elfedit_sec_getversym		elfedit64_sec_getversym
10355088Sab196087 #define	elfedit_sec_getxshndx		elfedit64_sec_getxshndx
10365088Sab196087 #define	elfedit_sec_issymtab		elfedit64_sec_issymtab
10375088Sab196087 #define	elfedit_shndx_to_name		elfedit64_shndx_to_name
10385088Sab196087 #define	elfedit_sec_msgprefix		elfedit64_sec_msgprefix
10395088Sab196087 #define	elfedit_strtab_insert		elfedit64_strtab_insert
10405088Sab196087 #define	elfedit_strtab_insert_test	elfedit64_strtab_insert_test
10419273SAli.Bahrami@Sun.COM #define	elfedit_test_osabi		elfedit64_test_osabi
10425088Sab196087 #define	elfedit_type_to_shndx		elfedit64_type_to_shndx
10435088Sab196087 #else
10445088Sab196087 #define	elfedit_dyn_elt_init		elfedit32_dyn_elt_init
10455088Sab196087 #define	elfedit_dyn_elt_save		elfedit32_dyn_elt_save
10465088Sab196087 #define	elfedit_dyn_offset_to_str	elfedit32_dyn_offset_to_str
10475088Sab196087 #define	elfedit_dynstr_getpad		elfedit32_dynstr_getpad
10485088Sab196087 #define	elfedit_dynstr_insert		elfedit32_dynstr_insert
10495088Sab196087 #define	elfedit_modified_data		elfedit32_modified_data
10505088Sab196087 #define	elfedit_modified_ehdr		elfedit32_modified_ehdr
10515088Sab196087 #define	elfedit_modified_phdr		elfedit32_modified_phdr
10525088Sab196087 #define	elfedit_modified_shdr		elfedit32_modified_shdr
10535088Sab196087 #define	elfedit_name_to_shndx		elfedit32_name_to_shndx
10545088Sab196087 #define	elfedit_name_to_symndx		elfedit32_name_to_symndx
10555088Sab196087 #define	elfedit_offset_to_str		elfedit32_offset_to_str
10565088Sab196087 #define	elfedit_sec_findstr		elfedit32_sec_findstr
10575892Sab196087 #define	elfedit_sec_get			elfedit32_sec_get
10585088Sab196087 #define	elfedit_sec_getcap		elfedit32_sec_getcap
10595088Sab196087 #define	elfedit_sec_getdyn		elfedit32_sec_getdyn
10605088Sab196087 #define	elfedit_sec_getstr		elfedit32_sec_getstr
10615088Sab196087 #define	elfedit_sec_getsyminfo		elfedit32_sec_getsyminfo
10625088Sab196087 #define	elfedit_sec_getsymtab		elfedit32_sec_getsymtab
10635088Sab196087 #define	elfedit_sec_getversym		elfedit32_sec_getversym
10645088Sab196087 #define	elfedit_sec_getxshndx		elfedit32_sec_getxshndx
10655088Sab196087 #define	elfedit_sec_issymtab		elfedit32_sec_issymtab
10665088Sab196087 #define	elfedit_shndx_to_name		elfedit32_shndx_to_name
10675088Sab196087 #define	elfedit_sec_msgprefix		elfedit32_sec_msgprefix
10685088Sab196087 #define	elfedit_strtab_insert		elfedit32_strtab_insert
10695088Sab196087 #define	elfedit_strtab_insert_test	elfedit32_strtab_insert_test
10709273SAli.Bahrami@Sun.COM #define	elfedit_test_osabi		elfedit32_test_osabi
10715088Sab196087 #define	elfedit_type_to_shndx		elfedit32_type_to_shndx
10725088Sab196087 #endif
10735088Sab196087 
10745088Sab196087 
10755088Sab196087 #ifdef	__cplusplus
10765088Sab196087 }
10775088Sab196087 #endif
10785088Sab196087 
10795088Sab196087 #endif	/* _ELFEDIT_H */
1080