1/*
2  Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
3  Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
4  Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
5  Portions Copyright 2009-2010 David Anderson. All rights reserved.
6  Portions Copyright 2009-2010 Novell Inc. All rights reserved.
7
8  This program is free software; you can redistribute it and/or modify it
9  under the terms of version 2.1 of the GNU Lesser General Public License
10  as published by the Free Software Foundation.
11
12  This program is distributed in the hope that it would be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16  Further, this software is distributed without any warranty that it is
17  free of the rightful claim of any third person regarding infringement
18  or the like.  Any license provided herein, whether implied or
19  otherwise, applies only to this software file.  Patent licenses, if
20  any, provided herein do not apply to combinations of this program with
21  other software, or any other product whatsoever.
22
23  You should have received a copy of the GNU Lesser General Public
24  License along with this program; if not, write the Free Software
25  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
26  USA.
27
28  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
29  Mountain View, CA 94043, or:
30
31  http://www.sgi.com
32
33  For further information regarding this notice, see:
34
35  http://oss.sgi.com/projects/GenInfo/NoticeExplan
36
37*/
38
39#include "config.h"
40#include "dwarf_incl.h"
41#include "dwarf_elf_access.h"
42
43#ifdef HAVE_ELF_H
44#include <elf.h>
45#endif
46#ifdef HAVE_LIBELF_H
47#include <libelf.h>
48#else
49#ifdef HAVE_LIBELF_LIBELF_H
50#include <libelf/libelf.h>
51#endif
52#endif
53
54#include <stdio.h>
55#include <sys/stat.h>
56#include <sys/types.h>
57#include <string.h>
58#include <stdlib.h>
59
60#define FALSE 0
61#define TRUE  1
62
63#ifndef EM_MIPS
64/* This is the standard elf value EM_MIPS. */
65#define EM_MIPS 8
66#endif
67
68
69#ifdef HAVE_ELF64_GETEHDR
70extern Elf64_Ehdr *elf64_getehdr(Elf *);
71#endif
72#ifdef HAVE_ELF64_GETSHDR
73extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
74#endif
75#ifdef WORDS_BIGENDIAN
76#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
77    { \
78      dbg->de_copy_word(dest, \
79                        ((char *)source) +srclength-len_out,  \
80                        len_out) ; \
81    }
82
83
84#else /* LITTLE ENDIAN */
85
86#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
87    { \
88      dbg->de_copy_word( (dest) , \
89                        ((char *)source) ,  \
90                        len_out) ; \
91    }
92#endif
93
94
95
96typedef struct {
97    dwarf_elf_handle elf;
98    int              is_64bit;
99    Dwarf_Small      length_size;
100    Dwarf_Small      pointer_size;
101    Dwarf_Unsigned   section_count;
102    Dwarf_Endianness endianness;
103    Dwarf_Small      machine;
104    int              libdwarf_owns_elf;
105    Elf32_Ehdr *ehdr32;
106
107#ifdef HAVE_ELF64_GETEHDR
108    Elf64_Ehdr *ehdr64;
109#endif
110    /* Elf symtab and its strtab.  Initialized at first
111       call to do relocations, the actual data is in the Dwarf_Debug
112       struct, not allocated locally here. */
113    struct Dwarf_Section_s *symtab;
114    struct Dwarf_Section_s *strtab;
115
116} dwarf_elf_object_access_internals_t;
117
118struct Dwarf_Elf_Rela {
119    Dwarf_ufixed64 r_offset;
120    /*Dwarf_ufixed64 r_info; */
121    Dwarf_ufixed64 r_type;
122    Dwarf_ufixed64 r_symidx;
123    Dwarf_ufixed64 r_addend;
124};
125
126
127static int dwarf_elf_object_access_load_section(void* obj_in,
128    Dwarf_Half section_index,
129    Dwarf_Small** section_data,
130    int* error);
131
132/*
133    dwarf_elf_object_access_internals_init()
134 */
135static int
136dwarf_elf_object_access_internals_init(void* obj_in,
137                              dwarf_elf_handle elf,
138                              int* error)
139{
140    dwarf_elf_object_access_internals_t*obj =
141        (dwarf_elf_object_access_internals_t*)obj_in;
142    char *ehdr_ident = 0;
143    Dwarf_Half machine = 0;
144    obj->elf = elf;
145
146    if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
147        *error = DW_DLE_ELF_GETIDENT_ERROR;
148        return DW_DLV_ERROR;
149    }
150
151    obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
152
153
154    if(ehdr_ident[EI_DATA] == ELFDATA2LSB){
155        obj->endianness = DW_OBJECT_LSB;
156    }
157    else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){
158        obj->endianness = DW_OBJECT_MSB;
159    }
160
161    if (obj->is_64bit) {
162#ifdef HAVE_ELF64_GETEHDR
163        obj->ehdr64 = elf64_getehdr(elf);
164        if (obj->ehdr64 == NULL) {
165            *error = DW_DLE_ELF_GETEHDR_ERROR;
166            return DW_DLV_ERROR;
167        }
168        obj->section_count = obj->ehdr64->e_shnum;
169        machine = obj->ehdr64->e_machine;
170        obj->machine = machine;
171#else
172        *error = DW_DLE_NO_ELF64_SUPPORT;
173        return DW_DLV_ERROR;
174#endif
175    }
176    else {
177        obj->ehdr32 = elf32_getehdr(elf);
178        if (obj->ehdr32 == NULL) {
179           *error = DW_DLE_ELF_GETEHDR_ERROR;
180           return DW_DLV_ERROR;
181        }
182        obj->section_count = obj->ehdr32->e_shnum;
183        machine = obj->ehdr32->e_machine;
184        obj->machine = machine;
185    }
186
187    /* The following length_size is Not Too Significant. Only used
188       one calculation, and an approximate one at that. */
189    obj->length_size = obj->is_64bit ? 8 : 4;
190    obj->pointer_size = obj->is_64bit ? 8 : 4;
191
192    if (obj->is_64bit && machine != EM_MIPS) {
193        /* MIPS/IRIX makes pointer size and length size 8 for -64.
194           Other platforms make length 4 always. */
195        /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus
196           tools, and the dwarfv2.1 64bit extension setting.
197           This is not the same as the size-of-an-offset, which
198           is 4 in 32bit dwarf and 8 in 64bit dwarf.  */
199        obj->length_size = 4;
200    }
201    return DW_DLV_OK;
202}
203
204/*
205    dwarf_elf_object_access_get_byte_order
206 */
207static
208Dwarf_Endianness
209dwarf_elf_object_access_get_byte_order(void* obj_in)
210{
211    dwarf_elf_object_access_internals_t*obj =
212        (dwarf_elf_object_access_internals_t*)obj_in;
213    return obj->endianness;
214}
215
216/*
217    dwarf_elf_object_access_get_section_count()
218 */
219static
220Dwarf_Unsigned
221dwarf_elf_object_access_get_section_count(void * obj_in)
222{
223    dwarf_elf_object_access_internals_t*obj =
224        (dwarf_elf_object_access_internals_t*)obj_in;
225    return obj->section_count;
226}
227
228
229/*
230    dwarf_elf_object_access_get_section()
231 */
232static
233int
234dwarf_elf_object_access_get_section_info(
235    void* obj_in,
236    Dwarf_Half section_index,
237    Dwarf_Obj_Access_Section* ret_scn,
238    int* error)
239{
240    dwarf_elf_object_access_internals_t*obj =
241        (dwarf_elf_object_access_internals_t*)obj_in;
242
243    Elf32_Shdr *shdr32 = 0;
244
245#ifdef HAVE_ELF64_GETSHDR
246    Elf64_Shdr *shdr64 = 0;
247#endif
248    Elf_Scn *scn = 0;
249
250
251    scn = elf_getscn(obj->elf, section_index);
252    if (scn == NULL) {
253        *error = DW_DLE_MDE;
254        return DW_DLV_ERROR;
255    }
256    if (obj->is_64bit) {
257#ifdef HAVE_ELF64_GETSHDR
258        shdr64 = elf64_getshdr(scn);
259        if (shdr64 == NULL) {
260            *error = DW_DLE_ELF_GETSHDR_ERROR;
261            return DW_DLV_ERROR;
262        }
263
264        ret_scn->size = shdr64->sh_size;
265        ret_scn->addr = shdr64->sh_addr;
266        ret_scn->link = shdr64->sh_link;
267
268        ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
269                                        shdr64->sh_name);
270        if(ret_scn->name == NULL) {
271            *error = DW_DLE_ELF_STRPTR_ERROR;
272            return DW_DLV_ERROR;
273        }
274        return DW_DLV_OK;
275#else
276        *error = DW_DLE_MISSING_ELF64_SUPPORT;
277        return DW_DLV_ERROR;
278#endif /* HAVE_ELF64_GETSHDR */
279    }
280    if ((shdr32 = elf32_getshdr(scn)) == NULL) {
281        *error = DW_DLE_ELF_GETSHDR_ERROR;
282        return DW_DLV_ERROR;
283    }
284
285    ret_scn->size = shdr32->sh_size;
286    ret_scn->addr = shdr32->sh_addr;
287    ret_scn->link = shdr32->sh_link;
288
289    ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
290        shdr32->sh_name);
291    if (ret_scn->name == NULL) {
292        *error = DW_DLE_ELF_STRPTR_ERROR;
293        return DW_DLV_ERROR;
294    }
295    return DW_DLV_OK;
296}
297
298/*
299    dwarf_elf_object_access_get_length_size
300 */
301static
302Dwarf_Small
303dwarf_elf_object_access_get_length_size(void* obj_in)
304{
305    dwarf_elf_object_access_internals_t*obj =
306        (dwarf_elf_object_access_internals_t*)obj_in;
307    return obj->length_size;
308}
309
310/*
311    dwarf_elf_object_access_get_pointer_size
312 */
313static
314Dwarf_Small
315dwarf_elf_object_access_get_pointer_size(void* obj_in)
316{
317    dwarf_elf_object_access_internals_t*obj =
318        (dwarf_elf_object_access_internals_t*)obj_in;
319    return obj->pointer_size;
320}
321
322#define MATCH_REL_SEC(i_,s_,r_)  \
323if(i_ == s_.dss_index) { \
324    *r_ = &s_;            \
325    return DW_DLV_OK;    \
326}
327
328static int
329find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
330   struct Dwarf_Section_s **relocatablesec, int *error)
331{
332    MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
333    MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
334    MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
335    MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
336    MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
337    MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
338    MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
339    MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
340    MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
341    MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
342    MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
343    MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
344    MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
345    MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
346    MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
347    /* dbg-> de_debug_str,syms); */
348    /* de_elf_symtab,syms); */
349    /* de_elf_strtab,syms); */
350    *error = DW_DLE_RELOC_SECTION_MISMATCH;
351    return DW_DLV_ERROR;
352
353}
354#undef MATCH_REL_SEC
355
356static void
357get_rela_elf32(Dwarf_Small *data, unsigned int i,
358  int endianness,
359  int machine, struct Dwarf_Elf_Rela *relap)
360{
361    Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
362    relap->r_offset = relp->r_offset;
363    /*
364    relap->r_info = relp->r_info;
365   */
366    relap->r_type = ELF32_R_TYPE(relp->r_info);
367    relap->r_symidx = ELF32_R_SYM(relp->r_info);
368    relap->r_addend = relp->r_addend;
369}
370
371static void
372get_rela_elf64(Dwarf_Small *data, unsigned int i,
373  int endianness,
374  int machine,struct Dwarf_Elf_Rela *relap)
375{
376#ifdef HAVE_ELF64_RELA
377    Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
378    relap->r_offset = relp->r_offset;
379    /*
380    relap->r_info = relp->r_info;
381    */
382    if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ) {
383        /* This is really wierd. Treat this very specially.
384           The Elf64 LE MIPS object used for
385           testing (that has rela) wants the
386           values as  sym  ssym type3 type2 type, treating
387           each value as independent value. But libelf xlate
388           treats it as something else so we fudge here.
389           It is unclear
390           how to precisely characterize where these relocations
391           were used.
392           SGI MIPS on IRIX never used .rela relocations.
393           The BE 64bit elf MIPS test object with rela uses traditional
394           elf relocation layouts, not this special case.  */
395#define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
396#define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
397        /* We ignore the special TYPE2 and TYPE3, they should be
398           value R_MIPS_NONE in rela. */
399        relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
400        relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
401#undef MIPS64SYM
402#undef MIPS64TYPE
403    } else
404    {
405        relap->r_type = ELF64_R_TYPE(relp->r_info);
406        relap->r_symidx = ELF64_R_SYM(relp->r_info);
407    }
408    relap->r_addend = relp->r_addend;
409#endif
410}
411
412static void
413get_relocations_array(Dwarf_Bool is_64bit,
414    int endianness,
415    int machine,
416    Dwarf_Small *data,
417    unsigned int num_relocations,
418    struct Dwarf_Elf_Rela *relap)
419{
420    unsigned int i = 0;
421    void (*get_relocations)(Dwarf_Small *data, unsigned int i,
422         int endianness,
423         int machine,
424         struct Dwarf_Elf_Rela *relap);
425
426    /* Handle 32/64 bit issue
427     */
428    if (is_64bit) {
429        get_relocations = get_rela_elf64;
430    } else {
431        get_relocations = get_rela_elf32;
432    }
433
434    for (i=0; i < num_relocations; i++) {
435       get_relocations(data, i,endianness,machine, &(relap[i]));
436    }
437
438}
439
440static int
441get_relocation_entries(Dwarf_Bool is_64bit,
442    int endianness,
443    int machine,
444    Dwarf_Small *relocation_section,
445    Dwarf_Unsigned relocation_section_size,
446    struct Dwarf_Elf_Rela **relas,
447    unsigned int *nrelas,
448    int *error)
449{
450    unsigned int relocation_size = 0;
451
452    if (is_64bit) {
453#ifdef HAVE_ELF64_RELA
454        relocation_size = sizeof(Elf64_Rela);
455#else
456        *error = DW_DLE_MISSING_ELF64_SUPPORT;
457        return DW_DLV_ERROR;
458#endif
459    } else {
460        relocation_size = sizeof(Elf32_Rela);
461    }
462
463    if (relocation_section == NULL) {
464        *error = DW_DLE_RELOC_SECTION_PTR_NULL;
465        return(DW_DLV_ERROR);
466    }
467
468    if ((relocation_section_size != 0)) {
469        size_t bytescount = 0;
470        if(relocation_section_size%relocation_size) {
471            *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
472            return DW_DLV_ERROR;
473        }
474        *nrelas = relocation_section_size/relocation_size;
475        bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
476        *relas = malloc(bytescount);
477        if (!*relas) {
478            *error = DW_DLE_MAF;
479            return(DW_DLV_ERROR);
480        }
481        memset(*relas,0,bytescount);
482        get_relocations_array(is_64bit,endianness,machine, relocation_section,
483            *nrelas, *relas);
484    }
485    return(DW_DLV_OK);
486}
487
488static Dwarf_Bool
489is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine)
490{
491    Dwarf_Bool r = 0;
492    switch (machine) {
493#if defined(EM_MIPS) && defined (R_MIPS_32)
494    case EM_MIPS:
495         r = (type == R_MIPS_32);
496         break;
497#endif
498#if defined(EM_SPARC32PLUS)  && defined (R_SPARC_UA32)
499    case EM_SPARC32PLUS:
500         r =  (type == R_SPARC_UA32);
501         break;
502#endif
503#if defined(EM_SPARCV9)  && defined (R_SPARC_UA32)
504    case EM_SPARCV9:
505         r =  (type == R_SPARC_UA32);
506         break;
507#endif
508#if defined(EM_SPARC) && defined (R_SPARC_UA32)
509    case EM_SPARC:
510         r =  (type == R_SPARC_UA32);
511         break;
512#endif
513#if defined(EM_386) && defined (R_386_32)
514    case EM_386:
515        r =  (type == R_386_32);
516        break;
517#endif
518#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
519    case EM_IA_64:
520        r =  (type == R_IA64_SECREL32LSB);
521        break;
522#endif
523#if defined(EM_PPC64) && defined (R_PPC64_ADDR32)
524    case EM_PPC64:
525        r =  (type == R_PPC64_ADDR32);
526        break;
527#endif
528#if defined(EM_PPC) && defined (R_PPC_ADDR32)
529    case EM_PPC:
530        r =  (type == R_PPC_ADDR32);
531        break;
532#endif
533#if defined(EM_S390) && defined (R_390_32)
534    case EM_S390:
535        r =  (type == R_390_32);
536        break;
537#endif
538#if defined(EM_X86_64) && defined (R_X86_64_32)
539    case EM_X86_64:
540        r = (type == R_X86_64_32);
541        break;
542#endif
543    }
544    return r;
545}
546
547static Dwarf_Bool
548is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine)
549{
550    Dwarf_Bool r = 0;
551    switch (machine) {
552#if defined(EM_MIPS) && defined (R_MIPS_64)
553    case EM_MIPS:
554        r =  (type == R_MIPS_64);
555        break;
556#endif
557#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64)
558    case EM_SPARC32PLUS:
559        r =  (type == R_SPARC_UA64);
560        break;
561#endif
562#if defined(EM_SPARCV9) && defined (R_SPARC_UA64)
563    case EM_SPARCV9:
564        r = (type == R_SPARC_UA64);
565        break;
566#endif
567#if defined(EM_SPARC) && defined (R_SPARC_UA64)
568    case EM_SPARC:
569        r = (type == R_SPARC_UA64);
570        break;
571#endif
572#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
573    case EM_IA_64:
574        r =  (type == R_IA64_DIR64LSB);
575        break;
576#endif
577#if defined(EM_PPC64) && defined (R_PPC64_ADDR64)
578    case EM_PPC64:
579        r =  (type == R_PPC64_ADDR64);
580        break;
581#endif
582#if defined(EM_S390) && defined (R_390_64)
583    case EM_S390:
584        r =  (type == R_390_64);
585        break;
586#endif
587#if defined(EM_X86_64) && defined (R_X86_64_64)
588    case EM_X86_64:
589        r =  (type == R_X86_64_64);
590        break;
591#endif
592    }
593    return r;
594}
595
596
597static void
598update_entry(Dwarf_Debug dbg,
599    Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
600    Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
601    Dwarf_Small *target_section, Dwarf_Small *section_data)
602{
603    unsigned int type = 0;
604    unsigned int sym_idx = 0;
605#ifdef HAVE_ELF64_SYM
606    Elf64_Sym sym_buf;
607    Elf64_Sym *sym = 0;
608#else
609    Elf32_Sym sym_buf;
610    Elf32_Sym *sym = 0;
611#endif
612    Elf32_Sym *sym32 = 0;
613    Dwarf_ufixed64 offset = 0;
614    Dwarf_sfixed64 addend = 0;
615    Dwarf_Unsigned reloc_size = 0;
616
617
618    /* Dwarf_Elf_Rela dereferencing */
619    offset = rela->r_offset;
620    addend = rela->r_addend;
621    type = rela->r_type;
622    sym_idx = rela->r_symidx;
623
624    if (is_64bit) {
625#ifdef HAVE_ELF64_SYM
626       sym = &((Elf64_Sym*)section_data)[sym_idx];
627#endif
628    } else {
629       sym32 = &((Elf32_Sym*)section_data)[sym_idx];
630
631       /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at
632        * an Elf64_Sym local variable (sym_buf) to allow us to use the
633        * same pointer (sym) for both 32-bit and 64-bit instances.
634        */
635       sym = &sym_buf;
636       sym->st_name = sym32->st_name;
637       sym->st_info = sym32->st_info;
638       sym->st_other = sym32->st_other;
639       sym->st_shndx = sym32->st_shndx;
640       sym->st_value = sym32->st_value;
641       sym->st_size = sym32->st_size;
642    }
643
644    /* Determine relocation size */
645    if (is_32bit_abs_reloc(type, machine)) {
646        reloc_size = 4;
647    } else if (is_64bit_abs_reloc(type, machine)) {
648        reloc_size = 8;
649    } else {
650        return;
651    }
652
653
654    {
655        /* Assuming we do not need to do a READ_UNALIGNED here
656           at target_section + offset and add its value to
657           outval.  Some ABIs say no read (for example MIPS),
658           but if some do then which ones? */
659        Dwarf_Unsigned outval = sym->st_value + addend;
660        WRITE_UNALIGNED(dbg,target_section + offset,
661                  &outval,sizeof(outval),reloc_size);
662    }
663}
664
665
666
667static int
668apply_rela_entries(Dwarf_Debug dbg,
669    Dwarf_Bool is_64bit,
670    Dwarf_Endianness endianess,
671    Dwarf_Half machine,
672    Dwarf_Small *target_section,
673    Dwarf_Small *symtab_section,
674    struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
675    int *error)
676{
677    if ((target_section != NULL)  && (relas != NULL)) {
678        unsigned int i;
679        for (i = 0; i < nrelas; i++) {
680            update_entry(dbg, is_64bit,
681                endianess,
682                machine,
683                &(relas)[i],
684                target_section,
685                symtab_section);
686        }
687    }
688    return DW_DLV_OK;
689}
690
691
692static int
693loop_through_relocations(
694   Dwarf_Debug dbg,
695   dwarf_elf_object_access_internals_t* obj,
696   struct Dwarf_Section_s *relocatablesec,
697   int *error)
698{
699    Dwarf_Small *target_section = 0;
700    Dwarf_Small *symtab_section = obj->symtab->dss_data;
701    Dwarf_Small *relocation_section  = relocatablesec->dss_reloc_data;
702    Dwarf_Unsigned relocation_section_size =
703              relocatablesec->dss_reloc_size;
704    int ret = DW_DLV_ERROR;
705    struct Dwarf_Elf_Rela *relas = 0;
706    unsigned int nrelas = 0;
707    Dwarf_Small *mspace = 0;
708
709    ret = get_relocation_entries(obj->is_64bit,
710        obj->endianness,
711        obj->machine,
712        relocation_section,
713        relocation_section_size,
714        &relas, &nrelas, error);
715    if(ret != DW_DLV_OK) {
716        free(relas);
717        return ret;
718    }
719
720    /* Some systems read Elf in read-only memory via mmap or the like.
721       So the only safe thing is to copy the current data into
722       malloc space and refer to the malloc space instead of the
723       space returned by the elf library */
724    mspace = malloc(relocatablesec->dss_size);
725    if(!mspace) {
726        *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
727        return DW_DLV_ERROR;
728    }
729    memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
730    relocatablesec->dss_data = mspace;
731    target_section = relocatablesec->dss_data;
732    relocatablesec->dss_data_was_malloc = 1;
733
734    ret = apply_rela_entries(
735        dbg,
736        obj->is_64bit,
737        obj->endianness, obj->machine,
738        target_section,
739        symtab_section,
740        relas, nrelas, error);
741
742    free(relas);
743
744    return ret;
745}
746
747/*
748    Find the section data in dbg and find all the relevant
749    sections.  Then do relocations.
750*/
751static int
752dwarf_elf_object_relocate_a_section(void* obj_in,
753    Dwarf_Half section_index,
754    Dwarf_Debug dbg,
755    int* error)
756{
757    int res = DW_DLV_ERROR;
758    dwarf_elf_object_access_internals_t*obj = 0;
759    struct Dwarf_Section_s * relocatablesec = 0;
760    if (section_index == 0) {
761        return DW_DLV_NO_ENTRY;
762    }
763    obj = (dwarf_elf_object_access_internals_t*)obj_in;
764
765    /* The section to relocate must already be loaded into memory. */
766    res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
767    if(res != DW_DLV_OK) {
768         return res;
769    }
770
771    /* Sun and possibly others do not always set sh_link in .debug_* sections.
772       So we cannot do full  consistency checks. */
773    if(relocatablesec->dss_reloc_index == 0 ) {
774        /* Something is wrong. */
775        *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
776        return DW_DLV_ERROR;
777    }
778    /* Now load the relocations themselves. */
779    res =  dwarf_elf_object_access_load_section(obj_in,
780            relocatablesec->dss_reloc_index,
781            &relocatablesec->dss_reloc_data, error);
782    if(res != DW_DLV_OK) {
783            return res;
784    }
785
786    /* Now get the symtab. */
787    if  (!obj->symtab) {
788       obj->symtab = &dbg->de_elf_symtab;
789       obj->strtab = &dbg->de_elf_strtab;
790    }
791    if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
792        /* Something is wrong. */
793        *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
794        return DW_DLV_ERROR;
795    }
796    if( obj->strtab->dss_index != obj->symtab->dss_link) {
797        /* Something is wrong. */
798        *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
799        return DW_DLV_ERROR;
800    }
801    if(!obj->symtab->dss_data) {
802        /* Now load the symtab */
803        res =  dwarf_elf_object_access_load_section(obj_in,
804            obj->symtab->dss_index,
805            &obj->symtab->dss_data, error);
806        if(res != DW_DLV_OK) {
807            return res;
808        }
809    }
810    if(! obj->strtab->dss_data) {
811        /* Now load the strtab */
812        res = dwarf_elf_object_access_load_section(obj_in,
813            obj->strtab->dss_index,
814            &obj->strtab->dss_data,error);
815        if(res != DW_DLV_OK){
816            return res;
817        }
818    }
819
820    /* We have all the data we need in memory. */
821    res = loop_through_relocations(dbg,obj,relocatablesec,error);
822
823    return res;
824}
825
826/*
827    dwarf_elf_object_access_load_section
828 */
829static int
830dwarf_elf_object_access_load_section(void* obj_in,
831    Dwarf_Half section_index,
832    Dwarf_Small** section_data,
833    int* error)
834{
835    dwarf_elf_object_access_internals_t*obj =
836        (dwarf_elf_object_access_internals_t*)obj_in;
837    if (section_index == 0) {
838        return DW_DLV_NO_ENTRY;
839    }
840
841    {
842        Elf_Scn *scn = 0;
843        Elf_Data *data = 0;
844
845        scn = elf_getscn(obj->elf, section_index);
846        if (scn == NULL) {
847            *error = DW_DLE_MDE;
848            return DW_DLV_ERROR;
849        }
850
851        /*
852           When using libelf as a producer, section data may be stored
853           in multiple buffers. In libdwarf however, we only use libelf
854           as a consumer (there is a dwarf producer API, but it doesn't
855           use libelf). Because of this, this single call to elf_getdata
856           will retrieve the entire section in a single contiguous
857           buffer. */
858        data = elf_getdata(scn, NULL);
859        if (data == NULL) {
860                  *error = DW_DLE_MDE;
861                  return DW_DLV_ERROR;
862        }
863        *section_data = data->d_buf;
864    }
865    return DW_DLV_OK;
866}
867
868
869/* dwarf_elf_access method table. */
870static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
871{
872    dwarf_elf_object_access_get_section_info,
873    dwarf_elf_object_access_get_byte_order,
874    dwarf_elf_object_access_get_length_size,
875    dwarf_elf_object_access_get_pointer_size,
876    dwarf_elf_object_access_get_section_count,
877    dwarf_elf_object_access_load_section,
878    dwarf_elf_object_relocate_a_section
879};
880
881
882/*
883    Interface for the ELF object file implementation.
884 */
885int
886dwarf_elf_object_access_init(dwarf_elf_handle elf,
887    int libdwarf_owns_elf,
888    Dwarf_Obj_Access_Interface** ret_obj,
889    int *err)
890{
891    int res = 0;
892    dwarf_elf_object_access_internals_t *internals = 0;
893    Dwarf_Obj_Access_Interface *intfc = 0;
894
895    internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
896    if(!internals) {
897        /* Impossible case, we hope. Give up. */
898        return DW_DLV_ERROR;
899    }
900    memset(internals,0,sizeof(*internals));
901    res = dwarf_elf_object_access_internals_init(internals, elf, err);
902    if(res != DW_DLV_OK){
903        free(internals);
904        return DW_DLV_ERROR;
905    }
906    internals->libdwarf_owns_elf = libdwarf_owns_elf;
907
908    intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
909    if(!intfc) {
910        /* Impossible case, we hope. Give up. */
911        free(internals);
912        return DW_DLV_ERROR;
913    }
914    /* Initialize the interface struct */
915    intfc->object = internals;
916    intfc->methods = &dwarf_elf_object_access_methods;
917
918    *ret_obj = intfc;
919    return DW_DLV_OK;
920}
921
922
923
924/*
925    Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.
926 */
927void
928dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
929{
930    if(!obj) {
931        return;
932    }
933    if(obj->object) {
934        dwarf_elf_object_access_internals_t *internals =
935            (dwarf_elf_object_access_internals_t *)obj->object;
936        if(internals->libdwarf_owns_elf){
937            elf_end(internals->elf);
938        }
939    }
940    free(obj->object);
941    free(obj);
942}
943
944/*
945    This function returns the Elf * pointer
946    associated with a Dwarf_Debug.
947
948    This function only makes sense if ELF is implied.
949 */
950int
951dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
952              Dwarf_Error * error)
953{
954    struct Dwarf_Obj_Access_Interface_s * obj = 0;
955    if (dbg == NULL) {
956        _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
957        return (DW_DLV_ERROR);
958    }
959
960    obj = dbg->de_obj_file;
961    if(obj) {
962       dwarf_elf_object_access_internals_t *internals =
963           (dwarf_elf_object_access_internals_t*)obj->object;
964       if(internals->elf == NULL) {
965           _dwarf_error(dbg, error, DW_DLE_FNO);
966           return (DW_DLV_ERROR);
967       }
968       *elf = internals->elf;
969       return DW_DLV_OK;
970
971    }
972    _dwarf_error(dbg, error, DW_DLE_FNO);
973    return DW_DLV_ERROR;
974}
975
976
977