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