Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
0004  */
0005 
0006 #include <stdio.h>
0007 #include <stdbool.h>
0008 #include <string.h>
0009 #include <stdlib.h>
0010 #include <unistd.h>
0011 #include <subcmd/exec-cmd.h>
0012 #include <subcmd/pager.h>
0013 #include <linux/kernel.h>
0014 
0015 #include <objtool/builtin.h>
0016 #include <objtool/objtool.h>
0017 #include <objtool/warn.h>
0018 
0019 bool help;
0020 
0021 const char *objname;
0022 static struct objtool_file file;
0023 
0024 static bool objtool_create_backup(const char *_objname)
0025 {
0026     int len = strlen(_objname);
0027     char *buf, *base, *name = malloc(len+6);
0028     int s, d, l, t;
0029 
0030     if (!name) {
0031         perror("failed backup name malloc");
0032         return false;
0033     }
0034 
0035     strcpy(name, _objname);
0036     strcpy(name + len, ".orig");
0037 
0038     d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
0039     if (d < 0) {
0040         perror("failed to create backup file");
0041         return false;
0042     }
0043 
0044     s = open(_objname, O_RDONLY);
0045     if (s < 0) {
0046         perror("failed to open orig file");
0047         return false;
0048     }
0049 
0050     buf = malloc(4096);
0051     if (!buf) {
0052         perror("failed backup data malloc");
0053         return false;
0054     }
0055 
0056     while ((l = read(s, buf, 4096)) > 0) {
0057         base = buf;
0058         do {
0059             t = write(d, base, l);
0060             if (t < 0) {
0061                 perror("failed backup write");
0062                 return false;
0063             }
0064             base += t;
0065             l -= t;
0066         } while (l);
0067     }
0068 
0069     if (l < 0) {
0070         perror("failed backup read");
0071         return false;
0072     }
0073 
0074     free(name);
0075     free(buf);
0076     close(d);
0077     close(s);
0078 
0079     return true;
0080 }
0081 
0082 struct objtool_file *objtool_open_read(const char *_objname)
0083 {
0084     if (objname) {
0085         if (strcmp(objname, _objname)) {
0086             WARN("won't handle more than one file at a time");
0087             return NULL;
0088         }
0089         return &file;
0090     }
0091     objname = _objname;
0092 
0093     file.elf = elf_open_read(objname, O_RDWR);
0094     if (!file.elf)
0095         return NULL;
0096 
0097     if (opts.backup && !objtool_create_backup(objname)) {
0098         WARN("can't create backup file");
0099         return NULL;
0100     }
0101 
0102     INIT_LIST_HEAD(&file.insn_list);
0103     hash_init(file.insn_hash);
0104     INIT_LIST_HEAD(&file.retpoline_call_list);
0105     INIT_LIST_HEAD(&file.return_thunk_list);
0106     INIT_LIST_HEAD(&file.static_call_list);
0107     INIT_LIST_HEAD(&file.mcount_loc_list);
0108     INIT_LIST_HEAD(&file.endbr_list);
0109     file.ignore_unreachables = opts.no_unreachable;
0110     file.hints = false;
0111 
0112     return &file;
0113 }
0114 
0115 void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func)
0116 {
0117     if (!opts.noinstr)
0118         return;
0119 
0120     if (!f->pv_ops) {
0121         WARN("paravirt confusion");
0122         return;
0123     }
0124 
0125     /*
0126      * These functions will be patched into native code,
0127      * see paravirt_patch().
0128      */
0129     if (!strcmp(func->name, "_paravirt_nop") ||
0130         !strcmp(func->name, "_paravirt_ident_64"))
0131         return;
0132 
0133     /* already added this function */
0134     if (!list_empty(&func->pv_target))
0135         return;
0136 
0137     list_add(&func->pv_target, &f->pv_ops[idx].targets);
0138     f->pv_ops[idx].clean = false;
0139 }
0140 
0141 int main(int argc, const char **argv)
0142 {
0143     static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
0144 
0145     /* libsubcmd init */
0146     exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
0147     pager_init(UNUSED);
0148 
0149     objtool_run(argc, argv);
0150 
0151     return 0;
0152 }