1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Relocate debug information. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng In addition, as a special exception, Red Hat, Inc. gives You the 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng additional right to link the code of Red Hat elfutils with code licensed 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng under any Open Source Initiative certified open source license 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (http://www.opensource.org/licenses/index.php) which requires the 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng distribution of source code with any binary distribution and to 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng distribute linked combinations of the two. Non-GPL Code permitted under 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this exception must only link to the code of Red Hat elfutils through 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng those well defined interfaces identified in the file named EXCEPTION 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng found in the source code files (the "Approved Interfaces"). The files 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng of Non-GPL Code may instantiate templates or use macros or inline 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng functions from the Approved Interfaces without causing the resulting 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng work to be covered by the GNU General Public License. Only Red Hat, 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc. may make changes or additions to the list of Approved Interfaces. 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat's grant of this exception is conditioned upon your not adding 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng any new exceptions. If you wish to add a new Approved Interface or 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception, please contact Red Hat. You must obey the GNU General Public 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng License in all respects for all of the Red Hat elfutils code and other 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng code used in conjunction with Red Hat elfutils except the Non-GPL Code 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng covered by this exception. If you modify this file, you may extend this 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception to your version of the file, but you are not obligated to do 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng so. If you do not wish to provide this exception without modification, 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng you must delete this exception statement from your version and license 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this file solely under the GPL without exception. 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "libdwflP.h" 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengtypedef uint8_t GElf_Byte; 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Adjust *VALUE to add the load address of the SHNDX section. 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We update the section header in place to cache the result. */ 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDwfl_Error 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenginternal_function 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word shndx, GElf_Addr *value) 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *refscn = elf_getscn (elf, shndx); 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem); 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (refshdr == NULL) 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC)) 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This is a loaded section. Find its actual 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng address and update the section header. */ 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*shstrndx == SHN_UNDEF 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && unlikely (elf_getshstrndx (elf, shstrndx) < 0)) 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name); 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (name == NULL)) 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod), 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name, shndx, refshdr, 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &refshdr->sh_addr)) 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return CBFAIL; 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (refshdr->sh_addr == (Dwarf_Addr) -1l) 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The callback indicated this section wasn't really loaded but we 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng don't really care. */ 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng refshdr->sh_addr = 0; /* Make no adjustment below. */ 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Update the in-core file's section header to show the final 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng load address (or unloadedness). This serves as a cache, 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng so we won't get here again for the same section. */ 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (refshdr->sh_addr != 0) 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && unlikely (! gelf_update_shdr (refscn, refshdr))) 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Apply the adjustment. */ 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *value += refshdr->sh_addr; 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_NOERROR; 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Cache used by relocate_getsym. */ 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct reloc_symtab_cache 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *symelf; 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata; 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symxndxdata; 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symstrdata; 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t symshstrndx; 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t strtabndx; 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define RELOC_SYMTAB_CACHE(cache) \ 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct reloc_symtab_cache cache = \ 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF } 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This is just doing dwfl_module_getsym, except that we must always use 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the symbol table in RELOCATED itself when it has one, not MOD->symfile. */ 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Dwfl_Error 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengrelocate_getsym (Dwfl_Module *mod, 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *relocated, struct reloc_symtab_cache *cache, 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int symndx, GElf_Sym *sym, GElf_Word *shndx) 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cache->symdata == NULL) 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod->symfile == NULL || mod->symfile->elf != relocated) 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have to look up the symbol table in the file we are 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocating, if it has its own. These reloc sections refer to 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the symbol table in this file, and a symbol table in the main 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng file might not match. However, some tools did produce ET_REL 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .debug files with relocs but no symtab of their own. */ 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (relocated, scn)) != NULL) 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr != NULL) 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr->sh_type) 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_SYMTAB: 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symelf = relocated; 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symdata = elf_getdata (scn, NULL); 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->strtabndx = shdr->sh_link; 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (cache->symdata == NULL)) 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_SYMTAB_SHNDX: 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symxndxdata = elf_getdata (scn, NULL); 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (cache->symxndxdata == NULL)) 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cache->symdata != NULL && cache->symxndxdata != NULL) 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cache->symdata == NULL) 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We might not have looked for a symbol table file yet, 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng when coming from __libdwfl_relocate_section. */ 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (mod->symfile == NULL) 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0)) 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return dwfl_errno (); 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The symbol table we have already cached is the one from 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the file being relocated, so it's what we need. Or else 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this is an ET_REL .debug file with no .symtab of its own; 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the symbols refer to the section indices in the main file. */ 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symelf = mod->symfile->elf; 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symdata = mod->symdata; 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symxndxdata = mod->symxndxdata; 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cache->symstrdata = mod->symstrdata; 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata, 180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symndx, sym, shndx) == NULL)) 181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *shndx = sym->st_shndx; 185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (*shndx) 187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHN_ABS: 189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHN_UNDEF: 190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHN_COMMON: 191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_NOERROR; 192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx, 195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *shndx, &sym->st_value); 196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle an undefined symbol. We really only support ET_REL for Linux 199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng kernel modules, and offline archives. The behavior of the Linux module 200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng loader is very simple and easy to mimic. It only matches magically 201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exported symbols, and we match any defined symbols. But we get the same 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng answer except when the module's symbols are undefined and would prevent 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it from being loaded. */ 204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Dwfl_Error 205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengresolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab, 206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym, GElf_Word shndx) 207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First we need its name. */ 209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_name != 0) 210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symtab->symstrdata == NULL) 212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Cache the strtab for this symtab. */ 214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (referer->symfile == NULL 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || referer->symfile->elf != symtab->symelf); 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf, 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symtab->strtabndx), 218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL); 219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (symtab->symstrdata == NULL)) 220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (sym->st_name >= symtab->symstrdata->d_size)) 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_BADSTROFF; 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = symtab->symstrdata->d_buf; 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name += sym->st_name; 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next) 229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (m != referer) 230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get this module's symtab. 232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If we got a fresh error reading the table, report it. 233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If we just have no symbols in this module, no harm done. */ 234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (m->symdata == NULL 235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && m->symerr == DWFL_E_NOERROR 236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && INTUSE(dwfl_module_getsymtab) (m) < 0 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && m->symerr != DWFL_E_NO_SYMTAB) 238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return m->symerr; 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t ndx = 1; ndx < m->syments; ++ndx) 241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym = gelf_getsymshndx (m->symdata, m->symxndxdata, 243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx, sym, &shndx); 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (sym == NULL)) 245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = sym->st_shndx; 248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We are looking for a defined global symbol with a name. */ 250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx == SHN_UNDEF || shndx == SHN_COMMON 251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || GELF_ST_BIND (sym->st_info) == STB_LOCAL 252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || sym->st_name == 0) 253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get this candidate symbol's name. */ 256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (sym->st_name >= m->symstrdata->d_size)) 257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_BADSTROFF; 258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *n = m->symstrdata->d_buf; 259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n += sym->st_name; 260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Does the name match? */ 262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcmp (name, n)) 263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We found it! */ 266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx == SHN_ABS) 267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_NOERROR; 268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* In an ET_REL file, the symbol table values are relative 270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng to the section, not to the module's load base. */ 271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t symshstrndx = SHN_UNDEF; 272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return __libdwfl_relocate_value (m, m->symfile->elf, 273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &symshstrndx, 274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx, &sym->st_value); 275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_RELUNDEF; 280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Dwfl_Error 283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengrelocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, 284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, 285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn, GElf_Shdr *shdr, 286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *tscn, bool debugscn, bool partial) 287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First, fetch the name of the section these relocations apply to. */ 289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr tshdr_mem; 290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem); 291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name); 292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (tname == NULL) 293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) 296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This relocation section is not for a debugging section. 297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Nothing to do here. */ 298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_NOERROR; 299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Fetch the section data that needs the relocations applied. */ 301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *tdata = elf_rawdata (tscn, NULL); 302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (tdata == NULL) 303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Apply one relocation. Returns true for any invalid data. */ 306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend, 307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int rtype, int symndx) 308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First see if this is a reloc we can handle. 310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If we are skipping it, don't bother resolving the symbol. */ 311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (type == ELF_T_NUM)) 313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_BADRELTYPE; 314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First, resolve the symbol to an absolute value. */ 316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr value; 317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symndx == STN_UNDEF) 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* When strip removes a section symbol referring to a 320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng section moved into the debuginfo file, it replaces 321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng that symbol index in relocs with STN_UNDEF. We 322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng don't actually need the symbol, because those relocs 323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng are always references relative to the nonallocated 324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debugging sections, which start at zero. */ 325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng value = 0; 326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym; 329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx; 330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, 331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symndx, &sym, &shndx); 332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (error != DWFL_E_NOERROR)) 333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return error; 334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx == SHN_UNDEF || shndx == SHN_COMMON) 336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Maybe we can figure it out anyway. */ 338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error = resolve_symbol (mod, reloc_symtab, &sym, shndx); 339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (error != DWFL_E_NOERROR) 340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return error; 341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng value = sym.st_value; 344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* These are the types we can relocate. */ 347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ 348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ 349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) 350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t size; 351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (type) 352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name) \ 354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ELF_T_##NAME: \ 355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size = sizeof (GElf_##Name); \ 356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break 357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TYPES; 358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE 359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_BADRELTYPE; 361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (offset + size > tdata->d_size) 364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_BADRELOFF; 365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name) GElf_##Name Name; 367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union { TYPES; } tmpbuf; 368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE 369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data tmpdata = 370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = type, 372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = &tmpbuf, 373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = size, 374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data rdata = 377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = type, 379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = tdata->d_buf + offset, 380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = size, 381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* XXX check for overflow? */ 385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (addend) 386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* For the addend form, we have the value already. */ 388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng value += *addend; 389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (type) 390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name) \ 392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ELF_T_##NAME: \ 393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf.Name = value; \ 394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break 395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TYPES; 396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE 397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng abort (); 399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Extract the original value and apply the reloc. */ 404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, 405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr->e_ident[EI_DATA]); 406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (d == NULL) 407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d == &tmpdata); 409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (type) 410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define DO_TYPE(NAME, Name) \ 412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ELF_T_##NAME: \ 413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf.Name += (GElf_##Name) value; \ 414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break 415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TYPES; 416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef DO_TYPE 417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng abort (); 419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now convert the relocated datum back to the target 423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng format. This will write into rdata.d_buf, which 424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng points into the raw section data being relocated. */ 425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata, 426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr->e_ident[EI_DATA]); 427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s == NULL) 428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (s == &rdata); 430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have applied this relocation! */ 432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_NOERROR; 433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Fetch the relocation section and apply each reloc in it. */ 436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *reldata = elf_getdata (scn, NULL); 437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (reldata == NULL) 438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Error result = DWFL_E_NOERROR; 441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool first_badreltype = true; 442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline void check_badreltype (void) 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (first_badreltype) 445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng first_badreltype = false; 447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_get_elfmachine (mod->ebl) == EM_NONE) 448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This might be because ebl_openbackend failed to find 449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng any libebl_CPU.so library. Diagnose that clearly. */ 450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = DWFL_E_UNKNOWN_MACHINE; 451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nrels = shdr->sh_size / shdr->sh_entsize; 455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t complete = 0; 456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type == SHT_REL) 457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem); 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r == NULL) 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = relocate (r->r_offset, NULL, 463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_TYPE (r->r_info), 464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_SYM (r->r_info)); 465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_badreltype (); 466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (partial) 467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (result) 468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_NOERROR: 470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We applied the relocation. Elide it. */ 471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (&rel_mem, 0, sizeof rel_mem); 472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_update_rel (reldata, relidx, &rel_mem); 473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++complete; 474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_BADRELTYPE: 476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_RELUNDEF: 477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We couldn't handle this relocation. Skip it. */ 478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = DWFL_E_NOERROR; 479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t relidx = 0; !result && relidx < nrels; ++relidx) 486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx, 488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &rela_mem); 489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r == NULL) 490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = relocate (r->r_offset, &r->r_addend, 492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_TYPE (r->r_info), 493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_SYM (r->r_info)); 494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_badreltype (); 495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (partial) 496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (result) 497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_NOERROR: 499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We applied the relocation. Elide it. */ 500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (&rela_mem, 0, sizeof rela_mem); 501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_update_rela (reldata, relidx, &rela_mem); 502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++complete; 503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_BADRELTYPE: 505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DWFL_E_RELUNDEF: 506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We couldn't handle this relocation. Skip it. */ 507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = DWFL_E_NOERROR; 508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (result == DWFL_E_NOERROR)) 515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!partial || complete == nrels) 517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Mark this relocation section as being empty now that we have 518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng done its work. This affects unstrip -R, so e.g. it emits an 519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng empty .rela.debug_info along with a .debug_info that has 520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng already been fully relocated. */ 521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nrels = 0; 522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (complete != 0) 523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We handled some of the relocations but not all. 525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We've zeroed out the ones we processed. 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Now remove them from the section. */ 527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t next = 0; 529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type == SHT_REL) 530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t relidx = 0; relidx < nrels; ++relidx) 531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); 534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r->r_info != 0 || r->r_offset != 0) 535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (next != relidx) 537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_update_rel (reldata, next, r); 538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++next; 539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t relidx = 0; relidx < nrels; ++relidx) 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); 546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0) 547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (next != relidx) 549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_update_rela (reldata, next, r); 550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++next; 551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nrels = next; 554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize; 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_update_shdr (scn, shdr); 558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDwfl_Error 564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenginternal_function 565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) 566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (mod->e_type == ET_REL); 568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr_mem; 570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem); 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr == NULL) 572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t d_shstrndx; 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elf_getshstrndx (debugfile, &d_shstrndx) < 0) 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng RELOC_SYMTAB_CACHE (reloc_symtab); 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Look at each section in the debuginfo file, and process the 581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocation sections for debugging sections. */ 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Error result = DWFL_E_NOERROR; 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (result == DWFL_E_NOERROR 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (scn = elf_nextscn (debugfile, scn)) != NULL) 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_size != 0) 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* It's a relocation section. */ 594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info); 596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (tscn == NULL)) 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = DWFL_E_LIBELF; 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = relocate_section (mod, debugfile, ehdr, d_shstrndx, 600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &reloc_symtab, scn, shdr, tscn, 601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debug, !debug); 602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDwfl_Error 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenginternal_function 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *relocscn, Elf_Scn *tscn, bool partial) 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr_mem; 614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng RELOC_SYMTAB_CACHE (reloc_symtab); 617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t shstrndx; 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elf_getshstrndx (relocated, &shstrndx) < 0) 620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWFL_E_LIBELF; 621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (__libdwfl_module_getebl (mod) 623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ?: relocate_section (mod, relocated, 624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_getehdr (relocated, &ehdr_mem), shstrndx, 625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &reloc_symtab, 626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocscn, gelf_getshdr (relocscn, &shdr_mem), 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tscn, false, partial)); 628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 629