8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / tools / ctf / dwarf / common / dwarf_elf_access.c
blob6caa64a758fc706848ed5208a0edb412d86fb700
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.
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.
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.
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.
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.
28 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
29 Mountain View, CA 94043, or:
31 http://www.sgi.com
33 For further information regarding this notice, see:
35 http://oss.sgi.com/projects/GenInfo/NoticeExplan
39 #include "config.h"
40 #include "dwarf_incl.h"
41 #include "dwarf_elf_access.h"
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
54 #include <stdio.h>
55 #include <sys/stat.h>
56 #include <sys/types.h>
57 #include <string.h>
58 #include <stdlib.h>
60 #define FALSE 0
61 #define TRUE 1
63 #ifndef EM_MIPS
64 /* This is the standard elf value EM_MIPS. */
65 #define EM_MIPS 8
66 #endif
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) ; \
84 #else /* LITTLE ENDIAN */
86 #define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
87 { \
88 dbg->de_copy_word( (dest) , \
89 ((char *)source) , \
90 len_out) ; \
92 #endif
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;
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;
116 } dwarf_elf_object_access_internals_t;
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;
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);
133 dwarf_elf_object_access_internals_init()
135 static int
136 dwarf_elf_object_access_internals_init(void* obj_in,
137 dwarf_elf_handle elf,
138 int* error)
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;
146 if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
147 *error = DW_DLE_ELF_GETIDENT_ERROR;
148 return DW_DLV_ERROR;
151 obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
154 if(ehdr_ident[EI_DATA] == ELFDATA2LSB){
155 obj->endianness = DW_OBJECT_LSB;
157 else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){
158 obj->endianness = DW_OBJECT_MSB;
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;
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
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;
182 obj->section_count = obj->ehdr32->e_shnum;
183 machine = obj->ehdr32->e_machine;
184 obj->machine = machine;
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;
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;
201 return DW_DLV_OK;
205 dwarf_elf_object_access_get_byte_order
207 static
208 Dwarf_Endianness
209 dwarf_elf_object_access_get_byte_order(void* obj_in)
211 dwarf_elf_object_access_internals_t*obj =
212 (dwarf_elf_object_access_internals_t*)obj_in;
213 return obj->endianness;
217 dwarf_elf_object_access_get_section_count()
219 static
220 Dwarf_Unsigned
221 dwarf_elf_object_access_get_section_count(void * obj_in)
223 dwarf_elf_object_access_internals_t*obj =
224 (dwarf_elf_object_access_internals_t*)obj_in;
225 return obj->section_count;
230 dwarf_elf_object_access_get_section()
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)
240 dwarf_elf_object_access_internals_t*obj =
241 (dwarf_elf_object_access_internals_t*)obj_in;
243 Elf32_Shdr *shdr32 = 0;
245 #ifdef HAVE_ELF64_GETSHDR
246 Elf64_Shdr *shdr64 = 0;
247 #endif
248 Elf_Scn *scn = 0;
251 scn = elf_getscn(obj->elf, section_index);
252 if (scn == NULL) {
253 *error = DW_DLE_MDE;
254 return DW_DLV_ERROR;
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;
264 ret_scn->size = shdr64->sh_size;
265 ret_scn->addr = shdr64->sh_addr;
266 ret_scn->link = shdr64->sh_link;
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;
274 return DW_DLV_OK;
275 #else
276 *error = DW_DLE_MISSING_ELF64_SUPPORT;
277 return DW_DLV_ERROR;
278 #endif /* HAVE_ELF64_GETSHDR */
280 if ((shdr32 = elf32_getshdr(scn)) == NULL) {
281 *error = DW_DLE_ELF_GETSHDR_ERROR;
282 return DW_DLV_ERROR;
285 ret_scn->size = shdr32->sh_size;
286 ret_scn->addr = shdr32->sh_addr;
287 ret_scn->link = shdr32->sh_link;
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;
295 return DW_DLV_OK;
299 dwarf_elf_object_access_get_length_size
301 static
302 Dwarf_Small
303 dwarf_elf_object_access_get_length_size(void* obj_in)
305 dwarf_elf_object_access_internals_t*obj =
306 (dwarf_elf_object_access_internals_t*)obj_in;
307 return obj->length_size;
311 dwarf_elf_object_access_get_pointer_size
313 static
314 Dwarf_Small
315 dwarf_elf_object_access_get_pointer_size(void* obj_in)
317 dwarf_elf_object_access_internals_t*obj =
318 (dwarf_elf_object_access_internals_t*)obj_in;
319 return obj->pointer_size;
322 #define MATCH_REL_SEC(i_,s_,r_) \
323 if(i_ == s_.dss_index) { \
324 *r_ = &s_; \
325 return DW_DLV_OK; \
328 static int
329 find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
330 struct Dwarf_Section_s **relocatablesec, int *error)
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;
354 #undef MATCH_REL_SEC
356 static void
357 get_rela_elf32(Dwarf_Small *data, unsigned int i,
358 int endianness,
359 int machine, struct Dwarf_Elf_Rela *relap)
361 Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
362 relap->r_offset = relp->r_offset;
364 relap->r_info = relp->r_info;
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;
371 static void
372 get_rela_elf64(Dwarf_Small *data, unsigned int i,
373 int endianness,
374 int machine,struct Dwarf_Elf_Rela *relap)
376 #ifdef HAVE_ELF64_RELA
377 Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
378 relap->r_offset = relp->r_offset;
380 relap->r_info = relp->r_info;
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
405 relap->r_type = ELF64_R_TYPE(relp->r_info);
406 relap->r_symidx = ELF64_R_SYM(relp->r_info);
408 relap->r_addend = relp->r_addend;
409 #endif
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)
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);
426 /* Handle 32/64 bit issue
428 if (is_64bit) {
429 get_relocations = get_rela_elf64;
430 } else {
431 get_relocations = get_rela_elf32;
434 for (i=0; i < num_relocations; i++) {
435 get_relocations(data, i,endianness,machine, &(relap[i]));
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)
450 unsigned int relocation_size = 0;
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);
463 if (relocation_section == NULL) {
464 *error = DW_DLE_RELOC_SECTION_PTR_NULL;
465 return(DW_DLV_ERROR);
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;
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);
481 memset(*relas,0,bytescount);
482 get_relocations_array(is_64bit,endianness,machine, relocation_section,
483 *nrelas, *relas);
485 return(DW_DLV_OK);
488 static Dwarf_Bool
489 is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine)
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
544 return r;
547 static Dwarf_Bool
548 is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine)
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
593 return r;
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)
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;
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;
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];
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.
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;
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;
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);
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)
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);
688 return DW_DLV_OK;
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)
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;
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;
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;
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;
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);
742 free(relas);
744 return ret;
748 Find the section data in dbg and find all the relevant
749 sections. Then do relocations.
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)
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;
763 obj = (dwarf_elf_object_access_internals_t*)obj_in;
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;
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;
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;
786 /* Now get the symtab. */
787 if (!obj->symtab) {
788 obj->symtab = &dbg->de_elf_symtab;
789 obj->strtab = &dbg->de_elf_strtab;
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;
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;
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;
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;
820 /* We have all the data we need in memory. */
821 res = loop_through_relocations(dbg,obj,relocatablesec,error);
823 return res;
827 dwarf_elf_object_access_load_section
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)
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;
842 Elf_Scn *scn = 0;
843 Elf_Data *data = 0;
845 scn = elf_getscn(obj->elf, section_index);
846 if (scn == NULL) {
847 *error = DW_DLE_MDE;
848 return DW_DLV_ERROR;
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;
863 *section_data = data->d_buf;
865 return DW_DLV_OK;
869 /* dwarf_elf_access method table. */
870 static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
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
883 Interface for the ELF object file implementation.
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)
891 int res = 0;
892 dwarf_elf_object_access_internals_t *internals = 0;
893 Dwarf_Obj_Access_Interface *intfc = 0;
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;
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;
906 internals->libdwarf_owns_elf = libdwarf_owns_elf;
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;
914 /* Initialize the interface struct */
915 intfc->object = internals;
916 intfc->methods = &dwarf_elf_object_access_methods;
918 *ret_obj = intfc;
919 return DW_DLV_OK;
925 Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.
927 void
928 dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
930 if(!obj) {
931 return;
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);
940 free(obj->object);
941 free(obj);
945 This function returns the Elf * pointer
946 associated with a Dwarf_Debug.
948 This function only makes sense if ELF is implied.
951 dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
952 Dwarf_Error * error)
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);
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);
968 *elf = internals->elf;
969 return DW_DLV_OK;
972 _dwarf_error(dbg, error, DW_DLE_FNO);
973 return DW_DLV_ERROR;