1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Combine stripped files with separate symbols and debug information. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2007 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Written by Roland McGrath <roland@redhat.com>, 2007. 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* TODO: 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng * SHX_XINDEX 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng * prelink vs .debug_* linked addresses 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng */ 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef HAVE_CONFIG_H 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# include <config.h> 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <argp.h> 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <assert.h> 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <errno.h> 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <error.h> 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <fcntl.h> 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <fnmatch.h> 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libintl.h> 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <locale.h> 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <mcheck.h> 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdbool.h> 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio.h> 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio_ext.h> 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <inttypes.h> 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdlib.h> 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <string.h> 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <unistd.h> 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <gelf.h> 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libebl.h> 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libdwfl.h> 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "system.h" 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef _ 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define _(str) gettext (str) 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Name and version of program. */ 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_version (FILE *stream, struct argp_state *state); 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengvoid (*argp_program_version_hook) (FILE *, struct argp_state *) 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng = print_version; 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address. */ 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT; 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Definitions of arguments for argp functions. */ 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const struct argp_option options[] = 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Group 2 will follow group 1 from dwfl_standard_argp. */ 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "match-file-names", 'f', NULL, 0, 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Match MODULE against file names, not module names"), 2 }, 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "ignore-missing", 'i', NULL, 0, N_("Silently skip unfindable files"), 0 }, 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, N_("Output options:"), 0 }, 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "output", 'o', "FILE", 0, N_("Place output into FILE"), 0 }, 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "output-directory", 'd', "DIRECTORY", 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 0, N_("Create multiple output files under DIRECTORY"), 0 }, 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "module-names", 'm', NULL, 0, N_("Use module rather than file names"), 0 }, 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "all", 'a', NULL, 0, 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Create output for modules that have no separate debug information"), 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 0 }, 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "relocate", 'R', NULL, 0, 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Apply relocations to section contents in ET_REL files"), 0 }, 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "list-only", 'n', NULL, 0, 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Only list module and file names, build IDs"), 0 }, 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, NULL, 0 } 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct arg_info 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *output_file; 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *output_dir; 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl *dwfl; 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char **args; 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool list; 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool all; 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool ignore; 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool modnames; 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool match_files; 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool relocate; 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle program arguments. */ 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic error_t 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengparse_opt (int key, char *arg, struct argp_state *state) 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct arg_info *info = state->input; 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (key) 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ARGP_KEY_INIT: 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng state->child_inputs[0] = &info->dwfl; 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'o': 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->output_file != NULL) 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, _("-o option specified twice")); 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->output_file = arg; 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'd': 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->output_dir != NULL) 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, _("-d option specified twice")); 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->output_dir = arg; 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'm': 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->modnames = true; 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'f': 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->match_files = true; 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'a': 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->all = true; 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'i': 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->ignore = true; 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'n': 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->list = true; 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'R': 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->relocate = true; 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ARGP_KEY_ARGS: 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ARGP_KEY_NO_ARGS: 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We "consume" all the arguments here. */ 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->args = &state->argv[state->next]; 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->output_file != NULL && info->output_dir != NULL) 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, _("only one of -o or -d allowed")); 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->list && (info->dwfl == NULL 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || info->output_dir != NULL 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || info->output_file != NULL)) 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("-n cannot be used with explicit files or -o or -d")); 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->output_dir != NULL) 180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct stat64 st; 182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error_t fail = 0; 183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stat64 (info->output_dir, &st) < 0) 184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fail = errno; 185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (!S_ISDIR (st.st_mode)) 186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fail = ENOTDIR; 187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (fail) 188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_failure (state, EXIT_FAILURE, fail, 190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("output directory '%s'"), info->output_dir); 191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return fail; 192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->dwfl == NULL) 196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (state->next + 2 != state->argc) 198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, _("exactly two file arguments are required")); 200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->ignore || info->all || info->modnames || info->relocate) 204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, _("\ 206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng-m, -a, -R, and -i options not allowed with explicit files")); 207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Bail out immediately to prevent dwfl_standard_argp's parser 211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng from defaulting to "-e a.out". */ 212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return ENOSYS; 213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (info->output_file == NULL && info->output_dir == NULL 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !info->list) 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_error (state, 218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("-o or -d is required when using implicit files")); 219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EINVAL; 220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return ARGP_ERR_UNKNOWN; 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Print the version information. */ 230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, "unstrip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, _("\ 235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengCopyright (C) %s Red Hat, Inc.\n\ 236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengThis is free software; see the source for copying conditions. There is NO\n\ 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008"); 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, gettext ("Written by %s.\n"), "Roland McGrath"); 240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define ELF_CHECK(call, msg) \ 243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do \ 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!(call)) \ 246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, msg, elf_errmsg (-1)); \ 247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } while (0) 248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Copy INELF to newly-created OUTELF, exit via error for any problems. */ 250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcopy_elf (Elf *outelf, Elf *inelf) 252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_newehdr (outelf, gelf_getclass (inelf)), 254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create ELF header: %s")); 255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr_mem; 257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr *ehdr = gelf_getehdr (inelf, &ehdr_mem); 258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_ehdr (outelf, ehdr), 259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot copy ELF header: %s")); 260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_phnum > 0) 262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_newphdr (outelf, ehdr->e_phnum), 264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create program headers: %s")); 265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i) 268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_phdr (outelf, i, 269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_getphdr (inelf, i, &phdr_mem)), 270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot copy program header: %s")); 271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (inelf, scn)) != NULL) 275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *newscn = elf_newscn (outelf); 277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem)), 280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot copy section header: %s")); 281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (data != NULL, _("cannot get section data: %s")); 284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *newdata = elf_newdata (newscn); 285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (newdata != NULL, _("cannot copy section data: %s")); 286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *newdata = *data; 287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (newdata, ELF_C_SET, ELF_F_DIRTY); 288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Create directories containing PATH. */ 292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengmake_directories (const char *path) 294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *lastslash = strrchr (path, '/'); 296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (lastslash == NULL) 297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (lastslash > path && lastslash[-1] == '/') 300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng --lastslash; 301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (lastslash == path) 302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *dir = strndupa (path, lastslash - path); 305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (mkdir (dir, 0777) < 0 && errno != EEXIST) 306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (errno == ENOENT) 307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng make_directories (dir); 308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir); 310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* The binutils linker leaves gratuitous section symbols in .symtab 314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng that strip has to remove. Older linkers likewise include a 315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symbol for every section, even unallocated ones, in .dynsym. 316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Because of this, the related sections can shrink in the stripped 317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng file from their original size. Older versions of strip do not 318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust the sh_size field in the debuginfo file's SHT_NOBITS 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng version of the section header, so it can appear larger. */ 320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection_can_shrink (const GElf_Shdr *shdr) 322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr->sh_type) 324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_SYMTAB: 326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_DYNSYM: 327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_HASH: 328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_versym: 329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* See if this symbol table has a leading section symbol for every single 335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng section, in order. The binutils linker produces this. While we're here, 336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng update each section symbol's st_value. */ 337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic size_t 338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsymtab_count_leading_section_symbols (Elf *elf, Elf_Scn *scn, size_t shnum, 339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *newsymdata) 340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shndxdata = NULL; /* XXX */ 343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 1; i < shnum; ++i) 345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = SHN_UNDEF; 348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsymshndx (data, shndxdata, i, &sym_mem, &shndx); 349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s")); 350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, i), &shdr_mem); 353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = sym->st_shndx; 357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx != i || GELF_ST_TYPE (sym->st_info) != STT_SECTION) 359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return i; 360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym->st_value = shdr->sh_addr; 362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = SHN_UNDEF; 364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (newsymdata, shndxdata, i, sym, shndx), 365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return shnum; 369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* We expanded the output section, so update its header. */ 372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengupdate_sh_size (Elf_Scn *outscn, const Elf_Data *data) 374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem); 377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (newshdr != NULL, _("cannot get section header: %s")); 378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newshdr->sh_size = data->d_size; 380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (outscn, newshdr), 382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Update relocation sections using the symbol table. */ 386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengadjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr, 388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t map[], const GElf_Shdr *symshdr) 389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (outscn, NULL); 391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline void adjust_reloc (GElf_Xword *info) 393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t ndx = GELF_R_SYM (*info); 395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ndx != STN_UNDEF) 396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info)); 397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr->sh_type) 400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_REL: 402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i) 403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *rel = gelf_getrel (data, i, &rel_mem); 406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_reloc (&rel->r_info); 407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_rel (data, i, rel), 408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update relocation: %s")); 409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_RELA: 413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i) 414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *rela = gelf_getrela (data, i, &rela_mem); 417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_reloc (&rela->r_info); 418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_rela (data, i, rela), 419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update relocation: %s")); 420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GROUP: 424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem); 427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (newshdr != NULL, _("cannot get section header: %s")); 428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (newshdr->sh_info != STN_UNDEF) 429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newshdr->sh_info = map[newshdr->sh_info - 1]; 431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (outscn, newshdr), 432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_HASH: 438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We must expand the table and rejigger its contents. */ 439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nsym = symshdr->sh_size / symshdr->sh_entsize; 441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t onent = shdr->sh_size / shdr->sh_entsize; 442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (data->d_size == shdr->sh_size); 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define CONVERT_HASH(Hash_Word) \ 445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const old_hash = data->d_buf; \ 447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nbucket = old_hash[0]; \ 448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nchain = old_hash[1]; \ 449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const old_bucket = &old_hash[2]; \ 450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const old_chain = &old_bucket[nbucket]; \ 451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (onent == 2 + nbucket + nchain); \ 452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nent = 2 + nbucket + nsym; \ 454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Hash_Word *const new_hash = xcalloc (nent, sizeof new_hash[0]); \ 455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Hash_Word *const new_bucket = &new_hash[2]; \ 456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Hash_Word *const new_chain = &new_bucket[nbucket]; \ 457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng new_hash[0] = nbucket; \ 459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng new_hash[1] = nsym; \ 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nbucket; ++i) \ 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (old_bucket[i] != STN_UNDEF) \ 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng new_bucket[i] = map[old_bucket[i] - 1]; \ 463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 1; i < nchain; ++i) \ 465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (old_chain[i] != STN_UNDEF) \ 466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng new_chain[map[i - 1]] = map[old_chain[i] - 1]; \ 467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data->d_buf = new_hash; \ 469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data->d_size = nent * sizeof new_hash[0]; \ 470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr->sh_entsize) 473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 4: 475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CONVERT_HASH (Elf32_Word); 476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 8: 478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CONVERT_HASH (Elf64_Xword); 479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng abort (); 482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); 485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng update_sh_size (outscn, data); 486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef CONVERT_HASH 488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_versym: 492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We must expand the table and move its elements around. */ 493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nent = symshdr->sh_size / symshdr->sh_entsize; 495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t onent = shdr->sh_size / shdr->sh_entsize; 496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (nent >= onent); 497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We don't bother using gelf_update_versym because there is 499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng really no conversion to be done. */ 500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (sizeof (Elf32_Versym) == sizeof (GElf_Versym)); 501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (sizeof (Elf64_Versym) == sizeof (GElf_Versym)); 502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Versym *versym = xcalloc (nent, sizeof versym[0]); 503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 1; i < onent; ++i) 505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Versym *v = gelf_getversym (data, i, &versym[map[i - 1]]); 507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (v != NULL, _("cannot get symbol version: %s")); 508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data->d_buf = versym; 511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data->d_size = nent * shdr->sh_entsize; 512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); 513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng update_sh_size (outscn, data); 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("unexpected section type in [%Zu] with sh_link to symtab"), 520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (inscn)); 521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Adjust all the relocation sections in the file. */ 525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengadjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr, 527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t map[]) 528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t new_sh_link = elf_ndxscn (symtab); 530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (elf, scn)) != NULL) 532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (scn != symtab) 533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link) 538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_relocs (scn, scn, shdr, map, symshdr); 539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* The original file probably had section symbols for all of its 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections, even the unallocated ones. To match it as closely as 544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng possible, add in section symbols for the added sections. */ 545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Elf_Data * 546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengadd_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum, 547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *elf, bool rel, Elf_Scn *symscn, size_t shnum) 548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t added = shnum - old_shnum; 550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem); 553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nsym = shdr->sh_size / shdr->sh_entsize; 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t symndx_map[nsym - 1]; 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_info += added; 559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_size += added * shdr->sh_entsize; 560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (symscn, shdr), 562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shndxdata = NULL; /* XXX */ 566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symdata->d_size = shdr->sh_size; 568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symdata->d_buf = xmalloc (symdata->d_size); 569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Copy the existing section symbols. */ 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *old_symdata = elf_getdata (old_symscn, NULL); 572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < old_shnum; ++i) 573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = SHN_UNDEF; 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata, 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng i, &sym_mem, &shndx); 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i, 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym, shndx), 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (i > 0) 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symndx_map[i - 1] = i; 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Add in the new section symbols. */ 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = old_shnum; i < shnum; ++i) 588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr i_shdr_mem; 590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *i_shdr = gelf_getshdr (elf_getscn (elf, i), &i_shdr_mem); 591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (i_shdr != NULL, _("cannot get section header: %s")); 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym = 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .st_value = rel ? 0 : i_shdr->sh_addr, 595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .st_info = GELF_ST_INFO (STB_LOCAL, STT_SECTION), 596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .st_shndx = i < SHN_LORESERVE ? i : SHN_XINDEX 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = i < SHN_LORESERVE ? SHN_UNDEF : i; 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i, 600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &sym, shndx), 601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now copy the rest of the existing symbols. */ 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = old_shnum; i < nsym; ++i) 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = SHN_UNDEF; 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata, 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng i, &sym_mem, &shndx); 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng i + added, sym, shndx), 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symndx_map[i - 1] = i + added; 616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Adjust any relocations referring to the old symbol table. */ 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_all_relocs (elf, symscn, shdr, symndx_map); 620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return symdata; 622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This has the side effect of updating STT_SECTION symbols' values, 625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in case of prelink adjustments. */ 626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Elf_Data * 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_symtab_section_symbols (Elf *elf, bool rel, Elf_Scn *scn, 628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t shnum, size_t shstrndx, 629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *oscn, size_t oshnum, size_t oshstrndx, 630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t debuglink) 631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t n = symtab_count_leading_section_symbols (elf, oscn, oshnum, 633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_getdata (scn, NULL)); 634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (n == oshnum) 636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return add_new_section_symbols (oscn, n, elf, rel, scn, shnum); 637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (n == oshstrndx || (n == debuglink && n == oshstrndx - 1)) 639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return add_new_section_symbols (oscn, n, elf, rel, scn, shstrndx); 640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return NULL; 642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct section 645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn; 647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *outscn; 649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strent *strent; 650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr; 651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_alloc_sections (const struct section *s1, const struct section *s2, 655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool rel) 656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!rel) 658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort by address. */ 660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s1->shdr.sh_addr < s2->shdr.sh_addr) 661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s1->shdr.sh_addr > s2->shdr.sh_addr) 663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* At the same address, preserve original section order. */ 667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (ssize_t) elf_ndxscn (s1->scn) - (ssize_t) elf_ndxscn (s2->scn); 668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2, 672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name1, const char *name2) 673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort by sh_flags as an arbitrary ordering. */ 675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr1->sh_flags < shdr2->sh_flags) 676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr1->sh_flags > shdr2->sh_flags) 678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort by name as last resort. */ 681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return strcmp (name1, name2); 682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_sections (const void *a, const void *b, bool rel) 686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *s1 = a; 688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *s2 = b; 689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort all non-allocated sections last. */ 691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((s1->shdr.sh_flags ^ s2->shdr.sh_flags) & SHF_ALLOC) 692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (s1->shdr.sh_flags & SHF_ALLOC) ? -1 : 1; 693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return ((s1->shdr.sh_flags & SHF_ALLOC) 695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? compare_alloc_sections (s1, s2, rel) 696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : compare_unalloc_sections (&s1->shdr, &s2->shdr, 697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s1->name, s2->name)); 698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_sections_rel (const void *a, const void *b) 702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return compare_sections (a, b, true); 704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint 707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_sections_nonrel (const void *a, const void *b) 708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return compare_sections (a, b, false); 710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct symbol 714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *map; 716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strent *strent; 721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct 725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr value; 727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword size; 728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx; 729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct 732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint8_t info; 734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint8_t other; 735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } info; 736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int16_t compare; 737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* For a symbol discarded after first sort, this matches its better's 741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng map pointer. */ 742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *duplicate; 743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Collect input symbols into our internal form. */ 747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcollect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, Elf_Scn *strscn, 749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nent, const GElf_Addr bias, 750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t scnmap[], struct symbol *table, size_t *map, 751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *split_bss) 752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *strdata = elf_getdata (strscn, NULL); 755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shndxdata = NULL; /* XXX */ 756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 1; i < nent; ++i) 758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = SHN_UNDEF; 761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsymshndx (symdata, shndxdata, i, 762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &sym_mem, &shndx); 763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s")); 764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = sym->st_shndx; 766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_name >= strdata->d_size) 768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("invalid string offset in symbol [%Zu]"), i); 770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct symbol *s = &table[i - 1]; 772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->map = &map[i - 1]; 773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->name = strdata->d_buf + sym->st_name; 774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->value = sym->st_value + bias; 775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->size = sym->st_size; 776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->shndx = shndx; 777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->info.info = sym->st_info; 778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->info.other = sym->st_other; 779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE) 781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->shndx = scnmap[shndx - 1]; 782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_ST_TYPE (s->info.info) == STT_SECTION && !rel) 784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Update the value to match the output section. */ 786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (outelf, s->shndx), 788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &shdr_mem); 789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->value = shdr->sh_addr; 791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (split_bss != NULL 793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && s->value < split_bss->shdr.sh_addr 794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && s->value >= split_bss[-1].shdr.sh_addr 795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shndx == elf_ndxscn (split_bss->outscn)) 796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This symbol was in .bss and was split into .dynbss. */ 797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->shndx = elf_ndxscn (split_bss[-1].outscn); 798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define CMP(value) \ 803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s1->value < s2->value) \ 804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; \ 805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s1->value > s2->value) \ 806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1 807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Compare symbols with a consistent ordering, 809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng but one only meaningful for equality. */ 810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_symbols (const void *a, const void *b) 812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct symbol *s1 = a; 814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct symbol *s2 = b; 815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CMP (value); 817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CMP (size); 818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CMP (shndx); 819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (s1->compare - s2->compare) ?: strcmp (s1->name, s2->name); 821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Compare symbols for output order after slots have been assigned. */ 824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_symbols_output (const void *a, const void *b) 826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct symbol *s1 = a; 828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct symbol *s2 = b; 829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int cmp; 830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort discarded symbols last. */ 832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cmp = (s1->name == NULL) - (s2->name == NULL); 833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cmp == 0) 835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Local symbols must come first. */ 836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cmp = ((GELF_ST_BIND (s2->info.info) == STB_LOCAL) 837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng - (GELF_ST_BIND (s1->info.info) == STB_LOCAL)); 838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cmp == 0) 840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* binutils always puts section symbols first. */ 841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cmp = ((GELF_ST_TYPE (s2->info.info) == STT_SECTION) 842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng - (GELF_ST_TYPE (s1->info.info) == STT_SECTION)); 843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cmp == 0) 845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_ST_TYPE (s1->info.info) == STT_SECTION) 847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* binutils always puts section symbols in section index order. */ 849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CMP (shndx); 850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (s1 == s2); 852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Nothing really matters, so preserve the original order. */ 855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CMP (map); 856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (s1 == s2); 858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return cmp; 861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef CMP 864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Return true iff the flags, size, and name match. */ 866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsections_match (const struct section *sections, size_t i, 868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Shdr *shdr, const char *name) 869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (sections[i].shdr.sh_flags == shdr->sh_flags 871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (sections[i].shdr.sh_size == shdr->sh_size 872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sections[i].shdr.sh_size < shdr->sh_size 873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && section_can_shrink (§ions[i].shdr))) 874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !strcmp (sections[i].name, name)); 875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Locate a matching allocated section in SECTIONS. */ 878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section * 879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengfind_alloc_section (const GElf_Shdr *shdr, GElf_Addr bias, const char *name, 880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section sections[], size_t nalloc) 881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Addr addr = shdr->sh_addr + bias; 883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t l = 0, u = nalloc; 884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (l < u) 885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t i = (l + u) / 2; 887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (addr < sections[i].shdr.sh_addr) 888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng u = i; 889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (addr > sections[i].shdr.sh_addr) 890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng l = i + 1; 891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We've found allocated sections with this address. 894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Find one with matching size, flags, and name. */ 895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (i > 0 && sections[i - 1].shdr.sh_addr == addr) 896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng --i; 897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (; i < nalloc && sections[i].shdr.sh_addr == addr; 898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++i) 899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sections_match (sections, i, shdr, name)) 900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return §ions[i]; 901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return NULL; 905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic inline const char * 908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengget_section_name (size_t ndx, const GElf_Shdr *shdr, const Elf_Data *shstrtab) 909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_name >= shstrtab->d_size) 911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"), 912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx, elf_errmsg (-1)); 913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return shstrtab->d_buf + shdr->sh_name; 914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Fix things up when prelink has moved some allocated sections around 917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng and the debuginfo file's section headers no longer match up. 918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This fills in SECTIONS[0..NALLOC-1].outscn or exits. 919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If there was a .bss section that was split into two sections 920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with the new one preceding it in sh_addr, we return that pointer. */ 921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct section * 922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengfind_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, 923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *main, const GElf_Ehdr *main_ehdr, 924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *main_shstrtab, GElf_Addr bias, 925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sections, 926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nalloc, size_t nsections) 927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Clear assignments that might have been bogus. */ 929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nalloc; ++i) 930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections[i].outscn = NULL; 931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *undo = NULL; 933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = nalloc; i < nsections; ++i) 934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *sec = §ions[i]; 936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->shdr.sh_type == SHT_PROGBITS 937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !(sec->shdr.sh_flags & SHF_ALLOC) 938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !strcmp (sec->name, ".gnu.prelink_undo")) 939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng undo = sec->scn; 941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Find the original allocated sections before prelinking. */ 946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *undo_sections = NULL; 947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t undo_nalloc = 0; 948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (undo != NULL) 949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *undodata = elf_rawdata (undo, NULL); 951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (undodata != NULL, 952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot read '.gnu.prelink_undo' section: %s")); 953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Ehdr e32; 957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Ehdr e64; 958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } ehdr; 959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data dst = 960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = &ehdr, 962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = sizeof ehdr, 963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = ELF_T_EHDR, 964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT 965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data src = *undodata; 967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng src.d_size = gelf_fsize (main, ELF_T_EHDR, 1, EV_CURRENT); 968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng src.d_type = ELF_T_EHDR; 969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_xlatetom (main, &dst, &src, 970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng main_ehdr->e_ident[EI_DATA]) != NULL, 971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot read '.gnu.prelink_undo' section: %s")); 972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast16_t phnum; 974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast16_t shnum; 975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phnum = ehdr.e32.e_phnum; 978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shnum = ehdr.e32.e_shnum; 979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phnum = ehdr.e64.e_phnum; 983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shnum = ehdr.e64.e_shnum; 984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t phsize = gelf_fsize (main, ELF_T_PHDR, phnum, EV_CURRENT); 987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng src.d_buf += src.d_size + phsize; 988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng src.d_size = gelf_fsize (main, ELF_T_SHDR, shnum - 1, EV_CURRENT); 989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng src.d_type = ELF_T_SHDR; 990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) (src.d_buf - undodata->d_buf) > undodata->d_size 991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || undodata->d_size - (src.d_buf - undodata->d_buf) != src.d_size) 992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("invalid contents in '%s' section"), 993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ".gnu.prelink_undo"); 994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Shdr s32[shnum - 1]; 998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Shdr s64[shnum - 1]; 999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } shdr; 1000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dst.d_buf = &shdr; 1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dst.d_size = sizeof shdr; 1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_xlatetom (main, &dst, &src, 1003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng main_ehdr->e_ident[EI_DATA]) != NULL, 1004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot read '.gnu.prelink_undo' section: %s")); 1005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng undo_sections = xmalloc ((shnum - 1) * sizeof undo_sections[0]); 1007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < shnum - 1; ++i) 1008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sec = &undo_sections[undo_nalloc]; 1010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 1011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define COPY(field) sec->shdr.field = shdr.s32[i].field 1013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_name); 1014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_type); 1015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_flags); 1016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_addr); 1017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_offset); 1018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_size); 1019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_link); 1020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_info); 1021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_addralign); 1022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng COPY (sh_entsize); 1023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef COPY 1024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->shdr = shdr.s64[i]; 1027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->shdr.sh_flags & SHF_ALLOC) 1028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->shdr.sh_addr += bias; 1030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab); 1031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->scn = elf_getscn (main, i + 1); /* Really just for ndx. */ 1032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->outscn = NULL; 1033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->strent = NULL; 1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++undo_nalloc; 1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (undo_sections, undo_nalloc, 1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sizeof undo_sections[0], compare_sections_nonrel); 1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool fail = false; 1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline void check_match (bool match, Elf_Scn *scn, const char *name) 1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!match) 1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fail = true; 1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, _("cannot find matching section for [%Zu] '%s'"), 1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn), name); 1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (debug, scn)) != NULL) 1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!(shdr->sh_flags & SHF_ALLOC)) 1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = get_section_name (elf_ndxscn (scn), shdr, 1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debug_shstrtab); 1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (undo_sections != NULL) 1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sec = find_alloc_section (shdr, 0, name, 1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng undo_sections, 1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng undo_nalloc); 1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec != NULL) 1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->outscn = scn; 1073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If there is no prelink info, we are just here to find 1078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the sections to give error messages about. */ 1079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; shdr != NULL && i < nalloc; ++i) 1080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sections[i].outscn == scn) 1081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr = NULL; 1082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_match (shdr == NULL, scn, name); 1083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (fail) 1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exit (EXIT_FAILURE); 1087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we have lined up output sections for each of the original sections 1089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng before prelinking. Translate those to the prelinked sections. 1090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This matches what prelink's undo_sections does. */ 1091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *split_bss = NULL; 1092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < undo_nalloc; ++i) 1093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *undo_sec = &undo_sections[i]; 1095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = undo_sec->name; 1097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng scn = undo_sec->scn; /* This is just for elf_ndxscn. */ 1098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t j = 0; j < nalloc; ++j) 1100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sec = §ions[j]; 1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define RELA_SCALED(field) \ 1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (2 * sec->shdr.field == 3 * undo_sec->shdr.field) 1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->outscn == NULL 1105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sec->shdr.sh_name == undo_sec->shdr.sh_name 1106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sec->shdr.sh_flags == undo_sec->shdr.sh_flags 1107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign 1108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (((sec->shdr.sh_type == undo_sec->shdr.sh_type 1109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize 1110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (sec->shdr.sh_size == undo_sec->shdr.sh_size 1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sec->shdr.sh_size > undo_sec->shdr.sh_size 1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && main_ehdr->e_type == ET_EXEC 1113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !strcmp (sec->name, ".dynstr")))) 1114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sec->shdr.sh_size == undo_sec->shdr.sh_size 1115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize 1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && undo_sec->shdr.sh_type == SHT_NOBITS) 1117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || undo_sec->shdr.sh_type == SHT_PROGBITS) 1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !strcmp (sec->name, ".plt"))) 1119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sec->shdr.sh_type == SHT_RELA 1120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && undo_sec->shdr.sh_type == SHT_REL 1121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size)) 1122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize 1123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (sec->shdr.sh_type == undo_sec->shdr.sh_type 1124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sec->shdr.sh_type == SHT_PROGBITS 1125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && undo_sec->shdr.sh_type == SHT_NOBITS)) 1126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sec->shdr.sh_size < undo_sec->shdr.sh_size 1127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (!strcmp (sec->name, ".bss") 1128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || !strcmp (sec->name, ".sbss")) 1129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (split_bss = sec) > sections))) 1130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->outscn = undo_sec->outscn; 1132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng undo_sec = NULL; 1133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_match (undo_sec == NULL, scn, name); 1138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (undo_sections); 1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (fail) 1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exit (EXIT_FAILURE); 1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return split_bss; 1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Create new .shstrtab contents, subroutine of copy_elided_sections. 1149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This can't be open coded there and still use variable-length auto arrays, 1150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng since the end of our block would free other VLAs too. */ 1151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Elf_Data * 1152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengnew_shstrtab (Elf *unstripped, size_t unstripped_shnum, 1153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shstrtab, size_t unstripped_shstrndx, 1154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sections, size_t stripped_shnum, 1155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strtab *strtab) 1156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strtab == NULL) 1158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return NULL; 1159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1]; 1161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (unstripped_strent, 0, sizeof unstripped_strent); 1162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (struct section *sec = sections; 1163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec < §ions[stripped_shnum - 1]; 1164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++sec) 1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->outscn != NULL) 1166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->strent == NULL) 1168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->strent = ebl_strtabadd (strtab, sec->name, 0); 1170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (sec->strent != NULL, 1171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot add section name to string table: %s")); 1172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent; 1174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Add names of sections we aren't touching. */ 1177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < unstripped_shnum - 1; ++i) 1178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_strent[i] == NULL) 1179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = elf_getscn (unstripped, i + 1); 1181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = get_section_name (i + 1, shdr, shstrtab); 1184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_strent[i] = ebl_strtabadd (strtab, name, 0); 1185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (unstripped_strent[i] != NULL, 1186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot add section name to string table: %s")); 1187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_strent[i] = NULL; 1190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now finalize the string table so we can get offsets. */ 1192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped, 1193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_shstrndx), NULL); 1194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY), 1195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header string table data: %s")); 1196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_strtabfinalize (strtab, strtab_data); 1197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Update the sh_name fields of sections we aren't modifying later. */ 1199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < unstripped_shnum - 1; ++i) 1200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_strent[i] != NULL) 1201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = elf_getscn (unstripped, i + 1); 1203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]); 1206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (i + 1 == unstripped_shstrndx) 1207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_size = strtab_data->d_size; 1208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (scn, shdr), 1209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 1210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return strtab_data; 1213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Fill in any SHT_NOBITS sections in UNSTRIPPED by 1216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copying their contents and sh_type from STRIPPED. */ 1217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcopy_elided_sections (Elf *unstripped, Elf *stripped, 1219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Ehdr *stripped_ehdr, GElf_Addr bias) 1220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t unstripped_shstrndx; 1222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_getshstrndx (unstripped, &unstripped_shstrndx) == 0, 1223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get section header string table section index: %s")); 1224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t stripped_shstrndx; 1226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_getshstrndx (stripped, &stripped_shstrndx) == 0, 1227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get section header string table section index: %s")); 1228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t unstripped_shnum; 1230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0, 1231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get section count: %s")); 1232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t stripped_shnum; 1234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_getshnum (stripped, &stripped_shnum) == 0, 1235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get section count: %s")); 1236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Cache the stripped file's section details. */ 1238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section sections[stripped_shnum - 1]; 1239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 1240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (stripped, scn)) != NULL) 1241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t i = elf_ndxscn (scn) - 1; 1243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, §ions[i].shdr); 1244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections[i].name = elf_strptr (stripped, stripped_shstrndx, 1246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_name); 1247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sections[i].name == NULL) 1248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"), 1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn), elf_errmsg (-1)); 1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections[i].scn = scn; 1251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections[i].outscn = NULL; 1252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections[i].strent = NULL; 1253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *stripped_symtab = NULL; 1256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Sort the sections, allocated by address and others after. */ 1258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (sections, stripped_shnum - 1, sizeof sections[0], 1259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_ehdr->e_type == ET_REL 1260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? compare_sections_rel : compare_sections_nonrel); 1261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nalloc = stripped_shnum - 1; 1262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC)) 1263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng --nalloc; 1265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sections[nalloc].shdr.sh_type == SHT_SYMTAB) 1266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_symtab = §ions[nalloc]; 1267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Locate a matching unallocated section in SECTIONS. */ 1270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline struct section *find_unalloc_section (const GElf_Shdr *shdr, 1271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name) 1272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t l = nalloc, u = stripped_shnum - 1; 1274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (l < u) 1275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t i = (l + u) / 2; 1277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sec = §ions[i]; 1278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int cmp = compare_unalloc_sections (shdr, &sec->shdr, 1279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name, sec->name); 1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cmp < 0) 1281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng u = i; 1282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (cmp > 0) 1283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng l = i + 1; 1284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return sec; 1286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return NULL; 1288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped, 1291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_shstrndx), NULL); 1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shstrtab != NULL, 1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot read section header string table: %s")); 1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Match each debuginfo section with its corresponding stripped section. */ 1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool check_prelink = false; 1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *unstripped_symtab = NULL; 1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t unstripped_strtab_ndx = SHN_UNDEF; 1299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t alloc_avail = 0; 1300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng scn = NULL; 1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (unstripped, scn)) != NULL) 1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type == SHT_SYMTAB) 1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_symtab = scn; 1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_strtab_ndx = shdr->sh_link; 1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t ndx = elf_ndxscn (scn); 1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ndx == unstripped_shstrndx) 1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = get_section_name (ndx, shdr, shstrtab); 1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *sec = NULL; 1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_flags & SHF_ALLOC) 1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr->e_type != ET_REL) 1324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Look for the section that matches. */ 1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec = find_alloc_section (shdr, bias, name, sections, nalloc); 1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec == NULL) 1328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We couldn't figure it out. It may be a prelink issue. */ 1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_prelink = true; 1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The sh_addr of allocated sections does not help us, 1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng but the order usually matches. */ 1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (sections_match (sections, alloc_avail, shdr, name))) 1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec = §ions[alloc_avail++]; 1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = alloc_avail + 1; i < nalloc; ++i) 1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sections_match (sections, i, shdr, name)) 1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec = §ions[i]; 1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Look for the section that matches. */ 1352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec = find_unalloc_section (shdr, name); 1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec == NULL) 1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* An additional unallocated section is fine if not SHT_NOBITS. 1356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We looked it up anyway in case it's an unallocated section 1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copied in both files (e.g. SHT_NOTE), and don't keep both. */ 1358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type != SHT_NOBITS) 1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Somehow some old .debug files wound up with SHT_NOBITS 1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .comment sections, so let those pass. */ 1363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!strcmp (name, ".comment")) 1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec == NULL) 1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 1370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot find matching section for [%Zu] '%s'"), 1371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn), name); 1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->outscn = scn; 1374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If that failed due to changes made by prelink, we take another tack. 1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We keep track of a .bss section that was partly split into .dynbss 1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng so that collect_symbols can update symbols' st_shndx fields. */ 1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct section *split_bss = NULL; 1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (check_prelink) 1381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (stripped, stripped_shstrndx), 1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL); 1384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (data != NULL, 1385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot read section header string table: %s")); 1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng split_bss = find_alloc_sections_prelink (unstripped, shstrtab, 1387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped, stripped_ehdr, 1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data, bias, sections, 1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nalloc, stripped_shnum - 1); 1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure each main file section has a place to go. */ 1393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct section *stripped_dynsym = NULL; 1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t debuglink = SHN_UNDEF; 1395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t ndx_section[stripped_shnum - 1]; 1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strtab *strtab = NULL; 1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (struct section *sec = sections; 1398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec < §ions[stripped_shnum - 1]; 1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++sec) 1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t secndx = elf_ndxscn (sec->scn); 1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->outscn == NULL) 1404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We didn't find any corresponding section for this. */ 1406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (secndx == stripped_shstrndx) 1408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We only need one .shstrtab. */ 1410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx_section[secndx - 1] = unstripped_shstrndx; 1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_symtab != NULL && sec == stripped_symtab) 1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We don't need a second symbol table. */ 1417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab); 1418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_symtab != NULL && stripped_symtab != NULL 1422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && secndx == stripped_symtab->shdr.sh_link) 1423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* ... nor its string table. */ 1425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem); 1427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx_section[secndx - 1] = shdr->sh_link; 1429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!(sec->shdr.sh_flags & SHF_ALLOC) 1433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !strcmp (sec->name, ".gnu_debuglink")) 1434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This was created by stripping. We don't want it. */ 1436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debuglink = secndx; 1437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx_section[secndx - 1] = SHN_UNDEF; 1438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->outscn = elf_newscn (unstripped); 1442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *newdata = elf_newdata (sec->outscn); 1443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (newdata != NULL && gelf_update_shdr (sec->outscn, 1444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &sec->shdr), 1445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot add new section: %s")); 1446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strtab == NULL) 1448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng strtab = ebl_strtabinit (true); 1449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec->strent = ebl_strtabadd (strtab, sec->name, 0); 1450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (sec->strent != NULL, 1451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot add section name to string table: %s")); 1452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Cache the mapping of original section indices to output sections. */ 1455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx_section[secndx - 1] = elf_ndxscn (sec->outscn); 1456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We added some sections, so we need a new shstrtab. */ 1459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum, 1460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shstrtab, unstripped_shstrndx, 1461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections, stripped_shnum, 1462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng strtab); 1463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get the updated section count. */ 1465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0, 1466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get section count: %s")); 1467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool placed[unstripped_shnum - 1]; 1469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (placed, 0, sizeof placed); 1470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now update the output sections and copy in their data. */ 1472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off offset = 0; 1473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (const struct section *sec = sections; 1474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec < §ions[stripped_shnum - 1]; 1475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++sec) 1476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->outscn != NULL) 1477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem); 1480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* In an ET_REL file under --relocate, the sh_addr of SHF_ALLOC 1483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections will have been set nonzero by relocation. This 1484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng touched the shdrs of whichever file had the symtab. sh_addr 1485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng is still zero in the corresponding shdr. The relocated 1486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng address is what we want to use. */ 1487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr->e_type != ET_REL 1488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || !(shdr_mem.sh_flags & SHF_ALLOC) 1489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr_mem.sh_addr == 0) 1490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_addr = sec->shdr.sh_addr; 1491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_type = sec->shdr.sh_type; 1493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_size = sec->shdr.sh_size; 1494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_info = sec->shdr.sh_info; 1495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_link = sec->shdr.sh_link; 1496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->shdr.sh_link != SHN_UNDEF) 1497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1]; 1498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr_mem.sh_flags & SHF_INFO_LINK) 1499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_info = ndx_section[sec->shdr.sh_info - 1]; 1500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strtab != NULL) 1502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_name = ebl_strtaboffset (sec->strent); 1503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *indata = elf_getdata (sec->scn, NULL); 1505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (indata != NULL, _("cannot get section data: %s")); 1506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *outdata = elf_getdata (sec->outscn, NULL); 1507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (outdata != NULL, _("cannot copy section data: %s")); 1508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *outdata = *indata; 1509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (outdata, ELF_C_SET, ELF_F_DIRTY); 1510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Preserve the file layout of the allocated sections. */ 1512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC)) 1513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr_mem.sh_offset = sec->shdr.sh_offset; 1515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng placed[elf_ndxscn (sec->outscn) - 1] = true; 1516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Off end_offset = (shdr_mem.sh_offset 1518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + (shdr_mem.sh_type == SHT_NOBITS 1519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? 0 : shdr_mem.sh_size)); 1520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (end_offset > offset) 1521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset = end_offset; 1522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (sec->outscn, &shdr_mem), 1525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 1526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr_mem.sh_type == SHT_SYMTAB || shdr_mem.sh_type == SHT_DYNSYM) 1528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We must adjust all the section indices in the symbol table. */ 1530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shndxdata = NULL; /* XXX */ 1532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i) 1534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 1536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word shndx = SHN_UNDEF; 1537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsymshndx (outdata, shndxdata, 1538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng i, &sym_mem, &shndx); 1539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (sym != NULL, 1540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get symbol table entry: %s")); 1541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_shndx != SHN_XINDEX) 1542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = sym->st_shndx; 1543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx != SHN_UNDEF && shndx < SHN_LORESERVE) 1545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx >= stripped_shnum) 1547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 1548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("symbol [%Zu] has invalid section index"), i); 1549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = ndx_section[shndx - 1]; 1551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx < SHN_LORESERVE) 1552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym->st_shndx = shndx; 1554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx = SHN_UNDEF; 1555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym->st_shndx = SHN_XINDEX; 1558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (outdata, shndxdata, 1560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng i, sym, shndx), 1561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 1562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr_mem.sh_type == SHT_SYMTAB) 1566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_symtab = sec; 1567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr_mem.sh_type == SHT_DYNSYM) 1568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_dynsym = sec; 1569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We may need to update the symbol table. */ 1573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = NULL; 1574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Ebl_Strtab *symstrtab = NULL; 1575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symstrdata = NULL; 1576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_symtab != NULL && (stripped_symtab != NULL 1577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || check_prelink /* Section adjustments. */ 1578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (stripped_ehdr->e_type != ET_REL 1579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && bias != 0))) 1580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Merge the stripped file's symbol table into the unstripped one. */ 1582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t stripped_nsym = (stripped_symtab == NULL ? 1 1583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : (stripped_symtab->shdr.sh_size 1584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng / stripped_symtab->shdr.sh_entsize)); 1585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem); 1588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize; 1590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First collect all the symbols from both tables. */ 1592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t total_syms = stripped_nsym - 1 + unstripped_nsym - 1; 1594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct symbol symbols[total_syms]; 1595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t symndx_map[total_syms]; 1596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_symtab != NULL) 1598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL, 1599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_symtab->scn, 1600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_getscn (stripped, stripped_symtab->shdr.sh_link), 1601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_nsym, 0, ndx_section, 1602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symbols, symndx_map, NULL); 1603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link); 1605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL, 1606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_symtab, unstripped_strtab, unstripped_nsym, 1607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL, 1608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &symbols[stripped_nsym - 1], 1609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &symndx_map[stripped_nsym - 1], split_bss); 1610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Next, sort our array of all symbols. */ 1612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (symbols, total_syms, sizeof symbols[0], compare_symbols); 1613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we can weed out the duplicates. Assign remaining symbols 1615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng new slots, collecting a map from old indices to new. */ 1616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nsym = 0; 1617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s) 1618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Skip a section symbol for a removed section. */ 1620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (s->shndx == SHN_UNDEF 1621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && GELF_ST_TYPE (s->info.info) == STT_SECTION) 1622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->name = NULL; /* Mark as discarded. */ 1624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *s->map = STN_UNDEF; 1625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->duplicate = NULL; 1626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct symbol *n = s; 1630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (n + 1 < &symbols[total_syms] && !compare_symbols (s, n + 1)) 1631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++n; 1632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (s < n) 1634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This is a duplicate. Its twin will get the next slot. */ 1636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->name = NULL; /* Mark as discarded. */ 1637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng s->duplicate = n->map; 1638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++s; 1639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Allocate the next slot. */ 1642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *s->map = ++nsym; 1643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we sort again, to determine the order in the output. */ 1646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (symbols, total_syms, sizeof symbols[0], compare_symbols_output); 1647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (nsym < total_syms) 1649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The discarded symbols are now at the end of the table. */ 1650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (symbols[nsym].name == NULL); 1651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now a final pass updates the map with the final order, 1653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng and builds up the new string table. */ 1654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symstrtab = ebl_strtabinit (true); 1655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nsym; ++i) 1656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (symbols[i].name != NULL); 1658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (*symbols[i].map != 0); 1659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *symbols[i].map = 1 + i; 1660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symbols[i].strent = ebl_strtabadd (symstrtab, symbols[i].name, 0); 1661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Scan the discarded symbols too, just to update their slots 1664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in SYMNDX_MAP to refer to their live duplicates. */ 1665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = nsym; i < total_syms; ++i) 1666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (symbols[i].name == NULL); 1668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symbols[i].duplicate == NULL) 1669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (*symbols[i].map == STN_UNDEF); 1670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (*symbols[i].duplicate != STN_UNDEF); 1673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *symbols[i].map = *symbols[i].duplicate; 1674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we are ready to write the new symbol table. */ 1678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symdata = elf_getdata (unstripped_symtab, NULL); 1679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symstrdata = elf_getdata (unstripped_strtab, NULL); 1680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *shndxdata = NULL; /* XXX */ 1681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_strtabfinalize (symstrtab, symstrdata); 1683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY); 1684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize; 1686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symdata->d_buf = xmalloc (symdata->d_size); 1687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym; 1689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (&sym, 0, sizeof sym); 1690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 0, &sym, SHN_UNDEF), 1691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 1692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_info = 1; 1694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nsym; ++i) 1695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct symbol *s = &symbols[i]; 1697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Fill in the symbol details. */ 1699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_name = ebl_strtaboffset (s->strent); 1700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_value = s->value; /* Already biased to output address. */ 1701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_size = s->size; 1702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_shndx = s->shndx; /* Already mapped to output index. */ 1703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_info = s->info.info; 1704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym.st_other = s->info.other; 1705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Keep track of the number of leading local symbols. */ 1707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_ST_BIND (sym.st_info) == STB_LOCAL) 1708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (shdr->sh_info == 1 + i); 1710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_info = 1 + i + 1; 1711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 1 + i, 1714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &sym, SHN_UNDEF), 1715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update symbol table: %s")); 1716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY); 1719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (unstripped_symtab, shdr), 1720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 1721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_symtab != NULL) 1723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Adjust any relocations referring to the old symbol table. */ 1725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn); 1726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (const struct section *sec = sections; 1727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sec < §ions[stripped_shnum - 1]; 1728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++sec) 1729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link) 1730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_relocs (sec->outscn, sec->scn, &sec->shdr, 1731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symndx_map, shdr); 1732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Also adjust references to the other old symbol table. */ 1735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng adjust_all_relocs (unstripped, unstripped_symtab, shdr, 1736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &symndx_map[stripped_nsym - 1]); 1737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (stripped_symtab != NULL && stripped_shnum != unstripped_shnum) 1739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_symtab_section_symbols (unstripped, 1740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_ehdr->e_type == ET_REL, 1741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_symtab->scn, 1742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_shnum, unstripped_shstrndx, 1743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_symtab->outscn, 1744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_shnum, stripped_shstrndx, 1745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debuglink); 1746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_dynsym != NULL) 1748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) check_symtab_section_symbols (unstripped, 1749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_ehdr->e_type == ET_REL, 1750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_dynsym->outscn, 1751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_shnum, 1752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_shstrndx, 1753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_dynsym->scn, stripped_shnum, 1754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_shstrndx, debuglink); 1755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We need to preserve the layout of the stripped file so the 1757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdrs will match up. This requires us to do our own layout of 1758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the added sections. We do manual layout even for ET_REL just 1759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng so we can try to match what the original probably had. */ 1760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagelf (unstripped, ELF_C_SET, ELF_F_LAYOUT); 1762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (offset == 0) 1764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* For ET_REL we are starting the layout from scratch. */ 1765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset = gelf_fsize (unstripped, ELF_T_EHDR, 1, EV_CURRENT); 1766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool skip_reloc = false; 1768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 1769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng skip_reloc = !skip_reloc; 1771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < unstripped_shnum - 1; ++i) 1772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!placed[i]) 1773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng scn = elf_getscn (unstripped, 1 + i); 1775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 1777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 1778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); 1779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (skip_reloc 1781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)) 1782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off align = shdr->sh_addralign ?: 1; 1785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset = (offset + align - 1) & -align; 1786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_offset = offset; 1787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type != SHT_NOBITS) 1788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset += shdr->sh_size; 1789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_shdr (scn, shdr), 1791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update section header: %s")); 1792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_shstrndx == 1 + i) 1794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Place the section headers immediately after 1796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .shstrtab, and update the ELF header. */ 1797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr_mem; 1799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr *ehdr = gelf_getehdr (unstripped, &ehdr_mem); 1800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s")); 1801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off sh_align = gelf_getclass (unstripped) * 4; 1803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset = (offset + sh_align - 1) & -sh_align; 1804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr->e_shnum = unstripped_shnum; 1805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr->e_shoff = offset; 1806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset += unstripped_shnum * ehdr->e_shentsize; 1807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_ehdr (unstripped, ehdr), 1808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update ELF header: %s")); 1809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng placed[i] = true; 1812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } while (skip_reloc); 1814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr->e_phnum > 0) 1816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_newphdr (unstripped, stripped_ehdr->e_phnum), 1817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create program headers: %s")); 1818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Copy each program header from the stripped file. */ 1820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i) 1821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 1823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem); 1824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (phdr != NULL, _("cannot get program header: %s")); 1825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_update_phdr (unstripped, i, phdr), 1827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot update program header: %s")); 1828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Finally, write out the file. */ 1831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_update (unstripped, ELF_C_WRITE) > 0, 1832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot write output file: %s")); 1833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strtab != NULL) 1835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_strtabfree (strtab); 1837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (strtab_data->d_buf); 1838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symdata != NULL) 1841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (symdata->d_buf); 1842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symstrtab != NULL) 1843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_strtabfree (symstrtab); 1845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (symstrdata->d_buf); 1846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Process one pair of files, already opened. */ 1850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_file (const char *output_file, bool create_dirs, 1852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *stripped, const GElf_Ehdr *stripped_ehdr, 1853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *unstripped) 1854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Determine the address bias between the debuginfo file and the main 1856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng file, which may have been modified by prelinking. */ 1857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias = 0; 1858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped != NULL) 1859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i) 1860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 1862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem); 1863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (phdr != NULL, _("cannot get program header: %s")); 1864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_type == PT_LOAD) 1865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr unstripped_phdr_mem; 1867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *unstripped_phdr = gelf_getphdr (unstripped, i, 1868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &unstripped_phdr_mem); 1869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (unstripped_phdr != NULL, 1870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot get program header: %s")); 1871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bias = phdr->p_vaddr - unstripped_phdr->p_vaddr; 1872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* One day we could adjust all the DWARF data (like prelink itself does). */ 1877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (bias != 0) 1878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (output_file == NULL) 1880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, _("\ 1881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDWARF data not adjusted for prelinking bias; consider prelink -u")); 1882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, _("\ 1884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"), 1885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng output_file); 1886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (output_file == NULL) 1889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Modify the unstripped file in place. */ 1890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copy_elided_sections (unstripped, stripped, stripped_ehdr, bias); 1891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (create_dirs) 1894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng make_directories (output_file); 1895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Copy the unstripped file and then modify it. */ 1897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int outfd = open64 (output_file, O_RDWR | O_CREAT, 1898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_ehdr->e_type == ET_REL ? 0666 : 0777); 1899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (outfd < 0) 1900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, errno, _("cannot open '%s'"), output_file); 1901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL); 1902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (outelf != NULL, _("cannot create ELF descriptor: %s")); 1903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped == NULL) 1905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Actually, we are just copying out the main file as it is. */ 1907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copy_elf (outelf, stripped); 1908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr->e_type != ET_REL) 1909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT); 1910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (elf_update (outelf, ELF_C_WRITE) > 0, 1911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot write output file: %s")); 1912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copy_elf (outelf, unstripped); 1916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng copy_elided_sections (outelf, stripped, stripped_ehdr, bias); 1917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_end (outelf); 1920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng close (outfd); 1921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengopen_file (const char *file, bool writable) 1926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int fd = open64 (file, writable ? O_RDWR : O_RDONLY); 1928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (fd < 0) 1929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, errno, _("cannot open '%s'"), file); 1930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return fd; 1931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle a pair of files we need to open by name. */ 1934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_explicit_files (const char *output_file, bool create_dirs, 1936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *stripped_file, const char *unstripped_file) 1937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int stripped_fd = open_file (stripped_file, false); 1939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL); 1940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr stripped_ehdr; 1941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr), 1942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create ELF descriptor: %s")); 1943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int unstripped_fd = -1; 1945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *unstripped = NULL; 1946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unstripped_file != NULL) 1947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped_fd = open_file (unstripped_file, output_file == NULL); 1949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unstripped = elf_begin (unstripped_fd, 1950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (output_file == NULL ? ELF_C_RDWR : ELF_C_READ), 1951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL); 1952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr unstripped_ehdr; 1953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr), 1954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create ELF descriptor: %s")); 1955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (memcmp (stripped_ehdr.e_ident, unstripped_ehdr.e_ident, EI_NIDENT) 1957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || stripped_ehdr.e_type != unstripped_ehdr.e_type 1958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || stripped_ehdr.e_machine != unstripped_ehdr.e_machine 1959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || stripped_ehdr.e_phnum != unstripped_ehdr.e_phnum) 1960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("'%s' and '%s' do not seem to match"), 1961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_file, unstripped_file); 1962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped); 1965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_end (stripped); 1967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng close (stripped_fd); 1968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_end (unstripped); 1970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng close (unstripped_fd); 1971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle a pair of files opened implicitly by libdwfl for one module. */ 1975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_dwfl_module (const char *output_file, bool create_dirs, 1977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *mod, bool all, bool ignore, bool relocate) 1978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias; 1980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *stripped = dwfl_module_getelf (mod, &bias); 1981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped == NULL) 1982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ignore) 1984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 1985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 1987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, 1988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, &file, NULL); 1989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (file == NULL) 1990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 1991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot find stripped file for module '%s': %s"), 1992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modname, dwfl_errmsg (-1)); 1993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 1995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot open stripped file '%s' for module '%s': %s"), 1996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modname, file, dwfl_errmsg (-1)); 1997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias)); 2000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (debug == NULL && !all) 2001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ignore) 2003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 2006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, 2007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, NULL, &file); 2008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (file == NULL) 2009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 2010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot find debug file for module '%s': %s"), 2011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modname, dwfl_errmsg (-1)); 2012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 2014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot open debug file '%s' for module '%s': %s"), 2015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modname, file, dwfl_errmsg (-1)); 2016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (debug == stripped) 2019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (all) 2021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debug = NULL; 2022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 2025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, 2026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, &file, NULL); 2027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("module '%s' file '%s' is not stripped"), 2028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modname, file); 2029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr stripped_ehdr; 2033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr), 2034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot create ELF descriptor: %s")); 2035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (stripped_ehdr.e_type == ET_REL) 2037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!relocate) 2039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We can't use the Elf handles already open, 2041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng because the DWARF sections have been relocated. */ 2042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *stripped_file = NULL; 2044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *unstripped_file = NULL; 2045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, 2046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &stripped_file, &unstripped_file); 2047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_explicit_files (output_file, create_dirs, 2049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng stripped_file, unstripped_file); 2050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Relocation is what we want! This ensures that all sections that can 2054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng get sh_addr values assigned have them, even ones not used in DWARF. 2055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng They might still be used in the symbol table. */ 2056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dwfl_module_relocations (mod) < 0) 2057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 2058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng _("cannot cache section addresses for module '%s': %s"), 2059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 2060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dwfl_errmsg (-1)); 2061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug); 2064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle one module being written to the output directory. */ 2067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_output_dir_module (const char *output_dir, Dwfl_Module *mod, 2069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool all, bool ignore, bool modnames, bool relocate) 2070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! modnames) 2072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure we've searched for the ELF file. */ 2074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias; 2075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) dwfl_module_getelf (mod, &bias); 2076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 2079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = dwfl_module_info (mod, NULL, NULL, NULL, 2080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, &file, NULL); 2081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (file == NULL && ignore) 2083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *output_file; 2086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0) 2087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("memory exhausted")); 2088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_dwfl_module (output_file, true, mod, all, ignore, relocate); 2090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenglist_module (Dwfl_Module *mod) 2095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure we have searched for the files. */ 2097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias; 2098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool have_elf = dwfl_module_getelf (mod, &bias) != NULL; 2099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL; 2100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 2102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *debug; 2103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Addr start; 2104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Addr end; 2105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = dwfl_module_info (mod, NULL, &start, &end, 2106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, &file, &debug); 2107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file))) 2108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debug = "."; 2109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const unsigned char *id; 2111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr id_vaddr; 2112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); 2113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start); 2115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (id_len > 0) 2117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 2119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng printf ("%02" PRIx8, *id++); 2120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (--id_len > 0); 2121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (id_vaddr != 0) 2122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng printf ("@%#" PRIx64, id_vaddr); 2123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng putchar ('-'); 2126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng printf (" %s %s %s\n", 2128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng file ?: have_elf ? "." : "-", 2129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng debug ?: have_dwarf ? "." : "-", 2130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name); 2131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct match_module_info 2135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char **patterns; 2137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *found; 2138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool match_files; 2139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 2140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 2142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengmatch_module (Dwfl_Module *mod, 2143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void **userdata __attribute__ ((unused)), 2144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name, 2145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Addr start __attribute__ ((unused)), 2146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *arg) 2147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct match_module_info *info = arg; 2149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->patterns[0] == NULL) /* Match all. */ 2151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng match: 2153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->found = mod; 2154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWARF_CB_ABORT; 2155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->match_files) 2158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure we've searched for the ELF file. */ 2160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias; 2161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) dwfl_module_getelf (mod, &bias); 2162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *file; 2164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *check = dwfl_module_info (mod, NULL, NULL, NULL, 2165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NULL, NULL, &file, NULL); 2166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (check == name); 2167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (file == NULL) 2168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWARF_CB_OK; 2169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = file; 2171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (char **p = info->patterns; *p != NULL; ++p) 2174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (fnmatch (*p, name, 0) == 0) 2175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto match; 2176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return DWARF_CB_OK; 2178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle files opened implicitly via libdwfl. */ 2181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghandle_implicit_modules (const struct arg_info *info) 2183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct match_module_info mmi = { info->args, NULL, info->match_files }; 2185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline ptrdiff_t next (ptrdiff_t offset) 2186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset); 2188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ptrdiff_t offset = next (0); 2190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (offset == 0) 2191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("no matching modules found")); 2192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->list) 2194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 2195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng list_module (mmi.found); 2196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((offset = next (offset)) > 0); 2197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (info->output_dir == NULL) 2198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (next (offset) != 0) 2200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("matched more than one module")); 2201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_dwfl_module (info->output_file, false, mmi.found, 2202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->all, info->ignore, info->relocate); 2203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 2206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_output_dir_module (info->output_dir, mmi.found, 2207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->all, info->ignore, 2208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->modnames, info->relocate); 2209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((offset = next (offset)) > 0); 2210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint 2213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengmain (int argc, char **argv) 2214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make memory leak detection possible. */ 2216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mtrace (); 2217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We use no threads here which can interfere with handling a stream. */ 2219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng __fsetlocking (stdin, FSETLOCKING_BYCALLER); 2220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng __fsetlocking (stdout, FSETLOCKING_BYCALLER); 2221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng __fsetlocking (stderr, FSETLOCKING_BYCALLER); 2222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Set locale. */ 2224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng setlocale (LC_ALL, ""); 2225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure the message catalog can be found. */ 2227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); 2228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Initialize the message catalog. */ 2230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng textdomain (PACKAGE_TARNAME); 2231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Parse and process arguments. */ 2233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct argp_child argp_children[] = 2234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .argp = dwfl_standard_argp (), 2237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .header = N_("Input selection options:"), 2238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .group = 1, 2239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }, 2240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { .argp = NULL }, 2241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 2242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct argp argp = 2243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .options = options, 2245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .parser = parse_opt, 2246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .children = argp_children, 2247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"), 2248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .doc = N_("\ 2249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengCombine stripped files with separate symbols and debug information.\v\ 2250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengThe first form puts the result in DEBUG-FILE if -o was not given.\n\ 2251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\n\ 2252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengMODULE arguments give file name patterns matching modules to process.\n\ 2253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengWith -f these match the file name of the main (stripped) file \ 2254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng(slashes are never special), otherwise they match the simple module names. \ 2255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengWith no arguments, process all modules found.\n\ 2256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\n\ 2257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengMultiple modules are written to files under OUTPUT-DIRECTORY, \ 2258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcreating subdirectories as needed. \ 2259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengWith -m these files have simple module names, otherwise they have the \ 2260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengname of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\ 2261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\n\ 2262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengWith -n no files are written, but one line to standard output for each module:\ 2263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng\n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\ 2264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengSTART and SIZE are hexadecimal giving the address bounds of the module. \ 2265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengBUILDID is hexadecimal for the build ID bits, or - if no ID is known; \ 2266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengthe hexadecimal may be followed by @0xADDR giving the address where the \ 2267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengID resides if that is known. \ 2268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFILE is the file name found for the module, or - if none was found, \ 2269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengor . if an ELF image is available but not from any named file. \ 2270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengDEBUGFILE is the separate debuginfo file name, \ 2271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengor - if no debuginfo was found, or . if FILE contains the debug information.\ 2272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng") 2273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 2274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int remaining; 2276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct arg_info info = { .args = NULL }; 2277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info); 2278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (result == ENOSYS) 2279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (info.dwfl == NULL); 2280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (result) 2281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return EXIT_FAILURE; 2282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (info.args != NULL); 2283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Tell the library which version we are expecting. */ 2285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_version (EV_CURRENT); 2286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info.dwfl == NULL) 2288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (result == ENOSYS); 2290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info.output_dir != NULL) 2292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *file; 2294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0) 2295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, _("memory exhausted")); 2296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_explicit_files (file, true, info.args[0], info.args[1]); 2297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (file); 2298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_explicit_files (info.output_file, false, 2301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info.args[0], info.args[1]); 2302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* parse_opt checked this. */ 2306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (info.output_file != NULL || info.output_dir != NULL || info.list); 2307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handle_implicit_modules (&info); 2309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dwfl_end (info.dwfl); 2311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h" 2318