11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2442f04c3SJosh Poimboeuf /* 3442f04c3SJosh Poimboeuf * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 4442f04c3SJosh Poimboeuf */ 5442f04c3SJosh Poimboeuf 6442f04c3SJosh Poimboeuf #include <stdio.h> 7442f04c3SJosh Poimboeuf #include <stdbool.h> 8442f04c3SJosh Poimboeuf #include <string.h> 9442f04c3SJosh Poimboeuf #include <stdlib.h> 108ad15c69SPeter Zijlstra #include <unistd.h> 11442f04c3SJosh Poimboeuf #include <subcmd/exec-cmd.h> 12442f04c3SJosh Poimboeuf #include <subcmd/pager.h> 1300614597SArnaldo Carvalho de Melo #include <linux/kernel.h> 14442f04c3SJosh Poimboeuf 157786032eSVasily Gorbik #include <objtool/builtin.h> 167786032eSVasily Gorbik #include <objtool/objtool.h> 177786032eSVasily Gorbik #include <objtool/warn.h> 18442f04c3SJosh Poimboeuf 19442f04c3SJosh Poimboeuf bool help; 20442f04c3SJosh Poimboeuf 216545eb03SJulien Thierry const char *objname; 226545eb03SJulien Thierry static struct objtool_file file; 236545eb03SJulien Thierry 248ad15c69SPeter Zijlstra static bool objtool_create_backup(const char *_objname) 258ad15c69SPeter Zijlstra { 268ad15c69SPeter Zijlstra int len = strlen(_objname); 278ad15c69SPeter Zijlstra char *buf, *base, *name = malloc(len+6); 288ad15c69SPeter Zijlstra int s, d, l, t; 298ad15c69SPeter Zijlstra 308ad15c69SPeter Zijlstra if (!name) { 318ad15c69SPeter Zijlstra perror("failed backup name malloc"); 328ad15c69SPeter Zijlstra return false; 338ad15c69SPeter Zijlstra } 348ad15c69SPeter Zijlstra 358ad15c69SPeter Zijlstra strcpy(name, _objname); 368ad15c69SPeter Zijlstra strcpy(name + len, ".orig"); 378ad15c69SPeter Zijlstra 388ad15c69SPeter Zijlstra d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644); 398ad15c69SPeter Zijlstra if (d < 0) { 408ad15c69SPeter Zijlstra perror("failed to create backup file"); 418ad15c69SPeter Zijlstra return false; 428ad15c69SPeter Zijlstra } 438ad15c69SPeter Zijlstra 448ad15c69SPeter Zijlstra s = open(_objname, O_RDONLY); 458ad15c69SPeter Zijlstra if (s < 0) { 468ad15c69SPeter Zijlstra perror("failed to open orig file"); 478ad15c69SPeter Zijlstra return false; 488ad15c69SPeter Zijlstra } 498ad15c69SPeter Zijlstra 508ad15c69SPeter Zijlstra buf = malloc(4096); 518ad15c69SPeter Zijlstra if (!buf) { 528ad15c69SPeter Zijlstra perror("failed backup data malloc"); 538ad15c69SPeter Zijlstra return false; 548ad15c69SPeter Zijlstra } 558ad15c69SPeter Zijlstra 568ad15c69SPeter Zijlstra while ((l = read(s, buf, 4096)) > 0) { 578ad15c69SPeter Zijlstra base = buf; 588ad15c69SPeter Zijlstra do { 598ad15c69SPeter Zijlstra t = write(d, base, l); 608ad15c69SPeter Zijlstra if (t < 0) { 618ad15c69SPeter Zijlstra perror("failed backup write"); 628ad15c69SPeter Zijlstra return false; 638ad15c69SPeter Zijlstra } 648ad15c69SPeter Zijlstra base += t; 658ad15c69SPeter Zijlstra l -= t; 668ad15c69SPeter Zijlstra } while (l); 678ad15c69SPeter Zijlstra } 688ad15c69SPeter Zijlstra 698ad15c69SPeter Zijlstra if (l < 0) { 708ad15c69SPeter Zijlstra perror("failed backup read"); 718ad15c69SPeter Zijlstra return false; 728ad15c69SPeter Zijlstra } 738ad15c69SPeter Zijlstra 748ad15c69SPeter Zijlstra free(name); 758ad15c69SPeter Zijlstra free(buf); 768ad15c69SPeter Zijlstra close(d); 778ad15c69SPeter Zijlstra close(s); 788ad15c69SPeter Zijlstra 798ad15c69SPeter Zijlstra return true; 808ad15c69SPeter Zijlstra } 818ad15c69SPeter Zijlstra 826545eb03SJulien Thierry struct objtool_file *objtool_open_read(const char *_objname) 836545eb03SJulien Thierry { 846545eb03SJulien Thierry if (objname) { 856545eb03SJulien Thierry if (strcmp(objname, _objname)) { 866545eb03SJulien Thierry WARN("won't handle more than one file at a time"); 876545eb03SJulien Thierry return NULL; 886545eb03SJulien Thierry } 896545eb03SJulien Thierry return &file; 906545eb03SJulien Thierry } 916545eb03SJulien Thierry objname = _objname; 926545eb03SJulien Thierry 936545eb03SJulien Thierry file.elf = elf_open_read(objname, O_RDWR); 946545eb03SJulien Thierry if (!file.elf) 956545eb03SJulien Thierry return NULL; 966545eb03SJulien Thierry 972daf7fabSJosh Poimboeuf if (opts.backup && !objtool_create_backup(objname)) { 988ad15c69SPeter Zijlstra WARN("can't create backup file"); 998ad15c69SPeter Zijlstra return NULL; 1008ad15c69SPeter Zijlstra } 1018ad15c69SPeter Zijlstra 1026545eb03SJulien Thierry INIT_LIST_HEAD(&file.insn_list); 1036545eb03SJulien Thierry hash_init(file.insn_hash); 10443d5430aSPeter Zijlstra INIT_LIST_HEAD(&file.retpoline_call_list); 105d9e9d230SPeter Zijlstra INIT_LIST_HEAD(&file.return_thunk_list); 1066545eb03SJulien Thierry INIT_LIST_HEAD(&file.static_call_list); 10799d00215SPeter Zijlstra INIT_LIST_HEAD(&file.mcount_loc_list); 10889bc853eSPeter Zijlstra INIT_LIST_HEAD(&file.endbr_list); 109*00abd384SPeter Zijlstra INIT_LIST_HEAD(&file.call_list); 1102daf7fabSJosh Poimboeuf file.ignore_unreachables = opts.no_unreachable; 1116545eb03SJulien Thierry file.hints = false; 1126545eb03SJulien Thierry 1136545eb03SJulien Thierry return &file; 1146545eb03SJulien Thierry } 1156545eb03SJulien Thierry 116db2b0c5dSPeter Zijlstra void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func) 117db2b0c5dSPeter Zijlstra { 1182daf7fabSJosh Poimboeuf if (!opts.noinstr) 119db2b0c5dSPeter Zijlstra return; 120db2b0c5dSPeter Zijlstra 121db2b0c5dSPeter Zijlstra if (!f->pv_ops) { 122db2b0c5dSPeter Zijlstra WARN("paravirt confusion"); 123db2b0c5dSPeter Zijlstra return; 124db2b0c5dSPeter Zijlstra } 125db2b0c5dSPeter Zijlstra 126db2b0c5dSPeter Zijlstra /* 127db2b0c5dSPeter Zijlstra * These functions will be patched into native code, 128db2b0c5dSPeter Zijlstra * see paravirt_patch(). 129db2b0c5dSPeter Zijlstra */ 130db2b0c5dSPeter Zijlstra if (!strcmp(func->name, "_paravirt_nop") || 131db2b0c5dSPeter Zijlstra !strcmp(func->name, "_paravirt_ident_64")) 132db2b0c5dSPeter Zijlstra return; 133db2b0c5dSPeter Zijlstra 134988f0168SPeter Zijlstra /* already added this function */ 135988f0168SPeter Zijlstra if (!list_empty(&func->pv_target)) 136988f0168SPeter Zijlstra return; 137988f0168SPeter Zijlstra 138db2b0c5dSPeter Zijlstra list_add(&func->pv_target, &f->pv_ops[idx].targets); 139db2b0c5dSPeter Zijlstra f->pv_ops[idx].clean = false; 140db2b0c5dSPeter Zijlstra } 141db2b0c5dSPeter Zijlstra 142442f04c3SJosh Poimboeuf int main(int argc, const char **argv) 143442f04c3SJosh Poimboeuf { 144442f04c3SJosh Poimboeuf static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED"; 145442f04c3SJosh Poimboeuf 146442f04c3SJosh Poimboeuf /* libsubcmd init */ 147442f04c3SJosh Poimboeuf exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED); 148442f04c3SJosh Poimboeuf pager_init(UNUSED); 149442f04c3SJosh Poimboeuf 150b51277ebSJosh Poimboeuf objtool_run(argc, argv); 151442f04c3SJosh Poimboeuf 152442f04c3SJosh Poimboeuf return 0; 153442f04c3SJosh Poimboeuf } 154