d29b2c4438482eb00488be49a1f5d6835f455546ab/*
d29b2c4438482eb00488be49a1f5d6835f455546ab * CDDL HEADER START
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * The contents of this file are subject to the terms of the
d29b2c4438482eb00488be49a1f5d6835f455546ab * Common Development and Distribution License (the "License").
d29b2c4438482eb00488be49a1f5d6835f455546ab * You may not use this file except in compliance with the License.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d29b2c4438482eb00488be49a1f5d6835f455546ab * or http://www.opensolaris.org/os/licensing.
d29b2c4438482eb00488be49a1f5d6835f455546ab * See the License for the specific language governing permissions
d29b2c4438482eb00488be49a1f5d6835f455546ab * and limitations under the License.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * When distributing Covered Code, include this CDDL HEADER in each
d29b2c4438482eb00488be49a1f5d6835f455546ab * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d29b2c4438482eb00488be49a1f5d6835f455546ab * If applicable, add the following below this CDDL HEADER, with the
d29b2c4438482eb00488be49a1f5d6835f455546ab * fields enclosed by brackets "[]" replaced with your own identifying
d29b2c4438482eb00488be49a1f5d6835f455546ab * information: Portions Copyright [yyyy] [name of copyright owner]
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * CDDL HEADER END
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab/*
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d29b2c4438482eb00488be49a1f5d6835f455546ab * Use is subject to license terms.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab/*
d29b2c4438482eb00488be49a1f5d6835f455546ab * ELFCLASS specific code for elfedit, built once for each class
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <stdlib.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <stdio.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <unistd.h>
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#include <_machelf.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <libelf.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <strings.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include <sgs.h>
d29b2c4438482eb00488be49a1f5d6835f455546ab#include "msg.h"
d29b2c4438482eb00488be49a1f5d6835f455546ab#include "_elfedit.h"
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab/*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Look up the elfedit_symtab_t that corresponds to the symbol table
d29b2c4438482eb00488be49a1f5d6835f455546ab * referenced by the sh_link field of the given auxiliary section.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * entry:
d29b2c4438482eb00488be49a1f5d6835f455546ab * obj_state - Partially constructed object state from
d29b2c4438482eb00488be49a1f5d6835f455546ab * elfedit_init_obj_state().
d29b2c4438482eb00488be49a1f5d6835f455546ab * auxsec - Section that is associated with the symbol table section
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * exit:
d29b2c4438482eb00488be49a1f5d6835f455546ab * Returns the pointer to the elfedit_symtab_t entry that is
d29b2c4438482eb00488be49a1f5d6835f455546ab * referenced by the auxiliary section. If not found,
d29b2c4438482eb00488be49a1f5d6835f455546ab * outputs a debug message, and returns NULL.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546abstatic elfedit_symtab_t *
d29b2c4438482eb00488be49a1f5d6835f455546abget_symtab(elfedit_obj_state_t *obj_state, elfedit_section_t *auxsec)
d29b2c4438482eb00488be49a1f5d6835f455546ab{
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_symtab_t *symtab = obj_state->os_symtab;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word sh_link = auxsec->sec_shdr->sh_link;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word i;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab for (i = 0; i < obj_state->os_symtabnum; i++, symtab++)
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symtab->symt_shndx == sh_link)
d29b2c4438482eb00488be49a1f5d6835f455546ab return (symtab);
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * If we don't return above, it doesn't reference a valid
d29b2c4438482eb00488be49a1f5d6835f455546ab * symbol table. Issue warning.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_AUX_LINK),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(auxsec->sec_shndx), auxsec->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(sh_link));
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab return (NULL);
d29b2c4438482eb00488be49a1f5d6835f455546ab}
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab/*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Fill in state.elf.obj_state with a a dynamically allocated
d29b2c4438482eb00488be49a1f5d6835f455546ab * elfedit_obj_state_t struct of the appropriate ELFCLASS.
d29b2c4438482eb00488be49a1f5d6835f455546ab * This pre-chewed form is fed to each command, reducing the amount
d29b2c4438482eb00488be49a1f5d6835f455546ab * of ELF boilerplate code each command needs to contain.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * entry:
d29b2c4438482eb00488be49a1f5d6835f455546ab * file - Name of file to process
d29b2c4438482eb00488be49a1f5d6835f455546ab * fd - Descriptor of open file which has been successfully
d29b2c4438482eb00488be49a1f5d6835f455546ab * processed by elf_begin().
d29b2c4438482eb00488be49a1f5d6835f455546ab * elf - Elf handle returned by elf_begin
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * exit:
d29b2c4438482eb00488be49a1f5d6835f455546ab * An elfedit_obj_state_t struct of the appropriate ELFCLASS has
d29b2c4438482eb00488be49a1f5d6835f455546ab * been dynamically allocated, and state.elf.obj_state references it.
d29b2c4438482eb00488be49a1f5d6835f455546ab * On failure, this routine does not return to the caller.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * note: The resulting elfedit_obj_state_t is allocated from a single
d29b2c4438482eb00488be49a1f5d6835f455546ab * piece of memory, such that a single call to free() suffices
d29b2c4438482eb00488be49a1f5d6835f455546ab * to release it as well as any memory it references.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab#ifdef _ELF64
d29b2c4438482eb00488be49a1f5d6835f455546abvoid
d29b2c4438482eb00488be49a1f5d6835f455546abelfedit64_init_obj_state(const char *file, int fd, Elf *elf)
d29b2c4438482eb00488be49a1f5d6835f455546ab#else
d29b2c4438482eb00488be49a1f5d6835f455546abvoid
d29b2c4438482eb00488be49a1f5d6835f455546abelfedit32_init_obj_state(const char *file, int fd, Elf *elf)
d29b2c4438482eb00488be49a1f5d6835f455546ab#endif
d29b2c4438482eb00488be49a1f5d6835f455546ab{
d29b2c4438482eb00488be49a1f5d6835f455546ab#define INITIAL_SYMTABNDX_ALLOC 5
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * These macros are used to call functions from libelf.
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami *
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * LIBELF_FAIL encapsulates the common way in which we handle
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * all of these errors: libelf_fail_name is set and execution
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * jumps to the libelf_failure label for handling.
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami *
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * LIBELF is used for the common case in which the function returns
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami * NULL for failure and something else for success.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami#define LIBELF_FAIL(_name) { libelf_fail_name = _name; goto libelf_failure; }
d29b2c4438482eb00488be49a1f5d6835f455546ab#define LIBELF(_libelf_expr, _name) \
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami if ((_libelf_expr) == NULL) \
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami LIBELF_FAIL(_name)
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab const char *libelf_fail_name; /* Used for LIBELF errors */
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab Elf_Scn *scn;
d29b2c4438482eb00488be49a1f5d6835f455546ab Elf_Data *data;
d29b2c4438482eb00488be49a1f5d6835f455546ab uint_t ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab size_t len, os_size, secarr_size;
d29b2c4438482eb00488be49a1f5d6835f455546ab char *names = 0;
d29b2c4438482eb00488be49a1f5d6835f455546ab size_t names_len;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_section_t *_cache;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_obj_state_t tstate;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_obj_state_t *obj_state = NULL;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word *symtabndx = NULL;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word symtabndx_size = 0;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_symtab_t *symtab;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_file = file;
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_fd = fd;
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_elf = elf;
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_dynndx = SHN_UNDEF;
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_symtabnum = 0;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF(tstate.os_ehdr = elf_getehdr(tstate.os_elf),
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_ORIG(MSG_ELF_GETEHDR))
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /* Program header array count and address */
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami if (elf_getphdrnum(tstate.os_elf, &tstate.os_phnum) == -1)
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETPHDRNUM))
d29b2c4438482eb00488be49a1f5d6835f455546ab if (tstate.os_phnum > 0) {
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF((tstate.os_phdr = elf_getphdr(tstate.os_elf)),
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_ORIG(MSG_ELF_GETPHDR))
d29b2c4438482eb00488be49a1f5d6835f455546ab } else {
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_phdr = NULL;
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami if (elf_getshdrnum(tstate.os_elf, &tstate.os_shnum) == -1)
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRNUM))
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Obtain the .shstrtab data buffer to provide the required section
d29b2c4438482eb00488be49a1f5d6835f455546ab * name strings.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami if (elf_getshdrstrndx(tstate.os_elf, &tstate.os_shstrndx) == -1)
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRSTRNDX))
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF((scn = elf_getscn(tstate.os_elf, tstate.os_shstrndx)),
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_ORIG(MSG_ELF_GETSCN))
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF((data = elf_getdata(scn, NULL)), MSG_ORIG(MSG_ELF_GETDATA))
d29b2c4438482eb00488be49a1f5d6835f455546ab names = data->d_buf;
d29b2c4438482eb00488be49a1f5d6835f455546ab names_len = (names == NULL) ? 0 : data->d_size;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Count the number of symbol tables and capture their indexes.
d29b2c4438482eb00488be49a1f5d6835f455546ab * Find the dynamic section.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
d29b2c4438482eb00488be49a1f5d6835f455546ab ndx++) {
d29b2c4438482eb00488be49a1f5d6835f455546ab Shdr *shdr;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF(shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab switch (shdr->sh_type) {
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_DYNAMIC:
d29b2c4438482eb00488be49a1f5d6835f455546ab /* Save index of dynamic section for use below */
d29b2c4438482eb00488be49a1f5d6835f455546ab tstate.os_dynndx = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_SYMTAB:
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_DYNSYM:
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_SUNW_LDYNSYM:
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symtabndx_size <= tstate.os_symtabnum) {
d29b2c4438482eb00488be49a1f5d6835f455546ab symtabndx_size = (symtabndx_size == 0) ?
d29b2c4438482eb00488be49a1f5d6835f455546ab INITIAL_SYMTABNDX_ALLOC :
d29b2c4438482eb00488be49a1f5d6835f455546ab (symtabndx_size * 2);
d29b2c4438482eb00488be49a1f5d6835f455546ab symtabndx = elfedit_realloc(
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_ALLOC_SYMTABOS), symtabndx,
d29b2c4438482eb00488be49a1f5d6835f455546ab symtabndx_size * sizeof (symtabndx[0]));
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab symtabndx[tstate.os_symtabnum++] = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Allocate space to hold the state. We allocate space for everything
d29b2c4438482eb00488be49a1f5d6835f455546ab * in one chunk to make releasing it easy:
d29b2c4438482eb00488be49a1f5d6835f455546ab * (1) elfedit_obj_state_t struct
d29b2c4438482eb00488be49a1f5d6835f455546ab * (2) The array of elfedit_section_t items referenced from
d29b2c4438482eb00488be49a1f5d6835f455546ab * the elfedit_obj_state_t struct.
d29b2c4438482eb00488be49a1f5d6835f455546ab * (3) The array of elfedit_symtab_t items referenced from
d29b2c4438482eb00488be49a1f5d6835f455546ab * the elfedit_obj_state_t struct.
d29b2c4438482eb00488be49a1f5d6835f455546ab * (4) The file name.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * Note that we round up the size of (1) and (2) to a double boundary
d29b2c4438482eb00488be49a1f5d6835f455546ab * to ensure proper alignment of (2) and (3). (4) can align on any
d29b2c4438482eb00488be49a1f5d6835f455546ab * boundary.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab os_size = S_DROUND(sizeof (tstate));
d29b2c4438482eb00488be49a1f5d6835f455546ab secarr_size = (tstate.os_shnum * sizeof (elfedit_section_t));
d29b2c4438482eb00488be49a1f5d6835f455546ab secarr_size = S_DROUND(secarr_size);
d29b2c4438482eb00488be49a1f5d6835f455546ab len = strlen(tstate.os_file) + 1;
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state = elfedit_malloc(MSG_INTL(MSG_ALLOC_OBJSTATE),
d29b2c4438482eb00488be49a1f5d6835f455546ab os_size + secarr_size +
d29b2c4438482eb00488be49a1f5d6835f455546ab (tstate.os_symtabnum * sizeof (elfedit_symtab_t)) + len);
d29b2c4438482eb00488be49a1f5d6835f455546ab *obj_state = tstate;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*LINTED E_BAD_PTR_CAST_ALIGN*/
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state->os_secarr = (elfedit_section_t *)
d29b2c4438482eb00488be49a1f5d6835f455546ab ((char *)obj_state + os_size);
d29b2c4438482eb00488be49a1f5d6835f455546ab if (obj_state->os_symtabnum == 0)
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state->os_symtab = NULL;
d29b2c4438482eb00488be49a1f5d6835f455546ab else
d29b2c4438482eb00488be49a1f5d6835f455546ab /*LINTED E_BAD_PTR_CAST_ALIGN*/
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state->os_symtab = (elfedit_symtab_t *)
d29b2c4438482eb00488be49a1f5d6835f455546ab ((char *)obj_state->os_secarr + secarr_size);
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state->os_file =
d29b2c4438482eb00488be49a1f5d6835f455546ab (char *)(obj_state->os_symtab + tstate.os_symtabnum);
d29b2c4438482eb00488be49a1f5d6835f455546ab (void) strncpy((char *)obj_state->os_file, tstate.os_file, len);
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Fill in obj_state->os_secarr with information for each section.
d29b2c4438482eb00488be49a1f5d6835f455546ab * At the same time, fill in obj_state->os_symtab with the symbol
d29b2c4438482eb00488be49a1f5d6835f455546ab * table related data.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab bzero(obj_state->os_secarr, sizeof (obj_state->os_secarr[0]));
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache = obj_state->os_secarr;
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF(scn = elf_getscn(tstate.os_elf, 0),
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_ORIG(MSG_ELF_GETSCN));
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_scn = scn;
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF(_cache->sec_shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
d29b2c4438482eb00488be49a1f5d6835f455546ab (names + _cache->sec_shdr->sh_name) : MSG_INTL(MSG_UNKNOWNSECNAM);
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache++;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab if (obj_state->os_symtab != NULL) {
d29b2c4438482eb00488be49a1f5d6835f455546ab bzero(obj_state->os_symtab,
d29b2c4438482eb00488be49a1f5d6835f455546ab sizeof (obj_state->os_symtab[0]) * obj_state->os_symtabnum);
d29b2c4438482eb00488be49a1f5d6835f455546ab for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++)
d29b2c4438482eb00488be49a1f5d6835f455546ab obj_state->os_symtab[ndx].symt_shndx = symtabndx[ndx];
d29b2c4438482eb00488be49a1f5d6835f455546ab free(symtabndx);
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
d29b2c4438482eb00488be49a1f5d6835f455546ab ndx++, _cache++) {
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_shndx = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_scn = scn;
d29b2c4438482eb00488be49a1f5d6835f455546ab LIBELF(_cache->sec_shdr = elf_getshdr(scn),
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_ORIG(MSG_ELF_GETSHDR))
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_data = elf_getdata(scn, NULL);
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
d29b2c4438482eb00488be49a1f5d6835f455546ab (names + _cache->sec_shdr->sh_name) :
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_UNKNOWNSECNAM);
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab switch (_cache->sec_shdr->sh_type) {
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_SYMTAB_SHNDX:
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab = get_symtab(obj_state, _cache);
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab->symt_xshndx = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_SUNW_syminfo:
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab = get_symtab(obj_state, _cache);
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab->symt_syminfo = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab case SHT_SUNW_versym:
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab = get_symtab(obj_state, _cache);
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab->symt_versym = ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Sanity check the symbol tables, and discard any auxiliary
d29b2c4438482eb00488be49a1f5d6835f455546ab * sections without enough elements.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab symtab = obj_state->os_symtab;
d29b2c4438482eb00488be49a1f5d6835f455546ab for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) {
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_section_t *symsec;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word symsec_cnt, aux_cnt;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab symsec = &obj_state->os_secarr[symtab->symt_shndx];
d29b2c4438482eb00488be49a1f5d6835f455546ab symsec_cnt = symsec->sec_shdr->sh_size / sizeof (Sym);
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /* Extended section indexes */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symtab->symt_xshndx != SHN_UNDEF) {
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache = &obj_state->os_secarr[symtab->symt_xshndx];
d29b2c4438482eb00488be49a1f5d6835f455546ab aux_cnt = _cache->sec_shdr->sh_size / sizeof (Word);
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symsec_cnt > aux_cnt)
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_AUX_SIZE),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(ndx), _cache->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(aux_cnt),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(symsec->sec_shndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab symsec->sec_name, EC_WORD(aux_cnt));
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /* Syminfo */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symtab->symt_syminfo != SHN_UNDEF) {
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache = &obj_state->os_secarr[symtab->symt_syminfo];
d29b2c4438482eb00488be49a1f5d6835f455546ab aux_cnt = _cache->sec_shdr->sh_size / sizeof (Syminfo);
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symsec_cnt > aux_cnt)
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_AUX_SIZE),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(ndx), _cache->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(aux_cnt),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(symsec->sec_shndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab symsec->sec_name, EC_WORD(aux_cnt));
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /* Versym */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symtab->symt_versym != SHN_UNDEF) {
d29b2c4438482eb00488be49a1f5d6835f455546ab _cache = &obj_state->os_secarr[symtab->symt_versym];
d29b2c4438482eb00488be49a1f5d6835f455546ab aux_cnt = _cache->sec_shdr->sh_size / sizeof (Versym);
d29b2c4438482eb00488be49a1f5d6835f455546ab if (symsec_cnt > aux_cnt)
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_AUX_SIZE),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(ndx), _cache->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(aux_cnt),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(symsec->sec_shndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab symsec->sec_name, EC_WORD(aux_cnt));
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * If this object has a dynsym section with a FLAGS_1 field,
d29b2c4438482eb00488be49a1f5d6835f455546ab * then set the DF_1_EDITED bit. elfedit allows changes that
d29b2c4438482eb00488be49a1f5d6835f455546ab * can break the resulting program, so knowing that a file was
d29b2c4438482eb00488be49a1f5d6835f455546ab * edited can be helpful when encountering a core file or other
d29b2c4438482eb00488be49a1f5d6835f455546ab * unexpected failure in the field. A single bit can't tell you
d29b2c4438482eb00488be49a1f5d6835f455546ab * what was changed, but it will alert you to the possibility that
d29b2c4438482eb00488be49a1f5d6835f455546ab * some additional questions might be in order.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (obj_state->os_dynndx != SHN_UNDEF) {
d29b2c4438482eb00488be49a1f5d6835f455546ab Word i;
d29b2c4438482eb00488be49a1f5d6835f455546ab Word numdyn;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_section_t *dynsec;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_t flags_1_elt;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_t null_elt;
d29b2c4438482eb00488be49a1f5d6835f455546ab Dyn *dyn;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
d29b2c4438482eb00488be49a1f5d6835f455546ab dyn = (Dyn *) dynsec->sec_data->d_buf;
d29b2c4438482eb00488be49a1f5d6835f455546ab numdyn = dynsec->sec_shdr->sh_size /
d29b2c4438482eb00488be49a1f5d6835f455546ab dynsec->sec_shdr->sh_entsize;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_init(&flags_1_elt);
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_init(&null_elt);
d29b2c4438482eb00488be49a1f5d6835f455546ab for (i = 0; i < numdyn; i++) {
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab switch (dyn[i].d_tag) {
d29b2c4438482eb00488be49a1f5d6835f455546ab case DT_NULL:
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Remember state of the first DT_NULL. If there
d29b2c4438482eb00488be49a1f5d6835f455546ab * are more than one (i.e. the first one is not
d29b2c4438482eb00488be49a1f5d6835f455546ab * in the final spot), and there is no flags1,
d29b2c4438482eb00488be49a1f5d6835f455546ab * then we will turn the first one into a
d29b2c4438482eb00488be49a1f5d6835f455546ab * DT_FLAGS_1.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (!null_elt.dn_seen)
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_save(&null_elt, i,
d29b2c4438482eb00488be49a1f5d6835f455546ab &dyn[i]);
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab case DT_FLAGS_1:
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_dyn_elt_save(&flags_1_elt, i, &dyn[i]);
d29b2c4438482eb00488be49a1f5d6835f455546ab break;
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab /* If don't have a flags1 field, can we make one from a NULL? */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (!flags_1_elt.dn_seen && null_elt.dn_seen &&
d29b2c4438482eb00488be49a1f5d6835f455546ab (null_elt.dn_ndx < (numdyn - 1))) {
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_NULL2DYNFL1),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(obj_state->os_dynndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab dynsec->sec_name, EC_WORD(null_elt.dn_ndx));
d29b2c4438482eb00488be49a1f5d6835f455546ab flags_1_elt.dn_seen = 1;
d29b2c4438482eb00488be49a1f5d6835f455546ab flags_1_elt.dn_ndx = null_elt.dn_ndx;
d29b2c4438482eb00488be49a1f5d6835f455546ab flags_1_elt.dn_dyn.d_tag = DT_FLAGS_1;
d29b2c4438482eb00488be49a1f5d6835f455546ab flags_1_elt.dn_dyn.d_un.d_val = 0;
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * If there is a flags 1 field, add the edit flag if
d29b2c4438482eb00488be49a1f5d6835f455546ab * it is not present, and report it's presence otherwise.
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (flags_1_elt.dn_seen) {
d29b2c4438482eb00488be49a1f5d6835f455546ab if (flags_1_elt.dn_dyn.d_un.d_val & DF_1_EDITED) {
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_SEEDYNFLG),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(obj_state->os_dynndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab dynsec->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(flags_1_elt.dn_ndx));
d29b2c4438482eb00488be49a1f5d6835f455546ab } else {
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_msg(ELFEDIT_MSG_DEBUG,
d29b2c4438482eb00488be49a1f5d6835f455546ab MSG_INTL(MSG_DEBUG_ADDDYNFLG),
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(obj_state->os_dynndx),
d29b2c4438482eb00488be49a1f5d6835f455546ab dynsec->sec_name,
d29b2c4438482eb00488be49a1f5d6835f455546ab EC_WORD(flags_1_elt.dn_ndx));
d29b2c4438482eb00488be49a1f5d6835f455546ab flags_1_elt.dn_dyn.d_un.d_val |= DF_1_EDITED;
d29b2c4438482eb00488be49a1f5d6835f455546ab dyn[flags_1_elt.dn_ndx] = flags_1_elt.dn_dyn;
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_modified_data(dynsec);
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab }
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ab#ifdef _ELF64
d29b2c4438482eb00488be49a1f5d6835f455546ab state.elf.obj_state.s64 = obj_state;
d29b2c4438482eb00488be49a1f5d6835f455546ab#else
d29b2c4438482eb00488be49a1f5d6835f455546ab state.elf.obj_state.s32 = obj_state;
d29b2c4438482eb00488be49a1f5d6835f455546ab#endif
d29b2c4438482eb00488be49a1f5d6835f455546ab return;
d29b2c4438482eb00488be49a1f5d6835f455546ab
d29b2c4438482eb00488be49a1f5d6835f455546ablibelf_failure:
d29b2c4438482eb00488be49a1f5d6835f455546ab /*
d29b2c4438482eb00488be49a1f5d6835f455546ab * Control comes here if there is an error with LIBELF.
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * entry:
d29b2c4438482eb00488be49a1f5d6835f455546ab * libelf_fail_name - Name of failing libelf function
d29b2c4438482eb00488be49a1f5d6835f455546ab * tstate.os_file - Name of ELF file being processed
d29b2c4438482eb00488be49a1f5d6835f455546ab * tstate.os_fd - Descriptor of open ELF file
d29b2c4438482eb00488be49a1f5d6835f455546ab *
d29b2c4438482eb00488be49a1f5d6835f455546ab * exit:
d29b2c4438482eb00488be49a1f5d6835f455546ab * - dynamic memory is released if necessary
d29b2c4438482eb00488be49a1f5d6835f455546ab * - The error issued
d29b2c4438482eb00488be49a1f5d6835f455546ab */
d29b2c4438482eb00488be49a1f5d6835f455546ab if (obj_state != NULL)
d29b2c4438482eb00488be49a1f5d6835f455546ab free(obj_state);
d29b2c4438482eb00488be49a1f5d6835f455546ab (void) close(tstate.os_fd);
d29b2c4438482eb00488be49a1f5d6835f455546ab elfedit_elferr(tstate.os_file, libelf_fail_name);
d29b2c4438482eb00488be49a1f5d6835f455546ab#undef INITIAL_SYMTABNDX_ALLOC
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami#undef LIBELF_FAIL
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami#undef LIBELF
d29b2c4438482eb00488be49a1f5d6835f455546ab}