1/* $NetBSD: dwarf_pro_reloc.c,v 1.5 2024/03/03 17:37:32 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2010 Kai Wang 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include "_libdwarf.h" 30 31__RCSID("$NetBSD: dwarf_pro_reloc.c,v 1.5 2024/03/03 17:37:32 christos Exp $"); 32ELFTC_VCSID("Id: dwarf_pro_reloc.c 2074 2011-10-27 03:34:33Z jkoshy"); 33 34int 35dwarf_get_relocation_info_count(Dwarf_P_Debug dbg, Dwarf_Unsigned *reloc_cnt, 36 int *drd_buffer_version, Dwarf_Error *error) 37{ 38 39 if (dbg == NULL || reloc_cnt == NULL || drd_buffer_version == NULL) { 40 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 41 return (DW_DLV_ERROR); 42 } 43 44 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) { 45 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 46 return (DW_DLV_NO_ENTRY); 47 } 48 49 *reloc_cnt = dbg->dbgp_drscnt; 50 *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; 51 52 return (DW_DLV_OK); 53} 54 55int 56dwarf_get_relocation_info(Dwarf_P_Debug dbg, Dwarf_Signed *elf_section_index, 57 Dwarf_Signed *elf_section_link, Dwarf_Unsigned *reloc_entry_count, 58 Dwarf_Relocation_Data *reloc_buffer, Dwarf_Error *error) 59{ 60 Dwarf_Rel_Section drs; 61 Dwarf_Rel_Entry dre; 62 int i; 63 64 if (dbg == NULL || elf_section_index == NULL || 65 elf_section_link == NULL || reloc_entry_count == NULL || 66 reloc_buffer == NULL) { 67 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 68 return (DW_DLV_ERROR); 69 } 70 71 if ((dbg->dbgp_flags & DW_DLC_SYMBOLIC_RELOCATIONS) == 0) { 72 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 73 return (DW_DLV_NO_ENTRY); 74 } 75 76 if (dbg->dbgp_drscnt == 0) { 77 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 78 return (DW_DLV_NO_ENTRY); 79 } 80 81 if (dbg->dbgp_drspos == NULL) { 82 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 83 return (DW_DLV_NO_ENTRY); 84 } 85 86 drs = dbg->dbgp_drspos; 87 assert(drs->drs_ds != NULL && drs->drs_ref != NULL); 88 assert(drs->drs_drecnt > 0); 89 90 *elf_section_index = drs->drs_ds->ds_ndx; 91 *elf_section_link = drs->drs_ref->ds_ndx; 92 *reloc_entry_count = drs->drs_drecnt; 93 94 if (drs->drs_drd == NULL) { 95 drs->drs_drd = calloc(*reloc_entry_count, 96 sizeof(struct Dwarf_Relocation_Data_s)); 97 if (drs->drs_drd == NULL) { 98 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 99 return (DW_DLV_ERROR); 100 } 101 for (i = 0, dre = STAILQ_FIRST(&drs->drs_dre); 102 (Dwarf_Unsigned) i < *reloc_entry_count && dre != NULL; 103 i++, dre = STAILQ_NEXT(dre, dre_next)) { 104 drs->drs_drd[i].drd_type = dre->dre_type; 105 drs->drs_drd[i].drd_length = dre->dre_length; 106 drs->drs_drd[i].drd_offset = dre->dre_offset; 107 drs->drs_drd[i].drd_symbol_index = dre->dre_symndx; 108 } 109 assert((Dwarf_Unsigned) i == *reloc_entry_count && dre == NULL); 110 } 111 112 *reloc_buffer = drs->drs_drd; 113 114 dbg->dbgp_drspos = STAILQ_NEXT(dbg->dbgp_drspos, drs_next); 115 116 return (DW_DLV_OK); 117} 118