~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/objtool/orc_gen.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
  4  */
  5 
  6 #include <stdlib.h>
  7 #include <string.h>
  8 
  9 #include <linux/objtool_types.h>
 10 #include <asm/orc_types.h>
 11 
 12 #include <objtool/check.h>
 13 #include <objtool/orc.h>
 14 #include <objtool/warn.h>
 15 #include <objtool/endianness.h>
 16 
 17 struct orc_list_entry {
 18         struct list_head list;
 19         struct orc_entry orc;
 20         struct section *insn_sec;
 21         unsigned long insn_off;
 22 };
 23 
 24 static int orc_list_add(struct list_head *orc_list, struct orc_entry *orc,
 25                         struct section *sec, unsigned long offset)
 26 {
 27         struct orc_list_entry *entry = malloc(sizeof(*entry));
 28 
 29         if (!entry) {
 30                 WARN("malloc failed");
 31                 return -1;
 32         }
 33 
 34         entry->orc      = *orc;
 35         entry->insn_sec = sec;
 36         entry->insn_off = offset;
 37 
 38         list_add_tail(&entry->list, orc_list);
 39         return 0;
 40 }
 41 
 42 static unsigned long alt_group_len(struct alt_group *alt_group)
 43 {
 44         return alt_group->last_insn->offset +
 45                alt_group->last_insn->len -
 46                alt_group->first_insn->offset;
 47 }
 48 
 49 int orc_create(struct objtool_file *file)
 50 {
 51         struct section *sec, *orc_sec;
 52         unsigned int nr = 0, idx = 0;
 53         struct orc_list_entry *entry;
 54         struct list_head orc_list;
 55 
 56         struct orc_entry null = { .type = ORC_TYPE_UNDEFINED };
 57 
 58         /* Build a deduplicated list of ORC entries: */
 59         INIT_LIST_HEAD(&orc_list);
 60         for_each_sec(file, sec) {
 61                 struct orc_entry orc, prev_orc = {0};
 62                 struct instruction *insn;
 63                 bool empty = true;
 64 
 65                 if (!sec->text)
 66                         continue;
 67 
 68                 sec_for_each_insn(file, sec, insn) {
 69                         struct alt_group *alt_group = insn->alt_group;
 70                         int i;
 71 
 72                         if (!alt_group) {
 73                                 if (init_orc_entry(&orc, insn->cfi, insn))
 74                                         return -1;
 75                                 if (!memcmp(&prev_orc, &orc, sizeof(orc)))
 76                                         continue;
 77                                 if (orc_list_add(&orc_list, &orc, sec,
 78                                                  insn->offset))
 79                                         return -1;
 80                                 nr++;
 81                                 prev_orc = orc;
 82                                 empty = false;
 83                                 continue;
 84                         }
 85 
 86                         /*
 87                          * Alternatives can have different stack layout
 88                          * possibilities (but they shouldn't conflict).
 89                          * Instead of traversing the instructions, use the
 90                          * alt_group's flattened byte-offset-addressed CFI
 91                          * array.
 92                          */
 93                         for (i = 0; i < alt_group_len(alt_group); i++) {
 94                                 struct cfi_state *cfi = alt_group->cfi[i];
 95                                 if (!cfi)
 96                                         continue;
 97                                 /* errors are reported on the original insn */
 98                                 if (init_orc_entry(&orc, cfi, insn))
 99                                         return -1;
100                                 if (!memcmp(&prev_orc, &orc, sizeof(orc)))
101                                         continue;
102                                 if (orc_list_add(&orc_list, &orc, insn->sec,
103                                                  insn->offset + i))
104                                         return -1;
105                                 nr++;
106                                 prev_orc = orc;
107                                 empty = false;
108                         }
109 
110                         /* Skip to the end of the alt_group */
111                         insn = alt_group->last_insn;
112                 }
113 
114                 /* Add a section terminator */
115                 if (!empty) {
116                         orc_list_add(&orc_list, &null, sec, sec->sh.sh_size);
117                         nr++;
118                 }
119         }
120         if (!nr)
121                 return 0;
122 
123         /* Create .orc_unwind, .orc_unwind_ip and .rela.orc_unwind_ip sections: */
124         sec = find_section_by_name(file->elf, ".orc_unwind");
125         if (sec) {
126                 WARN("file already has .orc_unwind section, skipping");
127                 return -1;
128         }
129         orc_sec = elf_create_section(file->elf, ".orc_unwind",
130                                      sizeof(struct orc_entry), nr);
131         if (!orc_sec)
132                 return -1;
133 
134         sec = elf_create_section_pair(file->elf, ".orc_unwind_ip", sizeof(int), nr, nr);
135         if (!sec)
136                 return -1;
137 
138         /* Write ORC entries to sections: */
139         list_for_each_entry(entry, &orc_list, list) {
140                 if (write_orc_entry(file->elf, orc_sec, sec, idx++,
141                                     entry->insn_sec, entry->insn_off,
142                                     &entry->orc))
143                         return -1;
144         }
145 
146         return 0;
147 }
148 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php