summaryrefslogtreecommitdiff
path: root/libdwarf/pro_reloc_symbolic.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
committerIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
commitbb1c3da3c12651f1c408d96dd6d33ae157bdadd6 (patch)
tree4a535b35500684ac6a928bf0fd661325b5a04697 /libdwarf/pro_reloc_symbolic.c
downloaddwarfutils-upstream.tar.gz
Imported Upstream version 20120410upstream/20120410upstream
Diffstat (limited to 'libdwarf/pro_reloc_symbolic.c')
-rw-r--r--libdwarf/pro_reloc_symbolic.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/libdwarf/pro_reloc_symbolic.c b/libdwarf/pro_reloc_symbolic.c
new file mode 100644
index 0000000..3db4505
--- /dev/null
+++ b/libdwarf/pro_reloc_symbolic.c
@@ -0,0 +1,279 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+/*#include <elfaccess.h> */
+#include "pro_incl.h"
+#include "pro_section.h"
+#include "pro_reloc.h"
+#include "pro_reloc_symbolic.h"
+
+/* Return DW_DLV_ERROR on malloc error.
+ Return DW_DLV_OK otherwise */
+
+int
+_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ /* get a slot, fill in the slot entry */
+ void *relrec_to_fill = 0;
+ int res = 0;
+ struct Dwarf_Relocation_Data_s *slotp;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+ slotp->drd_type = type;
+ slotp->drd_length = reltarget_length;
+ slotp->drd_offset = offset;
+ slotp->drd_symbol_index = symidx;
+ return DW_DLV_OK;
+}
+
+
+
+/* Return DW_DLV_ERROR on malloc error.
+ Return DW_DLV_OK otherwise */
+int
+_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ /* get a slot, fill in the slot entry */
+ void *relrec_to_fill = 0;
+ int res = 0;
+ struct Dwarf_Relocation_Data_s *slotp1 = 0;
+ struct Dwarf_Relocation_Data_s *slotp2 = 0;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+
+ /* ASSERT: type == dwarf_drt_first_of_length_type_pair */
+ slotp1->drd_type = type;
+ slotp1->drd_length = reltarget_length;
+ slotp1->drd_offset = offset;
+ slotp1->drd_symbol_index = start_symidx;
+
+ slotp2->drd_type = dwarf_drt_second_of_length_pair;
+ slotp2->drd_length = reltarget_length;
+ slotp2->drd_offset = offset;
+ slotp2->drd_symbol_index = end_symidx;
+ return DW_DLV_OK;
+}
+
+/* Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s
+ we must to allow adding a fresh new single
+ block easily (block consolidation use only). */
+static void
+_dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk,
+ unsigned long ct)
+{
+
+
+ /* Do not zero pr_sect_num_of_reloc_sect */
+ pblk->pr_reloc_total_count = 0;
+ pblk->pr_first_block = 0;
+ pblk->pr_last_block = 0;
+ pblk->pr_block_count = 0;
+ pblk->pr_slots_per_block_to_alloc = ct;
+}
+
+/* Ensure each stream is a single buffer and
+ add that single buffer to the set of stream buffers.
+
+ By creating a new buffer and copying if necessary.
+ (If > 1 block, reduce to 1 block)
+
+ Free the input set of buffers if we consolidate.
+
+ We pass back *new_sec_count as zero because we
+ are not creating normal sections for a .o, but
+ symbolic relocations, separately counted.
+
+ Return -1 on error (malloc failure)
+
+ Return DW_DLV_OK on success. Any other return indicates
+ malloc failed. */
+int
+_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Signed * new_sec_count)
+{
+ /* unsigned long total_size =0; */
+ Dwarf_Small *data = 0;
+ int sec_index = 0;
+ int res = 0;
+ unsigned long i = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Signed sec_count = 0;
+ Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
+
+ for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
+ unsigned long ct = p_reloc->pr_reloc_total_count;
+ struct Dwarf_P_Relocation_Block_s *p_blk;
+ struct Dwarf_P_Relocation_Block_s *p_blk_last;
+ int err;
+ if (ct == 0) {
+ continue;
+ }
+
+ /* len = dbg->de_relocation_record_size; */
+ ++sec_count;
+
+ /* total_size = ct *len; */
+ sec_index = p_reloc->pr_sect_num_of_reloc_sect;
+ if (sec_index == 0) {
+ /* Call de_callback_func or de_callback_func_b,
+ getting section number of reloc section. */
+ int rel_section_index = 0;
+ int int_name = 0;
+ Dwarf_Unsigned name_idx = 0;
+
+ /* This is a bit of a fake, as we do not really have true
+ elf sections at all. Just the data such might contain.
+ But this lets the caller eventually link things
+ together: without this call we would not know what rel
+ data goes with what section when we are asked for the
+ real arrays. */
+
+ if (dbg->de_callback_func_c) {
+ rel_section_index =
+ dbg->de_callback_func_c(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx,
+ dbg->de_user_data,&err);
+ } else if (dbg->de_callback_func_b) {
+ rel_section_index =
+ dbg->de_callback_func_b(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx, &err);
+ } else {
+ rel_section_index =
+ dbg->de_callback_func(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to, in elf, sh_info */
+ dbg->de_elf_sects[i], &int_name, &err);
+ name_idx = int_name;
+ }
+ if (rel_section_index == -1) {
+ {
+ _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
+ return (DW_DLV_ERROR);
+ }
+ }
+ p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
+ sec_index = rel_section_index;
+ }
+
+ p_blk = p_reloc->pr_first_block;
+
+ if (p_reloc->pr_block_count > 1) {
+ struct Dwarf_P_Relocation_Block_s *new_blk;
+
+ /* HACK , not normal interfaces, trashing p_reloc current
+ contents! */
+ _dwarf_reset_reloc_sect_info(p_reloc, ct);
+
+ /* Creating new single block for all 'ct' entries */
+ res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ new_blk = p_reloc->pr_first_block;
+
+ data = (Dwarf_Small *) new_blk->rb_data;
+
+ /* The following loop does the consolidation to a single
+ block and frees the input block(s). */
+ do {
+ unsigned long len =
+ p_blk->rb_where_to_add_next - p_blk->rb_data;
+ memcpy(data, p_blk->rb_data, len);
+ data += len;
+ p_blk_last = p_blk;
+ p_blk = p_blk->rb_next;
+ _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
+ } while (p_blk);
+ /* ASSERT: sum of len copied == total_size */
+ new_blk->rb_next_slot_to_use = ct;
+ new_blk->rb_where_to_add_next = (char *) data;
+ p_reloc->pr_reloc_total_count = ct;
+
+ /* Have now created a single block, but no change in slots
+ used (pr_reloc_total_count) */
+ }
+ }
+ *new_sec_count = 0;
+ return DW_DLV_OK;
+}