149d3bc91SRichard Lowe /*
249d3bc91SRichard Lowe 
307dc1947SRichard Lowe   Copyright (C) 2000,2001,2004 Silicon Graphics, Inc.  All Rights Reserved.
407dc1947SRichard Lowe   Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
5*4d9fdb46SRobert Mustacchi   Portions Copyright 2008-2016 David Anderson, Inc. All rights reserved.
649d3bc91SRichard Lowe 
749d3bc91SRichard Lowe   This program is free software; you can redistribute it and/or modify it
8*4d9fdb46SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
949d3bc91SRichard Lowe   as published by the Free Software Foundation.
1049d3bc91SRichard Lowe 
1149d3bc91SRichard Lowe   This program is distributed in the hope that it would be useful, but
1249d3bc91SRichard Lowe   WITHOUT ANY WARRANTY; without even the implied warranty of
13*4d9fdb46SRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1449d3bc91SRichard Lowe 
1549d3bc91SRichard Lowe   Further, this software is distributed without any warranty that it is
16*4d9fdb46SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
17*4d9fdb46SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
1849d3bc91SRichard Lowe   otherwise, applies only to this software file.  Patent licenses, if
19*4d9fdb46SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
20*4d9fdb46SRobert Mustacchi   other software, or any other product whatsoever.
2149d3bc91SRichard Lowe 
22*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
23*4d9fdb46SRobert Mustacchi   License along with this program; if not, write the Free Software
2407dc1947SRichard Lowe   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2549d3bc91SRichard Lowe   USA.
2649d3bc91SRichard Lowe 
2749d3bc91SRichard Lowe */
2849d3bc91SRichard Lowe 
2949d3bc91SRichard Lowe #include "config.h"
30*4d9fdb46SRobert Mustacchi #ifdef DWARF_WITH_LIBELF
3149d3bc91SRichard Lowe #include "libdwarfdefs.h"
3249d3bc91SRichard Lowe #include <stdio.h>
3349d3bc91SRichard Lowe #ifdef HAVE_ELFACCESS_H
3449d3bc91SRichard Lowe #include <elfaccess.h>
3549d3bc91SRichard Lowe #else
3649d3bc91SRichard Lowe /* Set r_info  as defined by ELF generic ABI */
3749d3bc91SRichard Lowe #define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t))
3849d3bc91SRichard Lowe #define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t))
3949d3bc91SRichard Lowe #endif
40*4d9fdb46SRobert Mustacchi #ifdef HAVE_STRING_H
41*4d9fdb46SRobert Mustacchi #include <string.h>
42*4d9fdb46SRobert Mustacchi #endif /* HAVE_STRING_H */
43*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDDEF_H
44*4d9fdb46SRobert Mustacchi #include <stddef.h>
45*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDDEF_H */
4649d3bc91SRichard Lowe #include "pro_incl.h"
47*4d9fdb46SRobert Mustacchi #include "dwarf.h"
48*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
49*4d9fdb46SRobert Mustacchi #include "pro_opaque.h"
50*4d9fdb46SRobert Mustacchi #include "pro_error.h"
51*4d9fdb46SRobert Mustacchi #include "pro_alloc.h"
5249d3bc91SRichard Lowe #include "pro_section.h"
5349d3bc91SRichard Lowe #include "pro_reloc.h"
5449d3bc91SRichard Lowe #include "pro_reloc_stream.h"
5549d3bc91SRichard Lowe 
56*4d9fdb46SRobert Mustacchi /*  Return DW_DLV_ERROR on malloc error or reltarget_length error.
57*4d9fdb46SRobert Mustacchi     Return DW_DLV_OK otherwise */
58*4d9fdb46SRobert Mustacchi /*ARGSUSED*/ int
_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)5907dc1947SRichard Lowe _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,
6007dc1947SRichard Lowe     int base_sec_index,
6107dc1947SRichard Lowe     Dwarf_Unsigned offset,      /* r_offset of reloc */
6207dc1947SRichard Lowe     Dwarf_Unsigned symidx,
6307dc1947SRichard Lowe     enum Dwarf_Rel_Type type,
6407dc1947SRichard Lowe     int reltarget_length)
6549d3bc91SRichard Lowe {
6649d3bc91SRichard Lowe #if HAVE_ELF64_GETEHDR
6707dc1947SRichard Lowe     REL64 *elf64_reloc = 0;
6807dc1947SRichard Lowe     void *relrec_to_fill = 0;
6907dc1947SRichard Lowe     int res = 0;
7007dc1947SRichard Lowe     int rel_type = 0;
7149d3bc91SRichard Lowe 
7249d3bc91SRichard Lowe     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
73*4d9fdb46SRobert Mustacchi         &relrec_to_fill);
7449d3bc91SRichard Lowe     if (res != DW_DLV_OK)
7507dc1947SRichard Lowe         return res;
7649d3bc91SRichard Lowe 
7749d3bc91SRichard Lowe 
7849d3bc91SRichard Lowe     if (type == dwarf_drt_data_reloc) {
79*4d9fdb46SRobert Mustacchi         if (reltarget_length == dbg->de_dwarf_offset_size) {
8007dc1947SRichard Lowe             rel_type = dbg->de_offset_reloc;
8107dc1947SRichard Lowe         } else if (reltarget_length == dbg->de_pointer_size) {
8207dc1947SRichard Lowe             rel_type = dbg->de_ptr_reloc;
8307dc1947SRichard Lowe         } else {
8407dc1947SRichard Lowe             return DW_DLV_ERROR;
8507dc1947SRichard Lowe         }
8649d3bc91SRichard Lowe     } else if (type == dwarf_drt_segment_rel) {
8707dc1947SRichard Lowe         rel_type = dbg->de_exc_reloc;
8849d3bc91SRichard Lowe     } else {
89*4d9fdb46SRobert Mustacchi         /*  We are in trouble: improper use of stream relocations.
90*4d9fdb46SRobert Mustacchi             Someone else will diagnose */
9107dc1947SRichard Lowe         rel_type = 0;
9249d3bc91SRichard Lowe     }
9349d3bc91SRichard Lowe 
9407dc1947SRichard Lowe     elf64_reloc = (REL64 *)relrec_to_fill;
9549d3bc91SRichard Lowe     elf64_reloc->r_offset = offset;
9649d3bc91SRichard Lowe     Set_REL64_info(*elf64_reloc, symidx, rel_type);
9749d3bc91SRichard Lowe     return DW_DLV_OK;
9849d3bc91SRichard Lowe #else /* !HAVE_ELF64_GETEHDR */
9949d3bc91SRichard Lowe     return DW_DLV_ERROR;
10049d3bc91SRichard Lowe #endif /* #if HAVE_ELF64_GETEHDR */
10149d3bc91SRichard Lowe }
10249d3bc91SRichard Lowe 
103*4d9fdb46SRobert Mustacchi /*  Return DW_DLV_ERROR on malloc error or reltarget_length error.
104*4d9fdb46SRobert Mustacchi     Return DW_DLV_OK otherwise
105*4d9fdb46SRobert Mustacchi     a binary reloc: 32bit ABI */ int
_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)106*4d9fdb46SRobert Mustacchi _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index,
10707dc1947SRichard Lowe     Dwarf_Unsigned offset,      /* r_offset of reloc */
10807dc1947SRichard Lowe     Dwarf_Unsigned symidx,
10907dc1947SRichard Lowe     enum Dwarf_Rel_Type type,
11007dc1947SRichard Lowe     int reltarget_length)
11149d3bc91SRichard Lowe {
11207dc1947SRichard Lowe     REL32 *elf32_reloc = 0;
11307dc1947SRichard Lowe     void *relrec_to_fill = 0;
11407dc1947SRichard Lowe     int res = 0;
11507dc1947SRichard Lowe     int rel_type = 0;
11649d3bc91SRichard Lowe 
11749d3bc91SRichard Lowe     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
118*4d9fdb46SRobert Mustacchi         &relrec_to_fill);
11949d3bc91SRichard Lowe     if (res != DW_DLV_OK)
12007dc1947SRichard Lowe         return res;
12149d3bc91SRichard Lowe     if (type == dwarf_drt_data_reloc) {
122*4d9fdb46SRobert Mustacchi         if (reltarget_length == dbg->de_dwarf_offset_size) {
12307dc1947SRichard Lowe             rel_type = dbg->de_offset_reloc;
12407dc1947SRichard Lowe         } else if (reltarget_length == dbg->de_pointer_size) {
12507dc1947SRichard Lowe             rel_type = dbg->de_ptr_reloc;
12607dc1947SRichard Lowe         } else {
12707dc1947SRichard Lowe             return DW_DLV_ERROR;
12807dc1947SRichard Lowe         }
12949d3bc91SRichard Lowe     } else if (type == dwarf_drt_segment_rel) {
13007dc1947SRichard Lowe         rel_type = dbg->de_exc_reloc;
13149d3bc91SRichard Lowe     } else {
132*4d9fdb46SRobert Mustacchi         /*  We are in trouble: improper use of stream relocations.
133*4d9fdb46SRobert Mustacchi             Someone else will diagnose */
13407dc1947SRichard Lowe         rel_type = 0;
13549d3bc91SRichard Lowe     }
13649d3bc91SRichard Lowe 
13707dc1947SRichard Lowe     elf32_reloc = (REL32*)relrec_to_fill;
13849d3bc91SRichard Lowe     elf32_reloc->r_offset = (Elf32_Addr) offset;
139*4d9fdb46SRobert Mustacchi     Set_REL32_info(*elf32_reloc, symidx, rel_type);
14049d3bc91SRichard Lowe     return DW_DLV_OK;
14149d3bc91SRichard Lowe 
14249d3bc91SRichard Lowe     /* get a slot, fill in the slot entry */
14349d3bc91SRichard Lowe }
14449d3bc91SRichard Lowe 
14549d3bc91SRichard Lowe 
14649d3bc91SRichard Lowe 
147*4d9fdb46SRobert Mustacchi /*  Return DW_DLV_OK.
148*4d9fdb46SRobert Mustacchi     Never can really do anything: lengths cannot
149*4d9fdb46SRobert Mustacchi     be represented as end-start in a stream.  */
150*4d9fdb46SRobert Mustacchi /*ARGSUSED*/ int
_dwarf_pro_reloc_length_stream(UNUSEDARG Dwarf_P_Debug dbg,UNUSEDARG int base_sec_index,UNUSEDARG Dwarf_Unsigned offset,UNUSEDARG Dwarf_Unsigned start_symidx,UNUSEDARG Dwarf_Unsigned end_symidx,UNUSEDARG enum Dwarf_Rel_Type type,UNUSEDARG int reltarget_length)151*4d9fdb46SRobert Mustacchi _dwarf_pro_reloc_length_stream(UNUSEDARG Dwarf_P_Debug dbg,
152*4d9fdb46SRobert Mustacchi     UNUSEDARG int base_sec_index,
153*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Unsigned offset,    /* r_offset of reloc */
154*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Unsigned start_symidx,
155*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Unsigned end_symidx,
156*4d9fdb46SRobert Mustacchi     UNUSEDARG enum Dwarf_Rel_Type type,
157*4d9fdb46SRobert Mustacchi     UNUSEDARG int reltarget_length)
15849d3bc91SRichard Lowe {
15949d3bc91SRichard Lowe     /* get a slot, fill in the slot entry */
16049d3bc91SRichard Lowe     return DW_DLV_OK;
16149d3bc91SRichard Lowe }
16249d3bc91SRichard Lowe 
16349d3bc91SRichard Lowe 
164*4d9fdb46SRobert Mustacchi /*  Ensure each stream is a single buffer and
165*4d9fdb46SRobert Mustacchi     add that single buffer to the set of stream buffers.
16649d3bc91SRichard Lowe 
167*4d9fdb46SRobert Mustacchi     By creating a new buffer and copying if necessary.
16849d3bc91SRichard Lowe 
169*4d9fdb46SRobert Mustacchi     Free the input set of buffers if we consolidate.
170*4d9fdb46SRobert Mustacchi     Return -1 on error (malloc failure)
17149d3bc91SRichard Lowe 
172*4d9fdb46SRobert Mustacchi     Return DW_DLV_OK on success. Any other return indicates
173*4d9fdb46SRobert Mustacchi     malloc failed.  */
17449d3bc91SRichard Lowe int
_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,Dwarf_Signed * new_sec_count)17549d3bc91SRichard Lowe _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
17607dc1947SRichard Lowe     Dwarf_Signed * new_sec_count)
17749d3bc91SRichard Lowe {
17849d3bc91SRichard Lowe     unsigned long total_size = 0;
179*4d9fdb46SRobert Mustacchi     int i = 0;
180*4d9fdb46SRobert Mustacchi     Dwarf_Error erre = 0;
181*4d9fdb46SRobert Mustacchi     Dwarf_Error *error = &erre;
18249d3bc91SRichard Lowe     Dwarf_Signed sec_count = 0;
18349d3bc91SRichard Lowe 
184*4d9fdb46SRobert Mustacchi     for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
185*4d9fdb46SRobert Mustacchi         Dwarf_P_Per_Reloc_Sect p_reloc = dbg->de_reloc_sect +i;
186*4d9fdb46SRobert Mustacchi         Dwarf_Small *data = 0;
187*4d9fdb46SRobert Mustacchi         int sec_index = 0;
18807dc1947SRichard Lowe         unsigned long ct = p_reloc->pr_reloc_total_count;
18907dc1947SRichard Lowe         unsigned len = 0;
19007dc1947SRichard Lowe         struct Dwarf_P_Relocation_Block_s *p_blk = 0;
19107dc1947SRichard Lowe         struct Dwarf_P_Relocation_Block_s *p_blk_last = 0;
19207dc1947SRichard Lowe         Dwarf_P_Per_Reloc_Sect prb = 0;
19307dc1947SRichard Lowe 
19407dc1947SRichard Lowe         if (ct == 0) {
19507dc1947SRichard Lowe             continue;
19607dc1947SRichard Lowe         }
19707dc1947SRichard Lowe         prb = &dbg->de_reloc_sect[i];
19807dc1947SRichard Lowe         len = dbg->de_relocation_record_size;
19907dc1947SRichard Lowe         ++sec_count;
20007dc1947SRichard Lowe 
20107dc1947SRichard Lowe         total_size = ct * len;
20207dc1947SRichard Lowe         sec_index = prb->pr_sect_num_of_reloc_sect;
20307dc1947SRichard Lowe         if (sec_index == 0) {
204*4d9fdb46SRobert Mustacchi             /*  Call de_callback_func or de_callback_func_b or _c, getting
205*4d9fdb46SRobert Mustacchi                 section number of reloc section. */
20607dc1947SRichard Lowe             int rel_section_index = 0;
20707dc1947SRichard Lowe             Dwarf_Unsigned name_idx = 0;
208*4d9fdb46SRobert Mustacchi             int erri = 0;
20907dc1947SRichard Lowe 
210*4d9fdb46SRobert Mustacchi             if (dbg->de_callback_func) {
21107dc1947SRichard Lowe                 rel_section_index =
21207dc1947SRichard Lowe                     dbg->de_callback_func(_dwarf_rel_section_names[i],
213*4d9fdb46SRobert Mustacchi                         /* size */ dbg->de_relocation_record_size,
214*4d9fdb46SRobert Mustacchi                         /* type */ SHT_REL,
215*4d9fdb46SRobert Mustacchi                         /* flags */ 0,
216*4d9fdb46SRobert Mustacchi                         /* link to symtab, which we cannot
217*4d9fdb46SRobert Mustacchi                             know */ 0,
218*4d9fdb46SRobert Mustacchi                         /* info == link to sec rels apply to */
219*4d9fdb46SRobert Mustacchi                             dbg->de_elf_sects[i],
220*4d9fdb46SRobert Mustacchi                         &name_idx,
221*4d9fdb46SRobert Mustacchi                         dbg->de_user_data,
222*4d9fdb46SRobert Mustacchi                         &erri);
22307dc1947SRichard Lowe             }
22407dc1947SRichard Lowe             if (rel_section_index == -1) {
22507dc1947SRichard Lowe                 {
22607dc1947SRichard Lowe                     _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR);
22707dc1947SRichard Lowe                     return (DW_DLV_ERROR);
22807dc1947SRichard Lowe                 }
22907dc1947SRichard Lowe 
23007dc1947SRichard Lowe             }
23107dc1947SRichard Lowe             prb->pr_sect_num_of_reloc_sect = rel_section_index;
23207dc1947SRichard Lowe             sec_index = rel_section_index;
23307dc1947SRichard Lowe         }
234*4d9fdb46SRobert Mustacchi         GET_CHUNK(dbg, sec_index, data, total_size, &erri);
23507dc1947SRichard Lowe         p_blk = p_reloc->pr_first_block;
23607dc1947SRichard Lowe 
237*4d9fdb46SRobert Mustacchi         /*  Following loop executes at least once. Effects the
238*4d9fdb46SRobert Mustacchi             consolidation to a single block or, if already a single
239*4d9fdb46SRobert Mustacchi             block, simply copies to the output buffer. And frees the
240*4d9fdb46SRobert Mustacchi             input block. The new block is in the de_debug_sects list. */
24107dc1947SRichard Lowe         while (p_blk) {
242*4d9fdb46SRobert Mustacchi             unsigned long lenk =
24307dc1947SRichard Lowe                 p_blk->rb_where_to_add_next - p_blk->rb_data;
24407dc1947SRichard Lowe 
245*4d9fdb46SRobert Mustacchi             memcpy(data, p_blk->rb_data, lenk);
246*4d9fdb46SRobert Mustacchi             data += lenk;
24707dc1947SRichard Lowe             p_blk_last = p_blk;
24807dc1947SRichard Lowe             p_blk = p_blk->rb_next;
24907dc1947SRichard Lowe             _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
25007dc1947SRichard Lowe         }
25107dc1947SRichard Lowe         /* ASSERT: sum of len copied == total_size */
25207dc1947SRichard Lowe 
253*4d9fdb46SRobert Mustacchi         /*  We have copied the input, now drop the pointers to it. For
254*4d9fdb46SRobert Mustacchi             debugging, leave the other data untouched. */
25507dc1947SRichard Lowe         p_reloc->pr_first_block = 0;
25607dc1947SRichard Lowe         p_reloc->pr_last_block = 0;
25749d3bc91SRichard Lowe     }
25849d3bc91SRichard Lowe     *new_sec_count = sec_count;
25949d3bc91SRichard Lowe     return DW_DLV_OK;
26049d3bc91SRichard Lowe }
261*4d9fdb46SRobert Mustacchi #else /* DWARF_WITH_LIBELF */
262*4d9fdb46SRobert Mustacchi /* avoids empty file warning if no libelf */
263*4d9fdb46SRobert Mustacchi int dwarf_dummy_pro_reloc_stream = 2;
264*4d9fdb46SRobert Mustacchi #endif /* DWARF_WITH_LIBELF */
265