#include "config.h"
#include "libdwarfdefs.h"
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_ELFACCESS_H
#include <elfaccess.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif /* HAVE_MALLOC_H */
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif /* HAVE_STDDEF_H */
#include "pro_incl.h"
#include "dwarf.h"
#include "libdwarf.h"
#include "pro_opaque.h"
#include "pro_error.h"
#include "pro_util.h"
#include "pro_encode_nm.h"
#include "pro_alloc.h"
#include "pro_section.h"
#include "pro_line.h"
#include "pro_frame.h"
#include "pro_die.h"
#include "pro_macinfo.h"
#include "pro_types.h"
#include "pro_dnames.h"
#ifndef SHN_UNDEF
#define SHN_UNDEF 0
#endif /* SHN_UNDEF */
#ifndef SHF_MIPS_NOSTRIP
#define SHF_MIPS_NOSTRIP 0
#endif
#ifndef R_MIPS_NONE
#define R_MIPS_NONE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef WORDS_BIGENDIAN
#define ASNOUT(t,s,l) \
do
{ \
unsigned sbyte = 0; \
const
char
*p = 0; \
if
(l >
sizeof
(s)) { \
_dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
return
DW_DLV_ERROR; \
} \
sbyte =
sizeof
(s) - l; \
p = (
const
char
*)(&s); \
dbg->de_copy_word(t,(
const
void
*)(p+sbyte),l);\
}
while
(0)
#else /* LITTLEENDIAN */
#define ASNOUT(t,s,l) \
do
{ \
const
char
*p = 0; \
if
(l >
sizeof
(s)) { \
_dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
return
DW_DLV_ERROR; \
} \
p = (
const
char
*)(&s); \
dbg->de_copy_word(t,(
const
void
*)p,l); \
}
while
(0)
#endif /* ENDIANNESS */
#define SIZEOFT32 4
struct
Dwarf_Sort_Abbrev_s {
Dwarf_Unsigned dsa_attr;
Dwarf_Unsigned dsa_form;
Dwarf_Signed dsa_implicitvalue;
Dwarf_P_Attribute dsa_attrp;
};
const
char
*_dwarf_rel_section_names[] = {
REL_SEC_PREFIX
".debug_info"
,
REL_SEC_PREFIX
".debug_line"
,
REL_SEC_PREFIX
".debug_abbrev"
,
REL_SEC_PREFIX
".debug_frame"
,
REL_SEC_PREFIX
".debug_aranges"
,
REL_SEC_PREFIX
".debug_pubnames"
,
REL_SEC_PREFIX
".debug_funcnames"
,
REL_SEC_PREFIX
".debug_typenames"
,
REL_SEC_PREFIX
".debug_varnames"
,
REL_SEC_PREFIX
".debug_weaknames"
,
REL_SEC_PREFIX
".debug_macinfo"
,
REL_SEC_PREFIX
".debug_loc"
,
REL_SEC_PREFIX
".debug_ranges"
,
REL_SEC_PREFIX
".debug_types"
,
REL_SEC_PREFIX
".debug_pubtypes"
,
REL_SEC_PREFIX
".debug_names"
,
REL_SEC_PREFIX
".debug_str"
,
REL_SEC_PREFIX
".debug_rnglists"
,
REL_SEC_PREFIX
".debug_line_str"
,
REL_SEC_PREFIX
".debug_macro"
,
REL_SEC_PREFIX
".debug_loclists"
,
REL_SEC_PREFIX
".debug_rnglists"
,
};
const
char
*_dwarf_sectnames[] = {
".debug_info"
,
".debug_line"
,
".debug_abbrev"
,
".debug_frame"
,
".debug_aranges"
,
".debug_pubnames"
,
".debug_funcnames"
,
".debug_typenames"
,
".debug_varnames"
,
".debug_weaknames"
,
".debug_macinfo"
,
".debug_loc"
,
".debug_ranges"
,
".debug_types"
,
".debug_pubtypes"
,
".debug_names"
,
".debug_str"
,
".debug_line_str"
,
".debug_macro"
,
".debug_loclists"
,
".debug_rnglists"
,
};
static
const
Dwarf_Ubyte std_opcode_len[] = { 0,
1,
1,
1,
1,
0,
0,
0,
1,
0,
0,
1,
};
typedef
struct
Dwarf_P_Rel_s *Dwarf_P_Rel;
struct
Dwarf_P_Rel_s {
Dwarf_P_Rel dr_next;
void
*dr_rel_datap;
};
typedef
struct
Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head;
struct
Dwarf_P_Rel_Head_s {
struct
Dwarf_P_Rel_s *drh_head;
struct
Dwarf_P_Rel_s *drh_tail;
};
static
int
_dwarf_pro_generate_debug_line_str(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
static
int
_dwarf_pro_generate_debug_names(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
static
int
_dwarf_pro_generate_debug_str(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
static
int
_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
static
int
_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
static
int
_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs, Dwarf_Error * error);
#if 0
static
void
dump_bytes(
char
* msg,Dwarf_Small * start,
long
len)
{
Dwarf_Small *end = start + len;
Dwarf_Small *cur = start;
printf
(
"%s len %ld "
,msg,len);
for
(; cur < end; cur++) {
printf
(
"%02x "
, *cur);
}
printf
(
"\n"
);
}
#endif
#if 0
static
void
print_single_abbrev(Dwarf_P_Abbrev c, unsigned idx)
{
unsigned j = 0;
printf
(
" %2u idx %2u tag 0x%x attrct %2u\n"
,idx,
(unsigned)c->abb_idx,
(unsigned)c->abb_tag,
(unsigned)c->abb_n_attr);
for
( ; j < (unsigned)c->abb_n_attr; ++j) {
printf
(
" %2u attr 0x%2x form 0x%2x impl val %"
DW_PR_DSd
"\n"
,
j,
(unsigned)c->abb_attrs[j],
(unsigned)c->abb_forms[j]);
(unsigned)c->abb_implicits[j]);
}
}
static
void
print_curabbrev(
const
char
*where,
Dwarf_P_Abbrev curabbrev)
{
Dwarf_P_Abbrev ca = 0;
unsigned i = 0;
for
(ca = curabbrev; ca ; ca = ca->abb_next,++i) {
printf
(
"ABBREV %u from %s\n"
,i,where);
print_single_abbrev(ca,i);
}
}
#endif
#define OPC_INCS_ZERO -1
#define OPC_OUT_OF_RANGE -2
#define LINE_OUT_OF_RANGE -3
static
int
_dwarf_pro_get_opc(
struct
Dwarf_P_Line_Inits_s *inits,
Dwarf_Unsigned addr_adv,
int
line_adv)
{
int
line_base = inits->pi_line_base;
int
line_range =inits->pi_line_range;
Dwarf_Unsigned factored_adv = 0;
factored_adv = addr_adv / inits->pi_minimum_instruction_length;
if
(line_adv == 0 && factored_adv == 0) {
return
OPC_INCS_ZERO;
}
if
(line_adv >= line_base && line_adv < line_base + line_range) {
int
opc = 0;
opc = (line_adv - line_base) +
(factored_adv * line_range) +
inits->pi_opcode_base;
if
(opc > 255) {
return
OPC_OUT_OF_RANGE;
}
return
opc;
}
return
LINE_OUT_OF_RANGE;
}
#define OFFSET_PLUS_EXTENSION_SIZE (offset_size + extension_size)
static
int
dwarf_need_debug_line_section(Dwarf_P_Debug dbg)
{
if
(dbg->de_output_version > 4) {
return
FALSE;
}
if
(dbg->de_lines == NULL && dbg->de_file_entries == NULL
&& dbg->de_inc_dirs == NULL) {
return
FALSE;
}
return
TRUE;
}
static
int
dwarf_need_debug_names_section(Dwarf_P_Debug dbg)
{
if
(dbg->de_output_version < 5) {
return
FALSE;
}
if
(!dbg->de_dnames) {
return
FALSE;
}
if
(!dbg->de_dnames->dn_create_section) {
return
FALSE;
}
return
TRUE;
}
Dwarf_Signed
dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
Dwarf_Signed count = 0;
int
res = 0;
res = dwarf_transform_to_disk_form_a(dbg, &count,error);
if
(res == DW_DLV_ERROR) {
return
DW_DLV_NOCOUNT;
}
return
count;
}
int
dwarf_transform_to_disk_form_a(Dwarf_P_Debug dbg, Dwarf_Signed *count,
Dwarf_Error * error)
{
Dwarf_Signed nbufs = 0;
int
sect = 0;
int
err = 0;
Dwarf_Unsigned du = 0;
if
(dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_ERROR);
}
for
(sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) {
long
flags = 0;
switch
(sect) {
case
DEBUG_INFO:
if
(dbg->de_dies == NULL) {
continue
;
}
break
;
case
DEBUG_LINE:
if
(dwarf_need_debug_line_section(dbg) == FALSE) {
continue
;
}
break
;
case
DEBUG_ABBREV:
if
(dbg->de_dies == NULL) {
continue
;
}
break
;
case
DEBUG_FRAME:
if
(dbg->de_frame_cies == NULL) {
continue
;
}
flags = SHF_MIPS_NOSTRIP;
break
;
case
DEBUG_ARANGES:
if
(dbg->de_arange == NULL) {
continue
;
}
break
;
case
DEBUG_PUBNAMES:
if
(dbg->de_simple_name_headers[dwarf_snk_pubname].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_PUBTYPES:
if
(dbg->de_simple_name_headers[dwarf_snk_pubtype].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_STR:
if
(dbg->de_debug_str->ds_data == NULL) {
continue
;
}
break
;
case
DEBUG_FUNCNAMES:
if
(dbg->de_simple_name_headers[dwarf_snk_funcname].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_TYPENAMES:
if
(dbg->de_simple_name_headers[dwarf_snk_typename].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_VARNAMES:
if
(dbg->de_simple_name_headers[dwarf_snk_varname].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_WEAKNAMES:
if
(dbg->de_simple_name_headers[dwarf_snk_weakname].
sn_head == NULL) {
continue
;
}
break
;
case
DEBUG_MACINFO:
if
(dbg->de_first_macinfo == NULL) {
continue
;
}
break
;
case
DEBUG_NAMES:
if
(dwarf_need_debug_names_section(dbg) == FALSE) {
continue
;
}
break
;
case
DEBUG_LOC:
continue
;
case
DEBUG_RANGES:
continue
;
case
DEBUG_TYPES:
continue
;
case
DEBUG_MACRO:
continue
;
case
DEBUG_LOCLISTS:
continue
;
case
DEBUG_RNGLISTS:
continue
;
case
DEBUG_LINE_STR:
if
(dwarf_need_debug_line_section(dbg) == FALSE) {
continue
;
}
continue
;
default
:
DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_ERROR);
}
{
int
new_base_elf_sect = 0;
if
(dbg->de_callback_func) {
new_base_elf_sect =
dbg->de_callback_func(_dwarf_sectnames[sect],
1,
SECTION_TYPE,
flags, SHN_UNDEF, 0, &du,
dbg->de_user_data, &err);
}
if
(new_base_elf_sect == -1) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR,
DW_DLV_ERROR);
}
dbg->de_elf_sects[sect] = new_base_elf_sect;
dbg->de_sect_name_idx[sect] = du;
}
}
nbufs = 0;
if
(dwarf_need_debug_line_section(dbg) == TRUE) {
int
res = _dwarf_pro_generate_debugline(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_frame_cies) {
int
res = _dwarf_pro_generate_debugframe(dbg,&nbufs,error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_first_macinfo) {
int
res = _dwarf_pro_transform_macro_info_to_disk(dbg,
&nbufs,error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_dies) {
int
res= _dwarf_pro_generate_debuginfo(dbg, &nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_debug_str->ds_data) {
int
res = _dwarf_pro_generate_debug_str(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_debug_line_str->ds_data) {
int
res = _dwarf_pro_generate_debug_line_str(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_arange) {
int
res = _dwarf_transform_arange_to_disk(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_output_version < 5) {
if
(dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_pubname,
DEBUG_PUBNAMES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_simple_name_headers[dwarf_snk_pubtype].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_pubtype,
DEBUG_PUBTYPES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_funcname,
DEBUG_FUNCNAMES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_typename,
DEBUG_TYPENAMES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_varname,
DEBUG_VARNAMES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) {
int
res = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_weakname, DEBUG_WEAKNAMES,
&nbufs,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
}
if
(dwarf_need_debug_names_section(dbg) == TRUE) {
int
res = _dwarf_pro_generate_debug_names(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
#if 0 /* FIXME: TODO new sections */
if
(dwarf_need_debug_macro_section(dbg) == TRUE) {
int
res = _dwarf_pro_generate_debug_macro(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dwarf_need_debug_loclists_section(dbg) == TRUE) {
int
res = _dwarf_pro_generate_debug_loclists(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
if
(dwarf_need_debug_rnglists_section(dbg) == TRUE) {
int
res = _dwarf_pro_generate_debug_rnglists(dbg,&nbufs, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
}
#endif
{
Dwarf_Signed new_chunks = 0;
int
res = 0;
res = dbg->de_transform_relocs_to_disk(dbg, &new_chunks);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_RELOCS_ERROR,
DW_DLV_ERROR);
}
nbufs += new_chunks;
}
*count = nbufs;
return
DW_DLV_OK;
}
static
int
write_fixed_size(Dwarf_Unsigned val,
Dwarf_P_Debug dbg,
int
elfsectno,
Dwarf_Unsigned size,
unsigned * size_out,
Dwarf_Error* error)
{
unsigned
char
*data = 0;
GET_CHUNK_ERR(dbg, elfsectno, data, size, error);
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &val,
sizeof
(val), size);
*size_out = size;
return
DW_DLV_OK;
}
static
int
write_ubyte(unsigned val,
Dwarf_P_Debug dbg,
int
elfsectno,
unsigned *len_out,
Dwarf_Error* error)
{
Dwarf_Ubyte db = val;
unsigned
char
*data = 0;
unsigned len =
sizeof
(Dwarf_Ubyte);
GET_CHUNK_ERR(dbg, elfsectno, data,
len, error);
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db), len);
*len_out = 1;
return
DW_DLV_OK;;
}
static
int
pretend_write_uval(Dwarf_Unsigned val,
Dwarf_P_Debug dbg,
unsigned *uval_len_out,
Dwarf_Error* error)
{
char
buff1[ENCODE_SPACE_NEEDED];
int
nbytes = 0;
int
res = 0;
res = _dwarf_pro_encode_leb128_nm(val,
&nbytes, buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg,DW_DLE_LEB_OUT_ERROR , DW_DLV_ERROR);
}
*uval_len_out = nbytes;
return
DW_DLV_OK;
}
static
int
write_sval(Dwarf_Signed val,
Dwarf_P_Debug dbg,
int
elfsectno,
unsigned *sval_len_out,
Dwarf_Error* error)
{
char
buff1[ENCODE_SPACE_NEEDED];
unsigned
char
*data = 0;
int
nbytes = 0;
int
res = _dwarf_pro_encode_signed_leb128_nm(val,
&nbytes, buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR);
}
GET_CHUNK(dbg, elfsectno, data, nbytes, error);
memcpy
((
void
*) data, (
const
void
*) buff1, nbytes);
*sval_len_out = nbytes;
return
DW_DLV_OK;
}
static
int
append_uval(Dwarf_Unsigned val,
Dwarf_P_Debug dbg,
unsigned
char
*data,
unsigned * uval_len_out,
Dwarf_Error* error)
{
char
buff1[ENCODE_SPACE_NEEDED];
int
nbytes = 0;
int
res = _dwarf_pro_encode_leb128_nm(val,
&nbytes, buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR);
}
memcpy
((
void
*) data, (
const
void
*) buff1, nbytes);
*uval_len_out = nbytes;
return
DW_DLV_OK;
}
static
int
write_uval(Dwarf_Unsigned val,
Dwarf_P_Debug dbg,
int
elfsectno,
unsigned * uval_len_out,
Dwarf_Error* error)
{
char
buff1[ENCODE_SPACE_NEEDED];
unsigned
char
*data = 0;
int
nbytes = 0;
int
res = _dwarf_pro_encode_leb128_nm(val,
&nbytes, buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR);
}
GET_CHUNK_ERR(dbg, elfsectno, data, nbytes, error);
memcpy
((
void
*) data, (
const
void
*) buff1, nbytes);
*uval_len_out = nbytes;
return
DW_DLV_OK;
}
static
unsigned
write_opcode_uval(
int
opcode,
Dwarf_P_Debug dbg,
int
elfsectno,
Dwarf_Unsigned val,
unsigned *len_out,
Dwarf_Error* error)
{
unsigned ublen = 0;
int
res = 0;
unsigned uvlen = 0;
res = write_ubyte(opcode,dbg,elfsectno,&ublen,error);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR);
}
res = write_uval(val,dbg,elfsectno,&uvlen,error);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LEB_OUT_ERROR, DW_DLV_ERROR);
}
*len_out = ublen +uvlen;
return
DW_DLV_OK;
}
static
int
determine_form_size(Dwarf_P_Debug dbg,
unsigned format_count,
struct
Dwarf_P_Line_format_s *format,
unsigned *size_out,
Dwarf_Bool write_out,
unsigned
char
*data,
Dwarf_Error *error)
{
unsigned calculated_size = 0;
unsigned n = 0;
int
res = 0;
calculated_size += sizeof_ubyte(dbg);
for
(n = 0; n < format_count; ++n) {
struct
Dwarf_P_Line_format_s *lf = format+n;
unsigned val_len = 0;
unsigned val_len2 = 0;
if
(write_out) {
res = append_uval(lf->def_content_type, dbg,
data,
&val_len,error);
}
else
{
res = pretend_write_uval(lf->def_content_type, dbg,
&val_len,error);
}
data += val_len;
if
(res != DW_DLV_OK) {
return
res;
}
if
(write_out) {
res = append_uval(lf->def_form_code, dbg,
data,
&val_len2,error);
}
else
{
res = pretend_write_uval(lf->def_form_code, dbg,
&val_len2,error);
}
if
(res != DW_DLV_OK) {
return
res;
}
data += val_len2;
calculated_size += val_len + val_len2;
}
*size_out = calculated_size;
return
DW_DLV_OK;
}
static
int
determine_file_content_size(Dwarf_P_Debug dbg,
Dwarf_P_F_Entry entry_list,
Dwarf_Unsigned format_count,
struct
Dwarf_P_Line_format_s *format,
unsigned *size_out,
Dwarf_Bool write_out,
unsigned
char
*data,
Dwarf_Error *error)
{
unsigned calculated_size = 0;
unsigned count_len = 0;
Dwarf_P_F_Entry cur = 0;
Dwarf_P_F_Entry nxt = 0;
unsigned n = 0;
int
res = 0;
Dwarf_Unsigned offset_size = 0;
offset_size = dbg->de_dwarf_offset_size;
res = pretend_write_uval(format_count,dbg,
&count_len,error);
if
(res != DW_DLV_OK) {
return
res;
}
calculated_size += count_len;
cur = entry_list;
for
(n = 0; cur; n++,cur = nxt) {
unsigned f = 0;
nxt = cur->dfe_next;
for
( ; f < format_count; f++) {
struct
Dwarf_P_Line_format_s *lf = format+f;
unsigned ctype = lf->def_content_type;
unsigned cform = lf->def_form_code;
switch
(ctype) {
case
DW_LNCT_path: {
switch
(cform) {
case
DW_FORM_string: {
unsigned slen =
strlen
(cur->dfe_name) +1;
calculated_size += slen;
if
(write_out) {
strcpy
((
char
*)data, cur->dfe_name);
data += slen;
}
}
break
;
case
DW_FORM_strp: {
unsigned slen =
strlen
(cur->dfe_name) +1;
if
(write_out) {
Dwarf_Unsigned stroffset = 0;
res = _dwarf_insert_or_find_in_debug_str(
dbg,
cur->dfe_name,
_dwarf_hash_debug_str,
slen,
&stroffset,error);
if
(res != DW_DLV_OK) {
return
res;
}
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &stroffset,
sizeof
(stroffset), offset_size);
data += offset_size;
}
calculated_size += offset_size;
}
break
;
case
DW_FORM_line_strp: {
unsigned slen =
strlen
(cur->dfe_name) +1;
if
(write_out) {
Dwarf_Unsigned stroffset = 0;
res = _dwarf_insert_or_find_in_debug_str(
dbg,
cur->dfe_name,
_dwarf_hash_debug_line_str,
slen,
&stroffset,error);
if
(res != DW_DLV_OK) {
return
res;
}
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &stroffset,
sizeof
(stroffset), offset_size);
data += offset_size;
}
calculated_size += offset_size;
}
break
;
case
DW_FORM_strp_sup:
case
DW_FORM_strx:
case
DW_FORM_strx1:
case
DW_FORM_strx2:
case
DW_FORM_strx3:
case
DW_FORM_strx4:
default
:
DWARF_P_DBG_ERROR(dbg,
DW_DLE_LNCT_FORM_CODE_NOT_HANDLED, DW_DLV_ERROR);
break
;
}
}
break
;
case
DW_LNCT_directory_index: {
switch
(cform) {
case
DW_FORM_data1:
calculated_size += 1;
if
(write_out) {
unsigned
char
ub = cur->dfe_index;
*data = ub;
data += 1;
}
break
;
case
DW_FORM_data2:
calculated_size += DWARF_HALF_SIZE;
if
(write_out) {
Dwarf_Half uh = cur->dfe_index;
memcpy
(data,&uh,DWARF_HALF_SIZE);
data += DWARF_HALF_SIZE;
}
break
;
case
DW_FORM_udata: {
unsigned val_len = 0;
if
(write_out) {
res = append_uval(cur->dfe_index,
dbg,
data,
&val_len,error);
data += val_len;
}
else
{
res = pretend_write_uval(cur->dfe_index,
dbg, &val_len,error);
}
if
(res != DW_DLV_OK) {
return
res;
}
calculated_size += val_len;
}
break
;
default
:
DWARF_P_DBG_ERROR(dbg,
DW_DLE_LNCT_FORM_CODE_NOT_HANDLED, DW_DLV_ERROR);
}
}
break
;
case
DW_LNCT_timestamp: {
switch
(cform) {
case
DW_FORM_udata: {
unsigned val_len = 0;
if
(write_out) {
res = append_uval(cur->dfe_timestamp,
dbg,
data,
&val_len,error);
data += val_len;
}
else
{
res = pretend_write_uval(cur->dfe_timestamp,
dbg, &val_len,error);
}
if
(res != DW_DLV_OK) {
return
res;
}
calculated_size += val_len;
}
break
;
case
DW_FORM_data4: {
calculated_size += DWARF_32BIT_SIZE;
if
(write_out) {
ASNOUT(data,cur->dfe_timestamp,
DWARF_32BIT_SIZE);
data += DWARF_32BIT_SIZE;
}
}
break
;
case
DW_FORM_data8:
calculated_size += DWARF_64BIT_SIZE;
if
(write_out) {
Dwarf_Unsigned u8 = cur->dfe_index;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &u8,
sizeof
(u8), DWARF_64BIT_SIZE);
data += DWARF_64BIT_SIZE;
}
break
;
case
DW_FORM_block:
default
:
DWARF_P_DBG_ERROR(dbg,
DW_DLE_LNCT_FORM_CODE_NOT_HANDLED, DW_DLV_ERROR);
}
}
break
;
case
DW_LNCT_size: {
switch
(cform) {
case
DW_FORM_data1:
calculated_size += 1;
if
(write_out) {
unsigned
char
ub = cur->dfe_index;
*data = ub;
data += 1;
}
break
;
case
DW_FORM_data2:
calculated_size += DWARF_HALF_SIZE;
if
(write_out) {
Dwarf_Half uh = cur->dfe_index;
memcpy
(data,&uh,DWARF_HALF_SIZE);
}
break
;
case
DW_FORM_data4:
calculated_size += DWARF_32BIT_SIZE;
if
(write_out) {
ASNOUT(data,cur->dfe_index,
DWARF_32BIT_SIZE);
data += DWARF_32BIT_SIZE;
}
break
;
case
DW_FORM_data8:
calculated_size += DWARF_64BIT_SIZE;
if
(write_out) {
Dwarf_Unsigned u8 = cur->dfe_index;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &u8,
sizeof
(u8), DWARF_64BIT_SIZE);
data += DWARF_64BIT_SIZE;
}
break
;
case
DW_FORM_udata: {
unsigned val_len = 0;
if
(write_out) {
res = append_uval(cur->dfe_size,
dbg,
data,
&val_len,error);
data += val_len;
}
else
{
res = pretend_write_uval(cur->dfe_size,
dbg, &val_len,error);
}
if
(res != DW_DLV_OK) {
return
res;
}
calculated_size += val_len;
}
break
;
default
:
DWARF_P_DBG_ERROR(dbg,
DW_DLE_LNCT_FORM_CODE_NOT_HANDLED, DW_DLV_ERROR);
}
}
break
;
case
DW_LNCT_MD5: {
switch
(cform) {
case
DW_FORM_data16:
if
(write_out) {
memcpy
(data,cur->dfe_md5,
sizeof
(cur->dfe_md5));
data += 16;
}
calculated_size += 16;
break
;
default
:
DWARF_P_DBG_ERROR(dbg,
DW_DLE_LNCT_FORM_CODE_NOT_HANDLED, DW_DLV_ERROR);
}
}
break
;
default
:
DWARF_P_DBG_ERROR(dbg, DW_DLE_LNCT_CODE_UNKNOWN, DW_DLV_ERROR);
}
}
}
*size_out = calculated_size;
return
DW_DLV_OK;
}
static
int
calculate_size_of_line_header5(Dwarf_P_Debug dbg,
struct
Dwarf_P_Line_Inits_s *inits,
unsigned *prolog_size_out,
Dwarf_Error *error)
{
unsigned prolog_size = 0;
int
offset_size = dbg->de_dwarf_offset_size;
int
extension_size = dbg->de_64bit_extension ? 4 : 0;
int
res = 0;
prolog_size += OFFSET_PLUS_EXTENSION_SIZE +
sizeof_uhalf(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
offset_size +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg);
prolog_size += sizeof_ubyte(dbg);
prolog_size += inits->pi_opcode_base-1;
{
unsigned fsize = 0;
res = determine_form_size(dbg,
inits->pi_directory_entry_format_count,
inits->pi_incformats,
&fsize,FALSE,0,error);
if
(res != DW_DLV_OK) {
return
res;
}
prolog_size += fsize;
}
{
unsigned dir_count_len = 0;
res = determine_file_content_size(dbg,
dbg->de_inc_dirs,
dbg->de_line_inits.pi_directory_entry_format_count,
dbg->de_line_inits.pi_incformats,
&dir_count_len,
FALSE,0,
error);
if
(res != DW_DLV_OK) {
return
res;
}
prolog_size += dir_count_len;
}
{
unsigned fsize = 0;
res = determine_form_size(dbg,
inits->pi_file_entry_format_count,
inits->pi_fileformats,
&fsize,
FALSE,0,
error);
if
(res != DW_DLV_OK) {
return
res;
}
prolog_size += fsize;
}
{
unsigned file_count_len = 0;
res = determine_file_content_size(dbg,
dbg->de_file_entries,
dbg->de_line_inits.pi_file_entry_format_count,
dbg->de_line_inits.pi_fileformats,
&file_count_len,
FALSE,0,
error);
if
(res != DW_DLV_OK) {
return
res;
}
prolog_size += file_count_len;
}
*prolog_size_out = prolog_size;
return
DW_DLV_OK;
}
static
int
calculate_size_of_line_header4(Dwarf_P_Debug dbg,
struct
Dwarf_P_Line_Inits_s *inits,
unsigned *prolog_size_out,
UNUSEDARG Dwarf_Error *error)
{
Dwarf_P_F_Entry curdir = 0;
Dwarf_P_F_Entry curentry = 0;
unsigned prolog_size = 0;
int
offset_size = dbg->de_dwarf_offset_size;
int
extension_size = dbg->de_64bit_extension ? 4 : 0;
prolog_size += OFFSET_PLUS_EXTENSION_SIZE +
sizeof_uhalf(dbg) +
offset_size +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg);
if
(inits->pi_linetable_version == DW_LINE_VERSION4) {
prolog_size += sizeof_ubyte(dbg);
}
prolog_size += inits->pi_opcode_base-1;
curdir = dbg->de_inc_dirs;
while
(curdir) {
prolog_size +=
strlen
(curdir->dfe_name) + 1;
curdir = curdir->dfe_next;
}
prolog_size++;
curentry = dbg->de_file_entries;
while
(curentry) {
prolog_size +=
strlen
(curentry->dfe_name) + 1 + curentry->dfe_nbytes;
curentry = curentry->dfe_next;
}
prolog_size++;
*prolog_size_out = prolog_size;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
Dwarf_Signed * nbufs,
Dwarf_Error * error)
{
Dwarf_P_F_Entry curdir = 0;
Dwarf_P_F_Entry curentry = 0;
Dwarf_P_Line curline = 0;
Dwarf_P_Line prevline = 0;
struct
Dwarf_P_Line_Inits_s *inits = 0;
int
sum_bytes = 0;
unsigned prolog_size = 0;
unsigned
char
*data = 0;
int
elfsectno = 0;
unsigned
char
*start_line_sec = 0;
Dwarf_Unsigned du = 0;
Dwarf_Ubyte db = 0;
Dwarf_Half dh = 0;
int
res = 0;
Dwarf_Half version = dbg->de_output_version;
int
offset_size = dbg->de_dwarf_offset_size;
Dwarf_Ubyte extension_size = dbg->de_64bit_extension ? 4 : 0;
Dwarf_Ubyte address_size = dbg->de_pointer_size;
sum_bytes = 0;
elfsectno = dbg->de_elf_sects[DEBUG_LINE];
inits = &dbg->de_line_inits;
if
(version < 5) {
res = calculate_size_of_line_header4(dbg,inits,&prolog_size,
error);
}
else
if
(version == 5) {
res = calculate_size_of_line_header5(dbg,inits,&prolog_size,
error);
}
else
{
_dwarf_p_error(dbg, error,DW_DLE_VERSION_STAMP_ERROR );
return
DW_DLV_ERROR;
}
if
(res != DW_DLV_OK) {
return
res;
}
GET_CHUNK_ERR(dbg, elfsectno, data, prolog_size, error);
start_line_sec = data;
du = 0;
if
(extension_size) {
DISTINGUISHED_VALUE_ARRAY(v4);
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &v4[0],
SIZEOFT32, extension_size);
data += extension_size;
}
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
dh = inits->pi_linetable_version;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &dh,
sizeof
(dh), DWARF_HALF_SIZE);
data += DWARF_HALF_SIZE;
if
(version == 5 ) {
db = inits->pi_address_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(db));
data +=
sizeof
(db);
db = inits->pi_segment_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(db));
data +=
sizeof
(db);
}
{
Dwarf_Unsigned sofar = data - start_line_sec;
du = prolog_size - sofar - offset_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
}
db = inits->pi_minimum_instruction_length;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
if
(inits->pi_linetable_version == 4 ||
inits->pi_linetable_version == 5) {
db = inits->pi_maximum_operations_per_instruction;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
}
db = inits->pi_default_is_stmt;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
db = inits->pi_line_base;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
db = inits->pi_line_range;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
db = inits->pi_opcode_base;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) std_opcode_len,
inits->pi_opcode_base-1,
inits->pi_opcode_base-1);
data += inits->pi_opcode_base-1;
if
(version < 5) {
curdir = dbg->de_inc_dirs;
while
(curdir) {
strcpy
((
char
*) data, curdir->dfe_name);
data +=
strlen
(curdir->dfe_name) + 1;
curdir = curdir->dfe_next;
}
*data =
'\0'
;
data++;
curentry = dbg->de_file_entries;
while
(curentry) {
strcpy
((
char
*) data, curentry->dfe_name);
data +=
strlen
(curentry->dfe_name) + 1;
memcpy
((
void
*) data,
(
const
void
*) curentry->dfe_args, curentry->dfe_nbytes);
data += curentry->dfe_nbytes;
curentry = curentry->dfe_next;
}
*data =
'\0'
;
data++;
}
else
if
(version == 5) {
{
unsigned fsize = 0;
res = determine_form_size(dbg,
inits->pi_directory_entry_format_count,
inits->pi_incformats,
&fsize,
TRUE,data,
error);
if
(res != DW_DLV_OK) {
return
res;
}
data += fsize;
}
{
unsigned dir_count_len = 0;
res = determine_file_content_size(dbg,
dbg->de_inc_dirs,
inits->pi_directory_entry_format_count,
inits->pi_incformats,
&dir_count_len,
TRUE,data,
error);
if
(res != DW_DLV_OK) {
return
res;
}
data += dir_count_len;
}
{
unsigned fsize = 0;
res = determine_form_size(dbg,
inits->pi_file_entry_format_count,
inits->pi_fileformats,
&fsize,
TRUE,data,
error);
if
(res != DW_DLV_OK) {
return
res;
}
data += fsize;
}
{
unsigned file_count_len = 0;
res = determine_file_content_size(dbg,
dbg->de_file_entries,
dbg->de_line_inits.pi_file_entry_format_count,
dbg->de_line_inits.pi_fileformats,
&file_count_len,
TRUE,data,
error);
if
(res != DW_DLV_OK) {
return
res;
}
data += file_count_len;
}
}
{
Dwarf_Unsigned sofar = data - start_line_sec;
if
(sofar != prolog_size) {
_dwarf_p_error(dbg, error,
DW_DLE_LINE_HEADER_LENGTH_BOTCH);
return
DW_DLV_ERROR;
}
sum_bytes += prolog_size;
}
curline = dbg->de_lines;
prevline = (Dwarf_P_Line)
_dwarf_p_get_alloc(dbg,
sizeof
(
struct
Dwarf_P_Line_s));
if
(prevline == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_ERROR);
}
_dwarf_pro_reg_init(dbg,prevline);
while
(curline) {
int
opc = 0;
int
no_lns_copy = 0;
Dwarf_Unsigned addr_adv = 0;
int
line_adv = 0;
no_lns_copy = 0;
if
(curline->dpl_opc != 0) {
int
inst_bytes = 0;
unsigned writelen = 0;
switch
(curline->dpl_opc) {
case
DW_LNE_end_sequence:
addr_adv = curline->dpl_address - prevline->dpl_address;
if
(addr_adv > 0) {
res = write_opcode_uval(DW_LNS_advance_pc,dbg,
elfsectno,
addr_adv/inits->pi_minimum_instruction_length,
&writelen,
error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_address = curline->dpl_address;
}
db = 0;
res = write_ubyte(db,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
inst_bytes =
sizeof
(Dwarf_Ubyte);
res = write_uval(inst_bytes,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_ubyte(DW_LNE_end_sequence,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
_dwarf_pro_reg_init(dbg,prevline);
no_lns_copy = 1;
break
;
case
DW_LNE_set_address:
db = 0;
res = write_ubyte(db,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
inst_bytes =
sizeof
(Dwarf_Ubyte) + address_size;
res = write_uval(inst_bytes,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_ubyte(DW_LNE_set_address,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_LINE,
sum_bytes,
curline->dpl_r_symidx,
dwarf_drt_data_reloc,
offset_size);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, DW_DLV_ERROR);
}
du = curline->dpl_address;
res = write_fixed_size(du,dbg,elfsectno,
address_size,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_address = curline->dpl_address;
no_lns_copy = 1;
break
;
case
DW_LNE_define_file:
no_lns_copy = 1;
break
;
case
DW_LNE_set_discriminator: {
unsigned val_len = 0;
db = 0;
res = write_ubyte(db,dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = pretend_write_uval(curline->dpl_discriminator,
dbg, &val_len,error);
if
(res != DW_DLV_OK) {
return
res;
}
val_len++;
res = write_uval(val_len +1,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_ubyte(DW_LNE_set_discriminator,
dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_uval(curline->dpl_discriminator,
dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
no_lns_copy = 1;
}
break
;
}
}
else
{
unsigned writelen = 0;
if
(inits->pi_opcode_base >12) {
if
(curline->dpl_epilogue_begin) {
res = write_ubyte(DW_LNS_set_epilogue_begin,dbg,
elfsectno,&writelen, error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
}
if
(curline->dpl_prologue_end) {
res = write_ubyte(DW_LNS_set_prologue_end,dbg,
elfsectno, &writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
}
if
(curline->dpl_isa != prevline->dpl_isa) {
res = write_opcode_uval(DW_LNS_set_isa,dbg,
elfsectno, curline->dpl_isa,
&writelen ,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
}
}
if
(curline->dpl_file != prevline->dpl_file) {
db = DW_LNS_set_file;
res = write_opcode_uval(db,dbg,
elfsectno,
curline->dpl_file,&writelen ,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_file = curline->dpl_file;
}
if
(curline->dpl_column != prevline->dpl_column) {
db = DW_LNS_set_column;
res = write_opcode_uval(db,dbg,
elfsectno, curline->dpl_column , &writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_column = curline->dpl_column;
}
if
(curline->dpl_is_stmt != prevline->dpl_is_stmt) {
res = write_ubyte(DW_LNS_negate_stmt,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_is_stmt = curline->dpl_is_stmt;
}
if
(curline->dpl_basic_block ==
true
&&
prevline->dpl_basic_block ==
false
) {
res = write_ubyte(DW_LNS_set_basic_block,dbg,
elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_basic_block = curline->dpl_basic_block;
}
if
(curline->dpl_discriminator) {
unsigned val_len = 0;
db = 0;
res = write_ubyte(db,dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = pretend_write_uval(curline->dpl_discriminator,
dbg, &val_len,error);
if
(res != DW_DLV_OK) {
return
res;
}
val_len ++;
res = write_uval(val_len +1,dbg,elfsectno,
&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_ubyte(DW_LNE_set_discriminator,
dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_uval(curline->dpl_discriminator,
dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
}
addr_adv = curline->dpl_address - prevline->dpl_address;
line_adv = (
int
) (curline->dpl_line - prevline->dpl_line);
if
((addr_adv % MIN_INST_LENGTH) != 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, DW_DLV_ERROR);
}
opc = _dwarf_pro_get_opc(inits,addr_adv, line_adv);
if
(opc > 0) {
no_lns_copy = 1;
res = write_ubyte(opc,dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_basic_block =
false
;
prevline->dpl_address = curline->dpl_address;
prevline->dpl_line = curline->dpl_line;
}
else
{
if
(addr_adv > 0) {
db = DW_LNS_advance_pc;
res = write_opcode_uval(db,dbg,
elfsectno,
addr_adv/inits->pi_minimum_instruction_length,
&writelen,
error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_basic_block =
false
;
prevline->dpl_address = curline->dpl_address;
}
if
(line_adv != 0) {
db = DW_LNS_advance_line;
res = write_ubyte(db,dbg,
elfsectno,
&writelen,
error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
res = write_sval(line_adv,dbg,
elfsectno,
&writelen,
error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_basic_block =
false
;
prevline->dpl_line = curline->dpl_line;
}
}
}
if
(no_lns_copy == 0) {
unsigned writelen = 0;
res = write_ubyte(DW_LNS_copy,dbg,elfsectno,&writelen,error);
if
(res != DW_DLV_OK) {
return
res;
}
sum_bytes += writelen;
prevline->dpl_basic_block =
false
;
}
curline = curline->dpl_next;
}
du = sum_bytes - OFFSET_PLUS_EXTENSION_SIZE;
{
start_line_sec += extension_size;
WRITE_UNALIGNED(dbg, (
void
*) start_line_sec,
(
const
void
*) &du,
sizeof
(du), offset_size);
}
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs,
Dwarf_Error * error)
{
int
elfsectno = 0;
int
i = 0;
int
firsttime = 1;
Dwarf_P_Cie curcie = 0;
Dwarf_P_Fde curfde = 0;
unsigned
char
*data = 0;
Dwarf_Unsigned du = 0;
Dwarf_Ubyte db = 0;
long
*cie_offs = 0;
unsigned
long
cie_length = 0;
int
cie_no = 0;
Dwarf_Ubyte offset_size = dbg->de_dwarf_offset_size;
Dwarf_Ubyte extension_size = dbg->de_64bit_extension ? 4 : 0;
Dwarf_Ubyte address_size = dbg->de_pointer_size;
Dwarf_Unsigned cur_off = 0;
elfsectno = dbg->de_elf_sects[DEBUG_FRAME];
curcie = dbg->de_frame_cies;
cie_length = 0;
cie_offs = (
long
*)
_dwarf_p_get_alloc(dbg,
sizeof
(
long
) * dbg->de_n_cie);
if
(cie_offs == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, DW_DLV_ERROR);
}
cie_no = 1;
while
(curcie) {
char
*code_al = 0;
int
codeal_bytes = 0;
char
*data_al = 0;
int
data_align_bytes = 0;
int
pad = 0;
int
res = 0;
char
buff1[ENCODE_SPACE_NEEDED];
char
buff2[ENCODE_SPACE_NEEDED];
char
buff3[ENCODE_SPACE_NEEDED];
char
*augmentation = 0;
char
*augmented_al = 0;
long
augmented_fields_length = 0;
int
irix_auglen_v0 = 0;
Dwarf_Half version = curcie->cie_version;
res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align,
&codeal_bytes,
buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, DW_DLV_ERROR);
}
res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align,
&data_align_bytes,
buff2,
sizeof
(buff2));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, DW_DLV_ERROR);
}
code_al = buff1;
data_al = buff2;
if
(firsttime) {
cie_offs[cie_no - 1] = 0;
firsttime = 0;
}
else
{
cie_offs[cie_no - 1] = cie_offs[cie_no - 2] +
(
long
) cie_length + OFFSET_PLUS_EXTENSION_SIZE;
}
cie_no++;
augmentation = curcie->cie_aug;
cie_length = offset_size +
sizeof
(Dwarf_Ubyte) +
strlen
(curcie->cie_aug) + 1 +
codeal_bytes +
data_align_bytes +
sizeof
(Dwarf_Ubyte) +
curcie->cie_inst_bytes;
if
(dbg->de_irix_exc_augmentation &&
(
strcmp
(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0)) {
augmented_fields_length = 0;
res = _dwarf_pro_encode_leb128_nm(augmented_fields_length,
&irix_auglen_v0, buff3,
sizeof
(buff3));
augmented_al = buff3;
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC,
DW_DLV_ERROR);
}
cie_length += irix_auglen_v0 ;
}
if
(version >= 4) {
cie_length += 1 +1;
}
pad = (
int
) PADDING(cie_length, address_size);
cie_length += pad;
GET_CHUNK_ERR(dbg, elfsectno, data, cie_length +
OFFSET_PLUS_EXTENSION_SIZE,
error);
if
(extension_size) {
DISTINGUISHED_VALUE_ARRAY(v4);
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &v4[0],
SIZEOFT32, extension_size);
data += extension_size;
}
du = cie_length;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
du = DW_CIE_ID;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
db = curcie->cie_version;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
strcpy
((
char
*) data, curcie->cie_aug);
data +=
strlen
(curcie->cie_aug) + 1;
if
(curcie->cie_version >= 4) {
db = dbg->de_pointer_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
db = dbg->de_segment_selector_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
}
memcpy
((
void
*) data, (
const
void
*) code_al, codeal_bytes);
data += codeal_bytes;
memcpy
((
void
*) data, (
const
void
*) data_al, data_align_bytes);
data += data_align_bytes;
db = curcie->cie_ret_reg;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
if
(dbg->de_irix_exc_augmentation &&
strcmp
(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
memcpy
((
void
*) data, (
const
void
*) augmented_al,
irix_auglen_v0);
data += irix_auglen_v0;
}
memcpy
((
void
*) data, (
const
void
*) curcie->cie_inst,
curcie->cie_inst_bytes);
data += curcie->cie_inst_bytes;
for
(i = 0; i < pad; i++) {
*data = DW_CFA_nop;
data++;
}
curcie = curcie->cie_next;
}
cur_off = cie_offs[cie_no - 2] + cie_length +
OFFSET_PLUS_EXTENSION_SIZE;
curfde = dbg->de_frame_fdes;
while
(curfde) {
Dwarf_P_Frame_Pgm curinst = 0;
long
fde_length = 0;
int
pad2 = 0;
Dwarf_P_Cie cie_ptr = 0;
Dwarf_Unsigned cie_index = 0;
Dwarf_Unsigned indx = 0;
int
oet_length = 0;
int
afl_length = 0;
int
res = 0;
int
v0_augmentation = 0;
char
afl_buff[ENCODE_SPACE_NEEDED];
cie_ptr = dbg->de_frame_cies;
cie_index = curfde->fde_cie;
indx = 1;
while
(cie_ptr && indx < cie_index) {
cie_ptr = cie_ptr->cie_next;
indx++;
}
if
(cie_ptr == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, DW_DLV_ERROR);
}
fde_length = curfde->fde_n_bytes +
OFFSET_PLUS_EXTENSION_SIZE +
address_size +
address_size;
if
(dbg->de_irix_exc_augmentation &&
strcmp
(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) {
v0_augmentation = 1;
oet_length = DWARF_32BIT_SIZE;
res = _dwarf_pro_encode_leb128_nm(oet_length,
&afl_length, afl_buff,
sizeof
(afl_buff));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC,
DW_DLV_ERROR);
}
fde_length +=
afl_length +
oet_length;
}
if
(curfde->fde_die) {
res = _dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off,
error);
if
(res != DW_DLV_OK) {
return
res;
}
}
res = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_FRAME, cur_off +
OFFSET_PLUS_EXTENSION_SIZE
,
dbg->de_sect_name_idx[DEBUG_FRAME],
dwarf_drt_data_reloc, offset_size);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, res );
}
res = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_FRAME,
cur_off + OFFSET_PLUS_EXTENSION_SIZE +
address_size
,
curfde->fde_r_symidx,
dwarf_drt_data_reloc, address_size);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, res);
}
if
(v0_augmentation &&
curfde->fde_offset_into_exception_tables >= 0) {
res = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_FRAME,
cur_off + OFFSET_PLUS_EXTENSION_SIZE +
offset_size + 2 * address_size +
afl_length,
curfde->fde_exception_table_symbol,
dwarf_drt_segment_rel,
DWARF_32BIT_SIZE);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, res);
}
}
pad2 = (
int
) PADDING(fde_length, address_size);
fde_length += pad2;
GET_CHUNK(dbg, elfsectno, data, fde_length +
OFFSET_PLUS_EXTENSION_SIZE,
error);
du = fde_length;
{
if
(extension_size) {
DISTINGUISHED_VALUE_ARRAY(v4);
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &v4[0],
SIZEOFT32, extension_size);
data += extension_size;
}
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
du = cie_offs[curfde->fde_cie - 1];
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
du = curfde->fde_initloc;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), address_size);
data += address_size;
if
(dbg->de_relocate_pair_by_symbol &&
curfde->fde_end_symbol != 0 &&
curfde->fde_addr_range == 0) {
Dwarf_Unsigned val;
res = dbg->de_relocate_pair_by_symbol(dbg,
DEBUG_FRAME,
cur_off + 2 * offset_size + address_size,
curfde->fde_r_symidx,
curfde->fde_end_symbol,
dwarf_drt_first_of_length_pair,
address_size);
if
(res != DW_DLV_OK) {
{
_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
return
DW_DLV_ERROR;
}
}
val = curfde->fde_end_symbol_offset -
curfde->fde_initloc;
WRITE_UNALIGNED(dbg, data,
(
const
void
*) &val,
sizeof
(val), address_size);
data += address_size;
}
else
{
du = curfde->fde_addr_range;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), address_size);
data += address_size;
}
}
if
(v0_augmentation) {
Dwarf_Signed dsw = 0;
memcpy
((
void
*) data, (
const
void
*) afl_buff, afl_length);
data += afl_length;
dsw = (Dwarf_Signed)curfde->fde_offset_into_exception_tables;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &dsw,
sizeof
(dsw), DWARF_32BIT_SIZE);
data += DWARF_32BIT_SIZE;
}
curinst = curfde->fde_inst;
if
(curfde->fde_block) {
unsigned
long
size = curfde->fde_inst_block_size;
memcpy
((
void
*) data, (
const
void
*) curfde->fde_block, size);
data += size;
}
else
{
while
(curinst) {
db = curinst->dfp_opcode;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
memcpy
((
void
*) data,
(
const
void
*) curinst->dfp_args,
curinst->dfp_nbytes);
data += curinst->dfp_nbytes;
curinst = curinst->dfp_next;
}
}
for
(i = 0; i < pad2; i++) {
*data = DW_CFA_nop;
data++;
}
cur_off += fde_length + offset_size;
curfde = curfde->fde_next;
}
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
static
int
marker_init(Dwarf_P_Debug dbg,
unsigned count)
{
dbg->de_marker_n_alloc = count;
dbg->de_markers = NULL;
if
(count > 0) {
dbg->de_markers = _dwarf_p_get_alloc(dbg,
sizeof
(
struct
Dwarf_P_Marker_s) * dbg->de_marker_n_alloc);
if
(dbg->de_markers == NULL) {
dbg->de_marker_n_alloc = 0;
return
DW_DLV_ERROR;
}
}
return
DW_DLV_OK;
}
static
int
marker_add(Dwarf_P_Debug dbg,
Dwarf_Unsigned offset,
Dwarf_Unsigned marker)
{
if
(dbg->de_marker_n_alloc >= (dbg->de_marker_n_used + 1)) {
unsigned n = dbg->de_marker_n_used++;
dbg->de_markers[n].ma_offset = offset;
dbg->de_markers[n].ma_marker = marker;
return
DW_DLV_OK;
}
return
DW_DLV_ERROR;
}
Dwarf_Signed
dwarf_get_die_markers(Dwarf_P_Debug dbg,
Dwarf_P_Marker * marker_list,
Dwarf_Unsigned * marker_count,
Dwarf_Error * error)
{
int
res = 0;
res = dwarf_get_die_markers_a(dbg,marker_list,marker_count,
error);
if
(res == DW_DLV_ERROR) {
return
DW_DLV_BADADDR;
}
return
0;
}
int
dwarf_get_die_markers_a(Dwarf_P_Debug dbg,
Dwarf_P_Marker * marker_list,
Dwarf_Unsigned * marker_count,
Dwarf_Error * error)
{
if
(marker_list == NULL || marker_count == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_ERROR);
}
if
(dbg->de_marker_n_used != dbg->de_marker_n_alloc) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_ERROR);
}
*marker_list = dbg->de_markers;
*marker_count = dbg->de_marker_n_used;
return
DW_DLV_OK;
}
static
int
string_attr_init (Dwarf_P_Debug dbg,
Dwarf_Signed section_index,
unsigned count)
{
Dwarf_P_Per_Sect_String_Attrs sect_sa =
&dbg->de_sect_string_attr[section_index];
sect_sa->sect_sa_n_alloc = count;
sect_sa->sect_sa_list = NULL;
if
(count > 0) {
sect_sa->sect_sa_section_number = section_index;
sect_sa->sect_sa_list = _dwarf_p_get_alloc(dbg,
sizeof
(
struct
Dwarf_P_String_Attr_s) * sect_sa->sect_sa_n_alloc);
if
(sect_sa->sect_sa_list == NULL) {
sect_sa->sect_sa_n_alloc = 0;
return
DW_DLV_ERROR;
}
}
return
DW_DLV_OK;
}
static
int
string_attr_add (Dwarf_P_Debug dbg,
Dwarf_Signed section_index,
Dwarf_Unsigned offset,
Dwarf_P_Attribute attr)
{
Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index];
if
(sect_sa->sect_sa_n_alloc >= (sect_sa->sect_sa_n_used + 1)) {
unsigned n = sect_sa->sect_sa_n_used++;
sect_sa->sect_sa_list[n].sa_offset = offset;
sect_sa->sect_sa_list[n].sa_nbytes = attr->ar_nbytes;
return
DW_DLV_OK;
}
return
DW_DLV_ERROR;
}
int
dwarf_get_string_attributes_count(Dwarf_P_Debug dbg,
Dwarf_Unsigned *
count_of_sa_sections,
int
*drd_buffer_version,
UNUSEDARG Dwarf_Error *error)
{
int
i = 0;
unsigned
int
count = 0;
for
(i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
if
(dbg->de_sect_string_attr[i].sect_sa_n_used > 0) {
++count;
}
}
*count_of_sa_sections = (Dwarf_Unsigned) count;
*drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
return
DW_DLV_OK;
}
int
dwarf_get_string_attributes_info(Dwarf_P_Debug dbg,
Dwarf_Signed *elf_section_index,
Dwarf_Unsigned *sect_sa_buffer_count,
Dwarf_P_String_Attr *sect_sa_buffer,
UNUSEDARG Dwarf_Error *error)
{
int
i = 0;
int
next = dbg->de_sect_sa_next_to_return;
for
(i = next; i < NUM_DEBUG_SECTIONS; ++i) {
Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[i];
if
(sect_sa->sect_sa_n_used > 0) {
dbg->de_sect_sa_next_to_return = i + 1;
*elf_section_index = sect_sa->sect_sa_section_number;
*sect_sa_buffer_count = sect_sa->sect_sa_n_used;
*sect_sa_buffer = sect_sa->sect_sa_list;
return
DW_DLV_OK;
}
}
return
DW_DLV_NO_ENTRY;
}
static
int
has_sibling_die_already(Dwarf_P_Die d)
{
Dwarf_P_Attribute a = 0;
for
(a = d->di_attrs; a ; a = a->ar_next) {
if
(a->ar_attribute == DW_AT_sibling) {
return
TRUE;
}
}
return
FALSE;
}
static
int
if_relocatable_string_form(Dwarf_P_Debug dbg, Dwarf_P_Attribute curattr,
int
*debug_str_reloc,
Dwarf_Error *error)
{
if
(curattr->ar_rel_type == R_MIPS_NONE) {
*debug_str_reloc = 0;
return
DW_DLV_OK;
}
if
(curattr->ar_attribute_form != DW_FORM_strp) {
_dwarf_p_error(dbg, error,DW_DLE_DEBUGSTR_UNEXPECTED_REL);
return
DW_DLV_ERROR;
}
if
(curattr->ar_rel_type != dbg->de_offset_reloc) {
_dwarf_p_error(dbg, error,DW_DLE_DEBUGSTR_UNEXPECTED_REL);
return
DW_DLV_ERROR;
}
*debug_str_reloc = 1;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_match_attr(Dwarf_P_Attribute attr,
Dwarf_P_Abbrev abbrev,
int
no_attr)
{
int
i = 0;
Dwarf_P_Attribute curatp = attr;
for
(i = 0; i < no_attr && curatp; i++,curatp = curatp->ar_next ) {
if
(curatp->ar_attribute != abbrev->abb_attrs[i] ||
curatp->ar_attribute_form != abbrev->abb_forms[i]) {
return
0;
}
if
(curatp->ar_attribute_form == DW_FORM_implicit_const) {
if
(abbrev->abb_forms[i] == DW_FORM_implicit_const) {
if
(curatp->ar_implicit_const !=
abbrev->abb_implicits[i]) {
return
0;
}
}
else
{
return
0;
}
}
else
{
if
(abbrev->abb_forms[i] == DW_FORM_implicit_const) {
return
0;
}
}
}
return
1;
}
static
int
verify_ab_no_dups(
struct
Dwarf_Sort_Abbrev_s *sortab,
int
attrcount)
{
int
k = 0;
unsigned preva = 0;
struct
Dwarf_Sort_Abbrev_s *ab = sortab;
if
(attrcount < 2) {
return
DW_DLV_OK;
}
for
(k = 0; k < attrcount; ++k,++ab) {
if
(k) {
if
(preva >= ab->dsa_attr) {
return
DW_DLV_ERROR;
}
}
preva = ab->dsa_attr;
}
return
DW_DLV_OK;
}
static
int
abcompare(
const
void
*l_in,
const
void
*r_in)
{
struct
Dwarf_Sort_Abbrev_s *l =
(
struct
Dwarf_Sort_Abbrev_s *)l_in;
struct
Dwarf_Sort_Abbrev_s *r =
(
struct
Dwarf_Sort_Abbrev_s *)r_in;
if
(l->dsa_attr < r->dsa_attr) {
return
-1;
}
if
(l->dsa_attr > r->dsa_attr) {
return
+1;
}
return
0;
}
static
int
_dwarf_pro_getabbrev(Dwarf_P_Debug dbg,
Dwarf_P_Die die, Dwarf_P_Abbrev head,
Dwarf_P_Abbrev*ab_out,Dwarf_Error *error)
{
Dwarf_P_Abbrev curabbrev = 0;
Dwarf_P_Attribute curattr = 0;
int
match = 0;
Dwarf_Unsigned *forms = 0;
Dwarf_Unsigned *attrs = 0;
Dwarf_Signed *implicits = 0;
int
attrcount = die->di_n_attr;
curabbrev = head;
while
(curabbrev) {
if
((die->di_tag == curabbrev->abb_tag) &&
((die->di_child != NULL &&
curabbrev->abb_children == DW_CHILDREN_yes) ||
(die->di_child == NULL &&
curabbrev->abb_children == DW_CHILDREN_no)) &&
(attrcount == curabbrev->abb_n_attr)) {
curattr = die->di_attrs;
match = _dwarf_pro_match_attr(curattr,
curabbrev,
(
int
) curabbrev->abb_n_attr);
if
(match == 1) {
*ab_out = curabbrev;
return
DW_DLV_OK;
}
}
curabbrev = curabbrev->abb_next;
}
if
(attrcount) {
forms = (Dwarf_Unsigned *)
_dwarf_p_get_alloc(die->di_dbg,
sizeof
(Dwarf_Unsigned) * attrcount);
if
(forms == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
attrs = (Dwarf_Unsigned *)
_dwarf_p_get_alloc(die->di_dbg,
sizeof
(Dwarf_Unsigned) * attrcount);
if
(attrs == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
implicits = (Dwarf_Signed *)
_dwarf_p_get_alloc(die->di_dbg,
sizeof
(Dwarf_Signed) * attrcount);
if
(implicits == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
}
curattr = die->di_attrs;
if
(forms && attrs && attrcount) {
struct
Dwarf_Sort_Abbrev_s *sortab = 0;
struct
Dwarf_Sort_Abbrev_s *ap = 0;
int
k = 0;
int
res = 0;
sortab = (
struct
Dwarf_Sort_Abbrev_s *)
malloc
(
sizeof
(
struct
Dwarf_Sort_Abbrev_s)*attrcount);
if
(!sortab) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
ap = sortab;
for
(; curattr; ++ap, curattr = curattr->ar_next) {
ap->dsa_attr = curattr->ar_attribute;
ap->dsa_form = curattr->ar_attribute_form;
ap->dsa_implicitvalue = curattr->ar_implicit_const;
ap->dsa_attrp = 0;
}
qsort
(sortab,attrcount,
sizeof
(
struct
Dwarf_Sort_Abbrev_s),
abcompare);
ap = sortab;
k = 0;
res = verify_ab_no_dups(sortab,attrcount);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg,DW_DLE_DUP_ATTR_ON_DIE,DW_DLV_ERROR);
}
for
( ; k < attrcount; ++k,++ap) {
attrs[k] = ap->dsa_attr;
forms[k] = ap->dsa_form;
implicits[k] = ap->dsa_implicitvalue;
}
free
(sortab);
}
curabbrev = (Dwarf_P_Abbrev)
_dwarf_p_get_alloc(die->di_dbg,
sizeof
(
struct
Dwarf_P_Abbrev_s));
if
(curabbrev == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
if
(die->di_child == NULL) {
curabbrev->abb_children = DW_CHILDREN_no;
}
else
{
curabbrev->abb_children = DW_CHILDREN_yes;
}
curabbrev->abb_tag = die->di_tag;
curabbrev->abb_attrs = attrs;
curabbrev->abb_forms = forms;
curabbrev->abb_implicits = implicits;
curabbrev->abb_n_attr = attrcount;
curabbrev->abb_idx = 0;
curabbrev->abb_next = NULL;
*ab_out = curabbrev;
return
DW_DLV_OK;
}
static
int
generate_debuginfo_header_2(Dwarf_P_Debug dbg,
unsigned *abbrev_offset_io,
unsigned
char
**data_io,
int
*cu_header_size_out,
Dwarf_Small **abbr_off_ptr_out,
Dwarf_Half version,
int
extension_size,
Dwarf_Ubyte address_size,
Dwarf_Error * error)
{
unsigned abbrev_offset = 0;
unsigned
char
* data = 0;
int
offset_size = dbg->de_dwarf_offset_size;
int
elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
int
cu_header_size = 0;
Dwarf_Unsigned du = 0;
Dwarf_Small *abbr_off_ptr = 0;
abbrev_offset = OFFSET_PLUS_EXTENSION_SIZE +
DWARF_HALF_SIZE ;
cu_header_size = abbrev_offset +
offset_size +
sizeof
(Dwarf_Ubyte);
GET_CHUNK_ERR(dbg, elfsectno_of_debug_info, data, cu_header_size,
error);
if
(extension_size) {
DISTINGUISHED_VALUE_ARRAY(v4);
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &v4[0], SIZEOFT32, extension_size);
data += extension_size;
}
abbr_off_ptr = data;
du = 0;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &version,
sizeof
(version), DWARF_HALF_SIZE);
data += DWARF_HALF_SIZE;
du = 0;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &address_size,
sizeof
(address_size),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
*abbrev_offset_io = abbrev_offset;
*data_io = data;
*cu_header_size_out = cu_header_size;
*abbr_off_ptr_out = abbr_off_ptr;
return
DW_DLV_OK;
}
static
int
generate_debuginfo_header_5(Dwarf_P_Debug dbg,
unsigned *abbrev_offset_io,
unsigned
char
**data_io,
int
*cu_header_size_out,
Dwarf_Small **abbr_off_ptr_out,
Dwarf_Half version,
Dwarf_Ubyte unit_type,
int
extension_size,
Dwarf_Ubyte address_size,
Dwarf_Error *error)
{
int
offset_size = dbg->de_dwarf_offset_size;
unsigned abbrev_offset = 0;
unsigned
char
* data = 0;
int
elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
int
cu_header_size = 0;
Dwarf_Unsigned du = 0;
Dwarf_Small *abbr_off_ptr = 0;
abbrev_offset = OFFSET_PLUS_EXTENSION_SIZE +
DWARF_HALF_SIZE +
sizeof
(unit_type) +
sizeof
(Dwarf_Ubyte);
cu_header_size = abbrev_offset + offset_size;
GET_CHUNK_ERR(dbg, elfsectno_of_debug_info, data, cu_header_size,
error);
if
(extension_size) {
DISTINGUISHED_VALUE_ARRAY(v4);
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &v4[0], SIZEOFT32, extension_size);
data += extension_size;
}
abbr_off_ptr = data;
du = 0;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &version,
sizeof
(version), DWARF_HALF_SIZE);
data += DWARF_HALF_SIZE;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &unit_type,
sizeof
(unit_type),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
WRITE_UNALIGNED(dbg, (
void
*) data, (
const
void
*) &address_size,
sizeof
(address_size),
sizeof
(Dwarf_Ubyte));
data +=
sizeof
(Dwarf_Ubyte);
du = 0;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), offset_size);
data += offset_size;
*abbrev_offset_io = abbrev_offset;
*data_io = data;
*cu_header_size_out = cu_header_size;
*abbr_off_ptr_out = abbr_off_ptr;
return
DW_DLV_OK;
}
static
int
write_out_debug_abbrev(Dwarf_P_Debug dbg,
Dwarf_P_Abbrev abbrev_head,
Dwarf_Error * error)
{
Dwarf_P_Abbrev curabbrev = abbrev_head;
unsigned
char
*data = 0;
int
res = 0;
int
abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV];
while
(curabbrev) {
int
idx = 0;
unsigned lebcount = 0;
Dwarf_Ubyte db = 0;
res = write_uval(curabbrev->abb_idx,dbg,abbrevsectno,
&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
res = write_uval(curabbrev->abb_tag,dbg,abbrevsectno,
&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
db = curabbrev->abb_children;
res = write_ubyte(db,dbg,abbrevsectno,&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
for
(idx = 0; idx < curabbrev->abb_n_attr; idx++) {
res =write_uval(curabbrev->abb_attrs[idx],
dbg,abbrevsectno,
&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
res =write_uval(curabbrev->abb_forms[idx],
dbg,abbrevsectno,
&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
if
(curabbrev->abb_forms[idx] == DW_FORM_implicit_const){
res =write_sval(curabbrev->abb_implicits[idx],
dbg,abbrevsectno,
&lebcount,error);
if
(res != DW_DLV_OK) {
return
res;
}
}
}
GET_CHUNK_ERR(dbg, abbrevsectno, data, 2, error);
*data = 0;
data++;
*data = 0;
curabbrev = curabbrev->abb_next;
}
GET_CHUNK_ERR(dbg, abbrevsectno, data, 1, error);
*data = 0;
return
DW_DLV_OK;
}
static
int
sort_die_attrs(Dwarf_P_Debug dbg,Dwarf_P_Die die,
Dwarf_Error *error)
{
struct
Dwarf_Sort_Abbrev_s *sortab = 0;
struct
Dwarf_Sort_Abbrev_s *ap = 0;
Dwarf_P_Attribute at = 0;
Dwarf_P_Attribute sorted_attrlist = 0;
Dwarf_P_Attribute sorted_tail = 0;
int
attrcount = die->di_n_attr;
int
res = 0;
unsigned ct = 0;
int
k = 0;
if
(attrcount < 2) {
return
DW_DLV_OK;
}
sortab = (
struct
Dwarf_Sort_Abbrev_s *)
malloc
(
sizeof
(
struct
Dwarf_Sort_Abbrev_s)*attrcount);
if
(!sortab) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
ap = sortab;
at = die->di_attrs;
for
(; at; ++ap, at = at->ar_next) {
ap->dsa_attr = at->ar_attribute;
ap->dsa_form = at->ar_attribute_form;
ap->dsa_attrp = at;
++ct;
}
qsort
(sortab,attrcount,
sizeof
(
struct
Dwarf_Sort_Abbrev_s),
abcompare);
res = verify_ab_no_dups(sortab,attrcount);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DUP_ATTR_ON_DIE, DW_DLV_ERROR);
}
ap = sortab;
k = 0;
for
( ; k < attrcount; ++k,++ap) {
Dwarf_P_Attribute localptr = ap->dsa_attrp;
if
(!sorted_attrlist) {
sorted_attrlist = localptr;
sorted_tail = sorted_attrlist;
localptr->ar_next = 0;
continue
;
}
sorted_tail->ar_next = localptr;
sorted_tail = localptr;
localptr->ar_next = 0;
}
die->di_attrs = sorted_attrlist;
free
(sortab);
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs,
Dwarf_Error * error)
{
int
elfsectno_of_debug_info = 0;
unsigned
char
*data = 0;
int
cu_header_size = 0;
Dwarf_P_Abbrev curabbrev = 0;
Dwarf_P_Abbrev abbrev_head = 0;
Dwarf_P_Abbrev abbrev_tail = 0;
Dwarf_P_Die curdie = 0;
Dwarf_P_Die first_child = 0;
Dwarf_Unsigned dw = 0;
Dwarf_Unsigned du = 0;
Dwarf_Half dh = 0;
Dwarf_Unsigned die_off = 0;
int
n_abbrevs = 0;
unsigned abbrev_offset = 0;
int
res = 0;
unsigned marker_count = 0;
unsigned string_attr_count = 0;
unsigned string_attr_offset = 0;
Dwarf_Small *abbr_off_ptr = 0;
int
offset_size = dbg->de_dwarf_offset_size;
Dwarf_Half version = dbg->de_output_version;
int
extension_size = dbg->de_64bit_extension ? 4 : 0;
Dwarf_Ubyte unit_type = DW_UT_compile;
Dwarf_Ubyte address_size = 0;
elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
address_size = dbg->de_pointer_size;
if
(version < 5) {
res = generate_debuginfo_header_2(dbg,
&abbrev_offset,
&data,
&cu_header_size,
&abbr_off_ptr,
version, extension_size, address_size,
error);
if
(res != DW_DLV_OK) {
return
res;
}
}
else
if
(version == 5) {
res = generate_debuginfo_header_5(dbg,
&abbrev_offset,
&data,
&cu_header_size,
&abbr_off_ptr,
version, unit_type, extension_size, address_size,
error);
if
(res != DW_DLV_OK) {
return
res;
}
}
else
{
DWARF_P_DBG_ERROR(dbg, DW_DLE_VERSION_STAMP_ERROR,
DW_DLV_ERROR);
}
curdie = dbg->de_dies;
if
( version < 5) {
if
(dbg->de_first_macinfo != NULL) {
res = _dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error);
if
(res != DW_DLV_OK) {
return
res;
}
}
}
else
{
#if 0
res = _dwarf_pro_add_AT_macro5_info(dbg, curdie, 0, error);
#endif
}
if
(dwarf_need_debug_line_section(dbg) == TRUE) {
res =_dwarf_pro_add_AT_stmt_list(dbg, curdie, error);
if
(res != DW_DLV_OK) {
return
res;
}
}
die_off = cu_header_size;
res = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_INFO,
abbrev_offset
,
dbg->de_sect_name_idx[DEBUG_ABBREV],
dwarf_drt_data_reloc, offset_size);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
}
first_child = curdie->di_child;
while
(first_child && first_child->di_right) {
if
(first_child->di_child) {
if
(!has_sibling_die_already(first_child)) {
dwarf_add_AT_reference(dbg,
first_child,
DW_AT_sibling,
first_child->di_right, error);
}
}
first_child = first_child->di_right;
}
abbrev_head = abbrev_tail = NULL;
marker_count = 0;
string_attr_count = 0;
while
(curdie != NULL) {
int
nbytes = 0;
Dwarf_P_Attribute curattr = 0;
char
*space = 0;
int
cres = 0;
char
buff1[ENCODE_SPACE_NEEDED];
curdie->di_offset = die_off;
if
(curdie->di_marker != 0) {
marker_count++;
}
cres =sort_die_attrs(dbg,curdie,error);
if
(cres != DW_DLV_OK) {
return
cres;
}
cres = _dwarf_pro_getabbrev(dbg,curdie, abbrev_head,&curabbrev,
error);
if
(cres != DW_DLV_OK) {
return
cres;
}
if
(abbrev_head == NULL) {
n_abbrevs = 1;
curabbrev->abb_idx = n_abbrevs;
abbrev_tail = abbrev_head = curabbrev;
}
else
{
if
(curabbrev->abb_idx == 0) {
n_abbrevs++;
curabbrev->abb_idx = n_abbrevs;
abbrev_tail->abb_next = curabbrev;
abbrev_tail = curabbrev;
}
}
cres = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx,
&nbytes,
buff1,
sizeof
(buff1));
if
(cres != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
space = _dwarf_p_get_alloc(dbg, nbytes);
if
(space == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, DW_DLV_ERROR);
}
memcpy
(space, buff1, nbytes);
curdie->di_abbrev = space;
curdie->di_abbrev_nbytes = nbytes;
die_off += nbytes;
curattr = curdie->di_attrs;
while
(curattr) {
if
(curattr->ar_rel_type != R_MIPS_NONE) {
int
rres=0;
switch
(curattr->ar_attribute) {
case
DW_AT_stmt_list:
curattr->ar_rel_symidx =
dbg->de_sect_name_idx[DEBUG_LINE];
break
;
case
DW_AT_MIPS_fde:
curattr->ar_rel_symidx =
dbg->de_sect_name_idx[DEBUG_FRAME];
break
;
case
DW_AT_macro_info:
curattr->ar_rel_symidx =
dbg->de_sect_name_idx[DEBUG_MACINFO];
break
;
case
DW_AT_comp_dir:
case
DW_AT_const_value:
case
DW_AT_linkage_name:
case
DW_AT_MIPS_abstract_name:
case
DW_AT_MIPS_linkage_name:
case
DW_AT_name:
case
DW_AT_producer: {
int
is_debug_str = 0;
int
nres = if_relocatable_string_form(dbg,curattr,
&is_debug_str,error);
if
(nres != DW_DLV_OK) {
return
res;
}
if
(is_debug_str) {
curattr->ar_rel_symidx =
dbg->de_sect_name_idx[DEBUG_STR];
}
}
break
;
default
:
break
;
}
rres = dbg->de_relocate_by_name_symbol(dbg,
DEBUG_INFO,
die_off + curattr->ar_rel_offset,
curattr->ar_rel_symidx,
dwarf_drt_data_reloc,
curattr->ar_reloc_len);
if
(rres != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
}
}
if
(curattr->ar_attribute_form == DW_FORM_string) {
string_attr_count++;
}
die_off += curattr->ar_nbytes;
curattr = curattr->ar_next;
}
if
(curdie->di_child) {
curdie = curdie->di_child;
}
else
{
while
(curdie != NULL && curdie->di_right == NULL) {
curdie = curdie->di_parent;
if
(curdie != NULL) {
die_off++;
}
}
if
(curdie != NULL) {
curdie = curdie->di_right;
}
}
}
res = marker_init(dbg, marker_count);
if
(res == DW_DLV_ERROR) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
}
res = string_attr_init(dbg, DEBUG_INFO, string_attr_count);
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
}
curdie = dbg->de_dies;
while
(curdie != NULL) {
Dwarf_P_Attribute curattr;
if
(curdie->di_marker != 0) {
res = marker_add(dbg, curdie->di_offset, curdie->di_marker);
if
(res == DW_DLV_ERROR) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
}
}
GET_CHUNK_ERR(dbg, elfsectno_of_debug_info,
data, curdie->di_abbrev_nbytes, error);
memcpy
((
void
*) data,
(
const
void
*) curdie->di_abbrev,
curdie->di_abbrev_nbytes);
curattr = curdie->di_attrs;
string_attr_offset = curdie->di_offset +
curdie->di_abbrev_nbytes;
while
(curattr) {
GET_CHUNK_ERR(dbg, elfsectno_of_debug_info, data,
(unsigned
long
) curattr->ar_nbytes, error);
switch
(curattr->ar_attribute_form) {
case
DW_FORM_ref1:
{
Dwarf_Ubyte db = 0;
if
(curattr->ar_ref_die->di_offset >
(unsigned) 0xff) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, DW_DLV_ERROR);
}
db = curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &db,
sizeof
(db),
sizeof
(Dwarf_Ubyte));
break
;
}
case
DW_FORM_ref2:
{
if
(curattr->ar_ref_die->di_offset >
(unsigned) 0xffff) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, DW_DLV_ERROR);
}
dh = curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &dh,
sizeof
(dh), DWARF_HALF_SIZE);
break
;
}
case
DW_FORM_ref_addr:
{
break
;
}
case
DW_FORM_ref4:
{
if
(curattr->ar_ref_die->di_offset >
(unsigned) 0xffffffff) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW,
DW_DLV_ERROR);
}
dw = (Dwarf_Unsigned) curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &dw,
sizeof
(dw), DWARF_32BIT_SIZE);
break
;
}
case
DW_FORM_ref8:
du = curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (
void
*) data,
(
const
void
*) &du,
sizeof
(du), DWARF_64BIT_SIZE);
break
;
case
DW_FORM_ref_udata:
{
int
nbytesx;
char
buff1[ENCODE_SPACE_NEEDED];
res =
_dwarf_pro_encode_leb128_nm(curattr->
ar_ref_die->
di_offset, &nbytesx,
buff1,
sizeof
(buff1));
if
(res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC,
DW_DLV_ERROR);
}
memcpy
(data, buff1, nbytesx);
break
;
}
default
:
if
(curattr->ar_nbytes) {
memcpy
((
void
*) data,
(
const
void
*) curattr->ar_data,
curattr->ar_nbytes);
}
break
;
}
if
(curattr->ar_attribute_form == DW_FORM_string) {
string_attr_add(dbg, DEBUG_INFO, string_attr_offset, curattr);
}
string_attr_offset += curattr->ar_nbytes;
curattr = curattr->ar_next;
}
if
(curdie->di_child) {
curdie = curdie->di_child;
}
else
{
while
(curdie != NULL && curdie->di_right == NULL) {
if
(!curdie->di_parent) {
break
;
}
GET_CHUNK_ERR(dbg, elfsectno_of_debug_info, data, 1, error);
*data =
'\0'
;
curdie = curdie->di_parent;
}
if
(curdie != NULL)
curdie = curdie->di_right;
}
}
du = die_off - OFFSET_PLUS_EXTENSION_SIZE;
WRITE_UNALIGNED(dbg, (
void
*) abbr_off_ptr,
(
const
void
*) &du,
sizeof
(du), offset_size);
data = 0;
res = write_out_debug_abbrev(dbg,
abbrev_head, error);
if
(res != DW_DLV_OK) {
return
res;
}
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debug_names(Dwarf_P_Debug dbg,
UNUSEDARG Dwarf_Signed *nbufs,
Dwarf_Error * error UNUSEDARG)
{
#if 0
int
elfsectno_of_debug_names = dbg->de_elf_sects[DEBUG_NAMES];
FIXME: Needs implementation
unsigned
char
*data = 0;
GET_CHUNK(dbg, elfsectno_of_debug_names, data,
dbg->de_debug_names->ds_nbytes,
error);
memcpy
(data,dbg->de_debug_names->ds_data,dbg->de_debug_names->ds_nbytes);
#endif
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debug_str(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs,
Dwarf_Error * error)
{
int
elfsectno_of_debug_str = 0;
unsigned
char
*data = 0;
elfsectno_of_debug_str = dbg->de_elf_sects[DEBUG_STR];
GET_CHUNK(dbg, elfsectno_of_debug_str, data, dbg->de_debug_str->ds_nbytes,
error);
memcpy
(data,dbg->de_debug_str->ds_data,dbg->de_debug_str->ds_nbytes);
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
static
int
_dwarf_pro_generate_debug_line_str(Dwarf_P_Debug dbg,
Dwarf_Signed *nbufs,
Dwarf_Error * error)
{
int
elfsectno_of_debug_line_str = 0;
unsigned
char
*data = 0;
elfsectno_of_debug_line_str = dbg->de_elf_sects[DEBUG_LINE_STR];
GET_CHUNK(dbg, elfsectno_of_debug_line_str, data,
dbg->de_debug_line_str->ds_nbytes,
error);
memcpy
(data,dbg->de_debug_line_str->ds_data,
dbg->de_debug_line_str->ds_nbytes);
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}
Dwarf_Ptr
dwarf_get_section_bytes(Dwarf_P_Debug dbg,
UNUSEDARG Dwarf_Signed dwarf_section,
Dwarf_Signed * section_idx,
Dwarf_Unsigned * length, Dwarf_Error * error)
{
Dwarf_Ptr s_bytes = 0;
int
res = 0;
res = dwarf_get_section_bytes_a(dbg,
dwarf_section,
section_idx,
length,
&s_bytes,
error);
if
(res == DW_DLV_ERROR) {
return
(Dwarf_Ptr)DW_DLV_BADADDR;
}
if
(res == DW_DLV_NO_ENTRY) {
return
NULL;
}
return
s_bytes;
}
int
dwarf_get_section_bytes_a(Dwarf_P_Debug dbg,
UNUSEDARG Dwarf_Signed dwarf_section,
Dwarf_Signed * section_idx,
Dwarf_Unsigned * length,
Dwarf_Ptr * section_bytes,
Dwarf_Error * error)
{
Dwarf_Ptr buf = 0;
if
(dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_ERROR);
}
*section_bytes = 0;
*length = 0;
if
(dbg->de_debug_sects == 0) {
return
DW_DLV_NO_ENTRY;
}
if
(dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
return
DW_DLV_NO_ENTRY;
}
*section_idx = dbg->de_debug_sects->ds_elf_sect_no;
*length = dbg->de_debug_sects->ds_nbytes;
buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data;
dbg->de_debug_sects = dbg->de_debug_sects->ds_next;
*section_bytes = buf;
return
DW_DLV_OK;
}
void
dwarf_reset_section_bytes(Dwarf_P_Debug dbg)
{
dbg->de_debug_sects = dbg->de_first_debug_sect;
dbg->de_reloc_next_to_return = 0;
dbg->de_sect_sa_next_to_return = 0;
}
Dwarf_Small *
_dwarf_pro_buffer(Dwarf_P_Debug dbg,
int
elfsectno, unsigned
long
nbytes)
{
Dwarf_P_Section_Data cursect = 0;
cursect = dbg->de_current_active_section;
if
((cursect->ds_elf_sect_no != elfsectno) ||
((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc)
) {
unsigned
long
space = nbytes;
if
(nbytes < CHUNK_SIZE)
space = CHUNK_SIZE;
cursect = (Dwarf_P_Section_Data)
_dwarf_p_get_alloc(dbg,
sizeof
(
struct
Dwarf_P_Section_Data_s)
+ space);
if
(cursect == NULL) {
return
(NULL);
}
cursect->ds_data = (
char
*) cursect +
sizeof
(
struct
Dwarf_P_Section_Data_s);
cursect->ds_orig_alloc = space;
cursect->ds_elf_sect_no = elfsectno;
cursect->ds_nbytes = nbytes;
if
(dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
dbg->de_debug_sects = cursect;
dbg->de_current_active_section = cursect;
dbg->de_first_debug_sect = cursect;
}
else
{
dbg->de_current_active_section->ds_next = cursect;
dbg->de_current_active_section = cursect;
}
dbg->de_n_debug_sect++;
return
((Dwarf_Small *) cursect->ds_data);
}
{
Dwarf_Small *space_for_caller = (Dwarf_Small *)
(cursect->ds_data + cursect->ds_nbytes);
cursect->ds_nbytes += nbytes;
return
space_for_caller;
}
}