Home | History | Annotate | Line # | Download | only in libdwarf
libdwarf_reloc.c revision 1.6
      1  1.6  christos /*	$NetBSD: libdwarf_reloc.c,v 1.6 2024/03/27 21:53:06 christos Exp $	*/
      2  1.2  christos 
      3  1.1  christos /*-
      4  1.1  christos  * Copyright (c) 2010 Kai Wang
      5  1.1  christos  * All rights reserved.
      6  1.1  christos  *
      7  1.1  christos  * Redistribution and use in source and binary forms, with or without
      8  1.1  christos  * modification, are permitted provided that the following conditions
      9  1.1  christos  * are met:
     10  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  christos  *    documentation and/or other materials provided with the distribution.
     15  1.1  christos  *
     16  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  christos  * SUCH DAMAGE.
     27  1.1  christos  */
     28  1.1  christos 
     29  1.1  christos #include "_libdwarf.h"
     30  1.1  christos 
     31  1.6  christos __RCSID("$NetBSD: libdwarf_reloc.c,v 1.6 2024/03/27 21:53:06 christos Exp $");
     32  1.5  christos ELFTC_VCSID("Id: libdwarf_reloc.c 3741 2019-06-07 06:32:01Z jkoshy");
     33  1.2  christos 
     34  1.1  christos Dwarf_Unsigned
     35  1.1  christos _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
     36  1.1  christos {
     37  1.1  christos 
     38  1.1  christos 	assert(dbg != NULL);
     39  1.6  christos #ifdef BUILTIN_ELF_HEADERS
     40  1.1  christos 	switch (dbg->dbgp_isa) {
     41  1.3  christos 	case DW_ISA_AARCH64:
     42  1.3  christos 		return (is64 ? R_AARCH64_ABS64 : R_AARCH64_ABS32);
     43  1.1  christos 	case DW_ISA_X86:
     44  1.1  christos 		return (R_386_32);
     45  1.1  christos 	case DW_ISA_X86_64:
     46  1.1  christos 		return (is64 ? R_X86_64_64 : R_X86_64_32);
     47  1.1  christos 	case DW_ISA_SPARC:
     48  1.1  christos 		return (is64 ? R_SPARC_UA64 : R_SPARC_UA32);
     49  1.1  christos 	case DW_ISA_PPC:
     50  1.5  christos 		return (is64 ? R_PPC64_ADDR64 : R_PPC_ADDR32);
     51  1.1  christos 	case DW_ISA_ARM:
     52  1.1  christos 		return (R_ARM_ABS32);
     53  1.1  christos 	case DW_ISA_MIPS:
     54  1.1  christos 		return (is64 ? R_MIPS_64 : R_MIPS_32);
     55  1.5  christos 	case DW_ISA_RISCV:
     56  1.5  christos 		return (is64 ? R_RISCV_64 : R_RISCV_32);
     57  1.1  christos 	case DW_ISA_IA64:
     58  1.1  christos 		return (is64 ? R_IA_64_DIR64LSB : R_IA_64_DIR32LSB);
     59  1.1  christos 	default:
     60  1.1  christos 		break;
     61  1.1  christos 	}
     62  1.6  christos #endif
     63  1.1  christos 	return (0);		/* NOT REACHED */
     64  1.1  christos }
     65  1.1  christos 
     66  1.1  christos int
     67  1.1  christos _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
     68  1.1  christos {
     69  1.1  christos 
     70  1.6  christos #ifdef BUILTIN_ELF_HEADERS
     71  1.1  christos 	switch (dbg->dbg_machine) {
     72  1.1  christos 	case EM_NONE:
     73  1.1  christos 		break;
     74  1.3  christos 	case EM_AARCH64:
     75  1.3  christos 		if (rel_type == R_AARCH64_ABS32)
     76  1.3  christos 			return (4);
     77  1.3  christos 		else if (rel_type == R_AARCH64_ABS64)
     78  1.3  christos 			return (8);
     79  1.3  christos 		break;
     80  1.1  christos 	case EM_ARM:
     81  1.1  christos 		if (rel_type == R_ARM_ABS32)
     82  1.1  christos 			return (4);
     83  1.1  christos 		break;
     84  1.1  christos 	case EM_386:
     85  1.3  christos 	case EM_IAMCU:
     86  1.1  christos 		if (rel_type == R_386_32)
     87  1.1  christos 			return (4);
     88  1.1  christos 		break;
     89  1.1  christos 	case EM_X86_64:
     90  1.1  christos 		if (rel_type == R_X86_64_32)
     91  1.1  christos 			return (4);
     92  1.1  christos 		else if (rel_type == R_X86_64_64)
     93  1.1  christos 			return (8);
     94  1.1  christos 		break;
     95  1.1  christos 	case EM_SPARC:
     96  1.1  christos 		if (rel_type == R_SPARC_UA32)
     97  1.1  christos 			return (4);
     98  1.1  christos 		else if (rel_type == R_SPARC_UA64)
     99  1.1  christos 			return (8);
    100  1.1  christos 		break;
    101  1.1  christos 	case EM_PPC:
    102  1.1  christos 		if (rel_type == R_PPC_ADDR32)
    103  1.1  christos 			return (4);
    104  1.1  christos 		break;
    105  1.5  christos 	case EM_PPC64:
    106  1.5  christos 		if (rel_type == R_PPC_ADDR32)
    107  1.5  christos 			return (4);
    108  1.5  christos 		else if (rel_type == R_PPC64_ADDR64)
    109  1.5  christos 			return (8);
    110  1.5  christos 		break;
    111  1.1  christos 	case EM_MIPS:
    112  1.1  christos 		if (rel_type == R_MIPS_32)
    113  1.1  christos 			return (4);
    114  1.1  christos 		else if (rel_type == R_MIPS_64)
    115  1.1  christos 			return (8);
    116  1.1  christos 		break;
    117  1.5  christos 	case EM_RISCV:
    118  1.5  christos 		if (rel_type == R_RISCV_32)
    119  1.5  christos 			return (4);
    120  1.5  christos 		else if (rel_type == R_RISCV_64)
    121  1.5  christos 			return (8);
    122  1.5  christos 		break;
    123  1.1  christos 	case EM_IA_64:
    124  1.1  christos 		if (rel_type == R_IA_64_SECREL32LSB)
    125  1.1  christos 			return (4);
    126  1.1  christos 		else if (rel_type == R_IA_64_DIR64LSB)
    127  1.1  christos 			return (8);
    128  1.1  christos 		break;
    129  1.1  christos 	default:
    130  1.1  christos 		break;
    131  1.1  christos 	}
    132  1.6  christos #endif
    133  1.1  christos 
    134  1.1  christos 	/* unknown relocation. */
    135  1.1  christos 	return (0);
    136  1.1  christos }
    137  1.1  christos 
    138  1.1  christos int
    139  1.1  christos _dwarf_reloc_section_init(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp,
    140  1.1  christos     Dwarf_P_Section ref, Dwarf_Error *error)
    141  1.1  christos {
    142  1.1  christos 	Dwarf_Rel_Section drs;
    143  1.1  christos 	char name[128];
    144  1.1  christos 	int pseudo;
    145  1.1  christos 
    146  1.1  christos 	assert(dbg != NULL && drsp != NULL && ref != NULL);
    147  1.1  christos 
    148  1.1  christos 	if ((drs = calloc(1, sizeof(struct _Dwarf_Rel_Section))) == NULL) {
    149  1.1  christos 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    150  1.1  christos 		return (DW_DLE_MEMORY);
    151  1.1  christos 	}
    152  1.1  christos 
    153  1.1  christos 	drs->drs_ref = ref;
    154  1.1  christos 
    155  1.1  christos 	/*
    156  1.1  christos 	 * FIXME The logic here is most likely wrong. It should
    157  1.1  christos 	 * be the ISA that determines relocation type.
    158  1.1  christos 	 */
    159  1.1  christos 	if (dbg->dbgp_flags & DW_DLC_SIZE_64)
    160  1.1  christos 		drs->drs_addend = 1;
    161  1.1  christos 	else
    162  1.1  christos 		drs->drs_addend = 0;
    163  1.1  christos 
    164  1.1  christos 	if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS)
    165  1.1  christos 		pseudo = 1;
    166  1.1  christos 	else
    167  1.1  christos 		pseudo = 0;
    168  1.1  christos 
    169  1.1  christos 	snprintf(name, sizeof(name), "%s%s",
    170  1.1  christos 	    drs->drs_addend ? ".rela" : ".rel", ref->ds_name);
    171  1.1  christos 	if (_dwarf_section_init(dbg, &drs->drs_ds, name, pseudo, error) !=
    172  1.1  christos 	    DW_DLE_NONE) {
    173  1.1  christos 		free(drs);
    174  1.1  christos 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    175  1.1  christos 		return (DW_DLE_MEMORY);
    176  1.1  christos 	}
    177  1.1  christos 
    178  1.1  christos 	STAILQ_INIT(&drs->drs_dre);
    179  1.1  christos 	STAILQ_INSERT_TAIL(&dbg->dbgp_drslist, drs, drs_next);
    180  1.1  christos 	dbg->dbgp_drscnt++;
    181  1.1  christos 	*drsp = drs;
    182  1.1  christos 
    183  1.1  christos 	return (DW_DLE_NONE);
    184  1.1  christos }
    185  1.1  christos 
    186  1.1  christos void
    187  1.1  christos _dwarf_reloc_section_free(Dwarf_P_Debug dbg, Dwarf_Rel_Section *drsp)
    188  1.1  christos {
    189  1.1  christos 	Dwarf_Rel_Section drs, tdrs;
    190  1.1  christos 	Dwarf_Rel_Entry dre, tdre;
    191  1.1  christos 
    192  1.1  christos 	assert(dbg != NULL && drsp != NULL);
    193  1.1  christos 
    194  1.1  christos 	if (*drsp == NULL)
    195  1.1  christos 		return;
    196  1.1  christos 
    197  1.1  christos 	STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) {
    198  1.1  christos 		if (drs != *drsp)
    199  1.1  christos 			continue;
    200  1.1  christos 		STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section,
    201  1.1  christos 		    drs_next);
    202  1.1  christos 		STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) {
    203  1.1  christos 			STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry,
    204  1.1  christos 			    dre_next);
    205  1.1  christos 			free(dre);
    206  1.1  christos 		}
    207  1.1  christos 		if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0)
    208  1.1  christos 			_dwarf_section_free(dbg, &drs->drs_ds);
    209  1.1  christos 		else {
    210  1.1  christos 			if (drs->drs_ds->ds_name)
    211  1.1  christos 				free(drs->drs_ds->ds_name);
    212  1.1  christos 			free(drs->drs_ds);
    213  1.1  christos 		}
    214  1.1  christos 		free(drs);
    215  1.1  christos 		*drsp = NULL;
    216  1.1  christos 		dbg->dbgp_drscnt--;
    217  1.1  christos 		break;
    218  1.1  christos 	}
    219  1.1  christos }
    220  1.1  christos 
    221  1.1  christos int
    222  1.1  christos _dwarf_reloc_entry_add(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
    223  1.1  christos     Dwarf_P_Section ds, unsigned char type, unsigned char length,
    224  1.1  christos     Dwarf_Unsigned offset, Dwarf_Unsigned symndx, Dwarf_Unsigned addend,
    225  1.1  christos     const char *secname, Dwarf_Error *error)
    226  1.1  christos {
    227  1.1  christos 	Dwarf_Rel_Entry dre;
    228  1.1  christos 	Dwarf_Unsigned reloff;
    229  1.1  christos 	int ret;
    230  1.1  christos 
    231  1.1  christos 	assert(drs != NULL);
    232  1.1  christos 	assert(offset <= ds->ds_size);
    233  1.1  christos 	reloff = offset;
    234  1.1  christos 
    235  1.1  christos 	/*
    236  1.1  christos 	 * If the DW_DLC_SYMBOLIC_RELOCATIONS flag is set or ElfXX_Rel
    237  1.1  christos 	 * is used instead of ELfXX_Rela, we need to write the addend
    238  1.1  christos 	 * in the storage unit to be relocated. Otherwise write 0 in the
    239  1.1  christos 	 * storage unit and the addend will be written into relocation
    240  1.1  christos 	 * section later.
    241  1.1  christos 	 */
    242  1.1  christos 	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) ||
    243  1.1  christos 	    drs->drs_addend == 0)
    244  1.1  christos 		ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
    245  1.1  christos 		    addend, length, error);
    246  1.1  christos 	else
    247  1.1  christos 		ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
    248  1.1  christos 		    0, length, error);
    249  1.1  christos 	if (ret != DW_DLE_NONE)
    250  1.1  christos 		return (ret);
    251  1.1  christos 	if (offset > ds->ds_size)
    252  1.1  christos 		ds->ds_size = offset;
    253  1.1  christos 
    254  1.1  christos 	if ((dre = calloc(1, sizeof(struct _Dwarf_Rel_Entry))) == NULL) {
    255  1.1  christos 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    256  1.1  christos 		return (DW_DLE_MEMORY);
    257  1.1  christos 	}
    258  1.1  christos 	STAILQ_INSERT_TAIL(&drs->drs_dre, dre, dre_next);
    259  1.1  christos 	dre->dre_type = type;
    260  1.1  christos 	dre->dre_length = length;
    261  1.1  christos 	dre->dre_offset = reloff;
    262  1.1  christos 	dre->dre_symndx = symndx;
    263  1.1  christos 	dre->dre_addend = addend;
    264  1.1  christos 	dre->dre_secname = secname;
    265  1.1  christos 	drs->drs_drecnt++;
    266  1.1  christos 
    267  1.1  christos 	return (DW_DLE_NONE);
    268  1.1  christos }
    269  1.1  christos 
    270  1.1  christos int
    271  1.1  christos _dwarf_reloc_entry_add_pair(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
    272  1.1  christos     Dwarf_P_Section ds, unsigned char length, Dwarf_Unsigned offset,
    273  1.1  christos     Dwarf_Unsigned symndx, Dwarf_Unsigned esymndx, Dwarf_Unsigned symoff,
    274  1.1  christos     Dwarf_Unsigned esymoff, Dwarf_Error *error)
    275  1.1  christos {
    276  1.1  christos 	Dwarf_Rel_Entry dre;
    277  1.1  christos 	Dwarf_Unsigned reloff;
    278  1.1  christos 	int ret;
    279  1.1  christos 
    280  1.1  christos 	assert(drs != NULL);
    281  1.1  christos 	assert(offset <= ds->ds_size);
    282  1.1  christos 	assert(dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS);
    283  1.1  christos 	reloff = offset;
    284  1.1  christos 
    285  1.1  christos 	/* Write net offset into section stream. */
    286  1.1  christos 	ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &offset,
    287  1.1  christos 	    esymoff - symoff, length, error);
    288  1.1  christos 	if (ret != DW_DLE_NONE)
    289  1.1  christos 		return (ret);
    290  1.1  christos 	if (offset > ds->ds_size)
    291  1.1  christos 		ds->ds_size = offset;
    292  1.1  christos 
    293  1.1  christos 	if ((dre = calloc(2, sizeof(struct _Dwarf_Rel_Entry))) == NULL) {
    294  1.1  christos 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    295  1.1  christos 		return (DW_DLE_MEMORY);
    296  1.1  christos 	}
    297  1.1  christos 	STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[0], dre_next);
    298  1.1  christos 	STAILQ_INSERT_TAIL(&drs->drs_dre, &dre[1], dre_next);
    299  1.1  christos 	dre[0].dre_type = dwarf_drt_first_of_length_pair;
    300  1.1  christos 	dre[0].dre_length = length;
    301  1.1  christos 	dre[0].dre_offset = reloff;
    302  1.1  christos 	dre[0].dre_symndx = symndx;
    303  1.1  christos 	dre[0].dre_addend = 0;
    304  1.1  christos 	dre[0].dre_secname = NULL;
    305  1.1  christos 	dre[1].dre_type = dwarf_drt_second_of_length_pair;
    306  1.1  christos 	dre[1].dre_length = length;
    307  1.1  christos 	dre[1].dre_offset = reloff;
    308  1.1  christos 	dre[1].dre_symndx = esymndx;
    309  1.1  christos 	dre[1].dre_addend = 0;
    310  1.1  christos 	dre[1].dre_secname = NULL;
    311  1.1  christos 	drs->drs_drecnt += 2;
    312  1.1  christos 
    313  1.1  christos 	return (DW_DLE_NONE);
    314  1.1  christos }
    315  1.1  christos 
    316  1.1  christos int
    317  1.1  christos _dwarf_reloc_section_finalize(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
    318  1.1  christos     Dwarf_Error *error)
    319  1.1  christos {
    320  1.1  christos 	Dwarf_P_Section ds;
    321  1.1  christos 	Dwarf_Unsigned unit;
    322  1.1  christos 	int ret, size;
    323  1.1  christos 
    324  1.1  christos 	assert(dbg != NULL && drs != NULL && drs->drs_ds != NULL &&
    325  1.1  christos 	    drs->drs_ref != NULL);
    326  1.1  christos 
    327  1.1  christos 	ds = drs->drs_ds;
    328  1.1  christos 
    329  1.1  christos 	/*
    330  1.1  christos 	 * Calculate the size (in bytes) of the relocation section.
    331  1.1  christos 	 */
    332  1.1  christos 	if (dbg->dbgp_flags & DW_DLC_SIZE_64)
    333  1.1  christos 		unit = drs->drs_addend ? sizeof(Elf64_Rela) : sizeof(Elf64_Rel);
    334  1.1  christos 	else
    335  1.1  christos 		unit = drs->drs_addend ? sizeof(Elf32_Rela) : sizeof(Elf32_Rel);
    336  1.1  christos 	assert(ds->ds_size == 0);
    337  1.1  christos 	size = drs->drs_drecnt * unit;
    338  1.1  christos 
    339  1.1  christos 	/*
    340  1.1  christos 	 * Discard this relocation section if there is no entry in it.
    341  1.1  christos 	 */
    342  1.1  christos 	if (size == 0) {
    343  1.1  christos 		_dwarf_reloc_section_free(dbg, &drs);
    344  1.1  christos 		return (DW_DLE_NONE);
    345  1.1  christos 	}
    346  1.1  christos 
    347  1.1  christos 	/*
    348  1.1  christos 	 * If we are under stream mode, realloc the section data block to
    349  1.1  christos 	 * this size.
    350  1.1  christos 	 */
    351  1.1  christos 	if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
    352  1.1  christos 		ds->ds_cap = size;
    353  1.1  christos 		if ((ds->ds_data = realloc(ds->ds_data, (size_t) ds->ds_cap)) ==
    354  1.1  christos 		    NULL) {
    355  1.1  christos 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    356  1.1  christos 			return (DW_DLE_MEMORY);
    357  1.1  christos 		}
    358  1.1  christos 	}
    359  1.1  christos 
    360  1.1  christos 	/*
    361  1.1  christos 	 * Notify the application the creation of this relocation section.
    362  1.1  christos 	 * Note that the section link here should point to the .symtab
    363  1.1  christos 	 * section, we set it to 0 since we have no way to know .symtab
    364  1.1  christos 	 * section index.
    365  1.1  christos 	 */
    366  1.1  christos 	ret = _dwarf_pro_callback(dbg, ds->ds_name, size,
    367  1.1  christos 	    drs->drs_addend ? SHT_RELA : SHT_REL, 0, 0, drs->drs_ref->ds_ndx,
    368  1.1  christos 	    &ds->ds_symndx, NULL);
    369  1.1  christos 	if (ret < 0) {
    370  1.1  christos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ELF_SECT_ERR);
    371  1.1  christos 		return (DW_DLE_ELF_SECT_ERR);
    372  1.1  christos 	}
    373  1.1  christos 	ds->ds_ndx = ret;
    374  1.1  christos 
    375  1.1  christos 	return (DW_DLE_NONE);
    376  1.1  christos }
    377  1.1  christos 
    378  1.1  christos int
    379  1.1  christos _dwarf_reloc_section_gen(Dwarf_P_Debug dbg, Dwarf_Rel_Section drs,
    380  1.1  christos     Dwarf_Error *error)
    381  1.1  christos {
    382  1.1  christos 	Dwarf_Rel_Entry dre;
    383  1.1  christos 	Dwarf_P_Section ds;
    384  1.1  christos 	Dwarf_Unsigned type;
    385  1.1  christos 	int ret;
    386  1.1  christos 
    387  1.1  christos 	assert((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0);
    388  1.1  christos 	assert(drs->drs_ds != NULL && drs->drs_ds->ds_size == 0);
    389  1.1  christos 	assert(!STAILQ_EMPTY(&drs->drs_dre));
    390  1.1  christos 	ds = drs->drs_ds;
    391  1.1  christos 
    392  1.1  christos 	STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) {
    393  1.1  christos 		assert(dre->dre_length == 4 || dre->dre_length == 8);
    394  1.1  christos 		type = _dwarf_get_reloc_type(dbg, dre->dre_length == 8);
    395  1.1  christos 		if (dbg->dbgp_flags & DW_DLC_SIZE_64) {
    396  1.1  christos 			/* Write r_offset (8 bytes) */
    397  1.1  christos 			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
    398  1.1  christos 			    &ds->ds_size, dre->dre_offset, 8, error);
    399  1.1  christos 			if (ret != DW_DLE_NONE)
    400  1.1  christos 				return (ret);
    401  1.1  christos 			/* Write r_info (8 bytes) */
    402  1.1  christos 			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
    403  1.1  christos 			    &ds->ds_size, ELF64_R_INFO(dre->dre_symndx, type),
    404  1.1  christos 			    8, error);
    405  1.1  christos 			if (ret != DW_DLE_NONE)
    406  1.1  christos 				return (ret);
    407  1.1  christos 			/* Write r_addend (8 bytes) */
    408  1.1  christos 			if (drs->drs_addend) {
    409  1.1  christos 				ret = dbg->write_alloc(&ds->ds_data,
    410  1.1  christos 				    &ds->ds_cap, &ds->ds_size, dre->dre_addend,
    411  1.1  christos 				    8, error);
    412  1.1  christos 				if (ret != DW_DLE_NONE)
    413  1.1  christos 					return (ret);
    414  1.1  christos 			}
    415  1.1  christos 		} else {
    416  1.1  christos 			/* Write r_offset (4 bytes) */
    417  1.1  christos 			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
    418  1.1  christos 			    &ds->ds_size, dre->dre_offset, 4, error);
    419  1.1  christos 			if (ret != DW_DLE_NONE)
    420  1.1  christos 				return (ret);
    421  1.1  christos 			/* Write r_info (4 bytes) */
    422  1.1  christos 			ret = dbg->write_alloc(&ds->ds_data, &ds->ds_cap,
    423  1.1  christos 			    &ds->ds_size, ELF32_R_INFO(dre->dre_symndx, type),
    424  1.1  christos 			    4, error);
    425  1.1  christos 			if (ret != DW_DLE_NONE)
    426  1.1  christos 				return (ret);
    427  1.1  christos 			/* Write r_addend (4 bytes) */
    428  1.1  christos 			if (drs->drs_addend) {
    429  1.1  christos 				ret = dbg->write_alloc(&ds->ds_data,
    430  1.1  christos 				    &ds->ds_cap, &ds->ds_size, dre->dre_addend,
    431  1.1  christos 				    4, error);
    432  1.1  christos 				if (ret != DW_DLE_NONE)
    433  1.1  christos 					return (ret);
    434  1.1  christos 			}
    435  1.1  christos 		}
    436  1.1  christos 	}
    437  1.1  christos 	assert(ds->ds_size == ds->ds_cap);
    438  1.1  christos 
    439  1.1  christos 	return (DW_DLE_NONE);
    440  1.1  christos }
    441  1.1  christos 
    442  1.1  christos int
    443  1.1  christos _dwarf_reloc_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
    444  1.1  christos {
    445  1.1  christos 	Dwarf_Rel_Section drs;
    446  1.1  christos 	Dwarf_Rel_Entry dre;
    447  1.1  christos 	Dwarf_P_Section ds;
    448  1.1  christos 	int ret;
    449  1.1  christos 
    450  1.1  christos 	STAILQ_FOREACH(drs, &dbg->dbgp_drslist, drs_next) {
    451  1.1  christos 		/*
    452  1.1  christos 		 * Update relocation entries: translate any section name
    453  1.1  christos 		 * reference to section symbol index.
    454  1.1  christos 		 */
    455  1.1  christos 		STAILQ_FOREACH(dre, &drs->drs_dre, dre_next) {
    456  1.1  christos 			if (dre->dre_secname == NULL)
    457  1.1  christos 				continue;
    458  1.1  christos 			ds = _dwarf_pro_find_section(dbg, dre->dre_secname);
    459  1.1  christos 			assert(ds != NULL && ds->ds_symndx != 0);
    460  1.1  christos 			dre->dre_symndx = ds->ds_symndx;
    461  1.1  christos 		}
    462  1.1  christos 
    463  1.1  christos 		/*
    464  1.1  christos 		 * Generate ELF relocation section if we are under stream
    465  1.1  christos 		 * mode.
    466  1.1  christos 		 */
    467  1.1  christos 		if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) {
    468  1.1  christos 			ret = _dwarf_reloc_section_gen(dbg, drs, error);
    469  1.1  christos 			if (ret != DW_DLE_NONE)
    470  1.1  christos 				return (ret);
    471  1.1  christos 		}
    472  1.1  christos 	}
    473  1.1  christos 
    474  1.1  christos 	return (DW_DLE_NONE);
    475  1.1  christos }
    476  1.1  christos 
    477  1.1  christos void
    478  1.1  christos _dwarf_reloc_cleanup(Dwarf_P_Debug dbg)
    479  1.1  christos {
    480  1.1  christos 	Dwarf_Rel_Section drs, tdrs;
    481  1.1  christos 	Dwarf_Rel_Entry dre, tdre;
    482  1.1  christos 
    483  1.1  christos 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
    484  1.1  christos 
    485  1.1  christos 	STAILQ_FOREACH_SAFE(drs, &dbg->dbgp_drslist, drs_next, tdrs) {
    486  1.1  christos 		STAILQ_REMOVE(&dbg->dbgp_drslist, drs, _Dwarf_Rel_Section,
    487  1.1  christos 		    drs_next);
    488  1.1  christos 		free(drs->drs_drd);
    489  1.1  christos 		STAILQ_FOREACH_SAFE(dre, &drs->drs_dre, dre_next, tdre) {
    490  1.1  christos 			STAILQ_REMOVE(&drs->drs_dre, dre, _Dwarf_Rel_Entry,
    491  1.1  christos 			    dre_next);
    492  1.1  christos 			free(dre);
    493  1.1  christos 		}
    494  1.1  christos 		if (dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
    495  1.1  christos 			if (drs->drs_ds) {
    496  1.1  christos 				if (drs->drs_ds->ds_name)
    497  1.1  christos 					free(drs->drs_ds->ds_name);
    498  1.1  christos 				free(drs->drs_ds);
    499  1.1  christos 			}
    500  1.1  christos 		}
    501  1.1  christos 		free(drs);
    502  1.1  christos 	}
    503  1.1  christos 	dbg->dbgp_drscnt = 0;
    504  1.1  christos 	dbg->dbgp_drspos = NULL;
    505  1.1  christos }
    506