#include "config.h"
#include "libdwarfdefs.h"
#include <stdio.h>
#include <string.h>
#include "pro_incl.h"
#include "pro_section.h"
#include "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, 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_pro_encode_leb128_nm(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_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return (DW_DLV_ERROR);
}
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_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);
if (res != DW_DLV_OK) {
_dwarf_p_error(NULL, error, compose_error_type);
return (DW_DLV_ERROR);
}
return DW_DLV_OK;
}
int
_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg,
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);
if (macinfo == NULL) {
_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (0);
}
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(dbg, (Dwarf_Small *) m_prev);
m_prev = 0;
}
m_prev = m_sect;
}
*macinfo_ptr = 0;
if (m_prev) {
_dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev);
m_prev = 0;
}
dbg->de_first_macinfo = NULL;
dbg->de_current_macinfo = NULL;
return (int) dbg->de_n_debug_sect;
}