xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_elf_load_headers.c (revision 3cac7b0d73edf3f2674ad0f64d1fff3d2e59ae8c)
1 /*
2 Copyright 2018 David Anderson. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with
5 or without modification, are permitted provided that the
6 following conditions are met:
7 
8     Redistributions of source code must retain the above
9     copyright notice, this list of conditions and the following
10     disclaimer.
11 
12     Redistributions in binary form must reproduce the above
13     copyright notice, this list of conditions and the following
14     disclaimer in the documentation and/or other materials
15     provided with the distribution.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 
32 /*
33 This reads elf headers and creates generic-elf
34 structures containing the Elf headers.
35 
36 These two enums used for type safety in passing
37 values.  See dwarf_elfread.h
38 
39 enum RelocRela
40 enum RelocOffsetSize
41 
42 dwarf_elfread.c
43 calls
44     _dwarf_load_elf_relx(intfc,i,...,enum RelocRela,errcode)
45         calls _dwarf_elf_load_a_relx_batch(ep,...enum RelocRela,
46             enum RelocOffsetSize,errcode)
47             which calls generic_rel_from_rela32(ep,gsh,relp,grel
48             or    calls generic_rel_from_rela64(ep,gsh,relp,grel
49             or    calls generic_rel_from_rel32(ep,gsh,relp,grel...
50             or    calls generic_rel_from_rel64(ep,gsh,relp,grel...
51 */
52 
53 
54 #include "config.h"
55 #include <stdio.h>
56 #include <string.h> /* For memcpy etc */
57 #ifdef HAVE_STDLIB_H
58 #include <stdlib.h>
59 #endif /* HAVE_STDLIB_H */
60 #ifdef HAVE_MALLOC_H
61 /* Useful include for some Windows compilers. */
62 #include <malloc.h>
63 #endif /* HAVE_MALLOC_H */
64 #include <stddef.h>
65 #include <sys/types.h>   /* for open() */
66 #include <sys/stat.h>   /* for open() */
67 #include <fcntl.h>   /* for open() */
68 #ifdef HAVE_UNISTD_H
69 #include <unistd.h> /* lseek read close */
70 #elif defined(_WIN32) && defined(_MSC_VER)
71 #include <io.h>
72 #endif /* HAVE_UNISTD_H */
73 
74 /* Windows specific header files */
75 #if defined(_WIN32) && defined(HAVE_STDAFX_H)
76 #include "stdafx.h"
77 #endif /* HAVE_STDAFX_H */
78 
79 #include "libdwarfdefs.h"
80 #include "dwarf.h"
81 #include "libdwarf.h"
82 #include "dwarf_base_types.h"
83 #include "dwarf_opaque.h"
84 #include "memcpy_swap.h"
85 #include "dwarf_elfstructs.h"
86 #include "dwarf_reading.h"
87 #include "dwarf_elf_defines.h"
88 #include "dwarf_elfread.h"
89 #include "dwarf_object_detector.h"
90 #include "dwarf_object_read_common.h"
91 #include "dwarf_util.h"
92 
93 #ifndef O_BINARY
94 #define O_BINARY 0
95 #endif /* O_BINARY */
96 
97 #ifdef HAVE_UNUSED_ATTRIBUTE
98 #define  UNUSEDARG __attribute__ ((unused))
99 #else
100 #define  UNUSEDARG
101 #endif
102 #define TRUE  1
103 #define FALSE 0
104 
105 #ifdef WORDS_BIGENDIAN
106 #define ASNAR(func,t,s)                         \
107     do {                                        \
108         unsigned tbyte = sizeof(t) - sizeof(s); \
109         t = 0;                                  \
110         func(((char *)&t)+tbyte ,&s[0],sizeof(s));  \
111     } while (0)
112 #else /* LITTLE ENDIAN */
113 #define ASNAR(func,t,s)                         \
114     do {                                        \
115         t = 0;                                  \
116         func(&t,&s[0],sizeof(s));               \
117     } while (0)
118 #endif /* end LITTLE- BIG-ENDIAN */
119 
120 static int
121 _dwarf_load_elf_section_is_dwarf(const char *sname,
122     int *is_rela,int *is_rel)
123 {
124     *is_rel = FALSE;
125     *is_rela = FALSE;
126     if(_dwarf_ignorethissection(sname)) {
127         return FALSE;
128     }
129     if (!strncmp(sname,".rel",4)) {
130         if (!strncmp(sname,".rela.",6)) {
131             *is_rela = TRUE;
132             return TRUE;
133         }
134         if (!strncmp(sname,".rel.",5)) {
135             *is_rela = TRUE;
136             return TRUE;
137         }
138         /*  Else something is goofy/Impossible */
139         return FALSE;
140     }
141     if (!strncmp(sname,".debug_",7)) {
142         return TRUE;
143     }
144     if (!strncmp(sname,".zdebug_",8)) {
145         return TRUE;
146     }
147     if (!strcmp(sname,".eh_frame")) {
148         return TRUE;
149     }
150     if (!strncmp(sname,".gdb_index",10)) {
151         return TRUE;
152     }
153     return FALSE;
154 }
155 
156 
157 static int
158 is_empty_section(Dwarf_Unsigned type)
159 {
160     if (type == SHT_NOBITS) {
161         return TRUE;
162     }
163     if (type == SHT_NULL) {
164         return TRUE;
165     }
166     return FALSE;
167 }
168 
169 #if 0
170 int
171 dwarf_construct_elf_access_path(const char *path,
172     dwarf_elf_object_access_internals_t **mp,int *errcode)
173 {
174     int fd = -1;
175     int res = 0;
176     dwarf_elf_object_access_internals_t *mymp = 0;
177 
178     fd = open(path, O_RDONLY|O_BINARY);
179     if (fd < 0) {
180         *errcode = DW_DLE_PATH_SIZE_TOO_SMALL;
181         return DW_DLV_ERROR;
182     }
183     res = dwarf_construct_elf_access(fd,
184         path,&mymp,errcode);
185     if (res != DW_DLV_OK) {
186         close(fd);
187         return res;
188     }
189     mymp->f_destruct_close_fd = TRUE;
190     *mp = mymp;
191     return res;
192 }
193 #endif /* 0 */
194 
195 /* Here path is not essential. Pass in with "" if unknown. */
196 int
197 dwarf_construct_elf_access(int fd,
198     const char *path,
199     dwarf_elf_object_access_internals_t **mp,int *errcode)
200 {
201     unsigned ftype = 0;
202     unsigned endian = 0;
203     unsigned offsetsize = 0;
204     Dwarf_Unsigned filesize = 0;
205     dwarf_elf_object_access_internals_t *mfp = 0;
206     int      res = 0;
207 
208     res = dwarf_object_detector_fd(fd,
209         &ftype,&endian,&offsetsize, &filesize, errcode);
210     if (res != DW_DLV_OK) {
211         return res;
212     }
213 
214     mfp = calloc(1,sizeof(dwarf_elf_object_access_internals_t));
215     if (!mfp) {
216         *errcode = DW_DLE_ALLOC_FAIL;
217         return DW_DLV_ERROR;
218     }
219     /* For non-libelf Elf, call it 'F'. Libelf Elf uses 'E' */
220     mfp->f_ident[0] = 'F';
221     mfp->f_ident[1] = 1;
222     mfp->f_fd = fd;
223     mfp->f_destruct_close_fd = FALSE;
224     mfp->f_is_64bit =  ((offsetsize==64)?TRUE:FALSE);
225     mfp->f_filesize = filesize;
226     mfp->f_offsetsize = offsetsize;
227     mfp->f_pointersize = offsetsize;
228     mfp->f_endian = endian;
229     mfp->f_ftype = ftype;
230     mfp->f_path = strdup(path);
231 
232     *mp = mfp;
233     return DW_DLV_OK;
234 }
235 
236 /*  Caller must zero the passed in pointer
237     after this returns to remind
238     the caller to avoid use of the pointer. */
239 int
240 dwarf_destruct_elf_access(dwarf_elf_object_access_internals_t* ep,
241     UNUSEDARG int *errcode)
242 {
243     struct generic_shdr *shp = 0;
244     Dwarf_Unsigned shcount = 0;
245     Dwarf_Unsigned i = 0;
246 
247     free(ep->f_ehdr);
248     shp = ep->f_shdr;
249     shcount = ep->f_loc_shdr.g_count;
250     for(i = 0; i < shcount; ++i,++shp) {
251         free(shp->gh_rels);
252         shp->gh_rels = 0;
253         free(shp->gh_content);
254         shp->gh_content = 0;
255         free(shp->gh_sht_group_array);
256         shp->gh_sht_group_array = 0;
257         shp->gh_sht_group_array_count = 0;
258     }
259     free(ep->f_shdr);
260     free(ep->f_phdr);
261     free(ep->f_elf_shstrings_data);
262     free(ep->f_dynamic);
263     free(ep->f_symtab_sect_strings);
264     free(ep->f_dynsym_sect_strings);
265     free(ep->f_symtab);
266     free(ep->f_dynsym);
267 
268     /* if TRUE close f_fd on destruct.*/
269     if (ep->f_destruct_close_fd) {
270         close(ep->f_fd);
271     }
272     ep->f_ident[0] = 'X';
273     free(ep->f_path);
274     free(ep);
275     return DW_DLV_OK;
276 }
277 
278 
279 
280 
281 static int
282 generic_ehdr_from_32(dwarf_elf_object_access_internals_t *ep,
283     struct generic_ehdr *ehdr, dw_elf32_ehdr *e,
284     UNUSEDARG int *errcode)
285 {
286     int i = 0;
287 
288     for (i = 0; i < EI_NIDENT; ++i) {
289         ehdr->ge_ident[i] = e->e_ident[i];
290     }
291     ASNAR(ep->f_copy_word,ehdr->ge_type,e->e_type);
292     ASNAR(ep->f_copy_word,ehdr->ge_machine,e->e_machine);
293     ASNAR(ep->f_copy_word,ehdr->ge_version,e->e_version);
294     ASNAR(ep->f_copy_word,ehdr->ge_entry,e->e_entry);
295     ASNAR(ep->f_copy_word,ehdr->ge_phoff,e->e_phoff);
296     ASNAR(ep->f_copy_word,ehdr->ge_shoff,e->e_shoff);
297     ASNAR(ep->f_copy_word,ehdr->ge_flags,e->e_flags);
298     ASNAR(ep->f_copy_word,ehdr->ge_ehsize,e->e_ehsize);
299     ASNAR(ep->f_copy_word,ehdr->ge_phentsize,e->e_phentsize);
300     ASNAR(ep->f_copy_word,ehdr->ge_phnum,e->e_phnum);
301     ASNAR(ep->f_copy_word,ehdr->ge_shentsize,e->e_shentsize);
302     ASNAR(ep->f_copy_word,ehdr->ge_shnum,e->e_shnum);
303     ASNAR(ep->f_copy_word,ehdr->ge_shstrndx,e->e_shstrndx);
304     ep->f_machine = ehdr->ge_machine;
305     ep->f_ehdr = ehdr;
306     ep->f_loc_ehdr.g_name = "Elf File Header";
307     ep->f_loc_ehdr.g_offset = 0;
308     ep->f_loc_ehdr.g_count = 1;
309     ep->f_loc_ehdr.g_entrysize = sizeof(dw_elf32_ehdr);
310     ep->f_loc_ehdr.g_totalsize = sizeof(dw_elf32_ehdr);
311     return DW_DLV_OK;
312 }
313 
314 static int
315 generic_ehdr_from_64(dwarf_elf_object_access_internals_t* ep,
316     struct generic_ehdr *ehdr, dw_elf64_ehdr *e,
317     UNUSEDARG int *errcode)
318 {
319     int i = 0;
320 
321     for (i = 0; i < EI_NIDENT; ++i) {
322         ehdr->ge_ident[i] = e->e_ident[i];
323     }
324     ASNAR(ep->f_copy_word,ehdr->ge_type,e->e_type);
325     ASNAR(ep->f_copy_word,ehdr->ge_machine,e->e_machine);
326     ASNAR(ep->f_copy_word,ehdr->ge_version,e->e_version);
327     ASNAR(ep->f_copy_word,ehdr->ge_entry,e->e_entry);
328     ASNAR(ep->f_copy_word,ehdr->ge_phoff,e->e_phoff);
329     ASNAR(ep->f_copy_word,ehdr->ge_shoff,e->e_shoff);
330     ASNAR(ep->f_copy_word,ehdr->ge_flags,e->e_flags);
331     ASNAR(ep->f_copy_word,ehdr->ge_ehsize,e->e_ehsize);
332     ASNAR(ep->f_copy_word,ehdr->ge_phentsize,e->e_phentsize);
333     ASNAR(ep->f_copy_word,ehdr->ge_phnum,e->e_phnum);
334     ASNAR(ep->f_copy_word,ehdr->ge_shentsize,e->e_shentsize);
335     ASNAR(ep->f_copy_word,ehdr->ge_shnum,e->e_shnum);
336     ASNAR(ep->f_copy_word,ehdr->ge_shstrndx,e->e_shstrndx);
337     ep->f_machine = ehdr->ge_machine;
338     ep->f_ehdr = ehdr;
339     ep->f_loc_ehdr.g_name = "Elf File Header";
340     ep->f_loc_ehdr.g_offset = 0;
341     ep->f_loc_ehdr.g_count = 1;
342     ep->f_loc_ehdr.g_entrysize = sizeof(dw_elf64_ehdr);
343     ep->f_loc_ehdr.g_totalsize = sizeof(dw_elf64_ehdr);
344     return DW_DLV_OK;
345 }
346 
347 
348 #if 0 /* not used */
349 static int
350 generic_phdr_from_phdr32(dwarf_elf_object_access_internals_t* ep,
351     struct generic_phdr **phdr_out,
352     Dwarf_Unsigned * count_out,
353     Dwarf_Unsigned offset,
354     Dwarf_Unsigned entsize,
355     Dwarf_Unsigned count,
356     int *errcode)
357 {
358     dw_elf32_phdr *pph =0;
359     dw_elf32_phdr *orig_pph =0;
360     struct generic_phdr *gphdr =0;
361     struct generic_phdr *orig_gphdr =0;
362     Dwarf_Unsigned i = 0;
363     int res = 0;
364 
365     *count_out = 0;
366     pph = (dw_elf32_phdr *)calloc(count , entsize);
367     if(pph == 0) {
368         *errcode =  DW_DLE_ALLOC_FAIL;
369         return DW_DLV_ERROR;
370     }
371     gphdr = (struct generic_phdr *)calloc(count,sizeof(*gphdr));
372     if(gphdr == 0) {
373         free(pph);
374         *errcode =  DW_DLE_ALLOC_FAIL;
375         return DW_DLV_ERROR;
376     }
377 
378     orig_pph = pph;
379     orig_gphdr = gphdr;
380     res = RRMOA(ep->f_fd,pph,offset,count*entsize,
381         ep->f_filesize,errcode);
382     if(res != DW_DLV_OK) {
383         free(pph);
384         free(gphdr);
385         return res;
386     }
387     for( i = 0; i < count;
388         ++i,  pph++,gphdr++) {
389         ASNAR(ep->f_copy_word,gphdr->gp_type,pph->p_type);
390         ASNAR(ep->f_copy_word,gphdr->gp_offset,pph->p_offset);
391         ASNAR(ep->f_copy_word,gphdr->gp_vaddr,pph->p_vaddr);
392         ASNAR(ep->f_copy_word,gphdr->gp_paddr,pph->p_paddr);
393         ASNAR(ep->f_copy_word,gphdr->gp_filesz,pph->p_filesz);
394         ASNAR(ep->f_copy_word,gphdr->gp_memsz,pph->p_memsz);
395         ASNAR(ep->f_copy_word,gphdr->gp_flags,pph->p_flags);
396         ASNAR(ep->f_copy_word,gphdr->gp_align,pph->p_align);
397     }
398     free(orig_pph);
399     *phdr_out = orig_gphdr;
400     *count_out = count;
401     ep->f_phdr = orig_gphdr;
402     ep->f_loc_phdr.g_name = "Program Header";
403     ep->f_loc_phdr.g_offset = offset;
404     ep->f_loc_phdr.g_count = count;
405     ep->f_loc_phdr.g_entrysize = sizeof(dw_elf32_phdr);
406     ep->f_loc_phdr.g_totalsize = sizeof(dw_elf32_phdr)*count;
407     return DW_DLV_OK;
408 }
409 
410 static int
411 generic_phdr_from_phdr64(dwarf_elf_object_access_internals_t* ep,
412     struct generic_phdr **phdr_out,
413     Dwarf_Unsigned * count_out,
414     Dwarf_Unsigned offset,
415     Dwarf_Unsigned entsize,
416     Dwarf_Unsigned count,
417     int *errcode)
418 {
419     dw_elf64_phdr *pph =0;
420     dw_elf64_phdr *orig_pph =0;
421     struct generic_phdr *gphdr =0;
422     struct generic_phdr *orig_gphdr =0;
423     int res = 0;
424     Dwarf_Unsigned i = 0;
425 
426     *count_out = 0;
427     pph = (dw_elf64_phdr *)calloc(count , entsize);
428     if(pph == 0) {
429         *errcode =  DW_DLE_ALLOC_FAIL;
430         return DW_DLV_ERROR;
431     }
432     gphdr = (struct generic_phdr *)calloc(count,sizeof(*gphdr));
433     if(gphdr == 0) {
434         free(pph);
435         *errcode =  DW_DLE_ALLOC_FAIL;
436         return DW_DLV_ERROR;
437     }
438 
439     orig_pph = pph;
440     orig_gphdr = gphdr;
441     res = RRMOA(ep->f_fd,pph,offset,count*entsize,
442         ep->f_filesize,errcode);
443     if(res != DW_DLV_OK) {
444         free(pph);
445         free(gphdr);
446         return res;
447     }
448     for( i = 0; i < count;
449         ++i,  pph++,gphdr++) {
450         ASNAR(ep->f_copy_word,gphdr->gp_type,pph->p_type);
451         ASNAR(ep->f_copy_word,gphdr->gp_offset,pph->p_offset);
452         ASNAR(ep->f_copy_word,gphdr->gp_vaddr,pph->p_vaddr);
453         ASNAR(ep->f_copy_word,gphdr->gp_paddr,pph->p_paddr);
454         ASNAR(ep->f_copy_word,gphdr->gp_filesz,pph->p_filesz);
455         ASNAR(ep->f_copy_word,gphdr->gp_memsz,pph->p_memsz);
456         ASNAR(ep->f_copy_word,gphdr->gp_flags,pph->p_flags);
457         ASNAR(ep->f_copy_word,gphdr->gp_align,pph->p_align);
458     }
459     free(orig_pph);
460     *phdr_out = orig_gphdr;
461     *count_out = count;
462     ep->f_phdr = orig_gphdr;
463     ep->f_loc_phdr.g_name = "Program Header";
464     ep->f_loc_phdr.g_offset = offset;
465     ep->f_loc_phdr.g_count = count;
466     ep->f_loc_phdr.g_entrysize = sizeof(dw_elf64_phdr);
467     ep->f_loc_phdr.g_totalsize = sizeof(dw_elf64_phdr)*count;
468     return DW_DLV_OK;
469 }
470 #endif /* not used */
471 
472 static int
473 generic_shdr_from_shdr32(dwarf_elf_object_access_internals_t *ep,
474     Dwarf_Unsigned * count_out,
475     Dwarf_Unsigned offset,
476     Dwarf_Unsigned entsize,
477     Dwarf_Unsigned count,
478     int *errcode)
479 {
480     dw_elf32_shdr          *psh =0;
481     dw_elf32_shdr          *orig_psh =0;
482     struct generic_shdr *gshdr =0;
483     struct generic_shdr *orig_gshdr =0;
484     Dwarf_Unsigned i = 0;
485     int res = 0;
486 
487     *count_out = 0;
488     psh = (dw_elf32_shdr *)calloc(count , entsize);
489     if(!psh) {
490         *errcode = DW_DLE_ALLOC_FAIL;
491         return DW_DLV_ERROR;
492     }
493     gshdr = (struct generic_shdr *)calloc(count,sizeof(*gshdr));
494     if(!gshdr) {
495         free(psh);
496         *errcode = DW_DLE_ALLOC_FAIL;
497         return DW_DLV_ERROR;
498     }
499 
500     orig_psh = psh;
501     orig_gshdr = gshdr;
502     res = RRMOA(ep->f_fd,psh,offset,count*entsize,
503         ep->f_filesize,errcode);
504     if(res != DW_DLV_OK) {
505         free(psh);
506         free(gshdr);
507         return res;
508     }
509     for(i = 0; i < count;
510         ++i,  psh++,gshdr++) {
511         gshdr->gh_secnum = i;
512         ASNAR(ep->f_copy_word,gshdr->gh_name,psh->sh_name);
513         ASNAR(ep->f_copy_word,gshdr->gh_type,psh->sh_type);
514         ASNAR(ep->f_copy_word,gshdr->gh_flags,psh->sh_flags);
515         ASNAR(ep->f_copy_word,gshdr->gh_addr,psh->sh_addr);
516         ASNAR(ep->f_copy_word,gshdr->gh_offset,psh->sh_offset);
517         ASNAR(ep->f_copy_word,gshdr->gh_size,psh->sh_size);
518         ASNAR(ep->f_copy_word,gshdr->gh_link,psh->sh_link);
519         ASNAR(ep->f_copy_word,gshdr->gh_info,psh->sh_info);
520         ASNAR(ep->f_copy_word,gshdr->gh_addralign,psh->sh_addralign);
521         ASNAR(ep->f_copy_word,gshdr->gh_entsize,psh->sh_entsize);
522         if (gshdr->gh_type == SHT_REL || gshdr->gh_type == SHT_RELA){
523             gshdr->gh_reloc_target_secnum = gshdr->gh_info;
524         }
525     }
526     free(orig_psh);
527     *count_out = count;
528     ep->f_shdr = orig_gshdr;
529     ep->f_loc_shdr.g_name = "Section Header";
530     ep->f_loc_shdr.g_count = count;
531     ep->f_loc_shdr.g_offset = offset;
532     ep->f_loc_shdr.g_entrysize = sizeof(dw_elf32_shdr);
533     ep->f_loc_shdr.g_totalsize = sizeof(dw_elf32_shdr)*count;
534     return DW_DLV_OK;
535 }
536 
537 static int
538 generic_shdr_from_shdr64(dwarf_elf_object_access_internals_t *ep,
539     Dwarf_Unsigned * count_out,
540     Dwarf_Unsigned offset,
541     Dwarf_Unsigned entsize,
542     Dwarf_Unsigned count,
543     int *errcode)
544 {
545     dw_elf64_shdr          *psh =0;
546     dw_elf64_shdr          *orig_psh =0;
547     struct generic_shdr *gshdr =0;
548     struct generic_shdr *orig_gshdr =0;
549     Dwarf_Unsigned i = 0;
550     int res = 0;
551 
552     *count_out = 0;
553     psh = (dw_elf64_shdr *)calloc(count , entsize);
554     if(!psh) {
555         *errcode = DW_DLE_ALLOC_FAIL;
556         return DW_DLV_ERROR;
557     }
558     gshdr = (struct generic_shdr *)calloc(count,sizeof(*gshdr));
559     if(gshdr == 0) {
560         free(psh);
561         *errcode = DW_DLE_ALLOC_FAIL;
562         return DW_DLV_ERROR;
563     }
564 
565     orig_psh = psh;
566     orig_gshdr = gshdr;
567     res = RRMOA(ep->f_fd,psh,offset,count*entsize,
568         ep->f_filesize,errcode);
569     if(res != DW_DLV_OK) {
570         free(psh);
571         free(gshdr);
572         return res;
573     }
574     for( i = 0; i < count;
575         ++i,  psh++,gshdr++) {
576         gshdr->gh_secnum = i;
577         ASNAR(ep->f_copy_word,gshdr->gh_name,psh->sh_name);
578         ASNAR(ep->f_copy_word,gshdr->gh_type,psh->sh_type);
579         ASNAR(ep->f_copy_word,gshdr->gh_flags,psh->sh_flags);
580         ASNAR(ep->f_copy_word,gshdr->gh_addr,psh->sh_addr);
581         ASNAR(ep->f_copy_word,gshdr->gh_offset,psh->sh_offset);
582         ASNAR(ep->f_copy_word,gshdr->gh_size,psh->sh_size);
583         ASNAR(ep->f_copy_word,gshdr->gh_link,psh->sh_link);
584         ASNAR(ep->f_copy_word,gshdr->gh_info,psh->sh_info);
585         ASNAR(ep->f_copy_word,gshdr->gh_addralign,psh->sh_addralign);
586         ASNAR(ep->f_copy_word,gshdr->gh_entsize,psh->sh_entsize);
587         if (gshdr->gh_type == SHT_REL ||
588             gshdr->gh_type == SHT_RELA){
589             gshdr->gh_reloc_target_secnum = gshdr->gh_info;
590         }
591     }
592     free(orig_psh);
593     *count_out = count;
594     ep->f_shdr = orig_gshdr;
595     ep->f_loc_shdr.g_name = "Section Header";
596     ep->f_loc_shdr.g_count = count;
597     ep->f_loc_shdr.g_offset = offset;
598     ep->f_loc_shdr.g_entrysize = sizeof(dw_elf64_shdr);
599     ep->f_loc_shdr.g_totalsize = sizeof(dw_elf64_shdr)*count;
600     return DW_DLV_OK;
601 }
602 
603 
604 
605 static int
606 dwarf_generic_elf_load_symbols32(
607     dwarf_elf_object_access_internals_t *ep,
608     struct generic_symentry **gsym_out,
609     Dwarf_Unsigned offset,Dwarf_Unsigned size,
610     Dwarf_Unsigned *count_out,int *errcode)
611 {
612     Dwarf_Unsigned ecount = 0;
613     Dwarf_Unsigned size2 = 0;
614     Dwarf_Unsigned i = 0;
615     dw_elf32_sym *psym = 0;
616     dw_elf32_sym *orig_psym = 0;
617     struct generic_symentry * gsym = 0;
618     struct generic_symentry * orig_gsym = 0;
619     int res = 0;
620 
621     ecount = (long)(size/sizeof(dw_elf32_sym));
622     size2 = ecount * sizeof(dw_elf32_sym);
623     if(size != size2) {
624         *errcode = DW_DLE_SECTION_SIZE_ERROR;
625         return DW_DLV_ERROR;
626     }
627     psym = calloc(ecount,sizeof(dw_elf32_sym));
628     if (!psym) {
629         *errcode = DW_DLE_ALLOC_FAIL;
630         return DW_DLV_ERROR;
631     }
632     gsym = calloc(ecount,sizeof(struct generic_symentry));
633     if (!gsym) {
634         free(psym);
635         *errcode = DW_DLE_ALLOC_FAIL;
636         return DW_DLV_ERROR;
637     }
638     res = RRMOA(ep->f_fd,psym,offset,size,
639         ep->f_filesize,errcode);
640     if(res!= DW_DLV_OK) {
641         free(psym);
642         free(gsym);
643         return res;
644     }
645     orig_psym = psym;
646     orig_gsym = gsym;
647     for ( i = 0; i < ecount; ++i,++psym,++gsym) {
648         Dwarf_Unsigned bind = 0;
649         Dwarf_Unsigned type = 0;
650 
651         ASNAR(ep->f_copy_word,gsym->gs_name,psym->st_name);
652         ASNAR(ep->f_copy_word,gsym->gs_value,psym->st_value);
653         ASNAR(ep->f_copy_word,gsym->gs_size,psym->st_size);
654         ASNAR(ep->f_copy_word,gsym->gs_info,psym->st_info);
655         ASNAR(ep->f_copy_word,gsym->gs_other,psym->st_other);
656         ASNAR(ep->f_copy_word,gsym->gs_shndx,psym->st_shndx);
657         bind = gsym->gs_info >> 4;
658         type = gsym->gs_info & 0xf;
659         gsym->gs_bind = bind;
660         gsym->gs_type = type;
661     }
662     *count_out = ecount;
663     *gsym_out = orig_gsym;
664     free(orig_psym);
665     return DW_DLV_OK;
666 }
667 
668 
669 static int
670 dwarf_generic_elf_load_symbols64(
671     dwarf_elf_object_access_internals_t *ep,
672     struct generic_symentry **gsym_out,
673     Dwarf_Unsigned offset,Dwarf_Unsigned size,
674     Dwarf_Unsigned *count_out,int *errcode)
675 {
676     Dwarf_Unsigned ecount = 0;
677     Dwarf_Unsigned size2 = 0;
678     Dwarf_Unsigned i = 0;
679     dw_elf64_sym *psym = 0;
680     dw_elf64_sym *orig_psym = 0;
681     struct generic_symentry * gsym = 0;
682     struct generic_symentry * orig_gsym = 0;
683     int res = 0;
684 
685     ecount = (long)(size/sizeof(dw_elf64_sym));
686     size2 = ecount * sizeof(dw_elf64_sym);
687     if(size != size2) {
688         *errcode = DW_DLE_SECTION_SIZE_ERROR;
689         return DW_DLV_ERROR;
690     }
691     psym = calloc(ecount,sizeof(dw_elf64_sym));
692     if (!psym) {
693         *errcode = DW_DLE_ALLOC_FAIL;
694         return DW_DLV_ERROR;
695     }
696     gsym = calloc(ecount,sizeof(struct generic_symentry));
697     if (!gsym) {
698         free(psym);
699         *errcode = DW_DLE_ALLOC_FAIL;
700         return DW_DLV_ERROR;
701     }
702     res = RRMOA(ep->f_fd,psym,offset,size,
703         ep->f_filesize,errcode);
704     if(res!= DW_DLV_OK) {
705         free(psym);
706         free(gsym);
707         *errcode = DW_DLE_ALLOC_FAIL;
708         return res;
709     }
710     orig_psym = psym;
711     orig_gsym = gsym;
712     for ( i = 0; i < ecount; ++i,++psym,++gsym) {
713         Dwarf_Unsigned bind = 0;
714         Dwarf_Unsigned type = 0;
715 
716         ASNAR(ep->f_copy_word,gsym->gs_name,psym->st_name);
717         ASNAR(ep->f_copy_word,gsym->gs_value,psym->st_value);
718         ASNAR(ep->f_copy_word,gsym->gs_size,psym->st_size);
719         ASNAR(ep->f_copy_word,gsym->gs_info,psym->st_info);
720         ASNAR(ep->f_copy_word,gsym->gs_other,psym->st_other);
721         ASNAR(ep->f_copy_word,gsym->gs_shndx,psym->st_shndx);
722         bind = gsym->gs_info >> 4;
723         type = gsym->gs_info & 0xf;
724         gsym->gs_bind = bind;
725         gsym->gs_type = type;
726     }
727     *count_out = ecount;
728     *gsym_out = orig_gsym;
729     free(orig_psym);
730     return DW_DLV_OK;
731 }
732 
733 static int
734 dwarf_generic_elf_load_symbols(
735     dwarf_elf_object_access_internals_t *ep,
736     int secnum,
737     struct generic_shdr *psh,
738     struct generic_symentry **gsym_out,
739     Dwarf_Unsigned *count_out,int *errcode)
740 {
741     int res = 0;
742     struct generic_symentry *gsym = 0;
743     Dwarf_Unsigned count = 0;
744 
745     if(!secnum) {
746         return DW_DLV_NO_ENTRY;
747     }
748     if (ep->f_offsetsize == 32) {
749         res = dwarf_generic_elf_load_symbols32(ep,
750             &gsym,
751             psh->gh_offset,psh->gh_size,
752             &count,errcode);
753     } else if (ep->f_offsetsize == 64) {
754         res = dwarf_generic_elf_load_symbols64(ep,
755             &gsym,
756             psh->gh_offset,psh->gh_size,
757             &count,errcode);
758     } else {
759         *errcode = DW_DLE_OFFSET_SIZE;
760         return DW_DLV_ERROR;
761     }
762     if (res == DW_DLV_OK) {
763         *gsym_out = gsym;
764         *count_out = count;
765     }
766     return res;
767 }
768 #if 0
769 int
770 dwarf_load_elf_dynsym_symbols(
771     dwarf_elf_object_access_internals_t *ep, int*errcode)
772 {
773     int res = 0;
774     struct generic_symentry *gsym = 0;
775     Dwarf_Unsigned count = 0;
776     Dwarf_Unsigned secnum = ep->f_dynsym_sect_index;
777     struct generic_shdr * psh = 0;
778 
779     if(!secnum) {
780         return DW_DLV_NO_ENTRY;
781     }
782     psh = ep->f_shdr + secnum;
783     res = dwarf_generic_elf_load_symbols(ep,
784         secnum,
785         psh,
786         &gsym,
787         &count,errcode);
788     if (res == DW_DLV_OK) {
789         ep->f_dynsym = gsym;
790         ep->f_loc_dynsym.g_count = count;
791     }
792     return res;
793 }
794 #endif /* 0 */
795 
796 int
797 _dwarf_load_elf_symtab_symbols(
798     dwarf_elf_object_access_internals_t *ep, int*errcode)
799 {
800     int res = 0;
801     struct generic_symentry *gsym = 0;
802     Dwarf_Unsigned count = 0;
803     Dwarf_Unsigned secnum = ep->f_symtab_sect_index;
804     struct generic_shdr * psh = 0;
805 
806     if(!secnum) {
807         return DW_DLV_NO_ENTRY;
808     }
809     psh = ep->f_shdr + secnum;
810     res = dwarf_generic_elf_load_symbols(ep,
811         secnum,
812         psh,
813         &gsym,
814         &count,errcode);
815     if (res == DW_DLV_OK) {
816         ep->f_symtab = gsym;
817         ep->f_loc_symtab.g_count = count;
818     }
819     return res;
820 }
821 
822 static int
823 generic_rel_from_rela32(
824     dwarf_elf_object_access_internals_t *ep,
825     struct generic_shdr * gsh,
826     dw_elf32_rela *relp,
827     struct generic_rela *grel,
828     int *errcode)
829 {
830     Dwarf_Unsigned ecount = 0;
831     Dwarf_Unsigned size = gsh->gh_size;
832     Dwarf_Unsigned size2 = 0;
833     Dwarf_Unsigned i = 0;
834 
835     ecount = size/sizeof(dw_elf32_rela);
836     size2 = ecount * sizeof(dw_elf32_rela);
837     if(size != size2) {
838         *errcode = DW_DLE_SECTION_SIZE_ERROR;
839         return  DW_DLV_ERROR;
840     }
841     for ( i = 0; i < ecount; ++i,++relp,++grel) {
842         ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset);
843         ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info);
844         /* addend signed */
845         ASNAR(ep->f_copy_word,grel->gr_addend,relp->r_addend);
846         SIGN_EXTEND(grel->gr_addend,sizeof(relp->r_addend));
847         grel->gr_sym  = grel->gr_info>>8; /* ELF32_R_SYM */
848         grel->gr_type = grel->gr_info & 0xff;
849         grel->gr_is_rela = TRUE;
850     }
851     return DW_DLV_OK;
852 }
853 
854 static int
855 generic_rel_from_rela64(
856     dwarf_elf_object_access_internals_t *ep,
857     struct generic_shdr * gsh,
858     dw_elf64_rela *relp,
859     struct generic_rela *grel, int *errcode)
860 {
861     Dwarf_Unsigned ecount = 0;
862     Dwarf_Unsigned size = gsh->gh_size;
863     Dwarf_Unsigned size2 = 0;
864     Dwarf_Unsigned i = 0;
865     int objlittleendian = (ep->f_endian == DW_OBJECT_LSB);
866     int ismips64 = (ep->f_machine == EM_MIPS);
867     int issparcv9 = (ep->f_machine == EM_SPARCV9);
868 
869     ecount = size/sizeof(dw_elf64_rela);
870     size2 = ecount * sizeof(dw_elf64_rela);
871     if(size != size2) {
872         *errcode = DW_DLE_SECTION_SIZE_ERROR;
873         return  DW_DLV_ERROR;
874     }
875     for ( i = 0; i < ecount; ++i,++relp,++grel) {
876         ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset);
877         ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info);
878         ASNAR(ep->f_copy_word,grel->gr_addend,relp->r_addend);
879         SIGN_EXTEND(grel->gr_addend,sizeof(relp->r_addend));
880         if (ismips64 && objlittleendian ) {
881             char realsym[4];
882 
883             memcpy(realsym,&relp->r_info,sizeof(realsym));
884             ASNAR(ep->f_copy_word,grel->gr_sym,realsym);
885             grel->gr_type  = relp->r_info[7];
886             grel->gr_type2 = relp->r_info[6];
887             grel->gr_type3 = relp->r_info[5];
888         } else if (issparcv9) {
889             /*  Always Big Endian?  */
890             char realsym[4];
891 
892             memcpy(realsym,&relp->r_info,sizeof(realsym));
893             ASNAR(ep->f_copy_word,grel->gr_sym,realsym);
894             grel->gr_type  = relp->r_info[7];
895         } else {
896             grel->gr_sym  = grel->gr_info >> 32;
897             grel->gr_type = grel->gr_info & 0xffffffff;
898         }
899         grel->gr_is_rela = TRUE;
900     }
901     return DW_DLV_OK;
902 }
903 
904 static int
905 generic_rel_from_rel32(
906     dwarf_elf_object_access_internals_t *ep,
907     struct generic_shdr * gsh,
908     dw_elf32_rel *relp,
909     struct generic_rela *grel,int *errcode)
910 {
911     Dwarf_Unsigned ecount = 0;
912     Dwarf_Unsigned size = gsh->gh_size;
913     Dwarf_Unsigned size2 = 0;
914     Dwarf_Unsigned i = 0;
915 
916     ecount = size/sizeof(dw_elf32_rel);
917     size2 = ecount * sizeof(dw_elf32_rel);
918     if(size != size2) {
919         *errcode = DW_DLE_SECTION_SIZE_ERROR;
920         return  DW_DLV_ERROR;
921     }
922     for ( i = 0; i < ecount; ++i,++relp,++grel) {
923         ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset);
924         ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info);
925         grel->gr_addend  = 0; /* Unused for plain .rel */
926         grel->gr_sym  = grel->gr_info >>8; /* ELF32_R_SYM */
927         grel->gr_is_rela = FALSE;
928         grel->gr_type = grel->gr_info & 0xff;
929     }
930     return DW_DLV_OK;
931 }
932 
933 static int
934 generic_rel_from_rel64(
935     dwarf_elf_object_access_internals_t *ep,
936     struct generic_shdr * gsh,
937     dw_elf64_rel *relp,
938     struct generic_rela *grel,int *errcode)
939 {
940     Dwarf_Unsigned ecount = 0;
941     Dwarf_Unsigned size = gsh->gh_size;
942     Dwarf_Unsigned size2 = 0;
943     Dwarf_Unsigned i = 0;
944     int objlittleendian = (ep->f_endian == DW_OBJECT_LSB);
945     int ismips64 = (ep->f_machine == EM_MIPS);
946     int issparcv9 = (ep->f_machine == EM_SPARCV9);
947 
948     ecount = size/sizeof(dw_elf64_rel);
949     size2 = ecount * sizeof(dw_elf64_rel);
950     if(size != size2) {
951         *errcode = DW_DLE_SECTION_SIZE_ERROR;
952         return DW_DLV_ERROR;
953     }
954     for ( i = 0; i < ecount; ++i,++relp,++grel) {
955         ASNAR(ep->f_copy_word,grel->gr_offset,relp->r_offset);
956         ASNAR(ep->f_copy_word,grel->gr_info,relp->r_info);
957         grel->gr_addend  = 0; /* Unused for plain .rel */
958         if (ismips64 && objlittleendian ) {
959             char realsym[4];
960 
961             memcpy(realsym,&relp->r_info,sizeof(realsym));
962             ASNAR(ep->f_copy_word,grel->gr_sym,realsym);
963             grel->gr_type  = relp->r_info[7];
964             grel->gr_type2 = relp->r_info[6];
965             grel->gr_type3 = relp->r_info[5];
966         } else if (issparcv9) {
967             /*  Always Big Endian?  */
968             char realsym[4];
969 
970             memcpy(realsym,&relp->r_info,sizeof(realsym));
971             ASNAR(ep->f_copy_word,grel->gr_sym,realsym);
972             grel->gr_type  = relp->r_info[7];
973         } else {
974             grel->gr_sym  = grel->gr_info >>32;
975             grel->gr_type = grel->gr_info & 0xffffffff;
976         }
977         grel->gr_is_rela = FALSE;
978     }
979     return DW_DLV_OK;
980 }
981 
982 #if 0
983 int
984 dwarf_load_elf_dynstr(
985     dwarf_elf_object_access_internals_t *ep, int *errcode)
986 {
987     struct generic_shdr *strpsh = 0;
988     int res = 0;
989     Dwarf_Unsigned strsectindex  =0;
990     Dwarf_Unsigned strsectlength = 0;
991 
992         if (!ep->f_dynsym_sect_strings_sect_index) {
993             return DW_DLV_NO_ENTRY;
994         }
995         strsectindex = ep->f_dynsym_sect_strings_sect_index;
996         strsectlength = ep->f_dynsym_sect_strings_max;
997         strpsh = ep->f_shdr + strsectindex;
998         /*  Alloc an extra byte as a guaranteed NUL byte
999             at the end of the strings in case the section
1000             is corrupted and lacks a NUL at end. */
1001         ep->f_dynsym_sect_strings = calloc(1,strsectlength+1);
1002         if(!ep->f_dynsym_sect_strings) {
1003             ep->f_dynsym_sect_strings = 0;
1004             ep->f_dynsym_sect_strings_max = 0;
1005             ep->f_dynsym_sect_strings_sect_index = 0;
1006             *errcode = DW_DLE_ALLOC_FAIL;
1007             return DW_DLV_ERROR;
1008         }
1009         res = RRMOA(ep->f_fd,ep->f_dynsym_sect_strings,
1010             strpsh->gh_offset,
1011             strsectlength,
1012             ep->f_filesize,errcode);
1013         if(res != DW_DLV_OK) {
1014             ep->f_dynsym_sect_strings = 0;
1015             ep->f_dynsym_sect_strings_max = 0;
1016             ep->f_dynsym_sect_strings_sect_index = 0;
1017             return res;
1018         }
1019     return DW_DLV_OK;
1020 }
1021 #endif /* 0 */
1022 
1023 int
1024 _dwarf_load_elf_symstr(
1025     dwarf_elf_object_access_internals_t *ep, int *errcode)
1026 {
1027     struct generic_shdr *strpsh = 0;
1028     int res = 0;
1029     Dwarf_Unsigned strsectindex  =0;
1030     Dwarf_Unsigned strsectlength = 0;
1031 
1032     if (!ep->f_symtab_sect_strings_sect_index) {
1033         return DW_DLV_NO_ENTRY;
1034     }
1035     strsectindex = ep->f_symtab_sect_strings_sect_index;
1036     strsectlength = ep->f_symtab_sect_strings_max;
1037     strpsh = ep->f_shdr + strsectindex;
1038     /*  Alloc an extra byte as a guaranteed NUL byte
1039         at the end of the strings in case the section
1040         is corrupted and lacks a NUL at end. */
1041     ep->f_symtab_sect_strings = calloc(1,strsectlength+1);
1042     if(!ep->f_symtab_sect_strings) {
1043         ep->f_symtab_sect_strings = 0;
1044         ep->f_symtab_sect_strings_max = 0;
1045         ep->f_symtab_sect_strings_sect_index = 0;
1046         *errcode = DW_DLE_ALLOC_FAIL;
1047         return DW_DLV_ERROR;
1048     }
1049     res = RRMOA(ep->f_fd,ep->f_symtab_sect_strings,
1050         strpsh->gh_offset,
1051         strsectlength,
1052         ep->f_filesize,errcode);
1053     if(res != DW_DLV_OK) {
1054         free(ep->f_symtab_sect_strings);
1055         ep->f_symtab_sect_strings = 0;
1056         ep->f_symtab_sect_strings_max = 0;
1057         ep->f_symtab_sect_strings_sect_index = 0;
1058         return res;
1059     }
1060     return DW_DLV_OK;
1061 }
1062 
1063 
1064 static int
1065 _dwarf_elf_load_sectstrings(
1066     dwarf_elf_object_access_internals_t *ep,
1067     Dwarf_Unsigned stringsection,
1068     int *errcode)
1069 {
1070     int res = 0;
1071     struct generic_shdr *psh = 0;
1072     Dwarf_Unsigned secoffset = 0;
1073 
1074     ep->f_elf_shstrings_length = 0;
1075     if (stringsection >= ep->f_ehdr->ge_shnum) {
1076         *errcode = DW_DLE_SECTION_INDEX_BAD;
1077         return DW_DLV_ERROR;
1078     }
1079     psh = ep->f_shdr + stringsection;
1080     secoffset = psh->gh_offset;
1081     if(is_empty_section(psh->gh_type)) {
1082         *errcode = DW_DLE_ELF_STRING_SECTION_MISSING;
1083         return DW_DLV_ERROR;
1084     }
1085     if(psh->gh_size > ep->f_elf_shstrings_max) {
1086         free(ep->f_elf_shstrings_data);
1087         ep->f_elf_shstrings_data = (char *)malloc(psh->gh_size);
1088         ep->f_elf_shstrings_max = psh->gh_size;
1089         if(!ep->f_elf_shstrings_data) {
1090             ep->f_elf_shstrings_max = 0;
1091             *errcode = DW_DLE_ALLOC_FAIL;
1092             return DW_DLV_ERROR;
1093         }
1094     }
1095     ep->f_elf_shstrings_length = psh->gh_size;
1096     res = RRMOA(ep->f_fd,ep->f_elf_shstrings_data,secoffset,
1097         psh->gh_size,
1098         ep->f_filesize,errcode);
1099     return res;
1100 }
1101 
1102 static int
1103 elf_load_sectheaders32(
1104     dwarf_elf_object_access_internals_t *ep,
1105     Dwarf_Unsigned offset,Dwarf_Unsigned entsize,
1106     Dwarf_Unsigned count,int *errcode)
1107 {
1108     Dwarf_Unsigned generic_count = 0;
1109     int res = 0;
1110 
1111 
1112     if(count == 0) {
1113         return DW_DLV_NO_ENTRY;
1114     }
1115     if(entsize < sizeof(dw_elf32_shdr)) {
1116         *errcode = DW_DLE_SECTION_SIZE_ERROR;
1117         return DW_DLV_ERROR;
1118     }
1119     if ((offset > ep->f_filesize)||
1120         (entsize > 200)||
1121         (count > ep->f_filesize) ||
1122         ((count *entsize +offset) > ep->f_filesize)) {
1123             *errcode = DW_DLE_FILE_OFFSET_BAD;
1124             return DW_DLV_ERROR;
1125     }
1126     res = generic_shdr_from_shdr32(ep,&generic_count,
1127         offset,entsize,count,errcode);
1128     if (res != DW_DLV_OK) {
1129         return res;
1130     }
1131     if (generic_count != count) {
1132         *errcode = DW_DLE_ELF_SECTION_COUNT_MISMATCH;
1133         return DW_DLV_ERROR;
1134     }
1135     return DW_DLV_OK;
1136 }
1137 
1138 static int
1139 elf_load_sectheaders64(
1140     dwarf_elf_object_access_internals_t *ep,
1141     Dwarf_Unsigned offset,Dwarf_Unsigned entsize,
1142     Dwarf_Unsigned count,int*errcode)
1143 {
1144     Dwarf_Unsigned generic_count = 0;
1145     int res = 0;
1146 
1147 
1148     if(count == 0) {
1149         return DW_DLV_NO_ENTRY;
1150     }
1151     if(entsize < sizeof(dw_elf64_shdr)) {
1152         *errcode = DW_DLE_SECTION_SIZE_ERROR;
1153         return DW_DLV_ERROR;
1154     }
1155     if ((offset > ep->f_filesize)||
1156         (entsize > 200)||
1157         (count > ep->f_filesize) ||
1158         ((count *entsize +offset) > ep->f_filesize)) {
1159             *errcode = DW_DLE_FILE_OFFSET_BAD;
1160             return DW_DLV_ERROR;
1161     }
1162     res = generic_shdr_from_shdr64(ep,&generic_count,
1163         offset,entsize,count,errcode);
1164     if (res != DW_DLV_OK) {
1165         return res;
1166     }
1167     if (generic_count != count) {
1168         *errcode = DW_DLE_ELF_SECTION_COUNT_MISMATCH;
1169         return DW_DLV_ERROR;
1170     }
1171     return DW_DLV_OK;
1172 }
1173 
1174 
1175 static int
1176 _dwarf_elf_load_a_relx_batch(
1177     dwarf_elf_object_access_internals_t *ep,
1178     struct generic_shdr * gsh,
1179     struct generic_rela ** grel_out,
1180     Dwarf_Unsigned *count_out,
1181     enum RelocRela localrela,
1182     enum RelocOffsetSize localoffsize,
1183     int *errcode)
1184 {
1185     Dwarf_Unsigned count = 0;
1186     Dwarf_Unsigned size = 0;
1187     Dwarf_Unsigned size2 = 0;
1188     Dwarf_Unsigned sizeg = 0;
1189     Dwarf_Unsigned offset = 0;
1190     int res = 0;
1191     Dwarf_Unsigned object_reclen = 0;
1192     struct generic_rela *grel = 0;
1193 
1194     /*  ASSERT: Caller guarantees localoffsetsize
1195         is a valid 4 or 8. */
1196     /*  ASSERT: Caller guarantees localrela is one
1197         of the 2 valid values 1 or 2 */
1198 
1199     offset = gsh->gh_offset;
1200     size = gsh->gh_size;
1201     if(size == 0) {
1202         return DW_DLV_NO_ENTRY;
1203     }
1204     if ((offset > ep->f_filesize)||
1205         (size > ep->f_filesize) ||
1206         ((size +offset) > ep->f_filesize)) {
1207             *errcode = DW_DLE_FILE_OFFSET_BAD;
1208             return DW_DLV_ERROR;
1209     }
1210     if (localoffsize == RelocOffset32) {
1211         if (localrela ==  RelocIsRela) {
1212             object_reclen = sizeof(dw_elf32_rela);
1213             count = (long)(size/object_reclen);
1214             size2 = count * object_reclen;
1215             if(size != size2) {
1216                 *errcode = DW_DLE_SECTION_SIZE_ERROR;
1217                 return DW_DLV_ERROR;
1218             }
1219         } else {
1220             object_reclen = sizeof(dw_elf32_rel);
1221             count = (long)(size/object_reclen);
1222             size2 = count * object_reclen;
1223             if(size != size2) {
1224                 *errcode = DW_DLE_SECTION_SIZE_ERROR;
1225                 return DW_DLV_ERROR;
1226             }
1227         }
1228     } else {
1229         if (localrela ==  RelocIsRela) {
1230             object_reclen = sizeof(dw_elf64_rela);
1231             count = (long)(size/object_reclen);
1232             size2 = count * object_reclen;
1233             if(size != size2) {
1234                 *errcode = DW_DLE_SECTION_SIZE_ERROR;
1235                 return DW_DLV_ERROR;
1236             }
1237         } else {
1238             object_reclen = sizeof(dw_elf64_rel);
1239             count = (long)(size/object_reclen);
1240             size2 = count * object_reclen;
1241             if(size != size2) {
1242                 *errcode = DW_DLE_SECTION_SIZE_ERROR;
1243                 return DW_DLV_ERROR;
1244             }
1245         }
1246     }
1247     sizeg = count*sizeof(struct generic_rela);
1248     grel = (struct generic_rela *)malloc(sizeg);
1249     if (!grel) {
1250         *errcode = DW_DLE_ALLOC_FAIL;
1251         return DW_DLV_ERROR;
1252     }
1253     if (localoffsize == RelocOffset32) {
1254         if (localrela ==  RelocIsRela) {
1255             dw_elf32_rela *relp = 0;
1256             relp = (dw_elf32_rela *)malloc(size);
1257             if(!relp) {
1258                 free(grel);
1259                 *errcode = DW_DLE_ALLOC_FAIL;
1260                 return DW_DLV_ERROR;
1261             }
1262             res = RRMOA(ep->f_fd,relp,offset,size,
1263                 ep->f_filesize,errcode);
1264             if(res != DW_DLV_OK) {
1265                 free(relp);
1266                 free(grel);
1267                 return res;
1268             }
1269             res = generic_rel_from_rela32(ep,gsh,relp,grel,errcode);
1270             free(relp);
1271         } else {
1272             dw_elf32_rel *relp = 0;
1273             relp = (dw_elf32_rel *)malloc(size);
1274             if(!relp) {
1275                 free(grel);
1276                 *errcode = DW_DLE_ALLOC_FAIL;
1277                 return DW_DLV_ERROR;
1278             }
1279             res = RRMOA(ep->f_fd,relp,offset,size,
1280                 ep->f_filesize,errcode);
1281             if(res != DW_DLV_OK) {
1282                 free(relp);
1283                 free(grel);
1284                 return res;
1285             }
1286             res = generic_rel_from_rel32(ep,gsh,relp,grel,errcode);
1287             free(relp);
1288         }
1289     } else {
1290         if (localrela ==  RelocIsRela) {
1291             dw_elf64_rela *relp = 0;
1292             relp = (dw_elf64_rela *)malloc(size);
1293             if(!relp) {
1294                 free(grel);
1295                 *errcode = DW_DLE_ALLOC_FAIL;
1296                 return DW_DLV_ERROR;
1297             }
1298             res = RRMOA(ep->f_fd,relp,offset,size,
1299                 ep->f_filesize,errcode);
1300             if(res != DW_DLV_OK) {
1301                 free(relp);
1302                 free(grel);
1303                 return res;
1304             }
1305             res = generic_rel_from_rela64(ep,gsh,relp,grel,errcode);
1306             free(relp);
1307         } else {
1308             dw_elf64_rel *relp = 0;
1309             relp = (dw_elf64_rel *)malloc(size);
1310             if(!relp) {
1311                 free(grel);
1312                 *errcode = DW_DLE_ALLOC_FAIL;
1313                 return DW_DLV_ERROR;
1314             }
1315             res = RRMOA(ep->f_fd,relp,offset,size,
1316                 ep->f_filesize,errcode);
1317             if(res != DW_DLV_OK) {
1318                 free(relp);
1319                 free(grel);
1320                 return res;
1321             }
1322             res = generic_rel_from_rel64(ep,gsh,relp,grel,errcode);
1323             free(relp);
1324         }
1325     }
1326     if (res == DW_DLV_OK) {
1327         gsh->gh_relcount = count;
1328         gsh->gh_rels = grel;
1329         *count_out = count;
1330         *grel_out = grel;
1331         return res;
1332     }
1333     /* Some sort of issue */
1334     count_out = 0;
1335     free(grel);
1336     return res;
1337 }
1338 
1339 
1340 /*  Is this rel/rela section related to dwarf at all?
1341     set oksecnum zero if not. Else set targ secnum.
1342     Never returns DW_DLV_NO_ENTRY. */
1343 static int
1344 this_rel_is_a_section_dwarf_related(
1345     dwarf_elf_object_access_internals_t *ep,
1346     struct generic_shdr *gshdr,
1347     unsigned *oksecnum_out,
1348     int *errcode)
1349 {
1350     unsigned oksecnum = 0;
1351     struct generic_shdr *gstarg = 0;
1352 
1353     if (gshdr->gh_type != SHT_RELA &&
1354         gshdr->gh_type != SHT_REL)  {
1355         *oksecnum_out = 0;
1356         return DW_DLV_OK;
1357     }
1358     oksecnum = gshdr->gh_reloc_target_secnum;
1359     if (oksecnum >= ep->f_loc_shdr.g_count) {
1360         *oksecnum_out = 0;
1361         *errcode = DW_DLE_ELF_SECTION_ERROR;
1362         return DW_DLV_ERROR;
1363     }
1364     gstarg = ep->f_shdr+oksecnum;
1365     if (!gstarg->gh_is_dwarf) {
1366         *oksecnum_out = 0; /* no reloc needed. */
1367         return DW_DLV_OK;
1368     }
1369     *oksecnum_out = oksecnum;
1370     return DW_DLV_OK;
1371 }
1372 /* Secnum here is the secnum of rela. Not
1373    the target of the relocations.
1374    This also loads .rel. */
1375 int
1376 _dwarf_load_elf_relx(
1377     dwarf_elf_object_access_internals_t *ep,
1378     Dwarf_Unsigned secnum,
1379     enum RelocRela localr,
1380     int *errcode)
1381 {
1382     struct generic_shdr *gshdr = 0;
1383     Dwarf_Unsigned seccount = 0;
1384     unsigned offsetsize = 0;
1385     struct generic_rela *grp = 0;
1386     Dwarf_Unsigned count_read = 0;
1387     int res = 0;
1388     unsigned oksec = 0;
1389     enum RelocOffsetSize localoffsize = RelocOffset32;
1390 
1391     /*  ASSERT: Caller guarantees localr is
1392         a valid RelocRela  */
1393     if (!ep) {
1394         *errcode = DW_DLE_INTERNAL_NULL_POINTER;
1395         return DW_DLV_ERROR;
1396     }
1397     offsetsize = ep->f_offsetsize;
1398     seccount = ep->f_loc_shdr.g_count;
1399     if (secnum >= seccount) {
1400         *errcode = DW_DLE_ELF_SECTION_ERROR;
1401         return DW_DLV_ERROR;
1402     }
1403     gshdr = ep->f_shdr +secnum;
1404     if (is_empty_section(gshdr->gh_type)) {
1405 
1406         return DW_DLV_NO_ENTRY;
1407     }
1408 
1409     res = this_rel_is_a_section_dwarf_related(ep,gshdr,
1410         &oksec,errcode);
1411     if (res == DW_DLV_ERROR) {
1412         return res;
1413     }
1414     if (!oksec) {
1415         return DW_DLV_OK;
1416     }
1417     /*  We will actually read these relocations. */
1418     if (offsetsize == 64) {
1419         localoffsize = RelocOffset64;
1420     } else if (offsetsize == 32) {
1421         localoffsize = RelocOffset32;
1422     } else {
1423         *errcode = DW_DLE_OFFSET_SIZE;
1424         return DW_DLV_ERROR;
1425     }
1426     /*  ASSERT: localoffsize is now a valid enum value,
1427         one of the two defined. */
1428     res = _dwarf_elf_load_a_relx_batch(ep,
1429         gshdr,&grp,&count_read,localr,localoffsize,errcode);
1430     if (res == DW_DLV_ERROR) {
1431         return res;
1432     }
1433     if (res == DW_DLV_NO_ENTRY) {
1434         return res;
1435     }
1436     gshdr->gh_rels = grp;
1437     gshdr->gh_relcount = count_read;
1438     return DW_DLV_OK;
1439 }
1440 static int
1441 validate_section_name_string(Dwarf_Unsigned section_length,
1442   Dwarf_Unsigned string_loc_index,
1443   const char * strings_start,
1444   int  * errcode)
1445 {
1446     const char *endpoint = strings_start + section_length;
1447     const char *cur = 0;
1448 
1449     if (section_length <= string_loc_index) {
1450         *errcode = DW_DLE_SECTION_STRING_OFFSET_BAD;
1451         return DW_DLV_ERROR;
1452     }
1453     cur = string_loc_index+strings_start;
1454     for(  ; cur < endpoint;++cur) {
1455         if (!*cur) {
1456             return DW_DLV_OK;
1457         }
1458     }
1459     *errcode = DW_DLE_SECTION_STRING_OFFSET_BAD;
1460     return DW_DLV_ERROR;
1461 }
1462 
1463 static int
1464 _dwarf_elf_load_sect_namestring(
1465     dwarf_elf_object_access_internals_t *ep,
1466     int *errcode)
1467 {
1468     struct generic_shdr *gshdr = 0;
1469     Dwarf_Unsigned generic_count = 0;
1470     Dwarf_Unsigned i = 1;
1471     const char *stringsecbase = 0;
1472 
1473     stringsecbase = ep->f_elf_shstrings_data;
1474     gshdr = ep->f_shdr;
1475     generic_count = ep->f_loc_shdr.g_count;
1476     for(i = 0; i < generic_count; i++, ++gshdr) {
1477         const char *namestr =
1478             "<Invalid sh_name value. Corrupt Elf.>";
1479         int res = 0;
1480 
1481         res = validate_section_name_string(ep->f_elf_shstrings_length,
1482             gshdr->gh_name, stringsecbase,
1483             errcode);
1484         if (res != DW_DLV_OK) {
1485             gshdr->gh_namestring = namestr;
1486             return res;
1487         }
1488         gshdr->gh_namestring = stringsecbase + gshdr->gh_name;
1489     }
1490     return DW_DLV_OK;
1491 }
1492 
1493 
1494 static int
1495 elf_load_elf_header32(
1496     dwarf_elf_object_access_internals_t *ep,int *errcode)
1497 {
1498     int res = 0;
1499     dw_elf32_ehdr ehdr32;
1500     struct generic_ehdr *ehdr = 0;
1501 
1502     res = RRMOA(ep->f_fd,&ehdr32,0,sizeof(ehdr32),
1503         ep->f_filesize,errcode);
1504     if(res != DW_DLV_OK) {
1505         return res;
1506     }
1507     ehdr = (struct generic_ehdr *)calloc(1,
1508         sizeof(struct generic_ehdr));
1509     if (!ehdr) {
1510         *errcode = DW_DLE_ALLOC_FAIL;
1511         return DW_DLV_ERROR;
1512     }
1513     res  = generic_ehdr_from_32(ep,ehdr,&ehdr32,errcode);
1514     return res;
1515 }
1516 static int
1517 elf_load_elf_header64(
1518     dwarf_elf_object_access_internals_t *ep,int *errcode)
1519 {
1520     int res = 0;
1521     dw_elf64_ehdr ehdr64;
1522     struct generic_ehdr *ehdr = 0;
1523 
1524     res = RRMOA(ep->f_fd,&ehdr64,0,sizeof(ehdr64),
1525         ep->f_filesize,errcode);
1526     if(res != DW_DLV_OK) {
1527         return res;
1528     }
1529     ehdr = (struct generic_ehdr *)calloc(1,
1530         sizeof(struct generic_ehdr));
1531     if (!ehdr) {
1532         *errcode = DW_DLE_ALLOC_FAIL;
1533         return DW_DLV_ERROR;
1534     }
1535     res  = generic_ehdr_from_64(ep,ehdr,&ehdr64,errcode);
1536     return res;
1537 }
1538 
1539 static int
1540 validate_struct_sizes(
1541 #ifdef HAVE_ELF_H
1542     int*errcode
1543 #else
1544     UNUSEDARG int*errcode
1545 #endif
1546     )
1547 {
1548 #ifdef HAVE_ELF_H
1549     /*  This is a sanity check when we have an elf.h
1550         to check against. */
1551     if (sizeof(Elf32_Ehdr) != sizeof(dw_elf32_ehdr)) {
1552         *errcode = DW_DLE_BAD_TYPE_SIZE;
1553         return DW_DLV_ERROR;
1554     }
1555     if (sizeof(Elf64_Ehdr) != sizeof(dw_elf64_ehdr)) {
1556         *errcode = DW_DLE_BAD_TYPE_SIZE;
1557         return DW_DLV_ERROR;
1558     }
1559     if (sizeof(Elf32_Shdr) != sizeof(dw_elf32_shdr)) {
1560         *errcode = DW_DLE_BAD_TYPE_SIZE;
1561         return DW_DLV_ERROR;
1562     }
1563     if (sizeof(Elf64_Shdr) != sizeof(dw_elf64_shdr)) {
1564         *errcode = DW_DLE_BAD_TYPE_SIZE;
1565         return DW_DLV_ERROR;
1566     }
1567     if (sizeof(Elf32_Phdr) != sizeof(dw_elf32_phdr)) {
1568         *errcode = DW_DLE_BAD_TYPE_SIZE;
1569         return DW_DLV_ERROR;
1570     }
1571     if (sizeof(Elf64_Phdr) != sizeof(dw_elf64_phdr)) {
1572         *errcode = DW_DLE_BAD_TYPE_SIZE;
1573         return DW_DLV_ERROR;
1574     }
1575     if (sizeof(Elf32_Rel) != sizeof(dw_elf32_rel)) {
1576         *errcode = DW_DLE_BAD_TYPE_SIZE;
1577         return DW_DLV_ERROR;
1578     }
1579     if (sizeof(Elf64_Rel) != sizeof(dw_elf64_rel)) {
1580         *errcode = DW_DLE_BAD_TYPE_SIZE;
1581         return DW_DLV_ERROR;
1582     }
1583     if (sizeof(Elf32_Rela) != sizeof(dw_elf32_rela)) {
1584         *errcode = DW_DLE_BAD_TYPE_SIZE;
1585         return DW_DLV_ERROR;
1586     }
1587     if (sizeof(Elf64_Rela) != sizeof(dw_elf64_rela)) {
1588         *errcode = DW_DLE_BAD_TYPE_SIZE;
1589         return DW_DLV_ERROR;
1590     }
1591     if (sizeof(Elf32_Sym) != sizeof(dw_elf32_sym)) {
1592         *errcode = DW_DLE_BAD_TYPE_SIZE;
1593         return DW_DLV_ERROR;
1594     }
1595     if (sizeof(Elf64_Sym) != sizeof(dw_elf64_sym)) {
1596         *errcode = DW_DLE_BAD_TYPE_SIZE;
1597         return DW_DLV_ERROR;
1598     }
1599 #endif /* HAVE_ELF_H */
1600     return DW_DLV_OK;
1601 }
1602 
1603 int
1604 _dwarf_load_elf_header(
1605     dwarf_elf_object_access_internals_t *ep,int*errcode)
1606 {
1607     unsigned offsetsize = ep->f_offsetsize;
1608     int res = 0;
1609 
1610     res = validate_struct_sizes(errcode);
1611     if (res != DW_DLV_OK) {
1612         return res;
1613     }
1614 
1615     if (offsetsize == 32) {
1616         res = elf_load_elf_header32(ep,errcode);
1617     } else if (offsetsize == 64) {
1618         if (sizeof(Dwarf_Unsigned) < 8) {
1619             *errcode =  DW_DLE_INTEGER_TOO_SMALL;
1620             return DW_DLV_ERROR;
1621         }
1622         res = elf_load_elf_header64(ep,errcode);
1623     } else {
1624         *errcode = DW_DLE_OFFSET_SIZE;
1625         return DW_DLV_ERROR;
1626     }
1627     return res;
1628 }
1629 
1630 static int
1631 validate_links(
1632     dwarf_elf_object_access_internals_t *ep,
1633     Dwarf_Unsigned knownsect,
1634     Dwarf_Unsigned string_sect,
1635     int *errcode)
1636 {
1637     struct generic_shdr* pshk = 0;
1638 
1639     if (!knownsect) {
1640         return DW_DLV_OK;
1641     }
1642     if (!string_sect) {
1643         *errcode = DW_DLE_ELF_STRING_SECTION_ERROR;
1644         return DW_DLV_ERROR;
1645     }
1646     pshk = ep->f_shdr + knownsect;
1647     if (string_sect != pshk->gh_link) {
1648         *errcode = DW_DLE_ELF_SECTION_LINK_ERROR;
1649         return DW_DLV_ERROR;
1650     }
1651     return DW_DLV_OK;
1652 }
1653 
1654 
1655 static int
1656 string_endswith(const char *n,const char *q)
1657 {
1658     unsigned long len = strlen(n);
1659     unsigned long qlen = strlen(q);
1660     const char *startpt = 0;
1661 
1662     if ( len < qlen) {
1663         return FALSE;
1664     }
1665     startpt = n + (len-qlen);
1666     if (strcmp(startpt,q)) {
1667         return FALSE;
1668     }
1669     return TRUE;
1670 }
1671 
1672 /*  We are allowing either SHT_GROUP or .group to indicate
1673     a group section, but really one should have both
1674     or neither! */
1675 static int
1676 elf_sht_groupsec(Dwarf_Unsigned type, const char *sname)
1677 {
1678     /*  ARM compilers name SHT group "__ARM_grp<long name here>"
1679         not .group */
1680     if ((type == SHT_GROUP) || (!strcmp(sname,".group"))){
1681         return TRUE;
1682     }
1683     return FALSE;
1684 }
1685 
1686 static int
1687 elf_flagmatches(Dwarf_Unsigned flagsword,Dwarf_Unsigned flag)
1688 {
1689     if ((flagsword&flag) == flag) {
1690         return TRUE;
1691     }
1692     return FALSE;
1693 }
1694 
1695 /*  For SHT_GROUP sections. */
1696 static int
1697 read_gs_section_group(
1698     dwarf_elf_object_access_internals_t *ep,
1699     struct generic_shdr* psh,
1700     int *errcode)
1701 {
1702     Dwarf_Unsigned i = 0;
1703     int res = 0;
1704 
1705     if (!psh->gh_sht_group_array) {
1706         Dwarf_Unsigned seclen = psh->gh_size;
1707         char *data = 0;
1708         char *dp = 0;
1709         Dwarf_Unsigned* grouparray = 0;
1710         char dblock[4];
1711         Dwarf_Unsigned va = 0;
1712         Dwarf_Unsigned count = 0;
1713         int foundone = 0;
1714 
1715         if (seclen < DWARF_32BIT_SIZE) {
1716             *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1717             return DW_DLV_ERROR;
1718         }
1719         data = malloc(seclen);
1720         if (!data) {
1721             *errcode = DW_DLE_ALLOC_FAIL;
1722             return DW_DLV_ERROR;
1723         }
1724         dp = data;
1725         if (psh->gh_entsize != DWARF_32BIT_SIZE) {
1726             *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1727             free(data);
1728             return DW_DLV_ERROR;
1729         }
1730         count = seclen/psh->gh_entsize;
1731         if (count > ep->f_loc_shdr.g_count) {
1732             /* Impossible */
1733             free(data);
1734             *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1735             return DW_DLV_ERROR;
1736         }
1737         res = RRMOA(ep->f_fd,data,psh->gh_offset,seclen,
1738             ep->f_filesize,errcode);
1739         if(res != DW_DLV_OK) {
1740             free(data);
1741             return res;
1742         }
1743         grouparray = malloc(count * sizeof(Dwarf_Unsigned));
1744         if (!grouparray) {
1745             free(data);
1746             *errcode = DW_DLE_ALLOC_FAIL;
1747             return DW_DLV_ERROR;
1748         }
1749 
1750         memcpy(dblock,dp,DWARF_32BIT_SIZE);
1751         ASNAR(memcpy,va,dblock);
1752         /* There is ambiguity on the endianness of this stuff. */
1753         if (va != 1 && va != 0x1000000) {
1754             /*  Could be corrupted elf object. */
1755             *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1756             free(data);
1757             free(grouparray);
1758             return DW_DLV_ERROR;
1759         }
1760         grouparray[0] = 1;
1761         dp = dp + DWARF_32BIT_SIZE;
1762         for( i = 1; i < count; ++i,dp += DWARF_32BIT_SIZE) {
1763             Dwarf_Unsigned gseca = 0;
1764             Dwarf_Unsigned gsecb = 0;
1765             struct generic_shdr* targpsh = 0;
1766 
1767             memcpy(dblock,dp,DWARF_32BIT_SIZE);
1768             ASNAR(memcpy,gseca,dblock);
1769             ASNAR(_dwarf_memcpy_swap_bytes,gsecb,dblock);
1770             if (!gseca) {
1771                 free(data);
1772                 free(grouparray);
1773                 *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1774                 return DW_DLV_ERROR;
1775             }
1776             grouparray[i] = gseca;
1777             if (gseca > ep->f_loc_shdr.g_count) {
1778                 /*  Might be confused endianness by
1779                     the compiler generating the SHT_GROUP.
1780                     This is pretty horrible. */
1781 
1782                 if (gsecb > ep->f_loc_shdr.g_count) {
1783                     *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1784                     free(data);
1785                     free(grouparray);
1786                     return DW_DLV_ERROR;
1787                 }
1788                 /* Ok. Yes, ugly. */
1789                 gseca = gsecb;
1790                 grouparray[i] = gseca;
1791             }
1792             targpsh = ep->f_shdr + gseca;
1793             if (targpsh->gh_section_group_number) {
1794                 /* multi-assignment to groups. Oops. */
1795                 free(data);
1796                 free(grouparray);
1797                 *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1798                 return DW_DLV_ERROR;
1799             }
1800             targpsh->gh_section_group_number =
1801                 ep->f_sg_next_group_number;
1802             foundone = 1;
1803         }
1804         if (foundone) {
1805             ++ep->f_sg_next_group_number;
1806             ++ep->f_sht_group_type_section_count;
1807         }
1808         free(data);
1809         psh->gh_sht_group_array = grouparray;
1810         psh->gh_sht_group_array_count = count;
1811     }
1812     return DW_DLV_OK;
1813 }
1814 /*  Does related things.
1815     A)  Counts the number of SHT_GROUP
1816         and for each builds an array of the sections in the group
1817         (which we expect are all DWARF-related)
1818         and sets the group number in each mentioned section.
1819     B)  Counts the number of SHF_GROUP flags.
1820     C)  If gnu groups:
1821         ensure all the DWARF sections marked with right group
1822         based on A(we will mark unmarked as group 1,
1823         DW_GROUPNUMBER_BASE).
1824     D)  If arm groups (SHT_GROUP zero, SHF_GROUP non-zero):
1825         Check the relocations of all SHF_GROUP section
1826         FIXME: algorithm needed.
1827 
1828 
1829     If SHT_GROUP and SHF_GROUP this is GNU groups.
1830     If no SHT_GROUP and have SHF_GROUP this is
1831     arm cc groups and we must use relocation information
1832     to identify the group members.
1833 
1834     It seems(?) impossible for an object to have both
1835     dwo sections and (SHF_GROUP or SHT_GROUP), but
1836     we do not rule that out here.  */
1837 static int
1838 _dwarf_elf_setup_all_section_groups(
1839     dwarf_elf_object_access_internals_t *ep,
1840     int *errcode)
1841 {
1842     struct generic_shdr* psh = 0;
1843     Dwarf_Unsigned i = 0;
1844     Dwarf_Unsigned count = 0;
1845     int res = 0;
1846 
1847     count = ep->f_loc_shdr.g_count;
1848     psh = ep->f_shdr;
1849 
1850     /* Does step A and step B */
1851     for (i = 0; i < count; ++psh,++i) {
1852         const char *name = psh->gh_namestring;
1853         if (is_empty_section(psh->gh_type)) {
1854             /*  No data here. */
1855             continue;
1856         }
1857         if (!elf_sht_groupsec(psh->gh_type,name)) {
1858             /* Step B */
1859             if (elf_flagmatches(psh->gh_flags,SHF_GROUP)) {
1860                 ep->f_shf_group_flag_section_count++;
1861             }
1862             continue;
1863         }
1864         /* Looks like a section group. Do Step A. */
1865         res  =read_gs_section_group(ep,psh,errcode);
1866         if (res != DW_DLV_OK) {
1867             return res;
1868         }
1869     }
1870     /*  Any sections not marked above or here are in
1871         grep DW_GROUPNUMBER_BASE (1).
1872         Section C. */
1873     psh = ep->f_shdr;
1874     for (i = 0; i < count; ++psh,++i) {
1875         const char *name = psh->gh_namestring;
1876         int is_rel = FALSE;
1877         int is_rela = FALSE;
1878 
1879         if (is_empty_section(psh->gh_type)) {
1880             /*  No data here. */
1881             continue;
1882         }
1883         if (elf_sht_groupsec(psh->gh_type,name)) {
1884             continue;
1885         }
1886         /* Not a section group */
1887         if(string_endswith(name,".dwo")) {
1888             if (psh->gh_section_group_number) {
1889                 /* multi-assignment to groups. Oops. */
1890                 *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
1891                 return DW_DLV_ERROR;
1892             }
1893             psh->gh_is_dwarf = TRUE;
1894             psh->gh_section_group_number = DW_GROUPNUMBER_DWO;
1895             ep->f_dwo_group_section_count++;
1896         } else if (_dwarf_load_elf_section_is_dwarf(name,&is_rela,&is_rel)) {
1897             if(!psh->gh_section_group_number) {
1898                 psh->gh_section_group_number = DW_GROUPNUMBER_BASE;
1899             }
1900             psh->gh_is_dwarf = TRUE;
1901         } else {
1902             /* Do nothing. */
1903         }
1904     }
1905     if (ep->f_sht_group_type_section_count) {
1906         /*  Not ARM. Done. */
1907     }
1908     if (!ep->f_shf_group_flag_section_count) {
1909         /*  Nothing more to do. */
1910         return DW_DLV_OK;
1911     }
1912     return DW_DLV_OK;
1913 }
1914 
1915 static int
1916 _dwarf_elf_find_sym_sections(
1917     dwarf_elf_object_access_internals_t *ep,
1918     int *errcode)
1919 {
1920     struct generic_shdr* psh = 0;
1921     Dwarf_Unsigned i = 0;
1922     Dwarf_Unsigned count = 0;
1923     int res = 0;
1924 
1925     count = ep->f_loc_shdr.g_count;
1926     psh = ep->f_shdr;
1927     for (i = 0; i < count; ++psh,++i) {
1928         const char *name = psh->gh_namestring;
1929         if (is_empty_section(psh->gh_type)) {
1930             /*  No data here. */
1931             continue;
1932         }
1933         if (!strcmp(name,".dynsym")) {
1934             ep->f_dynsym_sect_index = i;
1935             ep->f_loc_dynsym.g_offset = psh->gh_offset;
1936         } else if (!strcmp(name,".dynstr")) {
1937             ep->f_dynsym_sect_strings_sect_index = i;
1938             ep->f_dynsym_sect_strings_max = psh->gh_size;
1939         } else if (!strcmp(name,".symtab")) {
1940             ep->f_symtab_sect_index = i;
1941             ep->f_loc_symtab.g_offset = psh->gh_offset;
1942         } else if (!strcmp(name,".strtab")) {
1943             ep->f_symtab_sect_strings_sect_index = i;
1944             ep->f_symtab_sect_strings_max = psh->gh_size;
1945         } else if (!strcmp(name,".dynamic")) {
1946             ep->f_dynamic_sect_index = i;
1947             ep->f_loc_dynamic.g_offset = psh->gh_offset;
1948         }
1949     }
1950 
1951 #if 0
1952     res = validate_links(ep,ep->f_dynsym_sect_index,
1953         ep->f_dynsym_sect_strings_sect_index,errcode);
1954     if (res!= DW_DLV_OK) {
1955         return res;
1956     }
1957 #endif /* 0 */
1958     res = validate_links(ep,ep->f_symtab_sect_index,
1959         ep->f_symtab_sect_strings_sect_index,errcode);
1960     if (res!= DW_DLV_OK) {
1961         return res;
1962     }
1963     return DW_DLV_OK;
1964 }
1965 
1966 
1967 int
1968 _dwarf_load_elf_sectheaders(
1969     dwarf_elf_object_access_internals_t *ep,int*errcode)
1970 {
1971     int res = 0;
1972 
1973     if (ep->f_offsetsize == 32) {
1974         res  = elf_load_sectheaders32(ep,ep->f_ehdr->ge_shoff,
1975             ep->f_ehdr->ge_shentsize,
1976             ep->f_ehdr->ge_shnum,errcode);
1977     } else  if (ep->f_offsetsize == 64) {
1978         res  = elf_load_sectheaders64(ep,ep->f_ehdr->ge_shoff,
1979             ep->f_ehdr->ge_shentsize,
1980             ep->f_ehdr->ge_shnum,errcode);
1981     } else {
1982         *errcode = DW_DLE_OFFSET_SIZE;
1983         return DW_DLV_ERROR;
1984     }
1985     if (res != DW_DLV_OK) {
1986         return res;
1987     }
1988     res  = _dwarf_elf_load_sectstrings(ep,
1989         ep->f_ehdr->ge_shstrndx,errcode);
1990     if (res != DW_DLV_OK) {
1991         return res;
1992     }
1993     res  = _dwarf_elf_load_sect_namestring(ep,errcode);
1994     if (res != DW_DLV_OK) {
1995         return res;
1996     }
1997     res  = _dwarf_elf_find_sym_sections(ep,errcode);
1998     if (res != DW_DLV_OK) {
1999         return res;
2000     }
2001     res = _dwarf_elf_setup_all_section_groups(ep,errcode);
2002     return res;
2003 }
2004