linux/tools/objtool/builtin-check.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version 2
   7 * of the License, or (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18/*
  19 * objtool check:
  20 *
  21 * This command analyzes every .o file and ensures the validity of its stack
  22 * trace metadata.  It enforces a set of rules on asm code and C inline
  23 * assembly code so that stack traces can be reliable.
  24 *
  25 * For more information, see tools/objtool/Documentation/stack-validation.txt.
  26 */
  27
  28#include <string.h>
  29#include <stdlib.h>
  30#include <subcmd/parse-options.h>
  31
  32#include "builtin.h"
  33#include "elf.h"
  34#include "special.h"
  35#include "arch.h"
  36#include "warn.h"
  37
  38#include <linux/hashtable.h>
  39#include <linux/kernel.h>
  40
  41#define STATE_FP_SAVED          0x1
  42#define STATE_FP_SETUP          0x2
  43#define STATE_FENTRY            0x4
  44
  45struct instruction {
  46        struct list_head list;
  47        struct hlist_node hash;
  48        struct section *sec;
  49        unsigned long offset;
  50        unsigned int len, state;
  51        unsigned char type;
  52        unsigned long immediate;
  53        bool alt_group, visited;
  54        struct symbol *call_dest;
  55        struct instruction *jump_dest;
  56        struct list_head alts;
  57        struct symbol *func;
  58};
  59
  60struct alternative {
  61        struct list_head list;
  62        struct instruction *insn;
  63};
  64
  65struct objtool_file {
  66        struct elf *elf;
  67        struct list_head insn_list;
  68        DECLARE_HASHTABLE(insn_hash, 16);
  69        struct section *rodata, *whitelist;
  70        bool ignore_unreachables, c_file;
  71};
  72
  73const char *objname;
  74static bool nofp;
  75
  76static struct instruction *find_insn(struct objtool_file *file,
  77                                     struct section *sec, unsigned long offset)
  78{
  79        struct instruction *insn;
  80
  81        hash_for_each_possible(file->insn_hash, insn, hash, offset)
  82                if (insn->sec == sec && insn->offset == offset)
  83                        return insn;
  84
  85        return NULL;
  86}
  87
  88static struct instruction *next_insn_same_sec(struct objtool_file *file,
  89                                              struct instruction *insn)
  90{
  91        struct instruction *next = list_next_entry(insn, list);
  92
  93        if (&next->list == &file->insn_list || next->sec != insn->sec)
  94                return NULL;
  95
  96        return next;
  97}
  98
  99#define for_each_insn(file, insn)                                       \
 100        list_for_each_entry(insn, &file->insn_list, list)
 101
 102#define func_for_each_insn(file, func, insn)                            \
 103        for (insn = find_insn(file, func->sec, func->offset);           \
 104             insn && &insn->list != &file->insn_list &&                 \
 105                insn->sec == func->sec &&                               \
 106                insn->offset < func->offset + func->len;                \
 107             insn = list_next_entry(insn, list))
 108
 109#define func_for_each_insn_continue_reverse(file, func, insn)           \
 110        for (insn = list_prev_entry(insn, list);                        \
 111             &insn->list != &file->insn_list &&                         \
 112                insn->sec == func->sec && insn->offset >= func->offset; \
 113             insn = list_prev_entry(insn, list))
 114
 115#define sec_for_each_insn_from(file, insn)                              \
 116        for (; insn; insn = next_insn_same_sec(file, insn))
 117
 118
 119/*
 120 * Check if the function has been manually whitelisted with the
 121 * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted
 122 * due to its use of a context switching instruction.
 123 */
 124static bool ignore_func(struct objtool_file *file, struct symbol *func)
 125{
 126        struct rela *rela;
 127        struct instruction *insn;
 128
 129        /* check for STACK_FRAME_NON_STANDARD */
 130        if (file->whitelist && file->whitelist->rela)
 131                list_for_each_entry(rela, &file->whitelist->rela->rela_list, list)
 132                        if (rela->sym->sec == func->sec &&
 133                            rela->addend == func->offset)
 134                                return true;
 135
 136        /* check if it has a context switching instruction */
 137        func_for_each_insn(file, func, insn)
 138                if (insn->type == INSN_CONTEXT_SWITCH)
 139                        return true;
 140
 141        return false;
 142}
 143
 144/*
 145 * This checks to see if the given function is a "noreturn" function.
 146 *
 147 * For global functions which are outside the scope of this object file, we
 148 * have to keep a manual list of them.
 149 *
 150 * For local functions, we have to detect them manually by simply looking for
 151 * the lack of a return instruction.
 152 *
 153 * Returns:
 154 *  -1: error
 155 *   0: no dead end
 156 *   1: dead end
 157 */
 158static int __dead_end_function(struct objtool_file *file, struct symbol *func,
 159                               int recursion)
 160{
 161        int i;
 162        struct instruction *insn;
 163        bool empty = true;
 164
 165        /*
 166         * Unfortunately these have to be hard coded because the noreturn
 167         * attribute isn't provided in ELF data.
 168         */
 169        static const char * const global_noreturns[] = {
 170                "__stack_chk_fail",
 171                "panic",
 172                "do_exit",
 173                "__module_put_and_exit",
 174                "complete_and_exit",
 175                "kvm_spurious_fault",
 176                "__reiserfs_panic",
 177                "lbug_with_loc"
 178        };
 179
 180        if (!func || func->bind == STB_WEAK)
 181                return 0;
 182
 183        if (func->bind == STB_GLOBAL)
 184                for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
 185                        if (!strcmp(func->name, global_noreturns[i]))
 186                                return 1;
 187
 188        if (!func->sec)
 189                return 0;
 190
 191        func_for_each_insn(file, func, insn) {
 192                empty = false;
 193
 194                if (insn->type == INSN_RETURN)
 195                        return 0;
 196        }
 197
 198        if (empty)
 199                return 0;
 200
 201        /*
 202         * A function can have a sibling call instead of a return.  In that
 203         * case, the function's dead-end status depends on whether the target
 204         * of the sibling call returns.
 205         */
 206        func_for_each_insn(file, func, insn) {
 207                if (insn->sec != func->sec ||
 208                    insn->offset >= func->offset + func->len)
 209                        break;
 210
 211                if (insn->type == INSN_JUMP_UNCONDITIONAL) {
 212                        struct instruction *dest = insn->jump_dest;
 213                        struct symbol *dest_func;
 214
 215                        if (!dest)
 216                                /* sibling call to another file */
 217                                return 0;
 218
 219                        if (dest->sec != func->sec ||
 220                            dest->offset < func->offset ||
 221                            dest->offset >= func->offset + func->len) {
 222                                /* local sibling call */
 223                                dest_func = find_symbol_by_offset(dest->sec,
 224                                                                  dest->offset);
 225                                if (!dest_func)
 226                                        continue;
 227
 228                                if (recursion == 5) {
 229                                        WARN_FUNC("infinite recursion (objtool bug!)",
 230                                                  dest->sec, dest->offset);
 231                                        return -1;
 232                                }
 233
 234                                return __dead_end_function(file, dest_func,
 235                                                           recursion + 1);
 236                        }
 237                }
 238
 239                if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
 240                        /* sibling call */
 241                        return 0;
 242        }
 243
 244        return 1;
 245}
 246
 247static int dead_end_function(struct objtool_file *file, struct symbol *func)
 248{
 249        return __dead_end_function(file, func, 0);
 250}
 251
 252/*
 253 * Call the arch-specific instruction decoder for all the instructions and add
 254 * them to the global instruction list.
 255 */
 256static int decode_instructions(struct objtool_file *file)
 257{
 258        struct section *sec;
 259        struct symbol *func;
 260        unsigned long offset;
 261        struct instruction *insn;
 262        int ret;
 263
 264        list_for_each_entry(sec, &file->elf->sections, list) {
 265
 266                if (!(sec->sh.sh_flags & SHF_EXECINSTR))
 267                        continue;
 268
 269                for (offset = 0; offset < sec->len; offset += insn->len) {
 270                        insn = malloc(sizeof(*insn));
 271                        memset(insn, 0, sizeof(*insn));
 272
 273                        INIT_LIST_HEAD(&insn->alts);
 274                        insn->sec = sec;
 275                        insn->offset = offset;
 276
 277                        ret = arch_decode_instruction(file->elf, sec, offset,
 278                                                      sec->len - offset,
 279                                                      &insn->len, &insn->type,
 280                                                      &insn->immediate);
 281                        if (ret)
 282                                return ret;
 283
 284                        if (!insn->type || insn->type > INSN_LAST) {
 285                                WARN_FUNC("invalid instruction type %d",
 286                                          insn->sec, insn->offset, insn->type);
 287                                return -1;
 288                        }
 289
 290                        hash_add(file->insn_hash, &insn->hash, insn->offset);
 291                        list_add_tail(&insn->list, &file->insn_list);
 292                }
 293
 294                list_for_each_entry(func, &sec->symbol_list, list) {
 295                        if (func->type != STT_FUNC)
 296                                continue;
 297
 298                        if (!find_insn(file, sec, func->offset)) {
 299                                WARN("%s(): can't find starting instruction",
 300                                     func->name);
 301                                return -1;
 302                        }
 303
 304                        func_for_each_insn(file, func, insn)
 305                                if (!insn->func)
 306                                        insn->func = func;
 307                }
 308        }
 309
 310        return 0;
 311}
 312
 313/*
 314 * Warnings shouldn't be reported for ignored functions.
 315 */
 316static void add_ignores(struct objtool_file *file)
 317{
 318        struct instruction *insn;
 319        struct section *sec;
 320        struct symbol *func;
 321
 322        list_for_each_entry(sec, &file->elf->sections, list) {
 323                list_for_each_entry(func, &sec->symbol_list, list) {
 324                        if (func->type != STT_FUNC)
 325                                continue;
 326
 327                        if (!ignore_func(file, func))
 328                                continue;
 329
 330                        func_for_each_insn(file, func, insn)
 331                                insn->visited = true;
 332                }
 333        }
 334}
 335
 336/*
 337 * Find the destination instructions for all jumps.
 338 */
 339static int add_jump_destinations(struct objtool_file *file)
 340{
 341        struct instruction *insn;
 342        struct rela *rela;
 343        struct section *dest_sec;
 344        unsigned long dest_off;
 345
 346        for_each_insn(file, insn) {
 347                if (insn->type != INSN_JUMP_CONDITIONAL &&
 348                    insn->type != INSN_JUMP_UNCONDITIONAL)
 349                        continue;
 350
 351                /* skip ignores */
 352                if (insn->visited)
 353                        continue;
 354
 355                rela = find_rela_by_dest_range(insn->sec, insn->offset,
 356                                               insn->len);
 357                if (!rela) {
 358                        dest_sec = insn->sec;
 359                        dest_off = insn->offset + insn->len + insn->immediate;
 360                } else if (rela->sym->type == STT_SECTION) {
 361                        dest_sec = rela->sym->sec;
 362                        dest_off = rela->addend + 4;
 363                } else if (rela->sym->sec->idx) {
 364                        dest_sec = rela->sym->sec;
 365                        dest_off = rela->sym->sym.st_value + rela->addend + 4;
 366                } else if (strstr(rela->sym->name, "_indirect_thunk_")) {
 367                        /*
 368                         * Retpoline jumps are really dynamic jumps in
 369                         * disguise, so convert them accordingly.
 370                         */
 371                        insn->type = INSN_JUMP_DYNAMIC;
 372                        continue;
 373                } else {
 374                        /* sibling call */
 375                        insn->jump_dest = 0;
 376                        continue;
 377                }
 378
 379                insn->jump_dest = find_insn(file, dest_sec, dest_off);
 380                if (!insn->jump_dest) {
 381
 382                        /*
 383                         * This is a special case where an alt instruction
 384                         * jumps past the end of the section.  These are
 385                         * handled later in handle_group_alt().
 386                         */
 387                        if (!strcmp(insn->sec->name, ".altinstr_replacement"))
 388                                continue;
 389
 390                        WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
 391                                  insn->sec, insn->offset, dest_sec->name,
 392                                  dest_off);
 393                        return -1;
 394                }
 395        }
 396
 397        return 0;
 398}
 399
 400/*
 401 * Find the destination instructions for all calls.
 402 */
 403static int add_call_destinations(struct objtool_file *file)
 404{
 405        struct instruction *insn;
 406        unsigned long dest_off;
 407        struct rela *rela;
 408
 409        for_each_insn(file, insn) {
 410                if (insn->type != INSN_CALL)
 411                        continue;
 412
 413                rela = find_rela_by_dest_range(insn->sec, insn->offset,
 414                                               insn->len);
 415                if (!rela) {
 416                        dest_off = insn->offset + insn->len + insn->immediate;
 417                        insn->call_dest = find_symbol_by_offset(insn->sec,
 418                                                                dest_off);
 419
 420                        /*
 421                         * RHEL: This is a retpoline.  We don't have retpoline
 422                         * annotation on RHEL7, so don't warn about the missing
 423                         * call dest symbol.  Also disable any "unreachable
 424                         * instruction" warnings caused by the retpoline.
 425                         */
 426                        file->ignore_unreachables = true;
 427                } else if (rela->sym->type == STT_SECTION) {
 428                        insn->call_dest = find_symbol_by_offset(rela->sym->sec,
 429                                                                rela->addend+4);
 430                        if (!insn->call_dest ||
 431                            insn->call_dest->type != STT_FUNC) {
 432                                WARN_FUNC("can't find call dest symbol at %s+0x%x",
 433                                          insn->sec, insn->offset,
 434                                          rela->sym->sec->name,
 435                                          rela->addend + 4);
 436                                return -1;
 437                        }
 438                } else
 439                        insn->call_dest = rela->sym;
 440        }
 441
 442        return 0;
 443}
 444
 445/*
 446 * The .alternatives section requires some extra special care, over and above
 447 * what other special sections require:
 448 *
 449 * 1. Because alternatives are patched in-place, we need to insert a fake jump
 450 *    instruction at the end so that validate_branch() skips all the original
 451 *    replaced instructions when validating the new instruction path.
 452 *
 453 * 2. An added wrinkle is that the new instruction length might be zero.  In
 454 *    that case the old instructions are replaced with noops.  We simulate that
 455 *    by creating a fake jump as the only new instruction.
 456 *
 457 * 3. In some cases, the alternative section includes an instruction which
 458 *    conditionally jumps to the _end_ of the entry.  We have to modify these
 459 *    jumps' destinations to point back to .text rather than the end of the
 460 *    entry in .altinstr_replacement.
 461 *
 462 * 4. It has been requested that we don't validate the !POPCNT feature path
 463 *    which is a "very very small percentage of machines".
 464 */
 465static int handle_group_alt(struct objtool_file *file,
 466                            struct special_alt *special_alt,
 467                            struct instruction *orig_insn,
 468                            struct instruction **new_insn)
 469{
 470        struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
 471        unsigned long dest_off;
 472
 473        last_orig_insn = NULL;
 474        insn = orig_insn;
 475        sec_for_each_insn_from(file, insn) {
 476                if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
 477                        break;
 478
 479                if (special_alt->skip_orig)
 480                        insn->type = INSN_NOP;
 481
 482                insn->alt_group = true;
 483                last_orig_insn = insn;
 484        }
 485
 486        if (!next_insn_same_sec(file, last_orig_insn)) {
 487                WARN("%s: don't know how to handle alternatives at end of section",
 488                     special_alt->orig_sec->name);
 489                return -1;
 490        }
 491
 492        fake_jump = malloc(sizeof(*fake_jump));
 493        if (!fake_jump) {
 494                WARN("malloc failed");
 495                return -1;
 496        }
 497        memset(fake_jump, 0, sizeof(*fake_jump));
 498        INIT_LIST_HEAD(&fake_jump->alts);
 499        fake_jump->sec = special_alt->new_sec;
 500        fake_jump->offset = -1;
 501        fake_jump->type = INSN_JUMP_UNCONDITIONAL;
 502        fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
 503
 504        if (!special_alt->new_len) {
 505                *new_insn = fake_jump;
 506                return 0;
 507        }
 508
 509        last_new_insn = NULL;
 510        insn = *new_insn;
 511        sec_for_each_insn_from(file, insn) {
 512                if (insn->offset >= special_alt->new_off + special_alt->new_len)
 513                        break;
 514
 515                last_new_insn = insn;
 516
 517                if (insn->type != INSN_JUMP_CONDITIONAL &&
 518                    insn->type != INSN_JUMP_UNCONDITIONAL)
 519                        continue;
 520
 521                if (!insn->immediate)
 522                        continue;
 523
 524                dest_off = insn->offset + insn->len + insn->immediate;
 525                if (dest_off == special_alt->new_off + special_alt->new_len)
 526                        insn->jump_dest = fake_jump;
 527
 528                if (!insn->jump_dest) {
 529                        WARN_FUNC("can't find alternative jump destination",
 530                                  insn->sec, insn->offset);
 531                        return -1;
 532                }
 533        }
 534
 535        if (!last_new_insn) {
 536                WARN_FUNC("can't find last new alternative instruction",
 537                          special_alt->new_sec, special_alt->new_off);
 538                return -1;
 539        }
 540
 541        list_add(&fake_jump->list, &last_new_insn->list);
 542
 543        return 0;
 544}
 545
 546/*
 547 * A jump table entry can either convert a nop to a jump or a jump to a nop.
 548 * If the original instruction is a jump, make the alt entry an effective nop
 549 * by just skipping the original instruction.
 550 */
 551static int handle_jump_alt(struct objtool_file *file,
 552                           struct special_alt *special_alt,
 553                           struct instruction *orig_insn,
 554                           struct instruction **new_insn)
 555{
 556        if (orig_insn->type == INSN_NOP)
 557                return 0;
 558
 559        if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
 560                WARN_FUNC("unsupported instruction at jump label",
 561                          orig_insn->sec, orig_insn->offset);
 562                return -1;
 563        }
 564
 565        *new_insn = list_next_entry(orig_insn, list);
 566        return 0;
 567}
 568
 569/*
 570 * Read all the special sections which have alternate instructions which can be
 571 * patched in or redirected to at runtime.  Each instruction having alternate
 572 * instruction(s) has them added to its insn->alts list, which will be
 573 * traversed in validate_branch().
 574 */
 575static int add_special_section_alts(struct objtool_file *file)
 576{
 577        struct list_head special_alts;
 578        struct instruction *orig_insn, *new_insn;
 579        struct special_alt *special_alt, *tmp;
 580        struct alternative *alt;
 581        int ret;
 582
 583        ret = special_get_alts(file->elf, &special_alts);
 584        if (ret)
 585                return ret;
 586
 587        list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
 588                alt = malloc(sizeof(*alt));
 589                if (!alt) {
 590                        WARN("malloc failed");
 591                        ret = -1;
 592                        goto out;
 593                }
 594
 595                orig_insn = find_insn(file, special_alt->orig_sec,
 596                                      special_alt->orig_off);
 597                if (!orig_insn) {
 598                        WARN_FUNC("special: can't find orig instruction",
 599                                  special_alt->orig_sec, special_alt->orig_off);
 600                        ret = -1;
 601                        goto out;
 602                }
 603
 604                new_insn = NULL;
 605                if (!special_alt->group || special_alt->new_len) {
 606                        new_insn = find_insn(file, special_alt->new_sec,
 607                                             special_alt->new_off);
 608                        if (!new_insn) {
 609                                WARN_FUNC("special: can't find new instruction",
 610                                          special_alt->new_sec,
 611                                          special_alt->new_off);
 612                                ret = -1;
 613                                goto out;
 614                        }
 615                }
 616
 617                if (special_alt->group) {
 618                        ret = handle_group_alt(file, special_alt, orig_insn,
 619                                               &new_insn);
 620                        if (ret)
 621                                goto out;
 622                } else if (special_alt->jump_or_nop) {
 623                        ret = handle_jump_alt(file, special_alt, orig_insn,
 624                                              &new_insn);
 625                        if (ret)
 626                                goto out;
 627                }
 628
 629                alt->insn = new_insn;
 630                list_add_tail(&alt->list, &orig_insn->alts);
 631
 632                list_del(&special_alt->list);
 633                free(special_alt);
 634        }
 635
 636out:
 637        return ret;
 638}
 639
 640static int add_switch_table(struct objtool_file *file, struct symbol *func,
 641                            struct instruction *insn, struct rela *table,
 642                            struct rela *next_table)
 643{
 644        struct rela *rela = table;
 645        struct instruction *alt_insn;
 646        struct alternative *alt;
 647
 648        list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
 649                if (rela == next_table)
 650                        break;
 651
 652                if (rela->sym->sec != insn->sec ||
 653                    rela->addend <= func->offset ||
 654                    rela->addend >= func->offset + func->len)
 655                        break;
 656
 657                alt_insn = find_insn(file, insn->sec, rela->addend);
 658                if (!alt_insn) {
 659                        WARN("%s: can't find instruction at %s+0x%x",
 660                             file->rodata->rela->name, insn->sec->name,
 661                             rela->addend);
 662                        return -1;
 663                }
 664
 665                alt = malloc(sizeof(*alt));
 666                if (!alt) {
 667                        WARN("malloc failed");
 668                        return -1;
 669                }
 670
 671                alt->insn = alt_insn;
 672                list_add_tail(&alt->list, &insn->alts);
 673        }
 674
 675        return 0;
 676}
 677
 678/*
 679 * find_switch_table() - Given a dynamic jump, find the switch jump table in
 680 * .rodata associated with it.
 681 *
 682 * There are 3 basic patterns:
 683 *
 684 * 1. jmpq *[rodata addr](,%reg,8)
 685 *
 686 *    This is the most common case by far.  It jumps to an address in a simple
 687 *    jump table which is stored in .rodata.
 688 *
 689 * 2. jmpq *[rodata addr](%rip)
 690 *
 691 *    This is caused by a rare GCC quirk, currently only seen in three driver
 692 *    functions in the kernel, only with certain obscure non-distro configs.
 693 *
 694 *    As part of an optimization, GCC makes a copy of an existing switch jump
 695 *    table, modifies it, and then hard-codes the jump (albeit with an indirect
 696 *    jump) to use a single entry in the table.  The rest of the jump table and
 697 *    some of its jump targets remain as dead code.
 698 *
 699 *    In such a case we can just crudely ignore all unreachable instruction
 700 *    warnings for the entire object file.  Ideally we would just ignore them
 701 *    for the function, but that would require redesigning the code quite a
 702 *    bit.  And honestly that's just not worth doing: unreachable instruction
 703 *    warnings are of questionable value anyway, and this is such a rare issue.
 704 *
 705 * 3. mov [rodata addr],%reg1
 706 *    ... some instructions ...
 707 *    jmpq *(%reg1,%reg2,8)
 708 *
 709 *    This is a fairly uncommon pattern which is new for GCC 6.  As of this
 710 *    writing, there are 11 occurrences of it in the allmodconfig kernel.
 711 *
 712 *    TODO: Once we have DWARF CFI and smarter instruction decoding logic,
 713 *    ensure the same register is used in the mov and jump instructions.
 714 */
 715static struct rela *find_switch_table(struct objtool_file *file,
 716                                      struct symbol *func,
 717                                      struct instruction *insn)
 718{
 719        struct rela *text_rela, *rodata_rela;
 720
 721        text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
 722        if (text_rela && text_rela->sym == file->rodata->sym) {
 723                /* case 1 */
 724                rodata_rela = find_rela_by_dest(file->rodata,
 725                                                text_rela->addend);
 726                if (rodata_rela)
 727                        return rodata_rela;
 728
 729                /* case 2 */
 730                rodata_rela = find_rela_by_dest(file->rodata,
 731                                                text_rela->addend + 4);
 732                if (!rodata_rela)
 733                        return NULL;
 734                file->ignore_unreachables = true;
 735                return rodata_rela;
 736        }
 737
 738        /* case 3 */
 739        func_for_each_insn_continue_reverse(file, func, insn) {
 740                if (insn->type == INSN_JUMP_UNCONDITIONAL ||
 741                    insn->type == INSN_JUMP_DYNAMIC)
 742                        break;
 743
 744                text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
 745                                                    insn->len);
 746                if (text_rela && text_rela->sym == file->rodata->sym)
 747                        return find_rela_by_dest(file->rodata,
 748                                                 text_rela->addend);
 749        }
 750
 751        return NULL;
 752}
 753
 754static int add_func_switch_tables(struct objtool_file *file,
 755                                  struct symbol *func)
 756{
 757        struct instruction *insn, *prev_jump = NULL;
 758        struct rela *rela, *prev_rela = NULL;
 759        int ret;
 760
 761        func_for_each_insn(file, func, insn) {
 762                if (insn->type != INSN_JUMP_DYNAMIC)
 763                        continue;
 764
 765                rela = find_switch_table(file, func, insn);
 766                if (!rela)
 767                        continue;
 768
 769                /*
 770                 * We found a switch table, but we don't know yet how big it
 771                 * is.  Don't add it until we reach the end of the function or
 772                 * the beginning of another switch table in the same function.
 773                 */
 774                if (prev_jump) {
 775                        ret = add_switch_table(file, func, prev_jump, prev_rela,
 776                                               rela);
 777                        if (ret)
 778                                return ret;
 779                }
 780
 781                prev_jump = insn;
 782                prev_rela = rela;
 783        }
 784
 785        if (prev_jump) {
 786                ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
 787                if (ret)
 788                        return ret;
 789        }
 790
 791        return 0;
 792}
 793
 794/*
 795 * For some switch statements, gcc generates a jump table in the .rodata
 796 * section which contains a list of addresses within the function to jump to.
 797 * This finds these jump tables and adds them to the insn->alts lists.
 798 */
 799static int add_switch_table_alts(struct objtool_file *file)
 800{
 801        struct section *sec;
 802        struct symbol *func;
 803        int ret;
 804
 805        if (!file->rodata || !file->rodata->rela)
 806                return 0;
 807
 808        list_for_each_entry(sec, &file->elf->sections, list) {
 809                list_for_each_entry(func, &sec->symbol_list, list) {
 810                        if (func->type != STT_FUNC)
 811                                continue;
 812
 813                        ret = add_func_switch_tables(file, func);
 814                        if (ret)
 815                                return ret;
 816                }
 817        }
 818
 819        return 0;
 820}
 821
 822static int decode_sections(struct objtool_file *file)
 823{
 824        int ret;
 825
 826        ret = decode_instructions(file);
 827        if (ret)
 828                return ret;
 829
 830        add_ignores(file);
 831
 832        ret = add_jump_destinations(file);
 833        if (ret)
 834                return ret;
 835
 836        ret = add_call_destinations(file);
 837        if (ret)
 838                return ret;
 839
 840        ret = add_special_section_alts(file);
 841        if (ret)
 842                return ret;
 843
 844        ret = add_switch_table_alts(file);
 845        if (ret)
 846                return ret;
 847
 848        return 0;
 849}
 850
 851static bool is_fentry_call(struct instruction *insn)
 852{
 853        if (insn->type == INSN_CALL && insn->call_dest &&
 854            insn->call_dest->type == STT_NOTYPE &&
 855            !strcmp(insn->call_dest->name, "__fentry__"))
 856                return true;
 857
 858        return false;
 859}
 860
 861static bool has_modified_stack_frame(struct instruction *insn)
 862{
 863        return (insn->state & STATE_FP_SAVED) ||
 864               (insn->state & STATE_FP_SETUP);
 865}
 866
 867static bool has_valid_stack_frame(struct instruction *insn)
 868{
 869        return (insn->state & STATE_FP_SAVED) &&
 870               (insn->state & STATE_FP_SETUP);
 871}
 872
 873static unsigned int frame_state(unsigned long state)
 874{
 875        return (state & (STATE_FP_SAVED | STATE_FP_SETUP));
 876}
 877
 878/*
 879 * Follow the branch starting at the given instruction, and recursively follow
 880 * any other branches (jumps).  Meanwhile, track the frame pointer state at
 881 * each instruction and validate all the rules described in
 882 * tools/objtool/Documentation/stack-validation.txt.
 883 */
 884static int validate_branch(struct objtool_file *file,
 885                           struct instruction *first, unsigned char first_state)
 886{
 887        struct alternative *alt;
 888        struct instruction *insn;
 889        struct section *sec;
 890        struct symbol *func = NULL;
 891        unsigned char state;
 892        int ret;
 893
 894        insn = first;
 895        sec = insn->sec;
 896        state = first_state;
 897
 898        if (insn->alt_group && list_empty(&insn->alts)) {
 899                WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
 900                          sec, insn->offset);
 901                return 1;
 902        }
 903
 904        while (1) {
 905                if (file->c_file && insn->func) {
 906                        if (func && func != insn->func) {
 907                                WARN("%s() falls through to next function %s()",
 908                                     func->name, insn->func->name);
 909                                return 1;
 910                        }
 911
 912                        func = insn->func;
 913                }
 914
 915                if (insn->visited) {
 916                        if (frame_state(insn->state) != frame_state(state)) {
 917                                WARN_FUNC("frame pointer state mismatch",
 918                                          sec, insn->offset);
 919                                return 1;
 920                        }
 921
 922                        return 0;
 923                }
 924
 925                insn->visited = true;
 926                insn->state = state;
 927
 928                list_for_each_entry(alt, &insn->alts, list) {
 929                        ret = validate_branch(file, alt->insn, state);
 930                        if (ret)
 931                                return 1;
 932                }
 933
 934                switch (insn->type) {
 935
 936                case INSN_FP_SAVE:
 937                        if (!nofp) {
 938                                if (state & STATE_FP_SAVED) {
 939                                        WARN_FUNC("duplicate frame pointer save",
 940                                                  sec, insn->offset);
 941                                        return 1;
 942                                }
 943                                state |= STATE_FP_SAVED;
 944                        }
 945                        break;
 946
 947                case INSN_FP_SETUP:
 948                        if (!nofp) {
 949                                if (state & STATE_FP_SETUP) {
 950                                        WARN_FUNC("duplicate frame pointer setup",
 951                                                  sec, insn->offset);
 952                                        return 1;
 953                                }
 954                                state |= STATE_FP_SETUP;
 955                        }
 956                        break;
 957
 958                case INSN_FP_RESTORE:
 959                        if (!nofp) {
 960                                if (has_valid_stack_frame(insn))
 961                                        state &= ~STATE_FP_SETUP;
 962
 963                                state &= ~STATE_FP_SAVED;
 964                        }
 965                        break;
 966
 967                case INSN_RETURN:
 968                        if (!nofp && has_modified_stack_frame(insn)) {
 969                                WARN_FUNC("return without frame pointer restore",
 970                                          sec, insn->offset);
 971                                return 1;
 972                        }
 973                        return 0;
 974
 975                case INSN_CALL:
 976                        if (is_fentry_call(insn)) {
 977                                state |= STATE_FENTRY;
 978                                break;
 979                        }
 980
 981                        ret = dead_end_function(file, insn->call_dest);
 982                        if (ret == 1)
 983                                return 0;
 984                        if (ret == -1)
 985                                return 1;
 986
 987                        /* fallthrough */
 988                case INSN_CALL_DYNAMIC:
 989                        if (!nofp && !has_valid_stack_frame(insn)) {
 990                                WARN_FUNC("call without frame pointer save/setup",
 991                                          sec, insn->offset);
 992                                return 1;
 993                        }
 994                        break;
 995
 996                case INSN_JUMP_CONDITIONAL:
 997                case INSN_JUMP_UNCONDITIONAL:
 998                        if (insn->jump_dest) {
 999                                ret = validate_branch(file, insn->jump_dest,
1000                                                      state);
1001                                if (ret)
1002                                        return 1;
1003                        } else if (has_modified_stack_frame(insn)) {
1004                                WARN_FUNC("sibling call from callable instruction with changed frame pointer",
1005                                          sec, insn->offset);
1006                                return 1;
1007                        } /* else it's a sibling call */
1008
1009                        if (insn->type == INSN_JUMP_UNCONDITIONAL)
1010                                return 0;
1011
1012                        break;
1013
1014                case INSN_JUMP_DYNAMIC:
1015                        if (list_empty(&insn->alts) &&
1016                            has_modified_stack_frame(insn)) {
1017                                WARN_FUNC("sibling call from callable instruction with changed frame pointer",
1018                                          sec, insn->offset);
1019                                return 1;
1020                        }
1021
1022                        return 0;
1023
1024                case INSN_BUG:
1025                        return 0;
1026
1027                default:
1028                        break;
1029                }
1030
1031                insn = next_insn_same_sec(file, insn);
1032                if (!insn) {
1033                        WARN("%s: unexpected end of section", sec->name);
1034                        return 1;
1035                }
1036        }
1037
1038        return 0;
1039}
1040
1041static bool is_gcov_insn(struct instruction *insn)
1042{
1043        struct rela *rela;
1044        struct section *sec;
1045        struct symbol *sym;
1046        unsigned long offset;
1047
1048        rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
1049        if (!rela)
1050                return false;
1051
1052        if (rela->sym->type != STT_SECTION)
1053                return false;
1054
1055        sec = rela->sym->sec;
1056        offset = rela->addend + insn->offset + insn->len - rela->offset;
1057
1058        list_for_each_entry(sym, &sec->symbol_list, list) {
1059                if (sym->type != STT_OBJECT)
1060                        continue;
1061
1062                if (offset >= sym->offset && offset < sym->offset + sym->len)
1063                        return (!memcmp(sym->name, "__gcov0.", 8));
1064        }
1065
1066        return false;
1067}
1068
1069static bool is_kasan_insn(struct instruction *insn)
1070{
1071        return (insn->type == INSN_CALL && insn->call_dest &&
1072                !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
1073}
1074
1075static bool is_ubsan_insn(struct instruction *insn)
1076{
1077        return (insn->type == INSN_CALL && insn->call_dest &&
1078                !strcmp(insn->call_dest->name,
1079                        "__ubsan_handle_builtin_unreachable"));
1080}
1081
1082static bool ignore_unreachable_insn(struct symbol *func,
1083                                    struct instruction *insn)
1084{
1085        int i;
1086
1087        if (insn->type == INSN_NOP)
1088                return true;
1089
1090        if (is_gcov_insn(insn))
1091                return true;
1092
1093        /*
1094         * Check if this (or a subsequent) instruction is related to
1095         * CONFIG_UBSAN or CONFIG_KASAN.
1096         *
1097         * End the search at 5 instructions to avoid going into the weeds.
1098         */
1099        for (i = 0; i < 5; i++) {
1100
1101                if (is_kasan_insn(insn) || is_ubsan_insn(insn))
1102                        return true;
1103
1104                if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
1105                        insn = insn->jump_dest;
1106                        continue;
1107                }
1108
1109                if (insn->offset + insn->len >= func->offset + func->len)
1110                        break;
1111                insn = list_next_entry(insn, list);
1112        }
1113
1114        return false;
1115}
1116
1117static int validate_functions(struct objtool_file *file)
1118{
1119        struct section *sec;
1120        struct symbol *func;
1121        struct instruction *insn;
1122        int ret, warnings = 0;
1123
1124        list_for_each_entry(sec, &file->elf->sections, list) {
1125                list_for_each_entry(func, &sec->symbol_list, list) {
1126                        if (func->type != STT_FUNC)
1127                                continue;
1128
1129                        insn = find_insn(file, sec, func->offset);
1130                        if (!insn)
1131                                continue;
1132
1133                        ret = validate_branch(file, insn, 0);
1134                        warnings += ret;
1135                }
1136        }
1137
1138        list_for_each_entry(sec, &file->elf->sections, list) {
1139                list_for_each_entry(func, &sec->symbol_list, list) {
1140                        if (func->type != STT_FUNC)
1141                                continue;
1142
1143                        func_for_each_insn(file, func, insn) {
1144                                if (insn->visited)
1145                                        continue;
1146
1147                                insn->visited = true;
1148
1149                                if (file->ignore_unreachables || warnings ||
1150                                    ignore_unreachable_insn(func, insn))
1151                                        continue;
1152
1153                                WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1154                                warnings++;
1155                        }
1156                }
1157        }
1158
1159        return warnings;
1160}
1161
1162static int validate_uncallable_instructions(struct objtool_file *file)
1163{
1164        struct instruction *insn;
1165        int warnings = 0;
1166
1167        for_each_insn(file, insn) {
1168                if (!insn->visited && insn->type == INSN_RETURN) {
1169                        WARN_FUNC("return instruction outside of a callable function",
1170                                  insn->sec, insn->offset);
1171                        warnings++;
1172                }
1173        }
1174
1175        return warnings;
1176}
1177
1178static void cleanup(struct objtool_file *file)
1179{
1180        struct instruction *insn, *tmpinsn;
1181        struct alternative *alt, *tmpalt;
1182
1183        list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
1184                list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
1185                        list_del(&alt->list);
1186                        free(alt);
1187                }
1188                list_del(&insn->list);
1189                hash_del(&insn->hash);
1190                free(insn);
1191        }
1192        elf_close(file->elf);
1193}
1194
1195const char * const check_usage[] = {
1196        "objtool check [<options>] file.o",
1197        NULL,
1198};
1199
1200int cmd_check(int argc, const char **argv)
1201{
1202        struct objtool_file file;
1203        int ret, warnings = 0;
1204
1205        const struct option options[] = {
1206                OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
1207                OPT_END(),
1208        };
1209
1210        argc = parse_options(argc, argv, options, check_usage, 0);
1211
1212        if (argc != 1)
1213                usage_with_options(check_usage, options);
1214
1215        objname = argv[0];
1216
1217        file.elf = elf_open(objname);
1218        if (!file.elf) {
1219                fprintf(stderr, "error reading elf file %s\n", objname);
1220                return 1;
1221        }
1222
1223        INIT_LIST_HEAD(&file.insn_list);
1224        hash_init(file.insn_hash);
1225        file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard");
1226        file.rodata = find_section_by_name(file.elf, ".rodata");
1227        file.ignore_unreachables = false;
1228        file.c_file = find_section_by_name(file.elf, ".comment");
1229
1230        ret = decode_sections(&file);
1231        if (ret < 0)
1232                goto out;
1233        warnings += ret;
1234
1235        ret = validate_functions(&file);
1236        if (ret < 0)
1237                goto out;
1238        warnings += ret;
1239
1240        ret = validate_uncallable_instructions(&file);
1241        if (ret < 0)
1242                goto out;
1243        warnings += ret;
1244
1245out:
1246        cleanup(&file);
1247
1248        /* ignore warnings for now until we get all the code cleaned up */
1249        if (ret || warnings)
1250                return 0;
1251        return 0;
1252}
1253