#include "config.h"
#ifdef DWARF_WITH_LIBELF
#include "libdwarfdefs.h"
#include <stdio.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
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
#include "pro_incl.h"
#include "dwarf.h"
#include "libdwarf.h"
#include "pro_opaque.h"
#include "pro_error.h"
#include "pro_alloc.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
REL64 *elf64_reloc = 0;
void *relrec_to_fill = 0;
int res = 0;
int rel_type = 0;
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_dwarf_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 = (REL64 *)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)
{
REL32 *elf32_reloc = 0;
void *relrec_to_fill = 0;
int res = 0;
int rel_type = 0;
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_dwarf_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 = (REL32*)relrec_to_fill;
elf32_reloc->r_offset = (Elf32_Addr) offset;
Set_REL32_info(*elf32_reloc, symidx, rel_type);
return DW_DLV_OK;
}
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)
{
return DW_DLV_OK;
}
int
_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
Dwarf_Signed * new_sec_count)
{
unsigned long total_size = 0;
int i = 0;
Dwarf_Error erre = 0;
Dwarf_Error *error = &erre;
Dwarf_Signed sec_count = 0;
for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
Dwarf_P_Per_Reloc_Sect p_reloc = dbg->de_reloc_sect +i;
Dwarf_Small *data = 0;
int sec_index = 0;
unsigned long ct = p_reloc->pr_reloc_total_count;
unsigned len = 0;
struct Dwarf_P_Relocation_Block_s *p_blk = 0;
struct Dwarf_P_Relocation_Block_s *p_blk_last = 0;
Dwarf_P_Per_Reloc_Sect prb = 0;
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 = 0;
Dwarf_Unsigned name_idx = 0;
int erri = 0;
if (dbg->de_callback_func) {
rel_section_index =
dbg->de_callback_func(_dwarf_rel_section_names[i],
dbg->de_relocation_record_size,
SHT_REL,
0,
0,
dbg->de_elf_sects[i],
&name_idx,
dbg->de_user_data,
&erri);
}
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, &erri);
p_blk = p_reloc->pr_first_block;
while (p_blk) {
unsigned long lenk =
p_blk->rb_where_to_add_next - p_blk->rb_data;
memcpy(data, p_blk->rb_data, lenk);
data += lenk;
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;
}
#else
int dwarf_dummy_pro_reloc_stream = 2;
#endif