107dc194Richard Lowe/*
207dc194Richard Lowe  Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
307dc194Richard Lowe  Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
407dc194Richard Lowe  Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
507dc194Richard Lowe  Portions Copyright 2009-2010 David Anderson. All rights reserved.
607dc194Richard Lowe  Portions Copyright 2009-2010 Novell Inc. All rights reserved.
707dc194Richard Lowe
807dc194Richard Lowe  This program is free software; you can redistribute it and/or modify it
907dc194Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
1007dc194Richard Lowe  as published by the Free Software Foundation.
1107dc194Richard Lowe
1207dc194Richard Lowe  This program is distributed in the hope that it would be useful, but
1307dc194Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1507dc194Richard Lowe
1607dc194Richard Lowe  Further, this software is distributed without any warranty that it is
1707dc194Richard Lowe  free of the rightful claim of any third person regarding infringement
1807dc194Richard Lowe  or the like.  Any license provided herein, whether implied or
1907dc194Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
2007dc194Richard Lowe  any, provided herein do not apply to combinations of this program with
2107dc194Richard Lowe  other software, or any other product whatsoever.
2207dc194Richard Lowe
2307dc194Richard Lowe  You should have received a copy of the GNU Lesser General Public
2407dc194Richard Lowe  License along with this program; if not, write the Free Software
2507dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2607dc194Richard Lowe  USA.
2707dc194Richard Lowe
2807dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2907dc194Richard Lowe  Mountain View, CA 94043, or:
3007dc194Richard Lowe
3107dc194Richard Lowe  http://www.sgi.com
3207dc194Richard Lowe
3307dc194Richard Lowe  For further information regarding this notice, see:
3407dc194Richard Lowe
3507dc194Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3607dc194Richard Lowe
3707dc194Richard Lowe*/
3807dc194Richard Lowe
3907dc194Richard Lowe#include "config.h"
4007dc194Richard Lowe#include "dwarf_incl.h"
4107dc194Richard Lowe#include "dwarf_elf_access.h"
4207dc194Richard Lowe
4307dc194Richard Lowe#ifdef HAVE_ELF_H
4407dc194Richard Lowe#include <elf.h>
4507dc194Richard Lowe#endif
4607dc194Richard Lowe#ifdef HAVE_LIBELF_H
4707dc194Richard Lowe#include <libelf.h>
4807dc194Richard Lowe#else
4907dc194Richard Lowe#ifdef HAVE_LIBELF_LIBELF_H
5007dc194Richard Lowe#include <libelf/libelf.h>
5107dc194Richard Lowe#endif
5207dc194Richard Lowe#endif
5307dc194Richard Lowe
5407dc194Richard Lowe#include <stdio.h>
5507dc194Richard Lowe#include <sys/stat.h>
5607dc194Richard Lowe#include <sys/types.h>
5707dc194Richard Lowe#include <string.h>
5807dc194Richard Lowe#include <stdlib.h>
5907dc194Richard Lowe
6007dc194Richard Lowe#define FALSE 0
6107dc194Richard Lowe#define TRUE  1
6207dc194Richard Lowe
6307dc194Richard Lowe#ifndef EM_MIPS
6407dc194Richard Lowe/* This is the standard elf value EM_MIPS. */
6507dc194Richard Lowe#define EM_MIPS 8
6607dc194Richard Lowe#endif
6707dc194Richard Lowe
6807dc194Richard Lowe
6907dc194Richard Lowe#ifdef HAVE_ELF64_GETEHDR
7007dc194Richard Loweextern Elf64_Ehdr *elf64_getehdr(Elf *);
7107dc194Richard Lowe#endif
7207dc194Richard Lowe#ifdef HAVE_ELF64_GETSHDR
7307dc194Richard Loweextern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
7407dc194Richard Lowe#endif
7507dc194Richard Lowe#ifdef WORDS_BIGENDIAN
7607dc194Richard Lowe#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
7707dc194Richard Lowe    { \
7807dc194Richard Lowe      dbg->de_copy_word(dest, \
7907dc194Richard Lowe                        ((char *)source) +srclength-len_out,  \
8007dc194Richard Lowe                        len_out) ; \
8107dc194Richard Lowe    }
8207dc194Richard Lowe
8307dc194Richard Lowe
8407dc194Richard Lowe#else /* LITTLE ENDIAN */
8507dc194Richard Lowe
8607dc194Richard Lowe#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
8707dc194Richard Lowe    { \
8807dc194Richard Lowe      dbg->de_copy_word( (dest) , \
8907dc194Richard Lowe                        ((char *)source) ,  \
9007dc194Richard Lowe                        len_out) ; \
9107dc194Richard Lowe    }
9207dc194Richard Lowe#endif
9307dc194Richard Lowe
9407dc194Richard Lowe
9507dc194Richard Lowe
9607dc194Richard Lowetypedef struct {
9707dc194Richard Lowe    dwarf_elf_handle elf;
9807dc194Richard Lowe    int              is_64bit;
9907dc194Richard Lowe    Dwarf_Small      length_size;
10007dc194Richard Lowe    Dwarf_Small      pointer_size;
10107dc194Richard Lowe    Dwarf_Unsigned   section_count;
10207dc194Richard Lowe    Dwarf_Endianness endianness;
10307dc194Richard Lowe    Dwarf_Small      machine;
10407dc194Richard Lowe    int              libdwarf_owns_elf;
10507dc194Richard Lowe    Elf32_Ehdr *ehdr32;
10607dc194Richard Lowe
10707dc194Richard Lowe#ifdef HAVE_ELF64_GETEHDR
10807dc194Richard Lowe    Elf64_Ehdr *ehdr64;
10907dc194Richard Lowe#endif
11007dc194Richard Lowe    /* Elf symtab and its strtab.  Initialized at first
11107dc194Richard Lowe       call to do relocations, the actual data is in the Dwarf_Debug
11207dc194Richard Lowe       struct, not allocated locally here. */
11307dc194Richard Lowe    struct Dwarf_Section_s *symtab;
11407dc194Richard Lowe    struct Dwarf_Section_s *strtab;
11507dc194Richard Lowe
11607dc194Richard Lowe} dwarf_elf_object_access_internals_t;
11707dc194Richard Lowe
11807dc194Richard Lowestruct Dwarf_Elf_Rela {
11907dc194Richard Lowe    Dwarf_ufixed64 r_offset;
12007dc194Richard Lowe    /*Dwarf_ufixed64 r_info; */
12107dc194Richard Lowe    Dwarf_ufixed64 r_type;
12207dc194Richard Lowe    Dwarf_ufixed64 r_symidx;
12307dc194Richard Lowe    Dwarf_ufixed64 r_addend;
12407dc194Richard Lowe};
12507dc194Richard Lowe
12607dc194Richard Lowe
12707dc194Richard Lowestatic int dwarf_elf_object_access_load_section(void* obj_in,
12807dc194Richard Lowe    Dwarf_Half section_index,
12907dc194Richard Lowe    Dwarf_Small** section_data,
13007dc194Richard Lowe    int* error);
13107dc194Richard Lowe
13207dc194Richard Lowe/*
13307dc194Richard Lowe    dwarf_elf_object_access_internals_init()
13407dc194Richard Lowe */
13507dc194Richard Lowestatic int
13607dc194Richard Lowedwarf_elf_object_access_internals_init(void* obj_in,
13707dc194Richard Lowe                              dwarf_elf_handle elf,
13807dc194Richard Lowe                              int* error)
13907dc194Richard Lowe{
14007dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
14107dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
14207dc194Richard Lowe    char *ehdr_ident = 0;
14307dc194Richard Lowe    Dwarf_Half machine = 0;
14407dc194Richard Lowe    obj->elf = elf;
14507dc194Richard Lowe
14607dc194Richard Lowe    if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
14707dc194Richard Lowe        *error = DW_DLE_ELF_GETIDENT_ERROR;
14807dc194Richard Lowe        return DW_DLV_ERROR;
14907dc194Richard Lowe    }
15007dc194Richard Lowe
15107dc194Richard Lowe    obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
15207dc194Richard Lowe
15307dc194Richard Lowe
15407dc194Richard Lowe    if(ehdr_ident[EI_DATA] == ELFDATA2LSB){
15507dc194Richard Lowe        obj->endianness = DW_OBJECT_LSB;
15607dc194Richard Lowe    }
15707dc194Richard Lowe    else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){
15807dc194Richard Lowe        obj->endianness = DW_OBJECT_MSB;
15907dc194Richard Lowe    }
16007dc194Richard Lowe
16107dc194Richard Lowe    if (obj->is_64bit) {
16207dc194Richard Lowe#ifdef HAVE_ELF64_GETEHDR
16307dc194Richard Lowe        obj->ehdr64 = elf64_getehdr(elf);
16407dc194Richard Lowe        if (obj->ehdr64 == NULL) {
16507dc194Richard Lowe            *error = DW_DLE_ELF_GETEHDR_ERROR;
16607dc194Richard Lowe            return DW_DLV_ERROR;
16707dc194Richard Lowe        }
16807dc194Richard Lowe        obj->section_count = obj->ehdr64->e_shnum;
16907dc194Richard Lowe        machine = obj->ehdr64->e_machine;
17007dc194Richard Lowe        obj->machine = machine;
17107dc194Richard Lowe#else
17207dc194Richard Lowe        *error = DW_DLE_NO_ELF64_SUPPORT;
17307dc194Richard Lowe        return DW_DLV_ERROR;
17407dc194Richard Lowe#endif
17507dc194Richard Lowe    }
17607dc194Richard Lowe    else {
17707dc194Richard Lowe        obj->ehdr32 = elf32_getehdr(elf);
17807dc194Richard Lowe        if (obj->ehdr32 == NULL) {
17907dc194Richard Lowe           *error = DW_DLE_ELF_GETEHDR_ERROR;
18007dc194Richard Lowe           return DW_DLV_ERROR;
18107dc194Richard Lowe        }
18207dc194Richard Lowe        obj->section_count = obj->ehdr32->e_shnum;
18307dc194Richard Lowe        machine = obj->ehdr32->e_machine;
18407dc194Richard Lowe        obj->machine = machine;
18507dc194Richard Lowe    }
18607dc194Richard Lowe
18707dc194Richard Lowe    /* The following length_size is Not Too Significant. Only used
18807dc194Richard Lowe       one calculation, and an approximate one at that. */
18907dc194Richard Lowe    obj->length_size = obj->is_64bit ? 8 : 4;
19007dc194Richard Lowe    obj->pointer_size = obj->is_64bit ? 8 : 4;
19107dc194Richard Lowe
19207dc194Richard Lowe    if (obj->is_64bit && machine != EM_MIPS) {
19307dc194Richard Lowe        /* MIPS/IRIX makes pointer size and length size 8 for -64.
19407dc194Richard Lowe           Other platforms make length 4 always. */
19507dc194Richard Lowe        /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus
19607dc194Richard Lowe           tools, and the dwarfv2.1 64bit extension setting.
19707dc194Richard Lowe           This is not the same as the size-of-an-offset, which
19807dc194Richard Lowe           is 4 in 32bit dwarf and 8 in 64bit dwarf.  */
19907dc194Richard Lowe        obj->length_size = 4;
20007dc194Richard Lowe    }
20107dc194Richard Lowe    return DW_DLV_OK;
20207dc194Richard Lowe}
20307dc194Richard Lowe
20407dc194Richard Lowe/*
20507dc194Richard Lowe    dwarf_elf_object_access_get_byte_order
20607dc194Richard Lowe */
20707dc194Richard Lowestatic
20807dc194Richard LoweDwarf_Endianness
20907dc194Richard Lowedwarf_elf_object_access_get_byte_order(void* obj_in)
21007dc194Richard Lowe{
21107dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
21207dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
21307dc194Richard Lowe    return obj->endianness;
21407dc194Richard Lowe}
21507dc194Richard Lowe
21607dc194Richard Lowe/*
21707dc194Richard Lowe    dwarf_elf_object_access_get_section_count()
21807dc194Richard Lowe */
21907dc194Richard Lowestatic
22007dc194Richard LoweDwarf_Unsigned
22107dc194Richard Lowedwarf_elf_object_access_get_section_count(void * obj_in)
22207dc194Richard Lowe{
22307dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
22407dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
22507dc194Richard Lowe    return obj->section_count;
22607dc194Richard Lowe}
22707dc194Richard Lowe
22807dc194Richard Lowe
22907dc194Richard Lowe/*
23007dc194Richard Lowe    dwarf_elf_object_access_get_section()
23107dc194Richard Lowe */
23207dc194Richard Lowestatic
23307dc194Richard Loweint
23407dc194Richard Lowedwarf_elf_object_access_get_section_info(
23507dc194Richard Lowe    void* obj_in,
23607dc194Richard Lowe    Dwarf_Half section_index,
23707dc194Richard Lowe    Dwarf_Obj_Access_Section* ret_scn,
23807dc194Richard Lowe    int* error)
23907dc194Richard Lowe{
24007dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
24107dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
24207dc194Richard Lowe
24307dc194Richard Lowe    Elf32_Shdr *shdr32 = 0;
24407dc194Richard Lowe
24507dc194Richard Lowe#ifdef HAVE_ELF64_GETSHDR
24607dc194Richard Lowe    Elf64_Shdr *shdr64 = 0;
24707dc194Richard Lowe#endif
24807dc194Richard Lowe    Elf_Scn *scn = 0;
24907dc194Richard Lowe
25007dc194Richard Lowe
25107dc194Richard Lowe    scn = elf_getscn(obj->elf, section_index);
25207dc194Richard Lowe    if (scn == NULL) {
25307dc194Richard Lowe        *error = DW_DLE_MDE;
25407dc194Richard Lowe        return DW_DLV_ERROR;
25507dc194Richard Lowe    }
25607dc194Richard Lowe    if (obj->is_64bit) {
25707dc194Richard Lowe#ifdef HAVE_ELF64_GETSHDR
25807dc194Richard Lowe        shdr64 = elf64_getshdr(scn);
25907dc194Richard Lowe        if (shdr64 == NULL) {
26007dc194Richard Lowe            *error = DW_DLE_ELF_GETSHDR_ERROR;
26107dc194Richard Lowe            return DW_DLV_ERROR;
26207dc194Richard Lowe        }
26307dc194Richard Lowe
26407dc194Richard Lowe        ret_scn->size = shdr64->sh_size;
26507dc194Richard Lowe        ret_scn->addr = shdr64->sh_addr;
26607dc194Richard Lowe        ret_scn->link = shdr64->sh_link;
26707dc194Richard Lowe
26807dc194Richard Lowe        ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
26907dc194Richard Lowe                                        shdr64->sh_name);
27007dc194Richard Lowe        if(ret_scn->name == NULL) {
27107dc194Richard Lowe            *error = DW_DLE_ELF_STRPTR_ERROR;
27207dc194Richard Lowe            return DW_DLV_ERROR;
27307dc194Richard Lowe        }
27407dc194Richard Lowe        return DW_DLV_OK;
27507dc194Richard Lowe#else
27607dc194Richard Lowe        *error = DW_DLE_MISSING_ELF64_SUPPORT;
27707dc194Richard Lowe        return DW_DLV_ERROR;
27807dc194Richard Lowe#endif /* HAVE_ELF64_GETSHDR */
27907dc194Richard Lowe    }
28007dc194Richard Lowe    if ((shdr32 = elf32_getshdr(scn)) == NULL) {
28107dc194Richard Lowe        *error = DW_DLE_ELF_GETSHDR_ERROR;
28207dc194Richard Lowe        return DW_DLV_ERROR;
28307dc194Richard Lowe    }
28407dc194Richard Lowe
28507dc194Richard Lowe    ret_scn->size = shdr32->sh_size;
28607dc194Richard Lowe    ret_scn->addr = shdr32->sh_addr;
28707dc194Richard Lowe    ret_scn->link = shdr32->sh_link;
28807dc194Richard Lowe
28907dc194Richard Lowe    ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
29007dc194Richard Lowe        shdr32->sh_name);
29107dc194Richard Lowe    if (ret_scn->name == NULL) {
29207dc194Richard Lowe        *error = DW_DLE_ELF_STRPTR_ERROR;
29307dc194Richard Lowe        return DW_DLV_ERROR;
29407dc194Richard Lowe    }
29507dc194Richard Lowe    return DW_DLV_OK;
29607dc194Richard Lowe}
29707dc194Richard Lowe
29807dc194Richard Lowe/*
29907dc194Richard Lowe    dwarf_elf_object_access_get_length_size
30007dc194Richard Lowe */
30107dc194Richard Lowestatic
30207dc194Richard LoweDwarf_Small
30307dc194Richard Lowedwarf_elf_object_access_get_length_size(void* obj_in)
30407dc194Richard Lowe{
30507dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
30607dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
30707dc194Richard Lowe    return obj->length_size;
30807dc194Richard Lowe}
30907dc194Richard Lowe
31007dc194Richard Lowe/*
31107dc194Richard Lowe    dwarf_elf_object_access_get_pointer_size
31207dc194Richard Lowe */
31307dc194Richard Lowestatic
31407dc194Richard LoweDwarf_Small
31507dc194Richard Lowedwarf_elf_object_access_get_pointer_size(void* obj_in)
31607dc194Richard Lowe{
31707dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
31807dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
31907dc194Richard Lowe    return obj->pointer_size;
32007dc194Richard Lowe}
32107dc194Richard Lowe
32207dc194Richard Lowe#define MATCH_REL_SEC(i_,s_,r_)  \
32307dc194Richard Loweif(i_ == s_.dss_index) { \
32407dc194Richard Lowe    *r_ = &s_;            \
32507dc194Richard Lowe    return DW_DLV_OK;    \
32607dc194Richard Lowe}
32707dc194Richard Lowe
32807dc194Richard Lowestatic int
32907dc194Richard Lowefind_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
33007dc194Richard Lowe   struct Dwarf_Section_s **relocatablesec, int *error)
33107dc194Richard Lowe{
33207dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
33307dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
33407dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
33507dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
33607dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
33707dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
33807dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
33907dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
34007dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
34107dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
34207dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
34307dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
34407dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
34507dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
34607dc194Richard Lowe    MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
34707dc194Richard Lowe    /* dbg-> de_debug_str,syms); */
34807dc194Richard Lowe    /* de_elf_symtab,syms); */
34907dc194Richard Lowe    /* de_elf_strtab,syms); */
35007dc194Richard Lowe    *error = DW_DLE_RELOC_SECTION_MISMATCH;
35107dc194Richard Lowe    return DW_DLV_ERROR;
35207dc194Richard Lowe
35307dc194Richard Lowe}
35407dc194Richard Lowe#undef MATCH_REL_SEC
35507dc194Richard Lowe
35607dc194Richard Lowestatic void
35707dc194Richard Loweget_rela_elf32(Dwarf_Small *data, unsigned int i,
35807dc194Richard Lowe  int endianness,
35907dc194Richard Lowe  int machine, struct Dwarf_Elf_Rela *relap)
36007dc194Richard Lowe{
36107dc194Richard Lowe    Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
36207dc194Richard Lowe    relap->r_offset = relp->r_offset;
36307dc194Richard Lowe    /*
36407dc194Richard Lowe    relap->r_info = relp->r_info;
36507dc194Richard Lowe   */
36607dc194Richard Lowe    relap->r_type = ELF32_R_TYPE(relp->r_info);
36707dc194Richard Lowe    relap->r_symidx = ELF32_R_SYM(relp->r_info);
36807dc194Richard Lowe    relap->r_addend = relp->r_addend;
36907dc194Richard Lowe}
37007dc194Richard Lowe
37107dc194Richard Lowestatic void
37207dc194Richard Loweget_rela_elf64(Dwarf_Small *data, unsigned int i,
37307dc194Richard Lowe  int endianness,
37407dc194Richard Lowe  int machine,struct Dwarf_Elf_Rela *relap)
37507dc194Richard Lowe{
37607dc194Richard Lowe#ifdef HAVE_ELF64_RELA
37707dc194Richard Lowe    Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
37807dc194Richard Lowe    relap->r_offset = relp->r_offset;
37907dc194Richard Lowe    /*
38007dc194Richard Lowe    relap->r_info = relp->r_info;
38107dc194Richard Lowe    */
38207dc194Richard Lowe    if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ) {
38307dc194Richard Lowe        /* This is really wierd. Treat this very specially.
38407dc194Richard Lowe           The Elf64 LE MIPS object used for
38507dc194Richard Lowe           testing (that has rela) wants the
38607dc194Richard Lowe           values as  sym  ssym type3 type2 type, treating
38707dc194Richard Lowe           each value as independent value. But libelf xlate
38807dc194Richard Lowe           treats it as something else so we fudge here.
38907dc194Richard Lowe           It is unclear
39007dc194Richard Lowe           how to precisely characterize where these relocations
39107dc194Richard Lowe           were used.
39207dc194Richard Lowe           SGI MIPS on IRIX never used .rela relocations.
39307dc194Richard Lowe           The BE 64bit elf MIPS test object with rela uses traditional
39407dc194Richard Lowe           elf relocation layouts, not this special case.  */
39507dc194Richard Lowe#define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
39607dc194Richard Lowe#define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
39707dc194Richard Lowe        /* We ignore the special TYPE2 and TYPE3, they should be
39807dc194Richard Lowe           value R_MIPS_NONE in rela. */
39907dc194Richard Lowe        relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
40007dc194Richard Lowe        relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
40107dc194Richard Lowe#undef MIPS64SYM
40207dc194Richard Lowe#undef MIPS64TYPE
40307dc194Richard Lowe    } else
40407dc194Richard Lowe    {
40507dc194Richard Lowe        relap->r_type = ELF64_R_TYPE(relp->r_info);
40607dc194Richard Lowe        relap->r_symidx = ELF64_R_SYM(relp->r_info);
40707dc194Richard Lowe    }
40807dc194Richard Lowe    relap->r_addend = relp->r_addend;
40907dc194Richard Lowe#endif
41007dc194Richard Lowe}
41107dc194Richard Lowe
41207dc194Richard Lowestatic void
41307dc194Richard Loweget_relocations_array(Dwarf_Bool is_64bit,
41407dc194Richard Lowe    int endianness,
41507dc194Richard Lowe    int machine,
41607dc194Richard Lowe    Dwarf_Small *data,
41707dc194Richard Lowe    unsigned int num_relocations,
41807dc194Richard Lowe    struct Dwarf_Elf_Rela *relap)
41907dc194Richard Lowe{
42007dc194Richard Lowe    unsigned int i = 0;
42107dc194Richard Lowe    void (*get_relocations)(Dwarf_Small *data, unsigned int i,
42207dc194Richard Lowe         int endianness,
42307dc194Richard Lowe         int machine,
42407dc194Richard Lowe         struct Dwarf_Elf_Rela *relap);
42507dc194Richard Lowe
42607dc194Richard Lowe    /* Handle 32/64 bit issue
42707dc194Richard Lowe     */
42807dc194Richard Lowe    if (is_64bit) {
42907dc194Richard Lowe        get_relocations = get_rela_elf64;
43007dc194Richard Lowe    } else {
43107dc194Richard Lowe        get_relocations = get_rela_elf32;
43207dc194Richard Lowe    }
43307dc194Richard Lowe
43407dc194Richard Lowe    for (i=0; i < num_relocations; i++) {
43507dc194Richard Lowe       get_relocations(data, i,endianness,machine, &(relap[i]));
43607dc194Richard Lowe    }
43707dc194Richard Lowe
43807dc194Richard Lowe}
43907dc194Richard Lowe
44007dc194Richard Lowestatic int
44107dc194Richard Loweget_relocation_entries(Dwarf_Bool is_64bit,
44207dc194Richard Lowe    int endianness,
44307dc194Richard Lowe    int machine,
44407dc194Richard Lowe    Dwarf_Small *relocation_section,
44507dc194Richard Lowe    Dwarf_Unsigned relocation_section_size,
44607dc194Richard Lowe    struct Dwarf_Elf_Rela **relas,
44707dc194Richard Lowe    unsigned int *nrelas,
44807dc194Richard Lowe    int *error)
44907dc194Richard Lowe{
45007dc194Richard Lowe    unsigned int relocation_size = 0;
45107dc194Richard Lowe
45207dc194Richard Lowe    if (is_64bit) {
45307dc194Richard Lowe#ifdef HAVE_ELF64_RELA
45407dc194Richard Lowe        relocation_size = sizeof(Elf64_Rela);
45507dc194Richard Lowe#else
45607dc194Richard Lowe        *error = DW_DLE_MISSING_ELF64_SUPPORT;
45707dc194Richard Lowe        return DW_DLV_ERROR;
45807dc194Richard Lowe#endif
45907dc194Richard Lowe    } else {
46007dc194Richard Lowe        relocation_size = sizeof(Elf32_Rela);
46107dc194Richard Lowe    }
46207dc194Richard Lowe
46307dc194Richard Lowe    if (relocation_section == NULL) {
46407dc194Richard Lowe        *error = DW_DLE_RELOC_SECTION_PTR_NULL;
46507dc194Richard Lowe        return(DW_DLV_ERROR);
46607dc194Richard Lowe    }
46707dc194Richard Lowe
46807dc194Richard Lowe    if ((relocation_section_size != 0)) {
46907dc194Richard Lowe        size_t bytescount = 0;
47007dc194Richard Lowe        if(relocation_section_size%relocation_size) {
47107dc194Richard Lowe            *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
47207dc194Richard Lowe            return DW_DLV_ERROR;
47307dc194Richard Lowe        }
47407dc194Richard Lowe        *nrelas = relocation_section_size/relocation_size;
47507dc194Richard Lowe        bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
47607dc194Richard Lowe        *relas = malloc(bytescount);
47707dc194Richard Lowe        if (!*relas) {
47807dc194Richard Lowe            *error = DW_DLE_MAF;
47907dc194Richard Lowe            return(DW_DLV_ERROR);
48007dc194Richard Lowe        }
48107dc194Richard Lowe        memset(*relas,0,bytescount);
48207dc194Richard Lowe        get_relocations_array(is_64bit,endianness,machine, relocation_section,
48307dc194Richard Lowe            *nrelas, *relas);
48407dc194Richard Lowe    }
48507dc194Richard Lowe    return(DW_DLV_OK);
48607dc194Richard Lowe}
48707dc194Richard Lowe
48807dc194Richard Lowestatic Dwarf_Bool
48907dc194Richard Loweis_32bit_abs_reloc(unsigned int type, Dwarf_Half machine)
49007dc194Richard Lowe{
49107dc194Richard Lowe    Dwarf_Bool r = 0;
49207dc194Richard Lowe    switch (machine) {
49307dc194Richard Lowe#if defined(EM_MIPS) && defined (R_MIPS_32)
49407dc194Richard Lowe    case EM_MIPS:
49507dc194Richard Lowe         r = (type == R_MIPS_32);
49607dc194Richard Lowe         break;
49707dc194Richard Lowe#endif
49807dc194Richard Lowe#if defined(EM_SPARC32PLUS)  && defined (R_SPARC_UA32)
49907dc194Richard Lowe    case EM_SPARC32PLUS:
50007dc194Richard Lowe         r =  (type == R_SPARC_UA32);
50107dc194Richard Lowe         break;
50207dc194Richard Lowe#endif
50307dc194Richard Lowe#if defined(EM_SPARCV9)  && defined (R_SPARC_UA32)
50407dc194Richard Lowe    case EM_SPARCV9:
50507dc194Richard Lowe         r =  (type == R_SPARC_UA32);
50607dc194Richard Lowe         break;
50707dc194Richard Lowe#endif
50807dc194Richard Lowe#if defined(EM_SPARC) && defined (R_SPARC_UA32)
50907dc194Richard Lowe    case EM_SPARC:
51007dc194Richard Lowe         r =  (type == R_SPARC_UA32);
51107dc194Richard Lowe         break;
51207dc194Richard Lowe#endif
51307dc194Richard Lowe#if defined(EM_386) && defined (R_386_32)
51407dc194Richard Lowe    case EM_386:
51507dc194Richard Lowe        r =  (type == R_386_32);
51607dc194Richard Lowe        break;
51707dc194Richard Lowe#endif
51807dc194Richard Lowe#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
51907dc194Richard Lowe    case EM_IA_64:
52007dc194Richard Lowe        r =  (type == R_IA64_SECREL32LSB);
52107dc194Richard Lowe        break;
52207dc194Richard Lowe#endif
52307dc194Richard Lowe#if defined(EM_PPC64) && defined (R_PPC64_ADDR32)
52407dc194Richard Lowe    case EM_PPC64:
52507dc194Richard Lowe        r =  (type == R_PPC64_ADDR32);
52607dc194Richard Lowe        break;
52707dc194Richard Lowe#endif
52807dc194Richard Lowe#if defined(EM_PPC) && defined (R_PPC_ADDR32)
52907dc194Richard Lowe    case EM_PPC:
53007dc194Richard Lowe        r =  (type == R_PPC_ADDR32);
53107dc194Richard Lowe        break;
53207dc194Richard Lowe#endif
53307dc194Richard Lowe#if defined(EM_S390) && defined (R_390_32)
53407dc194Richard Lowe    case EM_S390:
53507dc194Richard Lowe        r =  (type == R_390_32);
53607dc194Richard Lowe        break;
53707dc194Richard Lowe#endif
53807dc194Richard Lowe#if defined(EM_X86_64) && defined (R_X86_64_32)
53907dc194Richard Lowe    case EM_X86_64:
54007dc194Richard Lowe        r = (type == R_X86_64_32);
54107dc194Richard Lowe        break;
54207dc194Richard Lowe#endif
54307dc194Richard Lowe    }
54407dc194Richard Lowe    return r;
54507dc194Richard Lowe}
54607dc194Richard Lowe
54707dc194Richard Lowestatic Dwarf_Bool
54807dc194Richard Loweis_64bit_abs_reloc(unsigned int type, Dwarf_Half machine)
54907dc194Richard Lowe{
55007dc194Richard Lowe    Dwarf_Bool r = 0;
55107dc194Richard Lowe    switch (machine) {
55207dc194Richard Lowe#if defined(EM_MIPS) && defined (R_MIPS_64)
55307dc194Richard Lowe    case EM_MIPS:
55407dc194Richard Lowe        r =  (type == R_MIPS_64);
55507dc194Richard Lowe        break;
55607dc194Richard Lowe#endif
55707dc194Richard Lowe#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64)
55807dc194Richard Lowe    case EM_SPARC32PLUS:
55907dc194Richard Lowe        r =  (type == R_SPARC_UA64);
56007dc194Richard Lowe        break;
56107dc194Richard Lowe#endif
56207dc194Richard Lowe#if defined(EM_SPARCV9) && defined (R_SPARC_UA64)
56307dc194Richard Lowe    case EM_SPARCV9:
56407dc194Richard Lowe        r = (type == R_SPARC_UA64);
56507dc194Richard Lowe        break;
56607dc194Richard Lowe#endif
56707dc194Richard Lowe#if defined(EM_SPARC) && defined (R_SPARC_UA64)
56807dc194Richard Lowe    case EM_SPARC:
56907dc194Richard Lowe        r = (type == R_SPARC_UA64);
57007dc194Richard Lowe        break;
57107dc194Richard Lowe#endif
57207dc194Richard Lowe#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
57307dc194Richard Lowe    case EM_IA_64:
57407dc194Richard Lowe        r =  (type == R_IA64_DIR64LSB);
57507dc194Richard Lowe        break;
57607dc194Richard Lowe#endif
57707dc194Richard Lowe#if defined(EM_PPC64) && defined (R_PPC64_ADDR64)
57807dc194Richard Lowe    case EM_PPC64:
57907dc194Richard Lowe        r =  (type == R_PPC64_ADDR64);
58007dc194Richard Lowe        break;
58107dc194Richard Lowe#endif
58207dc194Richard Lowe#if defined(EM_S390) && defined (R_390_64)
58307dc194Richard Lowe    case EM_S390:
58407dc194Richard Lowe        r =  (type == R_390_64);
58507dc194Richard Lowe        break;
58607dc194Richard Lowe#endif
58707dc194Richard Lowe#if defined(EM_X86_64) && defined (R_X86_64_64)
58807dc194Richard Lowe    case EM_X86_64:
58907dc194Richard Lowe        r =  (type == R_X86_64_64);
59007dc194Richard Lowe        break;
59107dc194Richard Lowe#endif
59207dc194Richard Lowe    }
59307dc194Richard Lowe    return r;
59407dc194Richard Lowe}
59507dc194Richard Lowe
59607dc194Richard Lowe
59707dc194Richard Lowestatic void
59807dc194Richard Loweupdate_entry(Dwarf_Debug dbg,
59907dc194Richard Lowe    Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
60007dc194Richard Lowe    Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
60107dc194Richard Lowe    Dwarf_Small *target_section, Dwarf_Small *section_data)
60207dc194Richard Lowe{
60307dc194Richard Lowe    unsigned int type = 0;
60407dc194Richard Lowe    unsigned int sym_idx = 0;
60507dc194Richard Lowe#ifdef HAVE_ELF64_SYM
60607dc194Richard Lowe    Elf64_Sym sym_buf;
60707dc194Richard Lowe    Elf64_Sym *sym = 0;
60807dc194Richard Lowe#else
60907dc194Richard Lowe    Elf32_Sym sym_buf;
61007dc194Richard Lowe    Elf32_Sym *sym = 0;
61107dc194Richard Lowe#endif
61207dc194Richard Lowe    Elf32_Sym *sym32 = 0;
61307dc194Richard Lowe    Dwarf_ufixed64 offset = 0;
61407dc194Richard Lowe    Dwarf_sfixed64 addend = 0;
61507dc194Richard Lowe    Dwarf_Unsigned reloc_size = 0;
61607dc194Richard Lowe
61707dc194Richard Lowe
61807dc194Richard Lowe    /* Dwarf_Elf_Rela dereferencing */
61907dc194Richard Lowe    offset = rela->r_offset;
62007dc194Richard Lowe    addend = rela->r_addend;
62107dc194Richard Lowe    type = rela->r_type;
62207dc194Richard Lowe    sym_idx = rela->r_symidx;
62307dc194Richard Lowe
62407dc194Richard Lowe    if (is_64bit) {
62507dc194Richard Lowe#ifdef HAVE_ELF64_SYM
62607dc194Richard Lowe       sym = &((Elf64_Sym*)section_data)[sym_idx];
62707dc194Richard Lowe#endif
62807dc194Richard Lowe    } else {
62907dc194Richard Lowe       sym32 = &((Elf32_Sym*)section_data)[sym_idx];
63007dc194Richard Lowe
63107dc194Richard Lowe       /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at
63207dc194Richard Lowe        * an Elf64_Sym local variable (sym_buf) to allow us to use the
63307dc194Richard Lowe        * same pointer (sym) for both 32-bit and 64-bit instances.
63407dc194Richard Lowe        */
63507dc194Richard Lowe       sym = &sym_buf;
63607dc194Richard Lowe       sym->st_name = sym32->st_name;
63707dc194Richard Lowe       sym->st_info = sym32->st_info;
63807dc194Richard Lowe       sym->st_other = sym32->st_other;
63907dc194Richard Lowe       sym->st_shndx = sym32->st_shndx;
64007dc194Richard Lowe       sym->st_value = sym32->st_value;
64107dc194Richard Lowe       sym->st_size = sym32->st_size;
64207dc194Richard Lowe    }
64307dc194Richard Lowe
64407dc194Richard Lowe    /* Determine relocation size */
64507dc194Richard Lowe    if (is_32bit_abs_reloc(type, machine)) {
64607dc194Richard Lowe        reloc_size = 4;
64707dc194Richard Lowe    } else if (is_64bit_abs_reloc(type, machine)) {
64807dc194Richard Lowe        reloc_size = 8;
64907dc194Richard Lowe    } else {
65007dc194Richard Lowe        return;
65107dc194Richard Lowe    }
65207dc194Richard Lowe
65307dc194Richard Lowe
65407dc194Richard Lowe    {
65507dc194Richard Lowe        /* Assuming we do not need to do a READ_UNALIGNED here
65607dc194Richard Lowe           at target_section + offset and add its value to
65707dc194Richard Lowe           outval.  Some ABIs say no read (for example MIPS),
65807dc194Richard Lowe           but if some do then which ones? */
65907dc194Richard Lowe        Dwarf_Unsigned outval = sym->st_value + addend;
66007dc194Richard Lowe        WRITE_UNALIGNED(dbg,target_section + offset,
66107dc194Richard Lowe                  &outval,sizeof(outval),reloc_size);
66207dc194Richard Lowe    }
66307dc194Richard Lowe}
66407dc194Richard Lowe
66507dc194Richard Lowe
66607dc194Richard Lowe
66707dc194Richard Lowestatic int
66807dc194Richard Loweapply_rela_entries(Dwarf_Debug dbg,
66907dc194Richard Lowe    Dwarf_Bool is_64bit,
67007dc194Richard Lowe    Dwarf_Endianness endianess,
67107dc194Richard Lowe    Dwarf_Half machine,
67207dc194Richard Lowe    Dwarf_Small *target_section,
67307dc194Richard Lowe    Dwarf_Small *symtab_section,
67407dc194Richard Lowe    struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
67507dc194Richard Lowe    int *error)
67607dc194Richard Lowe{
67707dc194Richard Lowe    if ((target_section != NULL)  && (relas != NULL)) {
67807dc194Richard Lowe        unsigned int i;
67907dc194Richard Lowe        for (i = 0; i < nrelas; i++) {
68007dc194Richard Lowe            update_entry(dbg, is_64bit,
68107dc194Richard Lowe                endianess,
68207dc194Richard Lowe                machine,
68307dc194Richard Lowe                &(relas)[i],
68407dc194Richard Lowe                target_section,
68507dc194Richard Lowe                symtab_section);
68607dc194Richard Lowe        }
68707dc194Richard Lowe    }
68807dc194Richard Lowe    return DW_DLV_OK;
68907dc194Richard Lowe}
69007dc194Richard Lowe
69107dc194Richard Lowe
69207dc194Richard Lowestatic int
69307dc194Richard Loweloop_through_relocations(
69407dc194Richard Lowe   Dwarf_Debug dbg,
69507dc194Richard Lowe   dwarf_elf_object_access_internals_t* obj,
69607dc194Richard Lowe   struct Dwarf_Section_s *relocatablesec,
69707dc194Richard Lowe   int *error)
69807dc194Richard Lowe{
69907dc194Richard Lowe    Dwarf_Small *target_section = 0;
70007dc194Richard Lowe    Dwarf_Small *symtab_section = obj->symtab->dss_data;
70107dc194Richard Lowe    Dwarf_Small *relocation_section  = relocatablesec->dss_reloc_data;
70207dc194Richard Lowe    Dwarf_Unsigned relocation_section_size =
70307dc194Richard Lowe              relocatablesec->dss_reloc_size;
70407dc194Richard Lowe    int ret = DW_DLV_ERROR;
70507dc194Richard Lowe    struct Dwarf_Elf_Rela *relas = 0;
70607dc194Richard Lowe    unsigned int nrelas = 0;
70707dc194Richard Lowe    Dwarf_Small *mspace = 0;
70807dc194Richard Lowe
70907dc194Richard Lowe    ret = get_relocation_entries(obj->is_64bit,
71007dc194Richard Lowe        obj->endianness,
71107dc194Richard Lowe        obj->machine,
71207dc194Richard Lowe        relocation_section,
71307dc194Richard Lowe        relocation_section_size,
71407dc194Richard Lowe        &relas, &nrelas, error);
71507dc194Richard Lowe    if(ret != DW_DLV_OK) {
71607dc194Richard Lowe        free(relas);
71707dc194Richard Lowe        return ret;
71807dc194Richard Lowe    }
71907dc194Richard Lowe
72007dc194Richard Lowe    /* Some systems read Elf in read-only memory via mmap or the like.
72107dc194Richard Lowe       So the only safe thing is to copy the current data into
72207dc194Richard Lowe       malloc space and refer to the malloc space instead of the
72307dc194Richard Lowe       space returned by the elf library */
72407dc194Richard Lowe    mspace = malloc(relocatablesec->dss_size);
72507dc194Richard Lowe    if(!mspace) {
72607dc194Richard Lowe        *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
72707dc194Richard Lowe        return DW_DLV_ERROR;
72807dc194Richard Lowe    }
72907dc194Richard Lowe    memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
73007dc194Richard Lowe    relocatablesec->dss_data = mspace;
73107dc194Richard Lowe    target_section = relocatablesec->dss_data;
73207dc194Richard Lowe    relocatablesec->dss_data_was_malloc = 1;
73307dc194Richard Lowe
73407dc194Richard Lowe    ret = apply_rela_entries(
73507dc194Richard Lowe        dbg,
73607dc194Richard Lowe        obj->is_64bit,
73707dc194Richard Lowe        obj->endianness, obj->machine,
73807dc194Richard Lowe        target_section,
73907dc194Richard Lowe        symtab_section,
74007dc194Richard Lowe        relas, nrelas, error);
74107dc194Richard Lowe
74207dc194Richard Lowe    free(relas);
74307dc194Richard Lowe
74407dc194Richard Lowe    return ret;
74507dc194Richard Lowe}
74607dc194Richard Lowe
74707dc194Richard Lowe/*
74807dc194Richard Lowe    Find the section data in dbg and find all the relevant
74907dc194Richard Lowe    sections.  Then do relocations.
75007dc194Richard Lowe*/
75107dc194Richard Lowestatic int
75207dc194Richard Lowedwarf_elf_object_relocate_a_section(void* obj_in,
75307dc194Richard Lowe    Dwarf_Half section_index,
75407dc194Richard Lowe    Dwarf_Debug dbg,
75507dc194Richard Lowe    int* error)
75607dc194Richard Lowe{
75707dc194Richard Lowe    int res = DW_DLV_ERROR;
75807dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj = 0;
75907dc194Richard Lowe    struct Dwarf_Section_s * relocatablesec = 0;
76007dc194Richard Lowe    if (section_index == 0) {
76107dc194Richard Lowe        return DW_DLV_NO_ENTRY;
76207dc194Richard Lowe    }
76307dc194Richard Lowe    obj = (dwarf_elf_object_access_internals_t*)obj_in;
76407dc194Richard Lowe
76507dc194Richard Lowe    /* The section to relocate must already be loaded into memory. */
76607dc194Richard Lowe    res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
76707dc194Richard Lowe    if(res != DW_DLV_OK) {
76807dc194Richard Lowe         return res;
76907dc194Richard Lowe    }
77007dc194Richard Lowe
77107dc194Richard Lowe    /* Sun and possibly others do not always set sh_link in .debug_* sections.
77207dc194Richard Lowe       So we cannot do full  consistency checks. */
77307dc194Richard Lowe    if(relocatablesec->dss_reloc_index == 0 ) {
77407dc194Richard Lowe        /* Something is wrong. */
77507dc194Richard Lowe        *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
77607dc194Richard Lowe        return DW_DLV_ERROR;
77707dc194Richard Lowe    }
77807dc194Richard Lowe    /* Now load the relocations themselves. */
77907dc194Richard Lowe    res =  dwarf_elf_object_access_load_section(obj_in,
78007dc194Richard Lowe            relocatablesec->dss_reloc_index,
78107dc194Richard Lowe            &relocatablesec->dss_reloc_data, error);
78207dc194Richard Lowe    if(res != DW_DLV_OK) {
78307dc194Richard Lowe            return res;
78407dc194Richard Lowe    }
78507dc194Richard Lowe
78607dc194Richard Lowe    /* Now get the symtab. */
78707dc194Richard Lowe    if  (!obj->symtab) {
78807dc194Richard Lowe       obj->symtab = &dbg->de_elf_symtab;
78907dc194Richard Lowe       obj->strtab = &dbg->de_elf_strtab;
79007dc194Richard Lowe    }
79107dc194Richard Lowe    if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
79207dc194Richard Lowe        /* Something is wrong. */
79307dc194Richard Lowe        *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
79407dc194Richard Lowe        return DW_DLV_ERROR;
79507dc194Richard Lowe    }
79607dc194Richard Lowe    if( obj->strtab->dss_index != obj->symtab->dss_link) {
79707dc194Richard Lowe        /* Something is wrong. */
79807dc194Richard Lowe        *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
79907dc194Richard Lowe        return DW_DLV_ERROR;
80007dc194Richard Lowe    }
80107dc194Richard Lowe    if(!obj->symtab->dss_data) {
80207dc194Richard Lowe        /* Now load the symtab */
80307dc194Richard Lowe        res =  dwarf_elf_object_access_load_section(obj_in,
80407dc194Richard Lowe            obj->symtab->dss_index,
80507dc194Richard Lowe            &obj->symtab->dss_data, error);
80607dc194Richard Lowe        if(res != DW_DLV_OK) {
80707dc194Richard Lowe            return res;
80807dc194Richard Lowe        }
80907dc194Richard Lowe    }
81007dc194Richard Lowe    if(! obj->strtab->dss_data) {
81107dc194Richard Lowe        /* Now load the strtab */
81207dc194Richard Lowe        res = dwarf_elf_object_access_load_section(obj_in,
81307dc194Richard Lowe            obj->strtab->dss_index,
81407dc194Richard Lowe            &obj->strtab->dss_data,error);
81507dc194Richard Lowe        if(res != DW_DLV_OK){
81607dc194Richard Lowe            return res;
81707dc194Richard Lowe        }
81807dc194Richard Lowe    }
81907dc194Richard Lowe
82007dc194Richard Lowe    /* We have all the data we need in memory. */
82107dc194Richard Lowe    res = loop_through_relocations(dbg,obj,relocatablesec,error);
82207dc194Richard Lowe
82307dc194Richard Lowe    return res;
82407dc194Richard Lowe}
82507dc194Richard Lowe
82607dc194Richard Lowe/*
82707dc194Richard Lowe    dwarf_elf_object_access_load_section
82807dc194Richard Lowe */
82907dc194Richard Lowestatic int
83007dc194Richard Lowedwarf_elf_object_access_load_section(void* obj_in,
83107dc194Richard Lowe    Dwarf_Half section_index,
83207dc194Richard Lowe    Dwarf_Small** section_data,
83307dc194Richard Lowe    int* error)
83407dc194Richard Lowe{
83507dc194Richard Lowe    dwarf_elf_object_access_internals_t*obj =
83607dc194Richard Lowe        (dwarf_elf_object_access_internals_t*)obj_in;
83707dc194Richard Lowe    if (section_index == 0) {
83807dc194Richard Lowe        return DW_DLV_NO_ENTRY;
83907dc194Richard Lowe    }
84007dc194Richard Lowe
84107dc194Richard Lowe    {
84207dc194Richard Lowe        Elf_Scn *scn = 0;
84307dc194Richard Lowe        Elf_Data *data = 0;
84407dc194Richard Lowe
84507dc194Richard Lowe        scn = elf_getscn(obj->elf, section_index);
84607dc194Richard Lowe        if (scn == NULL) {
84707dc194Richard Lowe            *error = DW_DLE_MDE;
84807dc194Richard Lowe            return DW_DLV_ERROR;
84907dc194Richard Lowe        }
85007dc194Richard Lowe
85107dc194Richard Lowe        /*
85207dc194Richard Lowe           When using libelf as a producer, section data may be stored
85307dc194Richard Lowe           in multiple buffers. In libdwarf however, we only use libelf
85407dc194Richard Lowe           as a consumer (there is a dwarf producer API, but it doesn't
85507dc194Richard Lowe           use libelf). Because of this, this single call to elf_getdata
85607dc194Richard Lowe           will retrieve the entire section in a single contiguous
85707dc194Richard Lowe           buffer. */
85807dc194Richard Lowe        data = elf_getdata(scn, NULL);
85907dc194Richard Lowe        if (data == NULL) {
86007dc194Richard Lowe                  *error = DW_DLE_MDE;
86107dc194Richard Lowe                  return DW_DLV_ERROR;
86207dc194Richard Lowe        }
86307dc194Richard Lowe        *section_data = data->d_buf;
86407dc194Richard Lowe    }
86507dc194Richard Lowe    return DW_DLV_OK;
86607dc194Richard Lowe}
86707dc194Richard Lowe
86807dc194Richard Lowe
86907dc194Richard Lowe/* dwarf_elf_access method table. */
87007dc194Richard Lowestatic const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
87107dc194Richard Lowe{
87207dc194Richard Lowe    dwarf_elf_object_access_get_section_info,
87307dc194Richard Lowe    dwarf_elf_object_access_get_byte_order,
87407dc194Richard Lowe    dwarf_elf_object_access_get_length_size,
87507dc194Richard Lowe    dwarf_elf_object_access_get_pointer_size,
87607dc194Richard Lowe    dwarf_elf_object_access_get_section_count,
87707dc194Richard Lowe    dwarf_elf_object_access_load_section,
87807dc194Richard Lowe    dwarf_elf_object_relocate_a_section
87907dc194Richard Lowe};
88007dc194Richard Lowe
88107dc194Richard Lowe
88207dc194Richard Lowe/*
88307dc194Richard Lowe    Interface for the ELF object file implementation.
88407dc194Richard Lowe */
88507dc194Richard Loweint
88607dc194Richard Lowedwarf_elf_object_access_init(dwarf_elf_handle elf,
88707dc194Richard Lowe    int libdwarf_owns_elf,
88807dc194Richard Lowe    Dwarf_Obj_Access_Interface** ret_obj,
88907dc194Richard Lowe    int *err)
89007dc194Richard Lowe{
89107dc194Richard Lowe    int res = 0;
89207dc194Richard Lowe    dwarf_elf_object_access_internals_t *internals = 0;
89307dc194Richard Lowe    Dwarf_Obj_Access_Interface *intfc = 0;
89407dc194Richard Lowe
89507dc194Richard Lowe    internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
89607dc194Richard Lowe    if(!internals) {
89707dc194Richard Lowe        /* Impossible case, we hope. Give up. */
89807dc194Richard Lowe        return DW_DLV_ERROR;
89907dc194Richard Lowe    }
90007dc194Richard Lowe    memset(internals,0,sizeof(*internals));
90107dc194Richard Lowe    res = dwarf_elf_object_access_internals_init(internals, elf, err);
90207dc194Richard Lowe    if(res != DW_DLV_OK){
90307dc194Richard Lowe        free(internals);
90407dc194Richard Lowe        return DW_DLV_ERROR;
90507dc194Richard Lowe    }
90607dc194Richard Lowe    internals->libdwarf_owns_elf = libdwarf_owns_elf;
90707dc194Richard Lowe
90807dc194Richard Lowe    intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
90907dc194Richard Lowe    if(!intfc) {
91007dc194Richard Lowe        /* Impossible case, we hope. Give up. */
91107dc194Richard Lowe        free(internals);
91207dc194Richard Lowe        return DW_DLV_ERROR;
91307dc194Richard Lowe    }
91407dc194Richard Lowe    /* Initialize the interface struct */
91507dc194Richard Lowe    intfc->object = internals;
91607dc194Richard Lowe    intfc->methods = &dwarf_elf_object_access_methods;
91707dc194Richard Lowe
91807dc194Richard Lowe    *ret_obj = intfc;
91907dc194Richard Lowe    return DW_DLV_OK;
92007dc194Richard Lowe}
92107dc194Richard Lowe
92207dc194Richard Lowe
92307dc194Richard Lowe
92407dc194Richard Lowe/*
92507dc194Richard Lowe    Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.
92607dc194Richard Lowe */
92707dc194Richard Lowevoid
92807dc194Richard Lowedwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
92907dc194Richard Lowe{
93007dc194Richard Lowe    if(!obj) {
93107dc194Richard Lowe        return;
93207dc194Richard Lowe    }
93307dc194Richard Lowe    if(obj->object) {
93407dc194Richard Lowe        dwarf_elf_object_access_internals_t *internals =
93507dc194Richard Lowe            (dwarf_elf_object_access_internals_t *)obj->object;
93607dc194Richard Lowe        if(internals->libdwarf_owns_elf){
93707dc194Richard Lowe            elf_end(internals->elf);
93807dc194Richard Lowe        }
93907dc194Richard Lowe    }
94007dc194Richard Lowe    free(obj->object);
94107dc194Richard Lowe    free(obj);
94207dc194Richard Lowe}
94307dc194Richard Lowe
94407dc194Richard Lowe/*
94507dc194Richard Lowe    This function returns the Elf * pointer
94607dc194Richard Lowe    associated with a Dwarf_Debug.
94707dc194Richard Lowe
94807dc194Richard Lowe    This function only makes sense if ELF is implied.
94907dc194Richard Lowe */
95007dc194Richard Loweint
95107dc194Richard Lowedwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
95207dc194Richard Lowe              Dwarf_Error * error)
95307dc194Richard Lowe{
95407dc194Richard Lowe    struct Dwarf_Obj_Access_Interface_s * obj = 0;
95507dc194Richard Lowe    if (dbg == NULL) {
95607dc194Richard Lowe        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
95707dc194Richard Lowe        return (DW_DLV_ERROR);
95807dc194Richard Lowe    }
95907dc194Richard Lowe
96007dc194Richard Lowe    obj = dbg->de_obj_file;
96107dc194Richard Lowe    if(obj) {
96207dc194Richard Lowe       dwarf_elf_object_access_internals_t *internals =
96307dc194Richard Lowe           (dwarf_elf_object_access_internals_t*)obj->object;
96407dc194Richard Lowe       if(internals->elf == NULL) {
96507dc194Richard Lowe           _dwarf_error(dbg, error, DW_DLE_FNO);
96607dc194Richard Lowe           return (DW_DLV_ERROR);
96707dc194Richard Lowe       }
96807dc194Richard Lowe       *elf = internals->elf;
96907dc194Richard Lowe       return DW_DLV_OK;
97007dc194Richard Lowe
97107dc194Richard Lowe    }
97207dc194Richard Lowe    _dwarf_error(dbg, error, DW_DLE_FNO);
97307dc194Richard Lowe    return DW_DLV_ERROR;
97407dc194Richard Lowe}
97507dc194Richard Lowe
97607dc194Richard Lowe