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