0001
0002
0003
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
0127
0128
0129 if (!strcmp(func->name, "_paravirt_nop") ||
0130 !strcmp(func->name, "_paravirt_ident_64"))
0131 return;
0132
0133
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
0146 exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
0147 pager_init(UNUSED);
0148
0149 objtool_run(argc, argv);
0150
0151 return 0;
0152 }