149d3bc91SRichard Lowe /*
207dc1947SRichard Lowe   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
3*4d9fdb46SRobert Mustacchi   Portions Copyright 2008-2016 David Anderson, Inc. All rights reserved.
449d3bc91SRichard Lowe 
549d3bc91SRichard Lowe   This program is free software; you can redistribute it and/or modify it
6*4d9fdb46SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
749d3bc91SRichard Lowe   as published by the Free Software Foundation.
849d3bc91SRichard Lowe 
949d3bc91SRichard Lowe   This program is distributed in the hope that it would be useful, but
1049d3bc91SRichard Lowe   WITHOUT ANY WARRANTY; without even the implied warranty of
11*4d9fdb46SRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1249d3bc91SRichard Lowe 
1349d3bc91SRichard Lowe   Further, this software is distributed without any warranty that it is
14*4d9fdb46SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
15*4d9fdb46SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
1649d3bc91SRichard Lowe   otherwise, applies only to this software file.  Patent licenses, if
17*4d9fdb46SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
18*4d9fdb46SRobert Mustacchi   other software, or any other product whatsoever.
1949d3bc91SRichard Lowe 
20*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
21*4d9fdb46SRobert Mustacchi   License along with this program; if not, write the Free Software
2207dc1947SRichard Lowe   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2349d3bc91SRichard Lowe   USA.
2449d3bc91SRichard Lowe 
2549d3bc91SRichard Lowe */
2649d3bc91SRichard Lowe 
2749d3bc91SRichard Lowe #include "config.h"
2849d3bc91SRichard Lowe #include "libdwarfdefs.h"
2949d3bc91SRichard Lowe #include <stdio.h>
30*4d9fdb46SRobert Mustacchi #ifdef HAVE_STRING_H
3149d3bc91SRichard Lowe #include <string.h>
32*4d9fdb46SRobert Mustacchi #endif /* HAVE_STRING_H */
33*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDDEF_H
34*4d9fdb46SRobert Mustacchi #include <stddef.h>
35*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDDEF_H */
3649d3bc91SRichard Lowe #include "pro_incl.h"
37*4d9fdb46SRobert Mustacchi #include "dwarf.h"
38*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
39*4d9fdb46SRobert Mustacchi #include "pro_opaque.h"
40*4d9fdb46SRobert Mustacchi #include "pro_error.h"
41*4d9fdb46SRobert Mustacchi #include "pro_alloc.h"
42*4d9fdb46SRobert Mustacchi #include "pro_reloc.h"
4349d3bc91SRichard Lowe 
4449d3bc91SRichard Lowe 
45*4d9fdb46SRobert Mustacchi /*  Do initial alloc of newslots slots.
46*4d9fdb46SRobert Mustacchi     Fails only if malloc fails.
4749d3bc91SRichard Lowe 
48*4d9fdb46SRobert Mustacchi     Supposed to be called before any relocs allocated.
49*4d9fdb46SRobert Mustacchi     Ignored if after any allocated.
5049d3bc91SRichard Lowe 
51*4d9fdb46SRobert Mustacchi     Part of an optimization, so that for a known 'newslots'
52*4d9fdb46SRobert Mustacchi     relocations count we can preallocate the right size block.
53*4d9fdb46SRobert Mustacchi     Called from just 2 places.
5449d3bc91SRichard Lowe 
55*4d9fdb46SRobert Mustacchi     We use 'slots' so we don't have to do a new
56*4d9fdb46SRobert Mustacchi     allocation for every relocation, just a new
57*4d9fdb46SRobert Mustacchi     allocation every n slots. slots_in_block.
58*4d9fdb46SRobert Mustacchi 
59*4d9fdb46SRobert Mustacchi     returns DW_DLV_OK or  DW_DLV_ERROR
6049d3bc91SRichard Lowe */
6149d3bc91SRichard Lowe int
_dwarf_pro_pre_alloc_specific_reloc_slots(Dwarf_P_Debug dbg,Dwarf_P_Per_Reloc_Sect prel,Dwarf_Unsigned newslots)62*4d9fdb46SRobert Mustacchi _dwarf_pro_pre_alloc_specific_reloc_slots(Dwarf_P_Debug dbg,
63*4d9fdb46SRobert Mustacchi     Dwarf_P_Per_Reloc_Sect prel,
6407dc1947SRichard Lowe     Dwarf_Unsigned newslots)
6549d3bc91SRichard Lowe {
6607dc1947SRichard Lowe     unsigned long len = 0;
6707dc1947SRichard Lowe     struct Dwarf_P_Relocation_Block_s *data = 0;
6849d3bc91SRichard Lowe     unsigned long slots_in_blk = (unsigned long) newslots;
6949d3bc91SRichard Lowe     unsigned long rel_rec_size = dbg->de_relocation_record_size;
7049d3bc91SRichard Lowe 
71*4d9fdb46SRobert Mustacchi     if (prel->pr_first_block) {
7207dc1947SRichard Lowe         return DW_DLV_OK;       /* do nothing */
73*4d9fdb46SRobert Mustacchi     }
7449d3bc91SRichard Lowe 
7549d3bc91SRichard Lowe     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
7607dc1947SRichard Lowe         slots_in_blk * rel_rec_size;
7749d3bc91SRichard Lowe     data = (struct Dwarf_P_Relocation_Block_s *)
7807dc1947SRichard Lowe         _dwarf_p_get_alloc(dbg, len);
7949d3bc91SRichard Lowe     if (!data) {
8007dc1947SRichard Lowe         return DW_DLV_ERROR;
8149d3bc91SRichard Lowe     }
8207dc1947SRichard Lowe     data->rb_slots_in_block = slots_in_blk;     /* could use default
83*4d9fdb46SRobert Mustacchi         here, as fallback in case our origininal
84*4d9fdb46SRobert Mustacchi         estimate wrong. When we call this we
85*4d9fdb46SRobert Mustacchi         presumably know what we are doing, so
86*4d9fdb46SRobert Mustacchi         keep this count for now */
8749d3bc91SRichard Lowe     data->rb_next_slot_to_use = 0;
8849d3bc91SRichard Lowe     data->rb_where_to_add_next =
8907dc1947SRichard Lowe         ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
9049d3bc91SRichard Lowe     data->rb_data = data->rb_where_to_add_next;
9149d3bc91SRichard Lowe 
9249d3bc91SRichard Lowe     prel->pr_first_block = data;
9349d3bc91SRichard Lowe     prel->pr_last_block = data;
9449d3bc91SRichard Lowe     prel->pr_block_count = 1;
9549d3bc91SRichard Lowe     return DW_DLV_OK;
9649d3bc91SRichard Lowe }
9749d3bc91SRichard Lowe 
9849d3bc91SRichard Lowe 
9949d3bc91SRichard Lowe /*Do alloc of slots.
10049d3bc91SRichard Lowe   Fails only if malloc fails.
10149d3bc91SRichard Lowe 
10249d3bc91SRichard Lowe   Only allocator used.
10349d3bc91SRichard Lowe 
10449d3bc91SRichard Lowe   returns DW_DLV_OK or  DW_DLV_ERROR
10549d3bc91SRichard Lowe */
10649d3bc91SRichard Lowe int
_dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg,int rel_sec_index)10749d3bc91SRichard Lowe _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index)
10849d3bc91SRichard Lowe {
10907dc1947SRichard Lowe     unsigned long len = 0;
11007dc1947SRichard Lowe     struct Dwarf_P_Relocation_Block_s *data = 0;
11149d3bc91SRichard Lowe     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
11249d3bc91SRichard Lowe     unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc;
11349d3bc91SRichard Lowe     unsigned long rel_rec_size = dbg->de_relocation_record_size;
11449d3bc91SRichard Lowe 
11549d3bc91SRichard Lowe     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
11607dc1947SRichard Lowe         slots_in_blk * rel_rec_size;
11749d3bc91SRichard Lowe 
11849d3bc91SRichard Lowe     data = (struct Dwarf_P_Relocation_Block_s *)
11907dc1947SRichard Lowe         _dwarf_p_get_alloc(dbg, len);
12049d3bc91SRichard Lowe     if (!data) {
12107dc1947SRichard Lowe         return DW_DLV_ERROR;
12249d3bc91SRichard Lowe     }
12349d3bc91SRichard Lowe 
12449d3bc91SRichard Lowe     if (prel->pr_first_block) {
12507dc1947SRichard Lowe         prel->pr_last_block->rb_next = data;
12607dc1947SRichard Lowe         prel->pr_last_block = data;
12707dc1947SRichard Lowe         prel->pr_block_count += 1;
12849d3bc91SRichard Lowe     } else {
12907dc1947SRichard Lowe         prel->pr_first_block = data;
13007dc1947SRichard Lowe         prel->pr_last_block = data;
13107dc1947SRichard Lowe         prel->pr_block_count = 1;
13249d3bc91SRichard Lowe     }
13349d3bc91SRichard Lowe     data->rb_slots_in_block = slots_in_blk;
13449d3bc91SRichard Lowe     data->rb_next_slot_to_use = 0;
13549d3bc91SRichard Lowe     data->rb_where_to_add_next =
13607dc1947SRichard Lowe         ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
13749d3bc91SRichard Lowe     data->rb_data = data->rb_where_to_add_next;
13849d3bc91SRichard Lowe     return DW_DLV_OK;
13949d3bc91SRichard Lowe 
14049d3bc91SRichard Lowe }
14149d3bc91SRichard Lowe 
142*4d9fdb46SRobert Mustacchi /*  Reserve a slot. return DW_DLV_OK if succeeds.
14349d3bc91SRichard Lowe 
144*4d9fdb46SRobert Mustacchi     Return DW_DLV_ERROR if fails (malloc error).
14549d3bc91SRichard Lowe 
146*4d9fdb46SRobert Mustacchi     Use the relrec_to_fill to pass back a pointer to
147*4d9fdb46SRobert Mustacchi     a slot space to use.  */
14849d3bc91SRichard Lowe int
_dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,int base_sec_index,void ** relrec_to_fill)14949d3bc91SRichard Lowe _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
15007dc1947SRichard Lowe     int base_sec_index, void **relrec_to_fill)
15149d3bc91SRichard Lowe {
15207dc1947SRichard Lowe     struct Dwarf_P_Relocation_Block_s *data = 0;
15349d3bc91SRichard Lowe     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index];
15449d3bc91SRichard Lowe     unsigned long rel_rec_size = dbg->de_relocation_record_size;
15549d3bc91SRichard Lowe 
15607dc1947SRichard Lowe     char *ret_addr = 0;
15749d3bc91SRichard Lowe 
15849d3bc91SRichard Lowe     data = prel->pr_last_block;
15949d3bc91SRichard Lowe     if ((data == 0) ||
16007dc1947SRichard Lowe         (data->rb_next_slot_to_use >= data->rb_slots_in_block)) {
16107dc1947SRichard Lowe         int res;
16249d3bc91SRichard Lowe 
16307dc1947SRichard Lowe         res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index);
16407dc1947SRichard Lowe         if (res != DW_DLV_OK) {
16507dc1947SRichard Lowe             return res;
16607dc1947SRichard Lowe         }
16749d3bc91SRichard Lowe     }
16849d3bc91SRichard Lowe 
16949d3bc91SRichard Lowe     data = prel->pr_last_block;
17049d3bc91SRichard Lowe     /* now we have an empty slot */
17149d3bc91SRichard Lowe     ret_addr = data->rb_where_to_add_next;
17249d3bc91SRichard Lowe     data->rb_where_to_add_next += rel_rec_size;
17349d3bc91SRichard Lowe     data->rb_next_slot_to_use += 1;
17449d3bc91SRichard Lowe     prel->pr_reloc_total_count += 1;
17549d3bc91SRichard Lowe     *relrec_to_fill = (void *) ret_addr;
17649d3bc91SRichard Lowe     return DW_DLV_OK;
17749d3bc91SRichard Lowe 
17849d3bc91SRichard Lowe }
17949d3bc91SRichard Lowe 
18049d3bc91SRichard Lowe /*
181*4d9fdb46SRobert Mustacchi     On success  returns count of
182*4d9fdb46SRobert Mustacchi     .rel.* sections that are symbolic
183*4d9fdb46SRobert Mustacchi     thru count_of_relocation_sections.
18449d3bc91SRichard Lowe 
185*4d9fdb46SRobert Mustacchi     On success, returns DW_DLV_OK.
18649d3bc91SRichard Lowe 
187*4d9fdb46SRobert Mustacchi     If this is not a 'symbolic' run, returns
18849d3bc91SRichard Lowe     DW_DLV_NO_ENTRY.
18949d3bc91SRichard Lowe 
190*4d9fdb46SRobert Mustacchi     No errors are possible.
19149d3bc91SRichard Lowe */
192*4d9fdb46SRobert Mustacchi /*ARGSUSED*/
193*4d9fdb46SRobert Mustacchi int
dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,Dwarf_Unsigned * count_of_relocation_sections,int * drd_buffer_version,UNUSEDARG Dwarf_Error * error)19449d3bc91SRichard Lowe dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,
19507dc1947SRichard Lowe     Dwarf_Unsigned *
19607dc1947SRichard Lowe     count_of_relocation_sections,
19707dc1947SRichard Lowe     int *drd_buffer_version,
198*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Error * error)
19949d3bc91SRichard Lowe {
20049d3bc91SRichard Lowe     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
201*4d9fdb46SRobert Mustacchi         int i = 0;
20207dc1947SRichard Lowe         unsigned int count = 0;
20307dc1947SRichard Lowe 
20407dc1947SRichard Lowe         for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
20507dc1947SRichard Lowe             if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) {
20607dc1947SRichard Lowe                 ++count;
20707dc1947SRichard Lowe             }
20807dc1947SRichard Lowe         }
20907dc1947SRichard Lowe         *count_of_relocation_sections = (Dwarf_Unsigned) count;
21007dc1947SRichard Lowe         *drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
21107dc1947SRichard Lowe         return DW_DLV_OK;
21249d3bc91SRichard Lowe     }
213*4d9fdb46SRobert Mustacchi     /*  Reset to start at beginning of reloc groups. */
214*4d9fdb46SRobert Mustacchi     dbg->de_reloc_next_to_return = 0;
21549d3bc91SRichard Lowe     return DW_DLV_NO_ENTRY;
21649d3bc91SRichard Lowe }
21749d3bc91SRichard Lowe 
21849d3bc91SRichard Lowe int
dwarf_get_relocation_info(Dwarf_P_Debug dbg,Dwarf_Signed * elf_section_index,Dwarf_Signed * elf_section_index_link,Dwarf_Unsigned * relocation_buffer_count,Dwarf_Relocation_Data * reldata_buffer,Dwarf_Error * error)21949d3bc91SRichard Lowe dwarf_get_relocation_info(Dwarf_P_Debug dbg,
22007dc1947SRichard Lowe     Dwarf_Signed * elf_section_index,
22107dc1947SRichard Lowe     Dwarf_Signed * elf_section_index_link,
22207dc1947SRichard Lowe     Dwarf_Unsigned * relocation_buffer_count,
22307dc1947SRichard Lowe     Dwarf_Relocation_Data * reldata_buffer,
22407dc1947SRichard Lowe     Dwarf_Error * error)
22549d3bc91SRichard Lowe {
22649d3bc91SRichard Lowe     int next = dbg->de_reloc_next_to_return;
22749d3bc91SRichard Lowe 
22849d3bc91SRichard Lowe     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
229*4d9fdb46SRobert Mustacchi         int i = 0;
23049d3bc91SRichard Lowe 
23107dc1947SRichard Lowe         for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
232*4d9fdb46SRobert Mustacchi             /*  de_reloc_sect[] and de_elf_sects[] are
233*4d9fdb46SRobert Mustacchi                 in direct parallel. */
23407dc1947SRichard Lowe             Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i];
235*4d9fdb46SRobert Mustacchi             int elf_sect_num =  dbg->de_elf_sects[i];
23649d3bc91SRichard Lowe 
23707dc1947SRichard Lowe             if (prel->pr_reloc_total_count > 0) {
238*4d9fdb46SRobert Mustacchi                 /*  Set up 'next' for subsequent call to
239*4d9fdb46SRobert Mustacchi                     dwarf_get_relocation_info(). */
24007dc1947SRichard Lowe                 dbg->de_reloc_next_to_return = i + 1;
24149d3bc91SRichard Lowe 
242*4d9fdb46SRobert Mustacchi                 /* ASSERT: prel->pr_block_count == 1 */
243*4d9fdb46SRobert Mustacchi                 *elf_section_index = prel->pr_sect_num_of_reloc_sect;
24449d3bc91SRichard Lowe 
245*4d9fdb46SRobert Mustacchi                 /*  Elf sec num in generated elf */
246*4d9fdb46SRobert Mustacchi                 *elf_section_index_link = elf_sect_num;
24749d3bc91SRichard Lowe 
24807dc1947SRichard Lowe                 *relocation_buffer_count = prel->pr_reloc_total_count;
24907dc1947SRichard Lowe                 *reldata_buffer = (Dwarf_Relocation_Data)
25007dc1947SRichard Lowe                     (prel->pr_first_block->rb_data);
25107dc1947SRichard Lowe                 return DW_DLV_OK;
25207dc1947SRichard Lowe             }
25307dc1947SRichard Lowe         }
25407dc1947SRichard Lowe         DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
25549d3bc91SRichard Lowe     }
25649d3bc91SRichard Lowe     return DW_DLV_NO_ENTRY;
25749d3bc91SRichard Lowe }
258