forked from Minki/linux
03b2cd72aa
- Standardize the crypto asm code so that it looks like compiler-generated code to objtool - so that it can understand it. This enables unwinding from crypto asm code - and also fixes the last known remaining objtool warnings for LTO and more. - x86 decoder fixes: clean up and fix the decoder, and also extend it a bit - Misc fixes and cleanups Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmCJEOQRHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1jN0A//dZIR9GPW1cHkPD3Na+lxb+RWgCVnFUgw meLEOum389zWr7S8YmcFpKWLy94f3l24i/e7ufKn6/RMdaQuT6pZUa6teiNPqDKN Qq1v6EX/LT49Q1zh/zCCnKdlmF1t7wDyA1/+HBLnB4YfYEtteEt+p2Apyv4xIHOl xWqaTMFcVR/El9FXSyqRWRR4zuqY0Uatz0fmfo5jmi2xq460k53fQlTLA/0w5Jw0 V3omyA3AYMUW6YlW5TGUINOhyDeAJm4PWl3siSUnSd6t8A/TVs5zpZX15BtseCle 0FRp2SbxOoVkiyo3N3XmkfYYns9+4wK7cr9qja9U9MsSBZJZwaBm2LO/t2WFrAhq 5dkOsoPmpIsjutsQnIhQgtVT9I/A4/u5m5Zi3trlXsBS0XAt/q+2GPfEngFmgb3q nae4rhGUsQ3NTGBiqNuMHQF4yeEvQZ8DCf3ytTz7DjBeiQ9nAtwzbUUGQjYl2mj1 ZPOnl7Xmq/Nyw+AmdpffFPiEUJxqEg9HWjDo7DQATXb3Hw2VJ3cU8jwPRqDDlO10 OB81vysXNGTmhOngHXexxncpmU9gDOIC1imZZpw5lNx4W9Qn20AlGaGAIbqzlfx0 p5VuhkIWCySe1bOZx03xuk7Gq7GBIPPy/a2m204Ftipetlo1HBYwT3KB/wVpHmh7 CSjWgdiW3+k= =poAZ -----END PGP SIGNATURE----- Merge tag 'objtool-core-2021-04-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull objtool updates from Ingo Molnar: - Standardize the crypto asm code so that it looks like compiler- generated code to objtool - so that it can understand it. This enables unwinding from crypto asm code - and also fixes the last known remaining objtool warnings for LTO and more. - x86 decoder fixes: clean up and fix the decoder, and also extend it a bit - Misc fixes and cleanups * tag 'objtool-core-2021-04-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits) x86/crypto: Enable objtool in crypto code x86/crypto/sha512-ssse3: Standardize stack alignment prologue x86/crypto/sha512-avx2: Standardize stack alignment prologue x86/crypto/sha512-avx: Standardize stack alignment prologue x86/crypto/sha256-avx2: Standardize stack alignment prologue x86/crypto/sha1_avx2: Standardize stack alignment prologue x86/crypto/sha_ni: Standardize stack alignment prologue x86/crypto/crc32c-pcl-intel: Standardize jump table x86/crypto/camellia-aesni-avx2: Unconditionally allocate stack buffer x86/crypto/aesni-intel_avx: Standardize stack alignment prologue x86/crypto/aesni-intel_avx: Fix register usage comments x86/crypto/aesni-intel_avx: Remove unused macros objtool: Support asm jump tables objtool: Parse options from OBJTOOL_ARGS objtool: Collate parse_options() users objtool: Add --backup objtool,x86: More ModRM sugar objtool,x86: Rewrite ADD/SUB/AND objtool,x86: Support %riz encodings objtool,x86: Simplify register decode ...
221 lines
4.2 KiB
C
221 lines
4.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
|
|
*/
|
|
|
|
/*
|
|
* objtool:
|
|
*
|
|
* The 'check' subcmd analyzes every .o file and ensures the validity of its
|
|
* stack trace metadata. It enforces a set of rules on asm code and C inline
|
|
* assembly code so that stack traces can be reliable.
|
|
*
|
|
* For more information, see tools/objtool/Documentation/stack-validation.txt.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <subcmd/exec-cmd.h>
|
|
#include <subcmd/pager.h>
|
|
#include <linux/kernel.h>
|
|
|
|
#include <objtool/builtin.h>
|
|
#include <objtool/objtool.h>
|
|
#include <objtool/warn.h>
|
|
|
|
struct cmd_struct {
|
|
const char *name;
|
|
int (*fn)(int, const char **);
|
|
const char *help;
|
|
};
|
|
|
|
static const char objtool_usage_string[] =
|
|
"objtool COMMAND [ARGS]";
|
|
|
|
static struct cmd_struct objtool_cmds[] = {
|
|
{"check", cmd_check, "Perform stack metadata validation on an object file" },
|
|
{"orc", cmd_orc, "Generate in-place ORC unwind tables for an object file" },
|
|
};
|
|
|
|
bool help;
|
|
|
|
const char *objname;
|
|
static struct objtool_file file;
|
|
|
|
static bool objtool_create_backup(const char *_objname)
|
|
{
|
|
int len = strlen(_objname);
|
|
char *buf, *base, *name = malloc(len+6);
|
|
int s, d, l, t;
|
|
|
|
if (!name) {
|
|
perror("failed backup name malloc");
|
|
return false;
|
|
}
|
|
|
|
strcpy(name, _objname);
|
|
strcpy(name + len, ".orig");
|
|
|
|
d = open(name, O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
|
if (d < 0) {
|
|
perror("failed to create backup file");
|
|
return false;
|
|
}
|
|
|
|
s = open(_objname, O_RDONLY);
|
|
if (s < 0) {
|
|
perror("failed to open orig file");
|
|
return false;
|
|
}
|
|
|
|
buf = malloc(4096);
|
|
if (!buf) {
|
|
perror("failed backup data malloc");
|
|
return false;
|
|
}
|
|
|
|
while ((l = read(s, buf, 4096)) > 0) {
|
|
base = buf;
|
|
do {
|
|
t = write(d, base, l);
|
|
if (t < 0) {
|
|
perror("failed backup write");
|
|
return false;
|
|
}
|
|
base += t;
|
|
l -= t;
|
|
} while (l);
|
|
}
|
|
|
|
if (l < 0) {
|
|
perror("failed backup read");
|
|
return false;
|
|
}
|
|
|
|
free(name);
|
|
free(buf);
|
|
close(d);
|
|
close(s);
|
|
|
|
return true;
|
|
}
|
|
|
|
struct objtool_file *objtool_open_read(const char *_objname)
|
|
{
|
|
if (objname) {
|
|
if (strcmp(objname, _objname)) {
|
|
WARN("won't handle more than one file at a time");
|
|
return NULL;
|
|
}
|
|
return &file;
|
|
}
|
|
objname = _objname;
|
|
|
|
file.elf = elf_open_read(objname, O_RDWR);
|
|
if (!file.elf)
|
|
return NULL;
|
|
|
|
if (backup && !objtool_create_backup(objname)) {
|
|
WARN("can't create backup file");
|
|
return NULL;
|
|
}
|
|
|
|
INIT_LIST_HEAD(&file.insn_list);
|
|
hash_init(file.insn_hash);
|
|
INIT_LIST_HEAD(&file.retpoline_call_list);
|
|
INIT_LIST_HEAD(&file.static_call_list);
|
|
INIT_LIST_HEAD(&file.mcount_loc_list);
|
|
file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
|
|
file.ignore_unreachables = no_unreachable;
|
|
file.hints = false;
|
|
|
|
return &file;
|
|
}
|
|
|
|
static void cmd_usage(void)
|
|
{
|
|
unsigned int i, longest = 0;
|
|
|
|
printf("\n usage: %s\n\n", objtool_usage_string);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
|
|
if (longest < strlen(objtool_cmds[i].name))
|
|
longest = strlen(objtool_cmds[i].name);
|
|
}
|
|
|
|
puts(" Commands:");
|
|
for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
|
|
printf(" %-*s ", longest, objtool_cmds[i].name);
|
|
puts(objtool_cmds[i].help);
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
if (!help)
|
|
exit(129);
|
|
exit(0);
|
|
}
|
|
|
|
static void handle_options(int *argc, const char ***argv)
|
|
{
|
|
while (*argc > 0) {
|
|
const char *cmd = (*argv)[0];
|
|
|
|
if (cmd[0] != '-')
|
|
break;
|
|
|
|
if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h")) {
|
|
help = true;
|
|
break;
|
|
} else {
|
|
fprintf(stderr, "Unknown option: %s\n", cmd);
|
|
cmd_usage();
|
|
}
|
|
|
|
(*argv)++;
|
|
(*argc)--;
|
|
}
|
|
}
|
|
|
|
static void handle_internal_command(int argc, const char **argv)
|
|
{
|
|
const char *cmd = argv[0];
|
|
unsigned int i, ret;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(objtool_cmds); i++) {
|
|
struct cmd_struct *p = objtool_cmds+i;
|
|
|
|
if (strcmp(p->name, cmd))
|
|
continue;
|
|
|
|
ret = p->fn(argc, argv);
|
|
|
|
exit(ret);
|
|
}
|
|
|
|
cmd_usage();
|
|
}
|
|
|
|
int main(int argc, const char **argv)
|
|
{
|
|
static const char *UNUSED = "OBJTOOL_NOT_IMPLEMENTED";
|
|
|
|
/* libsubcmd init */
|
|
exec_cmd_init("objtool", UNUSED, UNUSED, UNUSED);
|
|
pager_init(UNUSED);
|
|
|
|
argv++;
|
|
argc--;
|
|
handle_options(&argc, &argv);
|
|
|
|
if (!argc || help)
|
|
cmd_usage();
|
|
|
|
handle_internal_command(argc, argv);
|
|
|
|
return 0;
|
|
}
|