Ejemplo n.º 1
0
int
_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
{
    /* Total num of bytes in .debug_aranges section. */
    Dwarf_Unsigned arange_num_bytes = 0;

    /*  Adjustment to align the start of the actual address ranges on a
        boundary aligned with twice the address size. */
    Dwarf_Small remainder = 0;

    /*  Total number of bytes excluding the length field. */
    Dwarf_Unsigned adjusted_length = 0;

    /*  Points to first byte of .debug_aranges buffer. */
    Dwarf_Small *arange = 0;

    /*  Fills in the .debug_aranges buffer. */
    Dwarf_Small *arange_ptr = 0;

    /*  Scans the list of address ranges provided by user. */
    Dwarf_P_Arange given_arange = 0;

    /*  Used to fill in 0. */
    const Dwarf_Signed big_zero = 0;

    int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
    int uword_size = dbg->de_offset_size;
    int upointer_size = dbg->de_pointer_size;
    int res = 0;


    /* ***** BEGIN CODE ***** */

    /* Size of the .debug_aranges section header. */
    arange_num_bytes = extension_word_size + 
        uword_size +       /* Size of length field.  */
        sizeof(Dwarf_Half) +    /* Size of version field. */
        uword_size +            /* Size of .debug_info offset. */
        sizeof(Dwarf_Small) +   /* Size of address size field. */
        sizeof(Dwarf_Small);    /* Size of segment size field. */

    /*  Adjust the size so that the set of aranges begins on a boundary
        that aligned with twice the address size.  This is a Libdwarf
        requirement. */
    remainder = arange_num_bytes % (2 * upointer_size);
    if (remainder != 0)
        arange_num_bytes += (2 * upointer_size) - remainder;


    /* Add the bytes for the actual address ranges. */
    arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);

    GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
        arange, (unsigned long) arange_num_bytes, error);
    arange_ptr = arange;
    if (arange == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (0);
    }
    if (extension_word_size) {
        Dwarf_Word x = DISTINGUISHED_VALUE;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &x,
            sizeof(x), extension_word_size);
        arange_ptr += extension_word_size;
    }

    /* Write the total length of .debug_aranges section. */
    adjusted_length = arange_num_bytes - uword_size
        - extension_word_size;
    {
        Dwarf_Unsigned du = adjusted_length;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &du, sizeof(du), uword_size);
        arange_ptr += uword_size;
    }

    /* Write the version as 2 bytes. */
    {
        Dwarf_Half verstamp = CURRENT_VERSION_STAMP;

        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &verstamp,
            sizeof(verstamp), sizeof(Dwarf_Half));
        arange_ptr += sizeof(Dwarf_Half);
    }


    /* Write the .debug_info offset.  This is always 0. */
    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), uword_size);
    arange_ptr += uword_size;

    {
        unsigned long count = dbg->de_arange_count + 1;
        int res = 0;

        if (dbg->de_reloc_pair) {
            count = (3 * dbg->de_arange_count) + 1;
        }
        /*  The following is a small optimization: not needed for
            correctness */
        res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
            DEBUG_ARANGES, count);
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return (0);
        }
    }

    /* reloc for .debug_info */
    res = dbg->de_reloc_name(dbg,
        DEBUG_ARANGES,
        extension_word_size +
        uword_size + sizeof(Dwarf_Half),
        dbg->de_sect_name_idx[DEBUG_INFO],
        dwarf_drt_data_reloc, uword_size);

    /* Write the size of addresses. */
    *arange_ptr = dbg->de_pointer_size;
    arange_ptr++;

    /*  Write the size of segment addresses. This is zero for MIPS
        architectures. */
    *arange_ptr = 0;
    arange_ptr++;

    /*  Skip over the padding to align the start of the actual address
        ranges to twice the address size. */
    if (remainder != 0)
        arange_ptr += (2 * upointer_size) - remainder;





    /*  The arange address, length are pointer-size fields of the target 
        machine. */
    for (given_arange = dbg->de_arange; given_arange != NULL;
        given_arange = given_arange->ag_next) {

        /* Write relocation record for beginning of address range. */
        res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, 
            arange_ptr - arange,       /* r_offset */
            (long) given_arange->ag_symbol_index,
            dwarf_drt_data_reloc, upointer_size);
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return (0);
        }

        /* Copy beginning address of range. */
        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
            (const void *) &given_arange->ag_begin_address,
            sizeof(given_arange->ag_begin_address),
            upointer_size);
        arange_ptr += upointer_size;

        if (dbg->de_reloc_pair &&
            given_arange->ag_end_symbol_index != 0 &&
            given_arange->ag_length == 0) {
            /*  symbolic reloc, need reloc for length What if we really
                know the length? If so, should use the other part of
                'if'. */
            Dwarf_Unsigned val;

            res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, 
                arange_ptr - arange,   /* r_offset */
                given_arange->ag_symbol_index,
                given_arange->ag_end_symbol_index,
                dwarf_drt_first_of_length_pair,
                upointer_size);
            if (res != DW_DLV_OK) {
                _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
                return (0);
            }

            /*  arange pre-calc so assem text can do .word end - begin
                + val (gets val from stream) */
            val = given_arange->ag_end_symbol_offset -
                given_arange->ag_begin_address;
            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
                (const void *) &val,
                sizeof(val), upointer_size);
            arange_ptr += upointer_size;

        } else {
            /* plain old length to copy, no relocation at all */
            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
                (const void *) &given_arange->ag_length,
                sizeof(given_arange->ag_length),
                upointer_size);
            arange_ptr += upointer_size;
        }
    }

    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), upointer_size);

    arange_ptr += upointer_size;
    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
        (const void *) &big_zero,
        sizeof(big_zero), upointer_size);
    return (int) dbg->de_n_debug_sect;
}
Ejemplo n.º 2
0
/*
        Ensure each stream is a single buffer and
        add that single buffer to the set of stream buffers.

	By creating a new buffer and copying if necessary.
	(If > 1 block, reduce to 1 block)

        Free the input set of buffers if we consolidate.

	We pass back *new_sec_count as zero because we
        are not creating normal sections for a .o, but
	symbolic relocations, separately counted.

        Return -1 on error (malloc failure)


        Return DW_DLV_OK on success. Any other return indicates 
	malloc failed.
*/
int
_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
			       Dwarf_Signed * new_sec_count)
{
    /* unsigned long total_size =0; */
    Dwarf_Small *data;
    int sec_index;
    int res;
    unsigned long i;
    Dwarf_Error error;

    Dwarf_Signed sec_count = 0;

    Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];

    for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {

	unsigned long ct = p_reloc->pr_reloc_total_count;
	struct Dwarf_P_Relocation_Block_s *p_blk;
	struct Dwarf_P_Relocation_Block_s *p_blk_last;

	/* int len */
	int err;


	if (ct == 0) {
	    continue;
	}

	/* len = dbg->de_relocation_record_size; */
	++sec_count;

	/* total_size = ct *len; */
	sec_index = p_reloc->pr_sect_num_of_reloc_sect;
	if (sec_index == 0) {
	    /* call de_func or de_func_b, getting section number of
	       reloc sec */
	    int rel_section_index;
	    int int_name;
	    Dwarf_Unsigned name_idx;

	    /* 
	       This is a bit of a fake, as we do not really have true
	       elf sections at all. Just the data such might contain.
	       But this lets the caller eventually link things
	       together: without this call we would not know what rel
	       data goes with what section when we are asked for the
	       real arrays. */

	    if (dbg->de_func_b) {
		rel_section_index =
		    dbg->de_func_b(_dwarf_rel_section_names[i],
				   dbg->de_relocation_record_size,
				   /* type */ SHT_REL,
				   /* flags */ 0,
				   /* link to symtab, which we cannot
				      know */ SHN_UNDEF,
				   /* sec rels apply to */
				   dbg->de_elf_sects[i],
				   &name_idx, &err);
	    } else {
		rel_section_index =
		    dbg->de_func(_dwarf_rel_section_names[i],
				 dbg->de_relocation_record_size,
				 /* type */ SHT_REL,
				 /* flags */ 0,
				 /* link to symtab, which we cannot
				    know */ SHN_UNDEF,
				 /* sec rels apply to, in elf, sh_info */
				 dbg->de_elf_sects[i], &int_name, &err);
		name_idx = int_name;
	    }
	    if (rel_section_index == -1) {
		{
		    _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
		    return (DW_DLV_ERROR);
		}
	    }
	    p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
	    sec_index = rel_section_index;
	}

	p_blk = p_reloc->pr_first_block;

	if (p_reloc->pr_block_count > 1) {
	    struct Dwarf_P_Relocation_Block_s *new_blk;

	    /* HACK , not normal interfaces, trashing p_reloc
	       current contents! */
	    _dwarf_reset_reloc_sect_info(p_reloc, ct);

	    /* Creating new single block for all 'ct' entries */
	    res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct);


	    if (res != DW_DLV_OK) {
		return res;
	    }
	    new_blk = p_reloc->pr_first_block;

	    data = (Dwarf_Small *) new_blk->rb_data;

	    /* The following loop does the consolidation to a 
	       single block and frees the input block(s). */
	    do {

		unsigned long len =
		    p_blk->rb_where_to_add_next - p_blk->rb_data;

		memcpy(data, p_blk->rb_data, len);
		data += len;

		p_blk_last = p_blk;
		p_blk = p_blk->rb_next;

		_dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
	    } while (p_blk) ;
	    /* ASSERT: sum of len copied == total_size */
	    new_blk->rb_next_slot_to_use = ct;
	    new_blk->rb_where_to_add_next = (char *) data;
	    p_reloc->pr_reloc_total_count = ct;

	    /* have now created a single block, but no change in slots
	       used (pr_reloc_total_count) */
	}
    }

    *new_sec_count = 0;
    return DW_DLV_OK;
}