#include <config.h>
#include <stddef.h> /* NULL size_t */
#include <string.h> /* memcpy() strlen() */
#include "dwarf.h"
#include "libdwarf.h"
#include "dwarf_base_types.h"
#include "libdwarfp.h"
#include "dwarf_pro_incl.h"
#include "dwarf_pro_opaque.h"
#include "dwarf_pro_error.h"
#include "dwarf_pro_alloc.h"
#include "dwarf_pro_section.h"
#include "dwarf_pro_macinfo.h"
#define COMMAND_LEN ENCODE_SPACE_NEEDED
#define LINE_LEN ENCODE_SPACE_NEEDED
#define BASE_MACINFO_MALLOC_LEN 2048
static
int
libdwarf_compose_begin(Dwarf_P_Debug dbg,
int
code,
size_t
maxlen,
int
*compose_error_type)
{
unsigned
char
*nextchar;
struct
dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
if
(curblk == 0) {
struct
dw_macinfo_block_s *newb;
size_t
len;
size_t
blen = BASE_MACINFO_MALLOC_LEN;
if
(blen < maxlen) {
blen = 2 * maxlen;
}
len =
sizeof
(
struct
dw_macinfo_block_s) + blen;
newb = (
struct
dw_macinfo_block_s *)
_dwarf_p_get_alloc(dbg, len);
if
(!newb) {
*compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
return
DW_DLV_ERROR;
}
newb->mb_data =
(
char
*) newb +
sizeof
(
struct
dw_macinfo_block_s);
newb->mb_avail_len = blen;
newb->mb_used_len = 0;
newb->mb_macinfo_data_space_len = blen;
dbg->de_first_macinfo = newb;
dbg->de_current_macinfo = newb;
curblk = newb;
}
else
if
(curblk->mb_avail_len < maxlen) {
struct
dw_macinfo_block_s *newb;
size_t
len;
size_t
blen =
dbg->de_current_macinfo->mb_macinfo_data_space_len * 2;
if
(blen < maxlen) {
blen = 2 * maxlen;
}
len =
sizeof
(
struct
dw_macinfo_block_s) + blen;
newb = (
struct
dw_macinfo_block_s *)
_dwarf_p_get_alloc(dbg, len);
if
(!newb) {
*compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
return
DW_DLV_ERROR;
}
newb->mb_data =
(
char
*) newb +
sizeof
(
struct
dw_macinfo_block_s);
newb->mb_avail_len = blen;
newb->mb_used_len = 0;
newb->mb_macinfo_data_space_len = blen;
dbg->de_first_macinfo->mb_next = newb;
dbg->de_current_macinfo = newb;
curblk = newb;
}
dbg->de_compose_avail = curblk->mb_avail_len;
dbg->de_compose_used_len = curblk->mb_used_len;
nextchar = (unsigned
char
*)
(curblk->mb_data + dbg->de_compose_used_len);
*nextchar = code;
dbg->de_compose_avail--;
++dbg->de_compose_used_len;
return
DW_DLV_OK;
}
static
void
libdwarf_compose_add_string(Dwarf_P_Debug dbg,
const
char
*string,
size_t
len)
{
struct
dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
unsigned
char
*nextchar;
nextchar = (unsigned
char
*)
(curblk->mb_data + dbg->de_compose_used_len);
len += 1;
memcpy
(nextchar, string, len);
dbg->de_compose_avail -= len;
dbg->de_compose_used_len += len;
return
;
}
static
int
libdwarf_compose_add_line(Dwarf_P_Debug dbg,
Dwarf_Unsigned line,
int
*compose_error_type)
{
struct
dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
unsigned
char
*nextchar;
int
res;
int
nbytes;
nextchar = (unsigned
char
*)
(curblk->mb_data + dbg->de_compose_used_len);
res = dwarf_encode_leb128(line, &nbytes,
(
char
*) nextchar,
(
int
) dbg->de_compose_avail);
if
(res != DW_DLV_OK) {
*compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
return
DW_DLV_ERROR;
}
dbg->de_compose_avail -= nbytes;
dbg->de_compose_used_len += nbytes;
return
DW_DLV_OK;
}
static
int
libdwarf_compose_complete(Dwarf_P_Debug dbg,
int
*compose_error_type)
{
struct
dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
if
(dbg->de_compose_used_len >
curblk->mb_macinfo_data_space_len) {
*compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
return
DW_DLV_ERROR;
}
curblk->mb_avail_len = dbg->de_compose_avail;
curblk->mb_used_len = dbg->de_compose_used_len;
return
DW_DLV_OK;
}
int
dwarf_def_macro(Dwarf_P_Debug dbg,
Dwarf_Unsigned line,
char
*macname,
char
*macvalue, Dwarf_Error * error)
{
size_t
len;
size_t
len2;
size_t
length_est;
int
res;
int
compose_error_type;
if
(dbg == NULL) {
_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
if
(macname == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
return
DW_DLV_ERROR;
}
len =
strlen
(macname) + 1;
if
(len == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
return
DW_DLV_ERROR;
}
if
(macvalue) {
len2 =
strlen
(macvalue) + 1;
}
else
{
len2 = 0;
}
length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1;
res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
libdwarf_compose_add_string(dbg, macname, len);
libdwarf_compose_add_string(dbg,
" "
, 1);
if
(macvalue) {
libdwarf_compose_add_string(dbg,
" "
, 1);
libdwarf_compose_add_string(dbg, macvalue, len2);
}
res = libdwarf_compose_complete(dbg, &compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
return
DW_DLV_OK;
}
int
dwarf_undef_macro(Dwarf_P_Debug dbg,
Dwarf_Unsigned line,
char
*macname, Dwarf_Error * error)
{
size_t
len;
size_t
length_est;
int
res;
int
compose_error_type;
if
(dbg == NULL) {
_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
if
(macname == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
return
DW_DLV_ERROR;
}
len =
strlen
(macname) + 1;
if
(len == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
return
DW_DLV_ERROR;
}
length_est = COMMAND_LEN + LINE_LEN + len;
res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
libdwarf_compose_add_string(dbg, macname, len);
res = libdwarf_compose_complete(dbg, &compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
return
DW_DLV_OK;
}
int
dwarf_start_macro_file(Dwarf_P_Debug dbg,
Dwarf_Unsigned fileindex,
Dwarf_Unsigned linenumber, Dwarf_Error * error)
{
size_t
length_est;
int
res;
int
compose_error_type;
if
(dbg == NULL) {
_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
length_est = COMMAND_LEN + LINE_LEN + LINE_LEN;
res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file,
length_est,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_add_line(dbg, fileindex,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_add_line(dbg, linenumber,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
return
DW_DLV_OK;
}
int
dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
size_t
length_est;
int
res;
int
compose_error_type;
if
(dbg == NULL) {
_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
length_est = COMMAND_LEN;
res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est,
&compose_error_type);
if
(res == DW_DLV_ERROR) {
_dwarf_p_error(dbg, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_complete(dbg, &compose_error_type);
if
(res == DW_DLV_ERROR) {
_dwarf_p_error(dbg, error, compose_error_type);
return
res;
}
return
res;
}
int
dwarf_vendor_ext(Dwarf_P_Debug dbg,
Dwarf_Unsigned constant,
char
*string, Dwarf_Error * error)
{
size_t
len;
size_t
length_est;
int
res;
int
compose_error_type;
if
(dbg == NULL) {
_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
if
(string == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
return
DW_DLV_ERROR;
}
len =
strlen
(string) + 1;
if
(len == 0) {
_dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
return
DW_DLV_ERROR;
}
length_est = COMMAND_LEN + LINE_LEN + len;
res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext,
length_est,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
res = libdwarf_compose_add_line(dbg, constant,
&compose_error_type);
if
(res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return
DW_DLV_ERROR;
}
libdwarf_compose_add_string(dbg, string, len);
libdwarf_compose_complete(dbg, &compose_error_type);
return
DW_DLV_OK;
}
int
_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg,
Dwarf_Unsigned *nbufs,
Dwarf_Error * error)
{
Dwarf_Unsigned mac_num_bytes;
Dwarf_Small *macinfo;
Dwarf_Small *macinfo_ptr;
struct
dw_macinfo_block_s *m_prev;
struct
dw_macinfo_block_s *m_sect;
mac_num_bytes = 0;
for
(m_sect = dbg->de_first_macinfo; m_sect != NULL;
m_sect = m_sect->mb_next) {
mac_num_bytes += m_sect->mb_used_len;
}
mac_num_bytes += 1;
GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO],
macinfo, (unsigned
long
) mac_num_bytes, error);
macinfo_ptr = macinfo;
m_prev = 0;
for
(m_sect = dbg->de_first_macinfo; m_sect != NULL;
m_sect = m_sect->mb_next) {
memcpy
(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len);
macinfo_ptr += m_sect->mb_used_len;
if
(m_prev) {
_dwarf_p_dealloc((Dwarf_Small *) m_prev);
}
m_prev = m_sect;
}
*macinfo_ptr = 0;
if
(m_prev) {
_dwarf_p_dealloc((Dwarf_Small *) m_prev);
m_prev = 0;
}
dbg->de_first_macinfo = NULL;
dbg->de_current_macinfo = NULL;
*nbufs = dbg->de_n_debug_sect;
return
DW_DLV_OK;
}