39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * CDDL HEADER START
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The contents of this file are subject to the terms of the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Common Development and Distribution License (the "License").
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * You may not use this file except in compliance with the License.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * or http://www.opensolaris.org/os/licensing.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * See the License for the specific language governing permissions
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and limitations under the License.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * When distributing Covered Code, include this CDDL HEADER in each
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If applicable, add the following below this CDDL HEADER, with the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fields enclosed by brackets "[]" replaced with your own identifying
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * information: Portions Copyright [yyyy] [name of copyright owner]
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * CDDL HEADER END
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Use is subject to license terms.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Generate a cache of section header information for an ELF
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * object from the information found in its program headers.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Malicious code can remove or corrupt section headers. The
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * resulting program will be difficult to analyze, but is still
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * runnable. Hence, scribbling on the section headers or removing
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * them is an effective form of obfuscation. On the other hand,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * program headers must be accurate or the program will not run.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Section headers derived from them will necessarily lack information
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * found in the originals (particularly for non-allocable sections),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * but will provide essential symbol information. The focus is on
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * recovering information that elfdump knows how to display, and that
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * might be interesting in a forensic situation.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * There are some things we don't attempt to create sections for:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * plt, got
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * We have no way to determine the length of either of
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * these sections from the information available via
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the program headers or dynamic section. The data in
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the PLT is of little use to elfdump. The data in the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * GOT might be somewhat more interesting, especially as
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * it pertains to relocations. However, the sizing issue
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * remains.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * text, data, bss
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Although we could create these, there is little value
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * to doing so. elfdump cannot display the arbitrary
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * data in these sections, so this would amount to a
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * simple repetition of the information already displayed
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in the program headers, with no additional benefit.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <sys/elf_amd64.h>
a194faf8907a6722dcf10ad16c6ca72c9b7bd0barie#include <stdio.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <unistd.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <errno.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <string.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <strings.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <conv.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <msg.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab#include <_elfdump.h>
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Common information about the object that is needed by
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * all the routines in this module.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abtypedef struct {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab const char *file;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int fd;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Ehdr *ehdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr *phdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t phnum;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab} FSTATE;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * These values uniquely identify the sections that we know
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * how to recover.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Note: We write the sections to the cache array in this same order.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * It simplifies this code if the dynamic, dynstr, dynsym, and ldynsym
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sections occupy known slots in the cache array. Other sections reference
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * them by index, and if they are at a known spot, there is no need
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * for a fixup pass. Putting them in positions [1-4] solves this.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The order they are in was chosen such that if any one of them exists,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * all of the ones before it must also exist. This means that if the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * desired section exists, it will end up in the desired index in the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * cache array.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The order of the other sections is arbitrary. I've arranged them
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in roughly related groups.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abtypedef enum {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_NULL = 0,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_DYN = 1,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_DYNSTR = 2,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_DYNSYM = 3,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_LDYNSYM = 4,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_HASH = 5,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_SYMINFO = 6,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_SYMSORT = 7,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_TLSSORT = 8,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_VERNEED = 9,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_VERDEF = 10,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_VERSYM = 11,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_INTERP = 12,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_T_CAP = 13,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_CAPINFO = 14,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_CAPCHAIN = 15,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_UNWIND = 16,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_MOVE = 17,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_REL = 18,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_RELA = 19,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_PREINITARR = 20,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_INITARR = 21,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_FINIARR = 22,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_NOTE = 23,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO_T_NUM = 24 /* Count of items. Must come last */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab} SINFO_TYPE;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Table of per-section constant data used to set up the section
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * header cache and the various sub-parts it references. Indexed by
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * SINFO_T value.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * note: The sh_flags value should be either SHF_ALLOC, or 0.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * get_data() sets SHF_WRITE if the program header containing the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * section is writable. The other flags require information that
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the program headers don't contain (i.e. SHF_STRINGS, etc) so
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * we don't set them.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abtypedef struct {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab const char *name;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word sh_type;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word sh_flags;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word sh_addralign;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word sh_entsize;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Elf_Type libelf_type;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab} SINFO_DATA;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab/*
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * Many of these sections use an alignment given by M_WORD_ALIGN, a
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * value that varies depending on the object target machine. Since we
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * don't know that value at compile time, we settle for a value of
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * 4 for ELFCLASS32 objects, and 8 for ELFCLASS64. This matches the
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * platforms we current support (sparc and x86), and is good enough for
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * a fake section header in any event, as the resulting object is only
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab * analyzed, and is not executed.
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab */
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#ifdef _ELF64
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#define FAKE_M_WORD_ALIGN 8
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#else
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#define FAKE_M_WORD_ALIGN 4
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab#endif
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic SINFO_DATA sinfo_data[SINFO_T_NUM] = {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_NULL */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { 0 },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_DYN */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_DYN), SHT_DYNAMIC, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Dyn), ELF_T_DYN },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_DYNSTR */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_DYNSTR), SHT_STRTAB, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab 1, 0, ELF_T_BYTE },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_DYNSYM */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_DYNSYM), SHT_DYNSYM, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_LDYNSYM */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_LDYNSYM), SHT_SUNW_LDYNSYM, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Sym), ELF_T_SYM },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_HASH */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_HASH), SHT_HASH, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_SYMINFO */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_SYMINFO), SHT_SUNW_syminfo, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Syminfo), ELF_T_SYMINFO },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_SYMSORT */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_SYMSORT), SHT_SUNW_symsort, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_TLSSORT */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_TLSSORT), SHT_SUNW_tlssort, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Word), ELF_T_WORD },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_VERNEED */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verneed, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, 1, ELF_T_VNEED },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_VERDEF */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_verdef, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, 1, ELF_T_VDEF },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_VERSYM */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_VER), SHT_SUNW_versym, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Versym), ELF_T_HALF },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_INTERP */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_INTERP), SHT_PROGBITS, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab 1, 0, ELF_T_BYTE },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_CAP */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_CAP), SHT_SUNW_cap, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (Addr), sizeof (Cap), ELF_T_CAP },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans /* SINFO_T_CAPINFO */
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans { MSG_ORIG(MSG_PHDRNAM_CAPINFO), SHT_SUNW_capinfo, SHF_ALLOC,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans FAKE_M_WORD_ALIGN, sizeof (Capinfo), ELF_T_WORD },
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans /* SINFO_T_CAPCHAIN */
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans { MSG_ORIG(MSG_PHDRNAM_CAPCHAIN), SHT_SUNW_capchain, SHF_ALLOC,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans FAKE_M_WORD_ALIGN, sizeof (Capchain), ELF_T_WORD },
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_UNWIND */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_UNWIND), SHT_AMD64_UNWIND, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (Addr), 0, ELF_T_BYTE },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_MOVE */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_MOVE), SHT_SUNW_move, SHF_ALLOC,
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans sizeof (Lword), sizeof (Move), ELF_T_MOVE },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_REL */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_REL), SHT_REL, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Rel), ELF_T_REL },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_RELA */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_RELA), SHT_RELA, SHF_ALLOC,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, sizeof (Rela), ELF_T_RELA },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_PREINITARR */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_PREINITARR), SHT_PREINIT_ARRAY, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (Addr), sizeof (Addr), ELF_T_ADDR },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_INITARR */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_INITARR), SHT_INIT_ARRAY, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (Addr), sizeof (Addr), ELF_T_ADDR },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_FINIARR */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_FINIARR), SHT_FINI_ARRAY, SHF_ALLOC,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (Addr), sizeof (Addr), ELF_T_ADDR },
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* SINFO_T_NOTE */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab { MSG_ORIG(MSG_PHDRNAM_NOTE), SHT_NOTE, 0,
ba2be53024c0b999e74ba9adcd7d80fec5df8c57ab FAKE_M_WORD_ALIGN, 1, ELF_T_NOTE }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab};
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * As we read program headers and dynamic elements, we build up
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the data for our fake section headers in variables of the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * SINFO type. SINFO is used to track the sections that can only
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * appear a fixed number of times (usually once).
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * SINFO_LISTELT is used for sections that can occur an arbitrary
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * number of times. They are kept in a doubly linked circular
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * buffer.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abtypedef struct {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_TYPE type; /* Our type code for the section */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Addr vaddr; /* Virtual memory address */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off offset; /* File offset of data. Ignored unless */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* vaddr is 0. Used by program headers */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t size; /* # bytes in section */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t vercnt; /* Used by verdef and verneed to hold count */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Shdr *shdr; /* Constructed shdr */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Elf_Data *data; /* Constructed data descriptor */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab} SINFO;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5abtypedef struct _sinfo_listelt {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab struct _sinfo_listelt *next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab struct _sinfo_listelt *prev;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO sinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab} SINFO_LISTELT;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Free dynamic memory used by SINFO structures.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sinfo - Address of first SINFO structure to free
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * n - # of structures to clear
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * For each SINFO struct, the section header, data descriptor,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and data buffer are freed if non-NULL. The relevant
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fields are set to NULL, and the type is set to SINFO_T_NULL.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic void
39773e466ff90ce703d7f52f3267d7e96c09c6f5absinfo_free(SINFO *sinfo, size_t n)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (; n-- > 0; sinfo++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data != NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data->d_buf != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(sinfo->data->d_buf);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(sinfo->data);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->data = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->shdr) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(sinfo->shdr);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->shdr = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Allocate a new SINFO_LISTELT and put it at the end of the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * doubly linked list anchored by the given list root node.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, a new node has been put at the end of the circular
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * doubly linked list, and a pointer to the SINFO sub-structure is
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * returned. On failure, an error is printed, and NULL is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic SINFO *
39773e466ff90ce703d7f52f3267d7e96c09c6f5absinfo_list_alloc(FSTATE *fstate, SINFO_LISTELT *root)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_LISTELT *elt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((elt = malloc(sizeof (*elt))) == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int err = errno;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->file, strerror(err));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab elt->next = root;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab elt->prev = root->prev;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab root->prev = elt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab elt->prev->next = elt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab bzero(&elt->sinfo, sizeof (elt->sinfo));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (&elt->sinfo);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Release the memory used by the given list, restoring it to
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * an empty list.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic void
39773e466ff90ce703d7f52f3267d7e96c09c6f5absinfo_list_free_all(SINFO_LISTELT *root)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_LISTELT *elt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (elt = root->next; elt != root; elt = elt->next)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(&elt->sinfo, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab root->next = root->prev = root;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Given a virtual address and desired size of the data to be found
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * at that address, look through the program headers for the PT_LOAD
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * segment that contains it and return the offset within the ELF file
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * at which it resides.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fstate - Object state
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * addr - virtual address to be translated
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * size - Size of the data to be found at that address, in bytes
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * zero_bytes - NULL, or address to receive the number of data
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * bytes at the end of the data that are not contained
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in the file, and which must be zero filled by the caller.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If zero_bytes is NULL, the file must contain all of the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * desired data. If zero_bytes is not NULL, then the program
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * header must reserve the space for all of the data (p_memsz)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * but it is acceptable for only part of the data to be in
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the file (p_filesz). *zero_bytes is set to the difference
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in size, and is the number of bytes the caller must
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * set to 0 rather than reading from the file.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * phdr_ret - NULL, or address of variable to receive pointer
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * to program header that contains offset.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success: If zero_bytes is non-NULL, it is updated. If phdr_ret
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * is non-NULL, it is updated. The file offset is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On failure, 0 is returned. Since any ELF file we can understand
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * must start with an ELF magic number, 0 cannot be a valid file
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * offset for a virtual address, and is therefore unambiguous as
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * a failure indication.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic Off
39773e466ff90ce703d7f52f3267d7e96c09c6f5abmap_addr_to_offset(FSTATE *fstate, Addr addr, size_t size, size_t *zero_bytes,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr **phdr_ret)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Addr end_addr = addr + size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t avail_file;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr *phdr = fstate->phdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t phnum = fstate->phnum;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (; phnum--; phdr++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (phdr->p_type != PT_LOAD)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((addr >= phdr->p_vaddr) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (end_addr <= (phdr->p_vaddr + phdr->p_memsz))) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Subtract segment virtual address, leaving the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * offset relative to the segment (not the file).
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab offset = addr - phdr->p_vaddr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab avail_file = phdr->p_filesz - offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The addr/size are in bounds for this segment.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Is there enough data in the file to satisfy
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the request? If zero_bytes is NULL, it must
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * all be in the file. Otherwise it can be
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * zero filled.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (zero_bytes == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (size > avail_file)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *zero_bytes = (size > avail_file) ?
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (size - avail_file) : 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (phdr_ret != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *phdr_ret = phdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Add segment file offset, giving overall offset */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (phdr->p_offset + offset);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* If we get here, the mapping failed */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * This routine is the same thing as map_addr_to_offset(), except that
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * it goes the other way, mapping from offset to virtual address.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The comments for map_addr_to_offset() are applicable if you
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * reverse offset and address.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic Addr
39773e466ff90ce703d7f52f3267d7e96c09c6f5abmap_offset_to_addr(FSTATE *fstate, Off offset, size_t size, size_t *zero_bytes,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr **phdr_ret)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off end_offset = offset + size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t avail_file;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr *phdr = fstate->phdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t phnum = fstate->phnum;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (; phnum--; phdr++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (phdr->p_type != PT_LOAD)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((offset >= phdr->p_offset) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (end_offset <= (phdr->p_offset + phdr->p_memsz))) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Subtract segment offset, leaving the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * offset relative to the segment (not the file).
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab offset -= phdr->p_offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab avail_file = phdr->p_filesz - offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The offset/size are in bounds for this segment.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Is there enough data in the file to satisfy
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the request? If zero_bytes is NULL, it must
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * all be in the file. Otherwise it can be
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * zero filled.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (zero_bytes == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (size > avail_file)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *zero_bytes = (size > avail_file) ?
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (size - avail_file) : 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (phdr_ret != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *phdr_ret = phdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Add segment virtual address, giving overall addr */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (phdr->p_vaddr + offset);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* If we get here, the mapping failed */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Use elf_xlatetom() to convert the bytes in buf from their
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in-file representation to their in-memory representation.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Returns True(1) for success. On failure, an error message is printed
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and False(0) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abxlate_data(FSTATE *fstate, void *buf, size_t nbyte, Elf_Type xlate_type)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Elf_Data data;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_type = xlate_type;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_size = nbyte;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_off = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_align = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_version = fstate->ehdr->e_version;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab data.d_buf = buf;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (elf_xlatetom(&data, &data,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->ehdr->e_ident[EI_DATA]) == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab failure(fstate->file, MSG_ORIG(MSG_ELF_XLATETOM));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read nbytes of data into buf, starting at the specified offset
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * within the ELF file.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fstate - Object state
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * offset - Offset within the file at which desired data resides.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * buf - Buffer to receive the data
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * nbyte - # of bytes to read into buf
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * xlate_type - An ELF xlate type, specifying the type of data
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * being input. If xlate_type is ELF_T_BYTE, xlate is not
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * done. Otherwise, xlate_data() is called to convert the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * data into its in-memory representation.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, the data has been written into buf, xlate_data()
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * called on it if required, and True(1) is returned. Otherwise
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * False(0) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * note:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * This routine does not move the file pointer.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abread_data(FSTATE *fstate, Off offset, void *buf, size_t nbyte,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Elf_Type xlate_type)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (pread(fstate->fd, buf, nbyte, offset) != nbyte) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int err = errno;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) fprintf(stderr, MSG_INTL(MSG_ERR_READ),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->file, strerror(err));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_type != ELF_T_BYTE)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (xlate_data(fstate, buf, nbyte, xlate_type));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read the hash nbucket/nchain values from the start of the hash
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * table found at the given virtual address in the mapped ELF object.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, *nbucket, and *nchain have been filled in with their
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * values, *total contains the number of elements in the hash table,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and this routine returns True (1).
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On failure, False (0) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abhash_size(FSTATE *fstate, SINFO *hash_sinfo,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word *nbucket, Word *nchain, size_t *total)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word buf[2];
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab offset = map_addr_to_offset(fstate, hash_sinfo->vaddr,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sizeof (buf), NULL, NULL);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (offset == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (read_data(fstate, offset, buf, sizeof (buf), ELF_T_WORD) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *nbucket = buf[0];
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *nchain = buf[1];
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *total = 2 + *nbucket + *nchain;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read a Verdef structure at the specified file offset and return
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * its vd_cnt, vd_aux, and vd_next fields.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abread_verdef(FSTATE *fstate, Off offset, Half *cnt, Word *aux, Word *next)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Verdef verdef;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (read_data(fstate, offset, &verdef, sizeof (verdef),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_BYTE) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* xlate vd_cnt */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &verdef.vd_cnt, sizeof (verdef.vd_cnt),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_HALF) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * xlate vd_aux and vd_next. These items are adjacent and are
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * both Words, so they can be handled in a single operation.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &verdef.vd_aux,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab 2 * sizeof (Word), ELF_T_WORD) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *cnt = verdef.vd_cnt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *aux = verdef.vd_aux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *next = verdef.vd_next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read a Verdaux structure at the specified file offset and return
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * its vda_next field.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abread_verdaux(FSTATE *fstate, Off offset, Word *next)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Verdaux verdaux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (read_data(fstate, offset, &verdaux, sizeof (verdaux),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_BYTE) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* xlate vda_next */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &verdaux.vda_next, sizeof (verdaux.vda_next),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_WORD) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *next = verdaux.vda_next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read a Verneed structure at the specified file offset and return
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * its vn_cnt, vn_aux, and vn_next fields.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abread_verneed(FSTATE *fstate, Off offset, Half *cnt, Word *aux, Word *next)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Verneed verneed;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (read_data(fstate, offset, &verneed, sizeof (verneed),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_BYTE) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* xlate vn_cnt */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &verneed.vn_cnt, sizeof (verneed.vn_cnt),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_HALF) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * xlate vn_aux and vn_next. These items are adjacent and are
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * both Words, so they can be handled in a single operation.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &verneed.vn_aux,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab 2 * sizeof (Word), ELF_T_WORD) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *cnt = verneed.vn_cnt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *aux = verneed.vn_aux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *next = verneed.vn_next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Read a Vernaux structure at the specified file offset and return
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * its vna_next field.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abread_vernaux(FSTATE *fstate, Off offset, Word *next)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Vernaux vernaux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (read_data(fstate, offset, &vernaux, sizeof (vernaux),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_BYTE) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* xlate vna_next */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (xlate_data(fstate, &vernaux.vna_next, sizeof (vernaux.vna_next),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ELF_T_WORD) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *next = vernaux.vna_next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Compute the size of Verdef and Verneed sections. Both of these
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sections are made up of interleaved main nodes (Verdef and Verneed)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and auxiliary blocks (Verdaux and Vernaux). These nodes refer to
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * each other by relative offsets. The linker has a lot of flexibility
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in how it lays out these items, and we cannot assume a standard
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * layout. To determine the size of the section, we must read each
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * main node and compute the high water mark of the memory it and its
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * auxiliary structs access.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Although Verdef/Verdaux and Verneed/Vernaux are different types,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * their logical organization is the same. Each main block has
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * a cnt field that tells how many auxiliary blocks it has, an
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * aux field that gives the offset of the first auxiliary block, and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * an offset to the next main block. Each auxiliary block contains
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * an offset to the next auxiliary block. By breaking the type specific
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * code into separate sub-functions, we can process both Verdef and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sections Verdaux from a single routine.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fstate - Object state
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sec - Section to be processed (SINFO_T_VERDEF or SINFO_T_VERNEED).
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, sec->size is set to the section size in bytes, and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * True (1) is returned. On failure, False (0) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abverdefneed_size(FSTATE *fstate, SINFO *sec)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int (* read_main)(FSTATE *, Off, Half *, Word *, Word *);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int (* read_aux)(FSTATE *, Off, Word *);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t size_main, size_aux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off offset, aux_offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Off highwater, extent;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t num_main = sec->vercnt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Half v_cnt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word v_aux, v_next, va_next;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Set up the function pointers to the type-specific code
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * for fetching data from the main and auxiliary blocks.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec->type == SINFO_T_VERDEF) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_main = read_verdef;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_aux = read_verdaux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_main = sizeof (Verdef);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_aux = sizeof (Verdaux);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else { /* SINFO_T_VERNEED */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_main = read_verneed;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_aux = read_vernaux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_main = sizeof (Verneed);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_aux = sizeof (Vernaux);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Map starting address to file offset. Save the starting offset
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in the SINFO size field. Once we have the high water offset, we
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * can subtract this from it to get the size.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Note: The size argument set here is a lower bound --- the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * size of the main blocks without any auxiliary ones. It's
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the best we can do until the size has been determined for real.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab offset = highwater = map_addr_to_offset(fstate, sec->vaddr,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_main * num_main, NULL, NULL);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (offset == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->size = offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (; num_main-- > 0; offset += v_next) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Does this move the high water mark up? */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab extent = offset + size_main;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (extent > highwater)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab highwater = extent;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((*read_main)(fstate, offset, &v_cnt, &v_aux, &v_next) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If there are auxiliary structures referenced,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * check their position to see if it pushes
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the high water mark.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab aux_offset = offset + v_aux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (; v_cnt-- > 0; aux_offset += va_next) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab extent = aux_offset + size_aux;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (extent > highwater)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab highwater = extent;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((*read_aux)(fstate, aux_offset, &va_next) == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->size = highwater - sec->size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Allocate and fill in a fake section header, data descriptor,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and data buffer for the given section. Fill them in and read
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the associated data into the buffer.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fstate - Object state
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sec - Section information
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, the actions described above are complete, and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * True (1) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On failure, an error is reported, all resources used by sec
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * are released, and sec->type is set to SINFO_T_NULL, effectively
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * eliminating its contents from any further use. False (0) is
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abstatic int
39773e466ff90ce703d7f52f3267d7e96c09c6f5abget_data(FSTATE *fstate, SINFO *sec)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_DATA *tinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t read_bytes, zero_bytes;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Phdr *phdr = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If this is a NULL section, or if we've already processed
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * this item, then we are already done.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sec->type == SINFO_T_NULL) || (sec->shdr != NULL))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (((sec->shdr = malloc(sizeof (*sec->shdr))) == NULL) ||
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ((sec->data = malloc(sizeof (*sec->data))) == NULL)) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int err = errno;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(sec, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->file, strerror(err));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab tinfo = &sinfo_data[sec->type];
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Fill in fake section header
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sh_name should be the offset of the name in the shstrtab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * section referenced by the ELF header. There is no
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * value to elfdump in creating shstrtab, so we set
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * sh_name to 0, knowing that elfdump doesn't look at it.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_name = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_type = tinfo->sh_type;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_flags = tinfo->sh_flags;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((tinfo->sh_flags & SHF_ALLOC) == 0) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Non-allocable section: Pass the addr (which is probably
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * 0) and offset through without inspection.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_addr = sec->vaddr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_offset = sec->offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab zero_bytes = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else if (sec->vaddr == 0) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Allocable section with a 0 vaddr. Figure out the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * real address by mapping the offset to it using the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * program headers.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_addr = map_offset_to_addr(fstate, sec->offset,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->size, &zero_bytes, &phdr);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_offset = sec->offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Allocable section with non-0 vaddr. Use the vaddr
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * to derive the offset.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_addr = sec->vaddr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_offset = map_addr_to_offset(fstate,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->vaddr, sec->size, &zero_bytes, &phdr);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec->shdr->sh_offset == 0) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(sec, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If the program header has its write flags set, then set
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the section write flag.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (phdr && ((phdr->p_flags & PF_W) != 0))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_flags |= SHF_WRITE;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_size = sec->size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_info = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_addralign = tinfo->sh_addralign;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_entsize = tinfo->sh_entsize;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Some sections define special meanings for sh_link and sh_info.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab switch (tinfo->sh_type) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_DYNAMIC:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSTR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_DYNSYM:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSTR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_info = 1; /* First global symbol */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_LDYNSYM:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSTR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * ldynsym is all local symbols, so the index of the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * first global is equivalent to the number of symbols.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_info = sec->shdr->sh_size / sizeof (Sym);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_HASH:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_move:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_REL:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_RELA:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_versym:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_verdef:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_verneed:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSTR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_info = sec->vercnt;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_syminfo:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_DYNSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_info = SINFO_T_DYN;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_symsort:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case SHT_SUNW_tlssort:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->shdr->sh_link = SINFO_T_LDYNSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Fill in fake Elf_Data descriptor */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_type = tinfo->libelf_type;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_size = sec->size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_off = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_align = tinfo->sh_addralign;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_version = fstate->ehdr->e_version;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec->size == 0) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec->data->d_buf = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sec->data->d_buf = malloc(sec->size)) == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int err = errno;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(sec, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->file, strerror(err));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_bytes = sec->size - zero_bytes;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((read_bytes > 0) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (read_data(fstate, sec->shdr->sh_offset, sec->data->d_buf,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab read_bytes, ELF_T_BYTE) == 0)) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(sec, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (zero_bytes > 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab bzero(read_bytes + (char *)sec->data->d_buf, zero_bytes);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((tinfo->libelf_type != ELF_T_BYTE) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (elf_xlatetom(sec->data, sec->data,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate->ehdr->e_ident[EI_DATA]) == NULL)) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(sec, 1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab failure(fstate->file, MSG_ORIG(MSG_ELF_XLATETOM));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Generate a section header cache made up of information derived
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * from the program headers.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * entry:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * file - Name of object
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fd - Open file handle for object
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * elf - ELF descriptor
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * ehdr - Elf header
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * cache, shnum - Addresses of variables to receive resulting
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * cache and number of sections.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * exit:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On success, *cache and *shnum are set, and True (1) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * On failure, False (0) is returned.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * note:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The cache returned by this routine must be freed using
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fake_shdr_cache_free(), and not by a direct call to free().
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Otherwise, memory will leak.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abint
39773e466ff90ce703d7f52f3267d7e96c09c6f5abfake_shdr_cache(const char *file, int fd, Elf *elf, Ehdr *ehdr,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Cache **cache, size_t *shnum)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The C language guarantees that a structure of homogeneous
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * items will receive exactly the same layout in a structure
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * as a plain array of the same type. Hence, this structure, which
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * gives us by-name or by-index access to the various section
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * info descriptors we maintain.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * We use this for sections where
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * - Only one instance is allowed
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * - We need to be able to access them easily by
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * name (for instance, when mining the .dynamic
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * section for information to build them up.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * NOTE: These fields must be in the same order as the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * SINFO_T_ type codes that correspond to them. Otherwise,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * they will end up in the wrong order in the cache array,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and the sh_link/sh_info fields may be wrong.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab struct {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Note: No entry is needed for SINFO_T_NULL */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO dyn;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO dynstr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO dynsym;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO ldynsym;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO hash;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO syminfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO symsort;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO tlssort;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO verneed;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO verdef;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO versym;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO interp;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO cap;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO capinfo;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans SINFO capchain;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO unwind;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO move;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO rel;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO rela;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO preinitarr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO initarr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO finiarr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } sec;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab static const size_t sinfo_n = sizeof (sec) / sizeof (sec.dyn);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO *secarr = (SINFO *) &sec;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Doubly linked circular list, used to track sections
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * where multiple sections of a given type can exist.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * seclist is the root of the list. Its sinfo field is not
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * used --- it serves to anchor the root of the list, allowing
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * rapid access to the first and last element in the list.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_LISTELT seclist;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab FSTATE fstate;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t ndx;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t num_sinfo, num_list_sinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO *sinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab SINFO_LISTELT *sinfo_list;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Cache *_cache;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate.file = file;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate.fd = fd;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab fstate.ehdr = ehdr;
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami if (elf_getphdrnum(elf, &fstate.phnum) == -1) {
62b628a68db596a2d75a316dc7ffef658079231fAli Bahrami failure(file, MSG_ORIG(MSG_ELF_GETPHDRNUM));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((fstate.phdr = elf_getphdr(elf)) == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab failure(file, MSG_ORIG(MSG_ELF_GETPHDR));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab bzero(&sec, sizeof (sec)); /* Initialize "by-name" sec info */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab seclist.next = seclist.prev = &seclist; /* Empty circular list */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Go through the program headers and look for information
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * we can use to synthesize section headers. By far the most
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * valuable thing is a dynamic section, the contents of
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * which point at all sections used by ld.so.1.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (ndx = 0; ndx < fstate.phnum; ndx++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * A program header with no file size does
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * not have a backing section.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (fstate.phdr[ndx].p_filesz == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab switch (fstate.phdr[ndx].p_type) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab default:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Header we can't use. Move on to next one */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case PT_DYNAMIC:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dyn.type = SINFO_T_DYN;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sec.dyn;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case PT_INTERP:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.interp.type = SINFO_T_INTERP;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sec.interp;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case PT_NOTE:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sinfo = sinfo_list_alloc(&fstate, &seclist)) ==
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab continue;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->type = SINFO_T_NOTE;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case PT_SUNW_UNWIND:
7e16fca05dfbcfd32c2ebc9e4d1abdac1cd8657cAli Bahrami case PT_SUNW_EH_FRAME:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.unwind.type = SINFO_T_UNWIND;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sec.unwind;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case PT_SUNWCAP:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.cap.type = SINFO_T_CAP;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sec.cap;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Capture the position/extent information for
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * the header in the SINFO struct set up by the
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * switch statement above.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->vaddr = fstate.phdr[ndx].p_vaddr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->offset = fstate.phdr[ndx].p_offset;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->size = fstate.phdr[ndx].p_filesz;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If we found a dynamic section, look through it and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * gather information about the sections it references.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.dyn.type == SINFO_T_DYN)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) get_data(&fstate, &sec.dyn);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sec.dyn.type == SINFO_T_DYN) && (sec.dyn.data->d_buf != NULL)) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Dyn *dyn;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (dyn = sec.dyn.data->d_buf; dyn->d_tag != DT_NULL; dyn++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab switch (dyn->d_tag) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_HASH:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.hash.type = SINFO_T_HASH;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.hash.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_STRTAB:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynstr.type = SINFO_T_DYNSTR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynstr.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SYMTAB:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.type = SINFO_T_DYNSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_RELA:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rela.type = SINFO_T_RELA;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rela.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_RELASZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rela.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_STRSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynstr.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_REL:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rel.type = SINFO_T_REL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rel.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_RELSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rel.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_INIT_ARRAY:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.initarr.type = SINFO_T_INITARR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.initarr.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_INIT_ARRAYSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.initarr.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_FINI_ARRAY:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.finiarr.type = SINFO_T_FINIARR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.finiarr.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_FINI_ARRAYSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.finiarr.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_PREINIT_ARRAY:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.preinitarr.type = SINFO_T_PREINITARR;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.preinitarr.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_PREINIT_ARRAYSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.preinitarr.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans case DT_SUNW_CAPINFO:
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans sec.capinfo.type = SINFO_T_CAPINFO;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans sec.capinfo.vaddr = dyn->d_un.d_ptr;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans break;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans case DT_SUNW_CAPCHAIN:
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans sec.capchain.type = SINFO_T_CAPCHAIN;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans sec.capchain.vaddr = dyn->d_un.d_ptr;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans break;
08278a5e91755ccdb5850c19d21d42fb2e16b50eRod Evans
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_SYMTAB:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.type = SINFO_T_LDYNSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_SYMSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_SYMSORT:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.symsort.type = SINFO_T_SYMSORT;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.symsort.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_SYMSORTSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.symsort.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_TLSSORT:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.tlssort.type = SINFO_T_TLSSORT;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.tlssort.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SUNW_TLSSORTSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.tlssort.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_MOVETAB:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.move.type = SINFO_T_MOVE;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.move.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_MOVESZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.move.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SYMINFO:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.syminfo.type = SINFO_T_SYMINFO;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.syminfo.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_SYMINSZ:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.syminfo.size = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_VERSYM:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.versym.type = SINFO_T_VERSYM;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.versym.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_VERDEF:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.type = SINFO_T_VERDEF;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_VERDEFNUM:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.vercnt = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.size = sizeof (Verdef) *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_VERNEED:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.type = SINFO_T_VERNEED;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.vaddr = dyn->d_un.d_ptr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab case DT_VERNEEDNUM:
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.vercnt = dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.size = sizeof (Verneed) *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab dyn->d_un.d_val;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab break;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Different sections depend on each other, and are meaningless
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * without them. For instance, even if a .dynsym exists,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * no use can be made of it without a dynstr. These relationships
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * fan out: Disqualifying the .dynsym will disqualify the hash
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * section, and so forth.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Disqualify sections that don't have the necessary prerequisites.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Things that need the dynamic string table */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.dynstr.size == 0)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynstr.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.dynstr.type != SINFO_T_DYNSTR) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(&sec.dyn, 1); /* Data already fetched */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The length of the hash section is encoded in its first two
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * elements (nbucket, and nchain). The length of the dynsym,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * ldynsym, and versym are not given in the dynamic section,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * but are known to be the same as nchain.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If we don't have a hash table, or cannot read nbuckets and
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * nchain, we have to invalidate all of these.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.hash.type == SINFO_T_HASH) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word nbucket;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Word nchain;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab size_t total;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (hash_size(&fstate, &sec.hash,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab &nbucket, &nchain, &total) == 0) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.hash.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab } else {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Use these counts to set sizes for related sections */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.hash.size = total * sizeof (Word);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.size = nchain * sizeof (Sym);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.versym.size = nchain * sizeof (Versym);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The ldynsym size received the DT_SUNW_SYMSZ
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * value, which is the combined size of .dynsym
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * and .ldynsym. Now that we have the dynsym size,
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * use it to lower the ldynsym size to its real size.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.ldynsym.size > sec.dynsym.size)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.size -= sec.dynsym.size;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * If the hash table is not present, or if the call to
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * hash_size() failed, then discard the sections that
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * need it to determine their length.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.hash.type != SINFO_T_HASH) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.dynsym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.versym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * The runtime linker does not receive size information for
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Verdef and Verneed sections. We have to read their data
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * in pieces and calculate it.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sec.verdef.type == SINFO_T_VERDEF) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (verdefneed_size(&fstate, &sec.verdef) == 0))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verdef.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sec.verneed.type == SINFO_T_VERNEED) &&
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (verdefneed_size(&fstate, &sec.verneed) == 0))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.verneed.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Discard any section with a zero length */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ndx = sinfo_n;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (sinfo = secarr; ndx-- > 0; sinfo++)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sinfo->type != SINFO_T_NULL) && (sinfo->size == 0))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo->type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Things that need the dynamic symbol table */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.dynsym.type != SINFO_T_DYNSYM) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.ldynsym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.hash.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.syminfo.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.versym.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.move.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rel.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.rela.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /* Things that need the dynamic local symbol table */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sec.ldynsym.type != SINFO_T_DYNSYM) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.symsort.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sec.tlssort.type = SINFO_T_NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Look through the results and fetch the data for any sections
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * we have found. At the same time, count the number.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab num_sinfo = num_list_sinfo = 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ndx = sinfo_n;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (sinfo = secarr; ndx-- > 0; sinfo++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sinfo->type != SINFO_T_NULL) && (sinfo->data == NULL))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) get_data(&fstate, sinfo);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab num_sinfo++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (sinfo_list = seclist.next; sinfo_list != &seclist;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_list = sinfo_list->next) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sinfo_list->sinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((sinfo->type != SINFO_T_NULL) && (sinfo->data == NULL))
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) get_data(&fstate, sinfo);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab num_list_sinfo++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab /*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Allocate the cache array and fill it in. The cache array
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * ends up taking all the dynamic memory we've allocated
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * to build up sec and seclist, so on success, we have nothing
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * left to clean up. If we can't allocate the cache array
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * though, we have to free up everything else.
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *shnum = num_sinfo + num_list_sinfo + 1; /* Extra for 1st NULL sec. */
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if ((*cache = _cache = malloc((*shnum) * sizeof (Cache))) == NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab int err = errno;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab file, strerror(err));
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_free(secarr, num_sinfo);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_list_free_all(&seclist);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (0);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab *_cache = cache_init;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab ndx = 1;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (sinfo = secarr; num_sinfo > 0; sinfo++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data != NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_scn = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_shdr = sinfo->shdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_data = sinfo->data;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_name = (char *)sinfo_data[sinfo->type].name;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_ndx = ndx++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab num_sinfo--;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (sinfo_list = seclist.next; num_list_sinfo > 0;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo_list = sinfo_list->next) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab sinfo = &sinfo_list->sinfo;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (sinfo->data != NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_scn = NULL;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_shdr = sinfo->shdr;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_data = sinfo->data;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_name = (char *)sinfo_data[sinfo->type].name;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache->c_ndx = ndx++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab _cache++;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab num_list_sinfo--;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab return (1);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab/*
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * Release all the memory referenced by a cache array allocated
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab * by fake_shdr_cache().
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab */
39773e466ff90ce703d7f52f3267d7e96c09c6f5abvoid
39773e466ff90ce703d7f52f3267d7e96c09c6f5abfake_shdr_cache_free(Cache *cache, size_t shnum)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab{
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab Cache *_cache;
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab for (_cache = cache; shnum--; _cache++) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (_cache->c_data != NULL) {
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (_cache->c_data->d_buf != NULL)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(_cache->c_data->d_buf);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(_cache->c_data);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab if (_cache->c_shdr)
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(_cache->c_shdr);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab }
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab free(cache);
39773e466ff90ce703d7f52f3267d7e96c09c6f5ab}