omitrbp.c (4029B)
1 #include <sys/param.h> 2 #include <sys/sysctl.h> 3 4 #include <err.h> 5 #include <fcntl.h> 6 #include <gelf.h> 7 #include <libelf.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 struct section { 14 GElf_Shdr sh; 15 Elf_Scn *scn; 16 const char *name; 17 }; 18 19 static struct section *sl; 20 static size_t shnum; 21 static int first_instr = 0; 22 23 static void 24 print_rbp_ommited(const char *func, uint64_t lo, uint64_t hi) 25 { 26 Elf_Data *d; 27 struct section *s; 28 uint8_t *buf; 29 uint64_t addr; 30 int i; 31 32 for (i = 1; i < shnum; i++) { 33 s = &sl[i]; 34 if (strcmp(s->name, ".text") != 0 || 35 s->sh.sh_type != SHT_PROGBITS) 36 continue; 37 (void)elf_errno(); 38 if ((d = elf_getdata(s->scn, NULL)) == NULL) { 39 if (elf_errno() != 0) 40 warnx("elf_getdata(): %s", elf_errmsg(-1)); 41 continue; 42 } 43 if (d->d_size <= 0 || d->d_buf == NULL) 44 continue; 45 buf = d->d_buf; 46 addr = s->sh.sh_addr + d->d_off; 47 while (addr != lo) { 48 addr++; 49 buf++; 50 } 51 if (first_instr) { 52 if (*buf != 0x55) 53 puts(func); 54 } else { 55 int found = 0; 56 57 while (addr != hi) { 58 if (*buf == 0x55) 59 found = 1; 60 addr++; 61 buf++; 62 } 63 if (!found) 64 puts(func); 65 } 66 return; 67 } 68 } 69 70 int 71 main(int argc, char *argv[]) 72 { 73 Elf *elf; 74 Elf_Scn *scn; 75 Elf_Data *d; 76 GElf_Shdr sh; 77 GElf_Sym sym; 78 struct section *s; 79 uint64_t lo, hi; 80 uint32_t stab; 81 const char *name, *func; 82 char bootfile[BUFSIZ]; 83 size_t shstrndx, ndx, slen; 84 int fd, len, i, j, ch; 85 86 while ((ch = getopt(argc, argv, "f")) != -1) { 87 switch (ch) { 88 case 'f': 89 first_instr = 1; 90 break; 91 case '?': 92 default: 93 fprintf(stderr, "usage: %s [-f]\n", argv[0]); 94 exit(1); 95 } 96 } 97 argc -= optind; 98 argv += optind; 99 100 slen = sizeof(bootfile); 101 if (sysctlbyname("kern.bootfile", bootfile, &slen, NULL, 0) != 0) 102 strlcpy(bootfile, "/boot/kernel/kernel", sizeof(bootfile)); 103 104 if (elf_version(EV_CURRENT) == EV_NONE) 105 errx(1, "elf_version(): %s", elf_errmsg(-1)); 106 if ((fd = open(bootfile, O_RDONLY)) < 0) 107 err(1, "open(%s)", bootfile); 108 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) 109 errx(1, "elf_begin(): %s", elf_errmsg(-1)); 110 if (elf_kind(elf) == ELF_K_NONE) 111 errx(1, "not an ELF file: %s", bootfile); 112 113 if (!elf_getshnum(elf, &shnum)) 114 errx(1, "elf_getshnum(): %s", elf_errmsg(-1)); 115 if ((sl = malloc(shnum * sizeof(struct section))) == NULL) 116 err(1, "malloc"); 117 if (!elf_getshstrndx(elf, &shstrndx)) 118 errx(1, "elf_getshstrndx(): %s", elf_errmsg(-1)); 119 if ((scn = elf_getscn(elf, 0)) == NULL) 120 errx(1, "elf_getscn(): %s", elf_errmsg(-1)); 121 (void)elf_errno(); 122 123 do { 124 if (gelf_getshdr(scn, &sh) == NULL) { 125 warnx("gelf_getshdr(): %s", elf_errmsg(-1)); 126 (void)elf_errno(); 127 continue; 128 } 129 if ((name = elf_strptr(elf, shstrndx, sh.sh_name)) == NULL) 130 (void)elf_errno(); 131 if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF && elf_errno() != 0) { 132 warnx("elf_ndxscn(): %s", elf_errmsg(-1)); 133 continue; 134 } 135 if (ndx >= shnum) 136 continue; 137 s = &sl[ndx]; 138 s->scn = scn; 139 s->sh = sh; 140 s->name = name; 141 } while ((scn = elf_nextscn(elf, scn)) != NULL); 142 if (elf_errno() != 0) 143 warnx("elf_nextscn(): %s", elf_errmsg(-1)); 144 145 for (i = 1; i < shnum; i++) { 146 s = &sl[i]; 147 if (s->sh.sh_type != SHT_SYMTAB && s->sh.sh_type != SHT_DYNSYM) 148 continue; 149 if (s->sh.sh_link >= shnum) 150 continue; 151 stab = s->sh.sh_link; 152 len = (int)(s->sh.sh_size / s->sh.sh_entsize); 153 (void)elf_errno(); 154 if ((d = elf_getdata(s->scn, NULL)) == NULL) { 155 if (elf_errno() != 0) 156 warnx("elf_getdata(): %s", elf_errmsg(-1)); 157 continue; 158 } 159 if (d->d_size <= 0) 160 continue; 161 if (s->sh.sh_entsize == 0) 162 continue; 163 else if (len > INT_MAX) 164 continue; 165 for (j = 0; j < len; j++) { 166 if (gelf_getsym(d, j, &sym) != &sym) { 167 warnx("gelf_getsym(): %s", elf_errmsg(-1)); 168 continue; 169 } 170 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) 171 continue; 172 lo = sym.st_value; 173 hi = sym.st_value + sym.st_size; 174 if ((func = elf_strptr(elf, stab, sym.st_name)) != NULL) 175 print_rbp_ommited(func, lo, hi); 176 } 177 } 178 179 free(sl); 180 close(fd); 181 elf_end(elf); 182 183 return (0); 184 }