Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:lafenghu
libdwarf
libdwarf-relocation-support.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libdwarf-relocation-support.patch of Package libdwarf
From: Daniel Gollub <dgollub@suse.de> Subject: Initial ELF RELA/REL relocation support for libdwarf Signed-off-by: Daniel Gollub <dgollub@suse.de> --- diff --git a/libdwarf/Makefile.in b/libdwarf/Makefile.in index 4af29b3..22e5444 100644 --- a/libdwarf/Makefile.in +++ b/libdwarf/Makefile.in @@ -72,6 +72,7 @@ OBJS= dwarf_abbrev.o \ dwarf_arange.o \ dwarf_die_deliv.o \ dwarf_elf_access.o \ + dwarf_elf_relocation.o \ dwarf_error.o \ dwarf_form.o \ dwarf_frame.o \ diff --git a/libdwarf/dwarf_elf_access.c b/libdwarf/dwarf_elf_access.c index f0ed70c..eeb4936 100644 --- a/libdwarf/dwarf_elf_access.c +++ b/libdwarf/dwarf_elf_access.c @@ -37,6 +37,7 @@ #include "config.h" #include "dwarf_incl.h" #include "dwarf_elf_access.h" +#include "dwarf_elf_relocation.h" #ifdef HAVE_ELF_H #include <elf.h> @@ -218,6 +219,9 @@ dwarf_elf_object_access_get_section_info( *error = DW_DLE_ELF_STRPTR_ERROR; return DW_DLV_ERROR; } + + ret_scn->section_header = shdr64; + return DW_DLV_OK; } #endif /* HAVE_ELF64_GETSHDR */ @@ -235,6 +239,9 @@ dwarf_elf_object_access_get_section_info( *error = DW_DLE_ELF_STRPTR_ERROR; return DW_DLV_ERROR; } + + ret_scn->section_header = shdr32; + return DW_DLV_OK; } @@ -305,6 +312,87 @@ dwarf_elf_object_access_load_section(void* obj_in, return DW_DLV_OK; } +/* + dwarf_elf_object_access_is_relocatable + */ +static +int +dwarf_elf_object_access_is_relocatable(void* obj_in, Dwarf_Bool *is_relocatable, int* error) +{ + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; + + *is_relocatable = FALSE; + +#ifdef HAVE_ELF64_GETEHDR + if (obj->is_64bit) { + if (obj->ehdr64->e_type == ET_REL) + *is_relocatable = TRUE; + } else +#endif + { + if (obj->ehdr32->e_type == ET_REL) + *is_relocatable = TRUE; + } + + return DW_DLV_OK; +} + +/* + dwarf_elf_object_access_apply_relocation + */ +static +int +dwarf_elf_object_access_apply_relocation(void* obj_in, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + Dwarf_Small *relocation_section, + Dwarf_Obj_Access_Section *relocation_section_info, + int* error) +{ + Dwarf_Half machine; + Elf32_Shdr *shdr32 = 0; + Dwarf_Bool is_rela = FALSE; + int res; + +#ifdef HAVE_ELF64_GETSHDR + Elf64_Shdr *shdr64 = 0; +#endif + + + dwarf_elf_object_access_internals_t*obj = + (dwarf_elf_object_access_internals_t*)obj_in; +#ifdef HAVE_ELF64_GETEHDR + if (obj->is_64bit) { + machine = obj->ehdr64->e_machine; + shdr64 = relocation_section_info->section_header; + if (shdr64->sh_type == SHT_RELA) { + is_rela = TRUE; + } + } else +#endif + { + machine = obj->ehdr32->e_machine; + shdr32 = relocation_section_info->section_header; + if (shdr32->sh_type == SHT_RELA) { + is_rela = TRUE; + } + + } + + + res = dwarf_elf_relocation_apply(obj->is_64bit, + is_rela, + obj->endianness, + machine, + target_section, + symtab_section, + relocation_section, + relocation_section_info->size, + error); + + return res; +} /* dwarf_elf_access method table. */ static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods = @@ -314,7 +402,9 @@ static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods = dwarf_elf_object_access_get_length_size, dwarf_elf_object_access_get_pointer_size, dwarf_elf_object_access_get_section_count, - dwarf_elf_object_access_load_section + dwarf_elf_object_access_load_section, + dwarf_elf_object_access_is_relocatable, + dwarf_elf_object_access_apply_relocation }; diff --git a/libdwarf/dwarf_elf_relocation.c b/libdwarf/dwarf_elf_relocation.c new file mode 100644 index 0000000..88b44b0 --- /dev/null +++ b/libdwarf/dwarf_elf_relocation.c @@ -0,0 +1,517 @@ +/* + Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008 Novell, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + +*/ + +#include "config.h" +#include "dwarf_incl.h" + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_ELF_H +#include <elf.h> +#endif + +typedef struct { + Dwarf_ufixed64 r_offset; + /*Dwarf_ufixed64 r_info;*/ + Dwarf_ufixed64 r_type; + Dwarf_ufixed64 r_symidx; + Dwarf_ufixed64 r_addend; +} Dwarf_Elf_Rela; + +/* ELF RELA */ +static void +get_rela_elf32(Dwarf_Small *data, unsigned int i, Dwarf_Elf_Rela *relap) +{ + Elf32_Rela *relap32; + + relap32 = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela))); + relap->r_offset = relap32->r_offset; + /* + relap->r_info = relap32->r_info; + */ + relap->r_type = ELF32_R_TYPE(relap32->r_info); + relap->r_symidx = ELF32_R_SYM(relap32->r_info); + + relap->r_addend = relap32->r_addend; +} + +static void +get_rela_elf64(Dwarf_Small *data, unsigned int i, Dwarf_Elf_Rela *relap) +{ + Elf64_Rela *relap64; + + relap64 = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela))); + relap->r_offset = relap64->r_offset; + /* + relap->r_info = relap64->r_info; + */ + relap->r_type = ELF64_R_TYPE(relap64->r_info); + relap->r_symidx = ELF64_R_SYM(relap64->r_info); + + relap->r_addend = relap64->r_addend; +} + +/* ELF REL */ +static void +get_rel_elf32(Dwarf_Small *data, unsigned int i, Dwarf_Elf_Rela *relap) +{ + Elf32_Rel *relp32; + + relp32 = (Elf32_Rel*)(data + (i * sizeof(Elf32_Rel))); + relap->r_offset = relp32->r_offset; + /* + relap->r_info = relp32->r_info; + */ + relap->r_type = ELF32_R_TYPE(relp32->r_info); + relap->r_symidx = ELF32_R_SYM(relp32->r_info); + + relap->r_addend = 0; +} + +static void +get_rel_elf64(Dwarf_Small *data, unsigned int i, Dwarf_Elf_Rela *relap) +{ + Elf64_Rel *relp64; + + relp64 = (Elf64_Rel*)(data + (i * sizeof(Elf64_Rel))); + relap->r_offset = relp64->r_offset; + /* + relap->r_info = relp64->r_info; + */ + relap->r_type = ELF64_R_TYPE(relp64->r_info); + relap->r_symidx = ELF64_R_SYM(relp64->r_info); + + relap->r_addend = 0; +} + +static void +get_relocations(Dwarf_Bool is_64bit, Dwarf_Bool is_rela, Dwarf_Small *data, + unsigned int num_relocations, Dwarf_Elf_Rela *relap) +{ + + unsigned int i; + void (*get_relocations)(Dwarf_Small *data, unsigned int i, Dwarf_Elf_Rela *relap); + + /* Handle 32/64 bit issue + */ + if (is_64bit) { + if (is_rela) { + get_relocations = get_rela_elf64; + } else { + get_relocations = get_rel_elf64; + } + } else { + if (is_rela) { + get_relocations = get_rela_elf32; + } else { + get_relocations = get_rel_elf32; + } + } + + for (i=0; i < num_relocations; i++) { + get_relocations(data, i, &(relap[i])); + } + +} + +static int +get_relocation_entries(Dwarf_Bool is_64bit, + Dwarf_Bool is_rela, + Dwarf_Small *relocation_section, + Dwarf_Unsigned relocation_section_size, + Dwarf_Elf_Rela **relas, + unsigned int *nrelas, + int *error) +{ + unsigned int relocation_size = 0; + + if (is_64bit) { + if (is_rela) + relocation_size = sizeof(Elf64_Rela); + else + relocation_size = sizeof(Elf64_Rel); + } else { + if (is_rela) + relocation_size = sizeof(Elf32_Rela); + else + relocation_size = sizeof(Elf32_Rel); + } + + if (relocation_section == NULL) { + /* TODO: _dwarf_error() handling required? */ + return(DW_DLV_ERROR); + } + + if ((relocation_section_size != 0)) { + *nrelas = relocation_section_size/relocation_size; + *relas = malloc (*nrelas * sizeof(Dwarf_Elf_Rela)); + if (!*relas) { + *error = DW_DLE_MAF; + return(DW_DLV_ERROR); + } + + get_relocations(is_64bit, is_rela, relocation_section, *nrelas, *relas); + } + return(DW_DLV_OK); +} + +static uint64_t +byte_get_little_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[0])) + | (((unsigned int) (field[1])) << 8); + + case 4: + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); + + case 8: + if (sizeof (unsigned long long) == 8) + return ((unsigned long long) (field[0])) + | (((unsigned long long) (field[1])) << 8) + | (((unsigned long long) (field[2])) << 16) + | (((unsigned long long) (field[3])) << 24) + | (((unsigned long long) (field[4])) << 32) + | (((unsigned long long) (field[5])) << 40) + | (((unsigned long long) (field[6])) << 48) + | (((unsigned long long) (field[7])) << 56); + else if (sizeof (unsigned long long) == 4) + /* We want to extract data from an 8 byte wide field and + place it into a 4 byte wide field. Since this is a little + endian source we can just use the 4 byte extraction code. */ + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); + + default: + fprintf(stderr, "Unhandled data length: %d\n", size); + abort(); + } +} + +static uint64_t +byte_get_big_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); + + case 4: + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); + + case 8: + if (sizeof (unsigned long long) == 8) + return ((unsigned long long) (field[7])) + | (((unsigned long long) (field[6])) << 8) + | (((unsigned long long) (field[5])) << 16) + | (((unsigned long long) (field[4])) << 24) + | (((unsigned long long) (field[3])) << 32) + | (((unsigned long long) (field[2])) << 40) + | (((unsigned long long) (field[1])) << 48) + | (((unsigned long long) (field[0])) << 56); + else if (sizeof (unsigned long long) == 4) + { + /* Although we are extracing data from an 8 byte wide field, + we are returning only 4 bytes of data. */ + field += 4; + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); + } + + default: + fprintf(stderr, "Unhandled data length: %d\n", size); + abort(); + } +} + + +static void +byte_put_little_endian (unsigned char *field, uint64_t value, int size) +{ + switch (size) { + case 8: + field[7] = (((value >> 24) >> 24) >> 8) & 0xff; + field[6] = ((value >> 24) >> 24) & 0xff; + field[5] = ((value >> 24) >> 16) & 0xff; + field[4] = ((value >> 24) >> 8) & 0xff; + /* Fall through. */ + case 4: + field[3] = (value >> 24) & 0xff; + field[2] = (value >> 16) & 0xff; + /* Fall through. */ + case 2: + field[1] = (value >> 8) & 0xff; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + printf ("Unhandled data length: %d\n", size); + abort (); + } +} + +static void +byte_put_big_endian (unsigned char *field, uint64_t value, int size) +{ + switch (size) { + case 8: + field[7] = value & 0xff; + field[6] = (value >> 8) & 0xff; + field[5] = (value >> 16) & 0xff; + field[4] = (value >> 24) & 0xff; + value >>= 16; + value >>= 16; + /* Fall through. */ + case 4: + field[3] = value & 0xff; + field[2] = (value >> 8) & 0xff; + value >>= 16; + /* Fall through. */ + case 2: + field[1] = value & 0xff; + value >>= 8; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + printf("Unhandled data length: %d\n", size); + abort (); + } +} + +static Dwarf_Bool +is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine) { + switch (machine) { + case EM_386: + return type == R_386_32; + case EM_IA_64: + return type == R_IA64_SECREL32LSB; + case EM_PPC64: + return type == R_PPC64_ADDR32; + case EM_PPC: + return type == R_PPC_ADDR32; + case EM_S390: + return type == R_390_32; + case EM_X86_64: + return type == R_X86_64_32; + default: + return 0; + } +} + +static Dwarf_Bool +is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine) { + switch (machine) { + case EM_IA_64: + return type == R_IA64_DIR64LSB; + case EM_PPC64: + return type == R_PPC64_ADDR64; + case EM_S390: + return type == R_390_64; + case EM_X86_64: + return type == R_X86_64_64; + default: + return 0; + } +} + +static Dwarf_Bool +is_32bit_pcrel_reloc(unsigned int type, Dwarf_Half machine) { + switch (machine) { + case EM_386: + return type == R_386_PC32; + case EM_PPC64: + return type == R_PPC64_REL32; + case EM_PPC: + return type == R_PPC_REL32; + case EM_S390: + return type == R_390_PC32; + case EM_X86_64: + return type == R_X86_64_PC32; + default: + return 0; + } +} + + +static void +update_entry(Dwarf_Bool is_64bit, Dwarf_Bool is_rela, Dwarf_Endianness endianess, + Dwarf_Half machine, Dwarf_Elf_Rela *rela, + Dwarf_Small *target_section, Dwarf_Small *section_data) +{ + unsigned int type, sym_idx; + Elf64_Sym sym_buf; + Elf64_Sym *sym; + Elf32_Sym *sym32; + void (*byte_put) (unsigned char *field, uint64_t value, int size); + uint64_t (*byte_get) (unsigned char *field, int size); + Dwarf_ufixed64 offset; + Dwarf_sfixed64 addend; + Dwarf_Unsigned reloc_size; + + /* Dwarf_Elf_Rela dereferencing */ + offset = rela->r_offset; + addend = rela->r_addend; + type = rela->r_type; + sym_idx = rela->r_symidx; + + if (is_64bit) { + sym = &((Elf64_Sym*)section_data)[sym_idx]; + } else { + sym32 = &((Elf32_Sym*)section_data)[sym_idx]; + + /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at + * an Elf64_Sym local variable (sym_buf) to allow us to use the + * same pointer (sym) for both 32-bit and 64-bit instances. + */ + sym = &sym_buf; + sym->st_name = (Elf64_Word)sym32->st_name; + sym->st_info = sym32->st_info; + sym->st_other = sym32->st_other; + sym->st_shndx = (Elf64_Section)sym32->st_shndx; + sym->st_value = (Elf64_Addr)sym32->st_value; + sym->st_size = (Elf64_Xword)sym32->st_size; + } + + + /* TODO: handle REL without addend! */ + + /* Determine endianess */ + if (endianess == DW_OBJECT_MSB) { + byte_put = byte_put_big_endian; + byte_get = byte_get_big_endian; + } else { + byte_put = byte_put_little_endian; + byte_get = byte_get_little_endian; + } + + /* Determine relocation size */ + if (is_32bit_abs_reloc(type, machine)) { + reloc_size = 4; + } else if (is_64bit_abs_reloc(type, machine)) { + reloc_size = 8; + } else { + /* TODO: implemente 16bit ... */ + /* TODO: abort! */ + fprintf(stderr, "Unable to determine relocate size of reloc_type: %d\n", type); + exit(1); + return; + } + + addend = is_rela ? addend : byte_get(target_section + offset, reloc_size); + + if (is_32bit_pcrel_reloc(type, machine)) { + /* Relative */ + byte_put(target_section + offset, + (sym->st_value + addend) - offset, reloc_size); + } else { + /* Absolute */ + byte_put(target_section + offset, sym->st_value + addend, reloc_size); + } +} + +static int +apply_rela_entries(Dwarf_Bool is_64bit, + Dwarf_Bool is_rela, + Dwarf_Endianness endianess, + Dwarf_Half machine, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + Dwarf_Elf_Rela *relas, unsigned int nrelas, + int *error) +{ + unsigned int i; + + if ((target_section != NULL) && (relas != NULL)) { + for (i = 0; i < nrelas; i++) { + update_entry(is_64bit, + is_rela, + endianess, + machine, + &(relas)[i], + target_section, + symtab_section); + } + } + + return DW_DLV_OK; +} + +int +dwarf_elf_relocation_apply( + Dwarf_Bool is_64bit, + Dwarf_Bool is_rela, + Dwarf_Endianness endianess, + Dwarf_Half machine, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + Dwarf_Small *relocation_section, + Dwarf_Unsigned relocation_section_size, + int *error) +{ + int ret; + Dwarf_Elf_Rela *relas; + unsigned int nrelas; + + if ((ret = get_relocation_entries(is_64bit, is_rela, + relocation_section, + relocation_section_size, + &relas, &nrelas, error))) + return ret; + + if ((ret = apply_rela_entries(is_64bit, is_rela, + endianess, machine, + target_section, + symtab_section, + relas, nrelas, error))) + return ret; + + return DW_DLV_OK; +} + diff --git a/libdwarf/dwarf_elf_relocation.h b/libdwarf/dwarf_elf_relocation.h new file mode 100644 index 0000000..df93eb1 --- /dev/null +++ b/libdwarf/dwarf_elf_relocation.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008 Novell, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, + USA. + +*/ + +#ifndef DWARF_ELF_RELOCATION_H_ +#define DWARF_ELF_RELOCATION_H_ + +/* ELF RELA and REL relocation */ +int dwarf_elf_relocation_apply(Dwarf_Bool is_64bit, + Dwarf_Bool is_rela, + Dwarf_Endianness endianess, + Dwarf_Half machine, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + Dwarf_Small *relocation_section, + Dwarf_Unsigned relocation_section_size, + int *error); + + +#endif /*DWARF_ELF_RELOCATION_H_*/ + diff --git a/libdwarf/dwarf_init_finish.c b/libdwarf/dwarf_init_finish.c index 4fd7401..404592c 100644 --- a/libdwarf/dwarf_init_finish.c +++ b/libdwarf/dwarf_init_finish.c @@ -95,9 +95,12 @@ static int _dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) { const char *scn_name = 0; + int err, res = 0; int foundDwarf = 0; struct Dwarf_Obj_Access_Interface_s * obj = 0; + struct Dwarf_Obj_Access_Section_s doas; + Dwarf_Bool is_relocatable; Dwarf_Endianness endianness; Dwarf_Unsigned section_size = 0; @@ -142,10 +145,6 @@ _dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) for (section_index = 0; section_index < section_count; ++section_index) { - struct Dwarf_Obj_Access_Section_s doas; - Dwarf_Error section_error; - int res; - int err; res = obj->methods->get_section_info(obj->object, section_index, @@ -158,7 +157,20 @@ _dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) section_size = doas.size; scn_name = doas.name; - if (strncmp(scn_name, ".debug_", 7) + if (strcmp(scn_name, ".rela.debug_info") == 0 + || strcmp(scn_name, ".rel.debug_info") == 0) { + if (dbg->de_rela_debug_info != NULL) { + continue; + } + if (section_size == 0) { + continue; + } + dbg->de_rela_debug_info_index = section_index; + dbg->de_rela_debug_info_size = section_size; + } else if (strcmp(scn_name, ".symtab") == 0) { + dbg->de_symtab_index = section_index; + dbg->de_symtab_size = section_size; + } else if (strncmp(scn_name, ".debug_", 7) && strcmp(scn_name, ".eh_frame") ) continue; @@ -374,10 +386,54 @@ _dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error) dbg->de_debug_macinfo_size = section_size; } } - if (foundDwarf) { - return DW_DLV_OK; + if (!foundDwarf) { + return (DW_DLV_NO_ENTRY); + } + res = obj->methods->is_relocatable(obj->object, &is_relocatable, &err); + + if (res == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } + + /* Only try to relocate if: + * - object format is relocatable + * - any relocation section is available + */ + if (is_relocatable + && dbg->de_rela_debug_info_size + && dbg->de_symtab_size) { + + /* Load the rela- and regular debug info section in advance! */ + res = _dwarf_load_debug_info(dbg, error); + if (res != DW_DLV_OK) { + return res; + } + + /* Load symtab for relocation */ + res = _dwarf_load_symtab(dbg, error); + if (res != DW_DLV_OK) { + return res; + } + + res = obj->methods->get_section_info(obj->object, + dbg->de_rela_debug_info_index, + &doas, &err); + if (res == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } + + res = obj->methods->apply_relocation(obj->object, + dbg->de_debug_info, + dbg->de_symtab, + dbg->de_rela_debug_info, + &doas, &err); + + if (res == DW_DLV_ERROR) { + DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR); + } } - return (DW_DLV_NO_ENTRY); + + return (DW_DLV_OK); } @@ -517,3 +573,5 @@ dwarf_get_section_max_offsets(Dwarf_Debug dbg, return DW_DLV_OK; } + + diff --git a/libdwarf/dwarf_opaque.h b/libdwarf/dwarf_opaque.h index 13fe701..1b52969 100644 --- a/libdwarf/dwarf_opaque.h +++ b/libdwarf/dwarf_opaque.h @@ -188,6 +188,8 @@ struct Dwarf_Debug_s { Dwarf_Signed de_fde_count; Dwarf_Small *de_debug_info; + Dwarf_Small *de_rela_debug_info; + Dwarf_Small *de_symtab; Dwarf_Small *de_debug_abbrev; Dwarf_Small *de_debug_line; Dwarf_Small *de_debug_loc; @@ -211,6 +213,8 @@ struct Dwarf_Debug_s { Dwarf_Small *de_debug_weaknames; Dwarf_Unsigned de_debug_info_size; + Dwarf_Unsigned de_rela_debug_info_size; + Dwarf_Unsigned de_symtab_size; Dwarf_Unsigned de_debug_abbrev_size; Dwarf_Unsigned de_debug_line_size; Dwarf_Unsigned de_debug_loc_size; @@ -259,6 +263,8 @@ struct Dwarf_Debug_s { Dwarf_Half de_debug_frame_eh_gnu_index; Dwarf_Half de_debug_str_index; Dwarf_Half de_debug_info_index; + Dwarf_Half de_rela_debug_info_index; + Dwarf_Half de_symtab_index; Dwarf_Half de_debug_abbrev_index; Dwarf_Half de_debug_pubtypes_index; /* DWARF3 .debug_pubtypes */ diff --git a/libdwarf/dwarf_util.c b/libdwarf/dwarf_util.c index 6cbd92f..7040a6c 100644 --- a/libdwarf/dwarf_util.c +++ b/libdwarf/dwarf_util.c @@ -479,9 +479,35 @@ _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error) } res = _dwarf_load_section(dbg, dbg->de_debug_info_index, &dbg->de_debug_info, error); + if (res != DW_DLV_OK) { + return res; + } + + /* + * Load RELA section, if present, for proper relocation itself. + */ + if (dbg->de_rela_debug_info_index) { + res = _dwarf_load_section(dbg, dbg->de_rela_debug_info_index, + &dbg->de_rela_debug_info, error); + } return res; +} + +int +_dwarf_load_symtab(Dwarf_Debug dbg, Dwarf_Error * error) +{ + int res; + + if (dbg->de_symtab) { + return DW_DLV_OK; + } + + res = _dwarf_load_section(dbg, dbg->de_symtab_index, + &dbg->de_symtab, error); + return res; } + void _dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,Dwarf_Hash_Table hash_table) { diff --git a/libdwarf/dwarf_util.h b/libdwarf/dwarf_util.h index 7bd8883..290e8d5 100644 --- a/libdwarf/dwarf_util.h +++ b/libdwarf/dwarf_util.h @@ -303,6 +303,7 @@ Dwarf_Unsigned _dwarf_length_of_cu_header(Dwarf_Debug, Dwarf_Unsigned _dwarf_length_of_cu_header_simple(Dwarf_Debug); int _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error *error); +int _dwarf_load_symtab(Dwarf_Debug dbg, Dwarf_Error *error); void _dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg, struct Dwarf_Hash_Table_s* hash_table); diff --git a/libdwarf/libdwarf.h b/libdwarf/libdwarf.h index c8440cc..e2ea2c6 100644 --- a/libdwarf/libdwarf.h +++ b/libdwarf/libdwarf.h @@ -440,7 +440,6 @@ typedef Dwarf_Unsigned Dwarf_Tag; */ typedef void (*Dwarf_Handler)(Dwarf_Error /*error*/, Dwarf_Ptr /*errarg*/); - /* Begin libdwarf Object File Interface declarations. As of February 2008 there are multiple dwarf_reader object access @@ -472,11 +471,18 @@ typedef struct Dwarf_Obj_Access_Section_s Dwarf_Obj_Access_Section; method of setting up 'sections equivalents') must arrange to return standard DWARF section names in the 'name' field. libdwarf does - not free the strings in 'name'. */ + not free the strings in 'name'. + + section header contains pointer to format specific + header information about this certain information. + + */ struct Dwarf_Obj_Access_Section_s { Dwarf_Addr addr; Dwarf_Unsigned size; const char* name; + /* TODO: Some generic value or Bool if the section is relocatable?! */ + void *section_header; }; /* Returned by the get_endianness function in @@ -591,6 +597,47 @@ struct Dwarf_Obj_Access_Methods_s { */ int (*load_section)(void* obj, Dwarf_Half section_index, Dwarf_Small** return_data, int* error); + /** + * is_relocatable + * + * Check if object file is relocatable. + * + * Parameters + * is_reloctabler - Pointer to a Dwarf_Bool for returning the + * relocatable status. TRUE if relocatable, FALSE otherwise. + * error - Pointer to an integer for returning libdwarf-defined + * error numbers. + * + * Return + * DW_DLV_OK - No error. + * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined + * error number. + */ + int (*is_relocatable)(void* obj, Dwarf_Bool *is_relocatable, int* error); + /** + * apply_relocation + * + * Apply object file specific relocation. + * + * Parameters + * target_section - section to relocate + * symtab_section - section which points to symbol table + * relocation_section - section which contains relocation information + * relocation_section_info - information about the relocation section + * error - Pointer to an integer for returning libdwarf-defined + * error numbers. + * + * Return + * DW_DLV_OK - No error. + * DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined + * error number. + */ + int (*apply_relocation)(void* obj, + Dwarf_Small *target_section, + Dwarf_Small *symtab_section, + Dwarf_Small *relocation_section, + Dwarf_Obj_Access_Section *relocation_section_info, + int* error); };
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor