pro_reloc_stream.c [plain text]
#include "config.h"
#include "libdwarfdefs.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ELFACCESS_H
#include <elfaccess.h>
#else
#define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t))
#define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t))
#endif
#include "pro_incl.h"
#include "pro_section.h"
#include "pro_reloc.h"
#include "pro_reloc_stream.h"
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)
{
#if HAVE_ELF64_GETEHDR
Elf64_Rel *elf64_reloc;
void *relrec_to_fill;
int res;
int rel_type;
res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
&relrec_to_fill);
if (res != DW_DLV_OK)
return res;
if (type == dwarf_drt_data_reloc) {
if (reltarget_length == dbg->de_offset_size) {
rel_type = dbg->de_offset_reloc;
} else if (reltarget_length == dbg->de_pointer_size) {
rel_type = dbg->de_ptr_reloc;
} else {
return DW_DLV_ERROR;
}
} else if (type == dwarf_drt_segment_rel) {
rel_type = dbg->de_exc_reloc;
} else {
rel_type = 0;
}
elf64_reloc = (Elf64_Rel *) relrec_to_fill;
elf64_reloc->r_offset = offset;
Set_REL64_info(*elf64_reloc, symidx, rel_type);
return DW_DLV_OK;
#else
return DW_DLV_ERROR;
#endif
}
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)
{
Elf32_Rel *elf32_reloc;
void *relrec_to_fill;
int res;
int rel_type;
res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
&relrec_to_fill);
if (res != DW_DLV_OK)
return res;
if (type == dwarf_drt_data_reloc) {
if (reltarget_length == dbg->de_offset_size) {
rel_type = dbg->de_offset_reloc;
} else if (reltarget_length == dbg->de_pointer_size) {
rel_type = dbg->de_ptr_reloc;
} else {
return DW_DLV_ERROR;
}
} else if (type == dwarf_drt_segment_rel) {
rel_type = dbg->de_exc_reloc;
} else {
rel_type = 0;
}
elf32_reloc = (Elf32_Rel *) relrec_to_fill;
elf32_reloc->r_offset = (Elf32_Addr) offset;
Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type);
return DW_DLV_OK;
}
int
_dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset,
Dwarf_Unsigned start_symidx,
Dwarf_Unsigned end_symidx,
enum Dwarf_Rel_Type type,
int reltarget_length)
{
return DW_DLV_OK;
}
int
_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
Dwarf_Signed * new_sec_count)
{
unsigned long total_size = 0;
Dwarf_Small *data;
int sec_index;
unsigned long i;
Dwarf_Error err;
Dwarf_Error *error = &err;
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;
unsigned len;
struct Dwarf_P_Relocation_Block_s *p_blk;
struct Dwarf_P_Relocation_Block_s *p_blk_last;
Dwarf_P_Per_Reloc_Sect prb;
if (ct == 0) {
continue;
}
prb = &dbg->de_reloc_sect[i];
len = dbg->de_relocation_record_size;
++sec_count;
total_size = ct * len;
sec_index = prb->pr_sect_num_of_reloc_sect;
if (sec_index == 0) {
int rel_section_index;
Dwarf_Unsigned name_idx;
int int_name;
int err;
if (dbg->de_func_b) {
rel_section_index =
dbg->de_func_b(_dwarf_rel_section_names[i],
dbg->de_relocation_record_size,
SHT_REL,
0,
0,
dbg->de_elf_sects[i],
&name_idx, &err);
} else {
rel_section_index =
dbg->de_func(_dwarf_rel_section_names[i],
dbg->de_relocation_record_size,
SHT_REL,
0,
0,
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);
}
}
prb->pr_sect_num_of_reloc_sect = rel_section_index;
sec_index = rel_section_index;
}
GET_CHUNK(dbg, sec_index, data, total_size, &err);
p_blk = p_reloc->pr_first_block;
while (p_blk) {
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);
}
p_reloc->pr_first_block = 0;
p_reloc->pr_last_block = 0;
}
*new_sec_count = sec_count;
return DW_DLV_OK;
}