151 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>4 */5 6#include <stdio.h>7#include <stdbool.h>8#include <string.h>9#include <stdlib.h>10#include <unistd.h>11#include <subcmd/exec-cmd.h>12#include <subcmd/pager.h>13#include <linux/kernel.h>14 15#include <objtool/builtin.h>16#include <objtool/objtool.h>17#include <objtool/warn.h>18 19bool help;20 21const char *objname;22static struct objtool_file file;23 24static bool objtool_create_backup(const char *_objname)25{26 int len = strlen(_objname);27 char *buf, *base, *name = malloc(len+6);28 int s, d, l, t;29 30 if (!name) {31 perror("failed backup name malloc");32 return false;33 }34 35 strcpy(name, _objname);36 strcpy(name + len, ".orig");37 38 d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);39 if (d < 0) {40 perror("failed to create backup file");41 return false;42 }43 44 s = open(_objname, O_RDONLY);45 if (s < 0) {46 perror("failed to open orig file");47 return false;48 }49 50 buf = malloc(4096);51 if (!buf) {52 perror("failed backup data malloc");53 return false;54 }55 56 while ((l = read(s, buf, 4096)) > 0) {57 base = buf;58 do {59 t = write(d, base, l);60 if (t < 0) {61 perror("failed backup write");62 return false;63 }64 base += t;65 l -= t;66 } while (l);67 }68 69 if (l < 0) {70 perror("failed backup read");71 return false;72 }73 74 free(name);75 free(buf);76 close(d);77 close(s);78 79 return true;80}81 82struct objtool_file *objtool_open_read(const char *_objname)83{84 if (objname) {85 if (strcmp(objname, _objname)) {86 WARN("won't handle more than one file at a time");87 return NULL;88 }89 return &file;90 }91 objname = _objname;92 93 file.elf = elf_open_read(objname, O_RDWR);94 if (!file.elf)95 return NULL;96 97 if (opts.backup && !objtool_create_backup(objname)) {98 WARN("can't create backup file");99 return NULL;100 }101 102 hash_init(file.insn_hash);103 INIT_LIST_HEAD(&file.retpoline_call_list);104 INIT_LIST_HEAD(&file.return_thunk_list);105 INIT_LIST_HEAD(&file.static_call_list);106 INIT_LIST_HEAD(&file.mcount_loc_list);107 INIT_LIST_HEAD(&file.endbr_list);108 INIT_LIST_HEAD(&file.call_list);109 file.ignore_unreachables = opts.no_unreachable;110 file.hints = false;111 112 return &file;113}114 115void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)116{117 if (!opts.noinstr)118 return;119 120 if (!f->pv_ops) {121 WARN("paravirt confusion");122 return;123 }124 125 /*126 * These functions will be patched into native code,127 * see paravirt_patch().128 */129 if (!strcmp(func->name, "_paravirt_nop") ||130 !strcmp(func->name, "_paravirt_ident_64"))131 return;132 133 /* already added this function */134 if (!list_empty(&func->pv_target))135 return;136 137 list_add(&func->pv_target, &f->pv_ops[idx].targets);138 f->pv_ops[idx].clean = false;139}140 141int main(int argc, const char **argv)142{143 static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";144 145 /* libsubcmd init */146 exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);147 pager_init(UNUSED);148 149 return objtool_run(argc, argv);150}151