a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* $Id$ */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @file
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * DBGPlugInCommonELF - Code Template for dealing with one kind of ELF.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2008-2013 Oracle Corporation
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License (GPL) as published by the Free Software
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#if ELF_MODE == 32
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Ehdr Elf32_Ehdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Shdr Elf32_Shdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Phdr Elf32_Phdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Sym Elf32_Sym
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define MY_ELFCLASS ELFCLASS32
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define ELF_ST_BIND ELF32_ST_BIND
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define DBGDiggerCommonParseElfMod DBGDiggerCommonParseElf32Mod
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Ehdr Elf64_Ehdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Shdr Elf64_Shdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Phdr Elf64_Phdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define Elf_Sym Elf64_Sym
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define MY_ELFCLASS ELFCLASS64
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define ELF_ST_BIND ELF64_ST_BIND
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync# define DBGDiggerCommonParseElfMod DBGDiggerCommonParseElf64Mod
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Common ELF module parser.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * It takes the essential bits of the ELF module (elf header, section headers,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * symbol table and string table), and inserts/updates the module and symbols.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox status code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pUVM The user mode VM handle.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pszModName The module name.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pszFilename The filename. optional.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param fFlags Flags.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pEhdr Pointer to the ELF header.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param paShdrs Pointer to the section headers. The caller must verify that
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * the e_shnum member of the ELF header is within the bounds of
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * this table. The caller should also adjust the section addresses
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * so these correspond to actual load addresses.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param paSyms Pointer to the symbol table.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param cMaxSyms The maximum number of symbols paSyms may hold. This isn't
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * the exact count, it's just a cap for avoiding SIGSEGVs
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * and general corruption.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pbStrings Pointer to the string table.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param cbMaxStrings The size of the memory pbStrings points to. This doesn't
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * have to match the string table size exactly, it's just to
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * avoid SIGSEGV when a bad string index is encountered.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param MinAddr Min address to care about.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param MaxAddr Max address to care about (inclusive). Together
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * with MinAddr this forms a valid address range for
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * symbols and sections that we care about. Anything
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * outside the range is ignored, except when doing
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * sanity checks..
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param uModTag Module tag. Pass 0 if tagging is of no interest.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
98427c0ab08697e468c26dc33ee9571308577867vboxsyncint DBGDiggerCommonParseElfMod(PUVM pUVM, const char *pszModName, const char *pszFilename, uint32_t fFlags,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Elf_Ehdr const *pEhdr, Elf_Shdr const *paShdrs,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Elf_Sym const *paSyms, size_t cMaxSyms,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char const *pbStrings, size_t cbMaxStrings,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCPTR MinAddr, RTGCPTR MaxAddr, uint64_t uModTag)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
98427c0ab08697e468c26dc33ee9571308577867vboxsync AssertPtrReturn(pUVM, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertReturn(!(fFlags & ~DBG_DIGGER_ELF_MASK), VERR_INVALID_PARAMETER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertReturn((fFlags & (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync != (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE), VERR_INVALID_PARAMETER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(paShdrs, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(paSyms, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtrReturn(pbStrings, VERR_INVALID_POINTER);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Validate the ELF header.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || pEhdr->e_ident[EI_MAG1] != ELFMAG1
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || pEhdr->e_ident[EI_MAG2] != ELFMAG2
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || pEhdr->e_ident[EI_MAG3] != ELFMAG3)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_INVALID_EXE_SIGNATURE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_ident[EI_CLASS] != MY_ELFCLASS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_MACHINE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_ODD_ENDIAN;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_ident[EI_VERSION] != EV_CURRENT)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_VERSION;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_version != EV_CURRENT)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_VERSION;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_ehsize != sizeof(*pEhdr))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#if ELF_MODE == 32
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( pEhdr->e_machine != EM_386
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pEhdr->e_machine != EM_486)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_MACHINE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_machine != EM_X86_64)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_MACHINE;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#endif
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( pEhdr->e_type != ET_DYN
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pEhdr->e_type != ET_REL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pEhdr->e_type != ET_EXEC) //??
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( pEhdr->e_phentsize != sizeof(Elf_Phdr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pEhdr->e_phentsize) //??
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_shentsize != sizeof(Elf_Shdr))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pEhdr->e_shentsize != sizeof(Elf_Shdr))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (ASMMemIsAll8(&pEhdr->e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0) != NULL) //??
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Validate the section headers, finding the string and symbol table
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * headers and the load address while at it.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint64_t uLoadAddr = UINT64_MAX;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const Elf_Shdr *pSymShdr = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const Elf_Shdr *pStrShdr = NULL;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (unsigned iSh = fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS ? 1 : 0; iSh < pEhdr->e_shnum; iSh++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Minimal validation. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paShdrs[iSh].sh_link >= pEhdr->e_shnum)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Is it the symbol table?*/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paShdrs[iSh].sh_type == SHT_SYMTAB)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pSymShdr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_MULTIPLE_SYMTABS;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pSymShdr = &paShdrs[iSh];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pSymShdr->sh_entsize != sizeof(Elf32_Sym))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pStrShdr = &paShdrs[paShdrs[iSh].sh_link];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (uLoadAddr > paShdrs[iSh].sh_addr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uLoadAddr = paShdrs[iSh].sh_addr;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Validate the symbol table and determine the max section index
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * when DBG_DIGGER_ELF_FUNNY_SHDRS is flagged.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t uMaxShIdx = fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS ? 0 : pEhdr->e_shnum - 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t const cbStrings = pStrShdr ? pStrShdr->sh_size : cbMaxStrings;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t const cSyms = pSymShdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync ? RT_MIN(cMaxSyms, pSymShdr->sh_size / sizeof(Elf_Sym))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync : cMaxSyms;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (size_t iSym = 1; iSym < cSyms; iSym++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paSyms[iSym].st_name >= cbStrings)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( paSyms[iSym].st_shndx > uMaxShIdx
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && paSyms[iSym].st_shndx < SHN_LORESERVE)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uMaxShIdx = paSyms[iSym].st_shndx;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if ( paSyms[iSym].st_shndx >= pEhdr->e_shnum
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && paSyms[iSym].st_shndx != SHN_UNDEF
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && ( paSyms[iSym].st_shndx < SHN_LORESERVE
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*|| paSyms[iSym].st_shndx > SHN_HIRESERVE*/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK) )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (uMaxShIdx > 4096)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return VERR_BAD_EXE_FORMAT;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Create new module.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The funny ELF section headers on solaris makes this very complicated.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t cSegs = uMaxShIdx + 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PDBGDIGGERELFSEG paSegs = (PDBGDIGGERELFSEG)alloca(sizeof(paSegs[0]) * cSegs);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (uint32_t i = 0; i < cSegs; i++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[i].uLoadAddr = RTGCPTR_MAX;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[i].uLastAddr = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[i].iSeg = NIL_RTDBGSEGIDX;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDBGMOD hMod;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = RTDbgModCreate(&hMod, pszModName, 0 /*cbSeg*/, 0 /*fFlags*/);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSetTag(hMod, uModTag); AssertRC(rc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Seek out the min and max symbol values for each section. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (uint32_t iSym = 1; iSym < cSyms; iSym++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Ignore undefined, absolute and weak symbols in this pass,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync but include local ones as well as nameless. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t iSh = paSyms[iSym].st_shndx;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( iSh != SHN_UNDEF
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && iSh < cSegs
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || ELF_ST_BIND(paSyms[iSym].st_info) == STB_LOCAL))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Calc the address and check that it doesn't wrap with the size. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCUINTPTR Address = paSyms[iSym].st_value;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCUINTPTR AddressLast = Address + RT_MAX(paSyms[iSym].st_size, 1) - 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (AddressLast < Address)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( Address < MinAddr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || AddressLast > MaxAddr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* update min/max. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (Address < paSegs[iSh].uLoadAddr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[iSh].uLoadAddr = Address;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (AddressLast > paSegs[iSh].uLastAddr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[iSh].uLastAddr = AddressLast;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Add the segments and fill in the translation table. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCPTR uRvaNext = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (unsigned i = 0; i < cSegs; i++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paSegs[i].uLastAddr != 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char szSeg[32];
068ceb4c22977593e2a9e69654726ba221ba8a35vboxsync RTStrPrintf(szSeg, sizeof(szSeg), "sec%02u", i);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCPTR cbSeg = paSegs[i].uLastAddr - paSegs[i].uLoadAddr + 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSegmentAdd(hMod, uRvaNext, cbSeg, szSeg, 0 /*fFlags*/, &paSegs[i].iSeg);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uRvaNext += RT_ALIGN_T(cbSeg, 32, RTGCPTR);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Add the segments and fill in the translation table. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCPTR uRvaNext = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (unsigned i = 0; i < cSegs; i++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paShdrs[i].sh_flags & SHF_ALLOC)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync char szSeg[32];
068ceb4c22977593e2a9e69654726ba221ba8a35vboxsync RTStrPrintf(szSeg, sizeof(szSeg), "sec%02u", i);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSegmentAdd(hMod, paShdrs[i].sh_addr - uLoadAddr, paShdrs[i].sh_size, szSeg, 0 /*fFlags*/, &paSegs[i].iSeg);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[i].uLoadAddr = paShdrs[i].sh_addr;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync paSegs[i].uLastAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size - 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDbgModRelease(hMod);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Add all relevant symbols in the module
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (uint32_t iSym = 1; iSym < cSyms; iSym++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Undefined symbols are not exports, they are imports. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDBGSEGIDX iSeg = paSyms[iSym].st_shndx;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( iSeg != SHN_UNDEF
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && ( ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || ELF_ST_BIND(paSyms[iSym].st_info) == STB_LOCAL
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Get the symbol name. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (paSyms[iSym].st_name >= cbMaxStrings)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *pszSymbol = pbStrings + paSyms[iSym].st_name;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!*pszSymbol)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Calc the address (value) and size. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCUINTPTR cbSym = paSyms[iSym].st_size;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTGCUINTPTR offSeg = paSyms[iSym].st_value;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (iSeg == SHN_ABS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync iSeg = RTDBGSEGIDX_ABS; /* absolute symbols are not subject to any relocation. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(iSeg < cSegs);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fFlags & (DBG_DIGGER_ELF_FUNNY_SHDRS | DBG_DIGGER_ELF_ADJUST_SYM_VALUE))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync offSeg -= paSegs[iSeg].uLoadAddr;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync iSeg = paSegs[iSeg].iSeg;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (iSeg == NIL_RTDBGSEGIDX)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (offSeg + cbSym < offSeg)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync continue;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSymbolAdd(hMod, pszSymbol, iSeg, offSeg, cbSym, 0 /*fFlags*/, NULL);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("%02x:%RGv %RGv %s!%s (rc=%Rrc)\n", paSyms[iSym].st_shndx, offSeg, cbSym, pszModName, pszSymbol, rc));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*else: silently ignore */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Link it into the address space.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
98427c0ab08697e468c26dc33ee9571308577867vboxsync RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (hAs != NIL_RTDBGAS)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = dbgDiggerCommonLinkElfSegs(hAs, hMod, paSegs, cSegs);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = VERR_INTERNAL_ERROR;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDbgModRelease(hMod);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDbgAsRelease(hAs);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return rc;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef Elf_Ehdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef Elf_Shdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef Elf_Phdr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef Elf_Sym
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef MY_ELFCLASS
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef ELF_ST_BIND
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#undef DBGDiggerCommonParseElfMod
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync