#include "config.h"
#include "libdwarfdefs.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ELFACCESS_H
#include <elfaccess.h>
#endif
#include "pro_incl.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"
#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
char *_dwarf_rel_section_names[] = {
".rel.debug_info",
".rel.debug_line",
".rel.debug_abbrev",
".rel.debug_frame",
".rel.debug_aranges",
".rel.debug_pubnames",
".rel.debug_str",
".rel.debug_funcnames",
".rel.debug_typenames",
".rel.debug_varnames",
".rel.debug_weaknames",
".rel.debug_macinfo",
".rel.debug_loc"
};
char *_dwarf_sectnames[] = {
".debug_info",
".debug_line",
".debug_abbrev",
".debug_frame",
".debug_aranges",
".debug_pubnames",
".debug_str",
".debug_funcnames",
".debug_typenames",
".debug_varnames",
".debug_weaknames",
".debug_macinfo",
".debug_loc"
};
static Dwarf_Ubyte std_opcode_len[] = { 0,
1,
1,
1,
1,
0,
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_debugline(Dwarf_P_Debug dbg,
Dwarf_Error * error);
static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
Dwarf_Error * error);
static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
Dwarf_Error * error);
static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev);
static int _dwarf_pro_match_attr
(Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr);
#define OPC_INCS_ZERO -1
#define OPC_OUT_OF_RANGE -2
#define LINE_OUT_OF_RANGE -3
static int _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv);
#define BEGIN_LEN_SIZE (uwordb_size + extension_size)
static int
dwarf_need_debug_line_section(Dwarf_P_Debug dbg)
{
if (dbg->de_lines == NULL && dbg->de_file_entries == NULL
&& dbg->de_inc_dirs == NULL) {
return FALSE;
}
return TRUE;
}
Dwarf_Signed
dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
int nbufs;
int sect;
int name_idx;
int err;
Dwarf_Unsigned du;
if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT);
}
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_STR:
if (dbg->de_strings == 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_LOC:
continue;
default:
DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT);
}
{
int new_base_elf_sect;
if (dbg->de_func_b) {
new_base_elf_sect =
dbg->de_func_b(_dwarf_sectnames[sect],
1,
SECTION_TYPE,
flags, SHN_UNDEF, 0, &du, &err);
} else {
new_base_elf_sect = dbg->de_func(_dwarf_sectnames[sect],
dbg->
de_relocation_record_size,
SECTION_TYPE, flags,
SHN_UNDEF, 0,
&name_idx, &err);
du = name_idx;
}
if (new_base_elf_sect == -1) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR,
DW_DLV_NOCOUNT);
}
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) {
nbufs = _dwarf_pro_generate_debugline(dbg, error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_frame_cies) {
nbufs = _dwarf_pro_generate_debugframe(dbg, error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_first_macinfo) {
nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_dies) {
nbufs = _dwarf_pro_generate_debuginfo(dbg, error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_arange) {
nbufs = _dwarf_transform_arange_to_disk(dbg, error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) {
nbufs = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_pubname,
DEBUG_PUBNAMES,
error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) {
nbufs = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_funcname,
DEBUG_FUNCNAMES,
error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) {
nbufs = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_typename,
DEBUG_TYPENAMES,
error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) {
nbufs = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_varname,
DEBUG_VARNAMES,
error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) {
nbufs = _dwarf_transform_simplename_to_disk(dbg,
dwarf_snk_weakname,
DEBUG_WEAKNAMES,
error);
if (nbufs < 0) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
}
{
Dwarf_Signed new_secs;
int res;
res = dbg->de_transform_relocs_to_disk(dbg, &new_secs);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
DW_DLV_NOCOUNT);
}
nbufs += new_secs;
}
return nbufs;
}
static int
_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
Dwarf_P_Inc_Dir curdir = 0;
Dwarf_P_F_Entry curentry = 0;
Dwarf_P_Line curline = 0;
Dwarf_P_Line prevline = 0;
int sum_bytes = 0;
int 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;
int uwordb_size = dbg->de_offset_size;
int extension_size = dbg->de_64bit_extension ? 4 : 0;
int upointer_size = dbg->de_pointer_size;
char buff1[ENCODE_SPACE_NEEDED];
sum_bytes = 0;
elfsectno = dbg->de_elf_sects[DEBUG_LINE];
curdir = dbg->de_inc_dirs;
while (curdir) {
prolog_size += strlen(curdir->did_name) + 1;
curdir = curdir->did_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 += BEGIN_LEN_SIZE + sizeof_uhalf(dbg) +
uwordb_size +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg) +
sizeof_ubyte(dbg);
prolog_size += sizeof(std_opcode_len);
GET_CHUNK(dbg, elfsectno, data, prolog_size, error);
start_line_sec = data;
du = 0;
if (extension_size) {
Dwarf_Word x = DISTINGUISHED_VALUE;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x,
sizeof(x), extension_size);
data += extension_size;
}
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
sizeof(du), uwordb_size);
data += uwordb_size;
dh = VERSION;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh,
sizeof(dh), sizeof(Dwarf_Half));
data += sizeof(Dwarf_Half);
du = prolog_size - (BEGIN_LEN_SIZE + sizeof(Dwarf_Half) +
uwordb_size);
{
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
sizeof(du), uwordb_size);
data += uwordb_size;
}
db = MIN_INST_LENGTH;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
db = DEFAULT_IS_STMT;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
db = (Dwarf_Ubyte) LINE_BASE;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
db = LINE_RANGE;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
db = 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,
sizeof(std_opcode_len), sizeof(std_opcode_len));
data += sizeof(std_opcode_len);
curdir = dbg->de_inc_dirs;
while (curdir) {
strcpy((char *) data, curdir->did_name);
data += strlen(curdir->did_name) + 1;
curdir = curdir->did_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++;
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, -1);
}
_dwarf_pro_reg_init(prevline);
while (curline) {
int nbytes;
char *arg;
int opc;
int no_lns_copy;
Dwarf_Unsigned addr_adv;
int line_adv;
no_lns_copy = 0;
if (curline->dpl_opc != 0) {
int inst_bytes;
char *str;
int str_nbytes;
switch (curline->dpl_opc) {
case DW_LNE_end_sequence:
addr_adv = curline->dpl_address - prevline->dpl_address;
if (addr_adv > 0) {
db = DW_LNS_advance_pc;
res =
_dwarf_pro_encode_leb128_nm(addr_adv /
MIN_INST_LENGTH,
&nbytes, buff1,
sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
GET_CHUNK(dbg, elfsectno, data,
nbytes + sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &db, sizeof(db),
sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
memcpy((void *) data, (const void *) buff1, nbytes);
data += nbytes + sizeof(Dwarf_Ubyte);
sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
prevline->dpl_address = curline->dpl_address;
}
db = 0;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
inst_bytes = sizeof(Dwarf_Ubyte);
res =
_dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
memcpy((void *) data, (const void *) buff1, str_nbytes);
data += str_nbytes;
sum_bytes += str_nbytes;
db = DW_LNE_end_sequence;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
_dwarf_pro_reg_init(prevline);
no_lns_copy = 1;
break;
case DW_LNE_set_address:
db = 0;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size;
res =
_dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
str = buff1;
memcpy((void *) data, (const void *) str, str_nbytes);
data += str_nbytes;
sum_bytes += str_nbytes;
db = DW_LNE_set_address;
GET_CHUNK(dbg, elfsectno, data, upointer_size +
sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
res = dbg->de_reloc_name(dbg, DEBUG_LINE, sum_bytes,
curline->dpl_r_symidx,
dwarf_drt_data_reloc,
uwordb_size);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
du = curline->dpl_address;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
sizeof(du), upointer_size);
data += upointer_size;
sum_bytes += upointer_size;
prevline->dpl_address = curline->dpl_address;
no_lns_copy = 1;
break;
}
} else {
if (curline->dpl_file != prevline->dpl_file) {
db = DW_LNS_set_file;
res =
_dwarf_pro_encode_leb128_nm(curline->dpl_file,
&nbytes, buff1,
sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
arg = buff1;
GET_CHUNK(dbg, elfsectno, data,
nbytes + sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
memcpy((void *) data, (const void *) arg, nbytes);
data += nbytes;
sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
prevline->dpl_file = curline->dpl_file;
}
if (curline->dpl_column != prevline->dpl_column) {
db = DW_LNS_set_column;
res = _dwarf_pro_encode_leb128_nm(curline->dpl_column,
&nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
arg = buff1;
GET_CHUNK(dbg, elfsectno, data,
nbytes + sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
memcpy((void *) data, (const void *) arg, nbytes);
data += nbytes;
sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
prevline->dpl_column = curline->dpl_column;
}
if (curline->dpl_is_stmt != prevline->dpl_is_stmt) {
db = DW_LNS_negate_stmt;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
prevline->dpl_is_stmt = curline->dpl_is_stmt;
}
if (curline->dpl_basic_block == true &&
prevline->dpl_basic_block == false) {
db = DW_LNS_set_basic_block;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
prevline->dpl_basic_block = curline->dpl_basic_block;
}
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, -1);
}
if ((opc = _dwarf_pro_get_opc(addr_adv, line_adv)) > 0) {
no_lns_copy = 1;
db = opc;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
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 =
_dwarf_pro_encode_leb128_nm(addr_adv /
MIN_INST_LENGTH,
&nbytes, buff1,
sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
arg = buff1;
GET_CHUNK(dbg, elfsectno, data,
nbytes + sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
memcpy((void *) data, (const void *) arg, nbytes);
data += nbytes + sizeof(Dwarf_Ubyte);
sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
prevline->dpl_basic_block = false;
prevline->dpl_address = curline->dpl_address;
}
if (line_adv != 0) {
db = DW_LNS_advance_line;
res = _dwarf_pro_encode_signed_leb128_nm(line_adv,
&nbytes,
buff1,
sizeof
(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
arg = buff1;
GET_CHUNK(dbg, elfsectno, data,
nbytes + sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &db, sizeof(db),
sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
memcpy((void *) data, (const void *) arg, nbytes);
data += nbytes + sizeof(Dwarf_Ubyte);
sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
prevline->dpl_basic_block = false;
prevline->dpl_line = curline->dpl_line;
}
}
}
if (no_lns_copy == 0) {
db = DW_LNS_copy;
GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
sum_bytes += sizeof(Dwarf_Ubyte);
prevline->dpl_basic_block = false;
}
curline = curline->dpl_next;
}
du = sum_bytes - BEGIN_LEN_SIZE;
{
start_line_sec += extension_size;
WRITE_UNALIGNED(dbg, (void *) start_line_sec,
(const void *) &du, sizeof(du), uwordb_size);
}
return (int) dbg->de_n_debug_sect;
}
static int
_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
int elfsectno;
int i;
int firsttime = 1;
int pad;
Dwarf_P_Cie curcie;
Dwarf_P_Fde curfde;
unsigned char *data;
Dwarf_sfixed dsw;
Dwarf_Unsigned du;
Dwarf_Ubyte db;
long *cie_offs;
unsigned long cie_length;
int cie_no;
int uwordb_size = dbg->de_offset_size;
int extension_size = dbg->de_64bit_extension ? 4 : 0;
int upointer_size = dbg->de_pointer_size;
Dwarf_Unsigned cur_off;
elfsectno = dbg->de_elf_sects[DEBUG_FRAME];
curcie = dbg->de_frame_cies;
cie_length = 0;
cur_off = 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, -1);
}
cie_no = 1;
while (curcie) {
char *code_al;
int c_bytes;
char *data_al;
int d_bytes;
int res;
char buff1[ENCODE_SPACE_NEEDED];
char buff2[ENCODE_SPACE_NEEDED];
char buff3[ENCODE_SPACE_NEEDED];
char *augmentation;
char *augmented_al;
long augmented_fields_length;
int a_bytes;
res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align,
&c_bytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
}
res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align,
&d_bytes,
buff2, sizeof(buff2));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
}
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 + BEGIN_LEN_SIZE;
}
cie_no++;
augmentation = curcie->cie_aug;
if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
augmented_fields_length = 0;
res = _dwarf_pro_encode_leb128_nm(augmented_fields_length,
&a_bytes, buff3,
sizeof(buff3));
augmented_al = buff3;
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
}
cie_length = uwordb_size +
sizeof(Dwarf_Ubyte) +
strlen(curcie->cie_aug) + 1 +
c_bytes +
d_bytes +
sizeof(Dwarf_Ubyte) +
a_bytes +
curcie->cie_inst_bytes;
} else {
cie_length = uwordb_size +
sizeof(Dwarf_Ubyte) +
strlen(curcie->cie_aug) + 1 +
c_bytes + d_bytes + sizeof(Dwarf_Ubyte) +
curcie->cie_inst_bytes;
}
pad = (int) PADDING(cie_length, upointer_size);
cie_length += pad;
GET_CHUNK(dbg, elfsectno, data, cie_length +
BEGIN_LEN_SIZE, error);
if (extension_size) {
Dwarf_Unsigned x = DISTINGUISHED_VALUE;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &x,
sizeof(x), extension_size);
data += extension_size;
}
du = cie_length;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du, sizeof(du), uwordb_size);
data += uwordb_size;
du = DW_CIE_ID;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
sizeof(du), uwordb_size);
data += uwordb_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;
memcpy((void *) data, (const void *) code_al, c_bytes);
data += c_bytes;
memcpy((void *) data, (const void *) data_al, d_bytes);
data += d_bytes;
db = curcie->cie_ret_reg;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
memcpy((void *) data, (const void *) augmented_al, a_bytes);
data += a_bytes;
}
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 + BEGIN_LEN_SIZE;
curfde = dbg->de_frame_fdes;
while (curfde) {
Dwarf_P_Frame_Pgm curinst;
long fde_length;
int pad;
Dwarf_P_Cie cie_ptr;
Dwarf_Word cie_index, index;
int oet_length, afl_length, res;
int v0_augmentation = 0;
#if 0
unsigned char *fde_start_point;
#endif
char afl_buff[ENCODE_SPACE_NEEDED];
cie_ptr = dbg->de_frame_cies;
cie_index = curfde->fde_cie;
index = 1;
while (cie_ptr && index < cie_index) {
cie_ptr = cie_ptr->cie_next;
index++;
}
if (cie_ptr == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1);
}
if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) {
v0_augmentation = 1;
oet_length = sizeof(Dwarf_sfixed);
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, -1);
}
fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE +
upointer_size +
upointer_size +
afl_length +
oet_length;
} else {
fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE +
upointer_size +
upointer_size;
}
if (_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off, error)
< 0)
return -1;
res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off +
BEGIN_LEN_SIZE,
dbg->de_sect_name_idx[DEBUG_FRAME],
dwarf_drt_data_reloc, uwordb_size);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
cur_off + BEGIN_LEN_SIZE +
upointer_size,
curfde->fde_r_symidx,
dwarf_drt_data_reloc, upointer_size);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
if (v0_augmentation &&
curfde->fde_offset_into_exception_tables >= 0) {
res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
cur_off + BEGIN_LEN_SIZE +
uwordb_size + 2 * upointer_size +
afl_length,
curfde->fde_exception_table_symbol,
dwarf_drt_segment_rel,
sizeof(Dwarf_sfixed));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
}
}
pad = (int) PADDING(fde_length, upointer_size);
fde_length += pad;
GET_CHUNK(dbg, elfsectno, data, fde_length + BEGIN_LEN_SIZE,
error);
#if 0
fde_start_point = data;
#endif
du = fde_length;
{
if (extension_size) {
Dwarf_Word x = DISTINGUISHED_VALUE;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &x,
sizeof(x), extension_size);
data += extension_size;
}
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), uwordb_size);
data += uwordb_size;
du = cie_offs[curfde->fde_cie - 1];
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), uwordb_size);
data += uwordb_size;
du = curfde->fde_initloc;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), upointer_size);
data += upointer_size;
if (dbg->de_reloc_pair &&
curfde->fde_end_symbol != 0 &&
curfde->fde_addr_range == 0) {
Dwarf_Unsigned val;
res = dbg->de_reloc_pair(dbg,
DEBUG_FRAME, cur_off + 2 * uwordb_size + upointer_size,
curfde->fde_r_symidx,
curfde->fde_end_symbol,
dwarf_drt_first_of_length_pair,
upointer_size);
if (res != DW_DLV_OK) {
{
_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (0);
}
}
val = curfde->fde_end_symbol_offset -
curfde->fde_initloc;
WRITE_UNALIGNED(dbg, data,
(const void *) &val,
sizeof(val), upointer_size);
data += upointer_size;
} else {
du = curfde->fde_addr_range;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), upointer_size);
data += upointer_size;
}
}
if (v0_augmentation) {
memcpy((void *) data, (const void *) afl_buff, afl_length);
data += afl_length;
dsw =
(Dwarf_sfixed) curfde->fde_offset_into_exception_tables;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw,
sizeof(dsw), sizeof(Dwarf_sfixed));
data += sizeof(Dwarf_sfixed);
}
curinst = curfde->fde_inst;
while (curinst) {
db = curinst->dfp_opcode;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
data += sizeof(Dwarf_Ubyte);
#if 0
if (curinst->dfp_sym_index) {
int res;
res = dbg->de_reloc_name(dbg,
DEBUG_FRAME,
(data - fde_start_point)
+ cur_off + uwordb_size,
curinst->dfp_sym_index,
dwarf_drt_data_reloc,
upointer_size);
if (res != DW_DLV_OK) {
{
_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (0);
}
}
}
#endif
memcpy((void *) data,
(const void *) curinst->dfp_args,
curinst->dfp_nbytes);
data += curinst->dfp_nbytes;
curinst = curinst->dfp_next;
}
for (i = 0; i < pad; i++) {
*data = DW_CFA_nop;
data++;
}
cur_off += fde_length + uwordb_size;
curfde = curfde->fde_next;
}
return (int) dbg->de_n_debug_sect;
}
static int
_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
int elfsectno_of_debug_info;
int abbrevsectno;
unsigned char *data;
int cu_header_size;
Dwarf_P_Abbrev curabbrev, abbrev_head, abbrev_tail;
Dwarf_P_Die curdie;
Dwarf_P_Die first_child;
Dwarf_Word dw;
Dwarf_Unsigned du;
Dwarf_Half dh;
Dwarf_Ubyte db;
Dwarf_Half version;
Dwarf_Unsigned die_off;
int n_abbrevs;
int res;
Dwarf_Small *start_info_sec;
int uwordb_size = dbg->de_offset_size;
int extension_size = dbg->de_64bit_extension ? 4 : 0;
abbrev_head = abbrev_tail = NULL;
elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
cu_header_size = BEGIN_LEN_SIZE + sizeof(Dwarf_Half) +
uwordb_size +
sizeof(Dwarf_Ubyte);
GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size,
error);
start_info_sec = data;
if (extension_size) {
du = DISTINGUISHED_VALUE;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du, sizeof(du), extension_size);
data += extension_size;
}
du = 0;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du, sizeof(du), uwordb_size);
data += uwordb_size;
version = CURRENT_VERSION_STAMP;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version,
sizeof(version), sizeof(Dwarf_Half));
data += sizeof(Dwarf_Half);
du = 0;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du, sizeof(du), uwordb_size);
data += uwordb_size;
db = dbg->de_pointer_size;
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), 1);
curdie = dbg->de_dies;
if (dbg->de_first_macinfo != NULL) {
if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0)
return -1;
}
if (dwarf_need_debug_line_section(dbg) == TRUE)
if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0)
return -1;
die_off = cu_header_size;
res = dbg->de_reloc_name(dbg, DEBUG_INFO, BEGIN_LEN_SIZE +
sizeof(Dwarf_Half),
dbg->de_sect_name_idx[DEBUG_ABBREV],
dwarf_drt_data_reloc, uwordb_size);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
}
first_child = curdie->di_child;
while (first_child && first_child->di_right) {
if (first_child->di_child)
dwarf_add_AT_reference(dbg,
first_child,
DW_AT_sibling,
first_child->di_right, error);
first_child = first_child->di_right;
}
while (curdie != NULL) {
int nbytes;
Dwarf_P_Attribute curattr;
char *space;
int res;
char buff1[ENCODE_SPACE_NEEDED];
curdie->di_offset = die_off;
curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head);
if (curabbrev == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
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;
}
}
res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx,
&nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
space = _dwarf_p_get_alloc(dbg, nbytes);
if (space == NULL) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
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) {
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;
default:
break;
}
res = dbg->de_reloc_name(dbg, DEBUG_INFO, die_off + curattr->ar_rel_offset,
curattr->ar_rel_symidx,
dwarf_drt_data_reloc,
curattr->ar_reloc_len);
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
}
}
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;
die_off++;
}
if (curdie != NULL)
curdie = curdie->di_right;
}
}
curdie = dbg->de_dies;
while (curdie != NULL) {
Dwarf_P_Attribute curattr;
GET_CHUNK(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;
while (curattr) {
GET_CHUNK(dbg, elfsectno_of_debug_info, data,
(unsigned long) curattr->ar_nbytes, error);
switch (curattr->ar_attribute_form) {
case DW_FORM_ref1:
{
if (curattr->ar_ref_die->di_offset >
(unsigned) 0xff) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
}
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, -1);
}
dh = curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &dh,
sizeof(dh), sizeof(Dwarf_Half));
break;
}
case DW_FORM_ref_addr:
{
du = curattr->ar_ref_die->di_offset;
{
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), uwordb_size);
}
break;
}
case DW_FORM_ref4:
{
if (curattr->ar_ref_die->di_offset >
(unsigned) 0xffffffff) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
}
dw = (Dwarf_Word) curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &dw,
sizeof(dw), sizeof(Dwarf_ufixed));
break;
}
case DW_FORM_ref8:
du = curattr->ar_ref_die->di_offset;
WRITE_UNALIGNED(dbg, (void *) data,
(const void *) &du,
sizeof(du), sizeof(Dwarf_Unsigned));
break;
case DW_FORM_ref_udata:
{
int nbytes;
char buff1[ENCODE_SPACE_NEEDED];
res =
_dwarf_pro_encode_leb128_nm(curattr->
ar_ref_die->
di_offset, &nbytes,
buff1,
sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
memcpy(data, buff1, nbytes);
break;
}
default:
memcpy((void *) data,
(const void *) curattr->ar_data,
curattr->ar_nbytes);
break;
}
curattr = curattr->ar_next;
}
if (curdie->di_child)
curdie = curdie->di_child;
else {
while (curdie != NULL && curdie->di_right == NULL) {
GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error);
*data = '\0';
curdie = curdie->di_parent;
}
if (curdie != NULL)
curdie = curdie->di_right;
}
}
du = die_off - BEGIN_LEN_SIZE;
WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size),
(const void *) &du, sizeof(du), uwordb_size);
data = 0;
abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV];
curabbrev = abbrev_head;
while (curabbrev) {
char *val;
int nbytes;
int idx;
int res;
char buff1[ENCODE_SPACE_NEEDED];
res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, &nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
val = buff1;
memcpy((void *) data, (const void *) val, nbytes);
res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_tag, &nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
val = buff1;
GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
memcpy((void *) data, (const void *) val, nbytes);
db = curabbrev->abb_children;
GET_CHUNK(dbg, abbrevsectno, data, sizeof(Dwarf_Ubyte), error);
WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
sizeof(db), sizeof(Dwarf_Ubyte));
for (idx = 0; idx < curabbrev->abb_n_attr; idx++) {
res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_attrs[idx],
&nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
val = buff1;
GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
memcpy((void *) data, (const void *) val, nbytes);
res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_forms[idx],
&nbytes,
buff1, sizeof(buff1));
if (res != DW_DLV_OK) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
}
val = buff1;
GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
memcpy((void *) data, (const void *) val, nbytes);
}
GET_CHUNK(dbg, abbrevsectno, data, 2, error);
*data = 0;
data++;
*data = 0;
curabbrev = curabbrev->abb_next;
}
GET_CHUNK(dbg, abbrevsectno, data, 1, error);
*data = 0;
return (int) dbg->de_n_debug_sect;
}
Dwarf_Ptr
dwarf_get_section_bytes(Dwarf_P_Debug dbg,
Dwarf_Signed dwarf_section,
Dwarf_Signed * section_idx,
Dwarf_Unsigned * length, Dwarf_Error * error)
{
Dwarf_Ptr buf;
if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL);
}
if (dbg->de_debug_sects == 0) {
return NULL;
}
if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
return NULL;
}
*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;
return buf;
}
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;
}
Dwarf_Small *
_dwarf_pro_buffer(Dwarf_P_Debug dbg,
int elfsectno, unsigned long nbytes)
{
Dwarf_P_Section_Data cursect;
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;
}
}
static int
_dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv)
{
int opc;
addr_adv = addr_adv / MIN_INST_LENGTH;
if (line_adv == 0 && addr_adv == 0)
return OPC_INCS_ZERO;
if (line_adv >= LINE_BASE && line_adv < LINE_BASE + LINE_RANGE) {
opc =
(line_adv - LINE_BASE) + (addr_adv * LINE_RANGE) +
OPCODE_BASE;
if (opc > 255)
return OPC_OUT_OF_RANGE;
return opc;
} else
return LINE_OUT_OF_RANGE;
}
static Dwarf_P_Abbrev
_dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head)
{
Dwarf_P_Abbrev curabbrev;
Dwarf_P_Attribute curattr;
int res1;
int nattrs;
int match;
Dwarf_ufixed *forms = 0;
Dwarf_ufixed *attrs = 0;
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)) &&
(die->di_n_attr == curabbrev->abb_n_attr)) {
curattr = die->di_attrs;
match = 1;
while (match && curattr) {
res1 = _dwarf_pro_match_attr(curattr,
curabbrev,
(int) curabbrev->
abb_n_attr);
if (res1 == 0)
match = 0;
curattr = curattr->ar_next;
}
if (match == 1)
return curabbrev;
}
curabbrev = curabbrev->abb_next;
}
if (die->di_n_attr != 0) {
forms = (Dwarf_ufixed *)
_dwarf_p_get_alloc(NULL,
sizeof(Dwarf_ufixed) * die->di_n_attr);
if (forms == NULL)
return NULL;
attrs = (Dwarf_ufixed *)
_dwarf_p_get_alloc(NULL,
sizeof(Dwarf_ufixed) * die->di_n_attr);
if (attrs == NULL)
return NULL;
}
nattrs = 0;
curattr = die->di_attrs;
while (curattr) {
attrs[nattrs] = curattr->ar_attribute;
forms[nattrs] = curattr->ar_attribute_form;
nattrs++;
curattr = curattr->ar_next;
}
curabbrev = (Dwarf_P_Abbrev)
_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Abbrev_s));
if (curabbrev == NULL)
return NULL;
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_n_attr = die->di_n_attr;
curabbrev->abb_idx = 0;
curabbrev->abb_next = NULL;
return curabbrev;
}
static int
_dwarf_pro_match_attr(Dwarf_P_Attribute attr,
Dwarf_P_Abbrev abbrev, int no_attr)
{
int i;
int found = 0;
for (i = 0; i < no_attr; i++) {
if (attr->ar_attribute == abbrev->abb_attrs[i] &&
attr->ar_attribute_form == abbrev->abb_forms[i]) {
found = 1;
break;
}
}
return found;
}