xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_elf_access.c (revision 142d813a06c6f9a6142e2c276b62129a17a31a65)
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
70 extern Elf64_Ehdr *elf64_getehdr(Elf *);
71 #endif
72 #ifdef HAVE_ELF64_GETSHDR
73 extern 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 
96 typedef 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 
118 struct 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 
127 static 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  */
135 static int
136 dwarf_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  */
207 static
208 Dwarf_Endianness
209 dwarf_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  */
219 static
220 Dwarf_Unsigned
221 dwarf_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  */
232 static
233 int
234 dwarf_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  */
301 static
302 Dwarf_Small
303 dwarf_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  */
313 static
314 Dwarf_Small
315 dwarf_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_)  \
323 if(i_ == s_.dss_index) { \
324     *r_ = &s_;            \
325     return DW_DLV_OK;    \
326 }
327 
328 static int
329 find_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 
356 static void
357 get_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 
371 static void
372 get_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 
412 static void
413 get_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 
440 static int
441 get_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 
488 static Dwarf_Bool
489 is_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 
547 static Dwarf_Bool
548 is_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 
597 static void
598 update_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 
667 static int
668 apply_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 
692 static int
693 loop_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 */
751 static int
752 dwarf_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  */
829 static int
830 dwarf_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. */
870 static 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  */
885 int
886 dwarf_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  */
927 void
928 dwarf_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  */
950 int
951 dwarf_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